diff --git a/ChangeLog.txt b/ChangeLog.txt index bb5163e2d..3a4126d3d 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -17,6 +17,7 @@ - [#954] Valentina produces empty rotation operation. - [#955] Valentina corrupts file. - [#956] Setting pattern unit doesn't change combobox value in Tape app. +- [#957] Unable to cut an arc with negative length. # Version 0.6.1 October 23, 2018 - [#885] Regression. Broken support for multi size measurements. diff --git a/src/app/share/collection/bugs/Issue_#957.val b/src/app/share/collection/bugs/Issue_#957.val new file mode 100644 index 000000000..1f3f46b9b --- /dev/null +++ b/src/app/share/collection/bugs/Issue_#957.val @@ -0,0 +1,23 @@ + + + + 0.7.12 + cm + + + + + + + + + + + + + + +
+ + + diff --git a/src/libs/vgeometry/varc.cpp b/src/libs/vgeometry/varc.cpp index dcc69318d..28af26f2f 100644 --- a/src/libs/vgeometry/varc.cpp +++ b/src/libs/vgeometry/varc.cpp @@ -232,8 +232,7 @@ QVector VArc::GetPoints() const QVector points; QVector sectionAngle; - QPointF pStart; - IsFlipped() ? pStart = GetP2() : pStart = GetP1(); + QPointF pStart = IsFlipped() ? GetP2() : GetP1(); { qreal angle = AngleArc(); @@ -304,53 +303,56 @@ QVector VArc::GetPoints() const * @param arc2 second arc. * @return point cutting */ -QPointF VArc::CutArc(const qreal &length, VArc &arc1, VArc &arc2) const +QPointF VArc::CutArc(qreal length, VArc &arc1, VArc &arc2) const { //Always need return two arcs, so we must correct wrong length. - qreal len = 0; - const qreal minLength = ToPixel(1, Unit::Mm); const qreal fullLength = GetLength(); - if (fullLength <= minLength) + if (qAbs(fullLength) < ToPixel(2, Unit::Mm)) { arc1 = VArc(); arc2 = VArc(); return QPointF(); } - const qreal maxLength = fullLength - minLength; + QLineF line(static_cast(GetCenter()), GetP1()); - if (length < minLength) + if (not IsFlipped()) { - len = minLength; - } - else if (length > maxLength) - { - len = maxLength; + if (length < 0) + { + length = fullLength + length; + } + length = qBound(ToPixel(1, Unit::Mm), length, fullLength - ToPixel(1, Unit::Mm)); + + line.setAngle(line.angle() + qRadiansToDegrees(length/d->radius)); } else { - len = length; + if (length > 0) + { + length = fullLength + length; + } + length = qBound(fullLength + ToPixel(1, Unit::Mm), length, ToPixel(-1, Unit::Mm)); + + line.setAngle(line.angle() - qRadiansToDegrees(qAbs(length)/d->radius)); } - qreal n = qRadiansToDegrees(len/d->radius); // n - is angle in degrees - - QLineF line(static_cast(GetCenter()), GetP1()); - line.setAngle(line.angle()+n); - arc1 = VArc (GetCenter(), d->radius, d->formulaRadius, GetStartAngle(), GetFormulaF1(), line.angle(), QString().setNum(line.angle()), getIdObject(), getMode()); arc1.SetApproximationScale(GetApproximationScale()); + arc1.SetFlipped(IsFlipped()); arc2 = VArc (GetCenter(), d->radius, d->formulaRadius, line.angle(), QString().setNum(line.angle()), GetEndAngle(), GetFormulaF2(), getIdObject(), getMode()); arc2.SetApproximationScale(GetApproximationScale()); + arc2.SetFlipped(IsFlipped()); return line.p2(); } //--------------------------------------------------------------------------------------------------------------------- -QPointF VArc::CutArc(const qreal &length) const +QPointF VArc::CutArc(qreal length) const { VArc arc1; VArc arc2; diff --git a/src/libs/vgeometry/varc.h b/src/libs/vgeometry/varc.h index 33cf9d790..1608ef3bd 100644 --- a/src/libs/vgeometry/varc.h +++ b/src/libs/vgeometry/varc.h @@ -83,8 +83,8 @@ public: virtual QVector GetPoints () const override; - QPointF CutArc (const qreal &length, VArc &arc1, VArc &arc2) const; - QPointF CutArc (const qreal &length) const; + QPointF CutArc (qreal length, VArc &arc1, VArc &arc2) const; + QPointF CutArc (qreal length) const; protected: virtual void CreateName() override; virtual void FindF2(qreal length) override; diff --git a/src/test/ValentinaTest/tst_varc.cpp b/src/test/ValentinaTest/tst_varc.cpp index 6ac85f510..33135fa92 100644 --- a/src/test/ValentinaTest/tst_varc.cpp +++ b/src/test/ValentinaTest/tst_varc.cpp @@ -318,3 +318,81 @@ void TST_VArc::TestFlip() QCOMPARE(originArc.GetRadius(), res.GetRadius()); QCOMPARE(originArc.AngleArc(), res.AngleArc()); } + +//--------------------------------------------------------------------------------------------------------------------- +void TST_VArc::TestCutArc_data() +{ + QTest::addColumn("center"); + QTest::addColumn("radius"); + QTest::addColumn("startAngle"); + QTest::addColumn("length"); + QTest::addColumn("cutLength"); + QTest::addColumn("cutPoint"); + + QPointF center (189.13625196850393, 344.1267401574803); + qreal radius = ToPixel(10, Unit::Cm); + qreal startAngle = 45.0; + qreal length = ToPixel(-10, Unit::Cm); + qreal cutLength = ToPixel(6, Unit::Cm); + QPointF cutPoint(539.3657292513009, 202.04366960088566); + + // See file /src/app/share/collection/bugs/Issue_#957.val + QTest::newRow("Arc -10 cm length, cut length 6 cm") << center << radius << startAngle << length << cutLength + << cutPoint; + + cutLength = ToPixel(-4, Unit::Cm); + + // Opposite case + QTest::newRow("Arc -10 cm length, cut length -4 cm") << center << radius << startAngle << length << cutLength + << cutPoint; + + startAngle = 135; + length = ToPixel(10, Unit::Cm); + cutLength = ToPixel(-7, Unit::Cm); + cutPoint = QPointF(-145.1588983496871, 167.78888781060192); + + // See file /src/app/share/collection/bugs/Issue_#957.val + QTest::newRow("Arc 10 cm length, cut length -7 cm") << center << radius << startAngle << length << cutLength + << cutPoint; + + // Opposite case + cutLength = ToPixel(3, Unit::Cm); + QTest::newRow("Arc 10 cm length, cut length 3 cm") << center << radius << startAngle << length << cutLength + << cutPoint; +} + +//--------------------------------------------------------------------------------------------------------------------- +void TST_VArc::TestCutArc() +{ + QFETCH(QPointF, center); + QFETCH(qreal, radius); + QFETCH(qreal, startAngle); + QFETCH(qreal, length); + QFETCH(qreal, cutLength); + QFETCH(QPointF, cutPoint); + + VArc arc (length, VPointF(center), radius, startAngle); + arc.SetApproximationScale(0.5); + + VArc arc1; + VArc arc2; + QPointF point = arc.CutArc(cutLength, arc1, arc2); + + QCOMPARE(point, cutPoint); + + QCOMPARE(arc1.IsFlipped(), arc.IsFlipped()); + QCOMPARE(arc2.IsFlipped(), arc.IsFlipped()); + + QCOMPARE(arc1.GetApproximationScale(), arc.GetApproximationScale()); + QCOMPARE(arc2.GetApproximationScale(), arc.GetApproximationScale()); + + QCOMPARE(arc1.GetStartAngle(), arc.GetStartAngle()); + QCOMPARE(arc2.GetEndAngle(), arc.GetEndAngle()); + + QVERIFY(VFuzzyComparePossibleNulls(arc1.GetEndAngle(), arc2.GetStartAngle())); + + QCOMPARE(arc1.GetLength() + arc2.GetLength(), arc.GetLength()); + + qreal segmentsLength = VAbstractCurve::PathLength(arc1.GetPoints()) + VAbstractCurve::PathLength(arc2.GetPoints()); + QVERIFY(qAbs(segmentsLength - VAbstractCurve::PathLength(arc.GetPoints())) <= accuracyPointOnLine); +} diff --git a/src/test/ValentinaTest/tst_varc.h b/src/test/ValentinaTest/tst_varc.h index 29c44fc0e..657d49aea 100644 --- a/src/test/ValentinaTest/tst_varc.h +++ b/src/test/ValentinaTest/tst_varc.h @@ -46,6 +46,8 @@ private slots: void TestRotation(); void TestFlip_data(); void TestFlip(); + void TestCutArc_data(); + void TestCutArc(); }; #endif // TST_VARC_H