From 2548697a9ebdec4adb3eaa5e90c6484ae51b66a6 Mon Sep 17 00:00:00 2001 From: Roman Telezhynskyi Date: Thu, 10 Mar 2016 18:09:38 +0200 Subject: [PATCH] The tool Cut Spline now supports Cubic Bezier curve. --HG-- branch : feature --- src/libs/vgeometry/vabstractcubicbezier.cpp | 106 ++++++++++++++++ src/libs/vgeometry/vabstractcubicbezier.h | 8 ++ src/libs/vgeometry/vcubicbezier.cpp | 12 ++ src/libs/vgeometry/vcubicbezier.h | 4 + src/libs/vgeometry/vspline.cpp | 119 ++---------------- src/libs/vgeometry/vspline.h | 9 +- .../vtools/dialogs/tools/dialogcutspline.cpp | 2 +- src/libs/vtools/dialogs/tools/dialogtool.cpp | 77 +++++++++++- src/libs/vtools/dialogs/tools/dialogtool.h | 2 + .../toolcut/vtoolcutspline.cpp | 2 +- .../vtools/visualization/vistoolcutspline.cpp | 14 ++- 11 files changed, 235 insertions(+), 120 deletions(-) diff --git a/src/libs/vgeometry/vabstractcubicbezier.cpp b/src/libs/vgeometry/vabstractcubicbezier.cpp index 4cee6de99..aaee895ba 100644 --- a/src/libs/vgeometry/vabstractcubicbezier.cpp +++ b/src/libs/vgeometry/vabstractcubicbezier.cpp @@ -30,6 +30,7 @@ #include "../vgeometry/vpointf.h" #include +#include //--------------------------------------------------------------------------------------------------------------------- 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); +} diff --git a/src/libs/vgeometry/vabstractcubicbezier.h b/src/libs/vgeometry/vabstractcubicbezier.h index f6d74156d..ec8d8b8b9 100644 --- a/src/libs/vgeometry/vabstractcubicbezier.h +++ b/src/libs/vgeometry/vabstractcubicbezier.h @@ -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 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 diff --git a/src/libs/vgeometry/vcubicbezier.cpp b/src/libs/vgeometry/vcubicbezier.cpp index 76080e2ad..d8503d15c 100644 --- a/src/libs/vgeometry/vcubicbezier.cpp +++ b/src/libs/vgeometry/vcubicbezier.cpp @@ -145,3 +145,15 @@ QVector 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(); +} diff --git a/src/libs/vgeometry/vcubicbezier.h b/src/libs/vgeometry/vcubicbezier.h index 939f7a708..57b9193f8 100644 --- a/src/libs/vgeometry/vcubicbezier.h +++ b/src/libs/vgeometry/vcubicbezier.h @@ -61,6 +61,10 @@ public: virtual qreal GetLength() const Q_DECL_OVERRIDE; virtual QVector GetPoints() const Q_DECL_OVERRIDE; +protected: + virtual QPointF GetControlPoint1() const Q_DECL_OVERRIDE; + virtual QPointF GetControlPoint2() const Q_DECL_OVERRIDE; + private: QSharedDataPointer d; }; diff --git a/src/libs/vgeometry/vspline.cpp b/src/libs/vgeometry/vspline.cpp index d4c7eaf3b..9501fe326 100644 --- a/src/libs/vgeometry/vspline.cpp +++ b/src/libs/vgeometry/vspline.cpp @@ -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 (); +} diff --git a/src/libs/vgeometry/vspline.h b/src/libs/vgeometry/vspline.h index 5114694ab..6b420ab3d 100644 --- a/src/libs/vgeometry/vspline.h +++ b/src/libs/vgeometry/vspline.h @@ -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 GetPoints () const Q_DECL_OVERRIDE; // cppcheck-suppress unusedFunction static QVector 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 d; QVector CalcT(qreal curveCoord1, qreal curveCoord2, qreal curveCoord3, qreal curveCoord4, diff --git a/src/libs/vtools/dialogs/tools/dialogcutspline.cpp b/src/libs/vtools/dialogs/tools/dialogcutspline.cpp index f73db268a..80d2d1167 100644 --- a/src/libs/vtools/dialogs/tools/dialogcutspline.cpp +++ b/src/libs/vtools/dialogs/tools/dialogcutspline.cpp @@ -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); diff --git a/src/libs/vtools/dialogs/tools/dialogtool.cpp b/src/libs/vtools/dialogs/tools/dialogtool.cpp index c7b762bfe..51877ee89 100644 --- a/src/libs/vtools/dialogs/tools/dialogtool.cpp +++ b/src/libs/vtools/dialogs/tools/dialogtool.cpp @@ -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(box, GOType::Arc, rule, ch1, ch2); + FillCombo(box, GOType::Arc, rule, ch1, ch2); } //--------------------------------------------------------------------------------------------------------------------- void DialogTool::FillComboBoxSplines(QComboBox *box, FillComboBox rule, const quint32 &ch1, const quint32 &ch2) const { - FillCombo(box, GOType::Spline, rule, ch1, ch2); + FillCombo(box, GOType::Spline, rule, ch1, ch2); } //--------------------------------------------------------------------------------------------------------------------- void DialogTool::FillComboBoxSplinesPath(QComboBox *box, FillComboBox rule, const quint32 &ch1, const quint32 &ch2) const { - FillCombo(box, GOType::SplinePath, rule, ch1, ch2); + FillCombo(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 >::const_iterator i; + QMap list; + for (i = objs->constBegin(); i != objs->constEnd(); ++i) + { + if (rule == FillComboBox::NoChildren) + { + if (i.key() != toolId && i.key() != ch1 && i.key() != ch2) + { + QSharedPointer obj = i.value(); + if ((obj->getType() == GOType::Spline || obj->getType() == GOType::CubicBezier) && + obj->getMode() == Draw::Calculation) + { + const auto curve = data->GeometricObject(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 obj = i.value(); + if ((obj->getType() == GOType::Spline || obj->getType() == GOType::CubicBezier) && + obj->getMode() == Draw::Calculation) + { + const auto curve = data->GeometricObject(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 > *objs = data->DataGObjects(); + const auto objs = data->DataGObjects(); QMap list; QHash >::const_iterator i; for (i = objs->constBegin(); i != objs->constEnd(); ++i) @@ -157,9 +221,10 @@ void DialogTool::FillComboBoxCurves(QComboBox *box) const { QSharedPointer 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 curve = data->GeometricObject(i.key()); + const auto curve = data->GeometricObject(i.key()); QString newName = curve->name(); int bias = 0; diff --git a/src/libs/vtools/dialogs/tools/dialogtool.h b/src/libs/vtools/dialogs/tools/dialogtool.h index 1b35bf530..7722c1ec3 100644 --- a/src/libs/vtools/dialogs/tools/dialogtool.h +++ b/src/libs/vtools/dialogs/tools/dialogtool.h @@ -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 &stylesPics) const; void FillComboBoxLineColors(QComboBox *box)const; diff --git a/src/libs/vtools/tools/drawTools/toolpoint/toolsinglepoint/toolcut/vtoolcutspline.cpp b/src/libs/vtools/tools/drawTools/toolpoint/toolsinglepoint/toolcut/vtoolcutspline.cpp index 28e040e5f..d7d7c0de2 100644 --- a/src/libs/vtools/tools/drawTools/toolpoint/toolsinglepoint/toolcut/vtoolcutspline.cpp +++ b/src/libs/vtools/tools/drawTools/toolpoint/toolsinglepoint/toolcut/vtoolcutspline.cpp @@ -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 spl = data->GeometricObject(splineId); + const auto spl = data->GeometricObject(splineId); const qreal result = CheckFormula(_id, formula, data); diff --git a/src/libs/vtools/visualization/vistoolcutspline.cpp b/src/libs/vtools/visualization/vistoolcutspline.cpp index 2af9d7836..49cb7d81e 100644 --- a/src/libs/vtools/visualization/vistoolcutspline.cpp +++ b/src/libs/vtools/visualization/vistoolcutspline.cpp @@ -53,14 +53,20 @@ void VisToolCutSpline::RefreshGeometry() { if (object1Id > NULL_ID) { - const QSharedPointer spl = Visualization::data->GeometricObject(object1Id); + const auto spl = Visualization::data->GeometricObject(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);