Changed Point-In-Polygon Algorithm. Additional field for saving mirror state.

--HG--
branch : feature
This commit is contained in:
dismine 2015-01-18 20:56:01 +02:00
parent c044b334d7
commit c191059ddd
6 changed files with 122 additions and 35 deletions

View File

@ -40,13 +40,17 @@ enum class LayoutErrors : char
EmptyPaperError EmptyPaperError
}; };
//#define LAYOUT_DEBUG // Enable debug mode #define LAYOUT_DEBUG // Enable debug mode
#ifdef LAYOUT_DEBUG #ifdef LAYOUT_DEBUG
# define SHOW_VERTICES // Show contour vertices # define SHOW_VERTICES // Show contour vertices
# define SHOW_DIRECTION // Show contour direction # define SHOW_DIRECTION // Show contour direction
# define ARRANGED_DETAILS // Show already arranged details # define ARRANGED_DETAILS // Show already arranged details
//# define SHOW_CANDIDATE
//# define SHOW_ROTATION //# define SHOW_ROTATION
//# define SHOW_COMBINE
//# define SHOW_MIRROR
# define SHOW_BEST
#endif//LAYOUT_DEBUG #endif//LAYOUT_DEBUG
#endif // VLAYOUTDEF_H #endif // VLAYOUTDEF_H

View File

