Changed Point-In-Polygon Algorithm. Additional field for saving mirror state.
--HG-- branch : feature
This commit is contained in:
parent
c044b334d7
commit
c191059ddd
|
@ -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
|
||||
|
|
|
@ -104,13 +104,13 @@ QVector<QPointF> 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<QPointF> VLayoutDetail::Map(const QVector<QPointF> &points) const
|
|||
p.append(d->matrix.map(points.at(i)));
|
||||
}
|
||||
|
||||
if (d->matrix.m22() < 0)
|
||||
if (d->mirror)
|
||||
{
|
||||
QList<QPointF> list = p.toList();
|
||||
for(int k=0, s=list.size(), max=(s/2); k<max; k++)
|
||||
|
@ -405,3 +407,15 @@ QGraphicsItem *VLayoutDetail::GetItem() const
|
|||
item->setPath(ContourPath());
|
||||
return item;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
bool VLayoutDetail::IsMirror() const
|
||||
{
|
||||
return d->mirror;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VLayoutDetail::SetMirror(bool value)
|
||||
{
|
||||
d->mirror = value;
|
||||
}
|
||||
|
|
|
@ -54,12 +54,15 @@ public:
|
|||
QVector<QPointF> 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);
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#include <QSharedData>
|
||||
#include <QPointF>
|
||||
#include <QVector>
|
||||
#include <QMatrix>
|
||||
#include <QTransform>
|
||||
|
||||
#ifdef Q_CC_GNU
|
||||
#pragma GCC diagnostic push
|
||||
|
@ -44,12 +44,12 @@ class VLayoutDetailData : public QSharedData
|
|||
public:
|
||||
VLayoutDetailData()
|
||||
:contour(QVector<QPointF>()), seamAllowence(QVector<QPointF>()), layoutAllowence(QVector<QPointF>()),
|
||||
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<QPointF> 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
|
||||
|
|
|
@ -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<qint64>(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<qint64>(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<qint64>(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<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())
|
||||
{
|
||||
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; 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;
|
||||
}
|
||||
|
@ -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<QPointF> 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));
|
||||
|
|
|
@ -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<QPointF> UniteWithContour(const VLayoutDetail &detail, int globalI, int detJ) const;
|
||||
|
|
Loading…
Reference in New Issue
Block a user