2013-11-15 13:41:26 +01:00
|
|
|
|
/************************************************************************
|
2013-09-18 21:16:19 +02:00
|
|
|
|
**
|
2013-11-15 13:50:05 +01:00
|
|
|
|
** @file vspline.cpp
|
2013-11-15 13:41:26 +01:00
|
|
|
|
** @author Roman Telezhinsky <dismine@gmail.com>
|
2013-11-15 13:50:05 +01:00
|
|
|
|
** @date November 15, 2013
|
2013-09-18 21:16:19 +02:00
|
|
|
|
**
|
2013-11-15 13:41:26 +01:00
|
|
|
|
** @brief
|
|
|
|
|
** @copyright
|
|
|
|
|
** This source code is part of the Valentine project, a pattern making
|
|
|
|
|
** program, whose allow create and modeling patterns of clothing.
|
|
|
|
|
** Copyright (C) 2013 Valentina project
|
|
|
|
|
** <https://bitbucket.org/dismine/valentina> All Rights Reserved.
|
2013-09-18 21:16:19 +02:00
|
|
|
|
**
|
2013-11-15 13:41:26 +01:00
|
|
|
|
** Valentina is free software: you can redistribute it and/or modify
|
2013-09-18 21:16:19 +02:00
|
|
|
|
** it under the terms of the GNU General Public License as published by
|
|
|
|
|
** the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
** (at your option) any later version.
|
|
|
|
|
**
|
2013-10-27 13:36:29 +01:00
|
|
|
|
** Valentina is distributed in the hope that it will be useful,
|
2013-09-18 21:16:19 +02:00
|
|
|
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
** GNU General Public License for more details.
|
|
|
|
|
**
|
|
|
|
|
** You should have received a copy of the GNU General Public License
|
|
|
|
|
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
**
|
2013-11-15 13:41:26 +01:00
|
|
|
|
*************************************************************************/
|
2013-09-18 21:16:19 +02:00
|
|
|
|
|
2013-08-05 10:37:56 +02:00
|
|
|
|
#include "vspline.h"
|
|
|
|
|
|
2013-11-21 13:05:26 +01:00
|
|
|
|
#include <QDebug>
|
|
|
|
|
|
2013-11-04 21:35:15 +01:00
|
|
|
|
VSpline::VSpline()
|
|
|
|
|
:p1(0), p2(QPointF()), p3(QPointF()), p4(0), angle1(0), angle2(0), kAsm1(1), kAsm2(1), kCurve(1),
|
2013-12-21 12:36:51 +01:00
|
|
|
|
points(QHash<qint64, VPointF>()), idObject(0), _name(QString()){}
|
2013-08-05 10:37:56 +02:00
|
|
|
|
|
2013-11-04 21:35:15 +01:00
|
|
|
|
VSpline::VSpline ( const VSpline & spline )
|
|
|
|
|
:p1(spline.GetP1 ()), p2(spline.GetP2 ()), p3(spline.GetP3 ()), p4(spline.GetP4 ()), angle1(spline.GetAngle1 ()),
|
|
|
|
|
angle2(spline.GetAngle2 ()), kAsm1(spline.GetKasm1()), kAsm2(spline.GetKasm2()), kCurve(spline.GetKcurve()),
|
2013-12-21 12:36:51 +01:00
|
|
|
|
points(spline.GetDataPoints()), idObject(spline.getIdObject()), _name(spline.name()){}
|
2013-08-05 10:37:56 +02:00
|
|
|
|
|
2013-10-04 13:32:42 +02:00
|
|
|
|
VSpline::VSpline (const QHash<qint64, VPointF> *points, qint64 p1, qint64 p4, qreal angle1, qreal angle2,
|
2013-12-21 12:36:51 +01:00
|
|
|
|
qreal kAsm1, qreal kAsm2, qreal kCurve, qint64 idObject)
|
2013-11-04 21:35:15 +01:00
|
|
|
|
:p1(p1), p2(QPointF()), p3(QPointF()), p4(p4), angle1(angle1), angle2(angle2), kAsm1(kAsm1), kAsm2(kAsm2),
|
2013-12-21 12:36:51 +01:00
|
|
|
|
kCurve(kCurve), points(*points), idObject(idObject), _name(QString())
|
2013-11-04 21:35:15 +01:00
|
|
|
|
{
|
2013-11-12 13:48:45 +01:00
|
|
|
|
_name = QString("Spl_%1_%2").arg(this->GetPointP1().name(), this->GetPointP4().name());
|
2013-08-05 10:37:56 +02:00
|
|
|
|
ModifiSpl ( p1, p4, angle1, angle2, kAsm1, kAsm2, kCurve );
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-04 13:32:42 +02:00
|
|
|
|
VSpline::VSpline (const QHash<qint64, VPointF> *points, qint64 p1, QPointF p2, QPointF p3, qint64 p4,
|
2013-12-21 12:36:51 +01:00
|
|
|
|
qreal kCurve, qint64 idObject)
|
|
|
|
|
:p1(p1), p2(p2), p3(p3), p4(p4), angle1(0), angle2(0), kAsm1(1), kAsm2(1), kCurve(1), points(*points),
|
2013-11-12 13:48:45 +01:00
|
|
|
|
idObject(idObject), _name(QString())
|
2013-11-04 21:35:15 +01:00
|
|
|
|
{
|
2013-11-12 13:48:45 +01:00
|
|
|
|
_name = QString("Spl_%1_%2").arg(this->GetPointP1().name(), this->GetPointP4().name());
|
2013-08-05 10:37:56 +02:00
|
|
|
|
ModifiSpl ( p1, p2, p3, p4, kCurve);
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-21 12:36:51 +01:00
|
|
|
|
void VSpline::ModifiSpl ( qint64 p1, qint64 p4, qreal angle1, qreal angle2, qreal kAsm1, qreal kAsm2, qreal kCurve)
|
2013-11-04 21:35:15 +01:00
|
|
|
|
{
|
2013-08-05 10:37:56 +02:00
|
|
|
|
this->p1 = p1;
|
|
|
|
|
this->p4 = p4;
|
|
|
|
|
this->angle1 = angle1;
|
|
|
|
|
this->angle2 = angle2;
|
|
|
|
|
this->kAsm1 = kAsm1;
|
|
|
|
|
this->kAsm2 = kAsm2;
|
|
|
|
|
this->kCurve = kCurve;
|
|
|
|
|
QLineF p1pX(GetPointP1().x(), GetPointP1().y(), GetPointP1().x() + 100, GetPointP1().y());
|
|
|
|
|
p1pX.setAngle( angle1 );
|
|
|
|
|
qreal L = 0, radius = 0, angle = 90;
|
2013-08-28 10:55:11 +02:00
|
|
|
|
// angle = QLineF(GetPointP1(), p1pX.p2()).angleTo(QLineF(GetPointP1(), GetPointP4()));
|
|
|
|
|
// if ( angle > 180 ){
|
|
|
|
|
// angle = 360 - angle;
|
|
|
|
|
// }
|
2013-08-13 18:48:36 +02:00
|
|
|
|
QPointF point1 = GetPointP1().toQPointF();
|
|
|
|
|
QPointF point4 = GetPointP4().toQPointF();
|
2013-11-04 21:35:15 +01:00
|
|
|
|
radius = QLineF(QPointF(point1.x(), point4.y()), point4).length();
|
2013-08-28 10:55:11 +02:00
|
|
|
|
// radius = QLineF(GetPointP1(), GetPointP4()).length() / 2 / sin( angle * M_PI / 180.0 );
|
2013-08-05 10:37:56 +02:00
|
|
|
|
L = kCurve * radius * 4 / 3 * tan( angle * M_PI / 180.0 / 4 );
|
|
|
|
|
QLineF p1p2(GetPointP1().x(), GetPointP1().y(), GetPointP1().x() + L * kAsm1, GetPointP1().y());
|
|
|
|
|
p1p2.setAngle(angle1);
|
|
|
|
|
QLineF p4p3(GetPointP4().x(), GetPointP4().y(), GetPointP4().x() + L * kAsm2, GetPointP4().y());
|
|
|
|
|
p4p3.setAngle(angle2);
|
|
|
|
|
this->p2 = p1p2.p2();
|
|
|
|
|
this->p3 = p4p3.p2();
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-07 15:40:39 +01:00
|
|
|
|
void VSpline::ModifiSpl (const qint64 &p1, const QPointF &p2, const QPointF &p3, const qint64 &p4, const qreal &kCurve)
|
2013-11-04 21:35:15 +01:00
|
|
|
|
{
|
2013-08-05 10:37:56 +02:00
|
|
|
|
this->p1 = p1;
|
|
|
|
|
this->p2 = p2;
|
|
|
|
|
this->p3 = p3;
|
|
|
|
|
this->p4 = p4;
|
2013-08-13 18:48:36 +02:00
|
|
|
|
this->angle1 = QLineF ( GetPointP1().toQPointF(), p2 ).angle();
|
|
|
|
|
this->angle2 = QLineF ( GetPointP4().toQPointF(), p3 ).angle();
|
2013-08-05 10:37:56 +02:00
|
|
|
|
|
|
|
|
|
QLineF p1pX(GetPointP1().x(), GetPointP1().y(), GetPointP1().x() + 100, GetPointP1().y());
|
|
|
|
|
p1pX.setAngle( angle1 );
|
|
|
|
|
qreal L = 0, radius = 0, angle = 90;
|
2013-08-28 10:55:11 +02:00
|
|
|
|
// angle = QLineF(GetPointP1(), p1pX.p2()).angleTo(QLineF(GetPointP1(), GetPointP4()));
|
|
|
|
|
// if ( angle >= 180 ){
|
|
|
|
|
// angle = 360 - angle;
|
|
|
|
|
// }
|
2013-08-13 18:48:36 +02:00
|
|
|
|
QPointF point1 = GetPointP1().toQPointF();
|
|
|
|
|
QPointF point4 = GetPointP4().toQPointF();
|
2013-11-04 21:35:15 +01:00
|
|
|
|
radius = QLineF(QPointF(point1.x(), point4.y()), point4).length();
|
2013-08-28 10:55:11 +02:00
|
|
|
|
// radius = QLineF(GetPointP1(), GetPointP4()).length() / 2 / sin( angle * M_PI / 180.0 );
|
2013-08-05 10:37:56 +02:00
|
|
|
|
L = kCurve * radius * 4 / 3 * tan( angle * M_PI / 180.0 / 4 );
|
|
|
|
|
|
|
|
|
|
this->kCurve = kCurve;
|
2013-08-13 18:48:36 +02:00
|
|
|
|
this->kAsm1 = QLineF ( GetPointP1().toQPointF(), p2 ).length()/L;
|
|
|
|
|
this->kAsm2 = QLineF ( GetPointP4().toQPointF(), p3 ).length()/L;
|
2013-08-05 10:37:56 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//void VSpline::RotationSpl (QPointF pRotate, qreal angle ){
|
|
|
|
|
// QLineF pRotateP1 (pRotate, p1);
|
|
|
|
|
// pRotateP1.setAngle(angle);
|
|
|
|
|
// p1 = pRotateP1.p2();
|
|
|
|
|
// QLineF pRotateP2 (pRotate, p2);
|
|
|
|
|
// pRotateP2.setAngle(angle);
|
|
|
|
|
// p2 = pRotateP2.p2();
|
|
|
|
|
// QLineF pRotateP3 (pRotate, p3);
|
|
|
|
|
// pRotateP3.setAngle(angle);
|
|
|
|
|
// p3 = pRotateP3.p2();
|
|
|
|
|
// QLineF pRotateP4 (pRotate, p4);
|
|
|
|
|
// pRotateP4.setAngle(angle);
|
|
|
|
|
// p4 = pRotateP4.p2();
|
|
|
|
|
// angle1 = QLineF(p1, p2).angle();
|
|
|
|
|
// angle2 = QLineF(p4, p2).angle();
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
//void VSpline::BiasSpl ( qreal mx, qreal my ){
|
|
|
|
|
// p1 = QPointF(p1.x()+mx, p1.y()+my);
|
|
|
|
|
// p2 = QPointF(p2.x()+mx, p2.y()+my);
|
|
|
|
|
// p3 = QPointF(p3.x()+mx, p3.y()+my);
|
|
|
|
|
// p4 = QPointF(p4.x()+mx, p4.y()+my);
|
|
|
|
|
//}
|
|
|
|
|
|
2013-11-04 21:35:15 +01:00
|
|
|
|
VPointF VSpline::GetPointP1() const
|
|
|
|
|
{
|
|
|
|
|
if (points.contains(p1))
|
|
|
|
|
{
|
2013-10-10 20:45:58 +02:00
|
|
|
|
return points.value(p1);
|
2013-11-04 21:35:15 +01:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2013-08-05 10:37:56 +02:00
|
|
|
|
qCritical()<<"Не можу знайти id = "<<p1<<" в таблиці.";
|
2013-11-04 21:35:15 +01:00
|
|
|
|
throw "Не можу знайти точку за id.";
|
2013-08-05 10:37:56 +02:00
|
|
|
|
}
|
|
|
|
|
return VPointF();
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-04 21:35:15 +01:00
|
|
|
|
VPointF VSpline::GetPointP4() const
|
|
|
|
|
{
|
|
|
|
|
if (points.contains(p4))
|
|
|
|
|
{
|
2013-10-10 20:45:58 +02:00
|
|
|
|
return points.value(p4);
|
2013-11-04 21:35:15 +01:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2013-08-05 10:37:56 +02:00
|
|
|
|
qCritical()<<"Не можу знайти id = "<<p4<<" в таблиці.";
|
2013-11-04 21:35:15 +01:00
|
|
|
|
throw "Не можу знайти точку за id.";
|
2013-08-05 10:37:56 +02:00
|
|
|
|
}
|
|
|
|
|
return VPointF();
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-04 21:35:15 +01:00
|
|
|
|
qreal VSpline::GetLength () const
|
|
|
|
|
{
|
2013-08-13 18:48:36 +02:00
|
|
|
|
return LengthBezier ( GetPointP1().toQPointF(), this->p2, this->p3, GetPointP4().toQPointF());
|
2013-08-05 10:37:56 +02:00
|
|
|
|
}
|
|
|
|
|
|
2013-11-04 21:35:15 +01:00
|
|
|
|
QString VSpline::GetName() const
|
|
|
|
|
{
|
2013-08-05 10:37:56 +02:00
|
|
|
|
VPointF first = GetPointP1();
|
|
|
|
|
VPointF second = GetPointP4();
|
|
|
|
|
return QString("Spl_%1_%2").arg(first.name(), second.name());
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-04 21:35:15 +01:00
|
|
|
|
QLineF::IntersectType VSpline::CrossingSplLine ( const QLineF &line, QPointF *intersectionPoint ) const
|
|
|
|
|
{
|
2013-08-05 10:37:56 +02:00
|
|
|
|
QVector<qreal> px;
|
|
|
|
|
QVector<qreal> py;
|
|
|
|
|
px.append ( GetPointP1 ().x () );
|
|
|
|
|
py.append ( GetPointP1 ().y () );
|
|
|
|
|
QVector<qreal>& wpx = px;
|
|
|
|
|
QVector<qreal>& wpy = py;
|
|
|
|
|
PointBezier_r ( GetPointP1 ().x (), GetPointP1 ().y (), GetP2 ().x (), GetP2 ().y (),
|
|
|
|
|
GetP3 ().x (), GetP3 ().y (), GetPointP4 ().x (), GetPointP4 ().y (),
|
|
|
|
|
0, wpx, wpy);
|
|
|
|
|
px.append ( GetPointP4 ().x () );
|
|
|
|
|
py.append ( GetPointP4 ().y () );
|
|
|
|
|
qint32 i = 0;
|
|
|
|
|
QPointF crosPoint;
|
|
|
|
|
QLineF::IntersectType type = QLineF::NoIntersection;
|
2013-11-04 21:35:15 +01:00
|
|
|
|
for ( i = 0; i < px.count()-1; ++i )
|
|
|
|
|
{
|
2013-08-05 10:37:56 +02:00
|
|
|
|
type = line.intersect(QLineF ( QPointF ( px[i], py[i] ),
|
|
|
|
|
QPointF ( px[i+1], py[i+1] )), &crosPoint);
|
2013-11-04 21:35:15 +01:00
|
|
|
|
if ( type == QLineF::BoundedIntersection )
|
|
|
|
|
{
|
2013-08-05 10:37:56 +02:00
|
|
|
|
*intersectionPoint = crosPoint;
|
|
|
|
|
return type;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
throw "Не можу знайти точку перетину сплайну з лінією.";
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-18 12:13:32 +01:00
|
|
|
|
qreal VSpline::LengthT(qreal t) const
|
|
|
|
|
{
|
|
|
|
|
if(t < 0 || t > 1)
|
|
|
|
|
{
|
|
|
|
|
qWarning()<<"Wrong value t.";
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
QLineF seg1_2 ( GetPointP1 ().toQPointF(), GetP2 () );
|
|
|
|
|
seg1_2.setLength(seg1_2.length () * t);
|
|
|
|
|
QPointF p12 = seg1_2.p2();
|
|
|
|
|
|
|
|
|
|
QLineF seg2_3 ( GetP2 (), GetP3 () );
|
|
|
|
|
seg2_3.setLength(seg2_3.length () * t);
|
|
|
|
|
QPointF p23 = seg2_3.p2();
|
|
|
|
|
|
|
|
|
|
QLineF seg12_23 ( p12, p23 );
|
|
|
|
|
seg12_23.setLength(seg12_23.length () * t);
|
|
|
|
|
QPointF p123 = seg12_23.p2();
|
|
|
|
|
|
|
|
|
|
QLineF seg3_4 ( GetP3 (), GetPointP4 ().toQPointF() );
|
|
|
|
|
seg3_4.setLength(seg3_4.length () * t);
|
|
|
|
|
QPointF p34 = seg3_4.p2();
|
|
|
|
|
|
|
|
|
|
QLineF seg23_34 ( p23, p34 );
|
|
|
|
|
seg23_34.setLength(seg23_34.length () * t);
|
|
|
|
|
QPointF p234 = seg23_34.p2();
|
|
|
|
|
|
|
|
|
|
QLineF seg123_234 ( p123, p234 );
|
|
|
|
|
seg123_234.setLength(seg123_234.length () * t);
|
|
|
|
|
QPointF p1234 = seg123_234.p2();
|
|
|
|
|
|
|
|
|
|
return LengthBezier ( GetPointP1().toQPointF(), p12, p123, p1234);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QPointF VSpline::CutSpline ( qreal length, QPointF &spl1p2, QPointF &spl1p3, QPointF &spl2p2, QPointF &spl2p3 ) const
|
|
|
|
|
{
|
|
|
|
|
//Always need return two splines, so we must correct wrong length.
|
|
|
|
|
if(length < GetLength()*0.02)
|
|
|
|
|
{
|
|
|
|
|
length = GetLength()*0.02;
|
|
|
|
|
}
|
|
|
|
|
else if ( length > GetLength()*0.98)
|
|
|
|
|
{
|
|
|
|
|
length = GetLength()*0.98;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Very stupid way find correct value of t.
|
|
|
|
|
// Better first compare with t = 0.5. Find length of spline.
|
|
|
|
|
// If length larger, take t = 0.75 and so on.
|
|
|
|
|
// If length less, take t = 0.25 and so on.
|
|
|
|
|
qreal parT = 0;
|
|
|
|
|
qreal step = 0.001;
|
|
|
|
|
while (1)
|
|
|
|
|
{
|
|
|
|
|
parT = parT + step;
|
|
|
|
|
qreal splLength = LengthT(parT);
|
|
|
|
|
if(splLength >= length || parT > 1){
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QLineF seg1_2 ( GetPointP1 ().toQPointF(), GetP2 () );
|
|
|
|
|
seg1_2.setLength(seg1_2.length () * parT);
|
|
|
|
|
QPointF p12 = seg1_2.p2();
|
|
|
|
|
|
|
|
|
|
QLineF seg2_3 ( GetP2 (), GetP3 () );
|
|
|
|
|
seg2_3.setLength(seg2_3.length () * parT);
|
|
|
|
|
QPointF p23 = seg2_3.p2();
|
|
|
|
|
|
|
|
|
|
QLineF seg12_23 ( p12, p23 );
|
|
|
|
|
seg12_23.setLength(seg12_23.length () * parT);
|
|
|
|
|
QPointF p123 = seg12_23.p2();
|
|
|
|
|
|
|
|
|
|
QLineF seg3_4 ( GetP3 (), GetPointP4 ().toQPointF() );
|
|
|
|
|
seg3_4.setLength(seg3_4.length () * parT);
|
|
|
|
|
QPointF p34 = seg3_4.p2();
|
|
|
|
|
|
|
|
|
|
QLineF seg23_34 ( p23, p34 );
|
|
|
|
|
seg23_34.setLength(seg23_34.length () * parT);
|
|
|
|
|
QPointF p234 = seg23_34.p2();
|
|
|
|
|
|
|
|
|
|
QLineF seg123_234 ( p123, p234 );
|
|
|
|
|
seg123_234.setLength(seg123_234.length () * parT);
|
|
|
|
|
QPointF p1234 = seg123_234.p2();
|
|
|
|
|
|
|
|
|
|
spl1p2 = p12;
|
|
|
|
|
spl1p3 = p123;
|
|
|
|
|
spl2p2 = p234;
|
|
|
|
|
spl2p3 = p34;
|
|
|
|
|
return p1234;
|
|
|
|
|
}
|
2013-08-05 10:37:56 +02:00
|
|
|
|
|
|
|
|
|
//void VSpline::CutSpline ( QPointF point, VSpline* curFir, VSpline* curSec ) const{
|
|
|
|
|
// qreal t = param_t (point);
|
|
|
|
|
// qreal length = t*this->GetLength();
|
|
|
|
|
// CutSpline ( length, curFir, curSec );
|
|
|
|
|
//}
|
|
|
|
|
|
2013-09-12 15:25:24 +02:00
|
|
|
|
//void VSpline::PutAlongSpl (QPointF &moveP, qreal move ) const{
|
|
|
|
|
// if ( GetLength () < move ){
|
|
|
|
|
// qDebug()<<"Довжина більше довжини сплайну.";
|
|
|
|
|
// qDebug()<<GetLength()<<"<"<<move;
|
|
|
|
|
// throw "Довжина більше довжини сплайну.";
|
|
|
|
|
// }
|
|
|
|
|
// if ( move <= 0 ){
|
|
|
|
|
// qDebug()<<"Довжина менше дорівнює нулю.";
|
|
|
|
|
// throw "Довжина менше дорівнює нулю.";
|
|
|
|
|
// }
|
|
|
|
|
// qreal t = 0;
|
|
|
|
|
// if ( move == 0 ){
|
|
|
|
|
// t = 0;
|
|
|
|
|
// } else {
|
|
|
|
|
// t = move / GetLength ();
|
|
|
|
|
// moveP.setX ( pow ( 1 - t, 3 ) * GetPointP1 ().x () + 3 * t * pow ( 1 - t, 2 ) *
|
|
|
|
|
// GetP2 ().x () + 3 * t * t * ( 1 - t ) * GetP3 ().x () +
|
|
|
|
|
// pow ( t, 3 ) * GetPointP4 ().x () );
|
|
|
|
|
// moveP.setY ( pow ( 1 - t, 3 ) * GetPointP1 ().y () + 3 * t * pow ( 1 - t, 2 ) *
|
|
|
|
|
// GetP2 ().y () + 3 * t * t * ( 1 - t ) * GetP3 ().y () +
|
|
|
|
|
// pow ( t, 3 ) * GetPointP4 ().y () );
|
|
|
|
|
// }
|
|
|
|
|
//}
|
2013-08-05 10:37:56 +02:00
|
|
|
|
|
2013-11-04 21:35:15 +01:00
|
|
|
|
QVector<QPointF> VSpline::GetPoints () const
|
|
|
|
|
{
|
2013-08-13 18:48:36 +02:00
|
|
|
|
return GetPoints(GetPointP1().toQPointF(), p2, p3, GetPointP4().toQPointF());
|
2013-09-10 14:29:06 +02:00
|
|
|
|
// QLineF line1(points.at(0).toPoint(), points.at(1).toPoint());
|
|
|
|
|
// line1.setLength(500);
|
|
|
|
|
// QLineF line2 = line1;
|
|
|
|
|
// line2.setAngle(line2.angle()+90);
|
|
|
|
|
// qreal xk1 = line1.p2().x();
|
|
|
|
|
// qreal xk0 = line1.p1().x();
|
|
|
|
|
// qreal y = line2.p2().y();
|
|
|
|
|
// qreal yk0 = line1.p1().y();
|
|
|
|
|
// qreal yk1 = line1.p2().y();
|
|
|
|
|
// qreal x = line2.p2().x();
|
|
|
|
|
// qreal check = (xk1 - xk0) * (y - yk0) - (yk1 - yk0) * (x - xk0);
|
|
|
|
|
// if(check > 0){
|
|
|
|
|
// return points;
|
|
|
|
|
// } else {
|
|
|
|
|
// QVector<QPointF> reversePoints;
|
|
|
|
|
// for (qint32 i = points.size() - 1; i >= 0; --i) {
|
|
|
|
|
// reversePoints.append(points.at(i));
|
|
|
|
|
// }
|
|
|
|
|
// return reversePoints;
|
|
|
|
|
// }
|
2013-08-05 10:37:56 +02:00
|
|
|
|
}
|
|
|
|
|
|
2013-11-07 15:40:39 +01:00
|
|
|
|
QVector<QPointF> VSpline::GetPoints (const QPointF &p1, const QPointF &p2, const QPointF &p3, const QPointF &p4)
|
2013-11-04 21:35:15 +01:00
|
|
|
|
{
|
2013-08-05 10:37:56 +02:00
|
|
|
|
QVector<QPointF> pvector;
|
|
|
|
|
QVector<qreal> x;
|
|
|
|
|
QVector<qreal> y;
|
|
|
|
|
QVector<qreal>& wx = x;
|
|
|
|
|
QVector<qreal>& wy = y;
|
|
|
|
|
x.append ( p1.x () );
|
|
|
|
|
y.append ( p1.y () );
|
|
|
|
|
PointBezier_r ( p1.x (), p1.y (), p2.x (), p2.y (),
|
|
|
|
|
p3.x (), p3.y (), p4.x (), p4.y (), 0, wx, wy );
|
|
|
|
|
x.append ( p4.x () );
|
|
|
|
|
y.append ( p4.y () );
|
2013-11-04 21:35:15 +01:00
|
|
|
|
for ( qint32 i = 0; i < x.count(); ++i )
|
|
|
|
|
{
|
2013-08-05 10:37:56 +02:00
|
|
|
|
pvector.append( QPointF ( x[i], y[i] ) );
|
|
|
|
|
}
|
|
|
|
|
return pvector;
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-07 15:40:39 +01:00
|
|
|
|
qreal VSpline::LengthBezier ( const QPointF &p1, const QPointF &p2, const QPointF &p3, const QPointF &p4 ) const
|
2013-11-04 21:35:15 +01:00
|
|
|
|
{
|
2013-08-05 10:37:56 +02:00
|
|
|
|
QPainterPath splinePath;
|
|
|
|
|
QVector<QPointF> points = GetPoints (p1, p2, p3, p4);
|
|
|
|
|
splinePath.moveTo(points[0]);
|
2013-11-04 21:35:15 +01:00
|
|
|
|
for (qint32 i = 1; i < points.count(); ++i)
|
|
|
|
|
{
|
2013-08-05 10:37:56 +02:00
|
|
|
|
splinePath.lineTo(points[i]);
|
|
|
|
|
}
|
2013-10-13 20:51:59 +02:00
|
|
|
|
return splinePath.length();
|
2013-08-05 10:37:56 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void VSpline::PointBezier_r ( qreal x1, qreal y1, qreal x2, qreal y2,
|
|
|
|
|
qreal x3, qreal y3, qreal x4, qreal y4,
|
2013-11-04 21:35:15 +01:00
|
|
|
|
qint16 level, QVector<qreal> &px, QVector<qreal> &py)
|
|
|
|
|
{
|
|
|
|
|
const double curve_collinearity_epsilon = 1e-30;
|
|
|
|
|
const double curve_angle_tolerance_epsilon = 0.01;
|
2013-08-05 10:37:56 +02:00
|
|
|
|
const double m_angle_tolerance = 0.0;
|
|
|
|
|
enum curve_recursion_limit_e { curve_recursion_limit = 32 };
|
|
|
|
|
const double m_cusp_limit = 0.0;
|
|
|
|
|
double m_approximation_scale = 1.0;
|
|
|
|
|
double m_distance_tolerance_square;
|
|
|
|
|
|
|
|
|
|
m_distance_tolerance_square = 0.5 / m_approximation_scale;
|
|
|
|
|
m_distance_tolerance_square *= m_distance_tolerance_square;
|
|
|
|
|
|
2013-11-04 21:35:15 +01:00
|
|
|
|
if (level > curve_recursion_limit)
|
2013-08-05 10:37:56 +02:00
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Calculate all the mid-points of the line segments
|
|
|
|
|
//----------------------
|
|
|
|
|
double x12 = (x1 + x2) / 2;
|
|
|
|
|
double y12 = (y1 + y2) / 2;
|
|
|
|
|
double x23 = (x2 + x3) / 2;
|
|
|
|
|
double y23 = (y2 + y3) / 2;
|
|
|
|
|
double x34 = (x3 + x4) / 2;
|
|
|
|
|
double y34 = (y3 + y4) / 2;
|
|
|
|
|
double x123 = (x12 + x23) / 2;
|
|
|
|
|
double y123 = (y12 + y23) / 2;
|
|
|
|
|
double x234 = (x23 + x34) / 2;
|
|
|
|
|
double y234 = (y23 + y34) / 2;
|
|
|
|
|
double x1234 = (x123 + x234) / 2;
|
|
|
|
|
double y1234 = (y123 + y234) / 2;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Try to approximate the full cubic curve by a single straight line
|
|
|
|
|
//------------------
|
|
|
|
|
double dx = x4-x1;
|
|
|
|
|
double dy = y4-y1;
|
|
|
|
|
|
2013-11-07 15:40:39 +01:00
|
|
|
|
double d2 = fabs((x2 - x4) * dy - (y2 - y4) * dx);
|
|
|
|
|
double d3 = fabs((x3 - x4) * dy - (y3 - y4) * dx);
|
2013-08-05 10:37:56 +02:00
|
|
|
|
double da1, da2, k;
|
|
|
|
|
|
2013-11-04 21:35:15 +01:00
|
|
|
|
switch ((static_cast<int>(d2 > curve_collinearity_epsilon) << 1) +
|
|
|
|
|
static_cast<int>(d3 > curve_collinearity_epsilon))
|
2013-08-05 10:37:56 +02:00
|
|
|
|
{
|
2013-11-04 21:35:15 +01:00
|
|
|
|
case 0:
|
|
|
|
|
// All collinear OR p1==p4
|
|
|
|
|
//----------------------
|
|
|
|
|
k = dx*dx + dy*dy;
|
2013-11-12 19:29:03 +01:00
|
|
|
|
if (k < 0.000000001)
|
2013-08-05 10:37:56 +02:00
|
|
|
|
{
|
2013-11-04 21:35:15 +01:00
|
|
|
|
d2 = CalcSqDistance(x1, y1, x2, y2);
|
|
|
|
|
d3 = CalcSqDistance(x4, y4, x3, y3);
|
2013-08-05 10:37:56 +02:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2013-11-04 21:35:15 +01:00
|
|
|
|
k = 1 / k;
|
|
|
|
|
da1 = x2 - x1;
|
|
|
|
|
da2 = y2 - y1;
|
|
|
|
|
d2 = k * (da1*dx + da2*dy);
|
|
|
|
|
da1 = x3 - x1;
|
|
|
|
|
da2 = y3 - y1;
|
|
|
|
|
d3 = k * (da1*dx + da2*dy);
|
|
|
|
|
if (d2 > 0 && d2 < 1 && d3 > 0 && d3 < 1)
|
|
|
|
|
{
|
|
|
|
|
// Simple collinear case, 1---2---3---4
|
|
|
|
|
// We can leave just two endpoints
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (d2 <= 0)
|
|
|
|
|
{
|
|
|
|
|
d2 = CalcSqDistance(x2, y2, x1, y1);
|
|
|
|
|
}
|
|
|
|
|
else if (d2 >= 1)
|
|
|
|
|
{
|
|
|
|
|
d2 = CalcSqDistance(x2, y2, x4, y4);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
d2 = CalcSqDistance(x2, y2, x1 + d2*dx, y1 + d2*dy);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (d3 <= 0)
|
|
|
|
|
{
|
|
|
|
|
d3 = CalcSqDistance(x3, y3, x1, y1);
|
|
|
|
|
}
|
|
|
|
|
else if (d3 >= 1)
|
|
|
|
|
{
|
|
|
|
|
d3 = CalcSqDistance(x3, y3, x4, y4);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
d3 = CalcSqDistance(x3, y3, x1 + d3*dx, y1 + d3*dy);
|
|
|
|
|
}
|
2013-08-05 10:37:56 +02:00
|
|
|
|
}
|
2013-11-04 21:35:15 +01:00
|
|
|
|
if (d2 > d3)
|
2013-08-05 10:37:56 +02:00
|
|
|
|
{
|
2013-11-04 21:35:15 +01:00
|
|
|
|
if (d2 < m_distance_tolerance_square)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
px.append(x2);
|
|
|
|
|
py.append(y2);
|
|
|
|
|
//m_points.add(point_d(x2, y2));
|
|
|
|
|
return;
|
|
|
|
|
}
|
2013-08-05 10:37:56 +02:00
|
|
|
|
}
|
2013-11-04 21:35:15 +01:00
|
|
|
|
else
|
2013-08-05 10:37:56 +02:00
|
|
|
|
{
|
2013-11-04 21:35:15 +01:00
|
|
|
|
if (d3 < m_distance_tolerance_square)
|
2013-08-05 10:37:56 +02:00
|
|
|
|
{
|
2013-11-04 21:35:15 +01:00
|
|
|
|
|
2013-08-05 10:37:56 +02:00
|
|
|
|
px.append(x3);
|
|
|
|
|
py.append(y3);
|
|
|
|
|
//m_points.add(point_d(x3, y3));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-11-04 21:35:15 +01:00
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
// p1,p2,p4 are collinear, p3 is significant
|
2013-08-05 10:37:56 +02:00
|
|
|
|
//----------------------
|
2013-11-04 21:35:15 +01:00
|
|
|
|
if (d3 * d3 <= m_distance_tolerance_square * (dx*dx + dy*dy))
|
2013-08-05 10:37:56 +02:00
|
|
|
|
{
|
2013-11-04 21:35:15 +01:00
|
|
|
|
if (m_angle_tolerance < curve_angle_tolerance_epsilon)
|
2013-08-05 10:37:56 +02:00
|
|
|
|
{
|
2013-11-04 21:35:15 +01:00
|
|
|
|
|
|
|
|
|
px.append(x23);
|
|
|
|
|
py.append(y23);
|
|
|
|
|
//m_points.add(point_d(x23, y23));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Angle Condition
|
|
|
|
|
//----------------------
|
|
|
|
|
da1 = fabs(atan2(y4 - y3, x4 - x3) - atan2(y3 - y2, x3 - x2));
|
|
|
|
|
if (da1 >= M_PI)
|
|
|
|
|
{
|
|
|
|
|
da1 = 2*M_PI - da1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (da1 < m_angle_tolerance)
|
|
|
|
|
{
|
|
|
|
|
|
2013-08-05 10:37:56 +02:00
|
|
|
|
px.append(x2);
|
|
|
|
|
py.append(y2);
|
2013-11-04 21:35:15 +01:00
|
|
|
|
|
|
|
|
|
px.append(x3);
|
|
|
|
|
py.append(y3);
|
2013-08-05 10:37:56 +02:00
|
|
|
|
//m_points.add(point_d(x2, y2));
|
2013-11-04 21:35:15 +01:00
|
|
|
|
//m_points.add(point_d(x3, y3));
|
2013-08-05 10:37:56 +02:00
|
|
|
|
return;
|
|
|
|
|
}
|
2013-11-04 21:35:15 +01:00
|
|
|
|
|
2013-11-12 19:29:03 +01:00
|
|
|
|
if (m_cusp_limit > 0.0 || m_cusp_limit < 0.0)
|
2013-11-04 21:35:15 +01:00
|
|
|
|
{
|
|
|
|
|
if (da1 > m_cusp_limit)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
px.append(x3);
|
|
|
|
|
py.append(y3);
|
|
|
|
|
//m_points.add(point_d(x3, y3));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-08-05 10:37:56 +02:00
|
|
|
|
}
|
2013-11-04 21:35:15 +01:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
|
// p1,p3,p4 are collinear, p2 is significant
|
2013-08-05 10:37:56 +02:00
|
|
|
|
//----------------------
|
2013-11-04 21:35:15 +01:00
|
|
|
|
if (d2 * d2 <= m_distance_tolerance_square * (dx*dx + dy*dy))
|
2013-08-05 10:37:56 +02:00
|
|
|
|
{
|
2013-11-04 21:35:15 +01:00
|
|
|
|
if (m_angle_tolerance < curve_angle_tolerance_epsilon)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
px.append(x23);
|
|
|
|
|
py.append(y23);
|
|
|
|
|
//m_points.add(point_d(x23, y23));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Angle Condition
|
2013-08-05 10:37:56 +02:00
|
|
|
|
//----------------------
|
2013-11-04 21:35:15 +01:00
|
|
|
|
da1 = fabs(atan2(y3 - y2, x3 - x2) - atan2(y2 - y1, x2 - x1));
|
|
|
|
|
if (da1 >= M_PI)
|
2013-08-05 10:37:56 +02:00
|
|
|
|
{
|
2013-11-04 21:35:15 +01:00
|
|
|
|
da1 = 2*M_PI - da1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (da1 < m_angle_tolerance)
|
|
|
|
|
{
|
|
|
|
|
|
2013-08-05 10:37:56 +02:00
|
|
|
|
px.append(x2);
|
|
|
|
|
py.append(y2);
|
2013-11-04 21:35:15 +01:00
|
|
|
|
|
|
|
|
|
px.append(x3);
|
|
|
|
|
py.append(y3);
|
|
|
|
|
//m_points.add(point_d(x2, y2));
|
|
|
|
|
//m_points.add(point_d(x3, y3));
|
2013-08-05 10:37:56 +02:00
|
|
|
|
return;
|
|
|
|
|
}
|
2013-11-04 21:35:15 +01:00
|
|
|
|
|
2013-11-12 19:29:03 +01:00
|
|
|
|
if (m_cusp_limit > 0.0 || m_cusp_limit < 0.0)
|
2013-08-05 10:37:56 +02:00
|
|
|
|
{
|
2013-11-04 21:35:15 +01:00
|
|
|
|
if (da1 > m_cusp_limit)
|
|
|
|
|
{
|
|
|
|
|
px.append(x2);
|
|
|
|
|
py.append(y2);
|
|
|
|
|
|
|
|
|
|
//m_points.add(point_d(x2, y2));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
|
// Regular case
|
|
|
|
|
//-----------------
|
|
|
|
|
if ((d2 + d3)*(d2 + d3) <= m_distance_tolerance_square * (dx*dx + dy*dy))
|
|
|
|
|
{
|
|
|
|
|
// If the curvature doesn't exceed the distance_tolerance value
|
|
|
|
|
// we tend to finish subdivisions.
|
|
|
|
|
//----------------------
|
|
|
|
|
if (m_angle_tolerance < curve_angle_tolerance_epsilon)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
px.append(x23);
|
|
|
|
|
py.append(y23);
|
|
|
|
|
//m_points.add(point_d(x23, y23));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Angle & Cusp Condition
|
|
|
|
|
//----------------------
|
|
|
|
|
k = atan2(y3 - y2, x3 - x2);
|
|
|
|
|
da1 = fabs(k - atan2(y2 - y1, x2 - x1));
|
|
|
|
|
da2 = fabs(atan2(y4 - y3, x4 - x3) - k);
|
|
|
|
|
if (da1 >= M_PI)
|
|
|
|
|
{
|
|
|
|
|
da1 = 2*M_PI - da1;
|
|
|
|
|
}
|
|
|
|
|
if (da2 >= M_PI)
|
|
|
|
|
{
|
|
|
|
|
da2 = 2*M_PI - da2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (da1 + da2 < m_angle_tolerance)
|
|
|
|
|
{
|
|
|
|
|
// Finally we can stop the recursion
|
|
|
|
|
//----------------------
|
|
|
|
|
|
|
|
|
|
px.append(x23);
|
|
|
|
|
py.append(y23);
|
|
|
|
|
//m_points.add(point_d(x23, y23));
|
2013-08-05 10:37:56 +02:00
|
|
|
|
return;
|
|
|
|
|
}
|
2013-11-04 21:35:15 +01:00
|
|
|
|
|
2013-11-12 19:29:03 +01:00
|
|
|
|
if (m_cusp_limit > 0.0 || m_cusp_limit < 0.0)
|
2013-11-04 21:35:15 +01:00
|
|
|
|
{
|
|
|
|
|
if (da1 > m_cusp_limit)
|
|
|
|
|
{
|
|
|
|
|
px.append(x2);
|
|
|
|
|
py.append(y2);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (da2 > m_cusp_limit)
|
|
|
|
|
{
|
|
|
|
|
px.append(x3);
|
|
|
|
|
py.append(y3);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-08-05 10:37:56 +02:00
|
|
|
|
}
|
2013-11-04 21:35:15 +01:00
|
|
|
|
break;
|
2013-11-12 19:29:03 +01:00
|
|
|
|
default:
|
|
|
|
|
break;
|
2013-08-05 10:37:56 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Continue subdivision
|
|
|
|
|
//----------------------
|
2013-08-20 12:26:02 +02:00
|
|
|
|
PointBezier_r(x1, y1, x12, y12, x123, y123, x1234, y1234, static_cast<qint16>(level + 1), px, py);
|
|
|
|
|
PointBezier_r(x1234, y1234, x234, y234, x34, y34, x4, y4, static_cast<qint16>(level + 1), px, py);
|
2013-08-05 10:37:56 +02:00
|
|
|
|
}
|
|
|
|
|
|
2013-11-04 21:35:15 +01:00
|
|
|
|
qreal VSpline::CalcSqDistance (qreal x1, qreal y1, qreal x2, qreal y2)
|
|
|
|
|
{
|
2013-08-05 10:37:56 +02:00
|
|
|
|
qreal dx = x2 - x1;
|
|
|
|
|
qreal dy = y2 - y1;
|
|
|
|
|
return dx * dx + dy * dy;
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-04 21:35:15 +01:00
|
|
|
|
QPainterPath VSpline::GetPath() const
|
|
|
|
|
{
|
2013-08-05 10:37:56 +02:00
|
|
|
|
QPainterPath splinePath;
|
|
|
|
|
QVector<QPointF> points = GetPoints ();
|
2013-11-04 21:35:15 +01:00
|
|
|
|
if (points.count() >= 2)
|
|
|
|
|
{
|
|
|
|
|
for (qint32 i = 0; i < points.count()-1; ++i)
|
|
|
|
|
{
|
2013-10-22 15:39:51 +02:00
|
|
|
|
splinePath.moveTo(points[i]);
|
|
|
|
|
splinePath.lineTo(points[i+1]);
|
|
|
|
|
}
|
2013-11-04 21:35:15 +01:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2013-10-22 15:39:51 +02:00
|
|
|
|
qWarning()<<"points.count() < 2"<<Q_FUNC_INFO;
|
2013-08-05 10:37:56 +02:00
|
|
|
|
}
|
|
|
|
|
return splinePath;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Cubic equation solution. Real coefficients case.
|
|
|
|
|
int Cubic(double *x,double a,double b,double c);
|
|
|
|
|
Parameters:
|
|
|
|
|
x - solution array (size 3). On output:
|
|
|
|
|
3 real roots -> then x is filled with them;
|
|
|
|
|
1 real + 2 complex -> x[0] is real, x[1] is real part of
|
|
|
|
|
complex roots, x[2] - non-negative
|
|
|
|
|
imaginary part.
|
|
|
|
|
a, b, c - coefficients, as described
|
|
|
|
|
Returns: 3 - 3 real roots;
|
|
|
|
|
1 - 1 real root + 2 complex;
|
|
|
|
|
2 - 1 real root + complex roots imaginary part is zero
|
|
|
|
|
(i.e. 2 real roots).
|
|
|
|
|
*/
|
2013-10-28 16:45:27 +01:00
|
|
|
|
//qint32 VSpline::Cubic(qreal *x, qreal a, qreal b, qreal c){
|
|
|
|
|
// qreal q,r,r2,q3;
|
2013-11-04 21:35:15 +01:00
|
|
|
|
//
|
2013-10-28 16:45:27 +01:00
|
|
|
|
// q = (a*a - 3.*b)/9.;
|
|
|
|
|
// r = (a*(2.*a*a - 9.*b) + 27.*c)/54.;
|
|
|
|
|
// r2 = r*r;
|
|
|
|
|
// q3 = pow(q,3);
|
|
|
|
|
// if(r2<q3) {
|
|
|
|
|
// qreal t = acos(r/sqrt(q3));
|
|
|
|
|
// a/=3.;
|
|
|
|
|
// q = -2.*sqrt(q);
|
|
|
|
|
// x[0] = q*cos(t/3.)-a;
|
|
|
|
|
// x[1] = q*cos((t + M_2PI)/3.) - a;
|
|
|
|
|
// x[2] = q*cos((t - M_2PI)/3.) - a;
|
|
|
|
|
// return(3);
|
|
|
|
|
// } else {
|
|
|
|
|
// qreal aa,bb;
|
|
|
|
|
// if(r<=0.){
|
|
|
|
|
// r=-r;
|
|
|
|
|
// }
|
|
|
|
|
// aa = -pow(r + sqrt(r2-q3),1./3.);
|
|
|
|
|
// if(aa!=0.){
|
|
|
|
|
// bb=q/aa;
|
|
|
|
|
// } else {
|
|
|
|
|
// bb=0.;
|
|
|
|
|
// }
|
|
|
|
|
// a/=3.;
|
|
|
|
|
// q = aa+bb;
|
|
|
|
|
// r = aa-bb;
|
|
|
|
|
// x[0] = q-a;
|
|
|
|
|
// x[1] = (-0.5)*q-a;
|
|
|
|
|
// x[2] = (sqrt(3.)*0.5)*fabs(r);
|
|
|
|
|
// if(x[2]==0.){
|
|
|
|
|
// return(2);
|
|
|
|
|
// }
|
|
|
|
|
// return(1);
|
|
|
|
|
// }
|
|
|
|
|
//}
|
2013-11-04 21:35:15 +01:00
|
|
|
|
//
|
2013-09-12 15:25:24 +02:00
|
|
|
|
//qreal VSpline::calc_t (qreal curve_coord1, qreal curve_coord2, qreal curve_coord3,
|
|
|
|
|
// qreal curve_coord4, qreal point_coord) const{
|
|
|
|
|
// qreal P1, P2, P3, P4, Bt;
|
|
|
|
|
// qreal a, b, c, d, ret_t;
|
2013-11-04 21:35:15 +01:00
|
|
|
|
//
|
2013-09-12 15:25:24 +02:00
|
|
|
|
// qreal *t = static_cast<qreal *>(malloc(3*sizeof(qreal)));
|
|
|
|
|
// P1 = curve_coord1;
|
|
|
|
|
// P2 = curve_coord2;
|
|
|
|
|
// P3 = curve_coord3;
|
|
|
|
|
// P4 = curve_coord4;
|
|
|
|
|
// Bt = point_coord;
|
2013-11-04 21:35:15 +01:00
|
|
|
|
//
|
2013-09-12 15:25:24 +02:00
|
|
|
|
// a = -P1 + 3*P2 - 3*P3 + P4;
|
|
|
|
|
// b = 3*P1 - 6*P2 + 3*P3;
|
|
|
|
|
// c = -3*P1 + 3*P2;
|
|
|
|
|
// d = -Bt + P1;
|
2013-11-04 21:35:15 +01:00
|
|
|
|
//
|
2013-09-12 15:25:24 +02:00
|
|
|
|
// if(Cubic(t, b/a, c/a, d/a) == 3){
|
|
|
|
|
// ret_t = t[2];
|
|
|
|
|
// } else {
|
|
|
|
|
// ret_t = t[0];
|
|
|
|
|
// }
|
|
|
|
|
// /*
|
|
|
|
|
// * Повертається три значення, але експереминтально знайдено що шукане
|
|
|
|
|
// * значення знаходиться в третьому.
|
|
|
|
|
// */
|
2013-11-04 21:35:15 +01:00
|
|
|
|
//
|
2013-09-12 15:25:24 +02:00
|
|
|
|
// free(t);
|
|
|
|
|
// if(ret_t<0 || ret_t>1){
|
|
|
|
|
// qDebug()<<"Неправильне значення параметра. фунція calc_t";
|
|
|
|
|
// throw"Неправильне значення параметра. фунція calc_t";
|
|
|
|
|
// }
|
|
|
|
|
// return ret_t;
|
|
|
|
|
//}
|
2013-08-05 10:37:56 +02:00
|
|
|
|
/*
|
|
|
|
|
* Функція знаходить підходяще значення параметна t якому відповідає точка на сплайні.
|
|
|
|
|
*/
|
2013-09-12 15:25:24 +02:00
|
|
|
|
//qreal VSpline::param_t (QPointF pBt)const{
|
|
|
|
|
// qreal t_x, t_y;
|
|
|
|
|
// t_x = calc_t (GetPointP1().x(), p2.x(), p3.x(), GetPointP4().x(), pBt.x());
|
|
|
|
|
// t_y = calc_t (GetPointP1().y(), p2.y(), p3.y(), GetPointP4().y(), pBt.y());
|
|
|
|
|
// /*
|
|
|
|
|
// * Порівнюємо значення по х і по у і визначаємо найбільше. Це значення і
|
|
|
|
|
// * буде шуканим.
|
|
|
|
|
// */
|
|
|
|
|
// if(t_x>t_y)
|
|
|
|
|
// return t_x;
|
|
|
|
|
// else
|
|
|
|
|
// return t_y;
|
|
|
|
|
//}
|
2013-11-04 21:35:15 +01:00
|
|
|
|
//
|
2013-08-05 10:37:56 +02:00
|
|
|
|
//void VSpline::Mirror(const QPointF Pmirror){
|
|
|
|
|
// QPointF P1 = p1;
|
|
|
|
|
// P1 = QPointF(P1.x() - Pmirror.x(), P1.y() - Pmirror.y());
|
|
|
|
|
// P1 = QPointF(P1.x() * -1.0, P1.y() * 1.0);
|
|
|
|
|
// P1 = QPointF(P1.x() + Pmirror.x(), P1.y() + Pmirror.y());
|
|
|
|
|
// QPointF P2 = p2;
|
|
|
|
|
// P2 = QPointF(P2.x() - Pmirror.x(), P2.y() - Pmirror.y());
|
|
|
|
|
// P2 = QPointF(P2.x() * -1.0, P2.y() * 1.0);
|
|
|
|
|
// P2 = QPointF(P2.x() + Pmirror.x(), P2.y() + Pmirror.y());
|
|
|
|
|
// QPointF P3 = p3;
|
|
|
|
|
// P3 = QPointF(P3.x() - Pmirror.x(), P3.y() - Pmirror.y());
|
|
|
|
|
// P3 = QPointF(P3.x() * -1.0, P3.y() * 1.0);
|
|
|
|
|
// P3 = QPointF(P3.x() + Pmirror.x(), P3.y() + Pmirror.y());
|
|
|
|
|
// QPointF P4 = p4;
|
|
|
|
|
// P4 = QPointF(P4.x() - Pmirror.x(), P4.y() - Pmirror.y());
|
|
|
|
|
// P4 = QPointF(P4.x() * -1.0, P4.y() * 1.0);
|
|
|
|
|
// P4 = QPointF(P4.x() + Pmirror.x(), P4.y() + Pmirror.y());
|
|
|
|
|
// this->ModifiSpl(P1, P2, P3, P4);
|
|
|
|
|
//}
|
2013-08-28 10:55:11 +02:00
|
|
|
|
|
2013-11-07 15:40:39 +01:00
|
|
|
|
QVector<QPointF> VSpline::SplinePoints(const QPointF &p1, const QPointF &p4, qreal angle1, qreal angle2, qreal kAsm1,
|
2013-11-04 21:35:15 +01:00
|
|
|
|
qreal kAsm2, qreal kCurve)
|
|
|
|
|
{
|
2013-08-28 10:55:11 +02:00
|
|
|
|
QLineF p1pX(p1.x(), p1.y(), p1.x() + 100, p1.y());
|
|
|
|
|
p1pX.setAngle( angle1 );
|
|
|
|
|
qreal L = 0, radius = 0, angle = 90;
|
2013-11-04 21:35:15 +01:00
|
|
|
|
radius = QLineF(QPointF(p1.x(), p4.y()), p4).length();
|
2013-08-28 10:55:11 +02:00
|
|
|
|
L = kCurve * radius * 4 / 3 * tan( angle * M_PI / 180.0 / 4 );
|
|
|
|
|
QLineF p1p2(p1.x(), p1.y(), p1.x() + L * kAsm1, p1.y());
|
|
|
|
|
p1p2.setAngle(angle1);
|
|
|
|
|
QLineF p4p3(p4.x(), p4.y(), p4.x() + L * kAsm2, p4.y());
|
|
|
|
|
p4p3.setAngle(angle2);
|
|
|
|
|
QPointF p2 = p1p2.p2();
|
|
|
|
|
QPointF p3 = p4p3.p2();
|
|
|
|
|
return GetPoints(p1, p2, p3, p4);
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-04 21:35:15 +01:00
|
|
|
|
VSpline &VSpline::operator =(const VSpline &spline)
|
|
|
|
|
{
|
2013-09-11 16:14:21 +02:00
|
|
|
|
this->p1 = spline.GetP1 ();
|
|
|
|
|
this->p2 = spline.GetP2 ();
|
|
|
|
|
this->p3 = spline.GetP3 ();
|
|
|
|
|
this->p4 = spline.GetP4 ();
|
|
|
|
|
this->angle1 = spline.GetAngle1 ();
|
|
|
|
|
this->angle2 = spline.GetAngle2 ();
|
|
|
|
|
this->kAsm1 = spline.GetKasm1();
|
|
|
|
|
this->kAsm2 = spline.GetKasm2();
|
|
|
|
|
this->kCurve = spline.GetKcurve();
|
|
|
|
|
this->points = spline.GetDataPoints();
|
|
|
|
|
this->idObject = spline.getIdObject();
|
2013-11-12 13:48:45 +01:00
|
|
|
|
this->_name = spline.name();
|
2013-09-11 16:14:21 +02:00
|
|
|
|
return *this;
|
|
|
|
|
}
|