From d5310d8ae1da59cac01a56cfc03e441cc6d6f000 Mon Sep 17 00:00:00 2001 From: Roman Telezhynskyi Date: Tue, 30 Mar 2021 16:20:38 +0300 Subject: [PATCH] Fix incorrect seam allowance. Closes #112 --- ChangeLog.txt | 1 + src/libs/vlayout/testpath.cpp | 12 - src/libs/vlayout/testpath.h | 20 +- src/libs/vlayout/vabstractpiece.cpp | 138 +++++------ src/libs/vtest/abstracttest.cpp | 69 +++++- src/libs/vtest/abstracttest.h | 23 +- .../share/smart_pattern_#112/input.json | 232 ++++++++++++++++++ .../share/smart_pattern_#112/output.json | 194 +++++++++++++++ src/test/ValentinaTest/share/test_data.qrc | 2 + src/test/ValentinaTest/tst_vabstractpiece.cpp | 48 ++-- src/test/ValentinaTest/tst_vabstractpiece.h | 2 + 11 files changed, 620 insertions(+), 121 deletions(-) create mode 100644 src/test/ValentinaTest/share/smart_pattern_#112/input.json create mode 100644 src/test/ValentinaTest/share/smart_pattern_#112/output.json diff --git a/ChangeLog.txt b/ChangeLog.txt index e9d307d68..d3c917ce6 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -2,6 +2,7 @@ - Fix incorrect calculation of value for multisize measurements in Valentina. - [smart-pattern/valentina#109] Pattern label template placeholder with dimension label value. - Incorrect duplication of a piece. Missing restoring pins. +- [smart-pattern/valentina#112] Incorrect seam allowance. # Version 0.7.45 Feb 26, 2021 - Fix incorrect seam allowance for angle type second edge right angle. diff --git a/src/libs/vlayout/testpath.cpp b/src/libs/vlayout/testpath.cpp index 937a924e8..3a7eb8f78 100644 --- a/src/libs/vlayout/testpath.cpp +++ b/src/libs/vlayout/testpath.cpp @@ -28,7 +28,6 @@ #include "testpath.h" #include -#include #include #include #include @@ -62,15 +61,4 @@ void VectorToJson(const QVector &points, QJsonObject &json) json[QLatin1String("vector")] = pointsArray; } -//--------------------------------------------------------------------------------------------------------------------- -void VectorToJson(const QVector &points, QJsonObject &json) -{ - QJsonArray pointsArray; - for (auto point: points) - { - pointsArray.append(point.toJson()); - } - json[QLatin1String("vector")] = pointsArray; -} - #endif // !defined(V_NO_ASSERT) diff --git a/src/libs/vlayout/testpath.h b/src/libs/vlayout/testpath.h index b3e92c01b..5ecdc4d57 100644 --- a/src/libs/vlayout/testpath.h +++ b/src/libs/vlayout/testpath.h @@ -30,20 +30,23 @@ #include #include +#include #include #include #include #include class QPointF; -class QJsonObject; template class QVector; class VSAPoint; +class VRawSAPoint; #if !defined(V_NO_ASSERT) QJsonObject PointToJson(const QPointF &point); void VectorToJson(const QVector &points, QJsonObject &json); -void VectorToJson(const QVector &points, QJsonObject &json); + +template +void VectorToJson(const QVector &points, QJsonObject &json); //--------------------------------------------------------------------------------------------------------------------- template @@ -78,6 +81,17 @@ void DumpVector(const QVector &points, const QString &templateName=QString()) out.flush(); } } -#endif // !defined(V_NO_ASSERT) +//--------------------------------------------------------------------------------------------------------------------- +template +void VectorToJson(const QVector &points, QJsonObject &json) +{ + QJsonArray pointsArray; + for (auto point: points) + { + pointsArray.append(point.toJson()); + } + json[QLatin1String("vector")] = pointsArray; +} +#endif // !defined(V_NO_ASSERT) #endif // TESTPATH_H diff --git a/src/libs/vlayout/vabstractpiece.cpp b/src/libs/vlayout/vabstractpiece.cpp index 9152ef8eb..5d2cc0960 100644 --- a/src/libs/vlayout/vabstractpiece.cpp +++ b/src/libs/vlayout/vabstractpiece.cpp @@ -1213,70 +1213,48 @@ QVector VAbstractPiece::CheckLoops(const QVector &points) */ auto VAbstractPiece::CheckLoops(const QVector &points) -> QVector { -// DumpVector(points); // Uncomment for dumping test data +// DumpVector(points, QStringLiteral("input.json.XXXXXX")); // Uncomment for dumping test data - int count = points.size(); /*If we got less than 4 points no need seek loops.*/ - if (count < 4) + if (points.size() < 4) { return CleanLoopArtifacts(points); } - const bool pathClosed = (points.first() == points.last()); + bool loopFound = false; - QVector ekvPoints; - ekvPoints.reserve(points.size()); - - QVector uniqueVertices; - uniqueVertices.reserve(4); - - qint32 i, j, jNext = 0; - for (i = 0; i < count; ++i) + auto CheckLoop = [&loopFound](const QVector &points) { - /*Last three points no need to check.*/ - /*Triangle can not contain a loop*/ - if (i > count-3) + loopFound = false; + + const bool pathClosed = (points.first() == points.last()); + + QVector ekvPoints; + ekvPoints.reserve(points.size()); + + qint32 i; + for (i = 0; i < points.size(); ++i) { - ekvPoints.append(points.at(i)); - continue; - } - - enum LoopIntersectType { NoIntersection, BoundedIntersection, ParallelIntersection }; - - QPointF crosPoint; - LoopIntersectType status = NoIntersection; - const QLineF line1(points.at(i), points.at(i+1)); - // Because a path can contains several loops we will seek the last and only then remove the loop(s) - // That's why we parse from the end - for (j = count-1; j >= i+2; --j) - { - j == count-1 ? jNext = 0 : jNext = j+1; - QLineF line2(points.at(j), points.at(jNext)); - - if(qFuzzyIsNull(line2.length())) - {//If a path is closed the edge (count-1;0) length will be 0 + /*Last three points no need to check.*/ + /*Triangle can not contain a loop*/ + if (loopFound || i > points.size()-4) + { + ekvPoints.append(points.at(i)); continue; } - uniqueVertices.clear(); + enum LoopIntersectType { NoIntersection, BoundedIntersection, ParallelIntersection }; - auto AddUniqueIndex = [&uniqueVertices](qint32 i) + QPointF crosPoint; + LoopIntersectType status = NoIntersection; + const QLineF line1(points.at(i), points.at(i+1)); + + const int limit = pathClosed && i == 0 ? 2 : 1; + qint32 j; + for (j = i+2; j < points.size()-limit; ++j) { - if (not uniqueVertices.contains(i)) - { - uniqueVertices.append(i); - } - }; + QLineF line2(points.at(j), points.at(j+1)); - AddUniqueIndex(i); - AddUniqueIndex(i+1); - AddUniqueIndex(j); - - // For closed path last point is equal to first. Using index of the first. - pathClosed && jNext == count-1 ? AddUniqueIndex(0) : AddUniqueIndex(jNext); - - if (uniqueVertices.size() == 4) - {// Lines are not neighbors const QLineF::IntersectType intersect = Intersects(line1, line2, &crosPoint); if (intersect == QLineF::NoIntersection) { // According to the documentation QLineF::NoIntersection indicates that the lines do not intersect; @@ -1294,32 +1272,48 @@ auto VAbstractPiece::CheckLoops(const QVector &points) -> QVector j ? i = jNext : i = j; // Skip a loop - break; - case BoundedIntersection: - ekvPoints.append(points.at(i)); - ekvPoints.append(crosPoint); - i = j; - break; - case NoIntersection: - /*We have not found loop.*/ - ekvPoints.append(points.at(i)); - break; - default: - break; + switch (status) + { + case ParallelIntersection: + /*We have found a loop.*/ + ekvPoints.append(points.at(i)); + ekvPoints.append(points.at(j+1)); + i = j+1; // Skip a loop + loopFound = true; + break; + case BoundedIntersection: + ekvPoints.append(points.at(i)); + ekvPoints.append(crosPoint); + i = j; + loopFound = true; + break; + case NoIntersection: + /*We have not found loop.*/ + ekvPoints.append(points.at(i)); + break; + default: + break; + } } - } + return ekvPoints; + }; + + QVector ekvPoints = points; + qint32 i; + const int maxLoops = 10000; // limit number of loops to be removed + + for (i = 0; i < maxLoops; ++i) + { + ekvPoints = CheckLoop(ekvPoints); + if (not loopFound) + { + break; + } + } + const QVector cleaned = CleanLoopArtifacts(ekvPoints); -// DumpVector(cleaned); // Uncomment for dumping test data +// DumpVector(cleaned, QStringLiteral("output.json.XXXXXX")); // Uncomment for dumping test data return cleaned; } diff --git a/src/libs/vtest/abstracttest.cpp b/src/libs/vtest/abstracttest.cpp index a26af7143..318c934fe 100644 --- a/src/libs/vtest/abstracttest.cpp +++ b/src/libs/vtest/abstracttest.cpp @@ -56,6 +56,7 @@ #include "../vgeometry/vspline.h" #include "../vgeometry/vsplinepath.h" #include "../vlayout/vabstractpiece.h" +#include "../vlayout/vrawsapoint.h" #include "../vpatterndb/vcontainer.h" #include "../vpatterndb/vpiece.h" #include "../vpatterndb/vpiecenode.h" @@ -68,7 +69,7 @@ AbstractTest::AbstractTest(QObject *parent) : } //--------------------------------------------------------------------------------------------------------------------- -void AbstractTest::VectorFromJson(const QString &json, QVector& vector) +void AbstractTest::VectorFromJson(const QString &json, QVector& vector) const { QByteArray saveData; PrepareDocument(json, saveData); @@ -102,7 +103,7 @@ void AbstractTest::VectorFromJson(const QString &json, QVector& vector) } //--------------------------------------------------------------------------------------------------------------------- -void AbstractTest::VectorFromJson(const QString &json, QVector &vector) +void AbstractTest::VectorFromJson(const QString &json, QVector &vector) const { QByteArray saveData; PrepareDocument(json, saveData); @@ -133,6 +134,38 @@ void AbstractTest::VectorFromJson(const QString &json, QVector &vector } } +//--------------------------------------------------------------------------------------------------------------------- +void AbstractTest::VectorFromJson(const QString &json, QVector &vector) const +{ + QByteArray saveData; + PrepareDocument(json, saveData); + QJsonDocument loadDoc(QJsonDocument::fromJson(saveData)); + + const QString vectorKey = QStringLiteral("vector"); + + QJsonObject vectorObject = loadDoc.object(); + TestRoot(vectorObject, vectorKey, json); + + QJsonArray vectorArray = vectorObject[vectorKey].toArray(); + for (int i = 0; i < vectorArray.size(); ++i) + { + QJsonObject pointObject = vectorArray[i].toObject(); + + QString type; + AbstractTest::ReadStringValue(pointObject, QStringLiteral("type"), type); + + if (type != QLatin1String("VRawSAPoint")) + { + const QString error = QStringLiteral("Invalid json file '%1'. Unexpected class '%2'.").arg(json, type); + QFAIL(qUtf8Printable(error)); + } + + VRawSAPoint point; + RawSAPointFromJson(pointObject, point); + vector.append(point); + } +} + //--------------------------------------------------------------------------------------------------------------------- void AbstractTest::PieceFromJson(const QString &json, VPiece &piece, QSharedPointer &data) { @@ -505,7 +538,7 @@ void AbstractTest::PrepareDocument(const QString &json, QByteArray &data) const } //--------------------------------------------------------------------------------------------------------------------- -void AbstractTest::TestRoot(const QJsonObject &root, const QString &attribute, const QString &file) +void AbstractTest::TestRoot(const QJsonObject &root, const QString &attribute, const QString &file) const { if (not root.contains(attribute)) { @@ -516,7 +549,7 @@ void AbstractTest::TestRoot(const QJsonObject &root, const QString &attribute, c //--------------------------------------------------------------------------------------------------------------------- void AbstractTest::ReadStringValue(const QJsonObject &itemObject, const QString &attribute, QString &value, - const QString &defaultValue) + const QString &defaultValue) const { if (itemObject.contains(attribute)) { @@ -547,7 +580,7 @@ void AbstractTest::ReadStringValue(const QJsonObject &itemObject, const QString //--------------------------------------------------------------------------------------------------------------------- void AbstractTest::ReadBooleanValue(const QJsonObject &itemObject, const QString &attribute, bool &value, - const QString &defaultValue) + const QString &defaultValue) const { if (itemObject.contains(attribute)) { @@ -674,7 +707,7 @@ void AbstractTest::ReadPieceNodeValue(const QJsonObject &itemObject, VPieceNode } //--------------------------------------------------------------------------------------------------------------------- -void AbstractTest::QPointFromJson(const QJsonObject &itemObject, QPointF &point) +void AbstractTest::QPointFromJson(const QJsonObject &itemObject, QPointF &point) const { qreal x = 0; AbstractTest::ReadDoubleValue(itemObject, QStringLiteral("x"), x); @@ -688,7 +721,7 @@ void AbstractTest::QPointFromJson(const QJsonObject &itemObject, QPointF &point) //--------------------------------------------------------------------------------------------------------------------- template::value>::type*> void AbstractTest::ReadDoubleValue(const QJsonObject &itemObject, const QString &attribute, T &value, - const QString &defaultValue) + const QString &defaultValue) const { if (itemObject.contains(attribute)) { @@ -727,7 +760,7 @@ void AbstractTest::ReadDoubleValue(const QJsonObject &itemObject, const QString //--------------------------------------------------------------------------------------------------------------------- template::value>::type*> void AbstractTest::ReadDoubleValue(const QJsonObject &itemObject, const QString &attribute, T &value, - const QString &defaultValue) + const QString &defaultValue) const { if (itemObject.contains(attribute)) { @@ -766,7 +799,7 @@ void AbstractTest::ReadDoubleValue(const QJsonObject &itemObject, const QString //--------------------------------------------------------------------------------------------------------------------- template::value>::type*> void AbstractTest::ReadDoubleValue(const QJsonObject &itemObject, const QString &attribute, T &value, - const QString &defaultValue) + const QString &defaultValue) const { if (itemObject.contains(attribute)) { @@ -840,7 +873,7 @@ void AbstractTest::QLineFromJson(const QJsonObject &itemObject, QLineF &line) } //--------------------------------------------------------------------------------------------------------------------- -void AbstractTest::SAPointFromJson(const QJsonObject &itemObject, VSAPoint &point) +void AbstractTest::SAPointFromJson(const QJsonObject &itemObject, VSAPoint &point) const { qreal x = 0; AbstractTest::ReadDoubleValue(itemObject, QStringLiteral("x"), x); @@ -864,6 +897,22 @@ void AbstractTest::SAPointFromJson(const QJsonObject &itemObject, VSAPoint &poin point.SetAngleType(angleType); } +//--------------------------------------------------------------------------------------------------------------------- +void AbstractTest::RawSAPointFromJson(const QJsonObject &itemObject, VRawSAPoint &point) const +{ + qreal x = 0; + AbstractTest::ReadDoubleValue(itemObject, QStringLiteral("x"), x); + point.setX(x); + + qreal y = 0; + AbstractTest::ReadDoubleValue(itemObject, QStringLiteral("y"), y); + point.setY(y); + + bool loopPoint; + AbstractTest::ReadBooleanValue(itemObject, QStringLiteral("loopPoint"), loopPoint, QStringLiteral("0")); + point.SetLoopPoint(loopPoint); +} + //--------------------------------------------------------------------------------------------------------------------- void AbstractTest::SplineFromJson(const QJsonObject &itemObject, QSharedPointer &data) { diff --git a/src/libs/vtest/abstracttest.h b/src/libs/vtest/abstracttest.h index cd7b4c2d9..994eedc0d 100644 --- a/src/libs/vtest/abstracttest.h +++ b/src/libs/vtest/abstracttest.h @@ -61,6 +61,7 @@ class VSplinePoint; class VPieceNode; enum class GOType : qint8; struct VPiecePassmarkData; +class VRawSAPoint; class AbstractTest : public QObject { @@ -68,8 +69,9 @@ class AbstractTest : public QObject public: explicit AbstractTest(QObject *parent = nullptr); - void VectorFromJson(const QString &json, QVector& vector); - void VectorFromJson(const QString &json, QVector& vector); + void VectorFromJson(const QString &json, QVector& vector) const; + void VectorFromJson(const QString &json, QVector& vector) const; + void VectorFromJson(const QString &json, QVector& vector) const; void PieceFromJson(const QString &json, VPiece &piece, QSharedPointer &data); @@ -91,30 +93,31 @@ protected: bool CopyRecursively(const QString &srcFilePath, const QString &tgtFilePath) const; void PrepareDocument(const QString &json, QByteArray &data) const; - void TestRoot(const QJsonObject &root, const QString &attribute, const QString &file); + void TestRoot(const QJsonObject &root, const QString &attribute, const QString &file) const; template ::value>::type* = nullptr> void ReadDoubleValue(const QJsonObject &itemObject, const QString &attribute, T &value, - const QString &defaultValue = QString()); + const QString &defaultValue = QString()) const; template ::value>::type* = nullptr> void ReadDoubleValue(const QJsonObject &itemObject, const QString &attribute, T &value, - const QString &defaultValue = QString()); + const QString &defaultValue = QString()) const; template ::value>::type* = nullptr> void ReadDoubleValue(const QJsonObject &itemObject, const QString &attribute, T &value, - const QString &defaultValue = QString()); + const QString &defaultValue = QString()) const; void ReadStringValue(const QJsonObject &itemObject, const QString &attribute, QString &value, - const QString &defaultValue = QString()); + const QString &defaultValue = QString()) const; void ReadBooleanValue(const QJsonObject &itemObject, const QString &attribute, bool &value, - const QString &defaultValue = QString()); + const QString &defaultValue = QString()) const; void ReadPointValue(const QJsonObject &itemObject, const QString &attribute, VPointF &value); void ReadSplinePointValues(const QJsonObject &itemObject, const QString &attribute, QVector &points); void ReadSplinePointValue(const QJsonObject &itemObject, VSplinePoint &point); void ReadPieceNodeValue(const QJsonObject &itemObject, VPieceNode &node); - void QPointFromJson(const QJsonObject &itemObject, QPointF &point); + void QPointFromJson(const QJsonObject &itemObject, QPointF &point) const; void VPointFromJson(const QJsonObject &itemObject, VPointF &point); void QLineFromJson(const QJsonObject &itemObject, QLineF &line); - void SAPointFromJson(const QJsonObject &itemObject, VSAPoint &point); + void SAPointFromJson(const QJsonObject &itemObject, VSAPoint &point) const; + void RawSAPointFromJson(const QJsonObject &itemObject, VRawSAPoint &point) const; void SplineFromJson(const QJsonObject &itemObject, QSharedPointer &data); void SplinePathFromJson(const QJsonObject &itemObject, QSharedPointer &data); diff --git a/src/test/ValentinaTest/share/smart_pattern_#112/input.json b/src/test/ValentinaTest/share/smart_pattern_#112/input.json new file mode 100644 index 000000000..c1d145d96 --- /dev/null +++ b/src/test/ValentinaTest/share/smart_pattern_#112/input.json @@ -0,0 +1,232 @@ +{ + "vector": [ + { + "loopPoint": false, + "type": "VRawSAPoint", + "x": -3124.2446685548284, + "y": -340.15748031496076 + }, + { + "loopPoint": false, + "type": "VRawSAPoint", + "x": -3111.699943251791, + "y": -396.7401714170824 + }, + { + "loopPoint": false, + "type": "VRawSAPoint", + "x": -2725.3596865816003, + "y": -585.8267716535435 + }, + { + "loopPoint": false, + "type": "VRawSAPoint", + "x": -2687.564410991049, + "y": -585.8267716535435 + }, + { + "loopPoint": false, + "type": "VRawSAPoint", + "x": -2677.58560358191, + "y": -569.3428170188263 + }, + { + "loopPoint": false, + "type": "VRawSAPoint", + "x": -2665.1502732124804, + "y": -552.0412529412208 + }, + { + "loopPoint": false, + "type": "VRawSAPoint", + "x": -2654.7385639979766, + "y": -539.3532784199779 + }, + { + "loopPoint": false, + "type": "VRawSAPoint", + "x": -2642.6534846020877, + "y": -526.5369475528651 + }, + { + "loopPoint": false, + "type": "VRawSAPoint", + "x": -2629.0304140300964, + "y": -514.3953398593414 + }, + { + "loopPoint": false, + "type": "VRawSAPoint", + "x": -2621.6288162143724, + "y": -508.90682548803926 + }, + { + "loopPoint": false, + "type": "VRawSAPoint", + "x": -2617.633216578171, + "y": -506.2259849672243 + }, + { + "loopPoint": false, + "type": "VRawSAPoint", + "x": -2607.5875815658464, + "y": -500.78291850199804 + }, + { + "loopPoint": false, + "type": "VRawSAPoint", + "x": -2589.3518167947404, + "y": -492.6769341780546 + }, + { + "loopPoint": false, + "type": "VRawSAPoint", + "x": -2562.160275286112, + "y": -482.74399225847844 + }, + { + "loopPoint": false, + "type": "VRawSAPoint", + "x": -2536.9822947561124, + "y": -474.79665668016196 + }, + { + "loopPoint": false, + "type": "VRawSAPoint", + "x": -2527.256410822591, + "y": -472.0553685667312 + }, + { + "loopPoint": false, + "type": "VRawSAPoint", + "x": -2506.5962179242733, + "y": -340.15748031496076 + }, + { + "loopPoint": false, + "type": "VRawSAPoint", + "x": -2515.110032578323, + "y": -335.7555078847252 + }, + { + "loopPoint": false, + "type": "VRawSAPoint", + "x": -2535.9026816577343, + "y": -327.4893541781814 + }, + { + "loopPoint": false, + "type": "VRawSAPoint", + "x": -2559.9139093453923, + "y": -319.92499126438355 + }, + { + "loopPoint": false, + "type": "VRawSAPoint", + "x": -2585.699887733156, + "y": -313.12513181892416 + }, + { + "loopPoint": false, + "type": "VRawSAPoint", + "x": -2624.7774917122233, + "y": -304.38080998706323 + }, + { + "loopPoint": false, + "type": "VRawSAPoint", + "x": -2669.6720177906936, + "y": -296.12066401328417 + }, + { + "loopPoint": false, + "type": "VRawSAPoint", + "x": -2698.5135894968607, + "y": -291.6966931721503 + }, + { + "loopPoint": false, + "type": "VRawSAPoint", + "x": -2733.7651077284, + "y": -288.0502381685658 + }, + { + "loopPoint": false, + "type": "VRawSAPoint", + "x": -2778.001039243382, + "y": -285.2249501336674 + }, + { + "loopPoint": false, + "type": "VRawSAPoint", + "x": -2830.958905626066, + "y": -283.6151470999638 + }, + { + "loopPoint": false, + "type": "VRawSAPoint", + "x": -2883.9661070936895, + "y": -283.5584406781999 + }, + { + "loopPoint": false, + "type": "VRawSAPoint", + "x": -2901.245682896105, + "y": -284.5648866073816 + }, + { + "loopPoint": false, + "type": "VRawSAPoint", + "x": -2928.8761792613104, + "y": -287.3856894036893 + }, + { + "loopPoint": false, + "type": "VRawSAPoint", + "x": -2964.3753054127446, + "y": -292.55631940653257 + }, + { + "loopPoint": false, + "type": "VRawSAPoint", + "x": -2991.658167915314, + "y": -297.4313269801869 + }, + { + "loopPoint": false, + "type": "VRawSAPoint", + "x": -3042.8109922236317, + "y": -308.3088184858541 + }, + { + "loopPoint": false, + "type": "VRawSAPoint", + "x": -3067.2435220244433, + "y": -314.8760955596215 + }, + { + "loopPoint": false, + "type": "VRawSAPoint", + "x": -3083.7898789348988, + "y": -320.39818087512595 + }, + { + "loopPoint": false, + "type": "VRawSAPoint", + "x": -3100.269407664129, + "y": -327.1484210254447 + }, + { + "loopPoint": false, + "type": "VRawSAPoint", + "x": -3116.4133322750586, + "y": -335.3579733766769 + }, + { + "loopPoint": false, + "type": "VRawSAPoint", + "x": -3124.2446685548284, + "y": -340.15748031496076 + } + ] +} diff --git a/src/test/ValentinaTest/share/smart_pattern_#112/output.json b/src/test/ValentinaTest/share/smart_pattern_#112/output.json new file mode 100644 index 000000000..6950e917a --- /dev/null +++ b/src/test/ValentinaTest/share/smart_pattern_#112/output.json @@ -0,0 +1,194 @@ +{ + "vector": [ + { + "type": "QPointF", + "x": -3124.2446685548284, + "y": -340.15748031496076 + }, + { + "type": "QPointF", + "x": -3111.699943251791, + "y": -396.7401714170824 + }, + { + "type": "QPointF", + "x": -2725.3596865816003, + "y": -585.8267716535435 + }, + { + "type": "QPointF", + "x": -2687.564410991049, + "y": -585.8267716535435 + }, + { + "type": "QPointF", + "x": -2677.58560358191, + "y": -569.3428170188263 + }, + { + "type": "QPointF", + "x": -2665.1502732124804, + "y": -552.0412529412208 + }, + { + "type": "QPointF", + "x": -2654.7385639979766, + "y": -539.3532784199779 + }, + { + "type": "QPointF", + "x": -2642.6534846020877, + "y": -526.5369475528651 + }, + { + "type": "QPointF", + "x": -2629.0304140300964, + "y": -514.3953398593414 + }, + { + "type": "QPointF", + "x": -2621.6288162143724, + "y": -508.90682548803926 + }, + { + "type": "QPointF", + "x": -2617.633216578171, + "y": -506.2259849672243 + }, + { + "type": "QPointF", + "x": -2607.5875815658464, + "y": -500.78291850199804 + }, + { + "type": "QPointF", + "x": -2589.3518167947404, + "y": -492.6769341780546 + }, + { + "type": "QPointF", + "x": -2562.160275286112, + "y": -482.74399225847844 + }, + { + "type": "QPointF", + "x": -2536.9822947561124, + "y": -474.79665668016196 + }, + { + "type": "QPointF", + "x": -2527.256410822591, + "y": -472.0553685667312 + }, + { + "type": "QPointF", + "x": -2506.5962179242733, + "y": -340.15748031496076 + }, + { + "type": "QPointF", + "x": -2515.110032578323, + "y": -335.7555078847252 + }, + { + "type": "QPointF", + "x": -2535.9026816577343, + "y": -327.4893541781814 + }, + { + "type": "QPointF", + "x": -2559.9139093453923, + "y": -319.92499126438355 + }, + { + "type": "QPointF", + "x": -2585.699887733156, + "y": -313.12513181892416 + }, + { + "type": "QPointF", + "x": -2624.7774917122233, + "y": -304.38080998706323 + }, + { + "type": "QPointF", + "x": -2669.6720177906936, + "y": -296.12066401328417 + }, + { + "type": "QPointF", + "x": -2698.5135894968607, + "y": -291.6966931721503 + }, + { + "type": "QPointF", + "x": -2733.7651077284, + "y": -288.0502381685658 + }, + { + "type": "QPointF", + "x": -2778.001039243382, + "y": -285.2249501336674 + }, + { + "type": "QPointF", + "x": -2830.958905626066, + "y": -283.6151470999638 + }, + { + "type": "QPointF", + "x": -2883.9661070936895, + "y": -283.5584406781999 + }, + { + "type": "QPointF", + "x": -2901.245682896105, + "y": -284.5648866073816 + }, + { + "type": "QPointF", + "x": -2928.8761792613104, + "y": -287.3856894036893 + }, + { + "type": "QPointF", + "x": -2964.3753054127446, + "y": -292.55631940653257 + }, + { + "type": "QPointF", + "x": -2991.658167915314, + "y": -297.4313269801869 + }, + { + "type": "QPointF", + "x": -3042.8109922236317, + "y": -308.3088184858541 + }, + { + "type": "QPointF", + "x": -3067.2435220244433, + "y": -314.8760955596215 + }, + { + "type": "QPointF", + "x": -3083.7898789348988, + "y": -320.39818087512595 + }, + { + "type": "QPointF", + "x": -3100.269407664129, + "y": -327.1484210254447 + }, + { + "type": "QPointF", + "x": -3116.4133322750586, + "y": -335.3579733766769 + }, + { + "type": "QPointF", + "x": -3124.2446685548284, + "y": -340.15748031496076 + } + ] +} diff --git a/src/test/ValentinaTest/share/test_data.qrc b/src/test/ValentinaTest/share/test_data.qrc index c4f5a4fb9..0761513dd 100644 --- a/src/test/ValentinaTest/share/test_data.qrc +++ b/src/test/ValentinaTest/share/test_data.qrc @@ -133,5 +133,7 @@ Issue_548_case2/output.json Issue_548_case3/input.json Issue_548_case3/output.json + smart_pattern_#112/input.json + smart_pattern_#112/output.json diff --git a/src/test/ValentinaTest/tst_vabstractpiece.cpp b/src/test/ValentinaTest/tst_vabstractpiece.cpp index 93fb3122c..6cffc46ca 100644 --- a/src/test/ValentinaTest/tst_vabstractpiece.cpp +++ b/src/test/ValentinaTest/tst_vabstractpiece.cpp @@ -28,6 +28,7 @@ #include "tst_vabstractpiece.h" #include "../vlayout/vabstractpiece.h" +#include "../vlayout/vrawsapoint.h" #include #include @@ -371,6 +372,39 @@ void TST_VAbstractPiece::SumTrapezoids() const Case5(); } +//--------------------------------------------------------------------------------------------------------------------- +void TST_VAbstractPiece::RawPathRemoveLoop_data() const +{ + QTest::addColumn>("path"); + QTest::addColumn>("expect"); + + auto ASSERT_TEST_CASE = [this](const char *title, const QString &input, const QString &output) + { + QVector inputPoints; + AbstractTest::VectorFromJson(input, inputPoints); + + QVector outputPoints; + AbstractTest::VectorFromJson(output, outputPoints); + + QTest::newRow(title) << inputPoints << outputPoints; + }; + + // See file src/app/share/collection/bugs/smart_pattern_#112.val (private collection) + ASSERT_TEST_CASE("Loop intersection", + QStringLiteral("://smart_pattern_#112/input.json"), + QStringLiteral("://smart_pattern_#112/output.json")); +} + +//--------------------------------------------------------------------------------------------------------------------- +void TST_VAbstractPiece::RawPathRemoveLoop() const +{ + QFETCH(QVector, path); + QFETCH(QVector, expect); + + QVector res = VAbstractPiece::CheckLoops(path); + Comparison(res, expect); +} + //--------------------------------------------------------------------------------------------------------------------- void TST_VAbstractPiece::PathRemoveLoop_data() const { @@ -417,11 +451,6 @@ void TST_VAbstractPiece::PathRemoveLoop_data() const res << QPointF(20, 10); QTest::newRow("One loop, closed a path (four unique points)") << path << res; - path.removeLast(); - res.removeLast(); - - QTest::newRow("One loop, unclosed a path (four unique points)") << path << res; - path.clear(); path << QPointF(20, 10); path << QPointF(20, 20); @@ -438,11 +467,6 @@ void TST_VAbstractPiece::PathRemoveLoop_data() const res << QPointF(20, 10); QTest::newRow("Two loops, closed a path (six unique points)") << path << res; - path.removeLast(); - res.removeLast(); - - QTest::newRow("Two loops, unclosed a path (six unique points)") << path << res; - path.clear(); path << QPointF(20, 10); path << QPointF(20, 20); @@ -459,10 +483,6 @@ void TST_VAbstractPiece::PathRemoveLoop_data() const res << QPointF(20, 10); QTest::newRow("One loop, the first loop, closed a path (six unique points)") << path << res; - path.removeLast(); - res.removeLast(); - QTest::newRow("One loop, the first loop, unclosed a path (six unique points)") << path << res; - path.clear(); path << QPointF(20, 10); path << QPointF(20, 20); diff --git a/src/test/ValentinaTest/tst_vabstractpiece.h b/src/test/ValentinaTest/tst_vabstractpiece.h index 7775d3453..0fceca326 100644 --- a/src/test/ValentinaTest/tst_vabstractpiece.h +++ b/src/test/ValentinaTest/tst_vabstractpiece.h @@ -45,6 +45,8 @@ private slots: void LayoutAllowanceRemoveLoop_data(); void LayoutAllowanceRemoveLoop() const; void SumTrapezoids() const; + void RawPathRemoveLoop_data() const; + void RawPathRemoveLoop() const; void PathRemoveLoop_data() const; void PathRemoveLoop() const; void PathLoopsCase_data() const;