New method curve length by given point.
--HG-- branch : develop
This commit is contained in:
parent
c99cdb69ec
commit
9470f76ba9
|
@ -524,14 +524,7 @@ QVector<QPointF> VAbstractCubicBezier::GetCubicBezierPoints(const QPointF &p1, c
|
||||||
*/
|
*/
|
||||||
qreal VAbstractCubicBezier::LengthBezier(const QPointF &p1, const QPointF &p2, const QPointF &p3, const QPointF &p4)
|
qreal VAbstractCubicBezier::LengthBezier(const QPointF &p1, const QPointF &p2, const QPointF &p3, const QPointF &p4)
|
||||||
{
|
{
|
||||||
QPainterPath splinePath;
|
return PathLength(GetCubicBezierPoints(p1, p2, p3, p4));
|
||||||
QVector<QPointF> points = GetCubicBezierPoints(p1, p2, p3, p4);
|
|
||||||
splinePath.moveTo(points.at(0));
|
|
||||||
for (qint32 i = 1; i < points.count(); ++i)
|
|
||||||
{
|
|
||||||
splinePath.lineTo(points.at(i));
|
|
||||||
}
|
|
||||||
return splinePath.length();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -89,10 +89,19 @@ QVector<QPointF> VAbstractCurve::GetSegmentPoints(const QPointF &begin, const QP
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
QVector<QPointF> VAbstractCurve::FromBegin(const QVector<QPointF> &points, const QPointF &begin)
|
QVector<QPointF> VAbstractCurve::FromBegin(const QVector<QPointF> &points, const QPointF &begin, bool *ok)
|
||||||
{
|
{
|
||||||
if (points.count() >= 2)
|
if (points.count() >= 2)
|
||||||
{
|
{
|
||||||
|
if (points.first().toPoint() == begin.toPoint())
|
||||||
|
{
|
||||||
|
if (ok != nullptr)
|
||||||
|
{
|
||||||
|
*ok = true;
|
||||||
|
}
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
QVector<QPointF> segment;
|
QVector<QPointF> segment;
|
||||||
bool theBegin = false;
|
bool theBegin = false;
|
||||||
for (qint32 i = 0; i < points.count()-1; ++i)
|
for (qint32 i = 0; i < points.count()-1; ++i)
|
||||||
|
@ -122,25 +131,36 @@ QVector<QPointF> VAbstractCurve::FromBegin(const QVector<QPointF> &points, const
|
||||||
|
|
||||||
if (segment.isEmpty())
|
if (segment.isEmpty())
|
||||||
{
|
{
|
||||||
|
if (ok != nullptr)
|
||||||
|
{
|
||||||
|
*ok = false;
|
||||||
|
}
|
||||||
return points;
|
return points;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (ok != nullptr)
|
||||||
|
{
|
||||||
|
*ok = true;
|
||||||
|
}
|
||||||
return segment;
|
return segment;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return points;
|
if (ok != nullptr)
|
||||||
|
{
|
||||||
|
*ok = false;
|
||||||
}
|
}
|
||||||
return points;
|
return points;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
QVector<QPointF> VAbstractCurve::ToEnd(const QVector<QPointF> &points, const QPointF &end)
|
QVector<QPointF> VAbstractCurve::ToEnd(const QVector<QPointF> &points, const QPointF &end, bool *ok)
|
||||||
{
|
{
|
||||||
QVector<QPointF> reversed = GetReversePoints(points);
|
QVector<QPointF> reversed = GetReversePoints(points);
|
||||||
reversed = FromBegin(reversed, end);
|
reversed = FromBegin(reversed, end, ok);
|
||||||
return GetReversePoints(reversed);
|
return GetReversePoints(reversed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,6 +190,29 @@ QPainterPath VAbstractCurve::GetPath(PathDirection direction) const
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
qreal VAbstractCurve::GetLengthByPoint(const QPointF &point) const
|
||||||
|
{
|
||||||
|
const QVector<QPointF> points = GetPoints();
|
||||||
|
if (points.size() < 2)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (points.first().toPoint() == point.toPoint())
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ok = false;
|
||||||
|
const QVector<QPointF> segment = ToEnd(points, point, &ok);
|
||||||
|
if (not ok)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return PathLength(segment);
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
/**
|
/**
|
||||||
* @brief IntersectLine return list of points for real intersection with line
|
* @brief IntersectLine return list of points for real intersection with line
|
||||||
|
@ -257,3 +300,15 @@ QPainterPath VAbstractCurve::ShowDirection(const QVector<QPointF> &points) const
|
||||||
}
|
}
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
qreal VAbstractCurve::PathLength(const QVector<QPointF> &path)
|
||||||
|
{
|
||||||
|
QPainterPath splinePath;
|
||||||
|
splinePath.moveTo(path.at(0));
|
||||||
|
for (qint32 i = 1; i < path.count(); ++i)
|
||||||
|
{
|
||||||
|
splinePath.lineTo(path.at(i));
|
||||||
|
}
|
||||||
|
return splinePath.length();
|
||||||
|
}
|
||||||
|
|
|
@ -59,6 +59,7 @@ public:
|
||||||
|
|
||||||
virtual QPainterPath GetPath(PathDirection direction = PathDirection::Hide) const;
|
virtual QPainterPath GetPath(PathDirection direction = PathDirection::Hide) const;
|
||||||
virtual qreal GetLength() const =0;
|
virtual qreal GetLength() const =0;
|
||||||
|
qreal GetLengthByPoint(const QPointF &point) const;
|
||||||
virtual QVector<QPointF> IntersectLine(const QLineF &line) const;
|
virtual QVector<QPointF> IntersectLine(const QLineF &line) const;
|
||||||
virtual bool IsIntersectLine(const QLineF &line) const;
|
virtual bool IsIntersectLine(const QLineF &line) const;
|
||||||
|
|
||||||
|
@ -74,11 +75,12 @@ public:
|
||||||
protected:
|
protected:
|
||||||
QPainterPath ShowDirection(const QVector<QPointF> &points) const;
|
QPainterPath ShowDirection(const QVector<QPointF> &points) const;
|
||||||
virtual void CreateName() =0;
|
virtual void CreateName() =0;
|
||||||
|
static qreal PathLength(const QVector<QPointF> &path);
|
||||||
private:
|
private:
|
||||||
QSharedDataPointer<VAbstractCurveData> d;
|
QSharedDataPointer<VAbstractCurveData> d;
|
||||||
|
|
||||||
static QVector<QPointF> FromBegin(const QVector<QPointF> &points, const QPointF &begin);
|
static QVector<QPointF> FromBegin(const QVector<QPointF> &points, const QPointF &begin, bool *ok = nullptr);
|
||||||
static QVector<QPointF> ToEnd(const QVector<QPointF> &points, const QPointF &end);
|
static QVector<QPointF> ToEnd(const QVector<QPointF> &points, const QPointF &end, bool *ok = nullptr);
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_TYPEINFO(VAbstractCurve, Q_MOVABLE_TYPE);
|
Q_DECLARE_TYPEINFO(VAbstractCurve, Q_MOVABLE_TYPE);
|
||||||
|
|
|
@ -128,15 +128,7 @@ VEllipticalArc::~VEllipticalArc()
|
||||||
*/
|
*/
|
||||||
qreal VEllipticalArc::GetLength() const
|
qreal VEllipticalArc::GetLength() const
|
||||||
{
|
{
|
||||||
qreal length = 0;
|
qreal length = PathLength(GetPoints());
|
||||||
QPainterPath elArc;
|
|
||||||
QVector<QPointF> points = GetPoints();
|
|
||||||
elArc.moveTo(points.at(0));
|
|
||||||
for (qint32 i = 1; i < points.count(); ++i)
|
|
||||||
{
|
|
||||||
elArc.lineTo(points.at(i));
|
|
||||||
}
|
|
||||||
length = elArc.length();
|
|
||||||
|
|
||||||
if (d->isFlipped)
|
if (d->isFlipped)
|
||||||
{
|
{
|
||||||
|
|
|
@ -531,10 +531,12 @@ QVector<QPointF> VGObject::GetReversePoints(const QVector<QPointF> &points)
|
||||||
{
|
{
|
||||||
return points;
|
return points;
|
||||||
}
|
}
|
||||||
QVector<QPointF> reversePoints;
|
QVector<QPointF> reversePoints(points.size());
|
||||||
|
qint32 j = 0;
|
||||||
for (qint32 i = points.size() - 1; i >= 0; --i)
|
for (qint32 i = points.size() - 1; i >= 0; --i)
|
||||||
{
|
{
|
||||||
reversePoints.append(points.at(i));
|
reversePoints.replace(j, points.at(i));
|
||||||
|
++j;
|
||||||
}
|
}
|
||||||
return reversePoints;
|
return reversePoints;
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,6 +107,7 @@ private:
|
||||||
static int Sign(long double ld);
|
static int Sign(long double ld);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(VSpline)
|
||||||
Q_DECLARE_TYPEINFO(VSpline, Q_MOVABLE_TYPE);
|
Q_DECLARE_TYPEINFO(VSpline, Q_MOVABLE_TYPE);
|
||||||
|
|
||||||
#endif // VSPLINE_H
|
#endif // VSPLINE_H
|
||||||
|
|
|
@ -307,6 +307,41 @@ void TST_VSpline::TestParametrT()
|
||||||
QVERIFY(qAbs(halfLength - resLength) < UnitConvertor(0.5, Unit::Mm, Unit::Px));
|
QVERIFY(qAbs(halfLength - resLength) < UnitConvertor(0.5, Unit::Mm, Unit::Px));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
void TST_VSpline::TestLengthByPoint_data()
|
||||||
|
{
|
||||||
|
VPointF p1(1168.8582803149607, 39.999874015748034, "p1", 5.0000125984251973, 9.9999874015748045);
|
||||||
|
VPointF p4(681.33729132409951, 1815.7969526662778, "p4", 5.0000125984251973, 9.9999874015748045);
|
||||||
|
|
||||||
|
VSpline spl(p1, p4, 229.381, 41.6325, 0.96294100000000005, 1.00054, 1);
|
||||||
|
|
||||||
|
QTest::addColumn<VSpline>("spl");
|
||||||
|
QTest::addColumn<QPointF>("point");
|
||||||
|
QTest::addColumn<qreal>("length");
|
||||||
|
|
||||||
|
const qreal length = spl.GetLength();
|
||||||
|
const qreal testLength = length*(2.0/3.0);
|
||||||
|
VSpline spl1, spl2;
|
||||||
|
const QPointF p = spl.CutSpline(testLength, spl1, spl2);
|
||||||
|
|
||||||
|
QTest::newRow("Point on spline") << spl << p << testLength;
|
||||||
|
QTest::newRow("Wrong point") << spl << QPointF(-10000, -10000) << -1.0;
|
||||||
|
QTest::newRow("First point") << spl << p1.toQPointF() << 0.0;
|
||||||
|
QTest::newRow("Last point") << spl << p4.toQPointF() << length;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
void TST_VSpline::TestLengthByPoint()
|
||||||
|
{
|
||||||
|
QFETCH(VSpline, spl);
|
||||||
|
QFETCH(QPointF, point);
|
||||||
|
QFETCH(qreal, length);
|
||||||
|
|
||||||
|
const qreal resLength = spl.GetLengthByPoint(point);
|
||||||
|
|
||||||
|
QVERIFY(qAbs(resLength - length) < ToPixel(0.5, Unit::Mm));
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
void TST_VSpline::CompareSplines(const VSpline &spl1, const VSpline &spl2) const
|
void TST_VSpline::CompareSplines(const VSpline &spl1, const VSpline &spl2) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -48,6 +48,8 @@ private slots:
|
||||||
void GetSegmentPoints_NullSegment();
|
void GetSegmentPoints_NullSegment();
|
||||||
void CompareThreeWays();
|
void CompareThreeWays();
|
||||||
void TestParametrT();
|
void TestParametrT();
|
||||||
|
void TestLengthByPoint_data();
|
||||||
|
void TestLengthByPoint();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Q_DISABLE_COPY(TST_VSpline)
|
Q_DISABLE_COPY(TST_VSpline)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user