Fixed issues with seam allowance.
More cases. --HG-- branch : release
This commit is contained in:
parent
f2218aa0b2
commit
695bcea062
|
@ -472,6 +472,21 @@ bool VGObject::IsPointOnLineSegment(const QPointF &t, const QPointF &p1, const Q
|
||||||
return IsPointOnLineviaPDP(t, p1, p2);
|
return IsPointOnLineviaPDP(t, p1, p2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
QPointF VGObject::CorrectDistortion(const QPointF &t, const QPointF &p1, const QPointF &p2)
|
||||||
|
{
|
||||||
|
if (not VFuzzyComparePoints(p1, p2))
|
||||||
|
{
|
||||||
|
QLineF line = QLineF(p1, p2);
|
||||||
|
line.setLength(QLineF(p1, VGObject::ClosestPoint(QLineF(p1, p2), t)).length());
|
||||||
|
return line.p2();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
/**
|
/**
|
||||||
* @brief IsPointOnLineviaPDP use the perp dot product (PDP) way.
|
* @brief IsPointOnLineviaPDP use the perp dot product (PDP) way.
|
||||||
|
|
|
@ -97,6 +97,7 @@ public:
|
||||||
static QPointF addVector (const QPointF &p, const QPointF &p1, const QPointF &p2, qreal k);
|
static QPointF addVector (const QPointF &p, const QPointF &p1, const QPointF &p2, qreal k);
|
||||||
static void LineCoefficients(const QLineF &line, qreal *a, qreal *b, qreal *c);
|
static void LineCoefficients(const QLineF &line, qreal *a, qreal *b, qreal *c);
|
||||||
static bool IsPointOnLineSegment (const QPointF &t, const QPointF &p1, const QPointF &p2);
|
static bool IsPointOnLineSegment (const QPointF &t, const QPointF &p1, const QPointF &p2);
|
||||||
|
static QPointF CorrectDistortion(const QPointF &t, const QPointF &p1, const QPointF &p2);
|
||||||
static bool IsPointOnLineviaPDP(const QPointF &t, const QPointF &p1, const QPointF &p2);
|
static bool IsPointOnLineviaPDP(const QPointF &t, const QPointF &p1, const QPointF &p2);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|
|
@ -263,8 +263,15 @@ QVector<QPointF> AngleByLength(QVector<QPointF> points, QPointF p2, const QLineF
|
||||||
{
|
{
|
||||||
if (not IsOutsidePoint(bigLine1.p1(), bigLine1.p2(), sp2))
|
if (not IsOutsidePoint(bigLine1.p1(), bigLine1.p2(), sp2))
|
||||||
{
|
{
|
||||||
bool success = false;
|
if (p.GetAngleType() != PieceNodeAngle::ByLengthCurve)
|
||||||
points = RollbackSeamAllowance(points, bigLine2, &success);
|
{
|
||||||
|
bool success = false;
|
||||||
|
points = RollbackSeamAllowance(points, bigLine2, &success);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
points.append(sp2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -871,6 +878,9 @@ QVector<QPointF> VAbstractPiece::Equidistant(QVector<VSAPoint> points, qreal wid
|
||||||
return QVector<QPointF>();
|
return QVector<QPointF>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fix distorsion
|
||||||
|
points = CorrectPathDistortion(points);
|
||||||
|
|
||||||
if (points.last().toPoint() != points.first().toPoint())
|
if (points.last().toPoint() != points.first().toPoint())
|
||||||
{
|
{
|
||||||
points.append(points.at(0));// Should be always closed
|
points.append(points.at(0));// Should be always closed
|
||||||
|
@ -1102,21 +1112,15 @@ QVector<QPointF> VAbstractPiece::EkvPoint(QVector<QPointF> points, const VSAPoin
|
||||||
return QVector<QPointF>(); // Wrong edges
|
return QVector<QPointF>(); // Wrong edges
|
||||||
}
|
}
|
||||||
|
|
||||||
// Correct distorsion
|
|
||||||
if (VGObject::IsPointOnLineSegment(p2Line1, p1Line1, p1Line2))
|
|
||||||
{
|
|
||||||
QLineF line = QLineF(p1Line1, p1Line2);
|
|
||||||
line.setLength(QLineF(p1Line1, p2Line1).length());
|
|
||||||
|
|
||||||
p2Line1.setX(line.p2().x());
|
|
||||||
p2Line1.setY(line.p2().y());
|
|
||||||
|
|
||||||
p2Line2.setX(line.p2().x());
|
|
||||||
p2Line2.setY(line.p2().y());
|
|
||||||
}
|
|
||||||
|
|
||||||
const QLineF bigLine1 = ParallelLine(p1Line1, p2Line1, width );
|
const QLineF bigLine1 = ParallelLine(p1Line1, p2Line1, width );
|
||||||
const QLineF bigLine2 = ParallelLine(p2Line2, p1Line2, width );
|
const QLineF bigLine2 = ParallelLine(p2Line2, p1Line2, width );
|
||||||
|
|
||||||
|
if (VFuzzyComparePoints(bigLine1.p2(), bigLine2.p1()))
|
||||||
|
{
|
||||||
|
points.append(bigLine1.p2());
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
QPointF crosPoint;
|
QPointF crosPoint;
|
||||||
const QLineF::IntersectType type = bigLine1.intersect( bigLine2, &crosPoint );
|
const QLineF::IntersectType type = bigLine1.intersect( bigLine2, &crosPoint );
|
||||||
switch (type)
|
switch (type)
|
||||||
|
@ -1129,8 +1133,21 @@ QVector<QPointF> VAbstractPiece::EkvPoint(QVector<QPointF> points, const VSAPoin
|
||||||
{ // Most common case
|
{ // Most common case
|
||||||
/* Case when a path has point on line (both segments lie on the same line) and seam allowance creates
|
/* Case when a path has point on line (both segments lie on the same line) and seam allowance creates
|
||||||
* prong. */
|
* prong. */
|
||||||
|
auto IsOnLine = [](const QPointF &base, const QPointF &sp1, const QPointF &sp2)
|
||||||
|
{
|
||||||
|
if (not VFuzzyComparePoints(base, sp1))
|
||||||
|
{
|
||||||
|
return VGObject::IsPointOnLineviaPDP(sp2, base, sp1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not VFuzzyComparePoints(base, sp2))
|
||||||
|
{
|
||||||
|
return VGObject::IsPointOnLineviaPDP(sp1, base, sp2);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
if (VGObject::IsPointOnLineSegment(p2Line1, p1Line1, p1Line2)
|
if (VGObject::IsPointOnLineSegment(p2Line1, p1Line1, p1Line2)
|
||||||
&& qAbs(QLineF(p2Line1, bigLine1.p2()).angle() - QLineF(p2Line1, bigLine2.p1()).angle()) < 0.001)
|
&& IsOnLine(p2Line1, bigLine1.p2(), bigLine2.p1()))
|
||||||
{
|
{
|
||||||
points.append(bigLine1.p2());
|
points.append(bigLine1.p2());
|
||||||
points.append(bigLine2.p1());
|
points.append(bigLine2.p1());
|
||||||
|
|
|
@ -190,6 +190,9 @@ public:
|
||||||
const VSAPoint &p1Line2, VSAPoint p2Line2, qreal width);
|
const VSAPoint &p1Line2, VSAPoint p2Line2, qreal width);
|
||||||
static QLineF ParallelLine(const VSAPoint &p1, const VSAPoint &p2, qreal width);
|
static QLineF ParallelLine(const VSAPoint &p1, const VSAPoint &p2, qreal width);
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
static QVector<T> CorrectPathDistortion(QVector<T> path);
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
static QVector<T> CorrectEquidistantPoints(const QVector<T> &points, bool removeFirstAndLast = true);
|
static QVector<T> CorrectEquidistantPoints(const QVector<T> &points, bool removeFirstAndLast = true);
|
||||||
|
|
||||||
|
@ -207,6 +210,44 @@ private:
|
||||||
|
|
||||||
Q_DECLARE_TYPEINFO(VAbstractPiece, Q_MOVABLE_TYPE);
|
Q_DECLARE_TYPEINFO(VAbstractPiece, Q_MOVABLE_TYPE);
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
template<class T>
|
||||||
|
QVector<T> VAbstractPiece::CorrectPathDistortion(QVector<T> path)
|
||||||
|
{
|
||||||
|
if (path.size() < 3)
|
||||||
|
{
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
int prev = -1;
|
||||||
|
for (qint32 i = 0; i < path.size(); ++i)
|
||||||
|
{
|
||||||
|
if (prev == -1)
|
||||||
|
{
|
||||||
|
i == 0 ? prev = path.size() - 1 : prev = i-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int next = i+1;
|
||||||
|
if (i == path.size() - 1)
|
||||||
|
{
|
||||||
|
next = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QPointF &iPoint = path.at(i);
|
||||||
|
const QPointF &prevPoint = path.at(prev);
|
||||||
|
const QPointF &nextPoint = path.at(next);
|
||||||
|
|
||||||
|
if (VGObject::IsPointOnLineSegment(iPoint, prevPoint, nextPoint))
|
||||||
|
{
|
||||||
|
const QPointF p = VGObject::CorrectDistortion(iPoint, prevPoint, nextPoint);
|
||||||
|
path[i].setX(p.x());
|
||||||
|
path[i].setY(p.y());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
/**
|
/**
|
||||||
* @brief CorrectEquidistantPoints clear equivalent points and remove point on line from equdistant.
|
* @brief CorrectEquidistantPoints clear equivalent points and remove point on line from equdistant.
|
||||||
|
|
|
@ -1104,7 +1104,7 @@ bool VPiece::GetPassmarkPreviousSAPoints(const QVector<VPieceNode> &path, int in
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
const VSAPoint previous = points.at(nodeIndex);
|
const VSAPoint previous = points.at(nodeIndex);
|
||||||
if (passmarkSAPoint.toPoint() != previous.toPoint())
|
if (not VFuzzyComparePoints(passmarkSAPoint, previous))
|
||||||
{
|
{
|
||||||
point = previous;
|
point = previous;
|
||||||
found = true;
|
found = true;
|
||||||
|
@ -1141,7 +1141,7 @@ int VPiece::GetPassmarkNextSAPoints(const QVector<VPieceNode> &path, int index,
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
const VSAPoint next = points.at(nodeIndex);
|
const VSAPoint next = points.at(nodeIndex);
|
||||||
if (passmarkSAPoint.toPoint() != next.toPoint())
|
if (not VFuzzyComparePoints(passmarkSAPoint, next))
|
||||||
{
|
{
|
||||||
point = next;
|
point = next;
|
||||||
found = true;
|
found = true;
|
||||||
|
@ -1159,32 +1159,22 @@ int VPiece::GetPassmarkNextSAPoints(const QVector<VPieceNode> &path, int index,
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
bool VPiece::GetSeamPassmarkSAPoint(const VSAPoint &previousSAPoint, const VSAPoint &passmarkSAPoint,
|
bool VPiece::GetSeamPassmarkSAPoint(const VSAPoint &previousSAPoint, VSAPoint passmarkSAPoint,
|
||||||
const VSAPoint &nextSAPoint, const VContainer *data, QPointF &point) const
|
const VSAPoint &nextSAPoint, const VContainer *data, QPointF &point) const
|
||||||
{
|
{
|
||||||
SCASSERT(data != nullptr)
|
SCASSERT(data != nullptr)
|
||||||
|
|
||||||
QVector<QPointF> ekvPoints;
|
// Correct distorsion
|
||||||
const qreal width = ToPixel(GetSAWidth(), *data->GetPatternUnit());
|
if (VGObject::IsPointOnLineSegment(passmarkSAPoint, previousSAPoint, nextSAPoint))
|
||||||
|
{
|
||||||
|
const QPointF p = VGObject::CorrectDistortion(passmarkSAPoint, previousSAPoint, nextSAPoint);
|
||||||
|
passmarkSAPoint.setX(p.x());
|
||||||
|
passmarkSAPoint.setY(p.y());
|
||||||
|
}
|
||||||
|
|
||||||
/* Because method VAbstractPiece::EkvPoint has troubles with edges on a same line we should specially treat such
|
QVector<QPointF> ekvPoints;
|
||||||
cases.
|
ekvPoints = EkvPoint(ekvPoints, previousSAPoint, passmarkSAPoint, nextSAPoint, passmarkSAPoint,
|
||||||
First check if two edges and seam alowance create paralell lines.
|
ToPixel(GetSAWidth(), *data->GetPatternUnit()));
|
||||||
Second case check if two edges are on a same line geometrically and a passmark point has equal SA width.*/
|
|
||||||
if (IsEkvPointOnLine(passmarkSAPoint, previousSAPoint, nextSAPoint)// see issue #665
|
|
||||||
|| (IsEkvPointOnLine(static_cast<QPointF>(passmarkSAPoint), static_cast<QPointF>(previousSAPoint),
|
|
||||||
static_cast<QPointF>(nextSAPoint))
|
|
||||||
&& qAbs(passmarkSAPoint.GetSABefore(width) - passmarkSAPoint.GetSAAfter(width)) < accuracyPointOnLine))
|
|
||||||
{
|
|
||||||
QLineF line (passmarkSAPoint, nextSAPoint);
|
|
||||||
line.setAngle(line.angle() + 90);
|
|
||||||
line.setLength(passmarkSAPoint.MaxLocalSA(width));
|
|
||||||
ekvPoints.append(line.p2());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ekvPoints = EkvPoint(ekvPoints, previousSAPoint, passmarkSAPoint, nextSAPoint, passmarkSAPoint, width);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ekvPoints.isEmpty())
|
if (ekvPoints.isEmpty())
|
||||||
{ // Just in case
|
{ // Just in case
|
||||||
|
|
|
@ -145,7 +145,7 @@ private:
|
||||||
const VContainer *data, VSAPoint &point, int passmarkIndex) const;
|
const VContainer *data, VSAPoint &point, int passmarkIndex) const;
|
||||||
int GetPassmarkNextSAPoints(const QVector<VPieceNode> &path, int index, const VSAPoint &passmarkSAPoint,
|
int GetPassmarkNextSAPoints(const QVector<VPieceNode> &path, int index, const VSAPoint &passmarkSAPoint,
|
||||||
const VContainer *data, VSAPoint &point, int passmarkIndex) const;
|
const VContainer *data, VSAPoint &point, int passmarkIndex) const;
|
||||||
bool GetSeamPassmarkSAPoint(const VSAPoint &previousSAPoint, const VSAPoint &passmarkSAPoint,
|
bool GetSeamPassmarkSAPoint(const VSAPoint &previousSAPoint, VSAPoint passmarkSAPoint,
|
||||||
const VSAPoint &nextSAPoint, const VContainer *data, QPointF &point) const;
|
const VSAPoint &nextSAPoint, const VContainer *data, QPointF &point) const;
|
||||||
|
|
||||||
bool IsPassmarkVisible(const QVector<VPieceNode> &path, int passmarkIndex) const;
|
bool IsPassmarkVisible(const QVector<VPieceNode> &path, int passmarkIndex) const;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user