Correct removing loop if a path contains them several. Seek and remove the last.

In this way we will correct remove them all.

--HG--
branch : develop
This commit is contained in:
Roman Telezhynskyi 2016-01-09 23:53:17 +02:00
parent 975a528560
commit c2976614ba
4 changed files with 149 additions and 26 deletions

View File

@ -300,57 +300,59 @@ QVector<QPointF> VAbstractDetail::CorrectEquidistantPoints(const QVector<QPointF
*/ */
QVector<QPointF> VAbstractDetail::CheckLoops(const QVector<QPointF> &points) QVector<QPointF> VAbstractDetail::CheckLoops(const QVector<QPointF> &points)
{ {
QVector<QPointF> ekvPoints; const int count = points.size();
/*If we got less than 4 points no need seek loops.*/ /*If we got less than 4 points no need seek loops.*/
if (points.size() < 4) if (count < 4)
{ {
qDebug()<<"Less then 4 points. Doesn't need check for loops."; qDebug()<<"Less then 4 points. Doesn't need check for loops.";
return points; return points;
} }
bool closed = false; bool closed = false;
if (points.at(0) == points.at(points.size()-1)) if (points.first() == points.last())
{ {
closed = true; closed = true;
} }
QVector<QPointF> ekvPoints;
qint32 i, j; qint32 i, j;
for (i = 0; i < points.size(); ++i) for (i = 0; i < count; ++i)
{ {
/*Last three points no need check.*/ /*Last three points no need check.*/
if (i >= points.size()-3) /*Triangle has not contain loops*/
if (i >= count-3)
{ {
ekvPoints.append(points.at(i)); ekvPoints.append(points.at(i));
continue; continue;
} }
QPointF crosPoint; QPointF crosPoint;
QLineF::IntersectType intersect = QLineF::NoIntersection; QLineF::IntersectType intersect = QLineF::NoIntersection;
QLineF line1(points.at(i), points.at(i+1)); const QLineF line1(points.at(i), points.at(i+1));
for (j = i+2; j < points.size()-1; ++j) // Because a path can contains several loops we will seek the last and only then remove the loop(s)
// That's why we parse from the end
for (j = count-2; j >= i+2; --j)
{ {
QLineF line2(points.at(j), points.at(j+1)); const QLineF line2(points.at(j), points.at(j+1));
intersect = line1.intersect(line2, &crosPoint); intersect = line1.intersect(line2, &crosPoint);
if (intersect == QLineF::BoundedIntersection) if (intersect == QLineF::BoundedIntersection && not (i == 0 && j+1 == count-1 && closed))
{ { // Break, but not if intersects the first edge and the last edge in closed path
break; break;
} }
intersect = QLineF::NoIntersection;
} }
if (intersect == QLineF::BoundedIntersection) if (intersect == QLineF::BoundedIntersection)
{ {
if (i == 0 && j+1 == points.size()-1 && closed) /*We have found loop.*/
{ ekvPoints.append(points.at(i));
/*We got closed contour.*/ ekvPoints.append(crosPoint);
ekvPoints.append(points.at(i)); i = j;
}
else
{
/*We found loop.*/
ekvPoints.append(points.at(i));
ekvPoints.append(crosPoint);
i = j;
}
} }
else else
{ {
/*We did not found loop.*/ /*We have not found loop.*/
ekvPoints.append(points.at(i)); ekvPoints.append(points.at(i));
} }
} }

View File

@ -65,13 +65,12 @@ public:
void setWidth(const qreal &value); void setWidth(const qreal &value);
static QVector<QPointF> Equidistant(const QVector<QPointF> &points, const EquidistantType &eqv, qreal width); static QVector<QPointF> Equidistant(const QVector<QPointF> &points, const EquidistantType &eqv, qreal width);
static qreal SumTrapezoids(const QVector<QPointF> &points); static qreal SumTrapezoids(const QVector<QPointF> &points);
static QVector<QPointF> CheckLoops(const QVector<QPointF> &points);
protected: protected:
static QVector<QPointF> RemoveDublicates(const QVector<QPointF> &points); static QVector<QPointF> RemoveDublicates(const QVector<QPointF> &points);
static QVector<QPointF> CorrectEquidistantPoints(const QVector<QPointF> &points); static QVector<QPointF> CorrectEquidistantPoints(const QVector<QPointF> &points);
static QVector<QPointF> CheckLoops(const QVector<QPointF> &points);
private: private:
QSharedDataPointer<VAbstractDetailData> d; QSharedDataPointer<VAbstractDetailData> d;

View File

@ -64,7 +64,127 @@ void TST_VAbstractDetail::SumTrapezoids() const
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void TST_VAbstractDetail::PathRemoveLoop_data() const
{
QTest::addColumn<QVector<QPointF>>("path");
QTest::addColumn<QVector<QPointF>>("expect");
QVector<QPointF> path;
path << QPointF(10, 10);
path << QPointF(20, 10);
path << QPointF(20, 20);
path << QPointF(10, 20);
path << QPointF(10, 10);
QTest::newRow("Correct closed a path (four unique points)") << path << path;
path.removeLast();
QTest::newRow("Correct unclosed a path (four unique points)") << path << path;
path.clear();
path << QPointF(0, 10);
path << QPointF(10, 10);
path << QPointF(20, 10);
path << QPointF(20, 20);
path << QPointF(10, 20);
path << QPointF(0, 20);
path << QPointF(0, 10);
QTest::newRow("Correct closed a path (six unique points)") << path << path;
path.removeLast();
QTest::newRow("Correct unclosed a path (six unique points)") << path << path;
path.clear();
path << QPointF(20, 10);
path << QPointF(10, 20);
path << QPointF(10, 10);
path << QPointF(20, 20);
path << QPointF(20, 10);
QVector<QPointF> res;
res << QPointF(20, 10);
res << QPointF(15, 15);
res << QPointF(20, 20);
res << QPointF(20, 10);
QTest::newRow("One loop, closed a path (four unique points)") << path << res;
path.removeLast();
res.removeLast();
QTest::newRow("One loop, unclosed a path (four unique points)") << path << res;
path.clear();
path << QPointF(20, 10);
path << QPointF(10, 20);
path << QPointF(0, 10);
path << QPointF(0, 20);
path << QPointF(10, 10);
path << QPointF(20, 20);
path << QPointF(20, 10);
res.clear();
res << QPointF(20, 10);
res << QPointF(15, 15);
res << QPointF(20, 20);
res << QPointF(20, 10);
QTest::newRow("Two loops, closed a path (six unique points)") << path << res;
path.removeLast();
res.removeLast();
QTest::newRow("Two loops, unclosed a path (six unique points)") << path << res;
path.clear();
path << QPointF(20, 10);
path << QPointF(10, 20);
path << QPointF(0, 20);
path << QPointF(0, 10);
path << QPointF(10, 10);
path << QPointF(20, 20);
path << QPointF(20, 10);
res.clear();
res << QPointF(20, 10);
res << QPointF(15, 15);
res << QPointF(20, 20);
res << QPointF(20, 10);
QTest::newRow("One loop, the first loop, closed a path (six unique points)") << path << res;
path.removeLast();
res.removeLast();
QTest::newRow("One loop, the first loop, unclosed a path (six unique points)") << path << res;
path.clear();
path << QPointF(20, 10);
path << QPointF(10, 10);
path << QPointF(0, 20);
path << QPointF(0, 10);
path << QPointF(10, 20);
path << QPointF(20, 20);
path << QPointF(20, 10);
res.clear();
res << QPointF(20, 10);
res << QPointF(10, 10);
res << QPointF(5, 15);
res << QPointF(10, 20);
res << QPointF(20, 20);
res << QPointF(20, 10);
QTest::newRow("One loop, the second loop, closed a path (six unique points)") << path << res;
path.removeLast();
res.removeLast();
QTest::newRow("One loop, the second loop, unclosed a path (six unique points)") << path << res;
}
//---------------------------------------------------------------------------------------------------------------------
void TST_VAbstractDetail::PathRemoveLoop() const
{
QFETCH(QVector<QPointF>, path);
QFETCH(QVector<QPointF>, expect);
QVector<QPointF> res = VAbstractDetail::CheckLoops(path);
Comparison(res, expect);
}
//---------------------------------------------------------------------------------------------------------------------
void TST_VAbstractDetail::Case1() const void TST_VAbstractDetail::Case1() const
{ {
const QVector<QPointF> points = InputPointsCase1(); // Input points. const QVector<QPointF> points = InputPointsCase1(); // Input points.

View File

@ -42,6 +42,8 @@ signals:
private slots: private slots:
void EquidistantRemoveLoop() const; void EquidistantRemoveLoop() const;
void SumTrapezoids() const; void SumTrapezoids() const;
void PathRemoveLoop_data() const;
void PathRemoveLoop() const;
private: private:
void Case1() const; void Case1() const;