Fixed issue #753. Elliptical arc tool is broken.
(grafted from 6e388ecf0b095aa084889cbf6cc0461fedb18cd3) --HG-- branch : develop
This commit is contained in:
parent
6689fc89d7
commit
a8dc3ed9f0
|
@ -53,6 +53,7 @@
|
||||||
- [#744] Check for Updates button produces error.
|
- [#744] Check for Updates button produces error.
|
||||||
- Remove space as thousands separator when return formula to user.
|
- Remove space as thousands separator when return formula to user.
|
||||||
- [#752] Valentina produces corrupted file if unite two pieces.
|
- [#752] Valentina produces corrupted file if unite two pieces.
|
||||||
|
- [#753] Elliptical arc tool is broken.
|
||||||
|
|
||||||
# Version 0.5.0 May 9, 2017
|
# Version 0.5.0 May 9, 2017
|
||||||
- [#581] User can now filter input lists by keyword in function wizard.
|
- [#581] User can now filter input lists by keyword in function wizard.
|
||||||
|
|
|
@ -208,7 +208,7 @@ qreal VEllipticalArc::GetLength() const
|
||||||
*/
|
*/
|
||||||
QPointF VEllipticalArc::GetP1() const
|
QPointF VEllipticalArc::GetP1() const
|
||||||
{
|
{
|
||||||
return GetPoint(GetStartAngle());
|
return GetPoints().first();
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
@ -218,169 +218,7 @@ QPointF VEllipticalArc::GetP1() const
|
||||||
*/
|
*/
|
||||||
QPointF VEllipticalArc::GetP2 () const
|
QPointF VEllipticalArc::GetP2 () const
|
||||||
{
|
{
|
||||||
return GetPoint(GetEndAngle());
|
return GetPoints().last();
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
|
||||||
/**
|
|
||||||
* @brief GetPoint return point associated with angle.
|
|
||||||
* @return point.
|
|
||||||
*/
|
|
||||||
QPointF VEllipticalArc::GetPoint (qreal angle) const
|
|
||||||
{
|
|
||||||
// Original idea http://alex-black.ru/article.php?content=109#head_3
|
|
||||||
if (angle > 360 || angle < 0)
|
|
||||||
{// Filter incorect value of angle
|
|
||||||
QLineF dummy(0, 0, 100, 0);
|
|
||||||
dummy.setAngle(angle);
|
|
||||||
angle = dummy.angle();
|
|
||||||
}
|
|
||||||
|
|
||||||
// p - point without rotation
|
|
||||||
qreal x = 0;
|
|
||||||
qreal y = 0;
|
|
||||||
|
|
||||||
qreal angleRad = qDegreesToRadians(angle);
|
|
||||||
const int n = GetQuadransRad(angleRad);
|
|
||||||
if (VFuzzyComparePossibleNulls(angleRad, 0) || VFuzzyComparePossibleNulls(angleRad, M_2PI) ||
|
|
||||||
VFuzzyComparePossibleNulls(angleRad, -M_2PI))
|
|
||||||
{ // 0 (360, -360) degress
|
|
||||||
x = d->radius1;
|
|
||||||
y = 0;
|
|
||||||
}
|
|
||||||
else if (VFuzzyComparePossibleNulls(angleRad, M_PI_2) || VFuzzyComparePossibleNulls(angleRad, -3 * M_PI_2))
|
|
||||||
{ // 90 (-270) degress
|
|
||||||
x = 0;
|
|
||||||
y = d->radius2;
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
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);
|
|
||||||
// rotation of point
|
|
||||||
QLineF line(static_cast<QPointF>(GetCenter()), p);
|
|
||||||
line.setAngle(line.angle() + GetRotationAngle());
|
|
||||||
|
|
||||||
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 <= 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 >= -M_PI_2)
|
|
||||||
{
|
|
||||||
n = 4;
|
|
||||||
}
|
|
||||||
else if (rad < -M_PI_2 && rad >= -M_PI)
|
|
||||||
{
|
|
||||||
n = 3;
|
|
||||||
rad = M_PI-rad;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
|
||||||
/**
|
|
||||||
* @brief GetAngles return list of angles needed for drawing arc.
|
|
||||||
* @return list of angles
|
|
||||||
*/
|
|
||||||
QVector<qreal> VEllipticalArc::GetAngles() const
|
|
||||||
{
|
|
||||||
QVector<qreal> sectionAngle;
|
|
||||||
qreal angle = AngleArc();
|
|
||||||
|
|
||||||
if (qFuzzyIsNull(angle))
|
|
||||||
{// Return the array that includes one angle
|
|
||||||
sectionAngle.append(GetStartAngle());
|
|
||||||
return sectionAngle;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (angle > 360 || angle < 0)
|
|
||||||
{// Filter incorect value of angle
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
sectionAngle.append(angleInterpolation);
|
|
||||||
}
|
|
||||||
|
|
||||||
const qreal tail = angle - sections * angleInterpolation;
|
|
||||||
if (tail > 0)
|
|
||||||
{
|
|
||||||
sectionAngle.append(tail);
|
|
||||||
}
|
|
||||||
return sectionAngle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
@ -390,34 +228,22 @@ QVector<qreal> VEllipticalArc::GetAngles() const
|
||||||
*/
|
*/
|
||||||
QVector<QPointF> VEllipticalArc::GetPoints() const
|
QVector<QPointF> VEllipticalArc::GetPoints() const
|
||||||
{
|
{
|
||||||
QVector<QPointF> points;
|
QRectF box(GetCenter().x() - d->radius1, GetCenter().y() - d->radius2, d->radius1*2,
|
||||||
QVector<qreal> sectionAngle = GetAngles();
|
d->radius2*2);
|
||||||
|
QPainterPath path;
|
||||||
|
IsFlipped() ? path.arcTo(box, GetEndAngle(), GetStartAngle()) : path.arcTo(box, GetStartAngle(), GetEndAngle());
|
||||||
|
|
||||||
qreal currentAngle;
|
QTransform t;
|
||||||
IsFlipped() ? currentAngle = GetEndAngle() : currentAngle = GetStartAngle();
|
t.translate(GetCenter().x(), GetCenter().y());
|
||||||
for (int i = 0; i < sectionAngle.size(); ++i)
|
t.rotate(-GetRotationAngle());
|
||||||
{
|
t.translate(-GetCenter().x(), -GetCenter().y());
|
||||||
QPointF startPoint = GetPoint(currentAngle);
|
|
||||||
QPointF ellipsePoint2 = GetPoint(currentAngle + sectionAngle.at(i)/3);
|
|
||||||
QPointF ellipsePoint3 = GetPoint(currentAngle + 2*sectionAngle.at(i)/3);
|
|
||||||
QPointF lastPoint = GetPoint(currentAngle + sectionAngle.at(i));
|
|
||||||
// four points that are on ellipse
|
|
||||||
|
|
||||||
QPointF bezierPoint1 = ( -5*startPoint + 18*ellipsePoint2 -9*ellipsePoint3 + 2*lastPoint )/6;
|
path = t.map(path);
|
||||||
QPointF bezierPoint2 = ( 2*startPoint - 9*ellipsePoint2 + 18*ellipsePoint3 - 5*lastPoint )/6;
|
|
||||||
|
|
||||||
VSpline spl(VPointF(startPoint), bezierPoint1, bezierPoint2, VPointF(lastPoint), 1.0);
|
QPolygonF polygon = path.toSubpathPolygons().first();
|
||||||
|
polygon.removeFirst(); // remove point (0;0)
|
||||||
|
|
||||||
QVector<QPointF> splPoints = spl.GetPoints();
|
return polygon;
|
||||||
|
|
||||||
if (not splPoints.isEmpty() && i != sectionAngle.size() - 1)
|
|
||||||
{
|
|
||||||
splPoints.removeLast();
|
|
||||||
}
|
|
||||||
points << splPoints;
|
|
||||||
currentAngle += sectionAngle.at(i);
|
|
||||||
}
|
|
||||||
return points;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -102,12 +102,7 @@ protected:
|
||||||
private:
|
private:
|
||||||
QSharedDataPointer<VEllipticalArcData> d;
|
QSharedDataPointer<VEllipticalArcData> d;
|
||||||
|
|
||||||
// cppcheck-suppress unusedPrivateFunction
|
|
||||||
QVector<qreal> GetAngles () const;
|
|
||||||
qreal MaxLength() const;
|
qreal MaxLength() const;
|
||||||
QPointF GetPoint (qreal angle) const;
|
|
||||||
|
|
||||||
static int GetQuadransRad(qreal &rad);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(VEllipticalArc)
|
Q_DECLARE_METATYPE(VEllipticalArc)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user