Fixed issue #957. Unable to cut an arc with negative length.

(grafted from 885261e387dda0508fda374445b9c05e379103e0)

--HG--
branch : develop
This commit is contained in:
Roman Telezhynskyi 2019-04-03 09:37:43 +03:00
parent de39309f5a
commit 2f420854c2
6 changed files with 128 additions and 22 deletions

View File

@ -33,6 +33,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.

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<pattern>
<!--Pattern created with Valentina v0.6.2.0 (https://valentinaproject.bitbucket.io/).-->
<version>0.7.12</version>
<unit>cm</unit>
<description/>
<notes/>
<measurements/>
<increments/>
<previewCalculations/>
<draw name="Pattern piece 1">
<calculation>
<point id="1" mx="0.132292" my="0.264583" name="А" showLabel="true" type="single" x="5.00423" y="9.10502"/>
<arc aScale="0.5" angle1="45" center="1" color="black" id="2" length="-10" penStyle="hair" radius="10" type="arcWithLength"/>
<point arc="2" id="3" length="6" mx="0.132292" my="0.264583" name="А1" showLabel="true" type="cutArc"/>
<arc aScale="0" angle1="135" center="1" color="black" id="4" length="10" penStyle="hair" radius="10" type="arcWithLength"/>
<point arc="4" id="5" length="-7" mx="0.132292" my="0.241842" name="А2" showLabel="true" type="cutArc"/>
</calculation>
<modeling/>
<details/>
<groups/>
</draw>
</pattern>

View File

@ -232,8 +232,7 @@ QVector<QPointF> VArc::GetPoints() const
QVector<QPointF> points;
QVector<qreal> sectionAngle;
QPointF pStart;
IsFlipped() ? pStart = GetP2() : pStart = GetP1();
QPointF pStart = IsFlipped() ? GetP2() : GetP1();
{
qreal angle = AngleArc();
@ -304,53 +303,56 @@ QVector<QPointF> 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<QPointF>(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<QPointF>(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;

View File

@ -83,8 +83,8 @@ public:
virtual QVector<QPointF> 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;

View File

@ -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<QPointF>("center");
QTest::addColumn<qreal>("radius");
QTest::addColumn<qreal>("startAngle");
QTest::addColumn<qreal>("length");
QTest::addColumn<qreal>("cutLength");
QTest::addColumn<QPointF>("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 <root>/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 <root>/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);
}

View File

@ -46,6 +46,8 @@ private slots:
void TestRotation();
void TestFlip_data();
void TestFlip();
void TestCutArc_data();
void TestCutArc();
};
#endif // TST_VARC_H