Improved calculation arc points.

--HG--
branch : develop
This commit is contained in:
Roman Telezhynskyi 2015-12-07 23:33:11 +02:00
parent 75701f8cad
commit 589bf173ae
2 changed files with 63 additions and 37 deletions

View file

@ -29,6 +29,7 @@
#include "varc.h"
#include "varc_p.h"
#include "../ifc/ifcdef.h"
#include "vspline.h"
#include <QDebug>
#include <QLineF>
@ -192,32 +193,68 @@ qreal VArc::AngleArc() const
QVector<QPointF> VArc::GetPoints() const
{
QVector<QPointF> points;
qreal i = 0;
const qreal angle = AngleArc();
const qint32 k = static_cast<qint32>(angle);
const qreal s = angle/(k/4); //-V636
do
QVector<qreal> 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<QPointF> splPoints = spl.GetPoints();
if (not splPoints.isEmpty() && i != sectionAngle.size() - 1)
{
splPoints.removeLast();
}
points << splPoints;
pStart = lineP4P3.p1();
}
return points;
}

View file

@ -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<QPointF> 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));
}
}