The tool Cut Spline now supports Cubic Bezier curve.

--HG--
branch : feature
This commit is contained in:
Roman Telezhynskyi 2016-03-10 18:09:38 +02:00
parent 53250a4dc4
commit 2548697a9e
11 changed files with 235 additions and 120 deletions

View file

@ -30,6 +30,7 @@
#include "../vgeometry/vpointf.h"
#include <QPainterPath>
#include <QDebug>
//---------------------------------------------------------------------------------------------------------------------
VAbstractCubicBezier::VAbstractCubicBezier(const GOType &type, const quint32 &idObject, const Draw &mode)
@ -59,6 +60,76 @@ VAbstractCubicBezier::~VAbstractCubicBezier()
{
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief CutSpline cut spline.
* @param length length first spline
* @param spl1p2 second point of first spline
* @param spl1p3 third point of first spline
* @param spl2p2 second point of second spline
* @param spl2p3 third point of second spline
* @return point of cutting. This point is forth point of first spline and first point of second spline.
*/
QPointF VAbstractCubicBezier::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 ( GetP1 ().toQPointF(), GetControlPoint1 () );
seg1_2.setLength(seg1_2.length () * parT);
QPointF p12 = seg1_2.p2();
QLineF seg2_3 ( GetControlPoint1(), GetControlPoint2 () );
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 ( GetControlPoint2 (), GetP4 ().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;
}
//---------------------------------------------------------------------------------------------------------------------
void VAbstractCubicBezier::CreateName()
{
@ -439,3 +510,38 @@ qreal VAbstractCubicBezier::LengthBezier(const QPointF &p1, const QPointF &p2, c
}
return splinePath.length();
}
//---------------------------------------------------------------------------------------------------------------------
qreal VAbstractCubicBezier::LengthT(qreal t) const
{
if (t < 0 || t > 1)
{
qDebug()<<"Wrong value t.";
return 0;
}
QLineF seg1_2 ( GetP1 ().toQPointF(), GetControlPoint1 () );
seg1_2.setLength(seg1_2.length () * t);
const QPointF p12 = seg1_2.p2();
QLineF seg2_3 ( GetControlPoint1 (), GetControlPoint2 () );
seg2_3.setLength(seg2_3.length () * t);
const QPointF p23 = seg2_3.p2();
QLineF seg12_23 ( p12, p23 );
seg12_23.setLength(seg12_23.length () * t);
const QPointF p123 = seg12_23.p2();
QLineF seg3_4 ( GetControlPoint2 (), GetP4 ().toQPointF() );
seg3_4.setLength(seg3_4.length () * t);
const QPointF p34 = seg3_4.p2();
QLineF seg23_34 ( p23, p34 );
seg23_34.setLength(seg23_34.length () * t);
const QPointF p234 = seg23_34.p2();
QLineF seg123_234 ( p123, p234 );
seg123_234.setLength(seg123_234.length () * t);
const QPointF p1234 = seg123_234.p2();
return LengthBezier ( GetP1().toQPointF(), p12, p123, p1234);
}

View file

@ -44,6 +44,8 @@ public:
virtual VPointF GetP1 () const =0;
virtual VPointF GetP4 () const =0;
QPointF CutSpline ( qreal length, QPointF &spl1p2, QPointF &spl1p3, QPointF &spl2p2, QPointF &spl2p3) const;
protected:
virtual void CreateName() Q_DECL_OVERRIDE;
@ -53,6 +55,12 @@ protected:
static QVector<QPointF> GetCubicBezierPoints(const QPointF &p1, const QPointF &p2, const QPointF &p3,
const QPointF &p4);
static qreal LengthBezier(const QPointF &p1, const QPointF &p2, const QPointF &p3, const QPointF &p4);
virtual QPointF GetControlPoint1() const =0;
virtual QPointF GetControlPoint2() const =0;
private:
qreal LengthT(qreal t) const;
};
#endif // VABSTRACTCUBICBEZIER_H

View file

