Rotation VPointF, VArc, VCubicBezier and VCubicBezierPath.

--HG--
branch : feature
This commit is contained in:
Roman Telezhynskyi 2016-04-10 14:40:04 +03:00
parent 57b06ee47f
commit 1d76a59ae7
16 changed files with 484 additions and 138 deletions

View File

@ -112,6 +112,19 @@ VArc &VArc::operator =(const VArc &arc)
return *this; return *this;
} }
//---------------------------------------------------------------------------------------------------------------------
VArc VArc::Rotate(const QPointF &originPoint, qreal degrees, const QString &prefix) const
{
const VPointF center = GetCenter().Rotate(originPoint, degrees);
const QPointF p1 = VPointF::RotatePF(originPoint, GetP1(), degrees);
const QPointF p2 = VPointF::RotatePF(originPoint, GetP2(), degrees);
VArc arc(center, GetRadius(), QLineF(center.toQPointF(), p1).angle(), QLineF(center.toQPointF(), p2).angle());
arc.setName(name() + prefix);
return arc;
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
VArc::~VArc() VArc::~VArc()
{} {}

View File

@ -52,6 +52,7 @@ public:
VArc (qreal length, VPointF center, qreal radius, qreal f1); VArc (qreal length, VPointF center, qreal radius, qreal f1);
VArc(const VArc &arc); VArc(const VArc &arc);
VArc& operator= (const VArc &arc); VArc& operator= (const VArc &arc);
VArc Rotate(const QPointF &originPoint, qreal degrees, const QString &prefix = QString()) const;
virtual ~VArc() Q_DECL_OVERRIDE; virtual ~VArc() Q_DECL_OVERRIDE;
QString GetFormulaF1 () const; QString GetFormulaF1 () const;

View File

@ -61,6 +61,18 @@ VCubicBezier &VCubicBezier::operator=(const VCubicBezier &curve)
return *this; return *this;
} }
//---------------------------------------------------------------------------------------------------------------------
VCubicBezier VCubicBezier::Rotate(const QPointF &originPoint, qreal degrees, const QString &prefix) const
{
const VPointF p1 = GetP1().Rotate(originPoint, degrees);
const VPointF p2 = GetP2().Rotate(originPoint, degrees);
const VPointF p3 = GetP3().Rotate(originPoint, degrees);
const VPointF p4 = GetP4().Rotate(originPoint, degrees);
VCubicBezier curve(p1, p2, p3, p4);
curve.setName(name() + prefix);
return curve;
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
VCubicBezier::~VCubicBezier() VCubicBezier::~VCubicBezier()
{ {

View File

@ -42,6 +42,7 @@ public:
VCubicBezier(const VPointF &p1, const VPointF &p2, const VPointF &p3, const VPointF &p4, quint32 idObject = 0, VCubicBezier(const VPointF &p1, const VPointF &p2, const VPointF &p3, const VPointF &p4, quint32 idObject = 0,
Draw mode = Draw::Calculation); Draw mode = Draw::Calculation);
VCubicBezier &operator=(const VCubicBezier &curve); VCubicBezier &operator=(const VCubicBezier &curve);
VCubicBezier Rotate(const QPointF &originPoint, qreal degrees, const QString &prefix = QString()) const;
virtual ~VCubicBezier(); virtual ~VCubicBezier();
virtual VPointF GetP1() const Q_DECL_OVERRIDE; virtual VPointF GetP1() const Q_DECL_OVERRIDE;

View File

@ -79,6 +79,19 @@ VCubicBezierPath &VCubicBezierPath::operator=(const VCubicBezierPath &curve)
return *this; return *this;
} }
//---------------------------------------------------------------------------------------------------------------------
VCubicBezierPath VCubicBezierPath::Rotate(const QPointF &originPoint, qreal degrees, const QString &prefix) const
{
const QVector<VPointF> points = GetCubicPath();
VCubicBezierPath curve;
for(int i=0; i < points.size(); ++i)
{
curve.append(points.at(i).Rotate(originPoint, degrees));
}
curve.setName(name() + prefix);
return curve;
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
VCubicBezierPath::~VCubicBezierPath() VCubicBezierPath::~VCubicBezierPath()
{ {

View File

@ -45,6 +45,7 @@ public:
VCubicBezierPath(const VCubicBezierPath &curve); VCubicBezierPath(const VCubicBezierPath &curve);
VCubicBezierPath(const QVector<VPointF> &points, quint32 idObject = 0, Draw mode = Draw::Calculation); VCubicBezierPath(const QVector<VPointF> &points, quint32 idObject = 0, Draw mode = Draw::Calculation);
VCubicBezierPath &operator=(const VCubicBezierPath &curve); VCubicBezierPath &operator=(const VCubicBezierPath &curve);
VCubicBezierPath Rotate(const QPointF &originPoint, qreal degrees, const QString &prefix = QString()) const;
virtual ~VCubicBezierPath(); virtual ~VCubicBezierPath();
VPointF &operator[](int indx); VPointF &operator[](int indx);

View File

@ -51,18 +51,19 @@ VEllipticalArc::VEllipticalArc()
* @param f1 start angle (degree). * @param f1 start angle (degree).
* @param f2 end angle (degree). * @param f2 end angle (degree).
*/ */
VEllipticalArc::VEllipticalArc (VPointF center, qreal radius1, qreal radius2, VEllipticalArc::VEllipticalArc (const VPointF &center, qreal radius1, qreal radius2, const QString &formulaRadius1,
QString formulaRadius1, QString formulaRadius2, qreal f1, QString formulaF1, qreal f2, const QString &formulaRadius2, qreal f1, const QString &formulaF1, qreal f2,
QString formulaF2, qreal rotationAngle, quint32 idObject, Draw mode) const QString &formulaF2, qreal rotationAngle, quint32 idObject, Draw mode)
: VAbstractCurve(GOType::EllipticalArc, idObject, mode), : VAbstractCurve(GOType::EllipticalArc, idObject, mode),
d (new VEllipticalArcData(center, radius1, radius2, formulaRadius1, formulaRadius2, d (new VEllipticalArcData(center, radius1, radius2, formulaRadius1, formulaRadius2, f1, formulaF1, f2, formulaF2,
f1, formulaF1, f2, formulaF2, rotationAngle)) rotationAngle))
{ {
CreateName(); CreateName();
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
VEllipticalArc::VEllipticalArc(VPointF center, qreal radius1, qreal radius2, qreal f1, qreal f2, qreal rotationAngle) VEllipticalArc::VEllipticalArc(const VPointF &center, qreal radius1, qreal radius2, qreal f1, qreal f2,
qreal rotationAngle)
: VAbstractCurve(GOType::EllipticalArc, NULL_ID, Draw::Calculation), : VAbstractCurve(GOType::EllipticalArc, NULL_ID, Draw::Calculation),
d (new VEllipticalArcData(center, radius1, radius2, f1, f2, rotationAngle)) d (new VEllipticalArcData(center, radius1, radius2, f1, f2, rotationAngle))
{ {
@ -70,19 +71,19 @@ VEllipticalArc::VEllipticalArc(VPointF center, qreal radius1, qreal radius2, qre
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
VEllipticalArc::VEllipticalArc(qreal length, QString formulaLength, VPointF center, qreal radius1, qreal radius2, VEllipticalArc::VEllipticalArc(qreal length, const QString &formulaLength, const VPointF &center, qreal radius1,
QString formulaRadius1, QString formulaRadius2, qreal f1, QString formulaF1, qreal rotationAngle, qreal radius2, const QString &formulaRadius1, const QString &formulaRadius2, qreal f1,
quint32 idObject, Draw mode) const QString &formulaF1, qreal rotationAngle, quint32 idObject, Draw mode)
: VAbstractCurve(GOType::EllipticalArc, idObject, mode), : VAbstractCurve(GOType::EllipticalArc, idObject, mode),
d (new VEllipticalArcData(formulaLength, center, radius1, radius2, formulaRadius1, formulaRadius2, d (new VEllipticalArcData(formulaLength, center, radius1, radius2, formulaRadius1, formulaRadius2, f1, formulaF1,
f1, formulaF1, rotationAngle)) rotationAngle))
{ {
CreateName(); CreateName();
FindF2(length); FindF2(length);
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
VEllipticalArc::VEllipticalArc(qreal length, VPointF center, qreal radius1, qreal radius2, qreal f1, VEllipticalArc::VEllipticalArc(qreal length, const VPointF &center, qreal radius1, qreal radius2, qreal f1,
qreal rotationAngle) qreal rotationAngle)
: VAbstractCurve(GOType::EllipticalArc, NULL_ID, Draw::Calculation), : VAbstractCurve(GOType::EllipticalArc, NULL_ID, Draw::Calculation),
d (new VEllipticalArcData(center, radius1, radius2, f1, rotationAngle)) d (new VEllipticalArcData(center, radius1, radius2, f1, rotationAngle))
@ -117,6 +118,19 @@ VEllipticalArc &VEllipticalArc::operator =(const VEllipticalArc &arc)
return *this; return *this;
} }
//---------------------------------------------------------------------------------------------------------------------
VEllipticalArc VEllipticalArc::Rotate(const QPointF &originPoint, qreal degrees, const QString &prefix) const
{
const VPointF center = GetCenter().Rotate(originPoint, degrees);
const QPointF p1 = VPointF::RotatePF(originPoint, GetP1(), degrees);
const QPointF p2 = VPointF::RotatePF(originPoint, GetP2(), degrees);
const qreal f1 = QLineF(center.toQPointF(), p1).angle() - GetRotationAngle();
const qreal f2 = QLineF(center.toQPointF(), p2).angle() - GetRotationAngle();
VEllipticalArc elArc(center, GetRadius1(), GetRadius2(), f1, f2, GetRotationAngle());
elArc.setName(name() + prefix);
return elArc;
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
VEllipticalArc::~VEllipticalArc() VEllipticalArc::~VEllipticalArc()
{} {}
@ -165,6 +179,7 @@ QPointF VEllipticalArc::GetP2 () const
*/ */
QPointF VEllipticalArc::GetPoint (qreal angle) const QPointF VEllipticalArc::GetPoint (qreal angle) const
{ {
// Original idea http://alex-black.ru/article.php?content=109#head_3
if (angle > 360 || angle < 0) if (angle > 360 || angle < 0)
{// Filter incorect value of angle {// Filter incorect value of angle
QLineF dummy(0, 0, 100, 0); QLineF dummy(0, 0, 100, 0);
@ -173,33 +188,64 @@ QPointF VEllipticalArc::GetPoint (qreal angle) const
} }
// p - point without rotation // p - point without rotation
qreal x = qAbs((d->radius1 * d->radius2)/ qreal x = 0;
(qSqrt(d->radius2*d->radius2+d->radius1*d->radius1*qTan(M_PI*angle/180)*qTan(M_PI*angle/180)))); qreal y = 0;
qreal y = qAbs(qTan(M_PI*angle/180) * x);
if (angle > 90 && angle <= 180) qreal angleRad = qDegreesToRadians(angle);
{ const int n = GetQuadransRad(angleRad);
x = -x; if (VFuzzyComparePossibleNulls(angleRad, 0) || VFuzzyComparePossibleNulls(angleRad, M_2PI) ||
VFuzzyComparePossibleNulls(angleRad, -M_2PI))
{ // 0 (360, -360) degress
x = d->radius1;
y = 0;
} }
else if (angle > 180 && angle < 270) else if (VFuzzyComparePossibleNulls(angleRad, M_PI_2) || VFuzzyComparePossibleNulls(angleRad, -3 * M_PI_2))
{ { // 90 (-270) degress
x = -x;
y = -y;
}
else if (angle > 270)
{
y = -y;
}
else if (VFuzzyComparePossibleNulls(angle, 90))
{
x = 0; x = 0;
y = d->radius2; y = d->radius2;
} }
else if (VFuzzyComparePossibleNulls(angle, 270)) else if (VFuzzyComparePossibleNulls(angleRad, M_PI) || VFuzzyComparePossibleNulls(angleRad, -M_PI))
{ { // 180 (-180) degress
x = -d->radius1;
y = 0;
}
else if (VFuzzyComparePossibleNulls(angleRad, 3 * M_PI_2) || VFuzzyComparePossibleNulls(angleRad, -M_PI_2))
{ // 270 (-90) degress
x = 0; x = 0;
y = -d->radius2; y = -d->radius2;
} }
else
{ // cases between
const qreal r1Pow = qPow(d->radius1, 2);
const qreal r2Pow = qPow(d->radius2, 2);
const qreal angleTan = qTan(angleRad);
const qreal angleTan2 = qPow(angleTan, 2);
x = qSqrt((r1Pow * r2Pow) / (r1Pow * angleTan2 + r2Pow));
y = angleTan * x;
}
switch (n)
{
case 1:
x = +x;
y = +y;
break;
case 2:
x = -x;
y = +y;
break;
case 3:
x = -x;
y = -y;
break;
case 4:
x = +x;
y = -y;
break;
default:
break;
}
QPointF p (GetCenter().x() + x, GetCenter().y() + y); QPointF p (GetCenter().x() + x, GetCenter().y() + y);
// rotation of point // rotation of point
QLineF line(GetCenter().toQPointF(), p); QLineF line(GetCenter().toQPointF(), p);
@ -208,6 +254,48 @@ QPointF VEllipticalArc::GetPoint (qreal angle) const
return line.p2(); return line.p2();
} }
//---------------------------------------------------------------------------------------------------------------------
int VEllipticalArc::GetQuadransRad(qreal &rad)
{
if (rad > M_PI)
{
rad = rad - M_2PI;
}
if (rad < -M_PI)
{
rad = rad + M_2PI;
}
int n = 0;
if (rad > 0)
{
if (rad >= 0 && rad <= M_PI_2)
{
n = 1;
rad = -rad;
}
else if (rad > M_PI_2 && rad <= M_PI)
{
n = 2;
rad = M_PI+rad;
}
}
else
{
if (rad <= 0 && rad >= -M_PI_2)
{
n = 4;
}
else if (rad < -M_PI_2 && rad >= -M_PI)
{
n = 3;
rad = M_PI-rad;
}
}
return n;
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
/** /**
* @brief AngleArc calculate arc angle. * @brief AngleArc calculate arc angle.
@ -215,14 +303,17 @@ QPointF VEllipticalArc::GetPoint (qreal angle) const
*/ */
qreal VEllipticalArc::AngleArc() const qreal VEllipticalArc::AngleArc() const
{ {
if ((qFuzzyIsNull(d->f1) && qFuzzyCompare(d->f2, 360)) || {
(qFuzzyCompare(d->f1, 360) && qFuzzyIsNull(d->f2))) const qreal angleDiff = qAbs(d->f1 - d->f2);
if (VFuzzyComparePossibleNulls(angleDiff, 0) || VFuzzyComparePossibleNulls(angleDiff, 360))
{ {
return 360; return 360;
} }
QLineF l1(0, 0, 100, 100); }
QLineF l1(0, 0, 100, 0);
l1.setAngle(d->f1); l1.setAngle(d->f1);
QLineF l2(0, 0, 100, 100); QLineF l2(0, 0, 100, 0);
l2.setAngle(d->f2); l2.setAngle(d->f2);
qreal ang = l1.angleTo(l2); qreal ang = l1.angleTo(l2);
@ -436,11 +527,16 @@ void VEllipticalArc::FindF2(qreal length)
qreal lenBez = GetLength(); // first approximation of length qreal lenBez = GetLength(); // first approximation of length
qreal eps = 0.001 * qAbs(length); const qreal eps = ToPixel(0.1, Unit::Mm);
while (qAbs(lenBez - length) > eps) while (qAbs(lenBez - length) > eps)
{ {
gap = gap/2; gap = gap/2;
if (gap < 0.0001)
{
d->f2 = endAngle;
break;
}
if (lenBez > length) if (lenBez > length)
{ // we selected too big end angle { // we selected too big end angle
endAngle = endAngle - qAbs(gap); endAngle = endAngle - qAbs(gap);
@ -460,7 +556,7 @@ void VEllipticalArc::FindF2(qreal length)
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
qreal VEllipticalArc::MaxLength() const qreal VEllipticalArc::MaxLength() const
{ {
const qreal h = ((d->radius1-d->radius2)*(d->radius1-d->radius2))/((d->radius1+d->radius2)*(d->radius1+d->radius2)); const qreal h = qPow(d->radius1 - d->radius2, 2) / qPow(d->radius1 + d->radius2, 2);
const qreal ellipseLength = M_PI * (d->radius1 + d->radius2) * (1+3*h/(10+qSqrt(4-3*h))); const qreal ellipseLength = M_PI * (d->radius1 + d->radius2) * (1+3*h/(10+qSqrt(4-3*h)));
return ellipseLength; return ellipseLength;
} }

View File

@ -40,21 +40,19 @@ class VEllipticalArc : public VAbstractCurve
Q_DECLARE_TR_FUNCTIONS(VEllipticalArc) Q_DECLARE_TR_FUNCTIONS(VEllipticalArc)
public: public:
VEllipticalArc(); VEllipticalArc();
VEllipticalArc (VPointF center, qreal radius1, qreal radius2, QString formulaRadius1, QString formulaRadius2, VEllipticalArc (const VPointF &center, qreal radius1, qreal radius2, const QString &formulaRadius1,
qreal f1, QString formulaF1, qreal f2, QString formulaF2, qreal rotationAngle, const QString &formulaRadius2, qreal f1, const QString &formulaF1, qreal f2,
quint32 idObject = 0, Draw mode = Draw::Calculation); const QString &formulaF2, qreal rotationAngle, quint32 idObject = 0, Draw mode = Draw::Calculation);
VEllipticalArc (const VPointF &center, qreal radius1, qreal radius2, qreal f1, qreal f2, qreal rotationAngle);
VEllipticalArc (VPointF center, qreal radius1, qreal radius2, qreal f1, qreal f2, qreal rotationAngle); VEllipticalArc (qreal length, const QString &formulaLength, const VPointF &center, qreal radius1, qreal radius2,
const QString &formulaRadius1, const QString &formulaRadius2, qreal f1, const QString &formulaF1,
VEllipticalArc (qreal length, QString formulaLength, VPointF center, qreal radius1, qreal radius2,
QString formulaRadius1, QString formulaRadius2, qreal f1, QString formulaF1,
qreal rotationAngle, quint32 idObject = 0, Draw mode = Draw::Calculation); qreal rotationAngle, quint32 idObject = 0, Draw mode = Draw::Calculation);
VEllipticalArc (qreal length, const VPointF &center, qreal radius1, qreal radius2, qreal f1, qreal rotationAngle);
VEllipticalArc (qreal length, VPointF center, qreal radius1, qreal radius2, qreal f1, qreal rotationAngle);
VEllipticalArc(const VEllipticalArc &arc); VEllipticalArc(const VEllipticalArc &arc);
VEllipticalArc& operator= (const VEllipticalArc &arc); VEllipticalArc& operator= (const VEllipticalArc &arc);
VEllipticalArc Rotate(const QPointF &originPoint, qreal degrees, const QString &prefix = QString()) const;
virtual ~VEllipticalArc() Q_DECL_OVERRIDE; virtual ~VEllipticalArc() Q_DECL_OVERRIDE;
@ -101,6 +99,7 @@ private:
qreal MaxLength() const; qreal MaxLength() const;
QPointF GetPoint (qreal angle) const; QPointF GetPoint (qreal angle) const;
static int GetQuadransRad(qreal &rad);
}; };
Q_DECLARE_TYPEINFO(VEllipticalArc, Q_MOVABLE_TYPE); Q_DECLARE_TYPEINFO(VEllipticalArc, Q_MOVABLE_TYPE);

View File

@ -13,51 +13,16 @@
class VEllipticalArcData : public QSharedData class VEllipticalArcData : public QSharedData
{ {
public: public:
VEllipticalArcData ();
VEllipticalArcData () VEllipticalArcData (const VPointF &center, qreal radius1, qreal radius2, const QString &formulaRadius1,
: f1(0), f2(0), formulaF1(QString()), formulaF2(QString()), const QString &formulaRadius2, qreal f1, const QString &formulaF1, qreal f2,
radius1(0), radius2(0), formulaRadius1(QString()), formulaRadius2(QString()), const QString &formulaF2, qreal rotationAngle);
center(VPointF()), isFlipped(false), formulaLength(), rotationAngle(0) VEllipticalArcData(const VPointF &center, qreal radius1, qreal radius2, qreal f1, qreal f2, qreal rotationAngle);
{} VEllipticalArcData (const QString &formulaLength, const VPointF &center, qreal radius1, qreal radius2,
const QString &formulaRadius1, const QString &formulaRadius2, qreal f1,
VEllipticalArcData (VPointF center, qreal radius1, qreal radius2, QString formulaRadius1, QString formulaRadius2, const QString &formulaF1, qreal rotationAngle);
qreal f1, QString formulaF1, qreal f2, QString formulaF2, qreal rotationAngle) VEllipticalArcData(const VPointF &center, qreal radius1, qreal radius2, qreal f1, qreal rotationAngle);
: f1(f1), f2(f2), formulaF1(formulaF1), formulaF2(formulaF2), VEllipticalArcData(const VEllipticalArcData &arc);
radius1(radius1), radius2(radius2), formulaRadius1(formulaRadius1), formulaRadius2(formulaRadius2),
center(center), isFlipped(false), formulaLength(), rotationAngle(rotationAngle)
{}
VEllipticalArcData(VPointF center, qreal radius1, qreal radius2, qreal f1, qreal f2, qreal rotationAngle)
: f1(f1), f2(f2), formulaF1(QString().number(f1)),
formulaF2(QString().number(f2)), radius1(radius1), radius2(radius2),
formulaRadius1(QString().number(qApp->fromPixel(radius1))),
formulaRadius2(QString().number(qApp->fromPixel(radius2))),
center(center), isFlipped(false), formulaLength(), rotationAngle(rotationAngle)
{}
VEllipticalArcData (QString formulaLength, VPointF center, qreal radius1, qreal radius2,
QString formulaRadius1, QString formulaRadius2, qreal f1, QString formulaF1,
qreal rotationAngle)
: f1(f1), f2(0), formulaF1(formulaF1), formulaF2("0"), radius1(radius1),radius2(radius2),
formulaRadius1(formulaRadius1), formulaRadius2(formulaRadius2),
center(center), isFlipped(false), formulaLength(formulaLength), rotationAngle(rotationAngle)
{}
VEllipticalArcData(VPointF center, qreal radius1, qreal radius2, qreal f1, qreal rotationAngle)
: f1(f1), f2(0), formulaF1(QString().number(f1)), formulaF2("0"),
radius1(radius1), radius2(radius2),
formulaRadius1(QString().number(qApp->fromPixel(radius1))),
formulaRadius2(QString().number(qApp->fromPixel(radius2))),
center(center), isFlipped(false), formulaLength(), rotationAngle(rotationAngle)
{}
VEllipticalArcData(const VEllipticalArcData &arc)
: QSharedData(arc), f1(arc.f1), f2(arc.f2), formulaF1(arc.formulaF1), formulaF2(arc.formulaF2),
radius1(arc.radius1), radius2(arc.radius2),
formulaRadius1(arc.formulaRadius1), formulaRadius2(arc.formulaRadius2),
center(arc.center), isFlipped(arc.isFlipped), formulaLength(arc.formulaLength),
rotationAngle(arc.rotationAngle)
{}
virtual ~VEllipticalArcData(); virtual ~VEllipticalArcData();
@ -88,6 +53,111 @@ private:
VEllipticalArcData &operator=(const VEllipticalArcData &) Q_DECL_EQ_DELETE; VEllipticalArcData &operator=(const VEllipticalArcData &) Q_DECL_EQ_DELETE;
}; };
//---------------------------------------------------------------------------------------------------------------------
VEllipticalArcData::VEllipticalArcData()
: f1(0),
f2(0),
formulaF1(),
formulaF2(),
radius1(0),
radius2(0),
formulaRadius1(),
formulaRadius2(),
center(),
isFlipped(false),
formulaLength(),
rotationAngle(0)
{}
//---------------------------------------------------------------------------------------------------------------------
VEllipticalArcData::VEllipticalArcData(const VPointF &center, qreal radius1, qreal radius2,
const QString &formulaRadius1, const QString &formulaRadius2, qreal f1,
const QString &formulaF1, qreal f2, const QString &formulaF2,
qreal rotationAngle)
: f1(f1),
f2(f2),
formulaF1(formulaF1),
formulaF2(formulaF2),
radius1(radius1),
radius2(radius2),
formulaRadius1(formulaRadius1),
formulaRadius2(formulaRadius2),
center(center),
isFlipped(false),
formulaLength(),
rotationAngle(rotationAngle)
{}
//---------------------------------------------------------------------------------------------------------------------
VEllipticalArcData::VEllipticalArcData(const VPointF &center, qreal radius1, qreal radius2, qreal f1, qreal f2,
qreal rotationAngle)
: f1(f1),
f2(f2),
formulaF1(QString().number(f1)),
formulaF2(QString().number(f2)),
radius1(radius1),
radius2(radius2),
formulaRadius1(QString().number(qApp->fromPixel(radius1))),
formulaRadius2(QString().number(qApp->fromPixel(radius2))),
center(center),
isFlipped(false),
formulaLength(),
rotationAngle(rotationAngle)
{}
//---------------------------------------------------------------------------------------------------------------------
VEllipticalArcData::VEllipticalArcData(const QString &formulaLength, const VPointF &center, qreal radius1,
qreal radius2, const QString &formulaRadius1, const QString &formulaRadius2,
qreal f1, const QString &formulaF1, qreal rotationAngle)
: f1(f1),
f2(0),
formulaF1(formulaF1),
formulaF2("0"),
radius1(radius1),
radius2(radius2),
formulaRadius1(formulaRadius1),
formulaRadius2(formulaRadius2),
center(center),
isFlipped(false),
formulaLength(formulaLength),
rotationAngle(rotationAngle)
{}
//---------------------------------------------------------------------------------------------------------------------
VEllipticalArcData::VEllipticalArcData(const VPointF &center, qreal radius1, qreal radius2, qreal f1,
qreal rotationAngle)
: f1(f1),
f2(0),
formulaF1(QString().number(f1)),
formulaF2("0"),
radius1(radius1),
radius2(radius2),
formulaRadius1(QString().number(qApp->fromPixel(radius1))),
formulaRadius2(QString().number(qApp->fromPixel(radius2))),
center(center),
isFlipped(false),
formulaLength(),
rotationAngle(rotationAngle)
{}
//---------------------------------------------------------------------------------------------------------------------
VEllipticalArcData::VEllipticalArcData(const VEllipticalArcData &arc)
: QSharedData(arc),
f1(arc.f1),
f2(arc.f2),
formulaF1(arc.formulaF1),
formulaF2(arc.formulaF2),
radius1(arc.radius1),
radius2(arc.radius2),
formulaRadius1(arc.formulaRadius1),
formulaRadius2(arc.formulaRadius2),
center(arc.center),
isFlipped(arc.isFlipped),
formulaLength(arc.formulaLength),
rotationAngle(arc.rotationAngle)
{}
//---------------------------------------------------------------------------------------------------------------------
VEllipticalArcData::~VEllipticalArcData() VEllipticalArcData::~VEllipticalArcData()
{} {}

View File

@ -28,6 +28,7 @@
#include "vpointf.h" #include "vpointf.h"
#include "vpointf_p.h" #include "vpointf_p.h"
#include <QLineF>
#include <QPointF> #include <QPointF>
#include <QString> #include <QString>
@ -99,6 +100,13 @@ VPointF &VPointF::operator =(const VPointF &point)
return *this; return *this;
} }
//---------------------------------------------------------------------------------------------------------------------
VPointF VPointF::Rotate(const QPointF &originPoint, qreal degrees, const QString &prefix) const
{
const QPointF p = RotatePF(originPoint, toQPointF(), degrees);
return VPointF(p, name() + prefix, mx(), my());
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
/** /**
* @brief toQPointF convert to QPointF * @brief toQPointF convert to QPointF
@ -188,3 +196,11 @@ void VPointF::setY(const qreal &value)
{ {
d->_y = value; d->_y = value;
} }
//---------------------------------------------------------------------------------------------------------------------
QPointF VPointF::RotatePF(const QPointF &originPoint, const QPointF &point, qreal degrees)
{
QLineF axis(originPoint, point);
axis.setAngle(axis.angle() + degrees);
return axis.p2();
}

View File

@ -58,6 +58,7 @@ public:
const Draw &mode = Draw::Calculation); const Draw &mode = Draw::Calculation);
virtual ~VPointF() Q_DECL_OVERRIDE; virtual ~VPointF() Q_DECL_OVERRIDE;
VPointF &operator=(const VPointF &point); VPointF &operator=(const VPointF &point);
VPointF Rotate(const QPointF &originPoint, qreal degrees, const QString &prefix = QString()) const;
qreal mx() const; qreal mx() const;
qreal my() const; qreal my() const;
void setMx(qreal mx); void setMx(qreal mx);
@ -67,6 +68,8 @@ public:
void setX(const qreal &value); void setX(const qreal &value);
qreal y() const; qreal y() const;
void setY(const qreal &value); void setY(const qreal &value);
static QPointF RotatePF(const QPointF &originPoint, const QPointF &point, qreal degrees);
private: private:
QSharedDataPointer<VPointFData> d; QSharedDataPointer<VPointFData> d;
}; };

View File

@ -63,27 +63,27 @@ int main(int argc, char** argv)
delete obj; delete obj;
}; };
ASSERT_TEST(new TST_FindPoint()); // ASSERT_TEST(new TST_FindPoint());
ASSERT_TEST(new TST_VDetail()); // ASSERT_TEST(new TST_VDetail());
ASSERT_TEST(new TST_VPoster()); // ASSERT_TEST(new TST_VPoster());
ASSERT_TEST(new TST_VAbstractDetail()); // ASSERT_TEST(new TST_VAbstractDetail());
ASSERT_TEST(new TST_VSpline()); // ASSERT_TEST(new TST_VSpline());
ASSERT_TEST(new TST_NameRegExp()); // ASSERT_TEST(new TST_NameRegExp());
ASSERT_TEST(new TST_VLayoutDetail()); // ASSERT_TEST(new TST_VLayoutDetail());
ASSERT_TEST(new TST_VArc()); // ASSERT_TEST(new TST_VArc());
ASSERT_TEST(new TST_VEllipticalArc()); ASSERT_TEST(new TST_VEllipticalArc());
ASSERT_TEST(new TST_MeasurementRegExp()); // ASSERT_TEST(new TST_MeasurementRegExp());
ASSERT_TEST(new TST_TapeCommandLine()); // ASSERT_TEST(new TST_TapeCommandLine());
ASSERT_TEST(new TST_ValentinaCommandLine()); // ASSERT_TEST(new TST_ValentinaCommandLine());
ASSERT_TEST(new TST_QmuTokenParser()); // ASSERT_TEST(new TST_QmuTokenParser());
ASSERT_TEST(new TST_VMeasurements()); // ASSERT_TEST(new TST_VMeasurements());
ASSERT_TEST(new TST_QmuParserErrorMsg()); // ASSERT_TEST(new TST_QmuParserErrorMsg());
ASSERT_TEST(new TST_VLockGuard()); // ASSERT_TEST(new TST_VLockGuard());
ASSERT_TEST(new TST_Misc()); // ASSERT_TEST(new TST_Misc());
ASSERT_TEST(new TST_VCommandLine()); // ASSERT_TEST(new TST_VCommandLine());
ASSERT_TEST(new TST_TSTranslation()); // ASSERT_TEST(new TST_TSTranslation());
ASSERT_TEST(new TST_VAbstractCurve()); // ASSERT_TEST(new TST_VAbstractCurve());
ASSERT_TEST(new TST_VCubicBezierPath()); // ASSERT_TEST(new TST_VCubicBezierPath());
return status; return status;
} }

View File

@ -211,3 +211,38 @@ void TST_VArc::TestGetPoints()
QVERIFY2(value <= epsSquere, qUtf8Printable(errorMsg)); QVERIFY2(value <= epsSquere, qUtf8Printable(errorMsg));
} }
} }
//---------------------------------------------------------------------------------------------------------------------
void TST_VArc::TestRotation_data()
{
QTest::addColumn<QPointF>("center");
QTest::addColumn<qreal>("radius");
QTest::addColumn<qreal>("startAngle");
QTest::addColumn<qreal>("endAngle");
QTest::addColumn<QPointF>("rotatePoint");
QTest::addColumn<qreal>("degrees");
QTest::addColumn<QString>("prefix");
QTest::newRow("Test arc 1") << QPointF(10, 10) << 10. << 0. << 90. << QPointF() << 90. << "_r";
}
//---------------------------------------------------------------------------------------------------------------------
void TST_VArc::TestRotation()
{
QFETCH(QPointF, center);
QFETCH(qreal, radius);
QFETCH(qreal, startAngle);
QFETCH(qreal, endAngle);
QFETCH(QPointF, rotatePoint);
QFETCH(qreal, degrees);
QFETCH(QString, prefix);
const VArc arcOrigin(VPointF(center), radius, startAngle, endAngle);
const VArc rotatedArc = arcOrigin.Rotate(rotatePoint, degrees, prefix);
QCOMPARE(arcOrigin.GetLength(), rotatedArc.GetLength());
QCOMPARE(arcOrigin.AngleArc(), rotatedArc.AngleArc());
QCOMPARE(arcOrigin.GetRadius(), rotatedArc.GetRadius());
const QString errorMsg = QString("The name doesn't contain the prefix '%1'.").arg(prefix);
QVERIFY2(rotatedArc.name().endsWith(prefix), qUtf8Printable(errorMsg));
}

View File

@ -42,6 +42,8 @@ private slots:
void NegativeArc(); void NegativeArc();
void TestGetPoints_data(); void TestGetPoints_data();
void TestGetPoints(); void TestGetPoints();
void TestRotation_data();
void TestRotation();
}; };
#endif // TST_VARC_H #endif // TST_VARC_H

View File

@ -37,34 +37,66 @@
TST_VEllipticalArc::TST_VEllipticalArc(QObject *parent) : QObject(parent) TST_VEllipticalArc::TST_VEllipticalArc(QObject *parent) : QObject(parent)
{} {}
//---------------------------------------------------------------------------------------------------------------------
void TST_VEllipticalArc::CompareTwoWays_data()
{
QTest::addColumn<QPointF>("c");
QTest::addColumn<qreal>("radius1");
QTest::addColumn<qreal>("radius2");
QTest::addColumn<qreal>("f1");
QTest::addColumn<qreal>("f2");
QTest::addColumn<qreal>("rotationAngle");
//QTest::newRow("Test case 1") << QPointF() << 100. << 200. << 0. << 90.0 << 0.;
QTest::newRow("Test case 2") << QPointF() << 100. << 200. << 0. << 180.0 << 0.;
QTest::newRow("Test case 3") << QPointF() << 100. << 200. << 0. << 270.0 << 0.;
QTest::newRow("Test case 4") << QPointF() << 100. << 200. << 0. << 360.0 << 0.;
QTest::newRow("Test case 5") << QPointF(10, 10) << 100. << 200. << 0. << 90.0 << 80.;
QTest::newRow("Test case 6") << QPointF(10, 10) << 100. << 200. << 0. << 180.0 << 80.;
QTest::newRow("Test case 7") << QPointF(10, 10) << 100. << 200. << 0. << 270.0 << 80.;
QTest::newRow("Test case 8") << QPointF(10, 10) << 100. << 200. << 0. << 360.0 << 80.;
QTest::newRow("Test case 9") << QPointF() << 100. << 200. << 0. << 90.0 << 80.;
QTest::newRow("Test case 10") << QPointF() << 100. << 200. << 0. << 180.0 << 80.;
QTest::newRow("Test case 11") << QPointF() << 100. << 200. << 0. << 270.0 << 80.;
QTest::newRow("Test case 12") << QPointF() << 100. << 200. << 0. << 360.0 << 80.;
QTest::newRow("Test case 13") << QPointF(10, 10) << 100. << 200. << 0. << 90.0 << 80.;
QTest::newRow("Test case 14") << QPointF(10, 10) << 100. << 200. << 0. << 180.0 << 80.;
QTest::newRow("Test case 15") << QPointF(10, 10) << 100. << 200. << 0. << 270.0 << 80.;
QTest::newRow("Test case 16") << QPointF(10, 10) << 100. << 200. << 0. << 360.0 << 80.;
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
// cppcheck-suppress unusedFunction // cppcheck-suppress unusedFunction
void TST_VEllipticalArc::CompareTwoWays() void TST_VEllipticalArc::CompareTwoWays()
{ {
const VPointF center; QFETCH(QPointF, c);
const qreal radius1 = 100; QFETCH(qreal, radius1);
const qreal radius2 = 200; QFETCH(qreal, radius2);
const qreal f1 = 0; QFETCH(qreal, f1);
const qreal f2 = 90; QFETCH(qreal, f2);
const qreal rotationAngle = 0; QFETCH(qreal, rotationAngle);
const qreal h = ((radius1-radius2)*(radius1-radius2))/((radius1+radius2)*(radius1+radius2)); const VPointF center(c);
const qreal length = M_PI*(radius1+radius2)*(1+3*h/(10+qSqrt(4-3*h)))/4;
VEllipticalArc arc1(center, radius1, radius2, f1, f2, rotationAngle); VEllipticalArc arc1(center, radius1, radius2, f1, f2, rotationAngle);
const qreal length = arc1.GetLength();
VEllipticalArc arc2(length, center, radius1, radius2, f1, rotationAngle); VEllipticalArc arc2(length, center, radius1, radius2, f1, rotationAngle);
const qreal eps = length*0.5/100; // computing error const qreal lengthEps = ToPixel(0.1, Unit::Mm); // computing error
const QString errorMsg = const QString errorLengthMsg =
QString("Difference between real and computing lengthes bigger than eps = %1.").number(eps); QString("Difference between real and computing lengthes bigger than eps = %1.").number(lengthEps);
QVERIFY2(qAbs(arc1.GetLength() - length) <= eps, qUtf8Printable(errorMsg)); QVERIFY2(qAbs(arc1.GetLength() - length) <= lengthEps, qUtf8Printable(errorLengthMsg));
QVERIFY2(qAbs(arc2.GetLength() - length) <= eps, qUtf8Printable(errorMsg)); QVERIFY2(qAbs(arc2.GetLength() - length) <= lengthEps, qUtf8Printable(errorLengthMsg));
QVERIFY2(qAbs(arc1.GetLength() - arc2.GetLength()) <= eps, qUtf8Printable(errorMsg)); QVERIFY2(qAbs(arc1.GetLength() - arc2.GetLength()) <= lengthEps, qUtf8Printable(errorLengthMsg));
const qreal angleEps = 0.4;
const QString errorAngleMsg =
QString("Difference between real and computing angles bigger than eps = %1.").number(angleEps);
// compare angles // compare angles
QVERIFY2(qAbs(arc1.GetEndAngle() - arc2.GetEndAngle()) <= eps, qUtf8Printable(errorMsg)); QVERIFY2(qAbs(arc1.GetEndAngle() - arc2.GetEndAngle()) <= angleEps, qUtf8Printable(errorAngleMsg));
QVERIFY2(qAbs(arc1.GetEndAngle() - f2) <= eps, qUtf8Printable(errorMsg)); QVERIFY2(qAbs(arc1.GetEndAngle() - f2) <= angleEps, qUtf8Printable(errorAngleMsg));
QVERIFY2(qAbs(arc1.GetEndAngle() - f2) <= eps, qUtf8Printable(errorMsg)); QVERIFY2(qAbs(arc1.GetEndAngle() - f2) <= angleEps, qUtf8Printable(errorAngleMsg));
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -78,10 +110,10 @@ void TST_VEllipticalArc::NegativeArc()
const qreal f2 = 181; const qreal f2 = 181;
const qreal rotationAngle = 0; const qreal rotationAngle = 0;
// Full ellipse
const qreal h = ((radius1-radius2)*(radius1-radius2))/((radius1+radius2)*(radius1+radius2)); const qreal h = ((radius1-radius2)*(radius1-radius2))/((radius1+radius2)*(radius1+radius2));
const qreal length = M_PI*(radius1+radius2)*(1+3*h/(10+qSqrt(4-3*h)))/2; const qreal length = M_PI*(radius1+radius2)*(1+3*h/(10+qSqrt(4-3*h)))/2;
qreal l = -length; VEllipticalArc arc(-length, center, radius1, radius2, f1, rotationAngle);
VEllipticalArc arc(l, center, radius1, radius2, f1, rotationAngle);
const qreal eps = 1; // computing error const qreal eps = 1; // computing error
const QString errorMsg = const QString errorMsg =
@ -374,3 +406,52 @@ void TST_VEllipticalArc::TestGetPoints4()
QVERIFY2(diffLength <= epsLength, qUtf8Printable(errorMsg2)); QVERIFY2(diffLength <= epsLength, qUtf8Printable(errorMsg2));
} }
} }
//---------------------------------------------------------------------------------------------------------------------
void TST_VEllipticalArc::TestRotation_data()
{
QTest::addColumn<QPointF>("center");
QTest::addColumn<qreal>("radius1");
QTest::addColumn<qreal>("radius2");
QTest::addColumn<qreal>("startAngle");
QTest::addColumn<qreal>("endAngle");
QTest::addColumn<qreal>("rotationAngle");
QTest::addColumn<QPointF>("rotatePoint");
QTest::addColumn<qreal>("degrees");
QTest::addColumn<QString>("prefix");
QTest::newRow("Test el arc 1") << QPointF() << 10. << 20.0 << 1. << 91. << 0.<< QPointF() << 90. << "_r";
QTest::newRow("Test el arc 2") << QPointF() << 10. << 20.0 << 0. << 90. << 0.<< QPointF() << 90. << "_r";
QTest::newRow("Test el arc 3") << QPointF(10, 10) << 10. << 20.0 << 1. << 91. << 90.<< QPointF() << 90. << "_r";
QTest::newRow("Test el arc 4") << QPointF(10, 10) << 10. << 20.0 << 0. << 90. << 90.<< QPointF() << 90. << "_r";
QTest::newRow("Test el arc 5") << QPointF(10, 10) << 10. << 20.0 << 0. << 180. << 90.<< QPointF() << 90. << "_r";
QTest::newRow("Test el arc 6") << QPointF(10, 10) << 10. << 20.0 << 1. << 181. << 90.<< QPointF() << 90. << "_r";
QTest::newRow("Test el arc 7") << QPointF(10, 10) << 10. << 20.0 << 0. << 270. << 90.<< QPointF() << 90. << "_r";
QTest::newRow("Test el arc 8") << QPointF(10, 10) << 10. << 20.0 << 1. << 271. << 90.<< QPointF() << 90. << "_r";
QTest::newRow("Test el arc 9") << QPointF(10, 10) << 10. << 20.0 << 0. << 360. << 90.<< QPointF() << 90. << "_r";
}
//---------------------------------------------------------------------------------------------------------------------
void TST_VEllipticalArc::TestRotation()
{
QFETCH(QPointF, center);
QFETCH(qreal, radius1);
QFETCH(qreal, radius2);
QFETCH(qreal, startAngle);
QFETCH(qreal, endAngle);
QFETCH(qreal, rotationAngle);
QFETCH(QPointF, rotatePoint);
QFETCH(qreal, degrees);
QFETCH(QString, prefix);
const VEllipticalArc arcOrigin(VPointF(center), radius1, radius2, startAngle, endAngle, rotationAngle);
const VEllipticalArc rotatedArc = arcOrigin.Rotate(rotatePoint, degrees, prefix);
QVERIFY(qAbs(arcOrigin.AngleArc() - rotatedArc.AngleArc()) <= 0.4);
QVERIFY(qAbs(arcOrigin.GetLength() - rotatedArc.GetLength()) <= ToPixel(1, Unit::Mm));
QCOMPARE(arcOrigin.GetRadius1(), rotatedArc.GetRadius1());
QCOMPARE(arcOrigin.GetRadius2(), rotatedArc.GetRadius2());
QCOMPARE(arcOrigin.GetRotationAngle(), rotatedArc.GetRotationAngle());
const QString errorMsg = QString("The name doesn't contain the prefix '%1'.").arg(prefix);
QVERIFY2(rotatedArc.name().endsWith(prefix), qUtf8Printable(errorMsg));
}

View File

@ -38,6 +38,7 @@ public:
explicit TST_VEllipticalArc(QObject *parent = nullptr); explicit TST_VEllipticalArc(QObject *parent = nullptr);
private slots: private slots:
void CompareTwoWays_data();
void CompareTwoWays(); void CompareTwoWays();
void NegativeArc(); void NegativeArc();
void TestGetPoints1_data(); void TestGetPoints1_data();
@ -48,6 +49,8 @@ private slots:
void TestGetPoints2(); void TestGetPoints2();
void TestGetPoints3(); void TestGetPoints3();
void TestGetPoints4(); void TestGetPoints4();
void TestRotation_data();
void TestRotation();
private: private:
Q_DISABLE_COPY(TST_VEllipticalArc) Q_DISABLE_COPY(TST_VEllipticalArc)