Fix incorrect seam allowance. Closes #112

This commit is contained in:
Roman Telezhynskyi 2021-03-30 16:20:38 +03:00
parent 33b8482f18
commit d5310d8ae1
11 changed files with 620 additions and 121 deletions

View File

@ -2,6 +2,7 @@
- Fix incorrect calculation of value for multisize measurements in Valentina. - Fix incorrect calculation of value for multisize measurements in Valentina.
- [smart-pattern/valentina#109] Pattern label template placeholder with dimension label value. - [smart-pattern/valentina#109] Pattern label template placeholder with dimension label value.
- Incorrect duplication of a piece. Missing restoring pins. - Incorrect duplication of a piece. Missing restoring pins.
- [smart-pattern/valentina#112] Incorrect seam allowance.
# Version 0.7.45 Feb 26, 2021 # Version 0.7.45 Feb 26, 2021
- Fix incorrect seam allowance for angle type second edge right angle. - Fix incorrect seam allowance for angle type second edge right angle.

View File

@ -28,7 +28,6 @@
#include "testpath.h" #include "testpath.h"
#include <QVector> #include <QVector>
#include <QJsonArray>
#include <QTemporaryFile> #include <QTemporaryFile>
#include <QJsonObject> #include <QJsonObject>
#include <QTextStream> #include <QTextStream>
@ -62,15 +61,4 @@ void VectorToJson(const QVector<QPointF> &points, QJsonObject &json)
json[QLatin1String("vector")] = pointsArray; json[QLatin1String("vector")] = pointsArray;
} }
//---------------------------------------------------------------------------------------------------------------------
void VectorToJson(const QVector<VSAPoint> &points, QJsonObject &json)
{
QJsonArray pointsArray;
for (auto point: points)
{
pointsArray.append(point.toJson());
}
json[QLatin1String("vector")] = pointsArray;
}
#endif // !defined(V_NO_ASSERT) #endif // !defined(V_NO_ASSERT)

View File

@ -30,20 +30,23 @@
#include <QDir> #include <QDir>
#include <QJsonDocument> #include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject> #include <QJsonObject>
#include <QString> #include <QString>
#include <QTemporaryFile> #include <QTemporaryFile>
#include <QTextStream> #include <QTextStream>
class QPointF; class QPointF;
class QJsonObject;
template <class T> class QVector; template <class T> class QVector;
class VSAPoint; class VSAPoint;
class VRawSAPoint;
#if !defined(V_NO_ASSERT) #if !defined(V_NO_ASSERT)
QJsonObject PointToJson(const QPointF &point); QJsonObject PointToJson(const QPointF &point);
void VectorToJson(const QVector<QPointF> &points, QJsonObject &json); void VectorToJson(const QVector<QPointF> &points, QJsonObject &json);
void VectorToJson(const QVector<VSAPoint> &points, QJsonObject &json);
template <class T>
void VectorToJson(const QVector<T> &points, QJsonObject &json);
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
template <class T> template <class T>
@ -78,6 +81,17 @@ void DumpVector(const QVector<T> &points, const QString &templateName=QString())
out.flush(); out.flush();
} }
} }
#endif // !defined(V_NO_ASSERT)
//---------------------------------------------------------------------------------------------------------------------
template <class T>
void VectorToJson(const QVector<T> &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 #endif // TESTPATH_H

View File

@ -1213,70 +1213,48 @@ QVector<QPointF> VAbstractPiece::CheckLoops(const QVector<QPointF> &points)
*/ */
auto VAbstractPiece::CheckLoops(const QVector<VRawSAPoint> &points) -> QVector<QPointF> auto VAbstractPiece::CheckLoops(const QVector<VRawSAPoint> &points) -> QVector<QPointF>
{ {
// 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 we got less than 4 points no need seek loops.*/
if (count < 4) if (points.size() < 4)
{ {
return CleanLoopArtifacts(points); return CleanLoopArtifacts(points);
} }
const bool pathClosed = (points.first() == points.last()); bool loopFound = false;
QVector<VRawSAPoint> ekvPoints; auto CheckLoop = [&loopFound](const QVector<VRawSAPoint> &points)
ekvPoints.reserve(points.size());
QVector<qint32> uniqueVertices;
uniqueVertices.reserve(4);
qint32 i, j, jNext = 0;
for (i = 0; i < count; ++i)
{ {
/*Last three points no need to check.*/ loopFound = false;
/*Triangle can not contain a loop*/
if (i > count-3) const bool pathClosed = (points.first() == points.last());
QVector<VRawSAPoint> ekvPoints;
ekvPoints.reserve(points.size());
qint32 i;
for (i = 0; i < points.size(); ++i)
{ {
ekvPoints.append(points.at(i)); /*Last three points no need to check.*/
continue; /*Triangle can not contain a loop*/
} if (loopFound || i > points.size()-4)
{
enum LoopIntersectType { NoIntersection, BoundedIntersection, ParallelIntersection }; ekvPoints.append(points.at(i));
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
continue; 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)) QLineF line2(points.at(j), points.at(j+1));
{
uniqueVertices.append(i);
}
};
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); const QLineF::IntersectType intersect = Intersects(line1, line2, &crosPoint);
if (intersect == QLineF::NoIntersection) if (intersect == QLineF::NoIntersection)
{ // According to the documentation QLineF::NoIntersection indicates that the lines do not intersect; { // According to the documentation QLineF::NoIntersection indicates that the lines do not intersect;
@ -1294,32 +1272,48 @@ auto VAbstractPiece::CheckLoops(const QVector<VRawSAPoint> &points) -> QVector<Q
break; break;
} }
} }
status = NoIntersection;
}
switch (status) switch (status)
{ {
case ParallelIntersection: case ParallelIntersection:
/*We have found a loop.*/ /*We have found a loop.*/
ekvPoints.append(points.at(i)); ekvPoints.append(points.at(i));
ekvPoints.append(points.at(jNext)); ekvPoints.append(points.at(j+1));
jNext > j ? i = jNext : i = j; // Skip a loop i = j+1; // Skip a loop
break; loopFound = true;
case BoundedIntersection: break;
ekvPoints.append(points.at(i)); case BoundedIntersection:
ekvPoints.append(crosPoint); ekvPoints.append(points.at(i));
i = j; ekvPoints.append(crosPoint);
break; i = j;
case NoIntersection: loopFound = true;
/*We have not found loop.*/ break;
ekvPoints.append(points.at(i)); case NoIntersection:
break; /*We have not found loop.*/
default: ekvPoints.append(points.at(i));
break; break;
default:
break;
}
} }
} return ekvPoints;
};
QVector<VRawSAPoint> 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<QPointF> cleaned = CleanLoopArtifacts(ekvPoints); const QVector<QPointF> cleaned = CleanLoopArtifacts(ekvPoints);
// DumpVector(cleaned); // Uncomment for dumping test data // DumpVector(cleaned, QStringLiteral("output.json.XXXXXX")); // Uncomment for dumping test data
return cleaned; return cleaned;
} }

