diff --git a/src/libs/vlayout/vabstractdetail.cpp b/src/libs/vlayout/vabstractdetail.cpp index dc13d85ee..098882f18 100644 --- a/src/libs/vlayout/vabstractdetail.cpp +++ b/src/libs/vlayout/vabstractdetail.cpp @@ -300,57 +300,59 @@ QVector VAbstractDetail::CorrectEquidistantPoints(const QVector VAbstractDetail::CheckLoops(const QVector &points) { - QVector ekvPoints; + const int count = points.size(); /*If we got less than 4 points no need seek loops.*/ - if (points.size() < 4) + if (count < 4) { qDebug()<<"Less then 4 points. Doesn't need check for loops."; return points; } + bool closed = false; - if (points.at(0) == points.at(points.size()-1)) + if (points.first() == points.last()) { closed = true; } + + QVector ekvPoints; + qint32 i, j; - for (i = 0; i < points.size(); ++i) + for (i = 0; i < count; ++i) { /*Last three points no need check.*/ - if (i >= points.size()-3) + /*Triangle has not contain loops*/ + if (i >= count-3) { ekvPoints.append(points.at(i)); continue; } + QPointF crosPoint; QLineF::IntersectType intersect = QLineF::NoIntersection; - QLineF line1(points.at(i), points.at(i+1)); - for (j = i+2; j < points.size()-1; ++j) + 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-2; j >= i+2; --j) { - QLineF line2(points.at(j), points.at(j+1)); + const QLineF line2(points.at(j), points.at(j+1)); intersect = line1.intersect(line2, &crosPoint); - if (intersect == QLineF::BoundedIntersection) - { + if (intersect == QLineF::BoundedIntersection && not (i == 0 && j+1 == count-1 && closed)) + { // Break, but not if intersects the first edge and the last edge in closed path break; } + intersect = QLineF::NoIntersection; } + if (intersect == QLineF::BoundedIntersection) { - if (i == 0 && j+1 == points.size()-1 && closed) - { - /*We got closed contour.*/ - ekvPoints.append(points.at(i)); - } - else - { - /*We found loop.*/ - ekvPoints.append(points.at(i)); - ekvPoints.append(crosPoint); - i = j; - } + /*We have found loop.*/ + ekvPoints.append(points.at(i)); + ekvPoints.append(crosPoint); + i = j; } else { - /*We did not found loop.*/ + /*We have not found loop.*/ ekvPoints.append(points.at(i)); } } diff --git a/src/libs/vlayout/vabstractdetail.h b/src/libs/vlayout/vabstractdetail.h index 0f8d00180..9ec07e7fb 100644 --- a/src/libs/vlayout/vabstractdetail.h +++ b/src/libs/vlayout/vabstractdetail.h @@ -65,13 +65,12 @@ public: void setWidth(const qreal &value); static QVector Equidistant(const QVector &points, const EquidistantType &eqv, qreal width); - static qreal SumTrapezoids(const QVector &points); - + static qreal SumTrapezoids(const QVector &points); + static QVector CheckLoops(const QVector &points); protected: static QVector RemoveDublicates(const QVector &points); static QVector CorrectEquidistantPoints(const QVector &points); - static QVector CheckLoops(const QVector &points); private: QSharedDataPointer d; diff --git a/src/test/ValentinaTest/tst_vabstractdetail.cpp b/src/test/ValentinaTest/tst_vabstractdetail.cpp index b2103cb61..dbb2316c0 100644 --- a/src/test/ValentinaTest/tst_vabstractdetail.cpp +++ b/src/test/ValentinaTest/tst_vabstractdetail.cpp @@ -64,7 +64,127 @@ void TST_VAbstractDetail::SumTrapezoids() const } //--------------------------------------------------------------------------------------------------------------------- +void TST_VAbstractDetail::PathRemoveLoop_data() const +{ + QTest::addColumn>("path"); + QTest::addColumn>("expect"); + QVector path; + path << QPointF(10, 10); + path << QPointF(20, 10); + path << QPointF(20, 20); + path << QPointF(10, 20); + path << QPointF(10, 10); + QTest::newRow("Correct closed a path (four unique points)") << path << path; + + path.removeLast(); + QTest::newRow("Correct unclosed a path (four unique points)") << path << path; + + path.clear(); + path << QPointF(0, 10); + path << QPointF(10, 10); + path << QPointF(20, 10); + path << QPointF(20, 20); + path << QPointF(10, 20); + path << QPointF(0, 20); + path << QPointF(0, 10); + QTest::newRow("Correct closed a path (six unique points)") << path << path; + + path.removeLast(); + QTest::newRow("Correct unclosed a path (six unique points)") << path << path; + + path.clear(); + path << QPointF(20, 10); + path << QPointF(10, 20); + path << QPointF(10, 10); + path << QPointF(20, 20); + path << QPointF(20, 10); + + QVector res; + res << QPointF(20, 10); + res << QPointF(15, 15); + res << QPointF(20, 20); + 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(10, 20); + path << QPointF(0, 10); + path << QPointF(0, 20); + path << QPointF(10, 10); + path << QPointF(20, 20); + path << QPointF(20, 10); + + res.clear(); + res << QPointF(20, 10); + res << QPointF(15, 15); + res << QPointF(20, 20); + 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(10, 20); + path << QPointF(0, 20); + path << QPointF(0, 10); + path << QPointF(10, 10); + path << QPointF(20, 20); + path << QPointF(20, 10); + + res.clear(); + res << QPointF(20, 10); + res << QPointF(15, 15); + res << QPointF(20, 20); + 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(10, 10); + path << QPointF(0, 20); + path << QPointF(0, 10); + path << QPointF(10, 20); + path << QPointF(20, 20); + path << QPointF(20, 10); + + res.clear(); + res << QPointF(20, 10); + res << QPointF(10, 10); + res << QPointF(5, 15); + res << QPointF(10, 20); + res << QPointF(20, 20); + res << QPointF(20, 10); + QTest::newRow("One loop, the second loop, closed a path (six unique points)") << path << res; + + path.removeLast(); + res.removeLast(); + QTest::newRow("One loop, the second loop, unclosed a path (six unique points)") << path << res; +} + +//--------------------------------------------------------------------------------------------------------------------- +void TST_VAbstractDetail::PathRemoveLoop() const +{ + QFETCH(QVector, path); + QFETCH(QVector, expect); + + QVector res = VAbstractDetail::CheckLoops(path); + Comparison(res, expect); +} + +//--------------------------------------------------------------------------------------------------------------------- void TST_VAbstractDetail::Case1() const { const QVector points = InputPointsCase1(); // Input points. diff --git a/src/test/ValentinaTest/tst_vabstractdetail.h b/src/test/ValentinaTest/tst_vabstractdetail.h index 83790c743..fc8759e92 100644 --- a/src/test/ValentinaTest/tst_vabstractdetail.h +++ b/src/test/ValentinaTest/tst_vabstractdetail.h @@ -42,6 +42,8 @@ signals: private slots: void EquidistantRemoveLoop() const; void SumTrapezoids() const; + void PathRemoveLoop_data() const; + void PathRemoveLoop() const; private: void Case1() const;