@ -104,13 +104,13 @@ QVector<QPointF> VLayoutDetail::GetLayoutAllowencePoints() const
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
QMatrix VLayoutDetail::GetMatrix() const QTransform VLayoutDetail::GetMatrix() const
{ {
return d->matrix; return d->matrix;
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VLayoutDetail::SetMatrix(const QMatrix &matrix) void VLayoutDetail::SetMatrix(const QTransform &matrix)
{ {
d->matrix = matrix; d->matrix = matrix;
} }
@ -130,7 +130,7 @@ void VLayoutDetail::SetLayoutWidth(const qreal &value)
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VLayoutDetail::Translate(qreal dx, qreal dy) void VLayoutDetail::Translate(qreal dx, qreal dy)
{ {
QMatrix m; QTransform m;
m.translate(dx, dy); m.translate(dx, dy);
d->matrix *= m; d->matrix *= m;
} }
@ -138,7 +138,7 @@ void VLayoutDetail::Translate(qreal dx, qreal dy)
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VLayoutDetail::Rotate(const QPointF &originPoint, qreal degrees) void VLayoutDetail::Rotate(const QPointF &originPoint, qreal degrees)
{ {
QMatrix m; QTransform m;
m.translate(originPoint.x(), originPoint.y()); m.translate(originPoint.x(), originPoint.y());
m.rotate(-degrees); m.rotate(-degrees);
m.translate(-originPoint.x(), -originPoint.y()); 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 QLineF axis = QLineF(edge.x2(), edge.y2(), edge.x2() + 100, edge.y2()); // Ox axis
const qreal angle = edge.angleTo(axis); const qreal angle = edge.angleTo(axis);
QMatrix m; QTransform m;
m.translate(edge.p2().x(), edge.p2().y()); m.translate(edge.p2().x(), edge.p2().y());
m.rotate(-angle); m.rotate(-angle);
m.translate(-edge.p2().x(), -edge.p2().y()); m.translate(-edge.p2().x(), -edge.p2().y());
@ -173,6 +173,8 @@ void VLayoutDetail::Mirror(const QLineF &edge)
m.rotate(-(360-angle)); m.rotate(-(360-angle));
m.translate(-edge.p2().x(), -edge.p2().y()); m.translate(-edge.p2().x(), -edge.p2().y());
d->matrix *= m; d->matrix *= m;
d->mirror = !d->mirror;
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -337,7 +339,7 @@ QVector<QPointF> VLayoutDetail::Map(const QVector<QPointF> &points) const
p.append(d->matrix.map(points.at(i))); p.append(d->matrix.map(points.at(i)));
} }
if (d->matrix.m22() < 0) if (d->mirror)
{ {
QList<QPointF> list = p.toList(); QList<QPointF> list = p.toList();
for(int k=0, s=list.size(), max=(s/2); k<max; k++) for(int k=0, s=list.size(), max=(s/2); k<max; k++)
@ -405,3 +407,15 @@ QGraphicsItem *VLayoutDetail::GetItem() const
item->setPath(ContourPath()); item->setPath(ContourPath());
return item; return item;
} }
//---------------------------------------------------------------------------------------------------------------------
bool VLayoutDetail::IsMirror() const
{
return d->mirror;
}
//---------------------------------------------------------------------------------------------------------------------
void VLayoutDetail::SetMirror(bool value)
{
d->mirror = value;
}

View File

@ -54,12 +54,15 @@ public:
QVector<QPointF> GetLayoutAllowencePoints() const; QVector<QPointF> GetLayoutAllowencePoints() const;
void SetLayoutAllowencePoints(); void SetLayoutAllowencePoints();
QMatrix GetMatrix() const; QTransform GetMatrix() const;
void SetMatrix(const QMatrix &matrix); void SetMatrix(const QTransform &matrix);
qreal GetLayoutWidth() const; qreal GetLayoutWidth() const;
void SetLayoutWidth(const qreal &value); void SetLayoutWidth(const qreal &value);
bool IsMirror() const;
void SetMirror(bool value);
void Translate(qreal dx, qreal dy); void Translate(qreal dx, qreal dy);
void Rotate(const QPointF &originPoint, qreal degrees); void Rotate(const QPointF &originPoint, qreal degrees);
void Mirror(const QLineF &edge); void Mirror(const QLineF &edge);

View File

@ -32,7 +32,7 @@
#include <QSharedData> #include <QSharedData>
#include <QPointF> #include <QPointF>
#include <QVector> #include <QVector>
#include <QMatrix> #include <QTransform>
#ifdef Q_CC_GNU #ifdef Q_CC_GNU
#pragma GCC diagnostic push #pragma GCC diagnostic push
@ -44,12 +44,12 @@ class VLayoutDetailData : public QSharedData
public: public:
VLayoutDetailData() VLayoutDetailData()
:contour(QVector<QPointF>()), seamAllowence(QVector<QPointF>()), layoutAllowence(QVector<QPointF>()), :contour(QVector<QPointF>()), seamAllowence(QVector<QPointF>()), layoutAllowence(QVector<QPointF>()),
matrix(QMatrix()), layoutWidth(0) matrix(QMatrix()), layoutWidth(0), mirror(false)
{} {}
VLayoutDetailData(const VLayoutDetailData &detail) VLayoutDetailData(const VLayoutDetailData &detail)
:QSharedData(detail), contour(detail.contour), seamAllowence(detail.seamAllowence), :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() {} ~VLayoutDetailData() {}
@ -64,10 +64,12 @@ public:
QVector<QPointF> layoutAllowence; QVector<QPointF> layoutAllowence;
/** @brief matrix transformation matrix*/ /** @brief matrix transformation matrix*/
QMatrix matrix; QTransform matrix;
/** @brief layoutWidth value layout allowence width in pixels. */ /** @brief layoutWidth value layout allowence width in pixels. */
qreal layoutWidth; qreal layoutWidth;
bool mirror;
}; };
#ifdef Q_CC_GNU #ifdef Q_CC_GNU

View File

