From 1395e39c392a5fffdebf079d54058deeaf9973db Mon Sep 17 00:00:00 2001 From: Roman Telezhynskyi Date: Tue, 8 Mar 2016 19:48:10 +0200 Subject: [PATCH 1/4] New classes VCubicBezier and VAbstractCubicBezier. --HG-- branch : feature --- src/libs/vgeometry/vabstractcubicbezier.cpp | 441 ++++++++++++++++++++ src/libs/vgeometry/vabstractcubicbezier.h | 58 +++ src/libs/vgeometry/vcubicbezier.cpp | 142 +++++++ src/libs/vgeometry/vcubicbezier.h | 69 +++ src/libs/vgeometry/vcubicbezier_p.h | 105 +++++ src/libs/vgeometry/vgeometry.pri | 9 +- src/libs/vgeometry/vgeometrydef.h | 2 +- src/libs/vgeometry/vspline.cpp | 404 +----------------- src/libs/vgeometry/vspline.h | 27 +- 9 files changed, 843 insertions(+), 414 deletions(-) create mode 100644 src/libs/vgeometry/vabstractcubicbezier.cpp create mode 100644 src/libs/vgeometry/vabstractcubicbezier.h create mode 100644 src/libs/vgeometry/vcubicbezier.cpp create mode 100644 src/libs/vgeometry/vcubicbezier.h create mode 100644 src/libs/vgeometry/vcubicbezier_p.h diff --git a/src/libs/vgeometry/vabstractcubicbezier.cpp b/src/libs/vgeometry/vabstractcubicbezier.cpp new file mode 100644 index 000000000..4cee6de99 --- /dev/null +++ b/src/libs/vgeometry/vabstractcubicbezier.cpp @@ -0,0 +1,441 @@ +/************************************************************************ + ** + ** @file vabstractcubicbezier.cpp + ** @author Roman Telezhynskyi + ** @date 8 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 "vabstractcubicbezier.h" +#include "../vgeometry/vpointf.h" + +#include + +//--------------------------------------------------------------------------------------------------------------------- +VAbstractCubicBezier::VAbstractCubicBezier(const GOType &type, const quint32 &idObject, const Draw &mode) + : VAbstractCurve(type, idObject, mode) +{ +} + +//--------------------------------------------------------------------------------------------------------------------- +VAbstractCubicBezier::VAbstractCubicBezier(const VAbstractCubicBezier &curve) + : VAbstractCurve(curve) +{ +} + +//--------------------------------------------------------------------------------------------------------------------- +VAbstractCubicBezier &VAbstractCubicBezier::operator=(const VAbstractCubicBezier &curve) +{ + if ( &curve == this ) + { + return *this; + } + VAbstractCurve::operator=(curve); + return *this; +} + +//--------------------------------------------------------------------------------------------------------------------- +VAbstractCubicBezier::~VAbstractCubicBezier() +{ +} + +//--------------------------------------------------------------------------------------------------------------------- +void VAbstractCubicBezier::CreateName() +{ + QString name = SPL_ + QString("%1_%2").arg(GetP1().name()).arg(GetP4().name()); + if (GetDuplicate() > 0) + { + name += QString("_%1").arg(GetDuplicate()); + } + + setName(name); +} + +//--------------------------------------------------------------------------------------------------------------------- +/** + * @brief CalcSqDistance calculate squared distance. + * @param x1 х coordinate first point. + * @param y1 у coordinate first point. + * @param x2 х coordinate second point. + * @param y2 у coordinate second point. + * @return squared length. + */ +qreal VAbstractCubicBezier::CalcSqDistance(qreal x1, qreal y1, qreal x2, qreal y2) +{ + const qreal dx = x2 - x1; + const qreal dy = y2 - y1; + return dx * dx + dy * dy; +} + +//--------------------------------------------------------------------------------------------------------------------- +/** + * @brief PointBezier_r find spline point using four point of spline. + * @param x1 х coordinate first point. + * @param y1 у coordinate first point. + * @param x2 х coordinate first control point. + * @param y2 у coordinate first control point. + * @param x3 х coordinate second control point. + * @param y3 у coordinate second control point. + * @param x4 х coordinate last point. + * @param y4 у coordinate last point. + * @param level level of recursion. In the begin 0. + * @param px list х coordinat spline points. + * @param py list у coordinat spline points. + */ +void VAbstractCubicBezier::PointBezier_r(qreal x1, qreal y1, qreal x2, qreal y2, qreal x3, qreal y3, qreal x4, qreal y4, + qint16 level, QVector &px, QVector &py) +{ + if (px.size() >= 2) + { + for (int i=1; i < px.size(); ++i) + { + if (QPointF(px.at(i-1), py.at(i-1)) == QPointF(px.at(i), py.at(i))) + { + qDebug("All neighbors points in path must be unique."); + } + } + } + + const double curve_collinearity_epsilon = 1e-30; + const double curve_angle_tolerance_epsilon = 0.01; + 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; + + if (level > curve_recursion_limit) + { + return; + } + + // Calculate all the mid-points of the line segments + //---------------------- + const double x12 = (x1 + x2) / 2; + const double y12 = (y1 + y2) / 2; + const double x23 = (x2 + x3) / 2; + const double y23 = (y2 + y3) / 2; + const double x34 = (x3 + x4) / 2; + const double y34 = (y3 + y4) / 2; + const double x123 = (x12 + x23) / 2; + const double y123 = (y12 + y23) / 2; + const double x234 = (x23 + x34) / 2; + const double y234 = (y23 + y34) / 2; + const double x1234 = (x123 + x234) / 2; + const double y1234 = (y123 + y234) / 2; + + + // Try to approximate the full cubic curve by a single straight line + //------------------ + const double dx = x4-x1; + const double dy = y4-y1; + + double d2 = fabs((x2 - x4) * dy - (y2 - y4) * dx); + double d3 = fabs((x3 - x4) * dy - (y3 - y4) * dx); + + switch ((static_cast(d2 > curve_collinearity_epsilon) << 1) + + static_cast(d3 > curve_collinearity_epsilon)) + { + case 0: + { + // All collinear OR p1==p4 + //---------------------- + double k = dx*dx + dy*dy; + if (k < 0.000000001) + { + d2 = CalcSqDistance(x1, y1, x2, y2); + d3 = CalcSqDistance(x4, y4, x3, y3); + } + else + { + k = 1 / k; + { + const double da1 = x2 - x1; + const double da2 = y2 - y1; + d2 = k * (da1*dx + da2*dy); + } + { + const double da1 = x3 - x1; + const double 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); + } + } + if (d2 > d3) + { + if (d2 < m_distance_tolerance_square) + { + px.append(x2); + py.append(y2); + return; + } + } + else + { + if (d3 < m_distance_tolerance_square) + { + px.append(x3); + py.append(y3); + return; + } + } + break; + } + case 1: + { + // p1,p2,p4 are collinear, p3 is significant + //---------------------- + if (d3 * d3 <= m_distance_tolerance_square * (dx*dx + dy*dy)) + { + if (m_angle_tolerance < curve_angle_tolerance_epsilon) + { + px.append(x23); + py.append(y23); + return; + } + + // Angle Condition + //---------------------- + double 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) + { + px.append(x2); + py.append(y2); + + px.append(x3); + py.append(y3); + return; + } + + if (m_cusp_limit > 0.0 || m_cusp_limit < 0.0) + { + if (da1 > m_cusp_limit) + { + px.append(x3); + py.append(y3); + return; + } + } + } + break; + } + case 2: + { + // p1,p3,p4 are collinear, p2 is significant + //---------------------- + if (d2 * d2 <= m_distance_tolerance_square * (dx*dx + dy*dy)) + { + if (m_angle_tolerance < curve_angle_tolerance_epsilon) + { + px.append(x23); + py.append(y23); + return; + } + + // Angle Condition + //---------------------- + double da1 = fabs(atan2(y3 - y2, x3 - x2) - atan2(y2 - y1, x2 - x1)); + if (da1 >= M_PI) + { + da1 = 2*M_PI - da1; + } + + if (da1 < m_angle_tolerance) + { + px.append(x2); + py.append(y2); + + px.append(x3); + py.append(y3); + return; + } + + if (m_cusp_limit > 0.0 || m_cusp_limit < 0.0) + { + if (da1 > m_cusp_limit) + { + px.append(x2); + py.append(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); + return; + } + + // Angle & Cusp Condition + //---------------------- + const double k = atan2(y3 - y2, x3 - x2); + double da1 = fabs(k - atan2(y2 - y1, x2 - x1)); + double 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); + return; + } + + if (m_cusp_limit > 0.0 || m_cusp_limit < 0.0) + { + if (da1 > m_cusp_limit) + { + px.append(x2); + py.append(y2); + return; + } + + if (da2 > m_cusp_limit) + { + px.append(x3); + py.append(y3); + return; + } + } + } + break; + } + default: + break; + } + + // Continue subdivision + //---------------------- + PointBezier_r(x1, y1, x12, y12, x123, y123, x1234, y1234, static_cast(level + 1), px, py); + PointBezier_r(x1234, y1234, x234, y234, x34, y34, x4, y4, static_cast(level + 1), px, py); +} + +//--------------------------------------------------------------------------------------------------------------------- +/** + * @brief GetCubicBezierPoints return list with cubic bezier curve points. + * @param p1 first spline point. + * @param p2 first control point. + * @param p3 second control point. + * @param p4 last spline point. + * @return list of points. + */ +QVector VAbstractCubicBezier::GetCubicBezierPoints(const QPointF &p1, const QPointF &p2, const QPointF &p3, + const QPointF &p4) +{ + QVector pvector; + QVector x; + QVector y; + QVector& wx = x; + QVector& 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 () ); + for ( qint32 i = 0; i < x.count(); ++i ) + { + pvector.append( QPointF ( x.at(i), y.at(i)) ); + } + return pvector; +} + +//--------------------------------------------------------------------------------------------------------------------- +/** + * @brief LengthBezier return spline length using 4 spline point. + * @param p1 first spline point + * @param p2 first control point. + * @param p3 second control point. + * @param p4 last spline point. + * @return length. + */ +qreal VAbstractCubicBezier::LengthBezier(const QPointF &p1, const QPointF &p2, const QPointF &p3, const QPointF &p4) +{ + QPainterPath splinePath; + QVector points = GetCubicBezierPoints(p1, p2, p3, p4); + splinePath.moveTo(points.at(0)); + for (qint32 i = 1; i < points.count(); ++i) + { + splinePath.lineTo(points.at(i)); + } + return splinePath.length(); +} diff --git a/src/libs/vgeometry/vabstractcubicbezier.h b/src/libs/vgeometry/vabstractcubicbezier.h new file mode 100644 index 000000000..f6d74156d --- /dev/null +++ b/src/libs/vgeometry/vabstractcubicbezier.h @@ -0,0 +1,58 @@ +/************************************************************************ + ** + ** @file vabstractcubicbezier.h + ** @author Roman Telezhynskyi + ** @date 8 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 VABSTRACTCUBICBEZIER_H +#define VABSTRACTCUBICBEZIER_H + +#include "vabstractcurve.h" + +class VPointF; + +class VAbstractCubicBezier : public VAbstractCurve +{ +public: + VAbstractCubicBezier(const GOType &type, const quint32 &idObject = NULL_ID, const Draw &mode = Draw::Calculation); + VAbstractCubicBezier(const VAbstractCubicBezier &curve); + VAbstractCubicBezier& operator= (const VAbstractCubicBezier &curve); + virtual ~VAbstractCubicBezier(); + + virtual VPointF GetP1 () const =0; + virtual VPointF GetP4 () const =0; + +protected: + virtual void CreateName() Q_DECL_OVERRIDE; + + static qreal CalcSqDistance(qreal x1, qreal y1, qreal x2, qreal y2); + static void PointBezier_r(qreal x1, qreal y1, qreal x2, qreal y2, qreal x3, qreal y3, qreal x4, + qreal y4, qint16 level, QVector &px, QVector &py); + 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); +}; + +#endif // VABSTRACTCUBICBEZIER_H diff --git a/src/libs/vgeometry/vcubicbezier.cpp b/src/libs/vgeometry/vcubicbezier.cpp new file mode 100644 index 000000000..cf8d7559a --- /dev/null +++ b/src/libs/vgeometry/vcubicbezier.cpp @@ -0,0 +1,142 @@ +/************************************************************************ + ** + ** @file vcubicbezier.cpp + ** @author Roman Telezhynskyi + ** @date 8 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 "vcubicbezier.h" +#include "vcubicbezier_p.h" + +//--------------------------------------------------------------------------------------------------------------------- +VCubicBezier::VCubicBezier() + : VAbstractCubicBezier(GOType::CubicBezier), d(new VCubicBezierData) +{ +} + +//--------------------------------------------------------------------------------------------------------------------- +VCubicBezier::VCubicBezier(const VCubicBezier &curve) + : VAbstractCubicBezier(curve), d(curve.d) +{ +} + +//--------------------------------------------------------------------------------------------------------------------- +VCubicBezier::VCubicBezier(const VPointF &p1, const VPointF &p2, const VPointF &p3, const VPointF &p4, quint32 idObject, + Draw mode) + : VAbstractCubicBezier(GOType::CubicBezier, idObject, mode), d(new VCubicBezierData(p1, p2, p3, p4)) +{ + CreateName(); +} + +//--------------------------------------------------------------------------------------------------------------------- +VCubicBezier &VCubicBezier::operator=(const VCubicBezier &curve) +{ + if ( &curve == this ) + { + return *this; + } + VAbstractCubicBezier::operator=(curve); + d = curve.d; + return *this; +} + +//--------------------------------------------------------------------------------------------------------------------- +VPointF VCubicBezier::GetP1() const +{ + return d->p1; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VCubicBezier::SetP1(const VPointF &p) +{ + d->p1 = p; +} + +//--------------------------------------------------------------------------------------------------------------------- +VPointF VCubicBezier::GetP2() const +{ + return d->p2; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VCubicBezier::SetP2(const VPointF &p) +{ + d->p2 = p; +} + +//--------------------------------------------------------------------------------------------------------------------- +VPointF VCubicBezier::GetP3() const +{ + return d->p3; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VCubicBezier::SetP3(const VPointF &p) +{ + d->p3 = p; +} + +//--------------------------------------------------------------------------------------------------------------------- +VPointF VCubicBezier::GetP4() const +{ + return d->p4; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VCubicBezier::SetP4(const VPointF &p) +{ + d->p4 = p; +} + +//--------------------------------------------------------------------------------------------------------------------- +qreal VCubicBezier::GetStartAngle() const +{ + return QLineF(GetP1().toQPointF(), GetP2().toQPointF()).angle(); +} + +//--------------------------------------------------------------------------------------------------------------------- +qreal VCubicBezier::GetEndAngle() const +{ + return QLineF(GetP4().toQPointF(), GetP3().toQPointF()).angle(); +} + +//--------------------------------------------------------------------------------------------------------------------- +/** + * @brief GetLength return length of cubic bezier curve. + * @return length. + */ +qreal VCubicBezier::GetLength() const +{ + return LengthBezier (GetP1().toQPointF(), GetP2().toQPointF(), GetP3().toQPointF(), GetP4().toQPointF()); +} + +//--------------------------------------------------------------------------------------------------------------------- +/** + * @brief GetPoints return list with cubic bezier curve points. + * @return list of points. + */ +QVector VCubicBezier::GetPoints() const +{ + return GetCubicBezierPoints(GetP1().toQPointF(), GetP2().toQPointF(), GetP3().toQPointF(), GetP4().toQPointF()); +} diff --git a/src/libs/vgeometry/vcubicbezier.h b/src/libs/vgeometry/vcubicbezier.h new file mode 100644 index 000000000..720e0d9db --- /dev/null +++ b/src/libs/vgeometry/vcubicbezier.h @@ -0,0 +1,69 @@ +/************************************************************************ + ** + ** @file vcubicbezier.h + ** @author Roman Telezhynskyi + ** @date 8 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 VCUBICBEZIER_H +#define VCUBICBEZIER_H + +#include "vabstractcubicbezier.h" +#include "vpointf.h" + +class VCubicBezierData; + +class VCubicBezier : public VAbstractCubicBezier +{ +public: + VCubicBezier(); + VCubicBezier(const VCubicBezier &curve); + VCubicBezier(const VPointF &p1, const VPointF &p2, const VPointF &p3, const VPointF &p4, quint32 idObject = 0, + Draw mode = Draw::Calculation); + VCubicBezier &operator=(const VCubicBezier &curve); + + virtual VPointF GetP1() const Q_DECL_OVERRIDE; + void SetP1(const VPointF &p); + + VPointF GetP2() const; + void SetP2(const VPointF &p); + + VPointF GetP3() const; + void SetP3(const VPointF &p); + + virtual VPointF GetP4() const Q_DECL_OVERRIDE; + void SetP4(const VPointF &p); + + virtual qreal GetStartAngle() const Q_DECL_OVERRIDE; + virtual qreal GetEndAngle() const Q_DECL_OVERRIDE; + virtual qreal GetLength() const Q_DECL_OVERRIDE; + virtual QVector GetPoints() const Q_DECL_OVERRIDE; + +private: + QSharedDataPointer d; +}; + +Q_DECLARE_TYPEINFO(VCubicBezier, Q_MOVABLE_TYPE); + +#endif // VCUBICBEZIER_H diff --git a/src/libs/vgeometry/vcubicbezier_p.h b/src/libs/vgeometry/vcubicbezier_p.h new file mode 100644 index 000000000..168d2d127 --- /dev/null +++ b/src/libs/vgeometry/vcubicbezier_p.h @@ -0,0 +1,105 @@ +/************************************************************************ + ** + ** @file vcubicbezier_p.h + ** @author Roman Telezhynskyi + ** @date 8 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 VCUBICBEZIER_P_H +#define VCUBICBEZIER_P_H + +#include +#include +#include + +#include "vpointf.h" +#include "../vmisc/vabstractapplication.h" + +#ifdef Q_CC_GNU + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Weffc++" +#endif + +class VCubicBezierData : public QSharedData +{ +public: + VCubicBezierData(); + VCubicBezierData(const VCubicBezierData &spline); + VCubicBezierData(const VPointF &p1, const VPointF &p2, const VPointF &p3, const VPointF &p4); + virtual ~VCubicBezierData(); + + /** @brief p1 first spline point. */ + VPointF p1; + + /** @brief p2 fourth spline point. */ + VPointF p2; + + /** @brief p3 fourth spline point. */ + VPointF p3; + + /** @brief p4 fourth spline point. */ + VPointF p4; + +private: + VCubicBezierData &operator=(const VCubicBezierData &) Q_DECL_EQ_DELETE; +}; + +//--------------------------------------------------------------------------------------------------------------------- +VCubicBezierData::VCubicBezierData() + : p1(), + p2(), + p3(), + p4() +{ +} + +//--------------------------------------------------------------------------------------------------------------------- +VCubicBezierData::VCubicBezierData(const VCubicBezierData &curve) + : QSharedData(curve), + p1(curve.p1), + p2(curve.p2), + p3(curve.p3), + p4(curve.p4) +{ +} + +//--------------------------------------------------------------------------------------------------------------------- +VCubicBezierData::VCubicBezierData(const VPointF &p1, const VPointF &p2, const VPointF &p3, const VPointF &p4) + : p1(p1), + p2(p2), + p3(p3), + p4(p4) +{ +} + +//--------------------------------------------------------------------------------------------------------------------- +VCubicBezierData::~VCubicBezierData() +{ +} + +#ifdef Q_CC_GNU +#pragma GCC diagnostic pop +#endif + +#endif // VCUBICBEZIER_P_H diff --git a/src/libs/vgeometry/vgeometry.pri b/src/libs/vgeometry/vgeometry.pri index 1c80d0ed3..94c1f4a34 100644 --- a/src/libs/vgeometry/vgeometry.pri +++ b/src/libs/vgeometry/vgeometry.pri @@ -9,7 +9,9 @@ SOURCES += \ $$PWD/vspline.cpp \ $$PWD/vsplinepath.cpp \ $$PWD/vsplinepoint.cpp \ - $$PWD/vellipticalarc.cpp + $$PWD/vellipticalarc.cpp \ + $$PWD/vcubicbezier.cpp \ + $$PWD/vabstractcubicbezier.cpp win32-msvc*:SOURCES += $$PWD/stable.cpp @@ -31,4 +33,7 @@ HEADERS += \ $$PWD/vgeometrydef.h \ $$PWD/vellipticalarc.h \ $$PWD/vellipticalarc_p.h \ - $$PWD/vabstractcurve_p.h + $$PWD/vabstractcurve_p.h \ + $$PWD/vcubicbezier.h \ + $$PWD/vcubicbezier_p.h \ + $$PWD/vabstractcubicbezier.h diff --git a/src/libs/vgeometry/vgeometrydef.h b/src/libs/vgeometry/vgeometrydef.h index 9c8840e72..67e60764f 100644 --- a/src/libs/vgeometry/vgeometrydef.h +++ b/src/libs/vgeometry/vgeometrydef.h @@ -32,7 +32,7 @@ #include enum class Draw : char { Calculation, Modeling, Layout }; -enum class GOType : char { Point, Arc, EllipticalArc, Spline, SplinePath, Unknown }; +enum class GOType : char { Point, Arc, EllipticalArc, Spline, SplinePath, CubicBezier, Unknown }; enum class SplinePointPosition : char { FirstPoint, LastPoint }; #endif // VGEOMETRYDEF_H diff --git a/src/libs/vgeometry/vspline.cpp b/src/libs/vgeometry/vspline.cpp index 699819b93..d4c7eaf3b 100644 --- a/src/libs/vgeometry/vspline.cpp +++ b/src/libs/vgeometry/vspline.cpp @@ -32,12 +32,14 @@ #include #include +#define M_2PI 6.28318530717958647692528676655900576 + //--------------------------------------------------------------------------------------------------------------------- /** * @brief VSpline default constructor */ VSpline::VSpline() - :VAbstractCurve(GOType::Spline), d(new VSplineData) + :VAbstractCubicBezier(GOType::Spline), d(new VSplineData) {} //--------------------------------------------------------------------------------------------------------------------- @@ -46,7 +48,7 @@ VSpline::VSpline() * @param spline spline from which the copy. */ VSpline::VSpline ( const VSpline & spline ) - :VAbstractCurve(spline), d(spline.d) + :VAbstractCubicBezier(spline), d(spline.d) {} //--------------------------------------------------------------------------------------------------------------------- @@ -62,7 +64,8 @@ VSpline::VSpline ( const VSpline & spline ) */ VSpline::VSpline (VPointF p1, VPointF p4, qreal angle1, qreal angle2, qreal kAsm1, qreal kAsm2, qreal kCurve, quint32 idObject, Draw mode) - :VAbstractCurve(GOType::Spline, idObject, mode), d(new VSplineData(p1, p4, angle1, angle2, kAsm1, kAsm2, kCurve)) + : VAbstractCubicBezier(GOType::Spline, idObject, mode), + d(new VSplineData(p1, p4, angle1, angle2, kAsm1, kAsm2, kCurve)) { CreateName(); } @@ -76,7 +79,7 @@ VSpline::VSpline (VPointF p1, VPointF p4, qreal angle1, qreal angle2, qreal kAsm * @param p4 second point spline. */ VSpline::VSpline (VPointF p1, QPointF p2, QPointF p3, VPointF p4, quint32 idObject, Draw mode) - :VAbstractCurve(GOType::Spline, idObject, mode), d(new VSplineData(p1, p2, p3, p4)) + :VAbstractCubicBezier(GOType::Spline, idObject, mode), d(new VSplineData(p1, p2, p3, p4)) { CreateName(); } @@ -101,14 +104,13 @@ VSpline::VSpline (VPointF p1, QPointF p2, QPointF p3, VPointF p4, quint32 idObje VSpline::VSpline(VPointF p1, VPointF p4, qreal angle1, const QString &angle1Formula, qreal angle2, const QString &angle2Formula, qreal c1Length, const QString &c1LengthFormula, qreal c2Length, const QString &c2LengthFormula, quint32 idObject, Draw mode) - : VAbstractCurve(GOType::Spline, idObject, mode), + : VAbstractCubicBezier(GOType::Spline, idObject, mode), d(new VSplineData(p1, p4, angle1, angle1Formula, angle2,angle2Formula, c1Length, c1LengthFormula, c2Length, c2LengthFormula)) { CreateName(); } - //--------------------------------------------------------------------------------------------------------------------- VSpline::~VSpline() {} @@ -249,391 +251,7 @@ QPointF VSpline::CutSpline(qreal length, VSpline &spl1, VSpline &spl2) const */ QVector VSpline::GetPoints () const { - return GetPoints(GetP1().toQPointF(), GetP2(), GetP3(), GetP4().toQPointF()); -} - -//--------------------------------------------------------------------------------------------------------------------- -/** - * @brief GetPoints return list with spline points. - * @param p1 first spline point. - * @param p2 first control point. - * @param p3 second control point. - * @param p4 last spline point. - * @return list of points. - */ -QVector VSpline::GetPoints (const QPointF &p1, const QPointF &p2, const QPointF &p3, const QPointF &p4) -{ - QVector pvector; - QVector x; - QVector y; - QVector& wx = x; - QVector& 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 () ); - for ( qint32 i = 0; i < x.count(); ++i ) - { - pvector.append( QPointF ( x.at(i), y.at(i)) ); - } - return pvector; -} - -//--------------------------------------------------------------------------------------------------------------------- -/** - * @brief LengthBezier return spline length using 4 spline point. - * @param p1 first spline point - * @param p2 first control point. - * @param p3 second control point. - * @param p4 last spline point. - * @return length. - */ -qreal VSpline::LengthBezier ( const QPointF &p1, const QPointF &p2, const QPointF &p3, const QPointF &p4 ) -{ - QPainterPath splinePath; - QVector points = GetPoints (p1, p2, p3, p4); - splinePath.moveTo(points.at(0)); - for (qint32 i = 1; i < points.count(); ++i) - { - splinePath.lineTo(points.at(i)); - } - return splinePath.length(); -} - -//--------------------------------------------------------------------------------------------------------------------- -/** - * @brief PointBezier_r find spline point using four point of spline. - * @param x1 х coordinate first point. - * @param y1 у coordinate first point. - * @param x2 х coordinate first control point. - * @param y2 у coordinate first control point. - * @param x3 х coordinate second control point. - * @param y3 у coordinate second control point. - * @param x4 х coordinate last point. - * @param y4 у coordinate last point. - * @param level level of recursion. In the begin 0. - * @param px list х coordinat spline points. - * @param py list у coordinat spline points. - */ -void VSpline::PointBezier_r ( qreal x1, qreal y1, qreal x2, qreal y2, - qreal x3, qreal y3, qreal x4, qreal y4, - qint16 level, QVector &px, QVector &py) -{ - if (px.size() >= 2) - { - for (int i=1; i < px.size(); ++i) - { - if (QPointF(px.at(i-1), py.at(i-1)) == QPointF(px.at(i), py.at(i))) - { - qDebug("All neighbors points in path must be unique."); - } - } - } - - const double curve_collinearity_epsilon = 1e-30; - const double curve_angle_tolerance_epsilon = 0.01; - 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; - - if (level > curve_recursion_limit) - { - return; - } - - // Calculate all the mid-points of the line segments - //---------------------- - const double x12 = (x1 + x2) / 2; - const double y12 = (y1 + y2) / 2; - const double x23 = (x2 + x3) / 2; - const double y23 = (y2 + y3) / 2; - const double x34 = (x3 + x4) / 2; - const double y34 = (y3 + y4) / 2; - const double x123 = (x12 + x23) / 2; - const double y123 = (y12 + y23) / 2; - const double x234 = (x23 + x34) / 2; - const double y234 = (y23 + y34) / 2; - const double x1234 = (x123 + x234) / 2; - const double y1234 = (y123 + y234) / 2; - - - // Try to approximate the full cubic curve by a single straight line - //------------------ - const double dx = x4-x1; - const double dy = y4-y1; - - double d2 = fabs((x2 - x4) * dy - (y2 - y4) * dx); - double d3 = fabs((x3 - x4) * dy - (y3 - y4) * dx); - - switch ((static_cast(d2 > curve_collinearity_epsilon) << 1) + - static_cast(d3 > curve_collinearity_epsilon)) - { - case 0: - { - // All collinear OR p1==p4 - //---------------------- - double k = dx*dx + dy*dy; - if (k < 0.000000001) - { - d2 = CalcSqDistance(x1, y1, x2, y2); - d3 = CalcSqDistance(x4, y4, x3, y3); - } - else - { - k = 1 / k; - { - const double da1 = x2 - x1; - const double da2 = y2 - y1; - d2 = k * (da1*dx + da2*dy); - } - { - const double da1 = x3 - x1; - const double 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); - } - } - if (d2 > d3) - { - if (d2 < m_distance_tolerance_square) - { - px.append(x2); - py.append(y2); - return; - } - } - else - { - if (d3 < m_distance_tolerance_square) - { - px.append(x3); - py.append(y3); - return; - } - } - break; - } - case 1: - { - // p1,p2,p4 are collinear, p3 is significant - //---------------------- - if (d3 * d3 <= m_distance_tolerance_square * (dx*dx + dy*dy)) - { - if (m_angle_tolerance < curve_angle_tolerance_epsilon) - { - px.append(x23); - py.append(y23); - return; - } - - // Angle Condition - //---------------------- - double 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) - { - px.append(x2); - py.append(y2); - - px.append(x3); - py.append(y3); - return; - } - - if (m_cusp_limit > 0.0 || m_cusp_limit < 0.0) - { - if (da1 > m_cusp_limit) - { - px.append(x3); - py.append(y3); - return; - } - } - } - break; - } - case 2: - { - // p1,p3,p4 are collinear, p2 is significant - //---------------------- - if (d2 * d2 <= m_distance_tolerance_square * (dx*dx + dy*dy)) - { - if (m_angle_tolerance < curve_angle_tolerance_epsilon) - { - px.append(x23); - py.append(y23); - return; - } - - // Angle Condition - //---------------------- - double da1 = fabs(atan2(y3 - y2, x3 - x2) - atan2(y2 - y1, x2 - x1)); - if (da1 >= M_PI) - { - da1 = 2*M_PI - da1; - } - - if (da1 < m_angle_tolerance) - { - px.append(x2); - py.append(y2); - - px.append(x3); - py.append(y3); - return; - } - - if (m_cusp_limit > 0.0 || m_cusp_limit < 0.0) - { - if (da1 > m_cusp_limit) - { - px.append(x2); - py.append(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); - return; - } - - // Angle & Cusp Condition - //---------------------- - const double k = atan2(y3 - y2, x3 - x2); - double da1 = fabs(k - atan2(y2 - y1, x2 - x1)); - double 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); - return; - } - - if (m_cusp_limit > 0.0 || m_cusp_limit < 0.0) - { - if (da1 > m_cusp_limit) - { - px.append(x2); - py.append(y2); - return; - } - - if (da2 > m_cusp_limit) - { - px.append(x3); - py.append(y3); - return; - } - } - } - break; - } - default: - break; - } - - // Continue subdivision - //---------------------- - PointBezier_r(x1, y1, x12, y12, x123, y123, x1234, y1234, static_cast(level + 1), px, py); - PointBezier_r(x1234, y1234, x234, y234, x34, y34, x4, y4, static_cast(level + 1), px, py); -} - -//--------------------------------------------------------------------------------------------------------------------- -/** - * @brief CalcSqDistance calculate squared distance. - * @param x1 х coordinate first point. - * @param y1 у coordinate first point. - * @param x2 х coordinate second point. - * @param y2 у coordinate second point. - * @return squared length. - */ -qreal VSpline::CalcSqDistance (qreal x1, qreal y1, qreal x2, qreal y2) -{ - const qreal dx = x2 - x1; - const qreal dy = y2 - y1; - return dx * dx + dy * dy; -} - -//--------------------------------------------------------------------------------------------------------------------- -/** - * @brief CreateName create spline name. - */ -void VSpline::CreateName() -{ - QString name = SPL_ + QString("%1_%2").arg(this->GetP1().name()).arg(this->GetP4().name()); - if (GetDuplicate() > 0) - { - name += QString("_%1").arg(GetDuplicate()); - } - - setName(name); + return GetCubicBezierPoints(GetP1().toQPointF(), GetP2(), GetP3(), GetP4().toQPointF()); } //--------------------------------------------------------------------------------------------------------------------- @@ -663,7 +281,7 @@ QVector VSpline::SplinePoints(const QPointF &p1, const QPointF &p4, qre p4p3.setAngle(angle2); QPointF p2 = p1p2.p2(); QPointF p3 = p4p3.p2(); - return GetPoints(p1, p2, p3, p4); + return GetCubicBezierPoints(p1, p2, p3, p4); } //--------------------------------------------------------------------------------------------------------------------- @@ -673,7 +291,7 @@ VSpline &VSpline::operator =(const VSpline &spline) { return *this; } - VAbstractCurve::operator=(spline); + VAbstractCubicBezier::operator=(spline); d = spline.d; return *this; } diff --git a/src/libs/vgeometry/vspline.h b/src/libs/vgeometry/vspline.h index 7b09a10ec..5114694ab 100644 --- a/src/libs/vgeometry/vspline.h +++ b/src/libs/vgeometry/vspline.h @@ -29,7 +29,7 @@ #ifndef VSPLINE_H #define VSPLINE_H -#include "vabstractcurve.h" +#include "vabstractcubicbezier.h" #include "vpointf.h" #include #include @@ -37,12 +37,10 @@ class QPainterPath; class VSplineData; -#define M_2PI 6.28318530717958647692528676655900576 - /** * @brief VSpline class that implements the spline. */ -class VSpline :public VAbstractCurve +class VSpline :public VAbstractCubicBezier { public: VSpline(); @@ -54,17 +52,17 @@ public: VSpline (VPointF p1, VPointF p4, qreal angle1, const QString &angle1Formula, qreal angle2, const QString &angle2Formula, qreal c1Length, const QString &c1LengthFormula, qreal c2Length, const QString &c2LengthFormula, quint32 idObject = 0, Draw mode = Draw::Calculation); - virtual ~VSpline() Q_DECL_OVERRIDE; + virtual ~VSpline(); VSpline &operator=(const VSpline &spl); - VPointF GetP1 () const; - void SetP1 (const VPointF &p); + virtual VPointF GetP1 () const Q_DECL_OVERRIDE; + void SetP1 (const VPointF &p); QPointF GetP2 () const; QPointF GetP3 () const; - VPointF GetP4 () const; - void SetP4 (const VPointF &p); + virtual VPointF GetP4 () const Q_DECL_OVERRIDE; + void SetP4 (const VPointF &p); virtual qreal GetStartAngle () const Q_DECL_OVERRIDE; virtual qreal GetEndAngle() const Q_DECL_OVERRIDE; @@ -84,27 +82,20 @@ public: void SetC1Length(qreal length, const QString &formula); void SetC2Length(qreal length, const QString &formula); - qreal GetLength () const; + virtual qreal GetLength () const Q_DECL_OVERRIDE; 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; QPointF CutSpline ( qreal length, VSpline &spl1, VSpline &spl2) const; - QVector GetPoints () 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: - static QVector GetPoints (const QPointF &p1, const QPointF &p2, const QPointF &p3, const QPointF &p4 ); - virtual void CreateName() Q_DECL_OVERRIDE; private: QSharedDataPointer d; - static qreal LengthBezier (const QPointF &p1, const QPointF &p2, const QPointF &p3, const QPointF &p4 ); - static void PointBezier_r ( qreal x1, qreal y1, qreal x2, qreal y2, qreal x3, qreal y3, qreal x4, qreal y4, - qint16 level, QVector &px, QVector &py); - static qreal CalcSqDistance ( qreal x1, qreal y1, qreal x2, qreal y2); QVector CalcT(qreal curveCoord1, qreal curveCoord2, qreal curveCoord3, qreal curveCoord4, qreal pointCoord) const; static qint32 Cubic(QVector &x, qreal a, qreal b, qreal c); From 53250a4dc49a06ed4bef5cd7d89c028e9b18a59f Mon Sep 17 00:00:00 2001 From: Roman Telezhynskyi Date: Thu, 10 Mar 2016 15:55:04 +0200 Subject: [PATCH 2/4] Simple curve which uses point as control handle. --HG-- branch : feature --- .../core/vtooloptionspropertybrowser.cpp | 54 ++++ .../core/vtooloptionspropertybrowser.h | 3 + src/app/valentina/dialogs/dialoghistory.cpp | 8 + src/app/valentina/mainwindow.cpp | 14 + src/app/valentina/mainwindow.h | 1 + src/app/valentina/mainwindow.ui | 39 ++- src/app/valentina/share/resources/cursor.qrc | 2 + .../resources/cursor/cubic_bezier_cursor.png | Bin 0 -> 644 bytes .../cursor/cubic_bezier_cursor@2x.png | Bin 0 -> 1395 bytes .../valentina/share/resources/toolicon.qrc | 2 + .../resources/toolicon/32x32/cubic_bezier.png | Bin 0 -> 895 bytes .../toolicon/32x32/cubic_bezier@2x.png | Bin 0 -> 1983 bytes .../resources/toolicon/svg/cubic_bezier.svg | 84 ++++++ src/app/valentina/xml/vpattern.cpp | 48 +++- src/app/valentina/xml/vpattern.h | 1 + src/libs/ifc/ifcdef.cpp | 1 + src/libs/ifc/ifcdef.h | 1 + src/libs/ifc/schema/pattern/v0.2.7.xsd | 2 + src/libs/vgeometry/vcubicbezier.cpp | 5 + src/libs/vgeometry/vcubicbezier.h | 1 + src/libs/vmisc/def.h | 2 + src/libs/vtools/dialogs/dialogs.pri | 9 +- src/libs/vtools/dialogs/tooldialogs.h | 1 + .../dialogs/tools/dialogcubicbezier.cpp | 261 ++++++++++++++++++ .../vtools/dialogs/tools/dialogcubicbezier.h | 77 ++++++ .../vtools/dialogs/tools/dialogcubicbezier.ui | 148 ++++++++++ src/libs/vtools/tools/drawTools/drawtools.h | 1 + .../drawTools/toolcurve/vtoolcubicbezier.cpp | 252 +++++++++++++++++ .../drawTools/toolcurve/vtoolcubicbezier.h | 70 +++++ .../tools/drawTools/toolcurve/vtoolspline.cpp | 4 +- src/libs/vtools/tools/tools.pri | 6 +- .../visualization/vistoolcubicbezier.cpp | 122 ++++++++ .../vtools/visualization/vistoolcubicbezier.h | 62 +++++ .../vtools/visualization/visualization.pri | 6 +- 34 files changed, 1269 insertions(+), 18 deletions(-) create mode 100644 src/app/valentina/share/resources/cursor/cubic_bezier_cursor.png create mode 100644 src/app/valentina/share/resources/cursor/cubic_bezier_cursor@2x.png create mode 100644 src/app/valentina/share/resources/toolicon/32x32/cubic_bezier.png create mode 100644 src/app/valentina/share/resources/toolicon/32x32/cubic_bezier@2x.png create mode 100644 src/app/valentina/share/resources/toolicon/svg/cubic_bezier.svg create mode 100644 src/libs/vtools/dialogs/tools/dialogcubicbezier.cpp create mode 100644 src/libs/vtools/dialogs/tools/dialogcubicbezier.h create mode 100644 src/libs/vtools/dialogs/tools/dialogcubicbezier.ui create mode 100644 src/libs/vtools/tools/drawTools/toolcurve/vtoolcubicbezier.cpp create mode 100644 src/libs/vtools/tools/drawTools/toolcurve/vtoolcubicbezier.h create mode 100644 src/libs/vtools/visualization/vistoolcubicbezier.cpp create mode 100644 src/libs/vtools/visualization/vistoolcubicbezier.h diff --git a/src/app/valentina/core/vtooloptionspropertybrowser.cpp b/src/app/valentina/core/vtooloptionspropertybrowser.cpp index 5e148e876..303c70c25 100644 --- a/src/app/valentina/core/vtooloptionspropertybrowser.cpp +++ b/src/app/valentina/core/vtooloptionspropertybrowser.cpp @@ -135,6 +135,9 @@ void VToolOptionsPropertyBrowser::ShowItemOptions(QGraphicsItem *item) case VToolSpline::Type: ShowOptionsToolSpline(item); break; + case VToolCubicBezier::Type: + ShowOptionsToolCubicBezier(item); + break; case VToolSplinePath::Type: ShowOptionsToolSplinePath(item); break; @@ -243,6 +246,9 @@ void VToolOptionsPropertyBrowser::UpdateOptions() case VToolSpline::Type: UpdateOptionsToolSpline(); break; + case VToolCubicBezier::Type: + UpdateOptionsToolCubicBezier(); + break; case VToolSplinePath::Type: UpdateOptionsToolSplinePath(); break; @@ -366,6 +372,9 @@ void VToolOptionsPropertyBrowser::userChangedData(VProperty *property) case VToolSpline::Type: ChangeDataToolSpline(prop); break; + case VToolCubicBezier::Type: + ChangeDataToolCubicBezier(prop); + break; case VToolSplinePath::Type: ChangeDataToolSplinePath(prop); break; @@ -1346,6 +1355,31 @@ void VToolOptionsPropertyBrowser::ChangeDataToolSpline(VProperty *property) } } +//--------------------------------------------------------------------------------------------------------------------- +void VToolOptionsPropertyBrowser::ChangeDataToolCubicBezier(VProperty *property) +{ + SCASSERT(property != nullptr) + + const QVariant value = property->data(VProperty::DPC_Data, Qt::DisplayRole); + const QString id = propertyToId[property]; + + auto i = qgraphicsitem_cast(currentItem); + SCASSERT(i != nullptr); + + switch (PropertiesList().indexOf(id)) + { + case 0: // AttrName + Q_UNREACHABLE();//The attribute is read only + break; + case 27: // AttrTypeColor + i->SetLineColor(value.toString()); + break; + default: + qWarning()<<"Unknown property type. id = "<(item); + i->ShowVisualization(true); + formView->setTitle(tr("Cubic bezier curve")); + + AddPropertyObjectName(i, tr("Name"), true); + AddPropertyLineColor(i, tr("Color"), VAbstractTool::ColorsList(), AttrColor); +} + //--------------------------------------------------------------------------------------------------------------------- void VToolOptionsPropertyBrowser::ShowOptionsToolSplinePath(QGraphicsItem *item) { @@ -2190,6 +2235,15 @@ void VToolOptionsPropertyBrowser::UpdateOptionsToolSpline() idToProperty[AttrColor]->setValue(VLineColorProperty::IndexOfColor(VAbstractTool::ColorsList(), i->GetLineColor())); } +//--------------------------------------------------------------------------------------------------------------------- +void VToolOptionsPropertyBrowser::UpdateOptionsToolCubicBezier() +{ + auto i = qgraphicsitem_cast(currentItem); + + idToProperty[AttrName]->setValue(i->name()); + idToProperty[AttrColor]->setValue(VLineColorProperty::IndexOfColor(VAbstractTool::ColorsList(), i->GetLineColor())); +} + //--------------------------------------------------------------------------------------------------------------------- void VToolOptionsPropertyBrowser::UpdateOptionsToolSplinePath() { diff --git a/src/app/valentina/core/vtooloptionspropertybrowser.h b/src/app/valentina/core/vtooloptionspropertybrowser.h index acb6b278d..a4847e5dd 100644 --- a/src/app/valentina/core/vtooloptionspropertybrowser.h +++ b/src/app/valentina/core/vtooloptionspropertybrowser.h @@ -138,6 +138,7 @@ private: void ChangeDataToolPointFromArcAndTangent(VPE::VProperty *property); void ChangeDataToolShoulderPoint(VPE::VProperty *property); void ChangeDataToolSpline(VPE::VProperty *property); + void ChangeDataToolCubicBezier(VPE::VProperty *property); void ChangeDataToolSplinePath(VPE::VProperty *property); void ChangeDataToolTriangle(VPE::VProperty *property); void ChangeDataToolLineIntersectAxis(VPE::VProperty *property); @@ -166,6 +167,7 @@ private: void ShowOptionsToolPointFromArcAndTangent(QGraphicsItem *item); void ShowOptionsToolShoulderPoint(QGraphicsItem *item); void ShowOptionsToolSpline(QGraphicsItem *item); + void ShowOptionsToolCubicBezier(QGraphicsItem *item); void ShowOptionsToolSplinePath(QGraphicsItem *item); void ShowOptionsToolTriangle(QGraphicsItem *item); void ShowOptionsToolLineIntersectAxis(QGraphicsItem *item); @@ -194,6 +196,7 @@ private: void UpdateOptionsToolPointFromArcAndTangent(); void UpdateOptionsToolShoulderPoint(); void UpdateOptionsToolSpline(); + void UpdateOptionsToolCubicBezier(); void UpdateOptionsToolSplinePath(); void UpdateOptionsToolTriangle(); void UpdateOptionsToolLineIntersectAxis(); diff --git a/src/app/valentina/dialogs/dialoghistory.cpp b/src/app/valentina/dialogs/dialoghistory.cpp index bb6b7287c..095938371 100644 --- a/src/app/valentina/dialogs/dialoghistory.cpp +++ b/src/app/valentina/dialogs/dialoghistory.cpp @@ -29,6 +29,7 @@ #include "dialoghistory.h" #include "ui_dialoghistory.h" #include "../vgeometry/varc.h" +#include "../vgeometry/vcubicbezier.h" #include "../vgeometry/vsplinepath.h" #include "../vgeometry/vpointf.h" #include "../vtools/tools/vabstracttool.h" @@ -282,6 +283,13 @@ QString DialogHistory::Record(const VToolRecord &tool) SCASSERT(spl != nullptr); return QString(tr("Curve %1_%2")).arg(PointName(spl->GetP1().id())).arg(PointName(spl->GetP4().id())); } + case Tool::CubicBezier: + { + const QSharedPointer spl = data->GeometricObject(tool.getId()); + SCASSERT(spl != nullptr); + return QString(tr("Cubic bezier curve %1_%2")).arg(PointName(spl->GetP1().id())) + .arg(PointName(spl->GetP4().id())); + } case Tool::Arc: { const QSharedPointer arc = data->GeometricObject(tool.getId()); diff --git a/src/app/valentina/mainwindow.cpp b/src/app/valentina/mainwindow.cpp index 310c9bfaa..91a41adcc 100644 --- a/src/app/valentina/mainwindow.cpp +++ b/src/app/valentina/mainwindow.cpp @@ -783,6 +783,15 @@ void MainWindow::ToolSpline(bool checked) &MainWindow::ApplyDialog); } +//--------------------------------------------------------------------------------------------------------------------- +void MainWindow::ToolCubicBezier(bool checked) +{ + SetToolButtonWithApply(checked, Tool::CubicBezier, ":/cursor/cubic_bezier_cursor.png", + tr("Select first curve point"), + &MainWindow::ClosedDialogWithApply, + &MainWindow::ApplyDialog); +} + //--------------------------------------------------------------------------------------------------------------------- /** * @brief ToolCutSpline handler tool CutSpline. @@ -1603,6 +1612,7 @@ void MainWindow::InitToolButtons() connect(ui->toolButtonBisector, &QToolButton::clicked, this, &MainWindow::ToolBisector); connect(ui->toolButtonLineIntersect, &QToolButton::clicked, this, &MainWindow::ToolLineIntersect); connect(ui->toolButtonSpline, &QToolButton::clicked, this, &MainWindow::ToolSpline); + connect(ui->toolButtonCubicBezier, &QToolButton::clicked, this, &MainWindow::ToolCubicBezier); connect(ui->toolButtonArc, &QToolButton::clicked, this, &MainWindow::ToolArc); connect(ui->toolButtonSplinePath, &QToolButton::clicked, this, &MainWindow::ToolSplinePath); connect(ui->toolButtonPointOfContact, &QToolButton::clicked, this, &MainWindow::ToolPointOfContact); @@ -1709,6 +1719,9 @@ void MainWindow::CancelTool() case Tool::Spline: ui->toolButtonSpline->setChecked(false); break; + case Tool::CubicBezier: + ui->toolButtonCubicBezier->setChecked(false); + break; case Tool::Arc: ui->toolButtonArc->setChecked(false); break; @@ -2933,6 +2946,7 @@ void MainWindow::SetEnableTool(bool enable) ui->toolButtonBisector->setEnabled(drawTools); ui->toolButtonLineIntersect->setEnabled(drawTools); ui->toolButtonSpline->setEnabled(drawTools); + ui->toolButtonCubicBezier->setEnabled(drawTools); ui->toolButtonArc->setEnabled(drawTools); ui->toolButtonSplinePath->setEnabled(drawTools); ui->toolButtonPointOfContact->setEnabled(drawTools); diff --git a/src/app/valentina/mainwindow.h b/src/app/valentina/mainwindow.h index e3cfc6140..4e54292d4 100644 --- a/src/app/valentina/mainwindow.h +++ b/src/app/valentina/mainwindow.h @@ -108,6 +108,7 @@ public slots: void ToolBisector(bool checked); void ToolLineIntersect(bool checked); void ToolSpline(bool checked); + void ToolCubicBezier(bool checked); void ToolCutSpline(bool checked); void ToolArc(bool checked); void ToolSplinePath(bool checked); diff --git a/src/app/valentina/mainwindow.ui b/src/app/valentina/mainwindow.ui index 6477697ae..6cc18b312 100644 --- a/src/app/valentina/mainwindow.ui +++ b/src/app/valentina/mainwindow.ui @@ -462,7 +462,7 @@ 0 0 130 - 156 + 196 @@ -540,7 +540,33 @@ - + + + + false + + + Curve tool which uses point as control handle + + + ... + + + + :/toolicon/32x32/cubic_bezier.png:/toolicon/32x32/cubic_bezier.png + + + + 32 + 32 + + + + true + + + + false @@ -566,7 +592,7 @@ - + false @@ -592,7 +618,7 @@ - + false @@ -618,7 +644,7 @@ - + false @@ -2140,9 +2166,6 @@
vmaingraphicsview.h
- - toolButtonSplinePath - diff --git a/src/app/valentina/share/resources/cursor.qrc b/src/app/valentina/share/resources/cursor.qrc index ce825ea6a..bde68b73c 100644 --- a/src/app/valentina/share/resources/cursor.qrc +++ b/src/app/valentina/share/resources/cursor.qrc @@ -60,5 +60,7 @@ cursor/true_darts_cursor@2x.png cursor/intersection_curves_cursor.png cursor/intersection_curves_cursor@2x.png + cursor/cubic_bezier_cursor.png + cursor/cubic_bezier_cursor@2x.png diff --git a/src/app/valentina/share/resources/cursor/cubic_bezier_cursor.png b/src/app/valentina/share/resources/cursor/cubic_bezier_cursor.png new file mode 100644 index 0000000000000000000000000000000000000000..6c50010d27fd51fe79074ef3a354ad2f6c90298c GIT binary patch literal 644 zcmV-~0(QgHJR=-?0(oCWm{aB*-bT?-w$G^kJ<>Y|7pR8TufhyJja=6cW9;UW!b?z~Gb zIRroB@qO<5dY=38aPU9J`3_7c2@qgENrbK=_JA8n0unnt|P(#x{7c@0=kBX0_X}NDj;@5tqnk|h;{+7AvyuXf;j9D&=x{90a7h$ z1n-*e5Bbh7!1H2BZMDf&ezK z37ien9KeF-!yq|W3aYz1Xgr{kA1YV6m$$&M#n(Zl04>+kJ zP|m!oZZ*z;4Vd-ji@-g+ZyzZ$U{>k_EuelBF-L3JK}We`TFZ4oZY!knK^>O!8#v7X zfG5C1Z$r@{U{tS|)5>60gloVUpat0jV@o0HhSJOFjoSM^YZ?I`fycm$sEq-33)!Jl zN6s@rCX}dU1+R6#+RSKsmn^?j1-A(1`thvAml+uSbSeGDzG^;_dHPz_uAtLcQpUM{||L1`G+adB{4?;aox3*)fj!fK~IPh<*4 eEN|fcz5E7GmMr{R-~j#r0000MK$Nla>V*q zNJP|(`b+-^M5z9V{)qml2q7g%F#5xySYV(SQ3Qg41d-FWOcOO6Yr0aWIj7tGwcY32 zAIITFXWPB!-n;u__X8L1k8_{%Jg@US&w0+_KsD7=Q_aNu1e^fo6}uwEir#&lW|ku8 zxYq^Xq2g9&=3|(MFzb3knu!3jt|zzw%qoOY+yQ0{!U&TC%nF3*04g3K#qqE8k(WL4crb^rmhwI4LCPc^O8mg z*1#TxBNiNq!MklaAP5+__a3?1&RhWu@H(&)=h2$HB?_z4u&p1K-hgEWcEn(b$Ks5_ zp*mr>QDA|P68QEQBy;Ijao`o;a1Lcm8ige(2>k=%1Li{15B0#GUdn5#WB=NSf5Vj& z&-Nxv`{_GoH=tf8!G2&p&g@)}D4YvHY%$bYpgtHd(CxLnj~}+zBQzmg1bHvq8NUPW zV`@5p^T0Zw$7^LWNe%oq47=-KBQPS+z7Bd%WLb`am0A^CVGQpB0af`l+!gN|``v9F za2Z%QNqNU`Dm0K~J-o(hhFU*phcm&NO#gWK8N%~M?FTXPf}%T68h~~?ka$BnxIMO= z8^9%Ck<0gA0o!q&Au5UJW_;H!U`Om)+n*e@)4uea08(#YIZB&|ti)MGCKcTm9B~Sd2iV?QIONW(v1Xcqt0jKiQq|Bqu z1dV3&cdK*|RPfOk5$H}jWdTA}Va9~-}}5A^gt9!dji5?C~f7H_NKhOTGBLWN3U|$Dp zU>-!w6gN~#0w4&Fq+rt}h$alg;yO3rEVzEpvMBYz&kB9ZV6or%+^cYWvOkmrz}RVO z{DfqAyt)iQmw}y8*e)toolicon/32x32/true_darts@2x.png toolicon/32x32/intersection_curves.png toolicon/32x32/intersection_curves@2x.png + toolicon/32x32/cubic_bezier.png + toolicon/32x32/cubic_bezier@2x.png diff --git a/src/app/valentina/share/resources/toolicon/32x32/cubic_bezier.png b/src/app/valentina/share/resources/toolicon/32x32/cubic_bezier.png new file mode 100644 index 0000000000000000000000000000000000000000..def478013da1a87d854e37138f2fb4f7887fbb97 GIT binary patch literal 895 zcmV-_1AzRAP)=p^R{pQ&fHtut=P#<8vQE7b`-`fy1M8-T9~fhQbq8_}DhALtyzxw|QLL^(SOwG> z>?%cSfjVG$k+NYG>Go@azvL?6*MlB#SbUE%RnoTRh2H^3%cbd!CWRyz4ZzT> z0D@+(2j~EX#OOY6V4`GUDaE0|z;z2X00!O*w4~rgv3v(03CA}^SU7 zn|Ej8>0HeLYN6A@j{6XO2hIv`1xDY%jbizc7C3C-_mRB%qhm@clha9C)jmfQ^s}~C zDf8zTh4wr|9|BJlLW`@gy;66DJ_FeekZ*##z}OUAEJvF$6kZ3@7rv!%cUPno+--sO zC>)`%`hRYfYr+Jq7r3gh6i@^A9oTY{xpjV}5`ZME5jd!j3E})b$j*oPf)?~$=o28u V2&jw65j_9^002ovPDHLkV1n`VftvsT literal 0 HcmV?d00001 diff --git a/src/app/valentina/share/resources/toolicon/32x32/cubic_bezier@2x.png b/src/app/valentina/share/resources/toolicon/32x32/cubic_bezier@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..813a94c19f340834c72075456a01ead5df73f66b GIT binary patch literal 1983 zcmV;w2SE6VP);*FJOK*GU|w!H!J=B%y>t+&Fe^Sqg%d zrbUSMqZElsZBqM}MwDw-mdD)2#RC4N9E{h+E^RWuS6C?AAYpu~}?7~8QEiB~Xr z5RwoGB*D*_`~r=$`@HrxRH;&>N|h>As#N*^L>9XP zmy>2lC*WR%n+?Pi-WGVi2R1qEAg}O)KKQp;+^$|83_JoPeMtKd`4~6@WPQ9c_LAzTbV0el!MY6^5f zy~19gF@S_x`Gv*B1F{Cb{~B~vLYY!&hXcS3KGX~YCxHN11$+rGFfK6cz}lh~L4|Et z<Sl`(<+4*dKSqq4>;Hwa0M=GYnGy+l;ens7itb*YG9-*45 zlb)wrZrXFc#Ew@Cy^V-B?6m)|!6B~@D8vlgk^|mfC)b;|2Xxs%epf=}nkIc*4}>dk z9#99~sE8J2;0-5!1Y8TD`x`P|;JrA#Ua=>^=KxwbB- zt;sb4PfmWP$g|52@#*xsMHwIk&j8&9TmxeUvX0&QTmz%PM*_bpulwbp&7@KNr^50{ zuRR?8FjM`ac7gXGUklI2t+JcMo~iRH%XuyRHPl~!0x)U;S2gyTr%6GpWLO|STqBScBJcL*=$2#%+-plLTLh;KpGWR z3)+Z1z8Ay3K+Lvu|Mg18abIg_;=$UR05%Q~hpF zu^(5=017hRl4>;s-$mG>Xp11Vm6AV=cY(c%>`6x5m!*f{QU#S|00on2i{Gv)-$VHh z_JmwXMg#^`7z7Th$~!phPxZMcE7d?r2GCBDZYKFNK_3Lxmm&iAK+v;_e28*ZM9(6e z5?@c`Ba!!g=eOof^o$faJ8IjG#|t;_)Yzbq}AvJl(sPW=JPtgAYLz z4i_Rjr81`h+|7wwfd6o@^7{n6FENlgQcmN=5JseT0Qd4)zkT2@S$O;qv!D0pVpapV zEs1MHI5_QIt-xc60q;=>W9th+Cp7ss-%zhM=~2k_<-;J%(I|ZLzi^>g*)s-2^d209 ze_W)zaDQ^Z+p&c z4E$0ce$3S+$K5;v?E2W}fu_jIo8QSUxbgr|SQkJw0|2kU}oum(^YnOYLJHaSs@ zd;`!94*|bcn@(Ob;v>U8j0Z622KwM&cKw#A(_z5~=7?J=6LV1j^2G;vG3~Gd*rpH( zAmxIb!6rU(3S&O%D_7;<7o{jr0ghuM&Upu@n^dq8t9clXch8p)k2DImViTS59B>#b z<-PECI0DY(Z16(T3+Dv(3giU*>wpcwjo5p27>>^YFO`y>H^wGSQ7~iJjkQ4Gjv40K zD}B=|hTj1r#-_6~HQ=YibG>?k^~9 zU{vggzoPK1KAQzEnh4Mz{+&;O(}11-F(!sw!vjZe*_xC=AG`_N*GO^OaNvI6c$n@Q3*F3h?7Yhg?6?w@hcGpE z3Pu{>?~e8S27$EL|1UZazN|h>As#N*n@IS*!PjYHj RpC14K002ovPDHLkV1m^nhyefq literal 0 HcmV?d00001 diff --git a/src/app/valentina/share/resources/toolicon/svg/cubic_bezier.svg b/src/app/valentina/share/resources/toolicon/svg/cubic_bezier.svg new file mode 100644 index 000000000..b2a3d3dd7 --- /dev/null +++ b/src/app/valentina/share/resources/toolicon/svg/cubic_bezier.svg @@ -0,0 +1,84 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp index 10eb79d79..0328f3da2 100644 --- a/src/app/valentina/xml/vpattern.cpp +++ b/src/app/valentina/xml/vpattern.cpp @@ -43,6 +43,7 @@ #include "../qmuparser/qmuparsererror.h" #include "../vgeometry/varc.h" #include "../vgeometry/vsplinepath.h" +#include "../vgeometry/vcubicbezier.h" #include "../core/vapplication.h" #include "../vpatterndb/calculator.h" @@ -1938,6 +1939,46 @@ void VPattern::ParseToolSpline(VMainGraphicsScene *scene, QDomElement &domElemen } } +//--------------------------------------------------------------------------------------------------------------------- +void VPattern::ParseToolCubicBezier(VMainGraphicsScene *scene, const QDomElement &domElement, const Document &parse) +{ + SCASSERT(scene != nullptr); + Q_ASSERT_X(not domElement.isNull(), Q_FUNC_INFO, "domElement is null"); + + try + { + quint32 id = 0; + + ToolsCommonAttributes(domElement, id); + const quint32 point1 = GetParametrUInt(domElement, AttrPoint1, NULL_ID_STR); + const quint32 point2 = GetParametrUInt(domElement, AttrPoint2, NULL_ID_STR); + const quint32 point3 = GetParametrUInt(domElement, AttrPoint3, NULL_ID_STR); + const quint32 point4 = GetParametrUInt(domElement, AttrPoint4, NULL_ID_STR); + + const QString color = GetParametrString(domElement, AttrColor, ColorBlack); + const quint32 duplicate = GetParametrUInt(domElement, AttrDuplicate, "0"); + + auto p1 = data->GeometricObject(point1); + auto p2 = data->GeometricObject(point2); + auto p3 = data->GeometricObject(point3); + auto p4 = data->GeometricObject(point4); + + VCubicBezier *spline = new VCubicBezier(*p1, *p2, *p3, *p4); + if (duplicate > 0) + { + spline->SetDuplicate(duplicate); + } + + VToolCubicBezier::Create(id, spline, color, scene, this, data, parse, Source::FromFile); + } + catch (const VExceptionBadId &e) + { + VExceptionObjectError excep(tr("Error creating or updating cubic bezier curve"), domElement); + excep.AddMoreInformation(e.ErrorMessage()); + throw excep; + } +} + //--------------------------------------------------------------------------------------------------------------------- void VPattern::ParseOldToolSplinePath(VMainGraphicsScene *scene, const QDomElement &domElement, const Document &parse) { @@ -2377,7 +2418,8 @@ void VPattern::ParseSplineElement(VMainGraphicsScene *scene, QDomElement &domEle << VToolSplinePath::OldToolType /*2*/ << VToolSplinePath::ToolType /*3*/ << VNodeSpline::ToolType /*4*/ - << VNodeSplinePath::ToolType; /*5*/ + << VNodeSplinePath::ToolType /*5*/ + << VToolCubicBezier::ToolType; /*6*/ switch (splines.indexOf(type)) { case 0: //VToolSpline::OldToolType @@ -2404,6 +2446,10 @@ void VPattern::ParseSplineElement(VMainGraphicsScene *scene, QDomElement &domEle qCDebug(vXML, "VNodeSplinePath."); ParseNodeSplinePath(domElement, parse); break; + case 6: //VToolCubicBezier::ToolType + qCDebug(vXML, "VToolCubicBezier."); + ParseToolCubicBezier(scene, domElement, parse); + break; default: VException e(tr("Unknown spline type '%1'.").arg(type)); throw e; diff --git a/src/app/valentina/xml/vpattern.h b/src/app/valentina/xml/vpattern.h index 8e78a4722..08724c88c 100644 --- a/src/app/valentina/xml/vpattern.h +++ b/src/app/valentina/xml/vpattern.h @@ -171,6 +171,7 @@ private: void ParseOldToolSpline(VMainGraphicsScene *scene, const QDomElement &domElement, const Document &parse); void ParseToolSpline(VMainGraphicsScene *scene, QDomElement &domElement, const Document &parse); + void ParseToolCubicBezier(VMainGraphicsScene *scene, const QDomElement &domElement, const Document &parse); // TODO. Delete if minimal supported version is 0.2.7 void ParseOldToolSplinePath(VMainGraphicsScene *scene, const QDomElement &domElement, const Document &parse); diff --git a/src/libs/ifc/ifcdef.cpp b/src/libs/ifc/ifcdef.cpp index e79ebba23..dc05e7ca5 100644 --- a/src/libs/ifc/ifcdef.cpp +++ b/src/libs/ifc/ifcdef.cpp @@ -100,6 +100,7 @@ const QString AttrP2Line2 = QStringLiteral("p2Line2"); const QString AttrPShoulder = QStringLiteral("pShoulder"); const QString AttrPoint1 = QStringLiteral("point1"); const QString AttrPoint2 = QStringLiteral("point2"); +const QString AttrPoint3 = QStringLiteral("point3"); const QString AttrPoint4 = QStringLiteral("point4"); const QString AttrKAsm1 = QStringLiteral("kAsm1"); const QString AttrKAsm2 = QStringLiteral("kAsm2"); diff --git a/src/libs/ifc/ifcdef.h b/src/libs/ifc/ifcdef.h index 84f8f0327..108fa1a23 100644 --- a/src/libs/ifc/ifcdef.h +++ b/src/libs/ifc/ifcdef.h @@ -102,6 +102,7 @@ extern const QString AttrP2Line2; extern const QString AttrPShoulder; extern const QString AttrPoint1; extern const QString AttrPoint2; +extern const QString AttrPoint3; extern const QString AttrPoint4; extern const QString AttrKAsm1;// TODO. Delete if minimal supported version is 0.2.7 extern const QString AttrKAsm2;// TODO. Delete if minimal supported version is 0.2.7 diff --git a/src/libs/ifc/schema/pattern/v0.2.7.xsd b/src/libs/ifc/schema/pattern/v0.2.7.xsd index 3db42ee88..e96f114de 100644 --- a/src/libs/ifc/schema/pattern/v0.2.7.xsd +++ b/src/libs/ifc/schema/pattern/v0.2.7.xsd @@ -198,6 +198,8 @@ + + diff --git a/src/libs/vgeometry/vcubicbezier.cpp b/src/libs/vgeometry/vcubicbezier.cpp index cf8d7559a..76080e2ad 100644 --- a/src/libs/vgeometry/vcubicbezier.cpp +++ b/src/libs/vgeometry/vcubicbezier.cpp @@ -61,6 +61,11 @@ VCubicBezier &VCubicBezier::operator=(const VCubicBezier &curve) return *this; } +//--------------------------------------------------------------------------------------------------------------------- +VCubicBezier::~VCubicBezier() +{ +} + //--------------------------------------------------------------------------------------------------------------------- VPointF VCubicBezier::GetP1() const { diff --git a/src/libs/vgeometry/vcubicbezier.h b/src/libs/vgeometry/vcubicbezier.h index 720e0d9db..939f7a708 100644 --- a/src/libs/vgeometry/vcubicbezier.h +++ b/src/libs/vgeometry/vcubicbezier.h @@ -42,6 +42,7 @@ public: VCubicBezier(const VPointF &p1, const VPointF &p2, const VPointF &p3, const VPointF &p4, quint32 idObject = 0, Draw mode = Draw::Calculation); VCubicBezier &operator=(const VCubicBezier &curve); + virtual ~VCubicBezier(); virtual VPointF GetP1() const Q_DECL_OVERRIDE; void SetP1(const VPointF &p); diff --git a/src/libs/vmisc/def.h b/src/libs/vmisc/def.h index 9fd2a2785..516f2ab3c 100644 --- a/src/libs/vmisc/def.h +++ b/src/libs/vmisc/def.h @@ -74,6 +74,7 @@ enum class Tool : ToolVisHolderType Bisector, LineIntersect, Spline, + CubicBezier, CutSpline, CutArc, Arc, @@ -127,6 +128,7 @@ enum class Vis : ToolVisHolderType ToolPointFromArcAndTangent, ToolShoulderPoint, ToolSpline, + ToolCubicBezier, ToolTriangle, ToolCutSpline, ToolSplinePath, diff --git a/src/libs/vtools/dialogs/dialogs.pri b/src/libs/vtools/dialogs/dialogs.pri index 4116ae451..a432d4e95 100644 --- a/src/libs/vtools/dialogs/dialogs.pri +++ b/src/libs/vtools/dialogs/dialogs.pri @@ -34,7 +34,8 @@ HEADERS += \ $$PWD/support/dialogeditwrongformula.h \ $$PWD/support/dialogundo.h \ $$PWD/tools/dialogtruedarts.h \ - $$PWD/tools/dialogpointofintersectioncurves.h + $$PWD/tools/dialogpointofintersectioncurves.h \ + $$PWD/tools/dialogcubicbezier.h SOURCES += \ $$PWD/tools/dialogalongline.cpp \ @@ -68,7 +69,8 @@ SOURCES += \ $$PWD/support/dialogeditwrongformula.cpp \ $$PWD/support/dialogundo.cpp \ $$PWD/tools/dialogtruedarts.cpp \ - $$PWD/tools/dialogpointofintersectioncurves.cpp + $$PWD/tools/dialogpointofintersectioncurves.cpp \ + $$PWD/tools/dialogcubicbezier.cpp FORMS += \ $$PWD/tools/dialogalongline.ui \ @@ -101,4 +103,5 @@ FORMS += \ $$PWD/support/dialogeditwrongformula.ui \ $$PWD/support/dialogundo.ui \ $$PWD/tools/dialogtruedarts.ui \ - $$PWD/tools/dialogpointofintersectioncurves.ui + $$PWD/tools/dialogpointofintersectioncurves.ui \ + $$PWD/tools/dialogcubicbezier.ui diff --git a/src/libs/vtools/dialogs/tooldialogs.h b/src/libs/vtools/dialogs/tooldialogs.h index 9a8c4fa68..c37b25f3b 100644 --- a/src/libs/vtools/dialogs/tooldialogs.h +++ b/src/libs/vtools/dialogs/tooldialogs.h @@ -42,6 +42,7 @@ #include "dialogs/tools/dialogshoulderpoint.h" #include "dialogs/tools/dialogsinglepoint.h" #include "dialogs/tools/dialogspline.h" +#include "dialogs/tools/dialogcubicbezier.h" #include "dialogs/tools/dialogsplinepath.h" #include "dialogs/tools/dialogheight.h" #include "dialogs/tools/dialogcutarc.h" diff --git a/src/libs/vtools/dialogs/tools/dialogcubicbezier.cpp b/src/libs/vtools/dialogs/tools/dialogcubicbezier.cpp new file mode 100644 index 000000000..1f33beb96 --- /dev/null +++ b/src/libs/vtools/dialogs/tools/dialogcubicbezier.cpp @@ -0,0 +1,261 @@ +/************************************************************************ + ** + ** @file dialogcubicbezier.cpp + ** @author Roman Telezhynskyi + ** @date 10 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 "dialogcubicbezier.h" +#include "ui_dialogcubicbezier.h" +#include "../../visualization/vistoolcubicbezier.h" + +//--------------------------------------------------------------------------------------------------------------------- +DialogCubicBezier::DialogCubicBezier(const VContainer *data, const quint32 &toolId, QWidget *parent) + : DialogTool(data, toolId, parent), + ui(new Ui::DialogCubicBezier), + spl(), + newDuplicate(-1) +{ + ui->setupUi(this); + InitOkCancelApply(ui); + + FillComboBoxPoints(ui->comboBoxP1); + FillComboBoxPoints(ui->comboBoxP2); + FillComboBoxPoints(ui->comboBoxP3); + FillComboBoxPoints(ui->comboBoxP4); + FillComboBoxLineColors(ui->comboBoxColor); + + CheckState(); + + connect(ui->comboBoxP1, static_cast(&QComboBox::currentIndexChanged), + this, &DialogCubicBezier::PointNameChanged); + connect(ui->comboBoxP2, static_cast(&QComboBox::currentIndexChanged), + this, &DialogCubicBezier::PointNameChanged); + connect(ui->comboBoxP3, static_cast(&QComboBox::currentIndexChanged), + this, &DialogCubicBezier::PointNameChanged); + connect(ui->comboBoxP4, static_cast(&QComboBox::currentIndexChanged), + this, &DialogCubicBezier::PointNameChanged); + + vis = new VisToolCubicBezier(data); +} + +//--------------------------------------------------------------------------------------------------------------------- +DialogCubicBezier::~DialogCubicBezier() +{ + DeleteVisualization(); + delete ui; +} + +//--------------------------------------------------------------------------------------------------------------------- +VCubicBezier DialogCubicBezier::GetSpline() const +{ + return spl; +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogCubicBezier::SetSpline(const VCubicBezier &spline) +{ + spl = spline; + + setCurrentPointId(ui->comboBoxP1, spl.GetP1().id()); + setCurrentPointId(ui->comboBoxP2, spl.GetP2().id()); + setCurrentPointId(ui->comboBoxP3, spl.GetP3().id()); + setCurrentPointId(ui->comboBoxP4, spl.GetP4().id()); + + ui->lineEditSplineName->setText(spl.name()); + + auto path = qobject_cast(vis); + SCASSERT(path != nullptr); + + path->setObject1Id(spl.GetP1().id()); + path->setObject2Id(spl.GetP2().id()); + path->setObject3Id(spl.GetP3().id()); + path->setObject4Id(spl.GetP4().id()); +} + +//--------------------------------------------------------------------------------------------------------------------- +QString DialogCubicBezier::GetColor() const +{ + return GetComboBoxCurrentData(ui->comboBoxColor); +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogCubicBezier::SetColor(const QString &value) +{ + ChangeCurrentData(ui->comboBoxColor, value); +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogCubicBezier::ChosenObject(quint32 id, const SceneObject &type) +{ + if (prepare == false)// After first choose we ignore all objects + { + if (type == SceneObject::Point) + { + auto *path = qobject_cast(vis); + SCASSERT(path != nullptr); + + switch (number) + { + case 0: + if (SetObject(id, ui->comboBoxP1, tr("Select the second point of curve"))) + { + ++number; + path->VisualMode(id); + } + break; + case 1: + if (SetObject(id, ui->comboBoxP2, tr("Select the third point of curve"))) + { + ++number; + + path->setObject2Id(id); + path->RefreshGeometry(); + } + break; + case 2: + if (SetObject(id, ui->comboBoxP3, tr("Select the fourth point of curve"))) + { + ++number; + + path->setObject3Id(id); + path->RefreshGeometry(); + } + break; + case 3: + if (getCurrentObjectId(ui->comboBoxP1) != id) + { + if (SetObject(id, ui->comboBoxP4, "")) + { + ++number; + + path->setObject4Id(id); + path->RefreshGeometry(); + prepare = true; + DialogAccepted(); + } + } + break; + default: + break; + } + } + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogCubicBezier::PointNameChanged() +{ + QColor color = okColor; + if (getCurrentObjectId(ui->comboBoxP1) == getCurrentObjectId(ui->comboBoxP4)) + { + flagError = false; + color = errorColor; + + ui->lineEditSplineName->setText(tr("Invalid spline")); + } + else + { + flagError = true; + color = okColor; + + if (getCurrentObjectId(ui->comboBoxP1) == spl.GetP1().id() && + getCurrentObjectId(ui->comboBoxP4) == spl.GetP4().id()) + { + newDuplicate = -1; + ui->lineEditSplineName->setText(spl.name()); + } + else + { + VCubicBezier spline(*GetP1(), *GetP2(), *GetP3(), *GetP4()); + + if (not data->IsUnique(spline.name())) + { + newDuplicate = DNumber(spline.name()); + spline.SetDuplicate(newDuplicate); + } + ui->lineEditSplineName->setText(spline.name()); + } + } + ChangeColor(ui->labelName, color); + ChangeColor(ui->labelFirstPoint, color); + ChangeColor(ui->labelSecondPoint, color); + ChangeColor(ui->labelThirdPoint, color); + ChangeColor(ui->labelForthPoint, color); + CheckState(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogCubicBezier::ShowVisualization() +{ + AddVisualization(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogCubicBezier::SaveData() +{ + const auto p1 = GetP1(); + const auto p2 = GetP2(); + const auto p3 = GetP3(); + const auto p4 = GetP4(); + + spl = VCubicBezier(*p1, *p2, *p3, *p4); + + const quint32 d = spl.GetDuplicate();//Save previous value + newDuplicate <= -1 ? spl.SetDuplicate(d) : spl.SetDuplicate(static_cast(newDuplicate)); + + auto path = qobject_cast(vis); + SCASSERT(path != nullptr); + + path->setObject1Id(p1->id()); + path->setObject2Id(p2->id()); + path->setObject3Id(p3->id()); + path->setObject4Id(p4->id()); + path->SetMode(Mode::Show); + path->RefreshGeometry(); +} + +//--------------------------------------------------------------------------------------------------------------------- +const QSharedPointer DialogCubicBezier::GetP1() const +{ + return data->GeometricObject(getCurrentObjectId(ui->comboBoxP1)); +} + +//--------------------------------------------------------------------------------------------------------------------- +const QSharedPointer DialogCubicBezier::GetP2() const +{ + return data->GeometricObject(getCurrentObjectId(ui->comboBoxP2)); +} + +//--------------------------------------------------------------------------------------------------------------------- +const QSharedPointer DialogCubicBezier::GetP3() const +{ + return data->GeometricObject(getCurrentObjectId(ui->comboBoxP3)); +} + +//--------------------------------------------------------------------------------------------------------------------- +const QSharedPointer DialogCubicBezier::GetP4() const +{ + return data->GeometricObject(getCurrentObjectId(ui->comboBoxP4)); +} diff --git a/src/libs/vtools/dialogs/tools/dialogcubicbezier.h b/src/libs/vtools/dialogs/tools/dialogcubicbezier.h new file mode 100644 index 000000000..490afb13a --- /dev/null +++ b/src/libs/vtools/dialogs/tools/dialogcubicbezier.h @@ -0,0 +1,77 @@ +/************************************************************************ + ** + ** @file dialogcubicbezier.h + ** @author Roman Telezhynskyi + ** @date 10 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 DIALOGCUBICBEZIER_H +#define DIALOGCUBICBEZIER_H + +#include "dialogtool.h" +#include "../vgeometry/vcubicbezier.h" + +namespace Ui +{ + class DialogCubicBezier; +} + +class DialogCubicBezier : public DialogTool +{ + Q_OBJECT + +public: + explicit DialogCubicBezier(const VContainer *data, const quint32 &toolId, QWidget *parent = nullptr); + virtual ~DialogCubicBezier(); + + VCubicBezier GetSpline() const; + void SetSpline(const VCubicBezier &spline); + + QString GetColor() const; + void SetColor(const QString &value); +public slots: + virtual void ChosenObject(quint32 id, const SceneObject &type) Q_DECL_OVERRIDE; + virtual void PointNameChanged() Q_DECL_OVERRIDE; +protected: + virtual void ShowVisualization() Q_DECL_OVERRIDE; + /** + * @brief SaveData Put dialog data in local variables + */ + virtual void SaveData() Q_DECL_OVERRIDE; +private: + Q_DISABLE_COPY(DialogCubicBezier) + Ui::DialogCubicBezier *ui; + + /** @brief spl spline */ + VCubicBezier spl; + + qint32 newDuplicate; + + const QSharedPointer GetP1() const; + const QSharedPointer GetP2() const; + const QSharedPointer GetP3() const; + const QSharedPointer GetP4() const; +}; + +#endif // DIALOGCUBICBEZIER_H diff --git a/src/libs/vtools/dialogs/tools/dialogcubicbezier.ui b/src/libs/vtools/dialogs/tools/dialogcubicbezier.ui new file mode 100644 index 000000000..e6b53f3bd --- /dev/null +++ b/src/libs/vtools/dialogs/tools/dialogcubicbezier.ui @@ -0,0 +1,148 @@ + + + DialogCubicBezier + + + + 0 + 0 + 285 + 245 + + + + Cubic bezier + + + + :/icon/64x64/icon64x64.png:/icon/64x64/icon64x64.png + + + + + + QFormLayout::ExpandingFieldsGrow + + + + + Color: + + + + + + + + 0 + 0 + + + + + + + + Name: + + + + + + + true + + + + + + + First point: + + + + + + + + + + Second point: + + + + + + + + + + Third point: + + + + + + + + + + Fourth point: + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + buttonBox + accepted() + DialogCubicBezier + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + DialogCubicBezier + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/libs/vtools/tools/drawTools/drawtools.h b/src/libs/vtools/tools/drawTools/drawtools.h index 58ba95ad7..fa96e5bfc 100644 --- a/src/libs/vtools/tools/drawTools/drawtools.h +++ b/src/libs/vtools/tools/drawTools/drawtools.h @@ -40,6 +40,7 @@ #include "toolcurve/vtoolarc.h" #include "toolcurve/vtoolarcwithlength.h" #include "toolcurve/vtoolspline.h" +#include "toolcurve/vtoolcubicbezier.h" #include "toolcurve/vtoolsplinepath.h" #include "vtoolline.h" #include "toolpoint/toolsinglepoint/toolcut/vtoolcutspline.h" diff --git a/src/libs/vtools/tools/drawTools/toolcurve/vtoolcubicbezier.cpp b/src/libs/vtools/tools/drawTools/toolcurve/vtoolcubicbezier.cpp new file mode 100644 index 000000000..b60338dfa --- /dev/null +++ b/src/libs/vtools/tools/drawTools/toolcurve/vtoolcubicbezier.cpp @@ -0,0 +1,252 @@ +/************************************************************************ + ** + ** @file vtoolcubicbezier.cpp + ** @author Roman Telezhynskyi + ** @date 10 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 "vtoolcubicbezier.h" +#include "../vgeometry/vcubicbezier.h" +#include "../../../dialogs/tools/dialogcubicbezier.h" +#include "../../../undocommands/movespline.h" +#include "../../../visualization/vistoolcubicbezier.h" + +const QString VToolCubicBezier::ToolType = QStringLiteral("cubicBezier"); + +//--------------------------------------------------------------------------------------------------------------------- +VToolCubicBezier::VToolCubicBezier(VAbstractPattern *doc, VContainer *data, quint32 id, const QString &color, + const Source &typeCreation, QGraphicsItem *parent) + :VAbstractSpline(doc, data, id, parent) +{ + sceneType = SceneObject::Spline; + lineColor = color; + + this->setPen(QPen(Qt::black, qApp->toPixel(WidthHairLine(*VAbstractTool::data.GetPatternUnit()))/factor)); + this->setFlag(QGraphicsItem::ItemIsSelectable, true); + this->setFlag(QGraphicsItem::ItemIsFocusable, true); + this->setAcceptHoverEvents(true); + this->setPath(ToolPath()); + + ToolCreation(typeCreation); +} + +//--------------------------------------------------------------------------------------------------------------------- +VToolCubicBezier::~VToolCubicBezier() +{ +} + +//--------------------------------------------------------------------------------------------------------------------- +void VToolCubicBezier::setDialog() +{ + SCASSERT(dialog != nullptr); + auto dialogTool = qobject_cast(dialog); + SCASSERT(dialogTool != nullptr); + const auto spl = VAbstractTool::data.GeometricObject(id); + dialogTool->SetSpline(*spl); + dialogTool->SetColor(lineColor); +} + +//--------------------------------------------------------------------------------------------------------------------- +VToolCubicBezier *VToolCubicBezier::Create(DialogTool *dialog, VMainGraphicsScene *scene, VAbstractPattern *doc, + VContainer *data) +{ + SCASSERT(dialog != nullptr); + auto dialogTool = qobject_cast(dialog); + SCASSERT(dialogTool != nullptr); + + auto spl = Create(0, new VCubicBezier(dialogTool->GetSpline()), dialogTool->GetColor(), scene, doc, data, + Document::FullParse, Source::FromGui); + + if (spl != nullptr) + { + spl->dialog=dialogTool; + } + return spl; +} + +//--------------------------------------------------------------------------------------------------------------------- +VToolCubicBezier *VToolCubicBezier::Create(const quint32 _id, VCubicBezier *spline, const QString &color, + VMainGraphicsScene *scene, VAbstractPattern *doc, VContainer *data, + const Document &parse, const Source &typeCreation) +{ + quint32 id = _id; + if (typeCreation == Source::FromGui) + { + id = data->AddGObject(spline); + data->AddCurve(id); + } + else + { + data->UpdateGObject(id, spline); + data->AddCurve(id); + if (parse != Document::FullParse) + { + doc->UpdateToolData(id, data); + } + } + VDrawTool::AddRecord(id, Tool::CubicBezier, doc); + if (parse == Document::FullParse) + { + auto _spl = new VToolCubicBezier(doc, data, id, color, typeCreation); + scene->addItem(_spl); + connect(_spl, &VToolCubicBezier::ChoosedTool, scene, &VMainGraphicsScene::ChoosedItem); + connect(scene, &VMainGraphicsScene::NewFactor, _spl, &VToolCubicBezier::SetFactor); + connect(scene, &VMainGraphicsScene::DisableItem, _spl, &VToolCubicBezier::Disable); + doc->AddTool(id, _spl); + doc->IncrementReferens(spline->GetP1().getIdTool()); + doc->IncrementReferens(spline->GetP1().getIdTool()); + doc->IncrementReferens(spline->GetP1().getIdTool()); + doc->IncrementReferens(spline->GetP4().getIdTool()); + return _spl; + } + return nullptr; +} + +//--------------------------------------------------------------------------------------------------------------------- +VCubicBezier VToolCubicBezier::getSpline() const +{ + auto spline = VAbstractTool::data.GeometricObject(id); + return *spline.data(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VToolCubicBezier::setSpline(const VCubicBezier &spl) +{ + QSharedPointer obj = VAbstractTool::data.GetGObject(id); + QSharedPointer spline = qSharedPointerDynamicCast(obj); + *spline.data() = spl; + SaveOption(obj); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VToolCubicBezier::ShowVisualization(bool show) +{ + ShowToolVisualization(show); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VToolCubicBezier::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) +{ + try + { + ContextMenu(this, event); + } + catch(const VExceptionToolWasDeleted &e) + { + Q_UNUSED(e); + return;//Leave this method immediately!!! + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VToolCubicBezier::RemoveReferens() +{ + const auto spl = VAbstractTool::data.GeometricObject(id); + doc->DecrementReferens(spl->GetP1().getIdTool()); + doc->DecrementReferens(spl->GetP2().getIdTool()); + doc->DecrementReferens(spl->GetP3().getIdTool()); + doc->DecrementReferens(spl->GetP4().getIdTool()); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VToolCubicBezier::SaveDialog(QDomElement &domElement) +{ + SCASSERT(dialog != nullptr); + auto dialogTool = qobject_cast(dialog); + SCASSERT(dialogTool != nullptr); + + const VCubicBezier spl = dialogTool->GetSpline(); + + SetSplineAttributes(domElement, spl); + doc->SetAttribute(domElement, AttrColor, dialogTool->GetColor()); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VToolCubicBezier::SaveOptions(QDomElement &tag, QSharedPointer &obj) +{ + VAbstractSpline::SaveOptions(tag, obj); + + auto spl = qSharedPointerDynamicCast(obj); + SCASSERT(spl.isNull() == false); + SetSplineAttributes(tag, *spl); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VToolCubicBezier::SetVisualization() +{ + if (vis != nullptr) + { + auto visual = qobject_cast(vis); + SCASSERT(visual != nullptr); + + const QSharedPointer spl = VAbstractTool::data.GeometricObject(id); + visual->setObject1Id(spl->GetP1().id()); + visual->setObject2Id(spl->GetP2().id()); + visual->setObject3Id(spl->GetP3().id()); + visual->setObject4Id(spl->GetP4().id()); + visual->SetMode(Mode::Show); + visual->RefreshGeometry(); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VToolCubicBezier::RefreshGeometry() +{ + this->setPen(QPen(CorrectColor(lineColor), + qApp->toPixel(WidthHairLine(*VAbstractTool::data.GetPatternUnit()))/factor)); + if (isHovered || detailsMode) + { + this->setPath(ToolPath(PathDirection::Show)); + } + else + { + this->setPath(ToolPath()); + } + + SetVisualization(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VToolCubicBezier::SetSplineAttributes(QDomElement &domElement, const VCubicBezier &spl) +{ + SCASSERT(doc != nullptr); + + doc->SetAttribute(domElement, AttrType, ToolType); + doc->SetAttribute(domElement, AttrPoint1, spl.GetP1().id()); + doc->SetAttribute(domElement, AttrPoint2, spl.GetP2().id()); + doc->SetAttribute(domElement, AttrPoint3, spl.GetP3().id()); + doc->SetAttribute(domElement, AttrPoint4, spl.GetP4().id()); + + if (spl.GetDuplicate() > 0) + { + doc->SetAttribute(domElement, AttrDuplicate, spl.GetDuplicate()); + } + else + { + if (domElement.hasAttribute(AttrDuplicate)) + { + domElement.removeAttribute(AttrDuplicate); + } + } +} diff --git a/src/libs/vtools/tools/drawTools/toolcurve/vtoolcubicbezier.h b/src/libs/vtools/tools/drawTools/toolcurve/vtoolcubicbezier.h new file mode 100644 index 000000000..0bde70ef8 --- /dev/null +++ b/src/libs/vtools/tools/drawTools/toolcurve/vtoolcubicbezier.h @@ -0,0 +1,70 @@ +/************************************************************************ + ** + ** @file vtoolcubicbezier.h + ** @author Roman Telezhynskyi + ** @date 10 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 VTOOLCUBICBEZIER_H +#define VTOOLCUBICBEZIER_H + +#include "vabstractspline.h" + +class VCubicBezier; + +class VToolCubicBezier : public VAbstractSpline +{ + Q_OBJECT +public: + VToolCubicBezier(VAbstractPattern *doc, VContainer *data, quint32 id, const QString &color, + const Source &typeCreation, QGraphicsItem * parent = nullptr); + virtual ~VToolCubicBezier(); + virtual void setDialog() Q_DECL_OVERRIDE; + static VToolCubicBezier *Create(DialogTool *dialog, VMainGraphicsScene *scene, VAbstractPattern *doc, + VContainer *data); + static VToolCubicBezier *Create(const quint32 _id, VCubicBezier *spline, const QString &color, + VMainGraphicsScene *scene, VAbstractPattern *doc, VContainer *data, + const Document &parse, const Source &typeCreation); + static const QString ToolType; + virtual int type() const Q_DECL_OVERRIDE {return Type;} + enum { Type = UserType + static_cast(Tool::CubicBezier)}; + + VCubicBezier getSpline()const; + void setSpline(const VCubicBezier &spl); + + virtual void ShowVisualization(bool show) Q_DECL_OVERRIDE; +protected: + virtual void contextMenuEvent ( QGraphicsSceneContextMenuEvent * event ) Q_DECL_OVERRIDE; + virtual void RemoveReferens() Q_DECL_OVERRIDE; + virtual void SaveDialog(QDomElement &domElement) Q_DECL_OVERRIDE; + virtual void SaveOptions(QDomElement &tag, QSharedPointer &obj) Q_DECL_OVERRIDE; + virtual void SetVisualization() Q_DECL_OVERRIDE; +private: + Q_DISABLE_COPY(VToolCubicBezier) + + void RefreshGeometry (); + void SetSplineAttributes(QDomElement &domElement, const VCubicBezier &spl); +}; + +#endif // VTOOLCUBICBEZIER_H diff --git a/src/libs/vtools/tools/drawTools/toolcurve/vtoolspline.cpp b/src/libs/vtools/tools/drawTools/toolcurve/vtoolspline.cpp index 20f8871bf..d6c0b7c8d 100644 --- a/src/libs/vtools/tools/drawTools/toolcurve/vtoolspline.cpp +++ b/src/libs/vtools/tools/drawTools/toolcurve/vtoolspline.cpp @@ -187,8 +187,8 @@ VToolSpline* VToolSpline::Create(const quint32 _id, VSpline *spline, const QStri connect(scene, &VMainGraphicsScene::EnableToolMove, _spl, &VToolSpline::EnableToolMove); connect(scene, &VMainGraphicsScene::CurveDetailsMode, _spl, &VToolSpline::DetailsMode); doc->AddTool(id, _spl); - doc->IncrementReferens(spline->GetP1().id()); - doc->IncrementReferens(spline->GetP4().id()); + doc->IncrementReferens(spline->GetP1().getIdTool()); + doc->IncrementReferens(spline->GetP4().getIdTool()); return _spl; } return nullptr; diff --git a/src/libs/vtools/tools/tools.pri b/src/libs/vtools/tools/tools.pri index 67eb8061e..dcf73d160 100644 --- a/src/libs/vtools/tools/tools.pri +++ b/src/libs/vtools/tools/tools.pri @@ -47,7 +47,8 @@ HEADERS += \ $$PWD/drawTools/toolpoint/vabstractpoint.h \ $$PWD/drawTools/toolpoint/tooldoublepoint/vtooldoublepoint.h \ $$PWD/drawTools/toolpoint/tooldoublepoint/vtooltruedarts.h \ - $$PWD/drawTools/toolpoint/toolsinglepoint/vtoolpointofintersectioncurves.h + $$PWD/drawTools/toolpoint/toolsinglepoint/vtoolpointofintersectioncurves.h \ + $$PWD/drawTools/toolcurve/vtoolcubicbezier.h SOURCES += \ $$PWD/vtooldetail.cpp \ @@ -92,4 +93,5 @@ SOURCES += \ $$PWD/drawTools/toolpoint/vabstractpoint.cpp \ $$PWD/drawTools/toolpoint/tooldoublepoint/vtooldoublepoint.cpp \ $$PWD/drawTools/toolpoint/tooldoublepoint/vtooltruedarts.cpp \ - $$PWD/drawTools/toolpoint/toolsinglepoint/vtoolpointofintersectioncurves.cpp + $$PWD/drawTools/toolpoint/toolsinglepoint/vtoolpointofintersectioncurves.cpp \ + $$PWD/drawTools/toolcurve/vtoolcubicbezier.cpp diff --git a/src/libs/vtools/visualization/vistoolcubicbezier.cpp b/src/libs/vtools/visualization/vistoolcubicbezier.cpp new file mode 100644 index 000000000..6234c6913 --- /dev/null +++ b/src/libs/vtools/visualization/vistoolcubicbezier.cpp @@ -0,0 +1,122 @@ +/************************************************************************ + ** + ** @file vistoolcubicbezier.cpp + ** @author Roman Telezhynskyi + ** @date 10 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 "vistoolcubicbezier.h" +#include "../vgeometry/vcubicbezier.h" + +//--------------------------------------------------------------------------------------------------------------------- +VisToolCubicBezier::VisToolCubicBezier(const VContainer *data, QGraphicsItem *parent) + : VisPath(data, parent), + object2Id(NULL_ID), + object3Id(NULL_ID), + object4Id(NULL_ID), + point1(nullptr), + point2(nullptr), + point3(nullptr), + point4(nullptr), + helpLine(nullptr) +{ + point1 = InitPoint(supportColor, this); + point2 = InitPoint(supportColor, this); //-V656 + point3 = InitPoint(supportColor, this); //-V656 + point4 = InitPoint(supportColor, this); //-V656 + + helpLine = InitItem(mainColor, this); +} + +//--------------------------------------------------------------------------------------------------------------------- +VisToolCubicBezier::~VisToolCubicBezier() +{ +} + +//--------------------------------------------------------------------------------------------------------------------- +void VisToolCubicBezier::RefreshGeometry() +{ + if (object1Id > NULL_ID) + { + const auto first = Visualization::data->GeometricObject(object1Id); + DrawPoint(point1, first->toQPointF(), supportColor); + + if (object2Id <= NULL_ID) + { + const QLineF line = QLineF(first->toQPointF(), Visualization::scenePos); + DrawLine(helpLine, line, mainColor, lineStyle); + } + else + { + helpLine->setVisible(false); + + const auto second = Visualization::data->GeometricObject(object2Id); + DrawPoint(point2, second->toQPointF(), supportColor); + + if (object3Id <= NULL_ID) + { + VCubicBezier spline(*first, *second, VPointF(Visualization::scenePos), + VPointF(Visualization::scenePos)); + DrawPath(this, spline.GetPath(PathDirection::Hide), mainColor, Qt::SolidLine, Qt::RoundCap); + } + else + { + const auto third = Visualization::data->GeometricObject(object3Id); + DrawPoint(point3, third->toQPointF(), supportColor); + + if (object4Id <= NULL_ID) + { + VCubicBezier spline(*first, *second, *third, VPointF(Visualization::scenePos)); + DrawPath(this, spline.GetPath(PathDirection::Hide), mainColor, Qt::SolidLine, Qt::RoundCap); + } + else + { + const auto fourth = Visualization::data->GeometricObject(object4Id); + DrawPoint(point4, fourth->toQPointF(), supportColor); + + VCubicBezier spline(*first, *second, *third, *fourth); + DrawPath(this, spline.GetPath(PathDirection::Show), mainColor, Qt::SolidLine, Qt::RoundCap); + } + } + } + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VisToolCubicBezier::setObject2Id(const quint32 &value) +{ + object2Id = value; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VisToolCubicBezier::setObject3Id(const quint32 &value) +{ + object3Id = value; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VisToolCubicBezier::setObject4Id(const quint32 &value) +{ + object4Id = value; +} diff --git a/src/libs/vtools/visualization/vistoolcubicbezier.h b/src/libs/vtools/visualization/vistoolcubicbezier.h new file mode 100644 index 000000000..d67fcfdf7 --- /dev/null +++ b/src/libs/vtools/visualization/vistoolcubicbezier.h @@ -0,0 +1,62 @@ +/************************************************************************ + ** + ** @file vistoolcubicbezier.h + ** @author Roman Telezhynskyi + ** @date 10 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 VISTOOLCUBICBEZIER_H +#define VISTOOLCUBICBEZIER_H + +#include "vispath.h" + +class VisToolCubicBezier : public VisPath +{ + Q_OBJECT +public: + explicit VisToolCubicBezier(const VContainer *data, QGraphicsItem *parent = nullptr); + virtual ~VisToolCubicBezier(); + + virtual void RefreshGeometry() Q_DECL_OVERRIDE; + + void setObject2Id(const quint32 &value); + void setObject3Id(const quint32 &value); + void setObject4Id(const quint32 &value); + + virtual int type() const Q_DECL_OVERRIDE {return Type;} + enum { Type = UserType + static_cast(Vis::ToolCubicBezier)}; + +protected: + Q_DISABLE_COPY(VisToolCubicBezier) + quint32 object2Id; + quint32 object3Id; + quint32 object4Id; + QGraphicsEllipseItem *point1; + QGraphicsEllipseItem *point2; + QGraphicsEllipseItem *point3; + QGraphicsEllipseItem *point4; + QGraphicsLineItem *helpLine; +}; + +#endif // VISTOOLCUBICBEZIER_H diff --git a/src/libs/vtools/visualization/visualization.pri b/src/libs/vtools/visualization/visualization.pri index bfb09ba0c..f1139b5ff 100644 --- a/src/libs/vtools/visualization/visualization.pri +++ b/src/libs/vtools/visualization/visualization.pri @@ -30,7 +30,8 @@ HEADERS += \ $$PWD/vistoolpointfromarcandtangent.h \ $$PWD/vistoolarcwithlength.h \ $$PWD/vistooltruedarts.h \ - $$PWD/vistoolpointofintersectioncurves.h + $$PWD/vistoolpointofintersectioncurves.h \ + $$PWD/vistoolcubicbezier.h SOURCES += \ $$PWD/visline.cpp \ @@ -61,4 +62,5 @@ SOURCES += \ $$PWD/vistoolpointfromarcandtangent.cpp \ $$PWD/vistoolarcwithlength.cpp \ $$PWD/vistooltruedarts.cpp \ - $$PWD/vistoolpointofintersectioncurves.cpp + $$PWD/vistoolpointofintersectioncurves.cpp \ + $$PWD/vistoolcubicbezier.cpp From 2548697a9ebdec4adb3eaa5e90c6484ae51b66a6 Mon Sep 17 00:00:00 2001 From: Roman Telezhynskyi Date: Thu, 10 Mar 2016 18:09:38 +0200 Subject: [PATCH 3/4] 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); From 2d69e1a46ff3cd2ef27281a79677083c6bdbd374 Mon Sep 17 00:00:00 2001 From: Roman Telezhynskyi Date: Thu, 10 Mar 2016 19:08:37 +0200 Subject: [PATCH 4/4] The tool Detail now supports Cubic Bezier curve. --HG-- branch : feature --- src/app/valentina/xml/vpattern.cpp | 20 ++++++++++++++++---- src/libs/vtools/tools/vtooldetail.cpp | 11 ++++++++++- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp index 0328f3da2..7311a8b72 100644 --- a/src/app/valentina/xml/vpattern.cpp +++ b/src/app/valentina/xml/vpattern.cpp @@ -2141,10 +2141,22 @@ void VPattern::ParseNodeSpline(const QDomElement &domElement, const Document &pa quint32 idTool = 0; SplinesCommonAttributes(domElement, id, idObject, idTool); - VSpline *spl = new VSpline(*data->GeometricObject(idObject)); - spl->setIdObject(idObject); - spl->setMode(Draw::Modeling); - data->UpdateGObject(id, spl); + const auto obj = data->GetGObject(idObject); + if (obj->getType() == GOType::Spline) + { + VSpline *spl = new VSpline(*data->GeometricObject(idObject)); + spl->setIdObject(idObject); + spl->setMode(Draw::Modeling); + data->UpdateGObject(id, spl); + } + else + { + VCubicBezier *spl = new VCubicBezier(*data->GeometricObject(idObject)); + spl->setIdObject(idObject); + spl->setMode(Draw::Modeling); + data->UpdateGObject(id, spl); + } + VNodeSpline::Create(this, data, id, idObject, parse, Source::FromFile, idTool); } catch (const VExceptionBadId &e) diff --git a/src/libs/vtools/tools/vtooldetail.cpp b/src/libs/vtools/tools/vtooldetail.cpp index e3fd18cea..525dc0176 100644 --- a/src/libs/vtools/tools/vtooldetail.cpp +++ b/src/libs/vtools/tools/vtooldetail.cpp @@ -29,6 +29,7 @@ #include "vtooldetail.h" #include "nodeDetails/nodedetails.h" #include "../vgeometry/varc.h" +#include "../vgeometry/vcubicbezier.h" #include "../vgeometry/vsplinepath.h" #include "../vwidgets/vmaingraphicsscene.h" #include "../vwidgets/vmaingraphicsview.h" @@ -178,7 +179,15 @@ void VToolDetail::Create(DialogTool *dialog, VMainGraphicsScene *scene, VAbstrac break; case (Tool::NodeSpline): { - id = CreateNode(data, nodeD.getId()); + const auto obj = data->GetGObject(nodeD.getId()); + if (obj->getType() == GOType::Spline) + { + id = CreateNode(data, nodeD.getId()); + } + else + { + id = CreateNode(data, nodeD.getId()); + } VNodeSpline::Create(doc, data, id, nodeD.getId(), Document::FullParse, Source::FromGui); } break;