diff --git a/src/libs/vgeometry/vgobject.cpp b/src/libs/vgeometry/vgobject.cpp index 713239bf7..9331bcd06 100644 --- a/src/libs/vgeometry/vgobject.cpp +++ b/src/libs/vgeometry/vgobject.cpp @@ -534,28 +534,6 @@ int VGObject::PointInCircle(const QPointF &p, const QPointF ¢er, qreal radiu return 2; // inside circle } -//--------------------------------------------------------------------------------------------------------------------- -/** - * @brief GetReversePoint return revers container of points. - * @param points container with points. - * @return reverced points. - */ -QVector VGObject::GetReversePoints(const QVector &points) -{ - if (points.isEmpty()) - { - return points; - } - QVector reversePoints(points.size()); - qint32 j = 0; - for (qint32 i = points.size() - 1; i >= 0; --i) - { - reversePoints.replace(j, points.at(i)); - ++j; - } - return reversePoints; -} - //--------------------------------------------------------------------------------------------------------------------- /** * @brief GetLengthContour return length of contour. diff --git a/src/libs/vgeometry/vgobject.h b/src/libs/vgeometry/vgobject.h index 328316fe9..360387f7e 100644 --- a/src/libs/vgeometry/vgobject.h +++ b/src/libs/vgeometry/vgobject.h @@ -90,7 +90,8 @@ public: static bool IsPointOnLineSegment (const QPointF &t, const QPointF &p1, const QPointF &p2); static bool IsPointOnLineviaPDP(const QPointF &t, const QPointF &p1, const QPointF &p2); - static QVector GetReversePoints(const QVector &points); + template + static QVector GetReversePoints(const QVector &points); static int GetLengthContour(const QVector &contour, const QVector &newPoints); static double accuracyPointOnLine; @@ -105,6 +106,29 @@ private: static int PointInCircle (const QPointF &p, const QPointF ¢er, qreal radius); }; +//--------------------------------------------------------------------------------------------------------------------- +/** + * @brief GetReversePoint return revers container of points. + * @param points container with points. + * @return reverced points. + */ +template +QVector VGObject::GetReversePoints(const QVector &points) +{ + if (points.isEmpty()) + { + return points; + } + QVector reversePoints(points.size()); + qint32 j = 0; + for (qint32 i = points.size() - 1; i >= 0; --i) + { + reversePoints.replace(j, points.at(i)); + ++j; + } + return reversePoints; +} + Q_DECLARE_TYPEINFO(VGObject, Q_MOVABLE_TYPE); #endif // VGOBJECT_H diff --git a/src/libs/vpatterndb/vpiece.cpp b/src/libs/vpatterndb/vpiece.cpp index bd42a1945..0b0f8b2d8 100644 --- a/src/libs/vpatterndb/vpiece.cpp +++ b/src/libs/vpatterndb/vpiece.cpp @@ -105,6 +105,11 @@ QVector VPiece::SeamAllowancePoints(const VContainer *data) const return QVector(); } + const QVector records = GetValidRecords(); + int recordIndex = -1; + bool insertingCSA = false; + const qreal width = ToPixel(GetSAWidth(), *data->GetPatternUnit()); + QVector pointsEkv; for (int i = 0; i< d->m_path.CountNodes(); ++i) { @@ -113,21 +118,54 @@ QVector VPiece::SeamAllowancePoints(const VContainer *data) const { case (Tool::NodePoint): { - const QSharedPointer point = data->GeometricObject(node.GetId()); - VSAPoint p(point->toQPointF()); + if (not insertingCSA) + { + pointsEkv.append(VPiecePath::PreparePointEkv(node, data)); - p.SetSAAfter(node.GetSAAfter(*data->GetPatternUnit())); - p.SetSABefore(node.GetSABefore(*data->GetPatternUnit())); - p.SetAngleType(node.GetAngleType()); - pointsEkv.append(p); + recordIndex = IsCSAStart(records, node.GetId()); + if (recordIndex != -1) + { + insertingCSA = true; + + const VPiecePath path = data->GetPiecePath(records.at(recordIndex).path); + QVector r = path.SeamAllowancePoints(data, width, records.at(recordIndex).reverse); + + if (records.at(recordIndex).includeType == PiecePathIncludeType::AsCustomSA) + { + for (int j = 0; j < r.size(); ++j) + { + r[i].SetAngleType(PieceNodeAngle::ByLength); + r[i].SetSABefore(0); + r[i].SetSABefore(0); + } + } + + pointsEkv += r; + } + } + else + { + if (records.at(recordIndex).endPoint == node.GetId()) + { + insertingCSA = false; + recordIndex = -1; + + pointsEkv.append(VPiecePath::PreparePointEkv(node, data)); + } + } } break; case (Tool::NodeArc): case (Tool::NodeSpline): case (Tool::NodeSplinePath): { - const QSharedPointer curve = data->GeometricObject(node.GetId()); - CurveSeamAllowanceSegment(pointsEkv, data, curve, i, node.GetReverse()); + if (not insertingCSA) + { + const QSharedPointer curve = data->GeometricObject(node.GetId()); + + pointsEkv += VPiecePath::CurveSeamAllowanceSegment(data, d->m_path.GetNodes(), curve, i, + node.GetReverse(), width); + } } break; default: @@ -136,7 +174,7 @@ QVector VPiece::SeamAllowancePoints(const VContainer *data) const } } - return Equidistant(pointsEkv, ToPixel(GetSAWidth(), *data->GetPatternUnit())); + return Equidistant(pointsEkv, width); } //--------------------------------------------------------------------------------------------------------------------- @@ -287,86 +325,31 @@ QVector VPiece::MissingCSAPath(const VPiece &det) const } //--------------------------------------------------------------------------------------------------------------------- -void VPiece::CurveSeamAllowanceSegment(QVector &pointsEkv, const VContainer *data, - const QSharedPointer &curve, int i, bool reverse) const +QVector VPiece::GetValidRecords() const { - const VSAPoint begin = d->m_path.StartSegment(data, i, reverse); - const VSAPoint end = d->m_path.EndSegment(data, i, reverse); - - const QVector points = curve->GetSegmentPoints(begin, end, reverse); - if (points.isEmpty()) + QVector records; + for (int i = 0; i < d->m_customSARecords.size(); ++i) { - return; - } + const CustomSARecord &record = d->m_customSARecords.at(i); - qreal w1 = begin.GetSAAfter(); - qreal w2 = end.GetSABefore(); - if (w1 < 0 && w2 < 0) - {// no local widths - for(int i = 0; i < points.size(); ++i) + if (record.startPoint > NULL_ID && record.path > NULL_ID && record.endPoint > NULL_ID) { - VSAPoint p(points.at(i)); - if (i == 0) - { // first point - p.SetSAAfter(begin.GetSAAfter()); - p.SetSABefore(begin.GetSABefore()); - p.SetAngleType(begin.GetAngleType()); - } - else if (i == points.size() - 1) - { // last point - p.SetSAAfter(end.GetSAAfter()); - p.SetSABefore(end.GetSABefore()); - p.SetAngleType(end.GetAngleType()); - } - pointsEkv.append(p); - } - } - else - { - const qreal width = ToPixel(GetSAWidth(), *data->GetPatternUnit()); - - if (w1 < 0) - { - w1 = width; - } - - if (w2 < 0) - { - w2 = width; - } - - const qreal wDiff = w2 - w1;// Difference between to local widths - const qreal fullLength = VAbstractCurve::PathLength(points); - - VSAPoint p(points.at(0));//First point in the list - p.SetSAAfter(begin.GetSAAfter()); - p.SetSABefore(begin.GetSABefore()); - p.SetAngleType(begin.GetAngleType()); - pointsEkv.append(p); - - qreal length = 0; // how much we handle - - for(int i = 1; i < points.size(); ++i) - { - p = VSAPoint(points.at(i)); - - if (i == points.size() - 1) - {// last point - p.SetSAAfter(end.GetSAAfter()); - p.SetSABefore(end.GetSABefore()); - p.SetAngleType(end.GetAngleType()); - } - else - { - length += QLineF(points.at(i-1), points.at(i)).length(); - const qreal localWidth = w1 + wDiff*(length/fullLength); - - p.SetSAAfter(localWidth); - p.SetSABefore(localWidth); - // curve points have angle type by default - } - - pointsEkv.append(p); + records.append(record); } } + return records; +} + +//--------------------------------------------------------------------------------------------------------------------- +int VPiece::IsCSAStart(const QVector &records, quint32 id) +{ + for (int i = 0; i < records.size(); ++i) + { + if (records.at(i).startPoint == id) + { + return i; + } + } + + return -1; } diff --git a/src/libs/vpatterndb/vpiece.h b/src/libs/vpatterndb/vpiece.h index 3eca969ed..099011102 100644 --- a/src/libs/vpatterndb/vpiece.h +++ b/src/libs/vpatterndb/vpiece.h @@ -84,8 +84,9 @@ public: private: QSharedDataPointer d; - void CurveSeamAllowanceSegment(QVector &pointsEkv, const VContainer *data, - const QSharedPointer &curve, int i, bool reverse) const; + QVector GetValidRecords() const; + + static int IsCSAStart(const QVector &records, quint32 id); }; Q_DECLARE_TYPEINFO(VPiece, Q_MOVABLE_TYPE); diff --git a/src/libs/vpatterndb/vpiecepath.cpp b/src/libs/vpatterndb/vpiecepath.cpp index 87e1a9484..1f761267e 100644 --- a/src/libs/vpatterndb/vpiecepath.cpp +++ b/src/libs/vpatterndb/vpiecepath.cpp @@ -190,6 +190,44 @@ QVector VPiecePath::PathNodePoints(const VContainer *data) const return points; } +//--------------------------------------------------------------------------------------------------------------------- +QVector VPiecePath::SeamAllowancePoints(const VContainer *data, qreal width, bool reverse) const +{ + SCASSERT(data != nullptr); + + QVector pointsEkv; + for (int i = 0; i< d->m_nodes.size(); ++i) + { + const VPieceNode &node = d->m_nodes.at(i); + switch (node.GetTypeTool()) + { + case (Tool::NodePoint): + { + pointsEkv.append(PreparePointEkv(node, data)); + } + break; + case (Tool::NodeArc): + case (Tool::NodeSpline): + case (Tool::NodeSplinePath): + { + const QSharedPointer curve = data->GeometricObject(node.GetId()); + pointsEkv += CurveSeamAllowanceSegment(data, d->m_nodes, curve, i, node.GetReverse(), width); + } + break; + default: + qDebug()<<"Get wrong tool type. Ignore."<< static_cast(node.GetTypeTool()); + break; + } + } + + if (reverse) + { + pointsEkv = VGObject::GetReversePoints(pointsEkv); + } + + return pointsEkv; +} + //--------------------------------------------------------------------------------------------------------------------- QPainterPath VPiecePath::PainterPath(const VContainer *data) const { @@ -210,14 +248,14 @@ QPainterPath VPiecePath::PainterPath(const VContainer *data) const } //--------------------------------------------------------------------------------------------------------------------- -VSAPoint VPiecePath::StartSegment(const VContainer *data, int i, bool reverse) const +VSAPoint VPiecePath::StartSegment(const VContainer *data, const QVector &nodes, int i, bool reverse) { - if (i < 0 && i > CountNodes()-1) + if (i < 0 && i > nodes.size()-1) { return VSAPoint(); } - const QSharedPointer curve = data->GeometricObject(at(i).GetId()); + const QSharedPointer curve = data->GeometricObject(nodes.at(i).GetId()); QVector points = curve->GetPoints(); if (reverse) @@ -226,13 +264,13 @@ VSAPoint VPiecePath::StartSegment(const VContainer *data, int i, bool reverse) c } VSAPoint begin = VSAPoint(points.first()); - if (CountNodes() > 1) + if (nodes.size() > 1) { if (i == 0) { - if (at(CountNodes()-1).GetTypeTool() == Tool::NodePoint) + if (nodes.at(nodes.size()-1).GetTypeTool() == Tool::NodePoint) { - const VPieceNode &node = at(CountNodes()-1); + const VPieceNode &node = nodes.at(nodes.size()-1); const QPointF p = *data->GeometricObject(node.GetId()); if (curve->IsPointOnCurve(p)) { @@ -245,9 +283,9 @@ VSAPoint VPiecePath::StartSegment(const VContainer *data, int i, bool reverse) c } else { - if (at(i-1).GetTypeTool() == Tool::NodePoint) + if (nodes.at(i-1).GetTypeTool() == Tool::NodePoint) { - const VPieceNode &node = at(i-1); + const VPieceNode &node = nodes.at(i-1); const QPointF p = *data->GeometricObject(node.GetId()); if (curve->IsPointOnCurve(p)) { @@ -263,14 +301,14 @@ VSAPoint VPiecePath::StartSegment(const VContainer *data, int i, bool reverse) c } //--------------------------------------------------------------------------------------------------------------------- -VSAPoint VPiecePath::EndSegment(const VContainer *data, int i, bool reverse) const +VSAPoint VPiecePath::EndSegment(const VContainer *data, const QVector &nodes, int i, bool reverse) { - if (i < 0 && i > CountNodes()-1) + if (i < 0 && i > nodes.size()-1) { return VSAPoint(); } - const QSharedPointer curve = data->GeometricObject(at(i).GetId()); + const QSharedPointer curve = data->GeometricObject(nodes.at(i).GetId()); QVector points = curve->GetPoints(); if (reverse) @@ -279,13 +317,13 @@ VSAPoint VPiecePath::EndSegment(const VContainer *data, int i, bool reverse) con } VSAPoint end = VSAPoint(points.last()); - if (CountNodes() > 2) + if (nodes.size() > 2) { - if (i == CountNodes() - 1) + if (i == nodes.size() - 1) { - if (at(0).GetTypeTool() == Tool::NodePoint) + if (nodes.at(0).GetTypeTool() == Tool::NodePoint) { - const VPieceNode &node = at(0); + const VPieceNode &node = nodes.at(0); const QPointF p = *data->GeometricObject(node.GetId()); if (curve->IsPointOnCurve(p)) { @@ -298,9 +336,9 @@ VSAPoint VPiecePath::EndSegment(const VContainer *data, int i, bool reverse) con } else { - if (at(i+1).GetTypeTool() == Tool::NodePoint) + if (nodes.at(i+1).GetTypeTool() == Tool::NodePoint) { - const VPieceNode &node = at(i+1); + const VPieceNode &node = nodes.at(i+1); const QPointF p = *data->GeometricObject(node.GetId()); if (curve->IsPointOnCurve(p)) { @@ -362,3 +400,116 @@ int VPiecePath::indexOfNode(quint32 id) const qDebug()<<"Can't find node."; return -1; } + +//--------------------------------------------------------------------------------------------------------------------- +VSAPoint VPiecePath::StartSegment(const VContainer *data, int i, bool reverse) const +{ + return StartSegment(data, d->m_nodes, i, reverse); +} + +//--------------------------------------------------------------------------------------------------------------------- +VSAPoint VPiecePath::EndSegment(const VContainer *data, int i, bool reverse) const +{ + return EndSegment(data, d->m_nodes, i, reverse); +} + +//--------------------------------------------------------------------------------------------------------------------- +VSAPoint VPiecePath::PreparePointEkv(const VPieceNode &node, const VContainer *data) +{ + const QSharedPointer point = data->GeometricObject(node.GetId()); + VSAPoint p(point->toQPointF()); + + p.SetSAAfter(node.GetSAAfter(*data->GetPatternUnit())); + p.SetSABefore(node.GetSABefore(*data->GetPatternUnit())); + p.SetAngleType(node.GetAngleType()); + + return p; +} + +//--------------------------------------------------------------------------------------------------------------------- +QVector VPiecePath::CurveSeamAllowanceSegment(const VContainer *data, const QVector &nodes, + const QSharedPointer &curve, int i, + bool reverse, qreal width) +{ + QVector pointsEkv; + + const VSAPoint begin = StartSegment(data, nodes, i, reverse); + const VSAPoint end = EndSegment(data, nodes, i, reverse); + + const QVector points = curve->GetSegmentPoints(begin, end, reverse); + if (points.isEmpty()) + { + return pointsEkv; + } + + qreal w1 = begin.GetSAAfter(); + qreal w2 = end.GetSABefore(); + if (w1 < 0 && w2 < 0) + {// no local widths + for(int i = 0; i < points.size(); ++i) + { + VSAPoint p(points.at(i)); + if (i == 0) + { // first point + p.SetSAAfter(begin.GetSAAfter()); + p.SetSABefore(begin.GetSABefore()); + p.SetAngleType(begin.GetAngleType()); + } + else if (i == points.size() - 1) + { // last point + p.SetSAAfter(end.GetSAAfter()); + p.SetSABefore(end.GetSABefore()); + p.SetAngleType(end.GetAngleType()); + } + pointsEkv.append(p); + } + } + else + { + if (w1 < 0) + { + w1 = width; + } + + if (w2 < 0) + { + w2 = width; + } + + const qreal wDiff = w2 - w1;// Difference between to local widths + const qreal fullLength = VAbstractCurve::PathLength(points); + + VSAPoint p(points.at(0));//First point in the list + p.SetSAAfter(begin.GetSAAfter()); + p.SetSABefore(begin.GetSABefore()); + p.SetAngleType(begin.GetAngleType()); + pointsEkv.append(p); + + qreal length = 0; // how much we handle + + for(int i = 1; i < points.size(); ++i) + { + p = VSAPoint(points.at(i)); + + if (i == points.size() - 1) + {// last point + p.SetSAAfter(end.GetSAAfter()); + p.SetSABefore(end.GetSABefore()); + p.SetAngleType(end.GetAngleType()); + } + else + { + length += QLineF(points.at(i-1), points.at(i)).length(); + const qreal localWidth = w1 + wDiff*(length/fullLength); + + p.SetSAAfter(localWidth); + p.SetSABefore(localWidth); + // curve points have angle type by default + } + + pointsEkv.append(p); + } + } + + return pointsEkv; +} diff --git a/src/libs/vpatterndb/vpiecepath.h b/src/libs/vpatterndb/vpiecepath.h index facfa10f2..7f90490bc 100644 --- a/src/libs/vpatterndb/vpiecepath.h +++ b/src/libs/vpatterndb/vpiecepath.h @@ -40,6 +40,7 @@ class QPointF; class VContainer; class VSAPoint; class QPainterPath; +class VAbstractCurve; class VPiecePath { @@ -66,18 +67,28 @@ public: QString GetName() const; void SetName(const QString &name); - QVector PathPoints(const VContainer *data) const; - QVector PathNodePoints(const VContainer *data) const; + QVector PathPoints(const VContainer *data) const; + QVector PathNodePoints(const VContainer *data) const; + QVector SeamAllowancePoints(const VContainer *data, qreal width, bool reverse) const; QPainterPath PainterPath(const VContainer *data) const; - VSAPoint StartSegment(const VContainer *data, int i, bool reverse) const; - VSAPoint EndSegment(const VContainer *data, int i, bool reverse) const; - QVector MissingNodes(const VPiecePath &path) const; int indexOfNode(quint32 id) const; + VSAPoint StartSegment(const VContainer *data, int i, bool reverse) const; + VSAPoint EndSegment(const VContainer *data, int i, bool reverse) const; + + static VSAPoint StartSegment(const VContainer *data, const QVector &nodes, int i, bool reverse); + static VSAPoint EndSegment(const VContainer *data, const QVector &nodes, int i, bool reverse); + + static VSAPoint PreparePointEkv(const VPieceNode &node, const VContainer *data); + + static QVector CurveSeamAllowanceSegment(const VContainer *data, const QVector &nodes, + const QSharedPointer &curve, + int i, bool reverse, qreal width); + private: QSharedDataPointer d; };