From 2e83967cafefdfea59cc9786ce9d14358d57cbb3 Mon Sep 17 00:00:00 2001 From: Roman Telezhynskyi Date: Mon, 28 Mar 2016 11:53:02 +0300 Subject: [PATCH] The layout generator optimization. Let QPainterPath check intersections. --HG-- branch : develop --- src/libs/vlayout/vcontour.cpp | 18 +++ src/libs/vlayout/vcontour.h | 3 + src/libs/vlayout/vlayoutdetail.cpp | 17 ++ src/libs/vlayout/vlayoutdetail.h | 1 + src/libs/vlayout/vposition.cpp | 249 ++--------------------------- src/libs/vlayout/vposition.h | 8 +- 6 files changed, 50 insertions(+), 246 deletions(-) diff --git a/src/libs/vlayout/vcontour.cpp b/src/libs/vlayout/vcontour.cpp index 0d4adffa1..b6af52726 100644 --- a/src/libs/vlayout/vcontour.cpp +++ b/src/libs/vlayout/vcontour.cpp @@ -32,6 +32,7 @@ #include #include +#include #if QT_VERSION < QT_VERSION_CHECK(5, 1, 0) # include "../vmisc/vmath.h" @@ -310,6 +311,23 @@ QRectF VContour::BoundingRect() const return QPolygonF(points).boundingRect(); } +//--------------------------------------------------------------------------------------------------------------------- +QPainterPath VContour::ContourPath() const +{ + QPainterPath path; + path.setFillRule(Qt::WindingFill); + + const QVector points = GetContour(); + path.moveTo(points.at(0)); + for (qint32 i = 1; i < points.count(); ++i) + { + path.lineTo(points.at(i)); + } + path.lineTo(points.at(0)); + + return path; +} + //--------------------------------------------------------------------------------------------------------------------- void VContour::AppendWhole(QVector &contour, const VLayoutDetail &detail, int detJ) const { diff --git a/src/libs/vlayout/vcontour.h b/src/libs/vlayout/vcontour.h index c8d1330e4..5bd5e8d0f 100644 --- a/src/libs/vlayout/vcontour.h +++ b/src/libs/vlayout/vcontour.h @@ -40,6 +40,7 @@ class QPointF; class VLayoutDetail; class QLineF; class QRectF; +class QPainterPath; class VContour { @@ -76,6 +77,8 @@ public: QRectF BoundingRect() const; + QPainterPath ContourPath() const; + private: QSharedDataPointer d; diff --git a/src/libs/vlayout/vlayoutdetail.cpp b/src/libs/vlayout/vlayoutdetail.cpp index 1f9be80b4..66f377471 100644 --- a/src/libs/vlayout/vlayoutdetail.cpp +++ b/src/libs/vlayout/vlayoutdetail.cpp @@ -406,6 +406,23 @@ QPainterPath VLayoutDetail::ContourPath() const return path; } +//--------------------------------------------------------------------------------------------------------------------- +QPainterPath VLayoutDetail::LayoutAllowencePath() const +{ + QPainterPath path; + path.setFillRule(Qt::WindingFill); + + const QVector points = GetLayoutAllowencePoints(); + path.moveTo(points.at(0)); + for (qint32 i = 1; i < points.count(); ++i) + { + path.lineTo(points.at(i)); + } + path.lineTo(points.at(0)); + + return path; +} + //--------------------------------------------------------------------------------------------------------------------- QGraphicsItem *VLayoutDetail::GetItem() const { diff --git a/src/libs/vlayout/vlayoutdetail.h b/src/libs/vlayout/vlayoutdetail.h index b82bf7bb8..433b1db8c 100644 --- a/src/libs/vlayout/vlayoutdetail.h +++ b/src/libs/vlayout/vlayoutdetail.h @@ -77,6 +77,7 @@ public: bool isNull() const; qint64 Square() const; QPainterPath ContourPath() const; + QPainterPath LayoutAllowencePath() const; QGraphicsItem *GetItem() const Q_REQUIRED_RESULT; private: diff --git a/src/libs/vlayout/vposition.cpp b/src/libs/vlayout/vposition.cpp index cbfa5e828..75f4feb0a 100644 --- a/src/libs/vlayout/vposition.cpp +++ b/src/libs/vlayout/vposition.cpp @@ -268,7 +268,7 @@ bool VPosition::CheckCombineEdges(VLayoutDetail &detail, int j, int &dEdge) { if (not gContour.GetContour().isEmpty()) { - type = Crossing(detail, j, dEdge); + type = Crossing(detail); } else { @@ -285,23 +285,8 @@ bool VPosition::CheckCombineEdges(VLayoutDetail &detail, int j, int &dEdge) flagMirror = true; break; case CrossingType::NoIntersection: - { - switch (InsideContour(detail, dEdge)) - { - case InsideType::EdgeError: - return false; - case InsideType::Inside: - detail.Mirror(globalEdge); - flagMirror = true; - break; - case InsideType::Outside: - flagSquare = true; - break; - default: - break; - } + flagSquare = true; break; - } default: break; } @@ -323,7 +308,7 @@ bool VPosition::CheckCombineEdges(VLayoutDetail &detail, int j, int &dEdge) CrossingType type = CrossingType::Intersection; if (SheetContains(detail.BoundingRect())) { - type = Crossing(detail, j, dEdge); + type = Crossing(detail); } switch (type) @@ -334,22 +319,8 @@ bool VPosition::CheckCombineEdges(VLayoutDetail &detail, int j, int &dEdge) flagSquare = false; break; case CrossingType::NoIntersection: - { - switch (InsideContour(detail, dEdge)) - { - case InsideType::EdgeError: - return false; - case InsideType::Inside: - flagSquare = false; - break; - case InsideType::Outside: - flagSquare = true; - break; - default: - break; - } + flagSquare = true; break; - } default: break; } @@ -374,7 +345,7 @@ bool VPosition::CheckRotationEdges(VLayoutDetail &detail, int j, int dEdge, int CrossingType type = CrossingType::Intersection; if (SheetContains(detail.BoundingRect())) { - type = Crossing(detail, j, dEdge); + type = Crossing(detail); } switch (type) @@ -385,22 +356,8 @@ bool VPosition::CheckRotationEdges(VLayoutDetail &detail, int j, int dEdge, int flagSquare = false; break; case CrossingType::NoIntersection: - { - switch (InsideContour(detail, dEdge)) - { - case InsideType::EdgeError: - return false; - case InsideType::Inside: - flagSquare = false; - break; - case InsideType::Outside: - flagSquare = true; - break; - default: - break; - } + flagSquare = true; break; - } default: break; } @@ -408,7 +365,7 @@ bool VPosition::CheckRotationEdges(VLayoutDetail &detail, int j, int dEdge, int } //--------------------------------------------------------------------------------------------------------------------- -VPosition::CrossingType VPosition::Crossing(const VLayoutDetail &detail, const int &globalI, const int &detailI) const +VPosition::CrossingType VPosition::Crossing(const VLayoutDetail &detail) const { const QRectF dRect = detail.BoundingRect(); const QRectF gRect = gContour.BoundingRect(); @@ -418,158 +375,14 @@ VPosition::CrossingType VPosition::Crossing(const VLayoutDetail &detail, const i return CrossingType::NoIntersection; } - int globalEdgesCount = gContour.GlobalEdgesCount(); - if (globalEdgesCount == 0) + if (gContour.ContourPath().intersects(detail.LayoutAllowencePath())) { - globalEdgesCount = 1;// For blank sheet - } - - const int detailEdgesCount = detail.EdgesCount(); - if (detailEdgesCount < 3) - { - return CrossingType::EdgeError; - } - - const QLineF gEdge = gContour.GlobalEdge(globalI); - const QLineF dEdge = detail.Edge(detailI); - - for (int i = 1; i <= globalEdgesCount; i++) - { - const QLineF globalEdge = gContour.GlobalEdge(i); - if (globalEdge.isNull()) // Got null edge - { - return CrossingType::EdgeError; - } - - for (int j = 1; j <= detailEdgesCount; j++) - { - if (i == globalI && j == detailI) - { - continue; - } - - const QLineF detailEdge = detail.Edge(j); - if (detailEdge.isNull()) // Got null edge - { - return CrossingType::EdgeError; - } - - QPointF xPoint; - if (globalEdge.intersect(detailEdge, &xPoint) == QLineF::BoundedIntersection) - { - if (TrueIntersection(gEdge, dEdge, xPoint)) - { - return CrossingType::Intersection; - } - } - } - } - - return CrossingType::NoIntersection; -} - -//--------------------------------------------------------------------------------------------------------------------- -VPosition::InsideType VPosition::InsideContour(const VLayoutDetail &detail, const int &detailI) const -{ - if (detail.EdgesCount() < 3) - { - return InsideType::EdgeError; - } - - const QVector lPoints = detail.GetLayoutAllowencePoints(); - - const QLineF detailEdge = detail.Edge(detailI); - if (detailEdge.isNull()) // Got null edge - { - return InsideType::EdgeError; - } - - if (gContour.GetContour().isEmpty()) - { - const QLineF globalEdge = gContour.GlobalEdge(1); - for (int i = 0; i < lPoints.count(); i++) - { - if (CheckSide(globalEdge, lPoints.at(i)) < 0) - { - return InsideType::Inside; - } - } + return CrossingType::Intersection; } else { - const int polyCorners = gContour.GlobalEdgesCount(); - int j = polyCorners-1; - - QVector constant; - QVector multiple; - - for (int i=0; i p = Triplet(detailEdge); - for (int n=0; n= pn.y()) || (yj < pn.y() && yi >= pn.y()))) - { - oddNodes ^= (pn.y() * multiple.at(i) + constant.at(i) < pn.x()); - } - - j=i; - } - - if (oddNodes) - { - return InsideType::Inside; - } - } - } + return CrossingType::NoIntersection; } - return InsideType::Outside; -} - -//--------------------------------------------------------------------------------------------------------------------- -qreal VPosition::CheckSide(const QLineF &edge, const QPointF &p) const -{ - return (edge.x2() - edge.x1()) * (p.y() - edge.y1()) - (edge.y2() - edge.y1()) * (p.x() - edge.x1()); } //--------------------------------------------------------------------------------------------------------------------- @@ -712,48 +525,6 @@ void VPosition::Rotate(int increase) } } -//--------------------------------------------------------------------------------------------------------------------- -bool VPosition::TrueIntersection(const QLineF &gEdge, const QLineF &dEdge, const QPointF &p) const -{ - const QPointF pX = RoundedPoint(p); - - QPointF xPoint; - if (gEdge.intersect(dEdge, &xPoint) == QLineF::NoIntersection) - { - const QPointF gP1 = RoundedPoint(gEdge.p1()); - const QPointF gP2 = RoundedPoint(gEdge.p2()); - const QPointF dP1 = RoundedPoint(dEdge.p1()); - const QPointF dP2 = RoundedPoint(dEdge.p2()); - - // If two edges are same line ignorring all intersection point that are equal to the start or the end point - return !(pX == gP1 || pX == gP2 || pX == dP1 || pX == dP2); - } - else - { - // Rotation case. Ignore intersection only in the point of edges intersection. - return pX != RoundedPoint(xPoint); - } -} - -//--------------------------------------------------------------------------------------------------------------------- -QPointF VPosition::RoundedPoint(const QPointF &p) const -{ - return QPointF(qRound(p.x()), qRound(p.y())); -} - -//--------------------------------------------------------------------------------------------------------------------- -QVector VPosition::Triplet(const QLineF &edge) const -{ - QVector p; - QLineF line = edge; - line.setLength(edge.length()/2); - - p.append(edge.p1()); - p.append(line.p2()); - p.append(edge.p2()); - return p; -} - //--------------------------------------------------------------------------------------------------------------------- QPainterPath VPosition::ShowDirection(const QLineF &edge) { diff --git a/src/libs/vlayout/vposition.h b/src/libs/vlayout/vposition.h index b7417e7f1..9d828f9a6 100644 --- a/src/libs/vlayout/vposition.h +++ b/src/libs/vlayout/vposition.h @@ -108,9 +108,7 @@ private: bool CheckCombineEdges(VLayoutDetail &detail, int j, int &dEdge); bool CheckRotationEdges(VLayoutDetail &detail, int j, int dEdge, int angle) const; - CrossingType Crossing(const VLayoutDetail &detail, const int &globalI, const int &detailI) const; - InsideType InsideContour(const VLayoutDetail &detail, const int &detailI) const; - qreal CheckSide(const QLineF &edge, const QPointF &p) const; + CrossingType Crossing(const VLayoutDetail &detail) const; bool SheetContains(const QRectF &rect) const; void CombineEdges(VLayoutDetail &detail, const QLineF &globalEdge, const int &dEdge); @@ -118,10 +116,6 @@ private: QPolygonF GlobalPolygon() const; - bool TrueIntersection(const QLineF &gEdge, const QLineF &dEdge, const QPointF &p) const; - QPointF RoundedPoint(const QPointF &p) const; - QVector Triplet(const QLineF &edge) const; - static QPainterPath ShowDirection(const QLineF &edge); static QPainterPath DrawContour(const QVector &points); static QPainterPath DrawDetails(const QVector &details);