Port changes from develop branch.

--HG--
branch : feature
This commit is contained in:
Roman Telezhynskyi 2017-01-11 14:53:16 +02:00
parent 5a95ce9c8a
commit 12162e49e8
2 changed files with 151 additions and 41 deletions

View File

@ -34,6 +34,7 @@
#include <QLineF> #include <QLineF>
#include <QSet> #include <QSet>
#include <QVector> #include <QVector>
#include <QPainterPath>
const qreal maxL = 2.4; const qreal maxL = 2.4;
@ -207,7 +208,6 @@ QVector<QPointF> VAbstractPiece::CheckLoops(const QVector<QPointF> &points)
/*If we got less than 4 points no need seek loops.*/ /*If we got less than 4 points no need seek loops.*/
if (count < 4) if (count < 4)
{ {
qDebug()<<"Less then 4 points. Doesn't need check for loops.";
return points; return points;
} }
@ -235,7 +235,6 @@ QVector<QPointF> VAbstractPiece::CheckLoops(const QVector<QPointF> &points)
// That's why we parse from the end // That's why we parse from the end
for (j = count-1; j >= i+2; --j) for (j = count-1; j >= i+2; --j)
{ {
j == count-1 ? jNext = 0 : jNext = j+1; j == count-1 ? jNext = 0 : jNext = j+1;
QLineF line2(points.at(j), points.at(jNext)); QLineF line2(points.at(j), points.at(jNext));
@ -257,11 +256,7 @@ QVector<QPointF> VAbstractPiece::CheckLoops(const QVector<QPointF> &points)
// Method IsPointOnLineviaPDP will check it. // Method IsPointOnLineviaPDP will check it.
if (VGObject::IsPointOnLineviaPDP(points.at(j), points.at(i), points.at(i+1)) if (VGObject::IsPointOnLineviaPDP(points.at(j), points.at(i), points.at(i+1))
// Lines are not neighbors // Lines are not neighbors
&& uniqueVertices.size() == 4 && uniqueVertices.size() == 4)
&& line1.p2() != line2.p2()
&& line1.p1() != line2.p1()
&& line1.p2() != line2.p1()
&& line1.p1() != line2.p2())
{ {
// Left to catch case where segments are on the same line, but do not have real intersections. // Left to catch case where segments are on the same line, but do not have real intersections.
QLineF tmpLine1 = line1; QLineF tmpLine1 = line1;
@ -279,57 +274,42 @@ QVector<QPointF> VAbstractPiece::CheckLoops(const QVector<QPointF> &points)
if (tmpIntrs1 == QLineF::BoundedIntersection || tmpIntrs2 == QLineF::BoundedIntersection) if (tmpIntrs1 == QLineF::BoundedIntersection || tmpIntrs2 == QLineF::BoundedIntersection)
{ // Now we really sure that lines are on the same lines and have real intersections. { // Now we really sure that lines are on the same lines and have real intersections.
QPointF cPoint;
const bool caseFlag = ParallelCrossPoint(line1, line2, cPoint);
if (not caseFlag || CheckIntersection(points, i, i+1, j, jNext, cPoint))
{
status = ParallelIntersection; status = ParallelIntersection;
break; break;
} }
} }
} }
}
else if (intersect == QLineF::BoundedIntersection) else if (intersect == QLineF::BoundedIntersection)
{ {
if (uniqueVertices.size() == 4 if (uniqueVertices.size() == 4)
&& line1.p1() != crosPoint { // Break, but not if lines are neighbors
if ((line1.p1() != crosPoint
&& line1.p2() != crosPoint && line1.p2() != crosPoint
&& line2.p1() != crosPoint && line2.p1() != crosPoint
&& line2.p2() != crosPoint) && line2.p2() != crosPoint) || CheckIntersection(points, i, i+1, j, jNext, crosPoint))
{ // Break, but not if lines are neighbors {
status = BoundedIntersection; status = BoundedIntersection;
break; break;
} }
} }
}
status = NoIntersection; status = NoIntersection;
} }
switch (status) switch (status)
{ {
case ParallelIntersection: case ParallelIntersection:
{
/*We have found a loop.*/ /*We have found a loop.*/
// Very tricky case
// See the file "collection/bugs/Issue_#603.val"
const QLineF line1(points.at(i+1), points.at(j));
const QLineF line2(points.at(i), points.at(jNext));
if (line1.length() <= line2.length())
{
// In this case we did not check a loop edges and can just skip them
ekvPoints.append(points.at(i)); ekvPoints.append(points.at(i));
ekvPoints.append(points.at(jNext)); ekvPoints.append(points.at(jNext));
jNext > j ? i = jNext : i = j; // Skip a loop
i = j; // Skip a loo
}
else
{
// In this case a loop edges probably was also chacked and added to the list
ekvPoints.clear();// Previous data is wrong and belong to loop.
ekvPoints.append(points.at(j));
ekvPoints.append(points.at(i+1));
count = j+1;// All beyond this belong to loop.
}
break; break;
}
case BoundedIntersection: case BoundedIntersection:
/*We have found a loop.*/
ekvPoints.append(points.at(i)); ekvPoints.append(points.at(i));
ekvPoints.append(crosPoint); ekvPoints.append(crosPoint);
i = j; i = j;
@ -831,3 +811,128 @@ qreal VAbstractPiece::AngleBetweenBisectors(const QLineF &b1, const QLineF &b2)
return angle2; return angle2;
} }
} }
//---------------------------------------------------------------------------------------------------------------------
bool VAbstractPiece::CheckIntersection(const QVector<QPointF> &points, int i, int iNext, int j, int jNext,
const QPointF &crossPoint)
{
QVector<QPointF> sub1 = SubPath(points, iNext, j);
sub1.append(crossPoint);
sub1 = CheckLoops(CorrectEquidistantPoints(sub1, false));
const qreal sub1Sum = SumTrapezoids(sub1);
QVector<QPointF> sub2 = SubPath(points, jNext, i);
sub2.append(crossPoint);
sub2 = CheckLoops(CorrectEquidistantPoints(sub2, false));
const qreal sub2Sum = SumTrapezoids(sub2);
if (sub1Sum < 0 && sub2Sum < 0)
{
if (Crossing(sub1, sub2))
{
return true;
}
}
else
{
if (not Crossing(sub1, sub2))
{
return true;
}
}
return false;
}
//---------------------------------------------------------------------------------------------------------------------
bool VAbstractPiece::ParallelCrossPoint(const QLineF &line1, const QLineF &line2, QPointF &point)
{
const bool l1p1el2p1 = (line1.p1() == line2.p1());
const bool l1p2el2p2 = (line1.p2() == line2.p2());
const bool l1p1el2p2 = (line1.p1() == line2.p2());
const bool l1p2el2p1 = (line1.p2() == line2.p1());
if (l1p2el2p2 || l1p2el2p1)
{
point = line1.p2();
return true;
}
else if (l1p1el2p1 || l1p1el2p2)
{
point = line1.p1();
return true;
}
else
{
point = QPointF();
return false;
}
}
//---------------------------------------------------------------------------------------------------------------------
bool VAbstractPiece::Crossing(const QVector<QPointF> &sub1, const QVector<QPointF> &sub2)
{
if (sub1.isEmpty() || sub2.isEmpty())
{
return false;
}
const QRectF sub1Rect = QPolygonF(sub1).boundingRect();
const QRectF sub2Rect = QPolygonF(sub2).boundingRect();
if (not sub1Rect.intersects(sub2Rect))
{
return false;
}
QPainterPath sub1Path;
sub1Path.setFillRule(Qt::WindingFill);
sub1Path.moveTo(sub1.at(0));
for (qint32 i = 1; i < sub1.count(); ++i)
{
sub1Path.lineTo(sub1.at(i));
}
sub1Path.lineTo(sub1.at(0));
QPainterPath sub2Path;
sub2Path.setFillRule(Qt::WindingFill);
sub2Path.moveTo(sub2.at(0));
for (qint32 i = 1; i < sub2.count(); ++i)
{
sub2Path.lineTo(sub2.at(i));
}
sub2Path.lineTo(sub2.at(0));
if (not sub1Path.intersects(sub2Path))
{
return false;
}
else
{
return true;
}
}
//---------------------------------------------------------------------------------------------------------------------
QVector<QPointF> VAbstractPiece::SubPath(const QVector<QPointF> &path, int startIndex, int endIndex)
{
if (path.isEmpty()
|| startIndex < 0 || startIndex >= path.size()
|| endIndex < 0 || endIndex >= path.size()
|| startIndex == endIndex)
{
return path;
}
QVector<QPointF> subPath;
int i = startIndex - 1;
do
{
++i;
if (i >= path.size())
{
i = 0;
}
subPath.append(path.at(i));
} while (i != endIndex);
return subPath;
}

View File

@ -170,6 +170,11 @@ protected:
private: private:
QSharedDataPointer<VAbstractPieceData> d; QSharedDataPointer<VAbstractPieceData> d;
static bool CheckIntersection(const QVector<QPointF> &points, int i, int iNext, int j, int jNext,
const QPointF &crossPoint);
static bool ParallelCrossPoint(const QLineF &line1, const QLineF &line2, QPointF &point);
static bool Crossing(const QVector<QPointF> &sub1, const QVector<QPointF> &sub2);
static QVector<QPointF> SubPath(const QVector<QPointF> &path, int startIndex, int endIndex);
static Q_DECL_CONSTEXPR qreal PointPosition(const QPointF &p, const QLineF &line); static Q_DECL_CONSTEXPR qreal PointPosition(const QPointF &p, const QLineF &line);
static qreal MaxLocalSA(const VSAPoint &p, qreal width); static qreal MaxLocalSA(const VSAPoint &p, qreal width);
static QVector<QPointF> EkvPoint(const VSAPoint &p1Line1, const VSAPoint &p2Line1, static QVector<QPointF> EkvPoint(const VSAPoint &p1Line1, const VSAPoint &p2Line1,