Seamly2D
Code documentation
vcontour.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 vcontour.cpp
27  ** @author Roman Telezhynskyi <dismine(at)gmail.com>
28  ** @date 21 1, 2015
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 "vcontour.h"
53 
54 #include <QLineF>
55 #include <QPainterPath>
56 #include <QPoint>
57 #include <QPointF>
58 #include <QPolygonF>
59 #include <QRectF>
60 #include <Qt>
61 
62 #include "vcontour_p.h"
63 #include "vlayoutpiece.h"
64 #include "../vmisc/vmath.h"
65 
66 #ifdef Q_COMPILER_RVALUE_REFS
67 VContour &VContour::operator=(VContour &&contour) Q_DECL_NOTHROW { Swap(contour); return *this; }
68 #endif
69 
70 void VContour::Swap(VContour &contour) Q_DECL_NOTHROW
71 { std::swap(d, contour.d); }
72 
73 //---------------------------------------------------------------------------------------------------------------------
75  :d(new VContourData())
76 {}
77 
78 //---------------------------------------------------------------------------------------------------------------------
79 VContour::VContour(int height, int width)
80  :d(new VContourData(height, width))
81 {}
82 
83 //---------------------------------------------------------------------------------------------------------------------
85  :d (contour.d)
86 {}
87 
88 //---------------------------------------------------------------------------------------------------------------------
90 {
91  if ( &contour == this )
92  {
93  return *this;
94  }
95  d = contour.d;
96  return *this;
97 }
98 
99 //---------------------------------------------------------------------------------------------------------------------
101 {}
102 
103 //---------------------------------------------------------------------------------------------------------------------
105 {
106  d->globalContour = contour;
107 }
108 
109 //---------------------------------------------------------------------------------------------------------------------
111 {
112  return d->globalContour;
113 }
114 
115 //---------------------------------------------------------------------------------------------------------------------
116 quint32 VContour::GetShift() const
117 {
118  return d->shift;
119 }
120 
121 //---------------------------------------------------------------------------------------------------------------------
122 void VContour::SetShift(quint32 shift)
123 {
124  d->shift = shift;
125 }
126 
127 //---------------------------------------------------------------------------------------------------------------------
129 {
130  return d->paperHeight;
131 }
132 
133 //---------------------------------------------------------------------------------------------------------------------
134 void VContour::SetHeight(int height)
135 {
136  d->paperHeight = height;
137 }
138 
139 //---------------------------------------------------------------------------------------------------------------------
141 {
142  return d->paperWidth;
143 }
144 
145 //---------------------------------------------------------------------------------------------------------------------
146 void VContour::SetWidth(int width)
147 {
148  d->paperWidth = width;
149 }
150 
151 //---------------------------------------------------------------------------------------------------------------------
152 QSizeF VContour::GetSize() const
153 {
154  return QSizeF(d->paperWidth, d->paperHeight);
155 }
156 
157 //---------------------------------------------------------------------------------------------------------------------
158 QVector<QPointF> VContour::UniteWithContour(const VLayoutPiece &detail, int globalI, int detJ, BestFrom type) const
159 {
160  QVector<QPointF> newContour;
161  if (d->globalContour.isEmpty()) //-V807
162  {
163  AppendWhole(newContour, detail, 0);
164  }
165  else
166  {
167  if (globalI <= 0 || globalI > GlobalEdgesCount())
168  {
169  return QVector<QPointF>();
170  }
171 
172  if (detJ <= 0 || detJ > detail.LayoutEdgesCount())
173  {
174  return QVector<QPointF>();
175  }
176 
177  int i2 = 0;
178  if (globalI == d->globalContour.count())
179  {
180  i2 = 0;
181  }
182  else
183  {
184  i2 = globalI;
185  }
186 
187  int i=0;
188  while (i < d->globalContour.count())
189  {
190  if (i == i2)
191  {
192  if (type == BestFrom::Rotation)
193  {
194  AppendWhole(newContour, detail, detJ);
195  }
196  else
197  {
198  int processedEdges = 0;
199  const int nD = detail.LayoutEdgesCount();
200  int j = detJ+1;
201  do
202  {
203  if (j > nD)
204  {
205  j=1;
206  }
207  if (j != detJ)
208  {
209  const QVector<QPointF> points = CutEdge(detail.LayoutEdge(j));
210  for (int i = 0; i < points.size()-1; ++i)
211  {
212  newContour.append(points.at(i));
213  }
214  }
215  ++processedEdges;
216  ++j;
217  }while (processedEdges < nD);
218  }
219  }
220 
221  if (newContour.isEmpty() == false)
222  {
223  if (newContour.last() != d->globalContour.at(i))
224  {
225  newContour.append(d->globalContour.at(i));
226  }
227  }
228  else
229  {
230  newContour.append(d->globalContour.at(i));
231  }
232  ++i;
233  }
234  }
235  return newContour;
236 }
237 
238 //---------------------------------------------------------------------------------------------------------------------
240 {
241  if (d->globalContour.isEmpty())
242  {
243  return 10;
244  }
245  else
246  {
247  return d->globalContour.count();
248  }
249 }
250 
251 //---------------------------------------------------------------------------------------------------------------------
252 QLineF VContour::GlobalEdge(int i) const
253 {
254  if (d->globalContour.isEmpty()) //-V807
255  {
256  // Because sheet is blank we have one global edge for all cases - Ox axis.
257  if (i < 1 || i > GlobalEdgesCount())
258  { // Doesn't exist such edge
259  return EmptySheetEdge();
260  }
261 
262  const qreal nShift = EmptySheetEdge().length()/GlobalEdgesCount();
263  return QLineF(nShift*(i-1), 0, nShift*i, 0);
264  }
265  else
266  {
267  if (i < 1 || i > GlobalEdgesCount())
268  { // Doesn't exist such edge
269  return QLineF();
270  }
271  QLineF edge;
272  if (i < GlobalEdgesCount())
273  {
274  edge = QLineF(d->globalContour.at(i-1), d->globalContour.at(i));
275  }
276  else
277  { // Closed countour
278  edge = QLineF(d->globalContour.at(GlobalEdgesCount()-1), d->globalContour.at(0));
279  }
280  return edge;
281  }
282 }
283 
284 //---------------------------------------------------------------------------------------------------------------------
285 QVector<QPointF> VContour::CutEdge(const QLineF &edge) const
286 {
287  QVector<QPointF> points;
288  if (d->shift == 0)
289  {
290  points.append(edge.p1());
291  points.append(edge.p2());
292  }
293  else
294  {
295  const int n = qFloor(edge.length()/d->shift);
296 
297  if (n <= 0)
298  {
299  points.append(edge.p1());
300  points.append(edge.p2());
301  }
302  else
303  {
304  const qreal nShift = edge.length()/n;
305  for (int i = 1; i <= n+1; ++i)
306  {
307  QLineF l1 = edge;
308  l1.setLength(nShift*(i-1));
309  points.append(l1.p2());
310  }
311  }
312  }
313  return points;
314 }
315 
316 //---------------------------------------------------------------------------------------------------------------------
318 {
319  QVector<QPointF> points;
320  const qreal nShift = EmptySheetEdge().length()/GlobalEdgesCount();
321  for (int i = 1; i <= GlobalEdgesCount()+1; ++i)
322  {
323  QLineF l1 = EmptySheetEdge();
324  l1.setLength(nShift*(i-1));
325  points.append(l1.p2());
326  }
327  return points;
328 }
329 
330 //---------------------------------------------------------------------------------------------------------------------
331 const QPointF &VContour::at(int i) const
332 {
333  return d->globalContour.at(i);
334 }
335 
336 //---------------------------------------------------------------------------------------------------------------------
338 {
339  QVector<QPointF> points = GetContour();
340  if (points.isEmpty())
341  {
342  return QRectF();
343  }
344  points.append(points.first());
345  return QPolygonF(points).boundingRect();
346 }
347 
348 //---------------------------------------------------------------------------------------------------------------------
349 QPainterPath VContour::ContourPath() const
350 {
351  QPainterPath path;
352  path.setFillRule(Qt::WindingFill);
353 
354  const QVector<QPointF> points = GetContour();
355  path.moveTo(points.at(0));
356  for (qint32 i = 1; i < points.count(); ++i)
357  {
358  path.lineTo(points.at(i));
359  }
360  path.lineTo(points.at(0));
361 
362  return path;
363 }
364 
365 //---------------------------------------------------------------------------------------------------------------------
366 void VContour::AppendWhole(QVector<QPointF> &contour, const VLayoutPiece &detail, int detJ) const
367 {
368  int processedEdges = 0;
369  const int nD = detail.LayoutEdgesCount();
370  int j = detJ+1;
371  do
372  {
373  if (j > nD)
374  {
375  j=1;
376  }
377  const QVector<QPointF> points = CutEdge(detail.LayoutEdge(j));
378  for (int i = 0; i < points.size()-1; ++i)
379  {
380  contour.append(points.at(i));
381  }
382  ++processedEdges;
383  ++j;
384  }while (processedEdges < nD);
385 }
386 
387 //---------------------------------------------------------------------------------------------------------------------
389 {
390  return QLineF(0, 0, d->paperWidth - 5, 0);
391 }
QSharedDataPointer< VContourData > d
Definition: vcontour.h:115
int GetHeight() const
Definition: vcontour.cpp:128
VContour & operator=(const VContour &contour)
Definition: vcontour.cpp:89
QPainterPath ContourPath() const
Definition: vcontour.cpp:349
void SetHeight(int height)
Definition: vcontour.cpp:134
QRectF BoundingRect() const
Definition: vcontour.cpp:337
void SetWidth(int width)
Definition: vcontour.cpp:146
const QPointF & at(int i) const
Definition: vcontour.cpp:331
int GetWidth() const
Definition: vcontour.cpp:140
void SetShift(quint32 shift)
Definition: vcontour.cpp:122
QVector< QPointF > GetContour() const
Definition: vcontour.cpp:110
void Swap(VContour &contour) Q_DECL_NOTHROW
Definition: vcontour.cpp:70
void AppendWhole(QVector< QPointF > &contour, const VLayoutPiece &detail, int detJ) const
Definition: vcontour.cpp:366
VContour()
Definition: vcontour.cpp:74
QLineF GlobalEdge(int i) const
Definition: vcontour.cpp:252
quint32 GetShift() const
Definition: vcontour.cpp:116
QSizeF GetSize() const
Definition: vcontour.cpp:152
QVector< QPointF > CutEdge(const QLineF &edge) const
Definition: vcontour.cpp:285
void SetContour(const QVector< QPointF > &contour)
Definition: vcontour.cpp:104
QLineF EmptySheetEdge() const
Definition: vcontour.cpp:388
int GlobalEdgesCount() const
Definition: vcontour.cpp:239
QVector< QPointF > CutEmptySheetEdge() const
Definition: vcontour.cpp:317
QVector< QPointF > UniteWithContour(const VLayoutPiece &detail, int globalI, int detJ, BestFrom type) const
Definition: vcontour.cpp:158
int LayoutEdgesCount() const
QLineF LayoutEdge(int i) const
BestFrom
Definition: vlayoutdef.h:68