diff --git a/src/libs/vlayout/vabstractpiece.cpp b/src/libs/vlayout/vabstractpiece.cpp index a20985498..061375072 100644 --- a/src/libs/vlayout/vabstractpiece.cpp +++ b/src/libs/vlayout/vabstractpiece.cpp @@ -34,6 +34,7 @@ #include #include #include +#include const qreal maxL = 2.4; @@ -207,7 +208,6 @@ QVector VAbstractPiece::CheckLoops(const QVector &points) /*If we got less than 4 points no need seek loops.*/ if (count < 4) { - qDebug()<<"Less then 4 points. Doesn't need check for loops."; return points; } @@ -235,7 +235,6 @@ QVector VAbstractPiece::CheckLoops(const QVector &points) // 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)); @@ -257,11 +256,7 @@ QVector VAbstractPiece::CheckLoops(const QVector &points) // Method IsPointOnLineviaPDP will check it. if (VGObject::IsPointOnLineviaPDP(points.at(j), points.at(i), points.at(i+1)) // Lines are not neighbors - && uniqueVertices.size() == 4 - && line1.p2() != line2.p2() - && line1.p1() != line2.p1() - && line1.p2() != line2.p1() - && line1.p1() != line2.p2()) + && uniqueVertices.size() == 4) { // Left to catch case where segments are on the same line, but do not have real intersections. QLineF tmpLine1 = line1; @@ -279,21 +274,28 @@ QVector VAbstractPiece::CheckLoops(const QVector &points) if (tmpIntrs1 == QLineF::BoundedIntersection || tmpIntrs2 == QLineF::BoundedIntersection) { // Now we really sure that lines are on the same lines and have real intersections. - status = ParallelIntersection; - break; + QPointF cPoint; + const bool caseFlag = ParallelCrossPoint(line1, line2, cPoint); + if (not caseFlag || CheckIntersection(points, i, i+1, j, jNext, cPoint)) + { + status = ParallelIntersection; + break; + } } } } else if (intersect == QLineF::BoundedIntersection) { - if (uniqueVertices.size() == 4 - && line1.p1() != crosPoint - && line1.p2() != crosPoint - && line2.p1() != crosPoint - && line2.p2() != crosPoint) + if (uniqueVertices.size() == 4) { // Break, but not if lines are neighbors - status = BoundedIntersection; - break; + if ((line1.p1() != crosPoint + && line1.p2() != crosPoint + && line2.p1() != crosPoint + && line2.p2() != crosPoint) || CheckIntersection(points, i, i+1, j, jNext, crosPoint)) + { + status = BoundedIntersection; + break; + } } } status = NoIntersection; @@ -302,34 +304,12 @@ QVector VAbstractPiece::CheckLoops(const QVector &points) switch (status) { case ParallelIntersection: - { /*We have found a loop.*/ - // Very tricky case - // See the file "collection/bugs/Issue_#603.val" - const QLineF line1(points.at(i+1), points.at(j)); - const QLineF line2(points.at(i), points.at(jNext)); - - if (line1.length() <= line2.length()) - { - // In this case we did not check a loop edges and can just skip them - ekvPoints.append(points.at(i)); - ekvPoints.append(points.at(jNext)); - - i = j; // Skip a loo - } - else - { - // In this case a loop edges probably was also chacked and added to the list - ekvPoints.clear();// Previous data is wrong and belong to loop. - ekvPoints.append(points.at(j)); - ekvPoints.append(points.at(i+1)); - - count = j+1;// All beyond this belong to loop. - } + ekvPoints.append(points.at(i)); + ekvPoints.append(points.at(jNext)); + jNext > j ? i = jNext : i = j; // Skip a loop break; - } case BoundedIntersection: - /*We have found a loop.*/ ekvPoints.append(points.at(i)); ekvPoints.append(crosPoint); i = j; @@ -831,3 +811,128 @@ qreal VAbstractPiece::AngleBetweenBisectors(const QLineF &b1, const QLineF &b2) return angle2; } } + +//--------------------------------------------------------------------------------------------------------------------- +bool VAbstractPiece::CheckIntersection(const QVector &points, int i, int iNext, int j, int jNext, + const QPointF &crossPoint) +{ + QVector sub1 = SubPath(points, iNext, j); + sub1.append(crossPoint); + sub1 = CheckLoops(CorrectEquidistantPoints(sub1, false)); + const qreal sub1Sum = SumTrapezoids(sub1); + + QVector sub2 = SubPath(points, jNext, i); + sub2.append(crossPoint); + sub2 = CheckLoops(CorrectEquidistantPoints(sub2, false)); + const qreal sub2Sum = SumTrapezoids(sub2); + + if (sub1Sum < 0 && sub2Sum < 0) + { + if (Crossing(sub1, sub2)) + { + return true; + } + } + else + { + if (not Crossing(sub1, sub2)) + { + return true; + } + } + return false; +} + +//--------------------------------------------------------------------------------------------------------------------- +bool VAbstractPiece::ParallelCrossPoint(const QLineF &line1, const QLineF &line2, QPointF &point) +{ + const bool l1p1el2p1 = (line1.p1() == line2.p1()); + const bool l1p2el2p2 = (line1.p2() == line2.p2()); + const bool l1p1el2p2 = (line1.p1() == line2.p2()); + const bool l1p2el2p1 = (line1.p2() == line2.p1()); + + if (l1p2el2p2 || l1p2el2p1) + { + point = line1.p2(); + return true; + } + else if (l1p1el2p1 || l1p1el2p2) + { + point = line1.p1(); + return true; + } + else + { + point = QPointF(); + return false; + } +} + +//--------------------------------------------------------------------------------------------------------------------- +bool VAbstractPiece::Crossing(const QVector &sub1, const QVector &sub2) +{ + if (sub1.isEmpty() || sub2.isEmpty()) + { + return false; + } + + const QRectF sub1Rect = QPolygonF(sub1).boundingRect(); + const QRectF sub2Rect = QPolygonF(sub2).boundingRect(); + if (not sub1Rect.intersects(sub2Rect)) + { + return false; + } + + QPainterPath sub1Path; + sub1Path.setFillRule(Qt::WindingFill); + sub1Path.moveTo(sub1.at(0)); + for (qint32 i = 1; i < sub1.count(); ++i) + { + sub1Path.lineTo(sub1.at(i)); + } + sub1Path.lineTo(sub1.at(0)); + + QPainterPath sub2Path; + sub2Path.setFillRule(Qt::WindingFill); + sub2Path.moveTo(sub2.at(0)); + for (qint32 i = 1; i < sub2.count(); ++i) + { + sub2Path.lineTo(sub2.at(i)); + } + sub2Path.lineTo(sub2.at(0)); + + if (not sub1Path.intersects(sub2Path)) + { + return false; + } + else + { + return true; + } +} + +//--------------------------------------------------------------------------------------------------------------------- +QVector VAbstractPiece::SubPath(const QVector &path, int startIndex, int endIndex) +{ + if (path.isEmpty() + || startIndex < 0 || startIndex >= path.size() + || endIndex < 0 || endIndex >= path.size() + || startIndex == endIndex) + { + return path; + } + + QVector subPath; + int i = startIndex - 1; + do + { + ++i; + if (i >= path.size()) + { + i = 0; + } + subPath.append(path.at(i)); + } while (i != endIndex); + + return subPath; +} diff --git a/src/libs/vlayout/vabstractpiece.h b/src/libs/vlayout/vabstractpiece.h index 3040ffc5d..fd618fe37 100644 --- a/src/libs/vlayout/vabstractpiece.h +++ b/src/libs/vlayout/vabstractpiece.h @@ -170,6 +170,11 @@ protected: private: QSharedDataPointer d; + static bool CheckIntersection(const QVector &points, int i, int iNext, int j, int jNext, + const QPointF &crossPoint); + static bool ParallelCrossPoint(const QLineF &line1, const QLineF &line2, QPointF &point); + static bool Crossing(const QVector &sub1, const QVector &sub2); + static QVector SubPath(const QVector &path, int startIndex, int endIndex); static Q_DECL_CONSTEXPR qreal PointPosition(const QPointF &p, const QLineF &line); static qreal MaxLocalSA(const VSAPoint &p, qreal width); static QVector EkvPoint(const VSAPoint &p1Line1, const VSAPoint &p2Line1,