@ -43,31 +43,33 @@ class BestResult
public: public:
BestResult(); 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; qint64 BestSquare() const;
int GContourEdge() const; int GContourEdge() const;
int DetailEdge() const; int DetailEdge() const;
QMatrix Matrix() const; QTransform Matrix() const;
bool ValideResult() const; bool ValideResult() const;
bool Mirror() const;
private: private:
// All nedded information about best result // All nedded information about best result
int resI; // Edge of global contour int resI; // Edge of global contour
int resJ; // Edge of detail 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. qint64 resSquare; // Best square size (least). For begin set max value.
bool valideResult; bool valideResult;
bool resMirror;
}; };
//===================================================BestResult======================================================== //===================================================BestResult========================================================
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
BestResult::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) if (square <= resSquare && square > 0)
{ {
@ -76,6 +78,7 @@ void BestResult::NewResult(qint64 square, int i, int j, const QMatrix &matrix)
resMatrix = matrix; resMatrix = matrix;
resSquare = square; resSquare = square;
valideResult = true; valideResult = true;
resMirror = mirror;
} }
} }
@ -98,7 +101,7 @@ int BestResult::DetailEdge() const
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
QMatrix BestResult::Matrix() const QTransform BestResult::Matrix() const
{ {
return resMatrix; return resMatrix;
} }
@ -109,6 +112,12 @@ bool BestResult::ValideResult() const
return valideResult; return valideResult;
} }
//---------------------------------------------------------------------------------------------------------------------
bool BestResult::Mirror() const
{
return resMirror;
}
//===================================================VLayoutPaper====================================================== //===================================================VLayoutPaper======================================================
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
VLayoutPaper::VLayoutPaper() VLayoutPaper::VLayoutPaper()
@ -255,12 +264,12 @@ bool VLayoutPaper::AddToBlankSheet(const VLayoutDetail &detail, bool &stop)
if (SheetContains(rec)) if (SheetContains(rec))
{ {
bestResult.NewResult(static_cast<qint64>(rec.width()*rec.height()), j, dEdge, bestResult.NewResult(static_cast<qint64>(rec.width()*rec.height()), j, dEdge,
workDetail.GetMatrix()); workDetail.GetMatrix(), workDetail.IsMirror());
} }
} }
d->frame = d->frame + 2; 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(); QCoreApplication::processEvents();
@ -278,7 +287,7 @@ bool VLayoutPaper::AddToBlankSheet(const VLayoutDetail &detail, bool &stop)
if (SheetContains(rec)) if (SheetContains(rec))
{ {
bestResult.NewResult(static_cast<qint64>(rec.width()*rec.height()), j, i, bestResult.NewResult(static_cast<qint64>(rec.width()*rec.height()), j, i,
workDetail.GetMatrix()); workDetail.GetMatrix(), workDetail.IsMirror());
} }
} }
++d->frame; ++d->frame;
@ -317,7 +326,7 @@ bool VLayoutPaper::AddToSheet(const VLayoutDetail &detail, bool &stop)
newGContour.append(newGContour.first()); newGContour.append(newGContour.first());
const QRectF rec = QPolygonF(newGContour).boundingRect(); const QRectF rec = QPolygonF(newGContour).boundingRect();
bestResult.NewResult(static_cast<qint64>(rec.width()*rec.height()), j, dEdge, bestResult.NewResult(static_cast<qint64>(rec.width()*rec.height()), j, dEdge,
workDetail.GetMatrix()); workDetail.GetMatrix(), workDetail.IsMirror());
} }
} }
d->frame = d->frame + 2; d->frame = d->frame + 2;
@ -337,7 +346,9 @@ bool VLayoutPaper::CheckCombineEdges(VLayoutDetail &detail, int j, int &dEdge) c
CombineEdges(detail, globalEdge, dEdge); CombineEdges(detail, globalEdge, dEdge);
#ifdef LAYOUT_DEBUG #ifdef LAYOUT_DEBUG
DrawDebug(detail, d->frame); # ifdef SHOW_COMBINE
DrawDebug(detail, d->frame);
# endif
#endif #endif
switch (Crossing(detail, j, dEdge)) switch (Crossing(detail, j, dEdge))
@ -372,7 +383,9 @@ bool VLayoutPaper::CheckCombineEdges(VLayoutDetail &detail, int j, int &dEdge) c
if (flagMirror) if (flagMirror)
{ {
#ifdef LAYOUT_DEBUG #ifdef LAYOUT_DEBUG
DrawDebug(detail, d->frame+1); #ifdef SHOW_MIRROR
DrawDebug(detail, d->frame+1);
#endif
#endif #endif
dEdge = detail.EdgeByPoint(globalEdge.p2()); 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(); int globalEdgesCount = EdgesCount();
if (globalEdgesCount == 0) 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) if (detail.EdgesCount() < 3)
{ {
@ -535,10 +549,35 @@ VLayoutPaper::InsideType VLayoutPaper::InsideContour(const VLayoutDetail &detail
} }
else else
{ {
const QPolygonF gPoly = GlobalPolygon(); const int polyCorners = EdgesCount();
for(int i = 0; i < lPoints.count(); i++) int j = polyCorners-1;
QVector<qreal> constant;
QVector<qreal> multiple;
for(int i=0; i<polyCorners; i++)
{ {
const QPointF p = lPoints.at(i); const qreal xi = d->globalContour.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()) if (p.isNull())
{ {
return InsideType::EdgeError; return InsideType::EdgeError;
@ -546,7 +585,23 @@ VLayoutPaper::InsideType VLayoutPaper::InsideContour(const VLayoutDetail &detail
if (p != detailEdge.p1() && p != detailEdge.p2()) if (p != detailEdge.p1() && p != detailEdge.p2())
{ {
if (gPoly.containsPoint(p, Qt::OddEvenFill)) int j = polyCorners-1;
bool oddNodes = false;
for (int i=0; i<polyCorners; i++)
{
const qreal yi = d->globalContour.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; 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); QLineF detailEdge = detail.Edge(dEdge);
@ -813,6 +868,7 @@ bool VLayoutPaper::SaveResult(const BestResult &bestResult, const VLayoutDetail
{ {
VLayoutDetail workDetail = detail; VLayoutDetail workDetail = detail;
workDetail.SetMatrix(bestResult.Matrix());// Don't forget set matrix workDetail.SetMatrix(bestResult.Matrix());// Don't forget set matrix
workDetail.SetMirror(bestResult.Mirror());
const QVector<QPointF> newGContour = UniteWithContour(workDetail, bestResult.GContourEdge(), const QVector<QPointF> newGContour = UniteWithContour(workDetail, bestResult.GContourEdge(),
bestResult.DetailEdge()); bestResult.DetailEdge());
if (newGContour.isEmpty()) if (newGContour.isEmpty())
@ -821,6 +877,12 @@ bool VLayoutPaper::SaveResult(const BestResult &bestResult, const VLayoutDetail
} }
d->details.append(workDetail); d->details.append(workDetail);
d->globalContour = newGContour; d->globalContour = newGContour;
#ifdef LAYOUT_DEBUG
# ifdef SHOW_BEST
DrawDebug(workDetail, UINT_MAX);
# endif
#endif
} }
return bestResult.ValideResult(); // Do we have the best result? 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); paint.drawPath(p);
} }
#ifdef SHOW_CANDIDATE
paint.setPen(QPen(Qt::darkGreen, 3, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin)); paint.setPen(QPen(Qt::darkGreen, 3, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin));
p = DrawContour(detail.GetLayoutAllowencePoints()); p = DrawContour(detail.GetLayoutAllowencePoints());
p.translate(d->paperWidth/2, d->paperHeight/2); p.translate(d->paperWidth/2, d->paperHeight/2);
paint.drawPath(p); paint.drawPath(p);
#endif
#ifdef ARRANGED_DETAILS #ifdef ARRANGED_DETAILS
paint.setPen(QPen(Qt::blue, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin)); paint.setPen(QPen(Qt::blue, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin));

View File

@ -90,12 +90,12 @@ private:
bool CheckCombineEdges(VLayoutDetail &detail, int j, int &dEdge) const; bool CheckCombineEdges(VLayoutDetail &detail, int j, int &dEdge) const;
bool CheckRotationEdges(VLayoutDetail &detail, int j, int dEdge, int angle) const; bool CheckRotationEdges(VLayoutDetail &detail, int j, int dEdge, int angle) const;
CrossingType Crossing(const VLayoutDetail &detail, int globalI, int detailI) const; CrossingType Crossing(const VLayoutDetail &detail, const int &globalI, const int &detailI) const;
InsideType InsideContour(const VLayoutDetail &detail, int detailI) const; InsideType InsideContour(const VLayoutDetail &detail, const int &detailI) const;
qreal CheckSide(const QLineF &edge, const QPointF &p) const; qreal CheckSide(const QLineF &edge, const QPointF &p) const;
bool SheetContains(const QRectF &rect) 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; void RotateEdges(VLayoutDetail &detail, const QLineF &globalEdge, int dEdge, int angle) const;
QVector<QPointF> UniteWithContour(const VLayoutDetail &detail, int globalI, int detJ) const; QVector<QPointF> UniteWithContour(const VLayoutDetail &detail, int globalI, int detJ) const;