Seamly2D
Code documentation
vistoolsplinepath.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * *
3  * Copyright (C) 2017 Seamly, LLC *
4  * *
5  * https://github.com/fashionfreedom/seamly2d *
6  * *
7  ***************************************************************************
8  **
9  ** Seamly2D is free software: you can redistribute it and/or modify
10  ** it under the terms of the GNU General Public License as published by
11  ** the Free Software Foundation, either version 3 of the License, or
12  ** (at your option) any later version.
13  **
14  ** Seamly2D is distributed in the hope that it will be useful,
15  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
16  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  ** GNU General Public License for more details.
18  **
19  ** You should have received a copy of the GNU General Public License
20  ** along with Seamly2D. If not, see <http://www.gnu.org/licenses/>.
21  **
22  **************************************************************************
23 
24  ************************************************************************
25  **
26  ** @file vistoolsplinepath.cpp
27  ** @author Roman Telezhynskyi <dismine(at)gmail.com>
28  ** @date 7 9, 2014
29  **
30  ** @brief
31  ** @copyright
32  ** This source code is part of the Valentine project, a pattern making
33  ** program, whose allow create and modeling patterns of clothing.
34  ** Copyright (C) 2013-2015 Seamly2D project
35  ** <https://github.com/fashionfreedom/seamly2d> All Rights Reserved.
36  **
37  ** Seamly2D is free software: you can redistribute it and/or modify
38  ** it under the terms of the GNU General Public License as published by
39  ** the Free Software Foundation, either version 3 of the License, or
40  ** (at your option) any later version.
41  **
42  ** Seamly2D is distributed in the hope that it will be useful,
43  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
44  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
45  ** GNU General Public License for more details.
46  **
47  ** You should have received a copy of the GNU General Public License
48  ** along with Seamly2D. If not, see <http://www.gnu.org/licenses/>.
49  **
50  *************************************************************************/
51 
52 #include "vistoolsplinepath.h"
53 
54 #include <QGraphicsPathItem>
55 #include <QLineF>
56 #include <QPainterPath>
57 #include <QPoint>
58 #include <Qt>
59 #include <QtAlgorithms>
60 
61 #include "../vgeometry/vabstractcurve.h"
62 #include "../vgeometry/vgeometrydef.h"
63 #include "../vgeometry/vpointf.h"
64 #include "../vgeometry/vspline.h"
65 #include "../vgeometry/vsplinepoint.h"
66 #include "../vpatterndb/vcontainer.h"
67 #include "../vwidgets/vcontrolpointspline.h"
68 #include "../visualization.h"
69 #include "vispath.h"
70 
71 //---------------------------------------------------------------------------------------------------------------------
72 VisToolSplinePath::VisToolSplinePath(const VContainer *data, QGraphicsItem *parent)
73  : VisPath(data, parent),
74  points(),
75  ctrlPoints(),
76  newCurveSegment(nullptr),
77  path(),
78  isLeftMousePressed(false),
79  pointIsSelected(false),
80  ctrlPoint()
81 {
82  newCurveSegment = InitItem<VCurvePathItem>(mainColor, this);
83 }
84 
85 //---------------------------------------------------------------------------------------------------------------------
87 {
88  emit ToolTip("");
89 }
90 
91 //---------------------------------------------------------------------------------------------------------------------
93 {
94  if (path.CountPoints() > 0)
95  {
96  const QVector<VSplinePoint> pathPoints = path.GetSplinePath();
97  const int size = pathPoints.size();
98 
99  for (int i = 0; i < size; ++i)
100  {
101  VScaledEllipse *point = this->getPoint(static_cast<unsigned>(i));
102  DrawPoint(point, static_cast<QPointF>(pathPoints.at(i).P()), supportColor);
103  }
104 
105  if (mode == Mode::Creation)
106  {
107  if (size > 1)
108  {
109  for (qint32 i = 1; i<=path.CountSubSpl(); ++i)
110  {
111  const int preLastPoint = (path.CountSubSpl() - 1) * 2;
112  const int lastPoint = preLastPoint + 1;
113 
114  VSpline spl = path.GetSpline(i);
115 
116  ctrlPoints[preLastPoint]->refreshCtrlPoint(i, SplinePointPosition::FirstPoint,
117  static_cast<QPointF>(spl.GetP2()),
118  static_cast<QPointF>(spl.GetP1()));
119  ctrlPoints[lastPoint]->refreshCtrlPoint(i, SplinePointPosition::LastPoint,
120  static_cast<QPointF>(spl.GetP3()),
121  static_cast<QPointF>(spl.GetP4()));
122  }
123  }
124 
125  Creating(static_cast<QPointF>(pathPoints.at(size-1).P()), size);
126  }
127 
128  if (size > 1)
129  {
130  DrawPath(this, path.GetPath(), path.DirectionArrows(), mainColor, lineStyle, lineWeight, Qt::RoundCap);
131  }
132 
133  if (path.CountPoints() < 3)
134  {
135  Visualization::toolTip = tr("<b>Curved path</b>: select three or more points");
136  }
137  else
138  {
139  Visualization::toolTip = tr("<b>Curved path</b>: select three or more points, "
140  "Press <b>ENTER</b> to finish tool creation");
141  }
142  if (mode == Mode::Show)
143  {
144  Visualization::toolTip = tr("Use <b>SHIFT</b> to constrain angle");
146  }
147  }
148 }
149 
150 //---------------------------------------------------------------------------------------------------------------------
152 {
153  path = value;
154 }
155 
156 //---------------------------------------------------------------------------------------------------------------------
157 // cppcheck-suppress unusedFunction
159 {
160  return path;
161 }
162 
163 //---------------------------------------------------------------------------------------------------------------------
165 {
166  if (mode == Mode::Creation)
167  {
168  isLeftMousePressed = true;
169  }
170 }
171 
172 //---------------------------------------------------------------------------------------------------------------------
174 {
175  if (mode == Mode::Creation)
176  {
177  isLeftMousePressed = false;
178  RefreshGeometry();
179  }
180 }
181 
182 //---------------------------------------------------------------------------------------------------------------------
184 {
185  if (static_cast<quint32>(points.size() - 1) >= i && points.isEmpty() == false)
186  {
187  return points.at(static_cast<int>(i));
188  }
189  else
190  {
191  pointIsSelected = false;
192 
193  auto point = InitPoint(supportColor, this);
194  points.append(point);
195 
196  if (points.size() == 1)
197  {
198  auto *controlPoint1 = new VControlPointSpline(points.size(), SplinePointPosition::FirstPoint, this);
199  controlPoint1->hide();
200  ctrlPoints.append(controlPoint1);
201  }
202  else
203  {
204  auto *controlPoint1 = new VControlPointSpline(points.size()-1, SplinePointPosition::LastPoint, this);
205  controlPoint1->hide();
206  ctrlPoints.append(controlPoint1);
207 
208  auto *controlPoint2 = new VControlPointSpline(points.size(), SplinePointPosition::FirstPoint, this);
209  controlPoint2->hide();
210  ctrlPoints.append(controlPoint2);
211  }
212 
213  return point;
214  }
215  return nullptr;
216 }
217 
218 //---------------------------------------------------------------------------------------------------------------------
219 void VisToolSplinePath::Creating(const QPointF &pSpl, int size)
220 {
221  int lastPoint = 0;
222  int preLastPoint = 0;
223 
224  if (size > 1)
225  {
226  lastPoint = (size - 1) * 2;
227  preLastPoint = lastPoint - 1;
228  }
229 
231  {
232  newCurveSegment->hide();
233 
235 
236  if (not ctrlPoints[lastPoint]->isVisible())
237  {
238  //Radius of point circle, but little bigger. Need handle with hover sizes.
239  if (QLineF(pSpl, ctrlPoint).length() > defPointRadiusPixel*1.5)
240  {
241  if (size == 1)
242  {
243  ctrlPoints[lastPoint]->show();
244  }
245  else
246  {
247  ctrlPoints[preLastPoint]->show();
248  ctrlPoints[lastPoint]->show();
249  }
250  }
251  else
252  {
253  ctrlPoint = pSpl;
254  }
255  }
256 
257  QLineF ctrlLine (pSpl, Visualization::scenePos);
258  ctrlLine.setAngle(ctrlLine.angle()+180);
259 
260  if (size == 1)
261  {
262  ctrlPoints[lastPoint]->refreshCtrlPoint(size, SplinePointPosition::FirstPoint, ctrlPoint, pSpl);
263  }
264  else
265  {
266  ctrlPoints[preLastPoint]->refreshCtrlPoint(size-1, SplinePointPosition::LastPoint, ctrlLine.p2(), pSpl);
267  ctrlPoints[lastPoint]->refreshCtrlPoint(size, SplinePointPosition::FirstPoint, ctrlPoint, pSpl);
268  }
269 
271 
272  if (size == 1)
273  {
274  path[size-1].SetAngle2(spline.GetStartAngle(), spline.GetStartAngleFormula());
275  if (ctrlPoint != pSpl)
276  {
277  path[size-1].SetLength2(spline.GetC1Length(), spline.GetC1LengthFormula());
278  }
279  else
280  {
281  path[size-1].SetLength2(0, "0");
282  }
283  emit PathChanged(path);
284  }
285  else
286  {
287  const VSpline spl = path.GetSpline(size - 1);
288  VSpline preSpl(spl.GetP1(), static_cast<QPointF>(spl.GetP2()), ctrlLine.p2(), VPointF(pSpl));
289 
290  path[size-1].SetAngle2(spline.GetStartAngle(), spline.GetStartAngleFormula());
291  if (ctrlPoint != pSpl)
292  {
293  path[size-1].SetLength1(preSpl.GetC2Length(), preSpl.GetC2LengthFormula());
294  path[size-1].SetLength2(spline.GetC1Length(), spline.GetC1LengthFormula());
295  }
296  else
297  {
298  path[size-1].SetLength1(0, "0");
299  path[size-1].SetLength2(0, "0");
300  }
301  emit PathChanged(path);
302  }
303  }
304  else
305  {
306  pointIsSelected = true;
307 
309 
310  path[size-1].SetAngle2(spline.GetStartAngle(), spline.GetStartAngleFormula());
311 
312  if (ctrlPoint != pSpl)
313  {
314  path[size-1].SetLength2(spline.GetC1Length(), spline.GetC1LengthFormula());
315  }
316  else
317  {
318  path[size-1].SetLength2(0, "0");
319  }
320  emit PathChanged(path);
321 
322  DrawPath(newCurveSegment, spline.GetPath(), mainColor, Qt::SolidLine, lineWeight, Qt::RoundCap);
323  }
324 }
virtual QPainterPath GetPath() const Q_DECL_OVERRIDE
GetPath return QPainterPath which reprezent spline path.
virtual QVector< DirectionArrow > DirectionArrows() const Q_DECL_OVERRIDE
virtual QPainterPath GetPath() const
The VContainer class container of all variables.
Definition: vcontainer.h:141
The VControlPointSpline class control spline point.
The VPointF class keep data of point.
Definition: vpointf.h:75
The VSplinePath class keep information about splinePath.
Definition: vsplinepath.h:72
virtual VSpline GetSpline(qint32 index) const Q_DECL_OVERRIDE
GetSpline return spline by index.
virtual qint32 CountPoints() const Q_DECL_OVERRIDE
CountPoints return count of points.
virtual QVector< VSplinePoint > GetSplinePath() const Q_DECL_OVERRIDE
GetSplinePath return list with spline points.
virtual qint32 CountSubSpl() const Q_DECL_OVERRIDE
CountSubSpl return count of simple splines.
VSpline class that implements the spline.
Definition: vspline.h:75
virtual qreal GetC2Length() const Q_DECL_OVERRIDE
Definition: vspline.cpp:385
virtual VPointF GetP4() const Q_DECL_OVERRIDE
GetP4 return last spline point.
Definition: vspline.cpp:321
QString GetC1LengthFormula() const
Definition: vspline.cpp:391
virtual qreal GetStartAngle() const Q_DECL_OVERRIDE
GetAngle1 return first angle control line.
Definition: vspline.cpp:337
virtual VPointF GetP1() const Q_DECL_OVERRIDE
GetP1 return first spline point.
Definition: vspline.cpp:281
virtual VPointF GetP2() const Q_DECL_OVERRIDE
GetP2 return first control point.
Definition: vspline.cpp:297
QString GetStartAngleFormula() const
Definition: vspline.cpp:353
virtual qreal GetC1Length() const Q_DECL_OVERRIDE
Definition: vspline.cpp:379
virtual VPointF GetP3() const Q_DECL_OVERRIDE
GetP3 return second control point.
Definition: vspline.cpp:309
QString GetC2LengthFormula() const
Definition: vspline.cpp:397
void setPath(const VSplinePath &value)
void PathChanged(const VSplinePath &path)
VCurvePathItem * newCurveSegment
VisToolSplinePath(const VContainer *data, QGraphicsItem *parent=nullptr)
virtual void RefreshGeometry() Q_DECL_OVERRIDE
QVector< VControlPointSpline * > ctrlPoints
VScaledEllipse * getPoint(quint32 i)
QVector< VScaledEllipse * > points
void Creating(const QPointF &pSpl, int size)
QColor supportColor
void ToolTip(const QString &toolTip)
QColor mainColor
Definition: visualization.h:99
void DrawPoint(QGraphicsEllipseItem *point, const QPointF &pos, const QColor &color, Qt::PenStyle style=Qt::SolidLine)
void DrawPath(VCurvePathItem *pathItem, const QPainterPath &path, const QColor &color, Qt::PenStyle style=Qt::SolidLine, const qreal &weight=0.35, Qt::PenCapStyle cap=Qt::SquareCap)
QPointF scenePos
Definition: visualization.h:98
VScaledEllipse * InitPoint(const QColor &color, QGraphicsItem *parent, qreal z=0) const
Qt::PenStyle lineStyle
const qreal defPointRadiusPixel
Definition: global.cpp:59
@ Creation