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