Seamly2D
Code documentation
vsplinepath.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 vsplinepath.cpp
27  ** @author Roman Telezhynskyi <dismine(at)gmail.com>
28  ** @date November 15, 2013
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 "vsplinepath.h"
53 
54 #include <QPoint>
55 
56 #include "../ifc/exception/vexception.h"
57 #include "../vmisc/vmath.h"
58 #include "vabstractcurve.h"
59 #include "vsplinepath_p.h"
60 
61 #ifdef Q_COMPILER_RVALUE_REFS
62 VSplinePath &VSplinePath::operator=(VSplinePath &&path) Q_DECL_NOTHROW { Swap(path); return *this; }
63 #endif
64 
65 void VSplinePath::Swap(VSplinePath &path) Q_DECL_NOTHROW
66 { VAbstractCubicBezierPath::Swap(path); std::swap(d, path.d); }
67 
68 //---------------------------------------------------------------------------------------------------------------------
69 /**
70  * @brief VSplinePath constructor.
71  * @param idObject parent id.
72  * @param mode mode creation spline path.
73  */
74 VSplinePath::VSplinePath(quint32 idObject, Draw mode)
75  : VAbstractCubicBezierPath(GOType::SplinePath, idObject, mode),
76  d(new VSplinePathData())
77 {}
78 
79 //---------------------------------------------------------------------------------------------------------------------
80 VSplinePath::VSplinePath(const QVector<VFSplinePoint> &points, qreal kCurve, quint32 idObject, Draw mode)
81  : VAbstractCubicBezierPath(GOType::SplinePath, idObject, mode),
82  d(new VSplinePathData())
83 {
84  if (points.size() < 3)
85  {
86  return;
87  }
88 
89  QVector<VSplinePoint> newPoints(points.size());
90  for (qint32 i = 1; i <= points.size()-1; ++i)
91  {
92  const VFSplinePoint &p1 = points.at(i-1);
93  const VFSplinePoint &p2 = points.at(i);
94  VSpline spl(p1.P(), p2.P(), p1.Angle2(), p2.Angle1(), p1.KAsm2(), p2.KAsm1(), kCurve);
95 
96  newPoints[i-1].SetP(p1.P());
97  newPoints[i-1].SetAngle2(p1.Angle2(), spl.GetStartAngleFormula());
98  newPoints[i-1].SetLength2(spl.GetC1Length(), spl.GetC1LengthFormula());
99 
100  newPoints[i].SetP(p2.P());
101  newPoints[i].SetAngle1(p2.Angle1(), spl.GetEndAngleFormula());
102  newPoints[i].SetLength1(spl.GetC2Length(), spl.GetC2LengthFormula());
103  }
104 
105  d->path = newPoints;
106  CreateName();
107 }
108 
109 //---------------------------------------------------------------------------------------------------------------------
110 VSplinePath::VSplinePath(const QVector<VSplinePoint> &points, quint32 idObject, Draw mode)
111  : VAbstractCubicBezierPath(GOType::SplinePath, idObject, mode),
112  d(new VSplinePathData())
113 {
114  if (points.isEmpty())
115  {
116  return;
117  }
118 
119  d->path = points;
120  CreateName();
121 }
122 
123 //---------------------------------------------------------------------------------------------------------------------
124 /**
125  * @brief VSplinePath copy constructor.
126  * @param splPath spline path.
127  */
130  d(splPath.d)
131 {}
132 
133 //---------------------------------------------------------------------------------------------------------------------
134 VSplinePath VSplinePath::Rotate(const QPointF &originPoint, qreal degrees, const QString &prefix) const
135 {
136  QVector<VSplinePoint> newPoints(CountPoints());
137  for (qint32 i = 1; i <= CountSubSpl(); ++i)
138  {
139  const VSpline spl = GetSpline(i).Rotate(originPoint, degrees);
140 
141  newPoints[i-1].SetP(spl.GetP1());
142  newPoints[i-1].SetAngle2(spl.GetStartAngle(), spl.GetStartAngleFormula());
143  newPoints[i-1].SetLength2(spl.GetC1Length(), spl.GetC1LengthFormula());
144 
145  newPoints[i].SetP(spl.GetP4());
146  newPoints[i].SetAngle1(spl.GetEndAngle(), spl.GetEndAngleFormula());
147  newPoints[i].SetLength1(spl.GetC2Length(), spl.GetC2LengthFormula());
148  }
149 
150  VSplinePath splPath(newPoints);
151  splPath.setName(name() + prefix);
152  splPath.setLineColor(getLineColor());
153  splPath.SetPenStyle(GetPenStyle());
154  splPath.setLineWeight(getLineWeight());
155  return splPath;
156 }
157 
158 //---------------------------------------------------------------------------------------------------------------------
159 VSplinePath VSplinePath::Flip(const QLineF &axis, const QString &prefix) const
160 {
161  QVector<VSplinePoint> newPoints(CountPoints());
162  for (qint32 i = 1; i <= CountSubSpl(); ++i)
163  {
164  const VSpline spl = GetSpline(i).Flip(axis);
165 
166  newPoints[i-1].SetP(spl.GetP1());
167  newPoints[i-1].SetAngle2(spl.GetStartAngle(), spl.GetStartAngleFormula());
168  newPoints[i-1].SetLength2(spl.GetC1Length(), spl.GetC1LengthFormula());
169 
170  newPoints[i].SetP(spl.GetP4());
171  newPoints[i].SetAngle1(spl.GetEndAngle(), spl.GetEndAngleFormula());
172  newPoints[i].SetLength1(spl.GetC2Length(), spl.GetC2LengthFormula());
173  }
174 
175  VSplinePath splPath(newPoints);
176  splPath.setName(name() + prefix);
177  splPath.setLineColor(getLineColor());
178  splPath.SetPenStyle(GetPenStyle());
179  splPath.setLineWeight(getLineWeight());
180  return splPath;
181 }
182 
183 //---------------------------------------------------------------------------------------------------------------------
184 VSplinePath VSplinePath::Move(qreal length, qreal angle, const QString &prefix) const
185 {
186  QVector<VSplinePoint> newPoints(CountPoints());
187  for (qint32 i = 1; i <= CountSubSpl(); ++i)
188  {
189  const VSpline spl = GetSpline(i).Move(length, angle);
190 
191  newPoints[i-1].SetP(spl.GetP1());
192  newPoints[i-1].SetAngle2(spl.GetStartAngle(), spl.GetStartAngleFormula());
193  newPoints[i-1].SetLength2(spl.GetC1Length(), spl.GetC1LengthFormula());
194 
195  newPoints[i].SetP(spl.GetP4());
196  newPoints[i].SetAngle1(spl.GetEndAngle(), spl.GetEndAngleFormula());
197  newPoints[i].SetLength1(spl.GetC2Length(), spl.GetC2LengthFormula());
198  }
199 
200  VSplinePath splPath(newPoints);
201  splPath.setName(name() + prefix);
202  splPath.setLineColor(getLineColor());
203  splPath.SetPenStyle(GetPenStyle());
204  splPath.setLineWeight(getLineWeight());
205  return splPath;
206 }
207 
208 //---------------------------------------------------------------------------------------------------------------------
210 {}
211 
212 //---------------------------------------------------------------------------------------------------------------------
213 /**
214  * @brief append add point in the end of list points.
215  * @param point new point.
216  */
218 {
219  if (d->path.size() > 0 && static_cast<QPointF>(d->path.last().P()) == static_cast<QPointF>(point.P())) //-V807
220  {
221  return;
222  }
223 
224  d->path.append(point);
225  CreateName();
226 }
227 
228 //---------------------------------------------------------------------------------------------------------------------
229 /**
230  * @brief CountSubSpl return count of simple splines.
231  * @return count.
232  */
234 {
235  if (d->path.isEmpty())
236  {
237  return 0;
238  }
239  else
240  {
241  return d->path.size() - 1;
242  }
243 }
244 
245 //---------------------------------------------------------------------------------------------------------------------
246 /**
247  * @brief GetSpline return spline by index.
248  * @param index index spline in spline path.
249  * @return spline
250  */
251 VSpline VSplinePath::GetSpline(qint32 index) const
252 {
253  if (CountPoints()<1)
254  {
255  throw VException(tr("Not enough points to create the spline."));
256  }
257 
258  if (index < 1 || index > CountSubSpl())
259  {
260  throw VException(tr("This spline does not exist."));
261  }
262 
263  const VSplinePoint &p1 = d->path.at(index-1);
264  const VSplinePoint &p2 = d->path.at(index);
265  VSpline spl(p1.P(), p2.P(), p1.Angle2(), p1.Angle2Formula(), p2.Angle1(), p2.Angle1Formula(), p1.Length2(),
266  p1.Length2Formula(), p2.Length1(), p2.Length1Formula(), 1);
267  return spl;
268 }
269 
270 //---------------------------------------------------------------------------------------------------------------------
271 /**
272  * @brief UpdatePoint update spline point in list.
273  * @param indexSpline spline index in list.
274  * @param pos position point in spline.
275  * @param point point.
276  */
277 void VSplinePath::UpdatePoint(qint32 indexSpline, const SplinePointPosition &pos, const VSplinePoint &point)
278 {
279  if (indexSpline < 1 || indexSpline > CountSubSpl())
280  {
281  throw VException(tr("This spline does not exist."));
282  }
284  {
285  d->path[indexSpline-1] = point;
286  }
287  else
288  {
289  d->path[indexSpline] = point;
290  }
291 }
292 
293 //---------------------------------------------------------------------------------------------------------------------
294 /**
295  * @brief GetSplinePoint return spline point from list.
296  * @param indexSpline spline index in list.
297  * @param pos position point in spline.
298  * @return spline point.
299  */
301 {
302  if (indexSpline < 1 || indexSpline > CountSubSpl())
303  {
304  throw VException(tr("This spline does not exist."));
305  }
307  {
308  return d->path.at(indexSpline-1);
309  }
310  else
311  {
312  return d->path.at(indexSpline);
313  }
314 }
315 
316 //---------------------------------------------------------------------------------------------------------------------
317 /**
318  * @brief operator = assignment operator.
319  * @param path spline path.
320  * @return spline path.
321  */
323 {
324  if ( &path == this )
325  {
326  return *this;
327  }
329  d = path.d;
330  return *this;
331 }
332 
333 //---------------------------------------------------------------------------------------------------------------------
334 /**
335  * @brief operator [] return spline point by index.
336  * @param indx index in list.
337  * @return spline point.
338  */
340 {
341  return d->path[indx];
342 }
343 
344 //---------------------------------------------------------------------------------------------------------------------
345 /**
346  * @brief at return spline point by index.
347  * @param indx index in list.
348  * @return spline point.
349  */
350 const VSplinePoint &VSplinePath::at(int indx) const
351 {
352  return d->path[indx];
353 }
354 
355 //---------------------------------------------------------------------------------------------------------------------
357 {
358  if (CountPoints() > 0)
359  {
360  return GetSplinePath().first().Angle2();
361  }
362  else
363  {
364  return 0;
365  }
366 }
367 
368 //---------------------------------------------------------------------------------------------------------------------
370 {
371  if (CountPoints() > 0)
372  {
373  return GetSplinePath().last().Angle1();
374  }
375  else
376  {
377  return 0;
378  }
379 }
380 
381 //---------------------------------------------------------------------------------------------------------------------
383 {
384  if (CountPoints() > 0)
385  {
386  return GetSplinePath().first().Length2();
387  }
388  else
389  {
390  return 0;
391  }
392 }
393 
394 //---------------------------------------------------------------------------------------------------------------------
396 {
397  if (CountPoints() > 0)
398  {
399  return GetSplinePath().last().Length1();
400  }
401  else
402  {
403  return 0;
404  }
405 }
406 
407 //---------------------------------------------------------------------------------------------------------------------
409 {
410  if (not d->path.isEmpty())
411  {
412  return d->path.first().P();
413  }
414  else
415  {
416  return VPointF();
417  }
418 }
419 
420 //---------------------------------------------------------------------------------------------------------------------
422 {
423  const qint32 count = CountSubSpl();
424  if (count >= 1)
425  {
426  return d->path.at(count).P();// Take last point of the last real spline
427  }
428  else
429  {
430  return VPointF();
431  }
432 }
433 
434 //---------------------------------------------------------------------------------------------------------------------
435 /**
436  * @brief CountPoints return count of points.
437  * @return count.
438  */
440 {
441  return d->path.size();
442 }
443 
444 //---------------------------------------------------------------------------------------------------------------------
445 /**
446  * @brief GetSplinePath return list with spline points.
447  * @return list.
448  */
450 {
451  return d->path;
452 }
453 
454 //---------------------------------------------------------------------------------------------------------------------
456 {
457  QVector<VFSplinePoint> points;
458  points.reserve(d->path.size());
459 
460  for (qint32 i = 1; i <= CountSubSpl(); ++i)
461  {
462  const VSplinePoint &p1 = d->path.at(i-1);
463  const VSplinePoint &p2 = d->path.at(i);
464  VSpline spl(p1.P(), p2.P(), p1.Angle2(), p1.Angle2Formula(), p2.Angle1(), p2.Angle1Formula(), p1.Length2(),
465  p1.Length2Formula(), p2.Length1(), p2.Length1Formula(), 1);
466 
467  points[i-1].SetP(p1.P());
468  points[i-1].SetAngle2(p1.Angle2());
469  points[i-1].SetKAsm2(spl.GetKasm1());
470 
471  points[i].SetP(p2.P());
472  points[i].SetAngle1(p2.Angle1());
473  points[i].SetKAsm1(spl.GetKasm2());
474  }
475 
476  return points;
477 }
478 
479 //---------------------------------------------------------------------------------------------------------------------
480 /**
481  * @brief Clear clear list of points.
482  */
484 {
485  d->path.clear();
486  SetDuplicate(0);
487 }
virtual void CreateName() Q_DECL_OVERRIDE
QString getLineWeight() const
getLineWeight return weight of the lines
void SetDuplicate(quint32 number)
VAbstractCurve & operator=(const VAbstractCurve &curve)
QString GetPenStyle() const
void Swap(VAbstractCurve &curve) Q_DECL_NOTHROW
QString getLineColor() const
The VException class parent for all exception. Could be use for abstract exception.
Definition: vexception.h:66
The VFSplinePoint class keep information about point in spline path. Each point have two angles and t...
Definition: vsplinepoint.h:70
VPointF P() const
P return point.
qreal Angle1() const
Angle1 return first angle of spline.
qreal KAsm1() const
KAsm1 return coefficient of length first control line.
qreal Angle2() const
Angle2 return second angle of spline.
qreal KAsm2() const
KAsm2 return coefficient of length second control line.
virtual QString name() const
name return name graphical object.
Definition: vgobject.cpp:148
The VPointF class keep data of point.
Definition: vpointf.h:75
The VSplinePath class keep information about splinePath.
Definition: vsplinepath.h:72
virtual qreal GetC2Length() const Q_DECL_OVERRIDE
VSplinePath Rotate(const QPointF &originPoint, qreal degrees, const QString &prefix=QString()) const
const VSplinePoint & at(int indx) const
at return spline point by index.
virtual qreal GetStartAngle() const Q_DECL_OVERRIDE
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.
VSplinePath Flip(const QLineF &axis, const QString &prefix=QString()) const
void UpdatePoint(qint32 indexSpline, const SplinePointPosition &pos, const VSplinePoint &point)
UpdatePoint update spline point in list.
VSplinePath & operator=(const VSplinePath &path)
operator = assignment operator.
virtual void Clear() Q_DECL_OVERRIDE
Clear clear list of points.
virtual QVector< VSplinePoint > GetSplinePath() const Q_DECL_OVERRIDE
GetSplinePath return list with spline points.
virtual VPointF FirstPoint() const Q_DECL_OVERRIDE
VSplinePath(quint32 idObject=0, Draw mode=Draw::Calculation)
VSplinePath constructor.
Definition: vsplinepath.cpp:74
QSharedDataPointer< VSplinePathData > d
Definition: vsplinepath.h:123
virtual qint32 CountSubSpl() const Q_DECL_OVERRIDE
CountSubSpl return count of simple splines.
virtual qreal GetEndAngle() const Q_DECL_OVERRIDE
QVector< VFSplinePoint > GetFSplinePath() const
virtual VPointF LastPoint() const Q_DECL_OVERRIDE
VSplinePoint & operator[](int indx)
operator [] return spline point by index.
VSplinePoint GetSplinePoint(qint32 indexSpline, SplinePointPosition pos) const
GetSplinePoint return spline point from list.
virtual ~VSplinePath() Q_DECL_OVERRIDE
VSplinePath Move(qreal length, qreal angle, const QString &prefix=QString()) const
void Swap(VSplinePath &path) Q_DECL_NOTHROW
Definition: vsplinepath.cpp:65
void append(const VSplinePoint &point)
append add point in the end of list points.
virtual qreal GetC1Length() const Q_DECL_OVERRIDE
The VSplinePoint class keep information about point in spline path. Each point have two angles and tw...
Definition: vsplinepoint.h:108
QString Length1Formula() const
qreal Length2() const
qreal Angle2() const
QString Angle2Formula() const
QString Length2Formula() const
QString Angle1Formula() const
qreal Angle1() const
VPointF P() const
qreal Length1() const
VSpline class that implements the spline.
Definition: vspline.h:75
VSpline Rotate(const QPointF &originPoint, qreal degrees, const QString &prefix=QString()) const
Definition: vspline.cpp:144
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
VSpline Flip(const QLineF &axis, const QString &prefix=QString()) const
Definition: vspline.cpp:161
virtual VPointF GetP1() const Q_DECL_OVERRIDE
GetP1 return first spline point.
Definition: vspline.cpp:281
QString GetStartAngleFormula() const
Definition: vspline.cpp:353
QString GetEndAngleFormula() const
Definition: vspline.cpp:359
qreal GetKasm1() const
GetKasm1 return coefficient of length first control line.
Definition: vspline.cpp:421
virtual qreal GetC1Length() const Q_DECL_OVERRIDE
Definition: vspline.cpp:379
QString GetC2LengthFormula() const
Definition: vspline.cpp:397
VSpline Move(qreal length, qreal angle, const QString &prefix=QString()) const
Definition: vspline.cpp:178
virtual qreal GetEndAngle() const Q_DECL_OVERRIDE
GetAngle2 return second angle control line.
Definition: vspline.cpp:347
qreal GetKasm2() const
GetKasm2 return coefficient of length second control line.
Definition: vspline.cpp:432
const QString splPath
Definition: ifcdef.cpp:419
GOType
Definition: vgeometrydef.h:56
@ SplinePath
Draw
Definition: vgeometrydef.h:55
SplinePointPosition
Definition: vgeometrydef.h:58