diff --git a/ChangeLog.txt b/ChangeLog.txt
index 8a5f2ae93..cc04ef6a6 100644
--- a/ChangeLog.txt
+++ b/ChangeLog.txt
@@ -6,6 +6,7 @@
- Fix export measurement separator to CSV.
- Fix option Hide labels.
- Improve segmenting a curve for calculating a piece path.
+- [smart-pattern/valentina#184] Fix incorrect seam allowance.
# Valentina 0.7.52 September 12, 2022
- Fix crash when default locale is ru.
diff --git a/src/app/share/collection/bugs/smart_pattern_#184_case1.val b/src/app/share/collection/bugs/smart_pattern_#184_case1.val
new file mode 100644
index 000000000..03220800f
--- /dev/null
+++ b/src/app/share/collection/bugs/smart_pattern_#184_case1.val
@@ -0,0 +1,1387 @@
+
+
+
+ 0.9.2
+ cm
+ Jeans mit gerader Seitennaht
+Müller u. Sohn Zeitschrift Ausgabe 10.20 , Seite 47-50 vom PDf (bzw. 14 - 17 vom Herrenteil)
+ 17.10.20:
+Anpassugen für die Kurzhose -> enger am Saum (-3.5)
+Hosenschlitzuntertritt gerade an der oberen Kante
+ Jeans Selvedge
+ #4
+ CrazyRori
+
+ 2000-01-01
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/app/share/collection/bugs/smart_pattern_#184_case1.vit b/src/app/share/collection/bugs/smart_pattern_#184_case1.vit
new file mode 100644
index 000000000..5cb510489
--- /dev/null
+++ b/src/app/share/collection/bugs/smart_pattern_#184_case1.vit
@@ -0,0 +1,47 @@
+
+
+
+ 0.5.1
+ false
+ Nach Messung wegen Büste am 16.03.2021
+Brustumfang : 88 -> 86
+Taille: 79 -> 76
+Hüfte: 92 -> 94
+Halsumfang: 39.5 -> 37
+ cm
+ 998
+
+ Ronan
+ 1987-04-03
+ male
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/libs/vlayout/vabstractpiece.cpp b/src/libs/vlayout/vabstractpiece.cpp
index c66118abe..ae6ce4439 100644
--- a/src/libs/vlayout/vabstractpiece.cpp
+++ b/src/libs/vlayout/vabstractpiece.cpp
@@ -113,7 +113,9 @@ auto AngleByLength(QVector points, QPointF p1, QPointF p2, QPointF
{
qDebug()<<"Couldn't find intersection with cut line.";
}
- points.append(VRawSAPoint(px, p.CurvePoint(), p.TurnPoint()));
+ VRawSAPoint sp(px, p.CurvePoint(), p.TurnPoint());
+ sp.SetPrimary(true);
+ points.append(sp);
cutLine.setAngle(cutLine.angle()-180);
type = Intersects(QLineF(sp2, sp3), cutLine, &px);
@@ -122,7 +124,9 @@ auto AngleByLength(QVector points, QPointF p1, QPointF p2, QPointF
{
qDebug()<<"Couldn't find intersection with cut line.";
}
- points.append(VRawSAPoint(px, p.CurvePoint(), p.TurnPoint()));
+ sp = VRawSAPoint(px, p.CurvePoint(), p.TurnPoint());
+ sp.SetPrimary(true);
+ points.append(sp);
}
else
{// The point just fine
@@ -1129,9 +1133,9 @@ auto VAbstractPiece::Equidistant(QVector points, qreal width, const QS
const bool removeFirstAndLast = false;
ekvPoints = RemoveDublicates(ekvPoints, removeFirstAndLast);
ekvPoints = CheckLoops(ekvPoints);
- CastTo(ekvPoints, cleaned);//Result path can contain loops
cleaned = CorrectEquidistantPoints(cleaned, removeFirstAndLast);
cleaned = CorrectPathDistortion(cleaned);
+ CastTo(ekvPoints, cleaned);//Result path can contain loops
// QVector dump;
// CastTo(cleaned, dump);
diff --git a/src/libs/vlayout/vabstractpiece.h b/src/libs/vlayout/vabstractpiece.h
index 5467e7806..e2a524266 100644
--- a/src/libs/vlayout/vabstractpiece.h
+++ b/src/libs/vlayout/vabstractpiece.h
@@ -38,6 +38,7 @@
#include "../vmisc/compatibility.h"
#include "../vgeometry/vgobject.h"
#include "vsapoint.h"
+#include "vrawsapoint.h"
#include "testpath.h"
class VAbstractPieceData;
@@ -351,6 +352,36 @@ inline auto VAbstractPiece::ComparePoints(QVector &points, const T &p1, const
return true;
}
+//---------------------------------------------------------------------------------------------------------------------
+template <>
+inline auto VAbstractPiece::ComparePoints(QVector &points, const VRawSAPoint &p1, const VRawSAPoint &p2,
+ qreal accuracy) -> bool
+{
+ qreal testAccuracy = accuracy;
+ if (p1.Primary() && p2.Primary())
+ {
+ testAccuracy = accuracyPointOnLine;
+ }
+
+ if (not VFuzzyComparePoints(p1, p2, testAccuracy))
+ {
+ points.append(p2);
+ return false;
+ }
+
+ if (not points.isEmpty() && p2.TurnPoint())
+ {
+ points.last().SetTurnPoint(true);
+ }
+
+ if (not points.isEmpty() && p2.CurvePoint())
+ {
+ points.last().SetCurvePoint(true);
+ }
+
+ return true;
+}
+
//---------------------------------------------------------------------------------------------------------------------
template <>
inline auto VAbstractPiece::ComparePoints(QVector &points, const QPointF &p1, const QPointF &p2,
@@ -386,6 +417,35 @@ inline auto VAbstractPiece::CompareFirstAndLastPoints(QVector &points, qreal
}
}
+//---------------------------------------------------------------------------------------------------------------------
+template <>
+inline auto VAbstractPiece::CompareFirstAndLastPoints(QVector &points, qreal accuracy) -> void
+{
+ const VRawSAPoint& first = ConstFirst(points);
+ const VRawSAPoint& last = ConstLast(points);
+
+ qreal testAccuracy = accuracy;
+ if (first.Primary() && last.Primary())
+ {
+ testAccuracy = accuracyPointOnLine;
+ }
+
+ if (VFuzzyComparePoints(first, last, testAccuracy))
+ {
+ points.removeLast();
+
+ if (not points.isEmpty() && last.TurnPoint())
+ {
+ points.last().SetTurnPoint(true);
+ }
+
+ if (not points.isEmpty() && last.CurvePoint())
+ {
+ points.last().SetCurvePoint(true);
+ }
+ }
+}
+
//---------------------------------------------------------------------------------------------------------------------
template <>
inline auto VAbstractPiece::CompareFirstAndLastPoints(QVector &points, qreal accuracy) -> void
diff --git a/src/libs/vlayout/vrawsapoint.cpp b/src/libs/vlayout/vrawsapoint.cpp
index 51855417e..f615680fc 100644
--- a/src/libs/vlayout/vrawsapoint.cpp
+++ b/src/libs/vlayout/vrawsapoint.cpp
@@ -37,6 +37,7 @@ auto VRawSAPoint::toJson() const -> QJsonObject
pointObject[QLatin1String("type")] = "VRawSAPoint";
pointObject[QLatin1String("loopPoint")] = m_loopPoint;
+ pointObject[QLatin1String("primary")] = m_primary;
return pointObject;
}
diff --git a/src/libs/vlayout/vrawsapoint.h b/src/libs/vlayout/vrawsapoint.h
index 7f80132fc..11a8f0947 100644
--- a/src/libs/vlayout/vrawsapoint.h
+++ b/src/libs/vlayout/vrawsapoint.h
@@ -53,10 +53,14 @@ public:
Q_DECL_CONSTEXPR auto LoopPoint() const -> bool;
Q_DECL_RELAXED_CONSTEXPR void SetLoopPoint(bool loopPoint);
+ Q_DECL_CONSTEXPR auto Primary() const -> bool;
+ Q_DECL_RELAXED_CONSTEXPR void SetPrimary(bool primary);
+
auto toJson() const -> QJsonObject override;
private:
bool m_loopPoint{false};
+ bool m_primary{false};
};
Q_DECLARE_METATYPE(VRawSAPoint) // NOLINT
@@ -106,6 +110,18 @@ Q_DECL_RELAXED_CONSTEXPR inline void VRawSAPoint::SetLoopPoint(bool loopPoint)
m_loopPoint = loopPoint;
}
+//---------------------------------------------------------------------------------------------------------------------
+Q_DECL_CONSTEXPR inline auto VRawSAPoint::Primary() const -> bool
+{
+ return m_primary;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+Q_DECL_RELAXED_CONSTEXPR inline void VRawSAPoint::SetPrimary(bool primary)
+{
+ m_primary = primary;
+}
+
QT_WARNING_POP
#endif // VRAWSAPOINT_H
diff --git a/src/test/ValentinaTest/share/smart_pattern_#184_case1/input.json b/src/test/ValentinaTest/share/smart_pattern_#184_case1/input.json
new file mode 100644
index 000000000..8e2494b2c
--- /dev/null
+++ b/src/test/ValentinaTest/share/smart_pattern_#184_case1/input.json
@@ -0,0 +1,78 @@
+{
+ "vector": [
+ {
+ "turnPoint": true,
+ "type": "VSAPoint",
+ "x": 589.0064206717155,
+ "y": 782.4496746376101
+ },
+ {
+ "turnPoint": true,
+ "type": "VSAPoint",
+ "x": 597.0841810534489,
+ "y": 666.714504931189
+ },
+ {
+ "turnPoint": true,
+ "type": "VSAPoint",
+ "x": 658.8439751213995,
+ "y": 829.6285575700094
+ },
+ {
+ "turnPoint": true,
+ "type": "VSAPoint",
+ "x": 668.7920249877046,
+ "y": 713.62278781496
+ },
+ {
+ "turnPoint": true,
+ "type": "VSAPoint",
+ "x": 681.6851838985511,
+ "y": 749.9461773118659
+ },
+ {
+ "saAfter": 37.795275590551185,
+ "turnPoint": true,
+ "type": "VSAPoint",
+ "x": 878.9287903098608,
+ "y": 721.4082798757745
+ },
+ {
+ "saAfter": 37.795275590551185,
+ "saBefore": 37.795275590551185,
+ "turnPoint": true,
+ "type": "VSAPoint",
+ "x": 892.8692692510483,
+ "y": 929.4298158977432
+ },
+ {
+ "saAfter": 37.795275590551185,
+ "saBefore": 37.795275590551185,
+ "turnPoint": true,
+ "type": "VSAPoint",
+ "x": 669.9070856247861,
+ "y": 1038.0664013590958
+ },
+ {
+ "saAfter": 37.795275590551185,
+ "saBefore": 37.795275590551185,
+ "turnPoint": true,
+ "type": "VSAPoint",
+ "x": 425.2968981082859,
+ "y": 997.079828054777
+ },
+ {
+ "saBefore": 37.795275590551185,
+ "turnPoint": true,
+ "type": "VSAPoint",
+ "x": 379.70536635128207,
+ "y": 793.6376774711312
+ },
+ {
+ "turnPoint": true,
+ "type": "VSAPoint",
+ "x": 580.6895517317213,
+ "y": 764.5585799377853
+ }
+ ]
+}
diff --git a/src/test/ValentinaTest/share/smart_pattern_#184_case1/output.json b/src/test/ValentinaTest/share/smart_pattern_#184_case1/output.json
new file mode 100644
index 000000000..46ce36176
--- /dev/null
+++ b/src/test/ValentinaTest/share/smart_pattern_#184_case1/output.json
@@ -0,0 +1,74 @@
+{
+ "vector": [
+ {
+ "type": "QPointF",
+ "x": 588.3649734856448,
+ "y": 778.9784872844474
+ },
+ {
+ "type": "QPointF",
+ "x": 596.2541170835045,
+ "y": 665.9457492496151
+ },
+ {
+ "type": "QPointF",
+ "x": 597.6571516077917,
+ "y": 665.7389557340655
+ },
+ {
+ "type": "QPointF",
+ "x": 658.2963192477988,
+ "y": 825.696946170516
+ },
+ {
+ "type": "QPointF",
+ "x": 667.9744279101468,
+ "y": 712.8390031327132
+ },
+ {
+ "type": "QPointF",
+ "x": 669.3849599515413,
+ "y": 712.6577947901065
+ },
+ {
+ "type": "QPointF",
+ "x": 682.2742197194734,
+ "y": 748.9701993850377
+ },
+ {
+ "type": "QPointF",
+ "x": 916.3859644867284,
+ "y": 715.0980902591248
+ },
+ {
+ "type": "QPointF",
+ "x": 932.2799599616667,
+ "y": 952.2702395211089
+ },
+ {
+ "type": "QPointF",
+ "x": 675.5894289258003,
+ "y": 1077.340699266617
+ },
+ {
+ "type": "QPointF",
+ "x": 393.97611715611157,
+ "y": 1030.1539293143521
+ },
+ {
+ "type": "QPointF",
+ "x": 341.99572232904575,
+ "y": 798.2028869986758
+ },
+ {
+ "type": "QPointF",
+ "x": 581.2124761447806,
+ "y": 763.5921672415425
+ },
+ {
+ "type": "QPointF",
+ "x": 588.3649734856448,
+ "y": 778.9784872844474
+ }
+ ]
+}
diff --git a/src/test/ValentinaTest/share/test_data.qrc b/src/test/ValentinaTest/share/test_data.qrc
index 054d83e76..85b2e5a06 100644
--- a/src/test/ValentinaTest/share/test_data.qrc
+++ b/src/test/ValentinaTest/share/test_data.qrc
@@ -155,5 +155,7 @@
hood_1/output.json
hood_2/input.json
hood_2/output.json
+ smart_pattern_#184_case1/input.json
+ smart_pattern_#184_case1/output.json
diff --git a/src/test/ValentinaTest/tst_vabstractpiece.cpp b/src/test/ValentinaTest/tst_vabstractpiece.cpp
index 76bda6036..a823a9728 100644
--- a/src/test/ValentinaTest/tst_vabstractpiece.cpp
+++ b/src/test/ValentinaTest/tst_vabstractpiece.cpp
@@ -956,6 +956,12 @@ void TST_VAbstractPiece::BrokenDetailEquidistant_data()
QStringLiteral("://hood_2/input.json"),
QStringLiteral("://hood_2/output.json"),
37.795275590551185 /*seam allowance width*/);
+
+ // See the file "collection/bugs/smart_pattern_#184_case1.val"
+ ASSERT_TEST_CASE("Issue #184 case 1",
+ QStringLiteral("://smart_pattern_#184_case1/input.json"),
+ QStringLiteral("://smart_pattern_#184_case1/output.json"),
+ 37.795275590551185 /*seam allowance width*/);
}
//---------------------------------------------------------------------------------------------------------------------