The layout generator optimization. Let QPainterPath check intersections.
--HG-- branch : develop
This commit is contained in:
parent
dd586bf01e
commit
2e83967caf
|
@ -32,6 +32,7 @@
|
||||||
|
|
||||||
#include <QPointF>
|
#include <QPointF>
|
||||||
#include <QLineF>
|
#include <QLineF>
|
||||||
|
#include <QPainterPath>
|
||||||
|
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
# include "../vmisc/vmath.h"
|
# include "../vmisc/vmath.h"
|
||||||
|
@ -310,6 +311,23 @@ QRectF VContour::BoundingRect() const
|
||||||
return QPolygonF(points).boundingRect();
|
return QPolygonF(points).boundingRect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
QPainterPath VContour::ContourPath() const
|
||||||
|
{
|
||||||
|
QPainterPath path;
|
||||||
|
path.setFillRule(Qt::WindingFill);
|
||||||
|
|
||||||
|
const QVector<QPointF> 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<QPointF> &contour, const VLayoutDetail &detail, int detJ) const
|
void VContour::AppendWhole(QVector<QPointF> &contour, const VLayoutDetail &detail, int detJ) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -40,6 +40,7 @@ class QPointF;
|
||||||
class VLayoutDetail;
|
class VLayoutDetail;
|
||||||
class QLineF;
|
class QLineF;
|
||||||
class QRectF;
|
class QRectF;
|
||||||
|
class QPainterPath;
|
||||||
|
|
||||||
class VContour
|
class VContour
|
||||||
{
|
{
|
||||||
|
@ -76,6 +77,8 @@ public:
|
||||||
|
|
||||||
QRectF BoundingRect() const;
|
QRectF BoundingRect() const;
|
||||||
|
|
||||||
|
QPainterPath ContourPath() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QSharedDataPointer<VContourData> d;
|
QSharedDataPointer<VContourData> d;
|
||||||
|
|
||||||
|
|
|
@ -406,6 +406,23 @@ QPainterPath VLayoutDetail::ContourPath() const
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
QPainterPath VLayoutDetail::LayoutAllowencePath() const
|
||||||
|
{
|
||||||
|
QPainterPath path;
|
||||||
|
path.setFillRule(Qt::WindingFill);
|
||||||
|
|
||||||
|
const QVector<QPointF> 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
|
QGraphicsItem *VLayoutDetail::GetItem() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -77,6 +77,7 @@ public:
|
||||||
bool isNull() const;
|
bool isNull() const;
|
||||||
qint64 Square() const;
|
qint64 Square() const;
|
||||||
QPainterPath ContourPath() const;
|
QPainterPath ContourPath() const;
|
||||||
|
QPainterPath LayoutAllowencePath() const;
|
||||||
QGraphicsItem *GetItem() const Q_REQUIRED_RESULT;
|
QGraphicsItem *GetItem() const Q_REQUIRED_RESULT;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -268,7 +268,7 @@ bool VPosition::CheckCombineEdges(VLayoutDetail &detail, int j, int &dEdge)
|
||||||
{
|
{
|
||||||
if (not gContour.GetContour().isEmpty())
|
if (not gContour.GetContour().isEmpty())
|
||||||
{
|
{
|
||||||
type = Crossing(detail, j, dEdge);
|
type = Crossing(detail);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -285,26 +285,11 @@ bool VPosition::CheckCombineEdges(VLayoutDetail &detail, int j, int &dEdge)
|
||||||
flagMirror = true;
|
flagMirror = true;
|
||||||
break;
|
break;
|
||||||
case CrossingType::NoIntersection:
|
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;
|
flagSquare = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flagMirror)
|
if (flagMirror)
|
||||||
{
|
{
|
||||||
|
@ -323,7 +308,7 @@ bool VPosition::CheckCombineEdges(VLayoutDetail &detail, int j, int &dEdge)
|
||||||
CrossingType type = CrossingType::Intersection;
|
CrossingType type = CrossingType::Intersection;
|
||||||
if (SheetContains(detail.BoundingRect()))
|
if (SheetContains(detail.BoundingRect()))
|
||||||
{
|
{
|
||||||
type = Crossing(detail, j, dEdge);
|
type = Crossing(detail);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
|
@ -334,25 +319,11 @@ bool VPosition::CheckCombineEdges(VLayoutDetail &detail, int j, int &dEdge)
|
||||||
flagSquare = false;
|
flagSquare = false;
|
||||||
break;
|
break;
|
||||||
case CrossingType::NoIntersection:
|
case CrossingType::NoIntersection:
|
||||||
{
|
|
||||||
switch (InsideContour(detail, dEdge))
|
|
||||||
{
|
|
||||||
case InsideType::EdgeError:
|
|
||||||
return false;
|
|
||||||
case InsideType::Inside:
|
|
||||||
flagSquare = false;
|
|
||||||
break;
|
|
||||||
case InsideType::Outside:
|
|
||||||
flagSquare = true;
|
flagSquare = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return flagSquare;
|
return flagSquare;
|
||||||
}
|
}
|
||||||
|
@ -374,7 +345,7 @@ bool VPosition::CheckRotationEdges(VLayoutDetail &detail, int j, int dEdge, int
|
||||||
CrossingType type = CrossingType::Intersection;
|
CrossingType type = CrossingType::Intersection;
|
||||||
if (SheetContains(detail.BoundingRect()))
|
if (SheetContains(detail.BoundingRect()))
|
||||||
{
|
{
|
||||||
type = Crossing(detail, j, dEdge);
|
type = Crossing(detail);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
|
@ -385,30 +356,16 @@ bool VPosition::CheckRotationEdges(VLayoutDetail &detail, int j, int dEdge, int
|
||||||
flagSquare = false;
|
flagSquare = false;
|
||||||
break;
|
break;
|
||||||
case CrossingType::NoIntersection:
|
case CrossingType::NoIntersection:
|
||||||
{
|
|
||||||
switch (InsideContour(detail, dEdge))
|
|
||||||
{
|
|
||||||
case InsideType::EdgeError:
|
|
||||||
return false;
|
|
||||||
case InsideType::Inside:
|
|
||||||
flagSquare = false;
|
|
||||||
break;
|
|
||||||
case InsideType::Outside:
|
|
||||||
flagSquare = true;
|
flagSquare = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return flagSquare;
|
return flagSquare;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
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 dRect = detail.BoundingRect();
|
||||||
const QRectF gRect = gContour.BoundingRect();
|
const QRectF gRect = gContour.BoundingRect();
|
||||||
|
@ -418,158 +375,14 @@ VPosition::CrossingType VPosition::Crossing(const VLayoutDetail &detail, const i
|
||||||
return CrossingType::NoIntersection;
|
return CrossingType::NoIntersection;
|
||||||
}
|
}
|
||||||
|
|
||||||
int globalEdgesCount = gContour.GlobalEdgesCount();
|
if (gContour.ContourPath().intersects(detail.LayoutAllowencePath()))
|
||||||
if (globalEdgesCount == 0)
|
|
||||||
{
|
|
||||||
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::Intersection;
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
}
|
{
|
||||||
}
|
|
||||||
|
|
||||||
return CrossingType::NoIntersection;
|
return CrossingType::NoIntersection;
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
|
||||||
VPosition::InsideType VPosition::InsideContour(const VLayoutDetail &detail, const int &detailI) const
|
|
||||||
{
|
|
||||||
if (detail.EdgesCount() < 3)
|
|
||||||
{
|
|
||||||
return InsideType::EdgeError;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const QVector<QPointF> 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const int polyCorners = gContour.GlobalEdgesCount();
|
|
||||||
int j = polyCorners-1;
|
|
||||||
|
|
||||||
QVector<qreal> constant;
|
|
||||||
QVector<qreal> multiple;
|
|
||||||
|
|
||||||
for (int i=0; i<polyCorners; i++)
|
|
||||||
{
|
|
||||||
const qreal xi = gContour.at(i).x(); //-V807
|
|
||||||
const qreal xj = gContour.at(j).x(); //-V807
|
|
||||||
const qreal yi = gContour.at(i).y();
|
|
||||||
const qreal yj = gContour.at(j).y();
|
|
||||||
if (VFuzzyComparePossibleNulls(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 m = 1; m <= detail.EdgesCount(); ++m)
|
|
||||||
{
|
|
||||||
if (m == detailI)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const QLineF detailEdge = detail.Edge(m);
|
|
||||||
if (detailEdge.isNull()) // Got null edge
|
|
||||||
{
|
|
||||||
return InsideType::EdgeError;
|
|
||||||
}
|
|
||||||
|
|
||||||
const QVector<QPointF> p = Triplet(detailEdge);
|
|
||||||
for (int n=0; n<p.size(); ++n )
|
|
||||||
{
|
|
||||||
int j = polyCorners-1;
|
|
||||||
bool oddNodes = false;
|
|
||||||
|
|
||||||
for (int i=0; i<polyCorners; i++)
|
|
||||||
{
|
|
||||||
const qreal yi = gContour.at(i).y();
|
|
||||||
const qreal yj = gContour.at(j).y();
|
|
||||||
|
|
||||||
const QPointF &pn = p.at(n);
|
|
||||||
if (((yi < pn.y() && yj >= 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 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<QPointF> VPosition::Triplet(const QLineF &edge) const
|
|
||||||
{
|
|
||||||
QVector<QPointF> 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)
|
QPainterPath VPosition::ShowDirection(const QLineF &edge)
|
||||||
{
|
{
|
||||||
|
|
|
@ -108,9 +108,7 @@ private:
|
||||||
bool CheckCombineEdges(VLayoutDetail &detail, int j, int &dEdge);
|
bool CheckCombineEdges(VLayoutDetail &detail, int j, int &dEdge);
|
||||||
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, const int &globalI, const int &detailI) const;
|
CrossingType Crossing(const VLayoutDetail &detail) 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;
|
bool SheetContains(const QRectF &rect) const;
|
||||||
|
|
||||||
void CombineEdges(VLayoutDetail &detail, const QLineF &globalEdge, const int &dEdge);
|
void CombineEdges(VLayoutDetail &detail, const QLineF &globalEdge, const int &dEdge);
|
||||||
|
@ -118,10 +116,6 @@ private:
|
||||||
|
|
||||||
QPolygonF GlobalPolygon() const;
|
QPolygonF GlobalPolygon() const;
|
||||||
|
|
||||||
bool TrueIntersection(const QLineF &gEdge, const QLineF &dEdge, const QPointF &p) const;
|
|
||||||
QPointF RoundedPoint(const QPointF &p) const;
|
|
||||||
QVector<QPointF> Triplet(const QLineF &edge) const;
|
|
||||||
|
|
||||||
static QPainterPath ShowDirection(const QLineF &edge);
|
static QPainterPath ShowDirection(const QLineF &edge);
|
||||||
static QPainterPath DrawContour(const QVector<QPointF> &points);
|
static QPainterPath DrawContour(const QVector<QPointF> &points);
|
||||||
static QPainterPath DrawDetails(const QVector<VLayoutDetail> &details);
|
static QPainterPath DrawDetails(const QVector<VLayoutDetail> &details);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user