From c191059ddd46dd4ff2a1e5864d0a27ddd1b713f8 Mon Sep 17 00:00:00 2001 From: dismine Date: Sun, 18 Jan 2015 20:56:01 +0200 Subject: [PATCH] Changed Point-In-Polygon Algorithm. Additional field for saving mirror state. --HG-- branch : feature --- src/libs/vlayout/vlayoutdef.h | 6 +- src/libs/vlayout/vlayoutdetail.cpp | 26 ++++++-- src/libs/vlayout/vlayoutdetail.h | 7 +- src/libs/vlayout/vlayoutdetail_p.h | 10 +-- src/libs/vlayout/vlayoutpaper.cpp | 102 +++++++++++++++++++++++------ src/libs/vlayout/vlayoutpaper.h | 6 +- 6 files changed, 122 insertions(+), 35 deletions(-) diff --git a/src/libs/vlayout/vlayoutdef.h b/src/libs/vlayout/vlayoutdef.h index 3ceb260f8..ef42dd6e9 100644 --- a/src/libs/vlayout/vlayoutdef.h +++ b/src/libs/vlayout/vlayoutdef.h @@ -40,13 +40,17 @@ enum class LayoutErrors : char EmptyPaperError }; -//#define LAYOUT_DEBUG // Enable debug mode +#define LAYOUT_DEBUG // Enable debug mode #ifdef LAYOUT_DEBUG # define SHOW_VERTICES // Show contour vertices # define SHOW_DIRECTION // Show contour direction # define ARRANGED_DETAILS // Show already arranged details +//# define SHOW_CANDIDATE //# define SHOW_ROTATION +//# define SHOW_COMBINE +//# define SHOW_MIRROR +# define SHOW_BEST #endif//LAYOUT_DEBUG #endif // VLAYOUTDEF_H diff --git a/src/libs/vlayout/vlayoutdetail.cpp b/src/libs/vlayout/vlayoutdetail.cpp index cc71a6ed2..a4cdc5cce 100644 --- a/src/libs/vlayout/vlayoutdetail.cpp +++ b/src/libs/vlayout/vlayoutdetail.cpp @@ -104,13 +104,13 @@ QVector VLayoutDetail::GetLayoutAllowencePoints() const } //--------------------------------------------------------------------------------------------------------------------- -QMatrix VLayoutDetail::GetMatrix() const +QTransform VLayoutDetail::GetMatrix() const { return d->matrix; } //--------------------------------------------------------------------------------------------------------------------- -void VLayoutDetail::SetMatrix(const QMatrix &matrix) +void VLayoutDetail::SetMatrix(const QTransform &matrix) { d->matrix = matrix; } @@ -130,7 +130,7 @@ void VLayoutDetail::SetLayoutWidth(const qreal &value) //--------------------------------------------------------------------------------------------------------------------- void VLayoutDetail::Translate(qreal dx, qreal dy) { - QMatrix m; + QTransform m; m.translate(dx, dy); d->matrix *= m; } @@ -138,7 +138,7 @@ void VLayoutDetail::Translate(qreal dx, qreal dy) //--------------------------------------------------------------------------------------------------------------------- void VLayoutDetail::Rotate(const QPointF &originPoint, qreal degrees) { - QMatrix m; + QTransform m; m.translate(originPoint.x(), originPoint.y()); m.rotate(-degrees); m.translate(-originPoint.x(), -originPoint.y()); @@ -156,7 +156,7 @@ void VLayoutDetail::Mirror(const QLineF &edge) const QLineF axis = QLineF(edge.x2(), edge.y2(), edge.x2() + 100, edge.y2()); // Ox axis const qreal angle = edge.angleTo(axis); - QMatrix m; + QTransform m; m.translate(edge.p2().x(), edge.p2().y()); m.rotate(-angle); m.translate(-edge.p2().x(), -edge.p2().y()); @@ -173,6 +173,8 @@ void VLayoutDetail::Mirror(const QLineF &edge) m.rotate(-(360-angle)); m.translate(-edge.p2().x(), -edge.p2().y()); d->matrix *= m; + + d->mirror = !d->mirror; } //--------------------------------------------------------------------------------------------------------------------- @@ -337,7 +339,7 @@ QVector VLayoutDetail::Map(const QVector &points) const p.append(d->matrix.map(points.at(i))); } - if (d->matrix.m22() < 0) + if (d->mirror) { QList list = p.toList(); for(int k=0, s=list.size(), max=(s/2); ksetPath(ContourPath()); return item; } + +//--------------------------------------------------------------------------------------------------------------------- +bool VLayoutDetail::IsMirror() const +{ + return d->mirror; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VLayoutDetail::SetMirror(bool value) +{ + d->mirror = value; +} diff --git a/src/libs/vlayout/vlayoutdetail.h b/src/libs/vlayout/vlayoutdetail.h index e926016ed..2ca4ac76f 100644 --- a/src/libs/vlayout/vlayoutdetail.h +++ b/src/libs/vlayout/vlayoutdetail.h @@ -54,12 +54,15 @@ public: QVector GetLayoutAllowencePoints() const; void SetLayoutAllowencePoints(); - QMatrix GetMatrix() const; - void SetMatrix(const QMatrix &matrix); + QTransform GetMatrix() const; + void SetMatrix(const QTransform &matrix); qreal GetLayoutWidth() const; void SetLayoutWidth(const qreal &value); + bool IsMirror() const; + void SetMirror(bool value); + void Translate(qreal dx, qreal dy); void Rotate(const QPointF &originPoint, qreal degrees); void Mirror(const QLineF &edge); diff --git a/src/libs/vlayout/vlayoutdetail_p.h b/src/libs/vlayout/vlayoutdetail_p.h index a15dd1e5e..296f1c780 100644 --- a/src/libs/vlayout/vlayoutdetail_p.h +++ b/src/libs/vlayout/vlayoutdetail_p.h @@ -32,7 +32,7 @@ #include #include #include -#include +#include #ifdef Q_CC_GNU #pragma GCC diagnostic push @@ -44,12 +44,12 @@ class VLayoutDetailData : public QSharedData public: VLayoutDetailData() :contour(QVector()), seamAllowence(QVector()), layoutAllowence(QVector()), - matrix(QMatrix()), layoutWidth(0) + matrix(QMatrix()), layoutWidth(0), mirror(false) {} VLayoutDetailData(const VLayoutDetailData &detail) :QSharedData(detail), contour(detail.contour), seamAllowence(detail.seamAllowence), - layoutAllowence(detail.layoutAllowence), matrix(detail.matrix), layoutWidth(detail.layoutWidth) + layoutAllowence(detail.layoutAllowence), matrix(detail.matrix), layoutWidth(detail.layoutWidth), mirror(false) {} ~VLayoutDetailData() {} @@ -64,10 +64,12 @@ public: QVector layoutAllowence; /** @brief matrix transformation matrix*/ - QMatrix matrix; + QTransform matrix; /** @brief layoutWidth value layout allowence width in pixels. */ qreal layoutWidth; + + bool mirror; }; #ifdef Q_CC_GNU diff --git a/src/libs/vlayout/vlayoutpaper.cpp b/src/libs/vlayout/vlayoutpaper.cpp index 8e8c255a0..30f8edab2 100644 --- a/src/libs/vlayout/vlayoutpaper.cpp +++ b/src/libs/vlayout/vlayoutpaper.cpp @@ -43,31 +43,33 @@ class BestResult public: BestResult(); - void NewResult(qint64 square, int i, int j, const QMatrix &matrix); + void NewResult(qint64 square, int i, int j, const QTransform &matrix, bool mirror); qint64 BestSquare() const; int GContourEdge() const; int DetailEdge() const; - QMatrix Matrix() const; + QTransform Matrix() const; bool ValideResult() const; + bool Mirror() const; private: // All nedded information about best result int resI; // Edge of global contour int resJ; // Edge of detail - QMatrix resMatrix; // Matrix for rotation and translation detail + QTransform resMatrix; // Matrix for rotation and translation detail qint64 resSquare; // Best square size (least). For begin set max value. bool valideResult; + bool resMirror; }; //===================================================BestResult======================================================== //--------------------------------------------------------------------------------------------------------------------- BestResult::BestResult() - :resI(0), resJ(0), resMatrix(QMatrix()), resSquare(LLONG_MAX),valideResult(false) + :resI(0), resJ(0), resMatrix(QMatrix()), resSquare(LLONG_MAX), valideResult(false), resMirror(false) {} //--------------------------------------------------------------------------------------------------------------------- -void BestResult::NewResult(qint64 square, int i, int j, const QMatrix &matrix) +void BestResult::NewResult(qint64 square, int i, int j, const QTransform &matrix, bool mirror) { if (square <= resSquare && square > 0) { @@ -76,6 +78,7 @@ void BestResult::NewResult(qint64 square, int i, int j, const QMatrix &matrix) resMatrix = matrix; resSquare = square; valideResult = true; + resMirror = mirror; } } @@ -98,7 +101,7 @@ int BestResult::DetailEdge() const } //--------------------------------------------------------------------------------------------------------------------- -QMatrix BestResult::Matrix() const +QTransform BestResult::Matrix() const { return resMatrix; } @@ -109,6 +112,12 @@ bool BestResult::ValideResult() const return valideResult; } +//--------------------------------------------------------------------------------------------------------------------- +bool BestResult::Mirror() const +{ + return resMirror; +} + //===================================================VLayoutPaper====================================================== //--------------------------------------------------------------------------------------------------------------------- VLayoutPaper::VLayoutPaper() @@ -255,12 +264,12 @@ bool VLayoutPaper::AddToBlankSheet(const VLayoutDetail &detail, bool &stop) if (SheetContains(rec)) { bestResult.NewResult(static_cast(rec.width()*rec.height()), j, dEdge, - workDetail.GetMatrix()); + workDetail.GetMatrix(), workDetail.IsMirror()); } } d->frame = d->frame + 2; - for (int angle = 0; angle <= 360; angle = angle+5) + for (int angle = 0; angle <= 360; angle = angle+20) { QCoreApplication::processEvents(); @@ -278,7 +287,7 @@ bool VLayoutPaper::AddToBlankSheet(const VLayoutDetail &detail, bool &stop) if (SheetContains(rec)) { bestResult.NewResult(static_cast(rec.width()*rec.height()), j, i, - workDetail.GetMatrix()); + workDetail.GetMatrix(), workDetail.IsMirror()); } } ++d->frame; @@ -317,7 +326,7 @@ bool VLayoutPaper::AddToSheet(const VLayoutDetail &detail, bool &stop) newGContour.append(newGContour.first()); const QRectF rec = QPolygonF(newGContour).boundingRect(); bestResult.NewResult(static_cast(rec.width()*rec.height()), j, dEdge, - workDetail.GetMatrix()); + workDetail.GetMatrix(), workDetail.IsMirror()); } } d->frame = d->frame + 2; @@ -337,7 +346,9 @@ bool VLayoutPaper::CheckCombineEdges(VLayoutDetail &detail, int j, int &dEdge) c CombineEdges(detail, globalEdge, dEdge); #ifdef LAYOUT_DEBUG - DrawDebug(detail, d->frame); +# ifdef SHOW_COMBINE + DrawDebug(detail, d->frame); +# endif #endif switch (Crossing(detail, j, dEdge)) @@ -372,7 +383,9 @@ bool VLayoutPaper::CheckCombineEdges(VLayoutDetail &detail, int j, int &dEdge) c if (flagMirror) { #ifdef LAYOUT_DEBUG - DrawDebug(detail, d->frame+1); + #ifdef SHOW_MIRROR + DrawDebug(detail, d->frame+1); + #endif #endif dEdge = detail.EdgeByPoint(globalEdge.p2()); @@ -455,7 +468,8 @@ bool VLayoutPaper::CheckRotationEdges(VLayoutDetail &detail, int j, int dEdge, i } //--------------------------------------------------------------------------------------------------------------------- -VLayoutPaper::CrossingType VLayoutPaper::Crossing(const VLayoutDetail &detail, int globalI, int detailI) const +VLayoutPaper::CrossingType VLayoutPaper::Crossing(const VLayoutDetail &detail, const int &globalI, + const int &detailI) const { int globalEdgesCount = EdgesCount(); if (globalEdgesCount == 0) @@ -507,7 +521,7 @@ VLayoutPaper::CrossingType VLayoutPaper::Crossing(const VLayoutDetail &detail, i } //--------------------------------------------------------------------------------------------------------------------- -VLayoutPaper::InsideType VLayoutPaper::InsideContour(const VLayoutDetail &detail, int detailI) const +VLayoutPaper::InsideType VLayoutPaper::InsideContour(const VLayoutDetail &detail, const int &detailI) const { if (detail.EdgesCount() < 3) { @@ -535,10 +549,35 @@ VLayoutPaper::InsideType VLayoutPaper::InsideContour(const VLayoutDetail &detail } else { - const QPolygonF gPoly = GlobalPolygon(); - for(int i = 0; i < lPoints.count(); i++) + const int polyCorners = EdgesCount(); + int j = polyCorners-1; + + QVector constant; + QVector multiple; + + for(int i=0; iglobalContour.at(i).x(); + const qreal xj = d->globalContour.at(j).x(); + const qreal yi = d->globalContour.at(i).y(); + const qreal yj = d->globalContour.at(j).y(); + if(qFuzzyCompare(yj, yi)) + { + constant.insert(i, xi); + multiple.insert(i, 0); + } + else + { + constant.insert(i, xi - (yi*xj)/(yj-yi) + (yi*xi)/(yj-yi)); + multiple.insert(i, (xj-xi)/(yj-yi)); + } + + j=i; + } + + for(int k = 0; k < lPoints.count(); k++) + { + const QPointF p = lPoints.at(k); if (p.isNull()) { return InsideType::EdgeError; @@ -546,7 +585,23 @@ VLayoutPaper::InsideType VLayoutPaper::InsideContour(const VLayoutDetail &detail if (p != detailEdge.p1() && p != detailEdge.p2()) { - if (gPoly.containsPoint(p, Qt::OddEvenFill)) + int j = polyCorners-1; + bool oddNodes = false; + + for (int i=0; iglobalContour.at(i).y(); + const qreal yj = d->globalContour.at(j).y(); + + if (((yi < p.y() && yj >= p.y()) || (yj < p.y() && yi >= p.y()))) + { + oddNodes ^= (p.y() * multiple.at(i) + constant.at(i) < p.x()); + } + + j=i; + } + + if (oddNodes) { return InsideType::Inside; } @@ -570,7 +625,7 @@ bool VLayoutPaper::SheetContains(const QRectF &rect) const } //--------------------------------------------------------------------------------------------------------------------- -void VLayoutPaper::CombineEdges(VLayoutDetail &detail, const QLineF &globalEdge, int dEdge) const +void VLayoutPaper::CombineEdges(VLayoutDetail &detail, const QLineF &globalEdge, const int &dEdge) const { QLineF detailEdge = detail.Edge(dEdge); @@ -813,6 +868,7 @@ bool VLayoutPaper::SaveResult(const BestResult &bestResult, const VLayoutDetail { VLayoutDetail workDetail = detail; workDetail.SetMatrix(bestResult.Matrix());// Don't forget set matrix + workDetail.SetMirror(bestResult.Mirror()); const QVector newGContour = UniteWithContour(workDetail, bestResult.GContourEdge(), bestResult.DetailEdge()); if (newGContour.isEmpty()) @@ -821,6 +877,12 @@ bool VLayoutPaper::SaveResult(const BestResult &bestResult, const VLayoutDetail } d->details.append(workDetail); d->globalContour = newGContour; + +#ifdef LAYOUT_DEBUG +# ifdef SHOW_BEST + DrawDebug(workDetail, UINT_MAX); +# endif +#endif } return bestResult.ValideResult(); // Do we have the best result? @@ -852,10 +914,12 @@ void VLayoutPaper::DrawDebug(const VLayoutDetail &detail, int frame) const paint.drawPath(p); } +#ifdef SHOW_CANDIDATE paint.setPen(QPen(Qt::darkGreen, 3, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin)); p = DrawContour(detail.GetLayoutAllowencePoints()); p.translate(d->paperWidth/2, d->paperHeight/2); paint.drawPath(p); +#endif #ifdef ARRANGED_DETAILS paint.setPen(QPen(Qt::blue, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin)); diff --git a/src/libs/vlayout/vlayoutpaper.h b/src/libs/vlayout/vlayoutpaper.h index bc950e5a4..ce74ccf0e 100644 --- a/src/libs/vlayout/vlayoutpaper.h +++ b/src/libs/vlayout/vlayoutpaper.h @@ -90,12 +90,12 @@ private: bool CheckCombineEdges(VLayoutDetail &detail, int j, int &dEdge) const; bool CheckRotationEdges(VLayoutDetail &detail, int j, int dEdge, int angle) const; - CrossingType Crossing(const VLayoutDetail &detail, int globalI, int detailI) const; - InsideType InsideContour(const VLayoutDetail &detail, int detailI) 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; bool SheetContains(const QRectF &rect) const; - void CombineEdges(VLayoutDetail &detail, const QLineF &globalEdge, int dEdge) const; + void CombineEdges(VLayoutDetail &detail, const QLineF &globalEdge, const int &dEdge) const; void RotateEdges(VLayoutDetail &detail, const QLineF &globalEdge, int dEdge, int angle) const; QVector UniteWithContour(const VLayoutDetail &detail, int globalI, int detJ) const;