View File

@ -56,6 +56,7 @@
#include "../vgeometry/vspline.h" #include "../vgeometry/vspline.h"
#include "../vgeometry/vsplinepath.h" #include "../vgeometry/vsplinepath.h"
#include "../vlayout/vabstractpiece.h" #include "../vlayout/vabstractpiece.h"
#include "../vlayout/vrawsapoint.h"
#include "../vpatterndb/vcontainer.h" #include "../vpatterndb/vcontainer.h"
#include "../vpatterndb/vpiece.h" #include "../vpatterndb/vpiece.h"
#include "../vpatterndb/vpiecenode.h" #include "../vpatterndb/vpiecenode.h"
@ -68,7 +69,7 @@ AbstractTest::AbstractTest(QObject *parent) :
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void AbstractTest::VectorFromJson(const QString &json, QVector<QPointF>& vector) void AbstractTest::VectorFromJson(const QString &json, QVector<QPointF>& vector) const
{ {
QByteArray saveData; QByteArray saveData;
PrepareDocument(json, saveData); PrepareDocument(json, saveData);
@ -102,7 +103,7 @@ void AbstractTest::VectorFromJson(const QString &json, QVector<QPointF>& vector)
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void AbstractTest::VectorFromJson(const QString &json, QVector<VSAPoint> &vector) void AbstractTest::VectorFromJson(const QString &json, QVector<VSAPoint> &vector) const
{ {
QByteArray saveData; QByteArray saveData;
PrepareDocument(json, saveData); PrepareDocument(json, saveData);
@ -133,6 +134,38 @@ void AbstractTest::VectorFromJson(const QString &json, QVector<VSAPoint> &vector
} }
} }
//---------------------------------------------------------------------------------------------------------------------
void AbstractTest::VectorFromJson(const QString &json, QVector<VRawSAPoint> &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<VContainer> &data) void AbstractTest::PieceFromJson(const QString &json, VPiece &piece, QSharedPointer<VContainer> &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)) 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, void AbstractTest::ReadStringValue(const QJsonObject &itemObject, const QString &attribute, QString &value,
const QString &defaultValue) const QString &defaultValue) const
{ {
if (itemObject.contains(attribute)) 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, void AbstractTest::ReadBooleanValue(const QJsonObject &itemObject, const QString &attribute, bool &value,
const QString &defaultValue) const QString &defaultValue) const
{ {
if (itemObject.contains(attribute)) 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; qreal x = 0;
AbstractTest::ReadDoubleValue(itemObject, QStringLiteral("x"), x); AbstractTest::ReadDoubleValue(itemObject, QStringLiteral("x"), x);
@ -688,7 +721,7 @@ void AbstractTest::QPointFromJson(const QJsonObject &itemObject, QPointF &point)
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
template<typename T, typename std::enable_if<std::is_floating_point<T>::value>::type*> template<typename T, typename std::enable_if<std::is_floating_point<T>::value>::type*>
void AbstractTest::ReadDoubleValue(const QJsonObject &itemObject, const QString &attribute, T &value, void AbstractTest::ReadDoubleValue(const QJsonObject &itemObject, const QString &attribute, T &value,
const QString &defaultValue) const QString &defaultValue) const
{ {
if (itemObject.contains(attribute)) if (itemObject.contains(attribute))
{ {
@ -727,7 +760,7 @@ void AbstractTest::ReadDoubleValue(const QJsonObject &itemObject, const QString
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
template<typename T, typename std::enable_if<std::is_enum<T>::value>::type*> template<typename T, typename std::enable_if<std::is_enum<T>::value>::type*>
void AbstractTest::ReadDoubleValue(const QJsonObject &itemObject, const QString &attribute, T &value, void AbstractTest::ReadDoubleValue(const QJsonObject &itemObject, const QString &attribute, T &value,
const QString &defaultValue) const QString &defaultValue) const
{ {
if (itemObject.contains(attribute)) if (itemObject.contains(attribute))
{ {
@ -766,7 +799,7 @@ void AbstractTest::ReadDoubleValue(const QJsonObject &itemObject, const QString
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
template<typename T, typename std::enable_if<std::is_integral<T>::value>::type*> template<typename T, typename std::enable_if<std::is_integral<T>::value>::type*>
void AbstractTest::ReadDoubleValue(const QJsonObject &itemObject, const QString &attribute, T &value, void AbstractTest::ReadDoubleValue(const QJsonObject &itemObject, const QString &attribute, T &value,
const QString &defaultValue) const QString &defaultValue) const
{ {
if (itemObject.contains(attribute)) 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; qreal x = 0;
AbstractTest::ReadDoubleValue(itemObject, QStringLiteral("x"), x); AbstractTest::ReadDoubleValue(itemObject, QStringLiteral("x"), x);
@ -864,6 +897,22 @@ void AbstractTest::SAPointFromJson(const QJsonObject &itemObject, VSAPoint &poin
point.SetAngleType(angleType); 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<VContainer> &data) void AbstractTest::SplineFromJson(const QJsonObject &itemObject, QSharedPointer<VContainer> &data)
{ {

View File

@ -61,6 +61,7 @@ class VSplinePoint;
class VPieceNode; class VPieceNode;
enum class GOType : qint8; enum class GOType : qint8;
struct VPiecePassmarkData; struct VPiecePassmarkData;
class VRawSAPoint;
class AbstractTest : public QObject class AbstractTest : public QObject
{ {
@ -68,8 +69,9 @@ class AbstractTest : public QObject
public: public:
explicit AbstractTest(QObject *parent = nullptr); explicit AbstractTest(QObject *parent = nullptr);
void VectorFromJson(const QString &json, QVector<QPointF>& vector); void VectorFromJson(const QString &json, QVector<QPointF>& vector) const;
void VectorFromJson(const QString &json, QVector<VSAPoint>& vector); void VectorFromJson(const QString &json, QVector<VSAPoint>& vector) const;
void VectorFromJson(const QString &json, QVector<VRawSAPoint>& vector) const;
void PieceFromJson(const QString &json, VPiece &piece, QSharedPointer<VContainer> &data); void PieceFromJson(const QString &json, VPiece &piece, QSharedPointer<VContainer> &data);
@ -91,30 +93,31 @@ protected:
bool CopyRecursively(const QString &srcFilePath, const QString &tgtFilePath) const; bool CopyRecursively(const QString &srcFilePath, const QString &tgtFilePath) const;
void PrepareDocument(const QString &json, QByteArray &data) 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 <typename T, typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr> template <typename T, typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr>
void ReadDoubleValue(const QJsonObject &itemObject, const QString &attribute, T &value, void ReadDoubleValue(const QJsonObject &itemObject, const QString &attribute, T &value,
const QString &defaultValue = QString()); const QString &defaultValue = QString()) const;
template <typename T, typename std::enable_if<std::is_enum<T>::value>::type* = nullptr> template <typename T, typename std::enable_if<std::is_enum<T>::value>::type* = nullptr>
void ReadDoubleValue(const QJsonObject &itemObject, const QString &attribute, T &value, void ReadDoubleValue(const QJsonObject &itemObject, const QString &attribute, T &value,
const QString &defaultValue = QString()); const QString &defaultValue = QString()) const;
template <typename T, typename std::enable_if<std::is_integral<T>::value>::type* = nullptr> template <typename T, typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
void ReadDoubleValue(const QJsonObject &itemObject, const QString &attribute, T &value, 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, 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, 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 ReadPointValue(const QJsonObject &itemObject, const QString &attribute, VPointF &value);
void ReadSplinePointValues(const QJsonObject &itemObject, const QString &attribute, QVector<VSplinePoint> &points); void ReadSplinePointValues(const QJsonObject &itemObject, const QString &attribute, QVector<VSplinePoint> &points);
void ReadSplinePointValue(const QJsonObject &itemObject, VSplinePoint &point); void ReadSplinePointValue(const QJsonObject &itemObject, VSplinePoint &point);
void ReadPieceNodeValue(const QJsonObject &itemObject, VPieceNode &node); 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 VPointFromJson(const QJsonObject &itemObject, VPointF &point);
void QLineFromJson(const QJsonObject &itemObject, QLineF &line); 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<VContainer> &data); void SplineFromJson(const QJsonObject &itemObject, QSharedPointer<VContainer> &data);
void SplinePathFromJson(const QJsonObject &itemObject, QSharedPointer<VContainer> &data); void SplinePathFromJson(const QJsonObject &itemObject, QSharedPointer<VContainer> &data);

View File

@ -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
}
]
}

View File

@ -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
}
]
}

View File

@ -133,5 +133,7 @@
<file>Issue_548_case2/output.json</file> <file>Issue_548_case2/output.json</file>
<file>Issue_548_case3/input.json</file> <file>Issue_548_case3/input.json</file>
<file>Issue_548_case3/output.json</file> <file>Issue_548_case3/output.json</file>
<file>smart_pattern_#112/input.json</file>
<file>smart_pattern_#112/output.json</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@ -28,6 +28,7 @@
#include "tst_vabstractpiece.h" #include "tst_vabstractpiece.h"
#include "../vlayout/vabstractpiece.h" #include "../vlayout/vabstractpiece.h"
#include "../vlayout/vrawsapoint.h"
#include <QPointF> #include <QPointF>
#include <QVector> #include <QVector>
@ -371,6 +372,39 @@ void TST_VAbstractPiece::SumTrapezoids() const
Case5(); Case5();
} }
//---------------------------------------------------------------------------------------------------------------------
void TST_VAbstractPiece::RawPathRemoveLoop_data() const
{
QTest::addColumn<QVector<VRawSAPoint>>("path");
QTest::addColumn<QVector<QPointF>>("expect");
auto ASSERT_TEST_CASE = [this](const char *title, const QString &input, const QString &output)
{
QVector<VRawSAPoint> inputPoints;
AbstractTest::VectorFromJson(input, inputPoints);
QVector<QPointF> 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<VRawSAPoint>, path);
QFETCH(QVector<QPointF>, expect);
QVector<QPointF> res = VAbstractPiece::CheckLoops(path);
Comparison(res, expect);
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void TST_VAbstractPiece::PathRemoveLoop_data() const void TST_VAbstractPiece::PathRemoveLoop_data() const
{ {
@ -417,11 +451,6 @@ void TST_VAbstractPiece::PathRemoveLoop_data() const
res << QPointF(20, 10); res << QPointF(20, 10);
QTest::newRow("One loop, closed a path (four unique points)") << path << res; 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.clear();
path << QPointF(20, 10); path << QPointF(20, 10);
path << QPointF(20, 20); path << QPointF(20, 20);
@ -438,11 +467,6 @@ void TST_VAbstractPiece::PathRemoveLoop_data() const
res << QPointF(20, 10); res << QPointF(20, 10);
QTest::newRow("Two loops, closed a path (six unique points)") << path << res; 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.clear();
path << QPointF(20, 10); path << QPointF(20, 10);
path << QPointF(20, 20); path << QPointF(20, 20);
@ -459,10 +483,6 @@ void TST_VAbstractPiece::PathRemoveLoop_data() const
res << QPointF(20, 10); res << QPointF(20, 10);
QTest::newRow("One loop, the first loop, closed a path (six unique points)") << path << res; 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.clear();
path << QPointF(20, 10); path << QPointF(20, 10);
path << QPointF(20, 20); path << QPointF(20, 20);

View File

@ -45,6 +45,8 @@ private slots:
void LayoutAllowanceRemoveLoop_data(); void LayoutAllowanceRemoveLoop_data();
void LayoutAllowanceRemoveLoop() const; void LayoutAllowanceRemoveLoop() const;
void SumTrapezoids() const; void SumTrapezoids() const;
void RawPathRemoveLoop_data() const;
void RawPathRemoveLoop() const;
void PathRemoveLoop_data() const; void PathRemoveLoop_data() const;
void PathRemoveLoop() const; void PathRemoveLoop() const;
void PathLoopsCase_data() const; void PathLoopsCase_data() const;