From 589bf173aee03817fc9fe5c4e66a8d2653b60c6b Mon Sep 17 00:00:00 2001 From: Roman Telezhynskyi Date: Mon, 7 Dec 2015 23:33:11 +0200 Subject: [PATCH] Improved calculation arc points. --HG-- branch : develop --- src/libs/vgeometry/varc.cpp | 75 +++++++++++++++++++++-------- src/test/ValentinaTest/tst_varc.cpp | 25 +++------- 2 files changed, 63 insertions(+), 37 deletions(-) diff --git a/src/libs/vgeometry/varc.cpp b/src/libs/vgeometry/varc.cpp index d98089d60..fc87a77d1 100644 --- a/src/libs/vgeometry/varc.cpp +++ b/src/libs/vgeometry/varc.cpp @@ -29,6 +29,7 @@ #include "varc.h" #include "varc_p.h" #include "../ifc/ifcdef.h" +#include "vspline.h" #include #include @@ -192,32 +193,68 @@ qreal VArc::AngleArc() const QVector VArc::GetPoints() const { QVector points; - qreal i = 0; - const qreal angle = AngleArc(); - const qint32 k = static_cast(angle); - const qreal s = angle/(k/4); //-V636 - do + QVector sectionAngle; + + QPointF pStart; + d->isFlipped ? pStart = GetP2() : pStart = GetP1(); + { - QPointF pStart; - if (d->isFlipped) + qreal angle = AngleArc(); + + if (qFuzzyIsNull(angle)) { - pStart = GetP2(); + points.append(pStart); + return points; } - else + + if (angle > 360 || angle < 0) + {// Filter incorect value + QLineF dummy(0,0, 100, 0); + dummy.setAngle(angle); + angle = dummy.angle(); + } + + const qreal angleInterpolation = 45; //degree + const int sections = qFloor(angle / angleInterpolation); + for (int i = 0; i < sections; ++i) { - pStart = GetP1(); + sectionAngle.append(angleInterpolation); } - QLineF line(d->center.toQPointF(), pStart); - line.setAngle(line.angle()+i); - points.append(line.p2()); - i = i + s; - if (i > angle) + + const qreal tail = angle - sections * angleInterpolation; + if (tail > 0) { - QLineF line(d->center.toQPointF(), pStart); - line.setAngle(line.angle()+angle); - points.append(line.p2()); + sectionAngle.append(tail); } - } while (i <= angle); + } + + for (int i = 0; i < sectionAngle.size(); ++i) + { + const qreal lDistance = GetRadius() * 4.0/3.0 * qTan(M_PI/180.0 * sectionAngle.at(i) * 0.25); + + const QPointF center = GetCenter().toQPointF(); + + QLineF lineP1P2(pStart, center); + lineP1P2.setAngle(lineP1P2.angle() - 90.0); + lineP1P2.setLength(lDistance); + + QLineF lineP4P3(center, pStart); + lineP4P3.setAngle(lineP4P3.angle() + sectionAngle.at(i)); + lineP4P3.setLength(GetRadius());//in case of computing error + lineP4P3 = QLineF(lineP4P3.p2(), center); + lineP4P3.setAngle(lineP4P3.angle() + 90.0); + lineP4P3.setLength(lDistance); + + VSpline spl(VPointF(pStart), lineP1P2.p2(), lineP4P3.p2(), VPointF(lineP4P3.p1()), 1.0); + QVector splPoints = spl.GetPoints(); + if (not splPoints.isEmpty() && i != sectionAngle.size() - 1) + { + splPoints.removeLast(); + } + + points << splPoints; + pStart = lineP4P3.p1(); + } return points; } diff --git a/src/test/ValentinaTest/tst_varc.cpp b/src/test/ValentinaTest/tst_varc.cpp index bc5760fd5..2f56ae3cb 100644 --- a/src/test/ValentinaTest/tst_varc.cpp +++ b/src/test/ValentinaTest/tst_varc.cpp @@ -89,91 +89,78 @@ void TST_VArc::TestGetPoints_data() QTest::newRow("Full circle: radius 1500") << 1500.0 << 0.0 << 360.0; QTest::newRow("Full circle: radius 50000") << 50000.0 << 0.0 << 360.0; QTest::newRow("Full circle: radius 90000") << 90000.0 << 0.0 << 360.0; - QTest::newRow("Full circle: radius 900000") << 900000.0 << 0.0 << 360.0; QTest::newRow("Arc less than 45 degree, radius 100") << 100.0 << 0.0 << 10.5; QTest::newRow("Arc less than 45 degree, radius 150") << 150.0 << 0.0 << 10.5; QTest::newRow("Arc less than 45 degree, radius 1500") << 1500.0 << 0.0 << 10.5; QTest::newRow("Arc less than 45 degree, radius 50000") << 50000.0 << 0.0 << 10.5; QTest::newRow("Arc less than 45 degree, radius 90000") << 90000.0 << 0.0 << 10.5; - QTest::newRow("Arc less than 45 degree, radius 900000") << 900000.0 << 0.0 << 10.5; QTest::newRow("Arc 45 degree, radius 100") << 100.0 << 0.0 << 45.0; QTest::newRow("Arc 45 degree, radius 150") << 150.0 << 0.0 << 45.0; QTest::newRow("Arc 45 degree, radius 1500") << 1500.0 << 0.0 << 45.0; QTest::newRow("Arc 45 degree, radius 50000") << 50000.0 << 0.0 << 45.0; QTest::newRow("Arc 45 degree, radius 90000") << 90000.0 << 0.0 << 45.0; - QTest::newRow("Arc 45 degree, radius 900000") << 900000.0 << 0.0 << 45.0; QTest::newRow("Arc less than 90 degree, radius 100") << 100.0 << 0.0 << 75.0; QTest::newRow("Arc less than 90 degree, radius 150") << 150.0 << 0.0 << 75.0; QTest::newRow("Arc less than 90 degree, radius 1500") << 1500.0 << 0.0 << 75.0; QTest::newRow("Arc less than 90 degree, radius 50000") << 50000.0 << 0.0 << 75.0; QTest::newRow("Arc less than 90 degree, radius 90000") << 90000.0 << 0.0 << 75.0; - QTest::newRow("Arc less than 90 degree, radius 900000") << 900000.0 << 0.0 << 75.0; QTest::newRow("Arc 90 degree, radius 100") << 100.0 << 0.0 << 90.0; QTest::newRow("Arc 90 degree, radius 150") << 150.0 << 0.0 << 90.0; QTest::newRow("Arc 90 degree, radius 1500") << 1500.0 << 0.0 << 90.0; QTest::newRow("Arc 90 degree, radius 50000") << 50000.0 << 0.0 << 90.0; QTest::newRow("Arc 90 degree, radius 90000") << 90000.0 << 0.0 << 90.0; - QTest::newRow("Arc 90 degree, radius 900000") << 900000.0 << 0.0 << 90.0; QTest::newRow("Arc less than 135 degree, radius 100") << 100.0 << 0.0 << 110.6; QTest::newRow("Arc less than 135 degree, radius 150") << 150.0 << 0.0 << 110.6; QTest::newRow("Arc less than 135 degree, radius 1500") << 1500.0 << 0.0 << 110.6; QTest::newRow("Arc less than 135 degree, radius 50000") << 50000.0 << 0.0 << 110.6; QTest::newRow("Arc less than 135 degree, radius 90000") << 90000.0 << 0.0 << 110.6; - QTest::newRow("Arc less than 135 degree, radius 900000") << 900000.0 << 0.0 << 110.6; QTest::newRow("Arc 135 degree, radius 100") << 100.0 << 0.0 << 135.0; QTest::newRow("Arc 135 degree, radius 150") << 150.0 << 0.0 << 135.0; QTest::newRow("Arc 135 degree, radius 1500") << 1500.0 << 0.0 << 135.0; QTest::newRow("Arc 135 degree, radius 50000") << 50000.0 << 0.0 << 135.0; QTest::newRow("Arc 135 degree, radius 90000") << 90000.0 << 0.0 << 135.0; - QTest::newRow("Arc 135 degree, radius 900000") << 900000.0 << 0.0 << 135.0; QTest::newRow("Arc less than 180 degree, radius 100") << 100.0 << 0.0 << 160.7; QTest::newRow("Arc less than 180 degree, radius 150") << 150.0 << 0.0 << 160.7; QTest::newRow("Arc less than 180 degree, radius 1500") << 1500.0 << 0.0 << 160.7; QTest::newRow("Arc less than 180 degree, radius 50000") << 50000.0 << 0.0 << 160.7; QTest::newRow("Arc less than 180 degree, radius 90000") << 90000.0 << 0.0 << 160.7; - QTest::newRow("Arc less than 180 degree, radius 900000") << 900000.0 << 0.0 << 160.7; QTest::newRow("Arc 180 degree, radius 100") << 100.0 << 0.0 << 180.0; QTest::newRow("Arc 180 degree, radius 150") << 150.0 << 0.0 << 180.0; QTest::newRow("Arc 180 degree, radius 1500") << 1500.0 << 0.0 << 180.0; QTest::newRow("Arc 180 degree, radius 50000") << 50000.0 << 0.0 << 180.0; QTest::newRow("Arc 180 degree, radius 90000") << 90000.0 << 0.0 << 180.0; - QTest::newRow("Arc 180 degree, radius 900000") << 900000.0 << 0.0 << 180.0; QTest::newRow("Arc less than 270 degree, radius 100") << 100.0 << 0.0 << 150.3; QTest::newRow("Arc less than 270 degree, radius 150") << 150.0 << 0.0 << 150.3; QTest::newRow("Arc less than 270 degree, radius 1500") << 1500.0 << 0.0 << 150.3; QTest::newRow("Arc less than 270 degree, radius 50000") << 50000.0 << 0.0 << 150.3; QTest::newRow("Arc less than 270 degree, radius 90000") << 90000.0 << 0.0 << 150.3; - QTest::newRow("Arc less than 270 degree, radius 900000") << 900000.0 << 0.0 << 150.3; QTest::newRow("Arc 270 degree, radius 100") << 100.0 << 0.0 << 270.0; QTest::newRow("Arc 270 degree, radius 150") << 150.0 << 0.0 << 270.0; QTest::newRow("Arc 270 degree, radius 1500") << 1500.0 << 0.0 << 270.0; QTest::newRow("Arc 270 degree, radius 50000") << 50000.0 << 0.0 << 270.0; QTest::newRow("Arc 270 degree, radius 90000") << 90000.0 << 0.0 << 270.0; - QTest::newRow("Arc 270 degree, radius 900000") << 900000.0 << 0.0 << 270.0; QTest::newRow("Arc less than 360 degree, radius 100") << 100.0 << 0.0 << 340.0; QTest::newRow("Arc less than 360 degree, radius 150") << 150.0 << 0.0 << 340.0; QTest::newRow("Arc less than 360 degree, radius 1500") << 1500.0 << 0.0 << 340.0; QTest::newRow("Arc less than 360 degree, radius 50000") << 50000.0 << 0.0 << 340.0; QTest::newRow("Arc less than 360 degree, radius 90000") << 90000.0 << 0.0 << 340.0; - QTest::newRow("Arc less than 360 degree, radius 900000") << 900000.0 << 0.0 << 340.0; QTest::newRow("Arc start 90 degree, angle 45 degree, radius 100") << 100.0 << 90.0 << 135.0; QTest::newRow("Arc start 90 degree, angle 45 degree, radius 150") << 150.0 << 90.0 << 135.0; QTest::newRow("Arc start 90 degree, angle 45 degree, radius 1500") << 1500.0 << 90.0 << 135.0; QTest::newRow("Arc start 90 degree, angle 45 degree, radius 50000") << 50000.0 << 90.0 << 135.0; QTest::newRow("Arc start 90 degree, angle 45 degree, radius 90000") << 90000.0 << 90.0 << 135.0; - QTest::newRow("Arc start 90 degree, angle 45 degree, radius 900000") << 900000.0 << 90.0 << 135.0; } //--------------------------------------------------------------------------------------------------------------------- @@ -190,13 +177,15 @@ void TST_VArc::TestGetPoints() QVector points = arc.GetPoints(); { - const qreal epsRadius = 1.0; // computing error + const qreal epsRadius = 1.5; // computing error for (int i=0; i < points.size(); ++i) { QLineF rLine(center.toQPointF(), points.at(i)); - QVERIFY2(qAbs(rLine.length() - radius) <= epsRadius, - "Broken the first rule. All points should be on the same distance from the center."); + const qreal value = qAbs(rLine.length() - radius); + const QString errorMsg = QString("Broken the first rule. All points should be on the same distance from " + "the center. Error ='%1'.").arg(value); + QVERIFY2(value <= epsRadius, qUtf8Printable(errorMsg)); } } @@ -214,11 +203,11 @@ void TST_VArc::TestGetPoints() } // calculated squere - qreal cSquare = qAbs(VAbstractDetail::SumTrapezoids(points)/2.0); + const qreal cSquare = qAbs(VAbstractDetail::SumTrapezoids(points)/2.0); const qreal value = qAbs(gSquere - cSquare); const QString errorMsg = QString("Broken the second rule. Interpolation has too big computing error. Error ='%1'.").arg(value); - const qreal epsSquere = 1.0; // computing error + const qreal epsSquere = gSquere * 0.24 / 100; // computing error 0.24 % from origin squere QVERIFY2(value <= epsSquere, qUtf8Printable(errorMsg)); } }