Fix issue in tool cut spline.
Infinite loop while calculating a t parameter.
This commit is contained in:
parent
11b8ba9e78
commit
e876a4d611
|
@ -29,6 +29,7 @@
|
|||
- New path validation Invalid segment.
|
||||
- [smart-pattern/valentina#43] Background image.
|
||||
- Fix alias for tool Cut Arc.
|
||||
- Fix infinite loop in tool cut spline.
|
||||
|
||||
# Valentina 0.7.49 July 1, 2021
|
||||
- Fix crash.
|
||||
|
|
|
@ -503,28 +503,38 @@ QString VAbstractCubicBezier::NameForHistory(const QString &toolName) const
|
|||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
qreal VAbstractCubicBezier::GetParmT(qreal length) const
|
||||
auto VAbstractCubicBezier::GetParmT(qreal length) const -> qreal
|
||||
{
|
||||
const qreal base = GetRealLength();
|
||||
if (length < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (length > GetLength())
|
||||
|
||||
if (length > base)
|
||||
{
|
||||
length = GetLength();
|
||||
length = base;
|
||||
}
|
||||
|
||||
const qreal eps = 0.001 * length;
|
||||
constexpr qreal eps = UnitConvertor(0.001, Unit::Mm, Unit::Px);
|
||||
qreal parT = 0.5;
|
||||
qreal step = parT;
|
||||
qreal splLength = LengthT(parT);
|
||||
qreal splLength = 0;
|
||||
|
||||
while (qAbs(splLength - length) > eps)
|
||||
do
|
||||
{
|
||||
splLength = RealLengthByT(parT);
|
||||
step /= 2.0;
|
||||
splLength > length ? parT -= step : parT += step;
|
||||
splLength = LengthT(parT);
|
||||
|
||||
if (qFuzzyIsNull(step))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
splLength > length ? parT -= step : parT += step;
|
||||
}
|
||||
while (qAbs(splLength - length) > eps);
|
||||
|
||||
return parT;
|
||||
}
|
||||
|
||||
|
@ -591,7 +601,7 @@ qreal VAbstractCubicBezier::LengthBezier(const QPointF &p1, const QPointF &p2, c
|
|||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
qreal VAbstractCubicBezier::LengthT(qreal t) const
|
||||
qreal VAbstractCubicBezier::RealLengthByT(qreal t) const
|
||||
{
|
||||
if (t < 0 || t > 1)
|
||||
{
|
||||
|
@ -622,5 +632,5 @@ qreal VAbstractCubicBezier::LengthT(qreal t) const
|
|||
seg123_234.setLength(seg123_234.length () * t);
|
||||
const QPointF p1234 = seg123_234.p2();
|
||||
|
||||
return LengthBezier ( static_cast<QPointF>(GetP1()), p12, p123, p1234, GetApproximationScale());
|
||||
return LengthBezier ( static_cast<QPointF>(GetP1()), p12, p123, p1234, maxCurveApproximationScale);
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ public:
|
|||
virtual QString NameForHistory(const QString &toolName) const override;
|
||||
|
||||
qreal GetParmT(qreal length) const;
|
||||
qreal LengthT(qreal t) const;
|
||||
qreal RealLengthByT(qreal t) const;
|
||||
|
||||
protected:
|
||||
virtual void CreateName() override;
|
||||
|
@ -75,6 +75,7 @@ protected:
|
|||
|
||||
virtual QPointF GetControlPoint1() const =0;
|
||||
virtual QPointF GetControlPoint2() const =0;
|
||||
virtual auto GetRealLength() const -> qreal =0;
|
||||
};
|
||||
|
||||
QT_WARNING_POP
|
||||
|
|
|
@ -252,3 +252,10 @@ QPointF VCubicBezier::GetControlPoint2() const
|
|||
{
|
||||
return static_cast<QPointF>(GetP3());
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
qreal VCubicBezier::GetRealLength() const
|
||||
{
|
||||
return LengthBezier (static_cast<QPointF>(GetP1()), static_cast<QPointF>(GetP2()),
|
||||
static_cast<QPointF>(GetP3()), static_cast<QPointF>(GetP4()), maxCurveApproximationScale);
|
||||
}
|
||||
|
|
|
@ -84,6 +84,7 @@ public:
|
|||
protected:
|
||||
virtual QPointF GetControlPoint1() const override;
|
||||
virtual QPointF GetControlPoint2() const override;
|
||||
auto GetRealLength() const -> qreal override;
|
||||
|
||||
private:
|
||||
QSharedDataPointer<VCubicBezierData> d;
|
||||
|
|
|
@ -611,3 +611,10 @@ QPointF VSpline::GetControlPoint2() const
|
|||
{
|
||||
return static_cast<QPointF>(GetP3 ());
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VSpline::GetRealLength() const -> qreal
|
||||
{
|
||||
return LengthBezier(static_cast<QPointF>(GetP1()), static_cast<QPointF>(GetP2()), static_cast<QPointF>(GetP3()),
|
||||
static_cast<QPointF>(GetP4()), maxCurveApproximationScale);
|
||||
}
|
||||
|
|
|
@ -117,6 +117,7 @@ public:
|
|||
protected:
|
||||
virtual QPointF GetControlPoint1() const override;
|
||||
virtual QPointF GetControlPoint2() const override;
|
||||
auto GetRealLength () const -> qreal override;
|
||||
private:
|
||||
QSharedDataPointer<VSplineData> d;
|
||||
QVector<qreal> CalcT(qreal curveCoord1, qreal curveCoord2, qreal curveCoord3, qreal curveCoord4,
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include "tst_vspline.h"
|
||||
#include "../vgeometry/vspline.h"
|
||||
#include "def.h"
|
||||
|
||||
#include <QtTest>
|
||||
|
||||
|
@ -717,18 +718,56 @@ void TST_VSpline::CompareThreeWays()
|
|||
CompareSplines(spl3, spl1);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void TST_VSpline::TestParametrT_data()
|
||||
{
|
||||
QTest::addColumn<VSpline>("spl");
|
||||
QTest::addColumn<qreal>("length");
|
||||
|
||||
VPointF p1(30, 39.999874015748034, QStringLiteral("p1"), 15, 30);
|
||||
VPointF p4(2883.86674323853821, 805.33182541168674, QStringLiteral("p4"), 9.9999874015748045, 15);
|
||||
|
||||
VSpline spl(p1, p4, 240.60499999999999, QStringLiteral("240.605"), 260.36399999999998, QStringLiteral("260.364"),
|
||||
6614.8535433070883, QStringLiteral("175.018"), 10695.382677165355, QStringLiteral("282.982"));
|
||||
|
||||
qreal base = spl.GetLength();
|
||||
|
||||
qreal step = 0;
|
||||
do
|
||||
{
|
||||
QTest::newRow(qUtf8Printable(QStringLiteral("Curve 1. Step = %1").arg(step))) << spl << base * step;
|
||||
step += 0.001;
|
||||
}
|
||||
while(step <= 1);
|
||||
|
||||
p1 = VPointF(3476.6410658375944, 334.08136371135333, QStringLiteral("p1"), -141.34148031496062, 109.00951181102363);
|
||||
p4 = VPointF(3483.5141183177025, 333.72231804361377, QStringLiteral("p4"), 48, 102.99930708661418);
|
||||
|
||||
spl = VSpline(p1, p4, 3.1976200000000001, QStringLiteral("3.19762"), 175.24700000000001, QStringLiteral("175.247"),
|
||||
7.5076913385826796, QStringLiteral("0.198641"), 9.7351181102362219, QStringLiteral("0.257575"));
|
||||
|
||||
base = spl.GetLength();
|
||||
|
||||
step = 0;
|
||||
do
|
||||
{
|
||||
QTest::newRow(qUtf8Printable(QStringLiteral("Curve 2. Step = %1").arg(step))) << spl << base * step;
|
||||
step += 0.001;
|
||||
}
|
||||
while(step <= 1);
|
||||
|
||||
QTest::newRow(qUtf8Printable(QStringLiteral("Curve 2. Bug.").arg(step))) << spl << 4.7813492845686536;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void TST_VSpline::TestParametrT()
|
||||
{
|
||||
VPointF p1(1168.8582803149607, 39.999874015748034, "p1", 5.0000125984251973, 9.9999874015748045);
|
||||
VPointF p4(681.33729132409951, 1815.7969526662778, "p4", 5.0000125984251973, 9.9999874015748045);
|
||||
QFETCH(VSpline, spl);
|
||||
QFETCH(qreal, length);
|
||||
|
||||
VSpline spl(p1, p4, 229.381, 41.6325, 0.96294100000000005, 1.00054, 1);
|
||||
const qreal resLength = spl.RealLengthByT(spl.GetParmT(length));
|
||||
|
||||
const qreal halfLength = spl.GetLength()/2.0;
|
||||
const qreal resLength = spl.LengthT(spl.GetParmT(halfLength));
|
||||
|
||||
QVERIFY(qAbs(halfLength - resLength) < UnitConvertor(0.5, Unit::Mm, Unit::Px));
|
||||
QVERIFY(qAbs(length - resLength) < UnitConvertor(1, Unit::Mm, Unit::Px));
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -49,6 +49,7 @@ private slots:
|
|||
void GetSegmentPoints_RotateTool();
|
||||
void GetSegmentPoints_issue767();
|
||||
void CompareThreeWays();
|
||||
void TestParametrT_data();
|
||||
void TestParametrT();
|
||||
void TestLengthByPoint_data();
|
||||
void TestLengthByPoint();
|
||||
|
|
Loading…
Reference in New Issue
Block a user