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)
|
||||
{
|
||||
QPainterPath splinePath;
|
||||
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();
|
||||
return PathLength(GetCubicBezierPoints(p1, p2, p3, p4));
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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.first().toPoint() == begin.toPoint())
|
||||
{
|
||||
if (ok != nullptr)
|
||||
{
|
||||
*ok = true;
|
||||
}
|
||||
return points;
|
||||
}
|
||||
|
||||
QVector<QPointF> segment;
|
||||
bool theBegin = false;
|
||||
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 (ok != nullptr)
|
||||
{
|
||||
*ok = false;
|
||||
}
|
||||
return points;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ok != nullptr)
|
||||
{
|
||||
*ok = true;
|
||||
}
|
||||
return segment;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
reversed = FromBegin(reversed, end);
|
||||
reversed = FromBegin(reversed, end, ok);
|
||||
return GetReversePoints(reversed);
|
||||
}
|
||||
|
||||
|
@ -170,6 +190,29 @@ QPainterPath VAbstractCurve::GetPath(PathDirection direction) const
|
|||
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
|
||||
|
@ -257,3 +300,15 @@ QPainterPath VAbstractCurve::ShowDirection(const QVector<QPointF> &points) const
|
|||
}
|
||||
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 qreal GetLength() const =0;
|
||||
qreal GetLengthByPoint(const QPointF &point) const;
|
||||
virtual QVector<QPointF> IntersectLine(const QLineF &line) const;
|
||||
virtual bool IsIntersectLine(const QLineF &line) const;
|
||||
|
||||
|
@ -74,11 +75,12 @@ public:
|
|||
protected:
|
||||
QPainterPath ShowDirection(const QVector<QPointF> &points) const;
|
||||
virtual void CreateName() =0;
|
||||
static qreal PathLength(const QVector<QPointF> &path);
|
||||
private:
|
||||
QSharedDataPointer<VAbstractCurveData> d;
|
||||
|
||||
static QVector<QPointF> FromBegin(const QVector<QPointF> &points, const QPointF &begin);
|
||||
static QVector<QPointF> ToEnd(const QVector<QPointF> &points, const QPointF &end);
|
||||
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, bool *ok = nullptr);
|
||||
};
|
||||
|
||||
Q_DECLARE_TYPEINFO(VAbstractCurve, Q_MOVABLE_TYPE);
|
||||
|
|
|
@ -128,15 +128,7 @@ VEllipticalArc::~VEllipticalArc()
|
|||
*/
|
||||
qreal VEllipticalArc::GetLength() const
|
||||
{
|
||||
qreal length = 0;
|
||||
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();
|
||||
qreal length = PathLength(GetPoints());
|
||||
|
||||
if (d->isFlipped)
|
||||
{
|
||||
|
|
|
@ -531,10 +531,12 @@ QVector<QPointF> VGObject::GetReversePoints(const QVector<QPointF> &points)
|
|||
{
|
||||
return points;
|
||||
}
|
||||
QVector<QPointF> reversePoints;
|
||||
QVector<QPointF> reversePoints(points.size());
|
||||
qint32 j = 0;
|
||||
for (qint32 i = points.size() - 1; i >= 0; --i)
|
||||
{
|
||||
reversePoints.append(points.at(i));
|
||||
reversePoints.replace(j, points.at(i));
|
||||
++j;
|
||||
}
|
||||
return reversePoints;
|
||||
}
|
||||
|
|
|
@ -107,6 +107,7 @@ private:
|
|||
static int Sign(long double ld);
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(VSpline)
|
||||
Q_DECLARE_TYPEINFO(VSpline, Q_MOVABLE_TYPE);
|
||||
|
||||
#endif // VSPLINE_H
|
||||
|
|
|
@ -307,6 +307,41 @@ void TST_VSpline::TestParametrT()
|
|||
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
|
||||
{
|
||||
|
|
|
@ -48,6 +48,8 @@ private slots:
|
|||
void GetSegmentPoints_NullSegment();
|
||||
void CompareThreeWays();
|
||||
void TestParametrT();
|
||||
void TestLengthByPoint_data();
|
||||
void TestLengthByPoint();
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(TST_VSpline)
|
||||
|
|
Loading…
Reference in New Issue
Block a user