@ -145,3 +145,15 @@ QVector<QPointF> VCubicBezier::GetPoints() const
{
return GetCubicBezierPoints(GetP1().toQPointF(), GetP2().toQPointF(), GetP3().toQPointF(), GetP4().toQPointF());
}
//---------------------------------------------------------------------------------------------------------------------
QPointF VCubicBezier::GetControlPoint1() const
{
return GetP2().toQPointF();
}
//---------------------------------------------------------------------------------------------------------------------
QPointF VCubicBezier::GetControlPoint2() const
{
return GetP3().toQPointF();
}

View file

@ -61,6 +61,10 @@ public:
virtual qreal GetLength() const Q_DECL_OVERRIDE;
virtual QVector<QPointF> GetPoints() const Q_DECL_OVERRIDE;
protected:
virtual QPointF GetControlPoint1() const Q_DECL_OVERRIDE;
virtual QPointF GetControlPoint2() const Q_DECL_OVERRIDE;
private:
QSharedDataPointer<VCubicBezierData> d;
};

View file

@ -125,111 +125,6 @@ qreal VSpline::GetLength () const
return LengthBezier ( GetP1().toQPointF(), GetP2(), GetP3(), GetP4().toQPointF());
}
//---------------------------------------------------------------------------------------------------------------------
qreal VSpline::LengthT(qreal t) const
{
if (t < 0 || t > 1)
{
qDebug()<<"Wrong value t.";
return 0;
}
QLineF seg1_2 ( GetP1 ().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 (), GetP4 ().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 ( GetP1().toQPointF(), p12, p123, p1234);
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief CutSpline cut spline. GetPointP1() of base spline will return first point for first spline, GetPointP4()
* of base spline will return forth point of second spline.
* @param length length first spline
* @param spl1p2 second point of first spline
* @param spl1p3 third point of first spline
* @param spl2p2 second point of second spline
* @param spl2p3 third point of second spline
* @return point of cutting. This point is forth point of first spline and first point of second spline.
*/
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 ( GetP1 ().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 (), GetP4 ().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;
}
//---------------------------------------------------------------------------------------------------------------------
QPointF VSpline::CutSpline(qreal length, VSpline &spl1, VSpline &spl2) const
{
@ -237,7 +132,7 @@ QPointF VSpline::CutSpline(qreal length, VSpline &spl1, VSpline &spl2) const
QPointF spl1p3;
QPointF spl2p2;
QPointF spl2p3;
QPointF cutPoint = CutSpline (length, spl1p2, spl1p3, spl2p2, spl2p3 );
const QPointF cutPoint = CutSpline (length, spl1p2, spl1p3, spl2p2, spl2p3 );
spl1 = VSpline(GetP1(), spl1p2, spl1p3, cutPoint);
spl2 = VSpline(cutPoint, spl2p2, spl2p3, GetP4());
@ -598,3 +493,15 @@ qreal VSpline::ParamT (const QPointF &pBt) const
return tx;
}
//---------------------------------------------------------------------------------------------------------------------
QPointF VSpline::GetControlPoint1() const
{
return GetP2 ();
}
//---------------------------------------------------------------------------------------------------------------------
QPointF VSpline::GetControlPoint2() const
{
return GetP3 ();
}

View file

@ -86,14 +86,19 @@ public:
qreal GetKasm1() const;
qreal GetKasm2() const;
qreal GetKcurve() const;
qreal LengthT(qreal t) const;
QPointF CutSpline ( qreal length, QPointF &spl1p2, QPointF &spl1p3, QPointF &spl2p2, QPointF &spl2p3) const;
using VAbstractCubicBezier::CutSpline;
QPointF CutSpline ( qreal length, VSpline &spl1, VSpline &spl2) const;
virtual QVector<QPointF> GetPoints () const Q_DECL_OVERRIDE;
// cppcheck-suppress unusedFunction
static QVector<QPointF> SplinePoints(const QPointF &p1, const QPointF &p4, qreal angle1, qreal angle2, qreal kAsm1,
qreal kAsm2, qreal kCurve);
qreal ParamT(const QPointF &pBt) const;
protected:
virtual QPointF GetControlPoint1() const Q_DECL_OVERRIDE;
virtual QPointF GetControlPoint2() const Q_DECL_OVERRIDE;
private:
QSharedDataPointer<VSplineData> d;
QVector<qreal> CalcT(qreal curveCoord1, qreal curveCoord2, qreal curveCoord3, qreal curveCoord4,

View file

@ -61,7 +61,7 @@ DialogCutSpline::DialogCutSpline(const VContainer *data, const quint32 &toolId,
flagFormula = false;
CheckState();
FillComboBoxSplines(ui->comboBoxSpline, FillComboBox::NoChildren, ch1, ch2);
FillComboBoxSimpleSplines(ui->comboBoxSpline, FillComboBox::NoChildren, ch1, ch2);
FillComboBoxLineColors(ui->comboBoxColor);
connect(ui->toolButtonExprLength, &QPushButton::clicked, this, &DialogCutSpline::FXLength);

View file

@ -128,27 +128,91 @@ void DialogTool::FillComboBoxPoints(QComboBox *box, FillComboBox rule, const qui
//---------------------------------------------------------------------------------------------------------------------
void DialogTool::FillComboBoxArcs(QComboBox *box, FillComboBox rule, const quint32 &ch1, const quint32 &ch2) const
{
FillCombo<VArc>(box, GOType::Arc, rule, ch1, ch2);
FillCombo<VAbstractCurve>(box, GOType::Arc, rule, ch1, ch2);
}
//---------------------------------------------------------------------------------------------------------------------
void DialogTool::FillComboBoxSplines(QComboBox *box, FillComboBox rule, const quint32 &ch1, const quint32 &ch2) const
{
FillCombo<VSpline>(box, GOType::Spline, rule, ch1, ch2);
FillCombo<VAbstractCurve>(box, GOType::Spline, rule, ch1, ch2);
}
//---------------------------------------------------------------------------------------------------------------------
void DialogTool::FillComboBoxSplinesPath(QComboBox *box, FillComboBox rule, const quint32 &ch1,
const quint32 &ch2) const
{
FillCombo<VSplinePath>(box, GOType::SplinePath, rule, ch1, ch2);
FillCombo<VAbstractCurve>(box, GOType::SplinePath, rule, ch1, ch2);
}
//---------------------------------------------------------------------------------------------------------------------
void DialogTool::FillComboBoxSimpleSplines(QComboBox *box, FillComboBox rule, const quint32 &ch1,
const quint32 &ch2) const
{
SCASSERT(box != nullptr);
box->blockSignals(true);
const auto objs = data->DataGObjects();
QHash<quint32, QSharedPointer<VGObject> >::const_iterator i;
QMap<QString, quint32> list;
for (i = objs->constBegin(); i != objs->constEnd(); ++i)
{
if (rule == FillComboBox::NoChildren)
{
if (i.key() != toolId && i.key() != ch1 && i.key() != ch2)
{
QSharedPointer<VGObject> obj = i.value();
if ((obj->getType() == GOType::Spline || obj->getType() == GOType::CubicBezier) &&
obj->getMode() == Draw::Calculation)
{
const auto curve = data->GeometricObject<VAbstractCurve>(i.key());
QString newName = curve->name();
int bias = 0;
if (qApp->TrVars()->VariablesToUser(newName, 0, curve->name(), bias))
{
list[newName] = i.key();
}
else
{
list[curve->name()] = i.key();
}
}
}
}
else
{
if (i.key() != toolId)
{
QSharedPointer<VGObject> obj = i.value();
if ((obj->getType() == GOType::Spline || obj->getType() == GOType::CubicBezier) &&
obj->getMode() == Draw::Calculation)
{
const auto curve = data->GeometricObject<VAbstractCurve>(i.key());
QString newName = curve->name();
int bias = 0;
if (qApp->TrVars()->VariablesToUser(newName, 0, curve->name(), bias))
{
list[newName] = i.key();
}
else
{
list[curve->name()] = i.key();
}
}
}
}
}
FillList(box, list);
box->blockSignals(false);
}
//---------------------------------------------------------------------------------------------------------------------
void DialogTool::FillComboBoxCurves(QComboBox *box) const
{
SCASSERT(box != nullptr);
const QHash<quint32, QSharedPointer<VGObject> > *objs = data->DataGObjects();
const auto objs = data->DataGObjects();
QMap<QString, quint32> list;
QHash<quint32, QSharedPointer<VGObject> >::const_iterator i;
for (i = objs->constBegin(); i != objs->constEnd(); ++i)
@ -157,9 +221,10 @@ void DialogTool::FillComboBoxCurves(QComboBox *box) const
{
QSharedPointer<VGObject> obj = i.value();
if ((obj->getType() == GOType::Arc || obj->getType() == GOType::Spline ||
obj->getType() == GOType::SplinePath) && obj->getMode() == Draw::Calculation)
obj->getType() == GOType::SplinePath || obj->getType() == GOType::CubicBezier) &&
obj->getMode() == Draw::Calculation)
{
const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(i.key());
const auto curve = data->GeometricObject<VAbstractCurve>(i.key());
QString newName = curve->name();
int bias = 0;

View file

@ -192,6 +192,8 @@ protected:
const quint32 &ch1 = NULL_ID, const quint32 &ch2 = NULL_ID)const;
void FillComboBoxSplinesPath(QComboBox *box, FillComboBox rule = FillComboBox::Whole,
const quint32 &ch1 = NULL_ID, const quint32 &ch2 = NULL_ID)const;
void FillComboBoxSimpleSplines(QComboBox *box, FillComboBox rule = FillComboBox::Whole,
const quint32 &ch1 = NULL_ID, const quint32 &ch2 = NULL_ID)const;
void FillComboBoxCurves(QComboBox *box)const;
void FillComboBoxTypeLine(QComboBox *box, const QMap<QString, QIcon> &stylesPics) const;
void FillComboBoxLineColors(QComboBox *box)const;

View file

@ -120,7 +120,7 @@ VToolCutSpline* VToolCutSpline::Create(const quint32 _id, const QString &pointNa
VMainGraphicsScene *scene, VAbstractPattern *doc, VContainer *data,
const Document &parse, const Source &typeCreation)
{
const QSharedPointer<VSpline> spl = data->GeometricObject<VSpline>(splineId);
const auto spl = data->GeometricObject<VAbstractCubicBezier>(splineId);
const qreal result = CheckFormula(_id, formula, data);

View file

@ -53,14 +53,20 @@ void VisToolCutSpline::RefreshGeometry()
{
if (object1Id > NULL_ID)
{
const QSharedPointer<VSpline> spl = Visualization::data->GeometricObject<VSpline>(object1Id);
const auto spl = Visualization::data->GeometricObject<VAbstractCubicBezier>(object1Id);
DrawPath(this, spl->GetPath(PathDirection::Show), supportColor, Qt::SolidLine, Qt::RoundCap);
if (qFuzzyCompare(1 + length, 1 + 0) == false)
{
VSpline sp1;
VSpline sp2;
QPointF p = spl->CutSpline(length, sp1, sp2);
QPointF spl1p2;
QPointF spl1p3;
QPointF spl2p2;
QPointF spl2p3;
const QPointF p = spl->CutSpline (length, spl1p2, spl1p3, spl2p2, spl2p3 );
const VSpline sp1 = VSpline(spl->GetP1(), spl1p2, spl1p3, p);
const VSpline sp2 = VSpline(p, spl2p2, spl2p3, spl->GetP4());
DrawPoint(point, p, mainColor);
DrawPath(spl1, sp1.GetPath(PathDirection::Show), Qt::darkGreen, Qt::SolidLine, Qt::RoundCap);