From 2c4312046ca59362cf003cd0c03b6d3da0be859e Mon Sep 17 00:00:00 2001 From: Roman Telezhynskyi Date: Wed, 16 Mar 2016 20:07:50 +0200 Subject: [PATCH] New classes VAbstractCubicBezierPath and VCubicBezierPath. --HG-- branch : feature --- .../vgeometry/vabstractcubicbezierpath.cpp | 203 ++++++++++++++++ src/libs/vgeometry/vabstractcubicbezierpath.h | 70 ++++++ src/libs/vgeometry/vcubicbezierpath.cpp | 218 ++++++++++++++++++ src/libs/vgeometry/vcubicbezierpath.h | 73 ++++++ src/libs/vgeometry/vcubicbezierpath_p.h | 70 ++++++ src/libs/vgeometry/vgeometry.pri | 9 +- src/libs/vgeometry/vsplinepath.cpp | 213 ++++------------- src/libs/vgeometry/vsplinepath.h | 23 +- .../vtools/dialogs/tools/dialogsplinepath.cpp | 12 +- .../drawTools/toolcurve/vtoolsplinepath.cpp | 14 +- .../toolcut/vtoolcutsplinepath.cpp | 2 +- src/libs/vtools/tools/vtooluniondetails.cpp | 4 +- .../visualization/vistoolcutsplinepath.cpp | 2 +- .../visualization/vistoolsplinepath.cpp | 8 +- 14 files changed, 709 insertions(+), 212 deletions(-) create mode 100644 src/libs/vgeometry/vabstractcubicbezierpath.cpp create mode 100644 src/libs/vgeometry/vabstractcubicbezierpath.h create mode 100644 src/libs/vgeometry/vcubicbezierpath.cpp create mode 100644 src/libs/vgeometry/vcubicbezierpath.h create mode 100644 src/libs/vgeometry/vcubicbezierpath_p.h diff --git a/src/libs/vgeometry/vabstractcubicbezierpath.cpp b/src/libs/vgeometry/vabstractcubicbezierpath.cpp new file mode 100644 index 000000000..8a5f9709d --- /dev/null +++ b/src/libs/vgeometry/vabstractcubicbezierpath.cpp @@ -0,0 +1,203 @@ +/************************************************************************ + ** + ** @file vabstractcubicbezierpath.cpp + ** @author Roman Telezhynskyi + ** @date 16 3, 2016 + ** + ** @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) 2016 Valentina project + ** All Rights Reserved. + ** + ** Valentina is free software: you can redistribute it and/or modify + ** 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. + ** + ** Valentina is distributed in the hope that it will be useful, + ** 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 . + ** + *************************************************************************/ + +#include "vabstractcubicbezierpath.h" +#include "../ifc/exception/vexception.h" +#include "vspline.h" + +#include + +//--------------------------------------------------------------------------------------------------------------------- +VAbstractCubicBezierPath::VAbstractCubicBezierPath(const GOType &type, const quint32 &idObject, const Draw &mode) + : VAbstractCurve(type, idObject, mode) +{ +} + +//--------------------------------------------------------------------------------------------------------------------- +VAbstractCubicBezierPath::VAbstractCubicBezierPath(const VAbstractCubicBezierPath &curve) + : VAbstractCurve(curve) +{ +} + +//--------------------------------------------------------------------------------------------------------------------- +VAbstractCubicBezierPath &VAbstractCubicBezierPath::operator=(const VAbstractCubicBezierPath &curve) +{ + if ( &curve == this ) + { + return *this; + } + VAbstractCurve::operator=(curve); + return *this; +} + +//--------------------------------------------------------------------------------------------------------------------- +VAbstractCubicBezierPath::~VAbstractCubicBezierPath() +{ +} + +//--------------------------------------------------------------------------------------------------------------------- +/** + * @brief GetPath return QPainterPath which reprezent spline path. + * @return path. + */ +QPainterPath VAbstractCubicBezierPath::GetPath(PathDirection direction) const +{ + QPainterPath painterPath; + for (qint32 i = 1; i <= CountSubSpl(); ++i) + { + painterPath.addPath(GetSpline(i).GetPath(direction)); + } + return painterPath; +} + +//--------------------------------------------------------------------------------------------------------------------- +/** + * @brief GetPathPoints return list of points what located on path. + * @return list. + */ +QVector VAbstractCubicBezierPath::GetPoints() const +{ + QVector pathPoints; + for (qint32 i = 1; i <= CountSubSpl(); ++i) + { + pathPoints += GetSpline(i).GetPoints(); + } + return pathPoints; +} + +//--------------------------------------------------------------------------------------------------------------------- +/** + * @brief GetLength return length of spline path. + * @return length. + */ +qreal VAbstractCubicBezierPath::GetLength() const +{ + qreal length = 0; + for (qint32 i = 1; i <= CountSubSpl(); ++i) + { + length += GetSpline(i).GetLength(); + } + return length; +} + +//--------------------------------------------------------------------------------------------------------------------- +int VAbstractCubicBezierPath::Segment(const QPointF &p) const +{ + int index = -1; + for (qint32 i = 1; i <= CountSubSpl(); ++i) + { + const qreal t = GetSpline(i).ParamT(p); + if (not qFuzzyIsNull(t) && qFuzzyCompare(t, -1)) + { + continue; + } + else + { + index = i; + break; + } + } + return index; +} + +//--------------------------------------------------------------------------------------------------------------------- +/** + * @brief CutSplinePath cut spline path into two. This method don't return two spline path. You must create spline + * paths by yourself. + * Example: + * QPointF spl1p2, spl1p3, spl2p2, spl2p3; + * qint32 p1 = 0, p2 = 0; + * QPointF point = splPath->CutSplinePath(length, p1, p2, spl1p2, spl1p3, spl2p2, spl2p3); + * + * VSplinePoint splP1 = splPath->at(p1); + * VSplinePoint splP2 = splPath->at(p2); + * VSpline spl1 = VSpline(splP1.P(), spl1p2, spl1p3, *p, splPath->GetKCurve()); + * VSpline spl2 = VSpline(*p, spl2p2, spl2p3, splP2.P(), splPath->GetKCurve()); + * @param length length first spline path. + * @param p1 index first spline point in list. + * @param p2 index second spline point in list. + * @param spl1p2 first control point first spline. + * @param spl1p3 second control point first spline. + * @param spl2p2 first control point second spline. + * @param spl2p3 second control point second spline. + * @return cutting point. + */ +QPointF VAbstractCubicBezierPath::CutSplinePath(qreal length, qint32 &p1, qint32 &p2, QPointF &spl1p2, QPointF &spl1p3, + QPointF &spl2p2, QPointF &spl2p3) const +{ + if (CountSubSpl() < 1) + { + throw VException(tr("Can't cut this spline")); + } + + //Always need return two spline paths, so we must correct wrong length. + qreal fullLength = GetLength(); + if (length < fullLength * 0.02) + { + length = fullLength * 0.02; + } + else if ( length > fullLength * 0.98) + { + length = fullLength * 0.98; + } + + fullLength = 0; + for (qint32 i = 1; i <= CountSubSpl(); ++i) + { + const VSpline spl = GetSpline(i); + fullLength += spl.GetLength(); + if (fullLength > length) + { + p1 = i-1; + p2 = i; + return spl.CutSpline(length - (fullLength - spl.GetLength()), spl1p2, spl1p3, spl2p2, spl2p3); + } + } + return QPointF(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VAbstractCubicBezierPath::CreateName() +{ + QString name; + if (CountPoints() > 0) + { + name = splPath; + name.append(QString("_%1").arg(FirstPoint().name())); + if (CountSubSpl() >= 1) + { + name.append(QString("_%1").arg(LastPoint().name())); + } + + if (GetDuplicate() > 0) + { + name += QString("_%1").arg(GetDuplicate()); + } + } + setName(name); +} diff --git a/src/libs/vgeometry/vabstractcubicbezierpath.h b/src/libs/vgeometry/vabstractcubicbezierpath.h new file mode 100644 index 000000000..d43b5a586 --- /dev/null +++ b/src/libs/vgeometry/vabstractcubicbezierpath.h @@ -0,0 +1,70 @@ +/************************************************************************ + ** + ** @file vabstractcubicbezierpath.h + ** @author Roman Telezhynskyi + ** @date 16 3, 2016 + ** + ** @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) 2016 Valentina project + ** All Rights Reserved. + ** + ** Valentina is free software: you can redistribute it and/or modify + ** 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. + ** + ** Valentina is distributed in the hope that it will be useful, + ** 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 . + ** + *************************************************************************/ + +#ifndef VABSTRACTCUBICBEZIERPATH_H +#define VABSTRACTCUBICBEZIERPATH_H + +#include "vabstractcurve.h" + +#include + +class VPointF; +class VSpline; + +class VAbstractCubicBezierPath : public VAbstractCurve +{ + Q_DECLARE_TR_FUNCTIONS(VAbstractCubicBezierPath) +public: + VAbstractCubicBezierPath(const GOType &type, const quint32 &idObject = NULL_ID, + const Draw &mode = Draw::Calculation); + VAbstractCubicBezierPath(const VAbstractCubicBezierPath &curve); + VAbstractCubicBezierPath& operator= (const VAbstractCubicBezierPath &curve); + virtual ~VAbstractCubicBezierPath(); + + virtual qint32 CountSubSpl() const =0; + virtual qint32 CountPoints() const =0; + virtual void Clear() =0; + virtual VSpline GetSpline(qint32 index) const =0; + + virtual QPainterPath GetPath(PathDirection direction = PathDirection::Hide) const Q_DECL_OVERRIDE; + virtual QVector GetPoints() const Q_DECL_OVERRIDE; + virtual qreal GetLength() const Q_DECL_OVERRIDE; + + int Segment(const QPointF &p) const; + + QPointF CutSplinePath(qreal length, qint32 &p1, qint32 &p2, QPointF &spl1p2, QPointF &spl1p3, QPointF &spl2p2, + QPointF &spl2p3) const; + +protected: + virtual void CreateName() Q_DECL_OVERRIDE; + + virtual VPointF FirstPoint() const =0; + virtual VPointF LastPoint() const =0; +}; + +#endif // VABSTRACTCUBICBEZIERPATH_H diff --git a/src/libs/vgeometry/vcubicbezierpath.cpp b/src/libs/vgeometry/vcubicbezierpath.cpp new file mode 100644 index 000000000..dbb7a31a6 --- /dev/null +++ b/src/libs/vgeometry/vcubicbezierpath.cpp @@ -0,0 +1,218 @@ +/************************************************************************ + ** + ** @file vcubicbezierpath.cpp + ** @author Roman Telezhynskyi + ** @date 16 3, 2016 + ** + ** @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) 2016 Valentina project + ** All Rights Reserved. + ** + ** Valentina is free software: you can redistribute it and/or modify + ** 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. + ** + ** Valentina is distributed in the hope that it will be useful, + ** 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 . + ** + *************************************************************************/ + +#include "vcubicbezierpath.h" +#include "vcubicbezierpath_p.h" +#include "vspline.h" +#include "../ifc/exception/vexception.h" + +#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0) +# include "../vmisc/vmath.h" +#else +# include +#endif + +//--------------------------------------------------------------------------------------------------------------------- +VCubicBezierPath::VCubicBezierPath(quint32 idObject, Draw mode) + : VAbstractCubicBezierPath(GOType::SplinePath, idObject, mode), + d(new VCubicBezierPathData()) +{ +} + +//--------------------------------------------------------------------------------------------------------------------- +VCubicBezierPath::VCubicBezierPath(const VCubicBezierPath &curve) + : VAbstractCubicBezierPath(curve), + d(curve.d) +{ +} + +//--------------------------------------------------------------------------------------------------------------------- +VCubicBezierPath::VCubicBezierPath(const QVector &points, quint32 idObject, Draw mode) + : VAbstractCubicBezierPath(GOType::SplinePath, idObject, mode), + d(new VCubicBezierPathData()) +{ + if (points.isEmpty()) + { + return; + } + + d->path = points; + CreateName(); +} + +//--------------------------------------------------------------------------------------------------------------------- +VCubicBezierPath &VCubicBezierPath::operator=(const VCubicBezierPath &curve) +{ + if ( &curve == this ) + { + return *this; + } + VAbstractCurve::operator=(curve); + d = curve.d; + return *this; +} + +//--------------------------------------------------------------------------------------------------------------------- +VCubicBezierPath::~VCubicBezierPath() +{ +} + +//--------------------------------------------------------------------------------------------------------------------- +VPointF &VCubicBezierPath::operator[](int indx) +{ + return d->path[indx]; +} + +//--------------------------------------------------------------------------------------------------------------------- +const VPointF &VCubicBezierPath::at(int indx) const +{ + return d->path[indx]; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VCubicBezierPath::append(const VPointF &point) +{ + if (d->path.size() > 0 && d->path.last().toQPointF() != point.toQPointF()) + { + return; + } + + d->path.append(point); + CreateName(); +} + +//--------------------------------------------------------------------------------------------------------------------- +qint32 VCubicBezierPath::CountSubSpl() const +{ + return qFloor(qAbs((d->path.size() - 4) / 3 + 1)); +} + +//--------------------------------------------------------------------------------------------------------------------- +qint32 VCubicBezierPath::CountPoints() const +{ + return d->path.size(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VCubicBezierPath::Clear() +{ + d->path.clear(); + SetDuplicate(0); +} + +//--------------------------------------------------------------------------------------------------------------------- +VSpline VCubicBezierPath::GetSpline(qint32 index) const +{ + if (CountPoints() < 4) + { + throw VException(tr("Not enough points to create the spline.")); + } + + if (index < 1 || index > CountSubSpl()) + { + throw VException(tr("This spline does not exist.")); + } + + const qint32 base = (index - 1) * 3; + + // Correction the first control point of each next spline curve except for the first. + QPointF p2 = d->path.at(base + 1).toQPointF(); + if (base + 1 > 1) + { + const QPointF b = d->path.at(base).toQPointF(); + QLineF foot1(b, d->path.at(base - 1).toQPointF()); + QLineF foot2(b, p2); + + foot2.setAngle(foot1.angle() + 180); + p2 = foot2.p2(); + } + + VSpline spl(d->path.at(base), p2, d->path.at(base + 2).toQPointF(), d->path.at(base + 3)); + return spl; +} + +//--------------------------------------------------------------------------------------------------------------------- +qreal VCubicBezierPath::GetStartAngle() const +{ + if (CountSubSpl() > 0) + { + return GetSpline(1).GetStartAngle(); + } + else + { + return 0; + } +} + +//--------------------------------------------------------------------------------------------------------------------- +qreal VCubicBezierPath::GetEndAngle() const +{ + const qint32 count = CountSubSpl(); + if (count > 0) + { + return GetSpline(count).GetEndAngle(); + } + else + { + return 0; + } +} + +//--------------------------------------------------------------------------------------------------------------------- +QVector VCubicBezierPath::GetSplinePath() const +{ + return d->path; +} + +//--------------------------------------------------------------------------------------------------------------------- +VPointF VCubicBezierPath::FirstPoint() const +{ + if (not d->path.isEmpty()) + { + return d->path.first(); + } + else + { + return VPointF(); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +VPointF VCubicBezierPath::LastPoint() const +{ + const qint32 count = CountSubSpl(); + if (count >= 1) + { + const qint32 base = (count - 1) * 3; + return d->path.at(base + 3);// Take last point of the last real spline + } + else + { + return VPointF(); + } +} diff --git a/src/libs/vgeometry/vcubicbezierpath.h b/src/libs/vgeometry/vcubicbezierpath.h new file mode 100644 index 000000000..ac67abd31 --- /dev/null +++ b/src/libs/vgeometry/vcubicbezierpath.h @@ -0,0 +1,73 @@ +/************************************************************************ + ** + ** @file vcubicbezierpath.h + ** @author Roman Telezhynskyi + ** @date 16 3, 2016 + ** + ** @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) 2016 Valentina project + ** All Rights Reserved. + ** + ** Valentina is free software: you can redistribute it and/or modify + ** 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. + ** + ** Valentina is distributed in the hope that it will be useful, + ** 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 . + ** + *************************************************************************/ + +#ifndef VCUBICBEZIERPATH_H +#define VCUBICBEZIERPATH_H + +#include "vabstractcubicbezierpath.h" +#include "vpointf.h" + +#include + +class VCubicBezierPathData; +class VSpline; + +class VCubicBezierPath : public VAbstractCubicBezierPath +{ + Q_DECLARE_TR_FUNCTIONS(VCubicBezierPath) +public: + explicit VCubicBezierPath(quint32 idObject = 0, Draw mode = Draw::Calculation); + VCubicBezierPath(const VCubicBezierPath &curve); + VCubicBezierPath(const QVector &points, quint32 idObject = 0, Draw mode = Draw::Calculation); + VCubicBezierPath &operator=(const VCubicBezierPath &curve); + virtual ~VCubicBezierPath(); + + VPointF &operator[](int indx); + + const VPointF &at(int indx) const; + + void append(const VPointF &point); + + virtual qint32 CountSubSpl() const Q_DECL_OVERRIDE; + virtual qint32 CountPoints() const Q_DECL_OVERRIDE; + virtual void Clear() Q_DECL_OVERRIDE; + virtual VSpline GetSpline(qint32 index) const Q_DECL_OVERRIDE; + virtual qreal GetStartAngle () const Q_DECL_OVERRIDE; + virtual qreal GetEndAngle () const Q_DECL_OVERRIDE; + + QVector GetSplinePath() const; +protected: + virtual VPointF FirstPoint() const Q_DECL_OVERRIDE; + virtual VPointF LastPoint() const Q_DECL_OVERRIDE; +private: + QSharedDataPointer d; +}; + +Q_DECLARE_TYPEINFO(VCubicBezierPath, Q_MOVABLE_TYPE); + +#endif // VCUBICBEZIERPATH_H diff --git a/src/libs/vgeometry/vcubicbezierpath_p.h b/src/libs/vgeometry/vcubicbezierpath_p.h new file mode 100644 index 000000000..34fd9b6f0 --- /dev/null +++ b/src/libs/vgeometry/vcubicbezierpath_p.h @@ -0,0 +1,70 @@ +/************************************************************************ + ** + ** @file vcubicbezierpath_p.h + ** @author Roman Telezhynskyi + ** @date 16 3, 2016 + ** + ** @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) 2016 Valentina project + ** All Rights Reserved. + ** + ** Valentina is free software: you can redistribute it and/or modify + ** 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. + ** + ** Valentina is distributed in the hope that it will be useful, + ** 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 . + ** + *************************************************************************/ + +#ifndef VCUBICBEZIERPATH_P_H +#define VCUBICBEZIERPATH_P_H + +#include + +#include "vpointf.h" + +#ifdef Q_CC_GNU + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Weffc++" +#endif + +class VCubicBezierPathData : public QSharedData +{ +public: + + VCubicBezierPathData() + : path() + {} + + VCubicBezierPathData(const VCubicBezierPathData &splPath) + : QSharedData(splPath), + path(splPath.path) + {} + + virtual ~VCubicBezierPathData(); + + /** @brief path list of points. */ + QVector path; + +private: + VCubicBezierPathData &operator=(const VCubicBezierPathData &) Q_DECL_EQ_DELETE; +}; + +VCubicBezierPathData::~VCubicBezierPathData() +{} + +#ifdef Q_CC_GNU +#pragma GCC diagnostic pop +#endif + +#endif // VCUBICBEZIERPATH_P_H diff --git a/src/libs/vgeometry/vgeometry.pri b/src/libs/vgeometry/vgeometry.pri index 94c1f4a34..60586d110 100644 --- a/src/libs/vgeometry/vgeometry.pri +++ b/src/libs/vgeometry/vgeometry.pri @@ -11,7 +11,9 @@ SOURCES += \ $$PWD/vsplinepoint.cpp \ $$PWD/vellipticalarc.cpp \ $$PWD/vcubicbezier.cpp \ - $$PWD/vabstractcubicbezier.cpp + $$PWD/vabstractcubicbezier.cpp \ + $$PWD/vabstractcubicbezierpath.cpp \ + $$PWD/vcubicbezierpath.cpp win32-msvc*:SOURCES += $$PWD/stable.cpp @@ -36,4 +38,7 @@ HEADERS += \ $$PWD/vabstractcurve_p.h \ $$PWD/vcubicbezier.h \ $$PWD/vcubicbezier_p.h \ - $$PWD/vabstractcubicbezier.h + $$PWD/vabstractcubicbezier.h \ + $$PWD/vabstractcubicbezierpath.h \ + $$PWD/vcubicbezierpath.h \ + $$PWD/vcubicbezierpath_p.h diff --git a/src/libs/vgeometry/vsplinepath.cpp b/src/libs/vgeometry/vsplinepath.cpp index 8928ef402..775e8c206 100644 --- a/src/libs/vgeometry/vsplinepath.cpp +++ b/src/libs/vgeometry/vsplinepath.cpp @@ -43,13 +43,13 @@ * @param mode mode creation spline path. */ VSplinePath::VSplinePath(quint32 idObject, Draw mode) - : VAbstractCurve(GOType::SplinePath, idObject, mode), + : VAbstractCubicBezierPath(GOType::SplinePath, idObject, mode), d(new VSplinePathData()) {} //--------------------------------------------------------------------------------------------------------------------- VSplinePath::VSplinePath(const QVector &points, qreal kCurve, quint32 idObject, Draw mode) - : VAbstractCurve(GOType::SplinePath, idObject, mode), + : VAbstractCubicBezierPath(GOType::SplinePath, idObject, mode), d(new VSplinePathData()) { if (points.size() < 3) @@ -84,7 +84,7 @@ VSplinePath::VSplinePath(const QVector &points, qreal kCurve, qui //--------------------------------------------------------------------------------------------------------------------- VSplinePath::VSplinePath(const QVector &points, quint32 idObject, Draw mode) - : VAbstractCurve(GOType::SplinePath, idObject, mode), + : VAbstractCubicBezierPath(GOType::SplinePath, idObject, mode), d(new VSplinePathData()) { if (points.isEmpty()) @@ -102,7 +102,7 @@ VSplinePath::VSplinePath(const QVector &points, quint32 idObject, * @param splPath spline path. */ VSplinePath::VSplinePath(const VSplinePath &splPath) - : VAbstractCurve(splPath), + : VAbstractCubicBezierPath(splPath), d(splPath.d) {} @@ -128,10 +128,10 @@ void VSplinePath::append(const VSplinePoint &point) //--------------------------------------------------------------------------------------------------------------------- /** - * @brief Count return count point. + * @brief CountSubSpl return count of simple splines. * @return count. */ -qint32 VSplinePath::Count() const +qint32 VSplinePath::CountSubSpl() const { if (d->path.size() == 0) { @@ -151,14 +151,16 @@ qint32 VSplinePath::Count() const */ VSpline VSplinePath::GetSpline(qint32 index) const { - if (Count()<1) + if (CountPoints()<1) { throw VException(tr("Not enough points to create the spline.")); } - if (index < 1 || index > Count()) + + if (index < 1 || index > CountSubSpl()) { throw VException(tr("This spline does not exist.")); } + const VSplinePoint &p1 = d->path.at(index-1); const VSplinePoint &p2 = d->path.at(index); VSpline spl(p1.P(), p2.P(), p1.Angle2(), p1.Angle2Formula(), p2.Angle1(), p2.Angle1Formula(), p1.Length2(), @@ -166,63 +168,6 @@ VSpline VSplinePath::GetSpline(qint32 index) const return spl; } -//--------------------------------------------------------------------------------------------------------------------- -/** - * @brief GetPath return QPainterPath which reprezent spline path. - * @return path. - */ -QPainterPath VSplinePath::GetPath(PathDirection direction) const -{ - QPainterPath painterPath; - for (qint32 i = 1; i <= Count(); ++i) - { - const VSplinePoint &p1 = d->path.at(i-1); - const VSplinePoint &p2 = d->path.at(i); - VSpline spl(p1.P(), p2.P(), p1.Angle2(), p1.Angle2Formula(), p2.Angle1(), p2.Angle1Formula(), p1.Length2(), - p1.Length2Formula(), p2.Length1(), p2.Length1Formula(), 1); - painterPath.addPath(spl.GetPath(direction)); - } - return painterPath; -} - -//--------------------------------------------------------------------------------------------------------------------- -/** - * @brief GetPathPoints return list of points what located on path. - * @return list. - */ -QVector VSplinePath::GetPoints() const -{ - QVector pathPoints; - for (qint32 i = 1; i <= Count(); ++i) - { - const VSplinePoint &p1 = d->path.at(i-1); - const VSplinePoint &p2 = d->path.at(i); - VSpline spl(p1.P(), p2.P(), p1.Angle2(), p1.Angle2Formula(), p2.Angle1(), p2.Angle1Formula(), p1.Length2(), - p1.Length2Formula(), p2.Length1(), p2.Length1Formula(), 1); - pathPoints += spl.GetPoints(); - } - return pathPoints; -} - -//--------------------------------------------------------------------------------------------------------------------- -/** - * @brief GetLength return length of spline path. - * @return length. - */ -qreal VSplinePath::GetLength() const -{ - qreal length = 0; - for (qint32 i = 1; i <= Count(); ++i) - { - const VSplinePoint &p1 = d->path.at(i-1); - const VSplinePoint &p2 = d->path.at(i); - VSpline spl(p1.P(), p2.P(), p1.Angle2(), p1.Angle2Formula(), p2.Angle1(), p2.Angle1Formula(), p1.Length2(), - p1.Length2Formula(), p2.Length1(), p2.Length1Formula(), 1); - length += spl.GetLength(); - } - return length; -} - //--------------------------------------------------------------------------------------------------------------------- /** * @brief UpdatePoint update spline point in list. @@ -232,7 +177,7 @@ qreal VSplinePath::GetLength() const */ void VSplinePath::UpdatePoint(qint32 indexSpline, const SplinePointPosition &pos, const VSplinePoint &point) { - if (indexSpline < 1 || indexSpline > Count()) + if (indexSpline < 1 || indexSpline > CountSubSpl()) { throw VException(tr("This spline does not exist.")); } @@ -255,7 +200,7 @@ void VSplinePath::UpdatePoint(qint32 indexSpline, const SplinePointPosition &pos */ VSplinePoint VSplinePath::GetSplinePoint(qint32 indexSpline, SplinePointPosition pos) const { - if (indexSpline < 1 || indexSpline > Count()) + if (indexSpline < 1 || indexSpline > CountSubSpl()) { throw VException(tr("This spline does not exist.")); } @@ -308,98 +253,12 @@ const VSplinePoint &VSplinePath::at(int indx) const return d->path[indx]; } -//--------------------------------------------------------------------------------------------------------------------- -/** - * @brief CutSplinePath cut spline path into two. This method don't return two spline path. You must create spline - * paths by yourself. - * Example: - * QPointF spl1p2, spl1p3, spl2p2, spl2p3; - * qint32 p1 = 0, p2 = 0; - * QPointF point = splPath->CutSplinePath(length, p1, p2, spl1p2, spl1p3, spl2p2, spl2p3); - * - * VSplinePoint splP1 = splPath->at(p1); - * VSplinePoint splP2 = splPath->at(p2); - * VSpline spl1 = VSpline(splP1.P(), spl1p2, spl1p3, *p, splPath->GetKCurve()); - * VSpline spl2 = VSpline(*p, spl2p2, spl2p3, splP2.P(), splPath->GetKCurve()); - * @param length length first spline path. - * @param p1 index first spline point in list. - * @param p2 index second spline point in list. - * @param spl1p2 first control point first spline. - * @param spl1p3 second control point first spline. - * @param spl2p2 first control point second spline. - * @param spl2p3 second control point second spline. - * @return cutting point. - */ -QPointF VSplinePath::CutSplinePath(qreal length, qint32 &p1, qint32 &p2, QPointF &spl1p2, QPointF &spl1p3, - QPointF &spl2p2, QPointF &spl2p3) const -{ - if (Count() < 2) - { - throw VException(tr("Can't cut spline path with one point")); - } - - //Always need return two spline paths, so we must correct wrong length. - qreal fullLength = GetLength(); - if (length < fullLength * 0.02) - { - length = fullLength * 0.02; - } - else if ( length > fullLength * 0.98) - { - length = fullLength * 0.98; - } - - fullLength = 0; - for (qint32 i = 1; i <= Count(); ++i) - { - const VSplinePoint &point1 = d->path.at(i-1); - const VSplinePoint &point2 = d->path.at(i); - VSpline spl = VSpline(point1.P(), point2.P(), point1.Angle2(), point1.Angle2Formula(), point2.Angle1(), - point2.Angle1Formula(), point1.Length2(), point1.Length2Formula(), point2.Length1(), - point2.Length1Formula(), 1); - fullLength += spl.GetLength(); - if (fullLength > length) - { - p1 = i-1; - p2 = i; - return spl.CutSpline(length - (fullLength - spl.GetLength()), spl1p2, spl1p3, spl2p2, spl2p3); - } - } - return QPointF(); -} - -//--------------------------------------------------------------------------------------------------------------------- -int VSplinePath::Segment(const QPointF &p) const -{ - int index = -1; - for (qint32 i = 1; i <= Count(); ++i) - { - const VSplinePoint &p1 = d->path.at(i-1); - const VSplinePoint &p2 = d->path.at(i); - VSpline spl = VSpline(p1.P(), p2.P(), p1.Angle2(), p1.Angle2Formula(), p2.Angle1(), p2.Angle1Formula(), - p1.Length2(), p1.Length2Formula(), p2.Length1(), p2.Length1Formula(), 1.0); - - const qreal t = spl.ParamT(p); - - if (qFloor(t) == -1) - { - continue; - } - else - { - index = i; - break; - } - } - return index; -} - //--------------------------------------------------------------------------------------------------------------------- qreal VSplinePath::GetStartAngle() const { - if (CountPoint() > 0) + if (CountPoints() > 0) { - return GetSplinePath().first().Angle1(); + return GetSplinePath().first().Angle2(); } else { @@ -410,9 +269,9 @@ qreal VSplinePath::GetStartAngle() const //--------------------------------------------------------------------------------------------------------------------- qreal VSplinePath::GetEndAngle() const { - if (CountPoint() > 0) + if (CountPoints() > 0) { - return GetSplinePath().last().Angle2(); + return GetSplinePath().last().Angle1(); } else { @@ -421,32 +280,38 @@ qreal VSplinePath::GetEndAngle() const } //--------------------------------------------------------------------------------------------------------------------- -void VSplinePath::CreateName() +VPointF VSplinePath::FirstPoint() const { - QString name; if (not d->path.isEmpty()) { - name = splPath; - name.append(QString("_%1").arg(d->path.first().P().name())); - if (d->path.size() > 1) - { - name.append(QString("_%1").arg(d->path.last().P().name())); - } - - if (GetDuplicate() > 0) - { - name += QString("_%1").arg(GetDuplicate()); - } + return d->path.first().P(); + } + else + { + return VPointF(); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +VPointF VSplinePath::LastPoint() const +{ + const qint32 count = CountSubSpl(); + if (count >= 1) + { + return d->path.at(count).P();// Take last point of the last real spline + } + else + { + return VPointF(); } - setName(name); } //--------------------------------------------------------------------------------------------------------------------- /** - * @brief CountPoint return count point. + * @brief CountPoints return count of points. * @return count. */ -qint32 VSplinePath::CountPoint() const +qint32 VSplinePath::CountPoints() const { return d->path.size(); } @@ -467,7 +332,7 @@ QVector VSplinePath::GetFSplinePath() const QVector points; points.reserve(d->path.size()); - for (qint32 i = 1; i <= Count(); ++i) + for (qint32 i = 1; i <= CountSubSpl(); ++i) { const VSplinePoint &p1 = d->path.at(i-1); const VSplinePoint &p2 = d->path.at(i); diff --git a/src/libs/vgeometry/vsplinepath.h b/src/libs/vgeometry/vsplinepath.h index d8d788367..5ec9c183f 100644 --- a/src/libs/vgeometry/vsplinepath.h +++ b/src/libs/vgeometry/vsplinepath.h @@ -29,7 +29,7 @@ #ifndef VSPLINEPATH_H #define VSPLINEPATH_H -#include "vabstractcurve.h" +#include "vabstractcubicbezierpath.h" #include "vspline.h" #include "vsplinepoint.h" #include @@ -41,7 +41,7 @@ class VSplinePathData; /** * @brief The VSplinePath class keep information about splinePath. */ -class VSplinePath :public VAbstractCurve +class VSplinePath :public VAbstractCubicBezierPath { Q_DECLARE_TR_FUNCTIONS(VSplinePath) public: @@ -56,14 +56,11 @@ public: VSplinePoint &operator[](int indx); void append(const VSplinePoint &point); - qint32 Count() const; - qint32 CountPoint() const; - void Clear(); - VSpline GetSpline(qint32 index) const; - QPainterPath GetPath(PathDirection direction = PathDirection::Hide) const; - QVector GetPoints() const; - qreal GetLength() const; + virtual qint32 CountSubSpl() const Q_DECL_OVERRIDE; + virtual qint32 CountPoints() const Q_DECL_OVERRIDE; + virtual void Clear() Q_DECL_OVERRIDE; + virtual VSpline GetSpline(qint32 index) const Q_DECL_OVERRIDE; QVector GetSplinePath() const; QVector GetFSplinePath() const; @@ -75,13 +72,9 @@ public: VSplinePoint GetSplinePoint(qint32 indexSpline, SplinePointPosition pos) const; const VSplinePoint &at(int indx) const; - - QPointF CutSplinePath(qreal length, qint32 &p1, qint32 &p2, QPointF &spl1p2, QPointF &spl1p3, QPointF &spl2p2, - QPointF &spl2p3) const; - - int Segment(const QPointF &p) const; protected: - virtual void CreateName() Q_DECL_OVERRIDE; + virtual VPointF FirstPoint() const Q_DECL_OVERRIDE; + virtual VPointF LastPoint() const Q_DECL_OVERRIDE; private: QSharedDataPointer d; }; diff --git a/src/libs/vtools/dialogs/tools/dialogsplinepath.cpp b/src/libs/vtools/dialogs/tools/dialogsplinepath.cpp index 7f0c47b0a..d9dd6e457 100644 --- a/src/libs/vtools/dialogs/tools/dialogsplinepath.cpp +++ b/src/libs/vtools/dialogs/tools/dialogsplinepath.cpp @@ -127,7 +127,7 @@ void DialogSplinePath::SetPath(const VSplinePath &value) this->path = value; ui->listWidget->blockSignals(true); ui->listWidget->clear(); - for (qint32 i = 0; i < path.CountPoint(); ++i) + for (qint32 i = 0; i < path.CountPoints(); ++i) { NewItem(path.at(i)); } @@ -179,7 +179,7 @@ void DialogSplinePath::ChosenObject(quint32 id, const SceneObject &type) SCASSERT(visPath != nullptr); visPath->setPath(path); - if (path.CountPoint() == 1) + if (path.CountPoints() == 1) { visPath->VisualMode(NULL_ID); connect(visPath, &VisToolSplinePath::ToolTip, this, &DialogTool::ShowVisToolTip); @@ -666,7 +666,7 @@ void DialogSplinePath::currentPointChanged(int index) auto first = qvariant_cast(ui->listWidget->item(0)->data(Qt::UserRole)); auto last = qvariant_cast(ui->listWidget->item(ui->listWidget->count()-1)->data(Qt::UserRole)); - if (first.P().id() == path.at(0).P().id() && last.P().id() == path.at(path.CountPoint()-1).P().id()) + if (first.P().id() == path.at(0).P().id() && last.P().id() == path.at(path.CountPoints()-1).P().id()) { newDuplicate = -1; ui->lineEditSplPathName->setText(path.name()); @@ -694,7 +694,7 @@ void DialogSplinePath::ShowDialog(bool click) { if (click == false) { - if (path.CountPoint() >= 3) + if (path.CountPoints() >= 3) { emit ToolTip(""); @@ -888,12 +888,12 @@ QSet DialogSplinePath::AllIds() const //--------------------------------------------------------------------------------------------------------------------- bool DialogSplinePath::IsPathValid() const { - if (path.CountPoint() < 3) + if (path.CountPoints() < 3) { return false; } - return (AllIds().size() == path.CountPoint()); + return (AllIds().size() == path.CountPoints()); } //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/libs/vtools/tools/drawTools/toolcurve/vtoolsplinepath.cpp b/src/libs/vtools/tools/drawTools/toolcurve/vtoolsplinepath.cpp index 78a51a3f7..e402ba19c 100644 --- a/src/libs/vtools/tools/drawTools/toolcurve/vtoolsplinepath.cpp +++ b/src/libs/vtools/tools/drawTools/toolcurve/vtoolsplinepath.cpp @@ -68,7 +68,7 @@ VToolSplinePath::VToolSplinePath(VAbstractPattern *doc, VContainer *data, quint3 this->setAcceptHoverEvents(true); const QSharedPointer splPath = data->GeometricObject(id); - for (qint32 i = 1; i<=splPath->Count(); ++i) + for (qint32 i = 1; i<=splPath->CountSubSpl(); ++i) { const VSpline spl = splPath->GetSpline(i); @@ -138,7 +138,7 @@ VToolSplinePath* VToolSplinePath::Create(DialogTool *dialog, VMainGraphicsScene SCASSERT(dialogTool != nullptr); VSplinePath *path = new VSplinePath(dialogTool->GetPath()); const QString color = dialogTool->GetColor(); - for (qint32 i = 0; i < path->CountPoint(); ++i) + for (qint32 i = 0; i < path->CountPoints(); ++i) { doc->IncrementReferens((*path)[i].P().getIdTool()); } @@ -302,7 +302,7 @@ void VToolSplinePath::SetSplinePathAttributes(QDomElement &domElement, const VSp void VToolSplinePath::UpdatePathPoints(VAbstractPattern *doc, QDomElement &element, const VSplinePath &path) { VDomDocument::RemoveAllChildren(element); - for (qint32 i = 0; i < path.CountPoint(); ++i) + for (qint32 i = 0; i < path.CountPoints(); ++i) { AddPathPoint(doc, element, path.at(i)); } @@ -390,7 +390,7 @@ void VToolSplinePath::AddPathPoint(VAbstractPattern *doc, QDomElement &domElemen void VToolSplinePath::RemoveReferens() { const VSplinePath splPath = *VAbstractTool::data.GeometricObject(id); - for (qint32 i = 0; i < splPath.Count(); ++i) + for (qint32 i = 0; i < splPath.CountSubSpl(); ++i) { doc->DecrementReferens(splPath.at(i).P().getIdTool()); } @@ -407,7 +407,7 @@ void VToolSplinePath::SaveDialog(QDomElement &domElement) SCASSERT(dialogTool != nullptr); const VSplinePath splPath = dialogTool->GetPath(); - for (qint32 i = 1; i <= splPath.Count(); ++i) + for (qint32 i = 1; i <= splPath.CountSubSpl(); ++i) { VSpline spl = splPath.GetSpline(i); qint32 j = i*2; @@ -605,7 +605,7 @@ bool VToolSplinePath::IsMovable(int index) const const auto splPath = VAbstractTool::data.GeometricObject(id); //index == -1 - can delete, but decided to left - if (index == -1 || index < 1 || index > splPath->Count()) + if (index == -1 || index < 1 || index > splPath->CountSubSpl()) { return false; } @@ -641,7 +641,7 @@ void VToolSplinePath::RefreshGeometry() qApp->toPixel(WidthHairLine(*VAbstractTool::data.GetPatternUnit()))/factor)); const auto splPath = VAbstractTool::data.GeometricObject(id); - for (qint32 i = 1; i<=splPath->Count(); ++i) + for (qint32 i = 1; i<=splPath->CountSubSpl(); ++i) { const qint32 j = i*2; diff --git a/src/libs/vtools/tools/drawTools/toolpoint/toolsinglepoint/toolcut/vtoolcutsplinepath.cpp b/src/libs/vtools/tools/drawTools/toolpoint/toolsinglepoint/toolcut/vtoolcutsplinepath.cpp index 2cba23674..0f8a20a82 100644 --- a/src/libs/vtools/tools/drawTools/toolpoint/toolsinglepoint/toolcut/vtoolcutsplinepath.cpp +++ b/src/libs/vtools/tools/drawTools/toolpoint/toolsinglepoint/toolcut/vtoolcutsplinepath.cpp @@ -154,7 +154,7 @@ VToolCutSplinePath* VToolCutSplinePath::Create(const quint32 _id, const QString VSplinePath *splPath1 = new VSplinePath(); VSplinePath *splPath2 = new VSplinePath(); - for (qint32 i = 0; i < splPath->CountPoint(); i++) + for (qint32 i = 0; i < splPath->CountPoints(); i++) { if (i <= p1 && i < p2) { diff --git a/src/libs/vtools/tools/vtooluniondetails.cpp b/src/libs/vtools/tools/vtooluniondetails.cpp index 39d1a1b45..0cce48dde 100644 --- a/src/libs/vtools/tools/vtooluniondetails.cpp +++ b/src/libs/vtools/tools/vtooluniondetails.cpp @@ -216,7 +216,7 @@ void VToolUnionDetails::AddToNewDetail(VMainGraphicsScene *scene, VAbstractPatte VSplinePath *path = new VSplinePath(); path->setMode(Draw::Modeling); const QSharedPointer splinePath = data->GeometricObject(det.at(i).getId()); - for (qint32 i = 1; i <= splinePath->Count(); ++i) + for (qint32 i = 1; i <= splinePath->CountSubSpl(); ++i) { const VSplinePoint &point1 = splinePath->at(i-1); const VSplinePoint &point2 = splinePath->at(i); @@ -366,7 +366,7 @@ void VToolUnionDetails::UpdatePoints(VContainer *data, const VDetail &det, const path->setMode(Draw::Modeling); const QSharedPointer splinePath = data->GeometricObject(det.at(i).getId()); SCASSERT(splinePath != nullptr); - for (qint32 i = 1; i <= splinePath->Count(); ++i) + for (qint32 i = 1; i <= splinePath->CountSubSpl(); ++i) { const VSplinePoint &point1 = splinePath->at(i-1); const VSplinePoint &point2 = splinePath->at(i); diff --git a/src/libs/vtools/visualization/vistoolcutsplinepath.cpp b/src/libs/vtools/visualization/vistoolcutsplinepath.cpp index 2b43faf89..35737a802 100644 --- a/src/libs/vtools/visualization/vistoolcutsplinepath.cpp +++ b/src/libs/vtools/visualization/vistoolcutsplinepath.cpp @@ -73,7 +73,7 @@ void VisToolCutSplinePath::RefreshGeometry() VSplinePath spPath1 = VSplinePath(); VSplinePath spPath2 = VSplinePath(); - for (qint32 i = 0; i < splPath->CountPoint(); i++) + for (qint32 i = 0; i < splPath->CountPoints(); i++) { if (i <= p1 && i < p2) { diff --git a/src/libs/vtools/visualization/vistoolsplinepath.cpp b/src/libs/vtools/visualization/vistoolsplinepath.cpp index a9dfb6617..47e0d16fa 100644 --- a/src/libs/vtools/visualization/vistoolsplinepath.cpp +++ b/src/libs/vtools/visualization/vistoolsplinepath.cpp @@ -53,7 +53,7 @@ VisToolSplinePath::~VisToolSplinePath() //--------------------------------------------------------------------------------------------------------------------- void VisToolSplinePath::RefreshGeometry() { - if (path.CountPoint() > 0) + if (path.CountPoints() > 0) { const QVector pathPoints = path.GetSplinePath(); const int size = pathPoints.size(); @@ -68,9 +68,9 @@ void VisToolSplinePath::RefreshGeometry() { if (size > 1) { - for (qint32 i = 1; i<=path.Count(); ++i) + for (qint32 i = 1; i<=path.CountSubSpl(); ++i) { - const int preLastPoint = (path.Count() - 1) * 2; + const int preLastPoint = (path.CountSubSpl() - 1) * 2; const int lastPoint = preLastPoint + 1; VSpline spl = path.GetSpline(i); @@ -90,7 +90,7 @@ void VisToolSplinePath::RefreshGeometry() DrawPath(this, path.GetPath(PathDirection::Show), mainColor, Qt::SolidLine, Qt::RoundCap); } - if (path.CountPoint() < 3) + if (path.CountPoints() < 3) { Visualization::toolTip = tr("Curved path: select three or more points"); }