Seamly2D
Code documentation
vpiece.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  ** @file vpiece.cpp
3  ** @author Douglas S Caskey
4  ** @date Jan 3, 2023
5  **
6  ** @copyright
7  ** Copyright (C) 2017 - 2023 Seamly, LLC
8  ** https://github.com/fashionfreedom/seamly2d
9  **
10  ** @brief
11  ** Seamly2D is free software: you can redistribute it and/or modify
12  ** it under the terms of the GNU General Public License as published by
13  ** the Free Software Foundation, either version 3 of the License, or
14  ** (at your option) any later version.
15  **
16  ** Seamly2D is distributed in the hope that it will be useful,
17  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
18  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  ** GNU General Public License for more details.
20  **
21  ** You should have received a copy of the GNU General Public License
22  ** along with Seamly2D. if not, see <http://www.gnu.org/licenses/>.
23  **************************************************************************/
24 
25 /************************************************************************
26  **
27  ** @file vpiece.cpp
28  ** @author Roman Telezhynskyi <dismine(at)gmail.com>
29  ** @date 3 11, 2016
30  **
31  ** @brief
32  ** @copyright
33  ** This source code is part of the Valentine project, a pattern making
34  ** program, whose allow create and modeling patterns of clothing.
35  ** Copyright (C) 2016 Valentina project
36  ** <https://bitbucket.org/dismine/valentina> All Rights Reserved.
37  **
38  ** Valentina is free software: you can redistribute it and/or modify
39  ** it under the terms of the GNU General Public License as published by
40  ** the Free Software Foundation, either version 3 of the License, or
41  ** (at your option) any later version.
42  **
43  ** Valentina is distributed in the hope that it will be useful,
44  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
45  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
46  ** GNU General Public License for more details.
47  **
48  ** You should have received a copy of the GNU General Public License
49  ** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
50  **
51  *************************************************************************/
52 
53 #include "vpiece.h"
54 #include "vpiece_p.h"
55 #include "vcontainer.h"
56 #include "../vgeometry/vpointf.h"
57 #include "../vgeometry/vabstractcurve.h"
58 #include "../vgeometry/varc.h"
59 #include "../vmisc/vabstractapplication.h"
60 
61 #include <QSharedPointer>
62 #include <QDebug>
63 #include <QPainterPath>
64 
65 namespace
66 {
68 {
69  if (d1Nodes.size() == d2Nodes.size()) //-V807
70  {
71  return QVector<quint32>();
72  }
73 
74  QSet<quint32> set1;
75  for (qint32 i = 0; i < d1Nodes.size(); ++i)
76  {
77  set1.insert(d1Nodes.at(i));
78  }
79 
80  QSet<quint32> set2;
81  for (qint32 j = 0; j < d2Nodes.size(); ++j)
82  {
83  set2.insert(d2Nodes.at(j));
84  }
85 
86  const QList<quint32> set3 = set1.subtract(set2).values();
88  for (qint32 i = 0; i < set3.size(); ++i)
89  {
90  r.append(set3.at(i));
91  }
92 
93  return r;
94 }
95 
96 //---------------------------------------------------------------------------------------------------------------------
98 {
99  int countPointNodes = 0;
100  int countOthers = 0;
101 
102  for (int i = 0; i< path.size(); ++i)
103  {
104  const VPieceNode &node = path.at(i);
105  if (node.isExcluded())
106  {
107  continue;// skip node
108  }
109 
110  node.GetTypeTool() == Tool::NodePoint ? ++countPointNodes : ++countOthers;
111  }
112 
113  return countPointNodes >= 3 || (countPointNodes >= 1 && countOthers >= 1);
114 }
115 }
116 
117 //---------------------------------------------------------------------------------------------------------------------
118 
119 #ifdef Q_COMPILER_RVALUE_REFS
120 VPiece &VPiece::operator=(VPiece &&piece) Q_DECL_NOTHROW
121 { Swap(piece); return *this; }
122 #endif
123 
124 void VPiece::Swap(VPiece &piece) Q_DECL_NOTHROW
125 { VAbstractPiece::Swap(piece); std::swap(d, piece.d); }
126 
127 //---------------------------------------------------------------------------------------------------------------------
129  : VAbstractPiece()
131 {}
132 
133 //---------------------------------------------------------------------------------------------------------------------
134 VPiece::VPiece(const VPiece &piece)
135  : VAbstractPiece(piece)
136  , d(piece.d)
137 {}
138 
139 //---------------------------------------------------------------------------------------------------------------------
141 {
142  if ( &piece == this )
143  {
144  return *this;
145  }
147  d = piece.d;
148  return *this;
149 }
150 
151 //---------------------------------------------------------------------------------------------------------------------
153 {}
154 
155 //---------------------------------------------------------------------------------------------------------------------
157 {
158  return d->m_path;
159 }
160 
161 //---------------------------------------------------------------------------------------------------------------------
163 {
164  return d->m_path;
165 }
166 
167 //---------------------------------------------------------------------------------------------------------------------
168 void VPiece::SetPath(const VPiecePath &path)
169 {
170  d->m_path = path;
171 }
172 
173 //---------------------------------------------------------------------------------------------------------------------
175 {
176  QVector<QPointF> points = GetPath().PathPoints(data);
177  points = CheckLoops(CorrectEquidistantPoints(points));//A path can contains loops
178  return points;
179 }
180 
181 //---------------------------------------------------------------------------------------------------------------------
182 QVector<VPointF> VPiece::MainPathNodePoints(const VContainer *data, bool showExcluded) const
183 {
184  return GetPath().PathNodePoints(data, showExcluded);
185 }
186 
187 //---------------------------------------------------------------------------------------------------------------------
189 {
190  SCASSERT(data != nullptr);
191 
192 
194  {
195  return QVector<QPointF>();
196  }
197 
199  int recordIndex = -1;
200  bool insertingCSA = false;
201  const qreal width = ToPixel(GetSAWidth(), *data->GetPatternUnit());
202  const QVector<VPieceNode> unitedPath = GetUnitedPath(data);
203 
204  QVector<VSAPoint> pointsEkv;
205  for (int i = 0; i< unitedPath.size(); ++i)
206  {
207  const VPieceNode &node = unitedPath.at(i);
208  if (node.isExcluded())
209  {
210  continue;// skip excluded node
211  }
212 
213  switch (node.GetTypeTool())
214  {
215  case (Tool::NodePoint):
216  {
217  if (not insertingCSA)
218  {
219  pointsEkv.append(VPiecePath::PreparePointEkv(node, data));
220 
221  recordIndex = IsCSAStart(records, node.GetId());
222  if (recordIndex != -1 && records.at(recordIndex).includeType == PiecePathIncludeType::AsCustomSA)
223  {
224  insertingCSA = true;
225 
226  const VPiecePath path = data->GetPiecePath(records.at(recordIndex).path);
227  QVector<VSAPoint> r = path.SeamAllowancePoints(data, width, records.at(recordIndex).reverse);
228 
229  for (int j = 0; j < r.size(); ++j)
230  {
231  r[j].SetAngleType(PieceNodeAngle::ByLength);
232  r[j].SetSABefore(0);
233  r[j].SetSAAfter(0);
234  }
235 
236  pointsEkv += r;
237  }
238  }
239  else
240  {
241  if (records.at(recordIndex).endPoint == node.GetId())
242  {
243  insertingCSA = false;
244  recordIndex = -1;
245 
246  pointsEkv.append(VPiecePath::PreparePointEkv(node, data));
247  }
248  }
249  }
250  break;
251  case (Tool::NodeArc):
252  case (Tool::NodeElArc):
253  case (Tool::NodeSpline):
254  case (Tool::NodeSplinePath):
255  {
256  if (not insertingCSA)
257  {
259 
260  pointsEkv += VPiecePath::CurveSeamAllowanceSegment(data, unitedPath, curve, i, node.GetReverse(),
261  width);
262  }
263  }
264  break;
265  default:
266  qDebug()<<"Get wrong tool type. Ignore."<< static_cast<char>(node.GetTypeTool());
267  break;
268  }
269  }
270 
271  return Equidistant(pointsEkv, width);
272 }
273 
274 //---------------------------------------------------------------------------------------------------------------------
275 QVector<QLineF> VPiece::createNotchLines(const VContainer *data, const QVector<QPointF> &seamAllowance) const
276 {
277  const QVector<VPieceNode> unitedPath = GetUnitedPath(data);
278  if (not notchesPossible(unitedPath))
279  {
280  return QVector<QLineF>();
281  }
282 
283  QVector<QLineF> notches;
284 
285  for (int i = 0; i< unitedPath.size(); ++i)
286  {
287  const VPieceNode &node = unitedPath.at(i);
288  if (node.isExcluded() || not node.isNotch())
289  {
290  continue;// skip node
291  }
292 
293  const int previousIndex = VPiecePath::FindInLoopNotExcludedUp(i, unitedPath);
294  const int nextIndex = VPiecePath::FindInLoopNotExcludedDown(i, unitedPath);
295 
296  notches += createNotch(unitedPath, previousIndex, i, nextIndex, data, seamAllowance);
297  }
298 
299  return notches;
300 }
301 
302 //---------------------------------------------------------------------------------------------------------------------
303 QPainterPath VPiece::MainPathPath(const VContainer *data) const
304 {
305  const QVector<QPointF> points = MainPathPoints(data);
306  QPainterPath path;
307 
308  if (not points.isEmpty())
309  {
310  path.moveTo(points[0]);
311  for (qint32 i = 1; i < points.count(); ++i)
312  {
313  path.lineTo(points.at(i));
314  }
315  path.lineTo(points.at(0));
316  path.setFillRule(Qt::WindingFill);
317  }
318 
319  return path;
320 }
321 
322 //---------------------------------------------------------------------------------------------------------------------
323 QPainterPath VPiece::SeamAllowancePath(const VContainer *data) const
324 {
326 }
327 
328 //---------------------------------------------------------------------------------------------------------------------
329 QPainterPath VPiece::SeamAllowancePath(const QVector<QPointF> &points) const
330 {
331  QPainterPath ekv;
332 
333  // seam allowence
335  {
336  if (not points.isEmpty())
337  {
338  ekv.moveTo(points.at(0));
339  for (qint32 i = 1; i < points.count(); ++i)
340  {
341  ekv.lineTo(points.at(i));
342  }
343 
344  ekv.setFillRule(Qt::WindingFill);
345  }
346  }
347 
348  return ekv;
349 }
350 
351 //---------------------------------------------------------------------------------------------------------------------
352 QPainterPath VPiece::getNotchesPath(const VContainer *data, const QVector<QPointF> &pathPoints) const
353 {
354  const QVector<QLineF> notches = createNotchLines(data, pathPoints);
355  QPainterPath path;
356 
357  // seam allowence
358  if (IsSeamAllowance())
359  {
360  if (not notches.isEmpty())
361  {
362  for (qint32 i = 0; i < notches.count(); ++i)
363  {
364  path.moveTo(notches.at(i).p1());
365  path.lineTo(notches.at(i).p2());
366  }
367 
368  path.setFillRule(Qt::WindingFill);
369  }
370  }
371 
372  return path;
373 }
374 
375 //---------------------------------------------------------------------------------------------------------------------
376 bool VPiece::isInLayout() const
377 {
378  return d->m_inLayout;
379 }
380 
381 //---------------------------------------------------------------------------------------------------------------------
382 void VPiece::SetInLayout(bool inLayout)
383 {
384  d->m_inLayout = inLayout;
385 }
386 
387 //---------------------------------------------------------------------------------------------------------------------
388 bool VPiece::isLocked() const
389 {
390  return d->m_isLocked;
391 }
392 
393 //---------------------------------------------------------------------------------------------------------------------
394 void VPiece::setIsLocked(bool isLocked)
395 {
396  d->m_isLocked = isLocked;
397 }
398 
399 //---------------------------------------------------------------------------------------------------------------------
400 bool VPiece::IsUnited() const
401 {
402  return d->m_united;
403 }
404 
405 //---------------------------------------------------------------------------------------------------------------------
406 void VPiece::SetUnited(bool united)
407 {
408  d->m_united = united;
409 }
410 
411 //---------------------------------------------------------------------------------------------------------------------
413 {
414  return d->m_formulaWidth;
415 }
416 
417 //---------------------------------------------------------------------------------------------------------------------
418 void VPiece::setSeamAllowanceWidthFormula(const QString &formula, qreal value)
419 {
420  SetSAWidth(value);
421  const qreal width = GetSAWidth();
422  width >= 0 ? d->m_formulaWidth = formula : d->m_formulaWidth = QLatin1String("0");
423 }
424 
425 //---------------------------------------------------------------------------------------------------------------------
427 {
428  return d->m_internalPaths;
429 }
430 
431 //---------------------------------------------------------------------------------------------------------------------
433 {
434  return d->m_internalPaths;
435 }
436 
437 //---------------------------------------------------------------------------------------------------------------------
439 {
440  d->m_internalPaths = iPaths;
441 }
442 
443 //---------------------------------------------------------------------------------------------------------------------
445 {
446  return d->m_customSARecords;
447 }
448 
449 //---------------------------------------------------------------------------------------------------------------------
451 {
452  return d->m_customSARecords;
453 }
454 
455 //---------------------------------------------------------------------------------------------------------------------
457 {
458  d->m_customSARecords = records;
459 }
460 
461 //---------------------------------------------------------------------------------------------------------------------
463 {
464  return d->m_anchors;
465 }
466 
467 //---------------------------------------------------------------------------------------------------------------------
469 {
470  return d->m_anchors;
471 }
472 
473 //---------------------------------------------------------------------------------------------------------------------
475 {
476  d->m_anchors = anchors;
477 }
478 
479 //---------------------------------------------------------------------------------------------------------------------
480 /**
481  * @brief MissingNodes find missing nodes in piece. When we deleted object in piece and return this piece need
482  * understand, what nodes need make invisible.
483  * @param piece changed piece.
484  * @return list with missing nodes.
485  */
487 {
488  return d->m_path.MissingNodes(piece.GetPath());
489 }
490 
491 //---------------------------------------------------------------------------------------------------------------------
493 {
494  QVector<quint32> oldCSARecords;
495  for (qint32 i = 0; i < d->m_customSARecords.size(); ++i)
496  {
497  oldCSARecords.append(d->m_customSARecords.at(i).path);
498  }
499 
500  QVector<quint32> newCSARecords;
501  for (qint32 i = 0; i < piece.GetCustomSARecords().size(); ++i)
502  {
503  newCSARecords.append(piece.GetCustomSARecords().at(i).path);
504  }
505 
506  return PieceMissingNodes(oldCSARecords, newCSARecords);
507 }
508 
509 //---------------------------------------------------------------------------------------------------------------------
511 {
512  return PieceMissingNodes(d->m_internalPaths, piece.GetInternalPaths());
513 }
514 
515 //---------------------------------------------------------------------------------------------------------------------
517 {
518  return PieceMissingNodes(d->m_anchors, piece.getAnchors());
519 }
520 
521 //---------------------------------------------------------------------------------------------------------------------
523 {
524  d->m_ppData = data;
525 }
526 
527 //---------------------------------------------------------------------------------------------------------------------
528 /**
529  * @brief Returns full access to the pattern piece data object
530  * @return pattern piece data object
531  */
533 {
534  return d->m_ppData;
535 }
536 
537 //---------------------------------------------------------------------------------------------------------------------
538 /**
539  * @brief Returns the read only reference to the pattern piece data object
540  * @return pattern piece data object
541  */
543 {
544  return d->m_ppData;
545 }
546 
547 //---------------------------------------------------------------------------------------------------------------------
549 {
550  d->m_piPatternInfo = info;
551 }
552 
553 //---------------------------------------------------------------------------------------------------------------------
554 /**
555  * @brief Returns full access to the pattern info geometry object
556  * @return pattern info geometry object
557  */
559 {
560  return d->m_piPatternInfo;
561 }
562 
563 //---------------------------------------------------------------------------------------------------------------------
564 /**
565  * @brief Returns the read only reference to the pattern info geometry object
566  * @return pattern info geometry object
567  */
569 {
570  return d->m_piPatternInfo;
571 }
572 
573 //---------------------------------------------------------------------------------------------------------------------
574 /**
575  * @brief VDetail::GetGrainlineGeometry full access to the grainline geometry object
576  * @return reference to grainline geometry object
577  */
579 {
580  return d->m_glGrainline;
581 }
582 
583 //---------------------------------------------------------------------------------------------------------------------
584 /**
585  * @brief VDetail::GetGrainlineGeometry returns the read-only reference to the grainline geometry object
586  * @return reference to grainline geometry object
587  */
589 {
590  return d->m_glGrainline;
591 }
592 
593 //---------------------------------------------------------------------------------------------------------------------
595 {
596  SCASSERT(data != nullptr)
597 
598  QVector<VPieceNode> united = d->m_path.GetNodes();
599 
601  {
602  return united;
603  }
604 
606 
607  for (int i = 0; i < records.size(); ++i)
608  {
609  if (records.at(i).includeType == PiecePathIncludeType::AsMainPath)
610  {
611  const int indexStartPoint = VPiecePath::indexOfNode(united, records.at(i).startPoint);
612  const int indexEndPoint = VPiecePath::indexOfNode(united, records.at(i).endPoint);
613 
614  if (indexStartPoint == -1 || indexEndPoint == -1)
615  {
616  continue;
617  }
618 
619  const QVector<VPieceNode> midBefore = united.mid(0, indexStartPoint+1);
620  const QVector<VPieceNode> midAfter = united.mid(indexEndPoint);
621 
622  QVector<VPieceNode> customNodes = data->GetPiecePath(records.at(i).path).GetNodes();
623  if (records.at(i).reverse)
624  {
625  customNodes = VGObject::GetReversePoints(customNodes);
626  }
627 
628  for (int j = 0; j < customNodes.size(); ++j)
629  {
630  // Additionally reverse all curves
631  if (records.at(i).reverse)
632  {
633  // don't make a check because node point will ignore the change
634  customNodes[j].SetReverse(not customNodes.at(j).GetReverse());
635  }
636 
637  // If seam allowance is built in main path user will not see a notch provided by piece path
639  {
640  customNodes[j].setNotch(false);
641  }
642  else
643  {
644  customNodes[j].SetMainPathNode(false);
645  }
646  }
647 
648  united = midBefore + customNodes + midAfter;
649  }
650  }
651  return united;
652 }
653 
654 //---------------------------------------------------------------------------------------------------------------------
656 {
657  QVector<CustomSARecord> records;
658  for (int i = 0; i < d->m_customSARecords.size(); ++i)
659  {
660  const CustomSARecord &record = d->m_customSARecords.at(i);
661  const int indexStartPoint = d->m_path.indexOfNode(record.startPoint);
662  const int indexEndPoint = d->m_path.indexOfNode(record.endPoint);
663 
664  if (record.startPoint > NULL_ID
665  && record.path > NULL_ID
666  && record.endPoint > NULL_ID
667  && indexStartPoint != -1
668  && not d->m_path.at(indexStartPoint).isExcluded()
669  && indexEndPoint != -1
670  && not d->m_path.at(indexEndPoint).isExcluded()
671  && indexStartPoint < indexEndPoint)
672  {
673  records.append(record);
674  }
675  }
676  return records;
677 }
678 
679 //---------------------------------------------------------------------------------------------------------------------
681 {
682  if (records.size() < 2)
683  {
684  return records;
685  }
686 
687  // cppcheck-suppress variableScope
688  bool foundFilter = false;// Need in case "filter" will stay empty.
689  CustomSARecord filter;
690  int startIndex = d->m_path.CountNodes()-1;
691 
692  for (int i = 0; i < records.size(); ++i)
693  {
694  const int indexStartPoint = d->m_path.indexOfNode(records.at(i).startPoint);
695  if (indexStartPoint < startIndex)
696  {
697  startIndex = i;
698  filter = records.at(i);
699  // cppcheck-suppress unreadVariable
700  foundFilter = true;
701  }
702  }
703 
704  if (not foundFilter)
705  {
706  return records; // return as is
707  }
708 
709  records.remove(startIndex);
710 
711  QVector<CustomSARecord> secondRound;
712  for (int i = 0; i < records.size(); ++i)
713  {
714  const int indexStartPoint = d->m_path.indexOfNode(records.at(i).startPoint);
715  const int indexEndPoint = d->m_path.indexOfNode(filter.endPoint);
716  if (indexStartPoint > indexEndPoint)
717  {
718  secondRound.append(records.at(i));
719  }
720  }
721 
722  QVector<CustomSARecord> filtered;
723  filtered.append(filter);
724 
725  filtered += FilterRecords(secondRound);
726 
727  return filtered;
728 }
729 
730 //---------------------------------------------------------------------------------------------------------------------
732 {
733  SCASSERT(data != nullptr)
734 
735  if (index < 0 || index >= path.size())
736  {
737  return QVector<VSAPoint>();
738  }
739 
740  const VPieceNode &node = path.at(index);
741  QVector<VSAPoint> points;
742 
743  if (node.GetTypeTool() == Tool::NodePoint)
744  {
745  points.append(VPiecePath::PreparePointEkv(node, data));
746  }
747  else
748  {
750  const qreal width = ToPixel(GetSAWidth(), *data->GetPatternUnit());
751 
752  points += VPiecePath::CurveSeamAllowanceSegment(data, path, curve, index, node.GetReverse(), width);
753  }
754  return points;
755 }
756 
757 //---------------------------------------------------------------------------------------------------------------------
758 bool VPiece::getNotchSAPoint(const QVector<VPieceNode> &path, int index, const VContainer *data,
759  VSAPoint &point) const
760 {
761  SCASSERT(data != nullptr)
762 
763  const QVector<VSAPoint> points = getNodeSAPoints(path, index, data);
764 
765  if (points.isEmpty() || points.size() > 1)
766  {
767  return false;
768  }
769 
770  point = points.first();
771  return true;
772 }
773 
774 //---------------------------------------------------------------------------------------------------------------------
775 bool VPiece::getNotchPreviousSAPoints(const QVector<VPieceNode> &path, int index, const VSAPoint &notchSAPoint,
776  const VContainer *data, VSAPoint &point) const
777 {
778  SCASSERT(data != nullptr)
779 
780  const QVector<VSAPoint> points = getNodeSAPoints(path, index, data);
781 
782  if (points.isEmpty())
783  {
784  return false; // Something wrong
785  }
786 
787  bool found = false;
788  int nodeIndex = points.size()-1;
789  do
790  {
791  const VSAPoint previous = points.at(nodeIndex);
792  if (notchSAPoint.toPoint() != previous.toPoint())
793  {
794  point = previous;
795  found = true;
796  }
797  --nodeIndex;
798  } while (nodeIndex >= 0 && not found);
799 
800  if (not found)
801  {
802  return false; // Something wrong
803  }
804  return true;
805 }
806 
807 //---------------------------------------------------------------------------------------------------------------------
808 int VPiece::getNextNotchSAPoints(const QVector<VPieceNode> &path, int index, const VSAPoint &notchSAPoint,
809  const VContainer *data, VSAPoint &point) const
810 {
811  SCASSERT(data != nullptr)
812 
813  const QVector<VSAPoint> points = getNodeSAPoints(path, index, data);
814 
815  if (points.isEmpty())
816  {
817  return false; // Something wrong
818  }
819 
820  bool found = false;
821  int nodeIndex = 0;
822  do
823  {
824  const VSAPoint next = points.at(nodeIndex);
825  if (notchSAPoint.toPoint() != next.toPoint())
826  {
827  point = next;
828  found = true;
829  }
830  ++nodeIndex;
831 
832  } while (nodeIndex < points.size() && not found);
833 
834  if (not found)
835  {
836  return false; // Something wrong
837  }
838  return true;
839 }
840 
841 //---------------------------------------------------------------------------------------------------------------------
842 bool VPiece::getSeamNotchSAPoint(const VSAPoint &previousSAPoint, const VSAPoint &notchSAPoint,
843  const VSAPoint &nextSAPoint, const VContainer *data, QPointF &point) const
844 {
845  SCASSERT(data != nullptr)
846 
847  QVector<QPointF> ekvPoints;
848  const qreal width = ToPixel(GetSAWidth(), *data->GetPatternUnit());
849 
850  /* Because method VAbstractPiece::EkvPoint has troubles with edges on the same line we should specially treat such
851  cases.
852  First check if two edges and seam allowance create parallel lines.
853  Second case check if two edges are on a same line geometrically and a notch point has equal SA width.*/
854  if (IsEkvPointOnLine(notchSAPoint, previousSAPoint, nextSAPoint)// see issue #665
855  || (IsEkvPointOnLine(static_cast<QPointF>(notchSAPoint), static_cast<QPointF>(previousSAPoint),
856  static_cast<QPointF>(nextSAPoint))
857  && qAbs(notchSAPoint.GetSABefore(width)
858  - notchSAPoint.GetSAAfter(width)) < VGObject::accuracyPointOnLine))
859  {
860  QLineF line (notchSAPoint, nextSAPoint);
861  line.setAngle(line.angle() + 90);
862  line.setLength(VAbstractPiece::MaxLocalSA(notchSAPoint, width));
863  ekvPoints.append(line.p2());
864  }
865  else
866  {
867  ekvPoints = EkvPoint(previousSAPoint, notchSAPoint, nextSAPoint, notchSAPoint, width);
868  }
869 
870  if (ekvPoints.isEmpty())
871  { // Just in case
872  return false; // Something wrong
873  }
874 
875  if (ekvPoints.size() == 1 || ekvPoints.size() > 2)
876  {
877  point = ekvPoints.first();
878  }
879  else if (ekvPoints.size() == 2)
880  {
881  QLineF line = QLineF(ekvPoints.at(0), ekvPoints.at(1));
882  line.setLength(line.length()/2.);
883  point = line.p2();
884  }
885  return true;
886 }
887 
888 //---------------------------------------------------------------------------------------------------------------------
889 bool VPiece::isNotchVisible(const QVector<VPieceNode> &path, int notchIndex) const
890 {
891  if (notchIndex < 0 || notchIndex >= path.size())
892  {
893  return false;
894  }
895 
896  const VPieceNode &node = path.at(notchIndex);
897  if (node.GetTypeTool() != Tool::NodePoint || not node.isNotch() || node.isExcluded())
898  {
899  return false;
900  }
901 
903  {
904  return true;
905  }
906 
908  if (records.isEmpty())
909  {
910  return true;
911  }
912 
913  for (int i = 0; i < records.size(); ++i)
914  {
915  if (records.at(i).includeType == PiecePathIncludeType::AsCustomSA)
916  {
917  const int indexStartPoint = VPiecePath::indexOfNode(path, records.at(i).startPoint);
918  const int indexEndPoint = VPiecePath::indexOfNode(path, records.at(i).endPoint);
919  if (notchIndex > indexStartPoint && notchIndex < indexEndPoint)
920  {
921  return false;
922  }
923  }
924  }
925  return true;
926 }
927 
928 //---------------------------------------------------------------------------------------------------------------------
929 QVector<QLineF> VPiece::createNotch(const QVector<VPieceNode> &path, int previousIndex, int notchIndex,
930  int nextIndex, const VContainer *data,
931  const QVector<QPointF> &pathPoints) const
932 {
933  SCASSERT(data != nullptr);
934 
935  if (not isNotchVisible(path, notchIndex))
936  {
937  return QVector<QLineF>();
938  }
939 
940  VSAPoint notchSAPoint;
941  if (not getNotchSAPoint(path, notchIndex, data, notchSAPoint))
942  {
943  return QVector<QLineF>(); // Something wrong
944  }
945 
946  VSAPoint previousSAPoint;
947  if (not getNotchPreviousSAPoints(path, previousIndex, notchSAPoint, data, previousSAPoint))
948  {
949  return QVector<QLineF>(); // Something wrong
950  }
951 
952  VSAPoint nextSAPoint;
953  if (not getNextNotchSAPoints(path, nextIndex, notchSAPoint, data, nextSAPoint))
954  {
955  return QVector<QLineF>(); // Something wrong
956  }
957 
958  const QVector<QPointF> mainPathPoints = MainPathPoints(data);
959  if (not IsSeamAllowanceBuiltIn())
960  {
961  QVector<QLineF> lines;
962  if (path.at(notchIndex).showNotch())
963  {
964  lines += createSeamAllowanceNotch(path, previousSAPoint, notchSAPoint, nextSAPoint,
965  data, notchIndex, pathPoints);
966  }
967  if (not isHideSeamLine()
968  && path.at(notchIndex).IsMainPathNode()
969  && path.at(notchIndex).getNotchSubType() != NotchSubType::Intersection
970  && path.at(notchIndex).showSeamlineNotch())
971  {
972  lines += createBuiltInSaNotch(path, previousSAPoint, notchSAPoint, nextSAPoint, data,
973  notchIndex, mainPathPoints);
974  }
975  return lines;
976  }
977  else
978  {
979  return createBuiltInSaNotch(path, previousSAPoint, notchSAPoint, nextSAPoint, data, notchIndex, mainPathPoints);
980  }
981 }
982 
983 //---------------------------------------------------------------------------------------------------------------------
985  const VSAPoint &notchSAPoint, VSAPoint &nextSAPoint,
986  const VContainer *data, int notchIndex,
987  const QVector<QPointF> &pathPoints) const
988 {
989  QPointF seamNotchSAPoint;
990  if (not getSeamNotchSAPoint(previousSAPoint, notchSAPoint, nextSAPoint, data, seamNotchSAPoint))
991  {
992  return QVector<QLineF>(); // Something wrong
993  }
994 
995  QVector<QLineF> notches;
996 
997  const VPieceNode &node = path.at(notchIndex);
998 
999  NotchData notchData;
1000  notchData.type = node.getNotchType();
1001  notchData.subType = node.getNotchSubType();
1002  notchData.length = ToPixel(node.getNotchLength(), *data->GetPatternUnit());
1003  notchData.width = ToPixel(node.getNotchWidth(), *data->GetPatternUnit());
1004  notchData.angle = node.getNotchAngle();
1005  notchData.count = node.getNotchCount();
1006 
1007 
1009  {
1010  QLineF line = QLineF(seamNotchSAPoint, notchSAPoint);
1011  line.setLength(notchData.length);
1012  notchData.line = line;
1013  notches += createNotches(notchData, pathPoints);
1014  }
1015  else if (node.getNotchSubType() == NotchSubType::Bisector)
1016  {
1017  const QLineF bigLine1 = createParallelLine(previousSAPoint, notchSAPoint, notchData.width );
1018  const QLineF bigLine2 = createParallelLine(notchSAPoint, nextSAPoint, notchData.width );
1019 
1020  QLineF edge1 = QLineF(seamNotchSAPoint, bigLine1.p1());
1021  QLineF edge2 = QLineF(seamNotchSAPoint, bigLine2.p2());
1022 
1023  edge1.setAngle(edge1.angle() + edge1.angleTo(edge2)/2.);
1024  edge1.setLength(notchData.length);
1025 
1026  notchData.line = edge1;
1027  notches += createNotches(notchData, pathPoints);
1028  }
1029  else if (node.getNotchSubType() == NotchSubType::Intersection)
1030  {
1031  QVector<QPointF> seamPoints;
1032  pathPoints.isEmpty() ? seamPoints = SeamAllowancePoints(data) : seamPoints = pathPoints;
1033 
1034  {
1035  // After notch
1036  QLineF line(notchSAPoint, previousSAPoint);
1037  line.setAngle(line.angle() - 180.0);
1038  line.setLength(40000.0);
1039 
1040  QVector<QPointF> intersections = VAbstractCurve::CurveIntersectLine(seamPoints, line);
1041  intersections.removeOne(notchSAPoint);
1042  if (!intersections.isEmpty())
1043  {
1044  line = QLineF(intersections.last(), notchSAPoint);
1045  line.setLength(notchData.length);
1046  notchData.line = line;
1047  notches += createNotches(notchData, pathPoints);
1048  }
1049  }
1050 
1051 
1052  {
1053  // Before notch
1054  QLineF line(notchSAPoint, nextSAPoint);
1055  line.setAngle(line.angle() - 180.0);
1056  line.setLength(40000.0);
1057 
1058  QVector<QPointF> intersections = VAbstractCurve::CurveIntersectLine(seamPoints, line);
1059  intersections.removeOne(notchSAPoint);
1060  if (!intersections.isEmpty())
1061  {
1062  line = QLineF(intersections.last(), notchSAPoint);
1063  line.setLength(notchData.length);
1064  notchData.line = line;
1065  notches += createNotches(notchData, pathPoints);
1066  }
1067  }
1068  }
1069 
1070  return notches;
1071 }
1072 
1073 //---------------------------------------------------------------------------------------------------------------------
1075  const VSAPoint &notchSAPoint, const VSAPoint &nextSAPoint,
1076  const VContainer *data, int notchIndex,
1077  const QVector<QPointF> &pathPoints) const
1078 {
1079  QVector<QLineF> notches;
1080 
1081  const VPieceNode &node = path.at(notchIndex);
1082 
1083  QLineF edge1 = QLineF(notchSAPoint, previousSAPoint);
1084  QLineF edge2 = QLineF(notchSAPoint, nextSAPoint);
1085 
1086  NotchData notchData;
1087  notchData.type = node.getNotchType();
1088  notchData.subType = node.getNotchSubType();
1089  notchData.length = ToPixel(node.getNotchLength(), *data->GetPatternUnit());
1090  notchData.width = ToPixel(node.getNotchWidth(), *data->GetPatternUnit());
1091  notchData.angle = node.getNotchAngle();
1092  notchData.count = node.getNotchCount();
1093 
1094  edge1.setAngle(edge1.angle() + edge1.angleTo(edge2)/2.);
1095  edge1.setLength(notchData.length);
1096  notchData.line = edge1;
1097  notches += createNotches(notchData, pathPoints);
1098 
1099  return notches;
1100 }
1101 
1102 //---------------------------------------------------------------------------------------------------------------------
1103 int VPiece::IsCSAStart(const QVector<CustomSARecord> &records, quint32 id)
1104 {
1105  for (int i = 0; i < records.size(); ++i)
1106  {
1107  if (records.at(i).startPoint == id)
1108  {
1109  return i;
1110  }
1111  }
1112 
1113  return -1;
1114 }
1115 
1116 //---------------------------------------------------------------------------------------------------------------------
1118 {
1119  QLineF refline = QLineF(notchData.line);
1120  qreal angle = notchData.angle;
1121  qreal offset = notchData.offset;
1122 
1123  QLineF line = createParallelLine(refline.p1(), refline.p2(), offset);
1124  line.setAngle(line.angle() + angle);
1125 
1126  QVector<QLineF> lines;
1127  lines.append(findIntersection(pathPoints, QLineF(line.p2(), line.p1())));
1128  return lines;
1129 }
1130 
1131 //---------------------------------------------------------------------------------------------------------------------
1133 {
1134  QLineF refline = QLineF(notchData.line);
1135  qreal length = notchData.length;
1136  qreal width = notchData.width;
1137  qreal angle = notchData.angle;
1138  qreal offset = notchData.offset;
1139 
1140  QLineF tempLine = createParallelLine(refline.p1(), refline.p2(), offset);
1141  tempLine.setAngle(tempLine.angle() + angle);
1142  tempLine = findIntersection(pathPoints, QLineF(tempLine.p2(), tempLine.p1()));
1143  QLineF line = QLineF(tempLine.p2(), tempLine.p1());
1144  line.setLength(length);
1145 
1146  QPointF p1;
1147  {
1148  QLineF tempLine = QLineF(line.p2(), line.p1());
1149  tempLine.setAngle(tempLine.angle() - 90);
1150  tempLine.setLength(width * 0.75 / 2);
1151  p1 = tempLine.p2();
1152  }
1153 
1154  QPointF p2;
1155  {
1156  QLineF tempLine = QLineF(line.p2(), line.p1());
1157  tempLine.setAngle(tempLine.angle() + 90);
1158  tempLine.setLength(width * 0.75 / 2);
1159  p2 = tempLine.p2();
1160  }
1161 
1162  QVector<QLineF> lines;
1163  lines.append(line);
1164  lines.append(QLineF(p1, p2));
1165  return lines;
1166 }
1167 
1168 //---------------------------------------------------------------------------------------------------------------------
1169 QVector<QLineF> VPiece::createUNotch(const NotchData notchData, const QVector<QPointF> &pathPoints) const
1170 {
1171  QLineF refline = QLineF(notchData.line);
1172  qreal length = notchData.length;
1173  qreal width = notchData.width;
1174  qreal angle = notchData.angle;
1175  qreal offset = notchData.offset;
1176 
1177  QLineF centerLine = createParallelLine(refline.p1(), refline.p2(), offset);
1178 
1179  QLineF line1 = createParallelLine(centerLine.p1(), centerLine.p2(), width / 2.);
1180  line1.setLength(length / 2.);
1181  line1.setAngle(line1.angle() + angle);
1182 
1183  QLineF line2 = createParallelLine(centerLine.p1(), centerLine.p2(), - width / 2.);
1184  line2.setLength(length / 2.);
1185  line2.setAngle(line2.angle() + angle);
1186 
1187  centerLine.setLength(length / 2.);
1188  centerLine.setAngle(centerLine.angle() + angle);
1189 
1190  VArc arc(VPointF(centerLine.p2()), width / 2., QLineF(centerLine.p2(), line2.p2()).angle(), QLineF(centerLine.p2(), line1.p2()).angle());
1191 
1192  QVector<QLineF> lines;
1193  lines.append(arc.getSegments());
1194  lines.append(findIntersection(pathPoints, QLineF(line1.p2(), line1.p1())));
1195  lines.append(findIntersection(pathPoints, QLineF(line2.p2(), line2.p1())));
1196  return lines;
1197 }
1198 
1199 //---------------------------------------------------------------------------------------------------------------------
1201 {
1202  QLineF refline = QLineF(notchData.line);
1203  qreal length = notchData.length;
1204  qreal width = notchData.width;
1205  qreal angle = notchData.angle;
1206  qreal offset = notchData.offset;
1207 
1208  QLineF tempLine = createParallelLine(refline.p1(), refline.p2(), offset);
1209  tempLine.setAngle(tempLine.angle() + angle);
1210  tempLine = findIntersection(pathPoints, QLineF(tempLine.p2(), tempLine.p1()));
1211  QLineF line = QLineF(tempLine.p2(), tempLine.p1());
1212  line.setLength(length);
1213 
1214  QPointF p1;
1215  {
1216  QLineF tempLine = QLineF(line.p2(), line.p1());
1217  tempLine.setAngle(tempLine.angle() - 90);
1218  tempLine.setLength(width / 2);
1219  p1 = tempLine.p2();
1220  }
1221 
1222  QPointF p2;
1223  {
1224  QLineF tempLine = QLineF(line.p2(), line.p1());
1225  tempLine.setAngle(tempLine.angle() + 90);
1226  tempLine.setLength(width / 2);
1227  p2 = tempLine.p2();
1228  }
1229 
1230  QVector<QLineF> lines;
1231  lines.append(QLineF(line.p1(), p2));
1232  lines.append(QLineF(line.p1(), p1));
1233  return lines;
1234 }
1235 
1236 //---------------------------------------------------------------------------------------------------------------------
1238 {
1239  QLineF refline = QLineF(notchData.line);
1240  qreal width = notchData.width;
1241  qreal angle = notchData.angle;
1242  qreal offset = notchData.offset;
1243 
1244  QLineF line = createParallelLine(refline.p1(), refline.p2(), offset);
1245  line.setAngle(line.angle() + angle);
1246 
1247  QPointF p1;
1248  {
1249  QLineF tempLine = QLineF(line.p1(), line.p2());
1250  tempLine.setAngle(tempLine.angle() - 90);
1251  tempLine.setLength(width / 2);
1252  p1 = tempLine.p2();
1253  }
1254 
1255  QPointF p2;
1256  {
1257  QLineF tempLine = QLineF(line.p1(), line.p2());
1258  tempLine.setAngle(tempLine.angle() + 90);
1259  tempLine.setLength(width / 2);
1260  p2 = tempLine.p2();
1261  }
1262 
1263  QVector<QLineF> lines;
1264  lines.append(findIntersection(pathPoints, QLineF(line.p2(), p2)));
1265  lines.append(findIntersection(pathPoints, QLineF(line.p2(), p1)));
1266  return lines;
1267 }
1268 
1269 //---------------------------------------------------------------------------------------------------------------------
1270 QVector<QLineF> VPiece::createCastleNotch(const NotchData notchData, const QVector<QPointF> &pathPoints) const
1271 {
1272  QLineF refline = notchData.line;
1273  qreal width = notchData.width;
1274  qreal angle = notchData.angle;
1275  qreal offset = notchData.offset;
1276 
1277  QLineF line = createParallelLine(refline.p1(), refline.p2(), offset);
1278 
1279  QLineF line1 = createParallelLine(line.p1(), line.p2(), width / 2.);
1280  line1.setAngle(line1.angle() + angle);
1281  QLineF line2 = createParallelLine(line.p1(), line.p2(), -width / 2.);
1282  line2.setAngle(line2.angle() + angle);
1283 
1284  QVector<QLineF> lines;
1285  lines.append(QLineF(line1.p2(), line2.p2()));
1286  lines.append(findIntersection(pathPoints, QLineF(line1.p2(), line1.p1())));
1287  lines.append(findIntersection(pathPoints, QLineF(line2.p2(), line2.p1())));
1288  return lines;
1289 }
1290 
1291 //---------------------------------------------------------------------------------------------------------------------
1293 {
1294  //QLineF refline = notchData.line;
1295  //qreal length = notchData.length;
1296  //qreal width = notchData.width;
1297  qreal angle = notchData.angle;
1298  //qreal offset = notchData.offset;
1299 
1300  QVector<QLineF> lines;
1301  lines += createVExternalNotch(notchData, pathPoints);
1302  notchData.angle = angle - 180;
1303  lines += createVExternalNotch(notchData, pathPoints);
1304  return lines;
1305 }
1306 
1307 //---------------------------------------------------------------------------------------------------------------------
1309 {
1310  int count = notchData.count;
1311  NotchType type = notchData.type;
1312  NotchSubType subType = notchData.subType;
1313  qreal width = notchData.width;
1314 
1315  QVector<QLineF> notches;
1316 
1317  if (subType == NotchSubType::Straightforward)
1318  {
1319  switch (type)
1320  {
1321  case NotchType::TNotch:
1322  {
1323  switch (count)
1324  {
1325  case 2:
1326  notchData.offset = width * .625;
1327  notches += createTNotch(notchData, pathPoints);
1328  notchData.offset = -(width * .625);
1329  notches += createTNotch(notchData, pathPoints);
1330  break;
1331  case 3:
1332  notchData.offset = 0;
1333  notches += createTNotch(notchData, pathPoints);
1334  notchData.offset = width * 1.25;
1335  notches += createTNotch(notchData, pathPoints);
1336  notchData.offset = -(width * 1.25);
1337  notches += createTNotch(notchData, pathPoints);
1338  break;
1339  case 1:
1340  default:
1341  notchData.offset = 0;
1342  notches += createTNotch(notchData, pathPoints);
1343  break;
1344  }
1345  break;
1346  case NotchType::UNotch:
1347  switch (count)
1348  {
1349  case 2:
1350  notchData.offset = width * .625;
1351  notches += createUNotch(notchData, pathPoints);
1352  notchData.offset = -(width * .625);
1353  notches += createUNotch(notchData, pathPoints);
1354  break;
1355  case 3:
1356  notchData.offset = 0;
1357  notches += createUNotch(notchData, pathPoints);
1358  notchData.offset = width * 1.375;
1359  notches += createUNotch(notchData, pathPoints);
1360  notchData.offset = -(width * 1.375);
1361  notches += createUNotch(notchData, pathPoints);
1362  break;
1363  case 1:
1364  default:
1365  notchData.offset = 0;
1366  notches += createUNotch(notchData, pathPoints);
1367  break;
1368  }
1369  break;
1370  case NotchType::VInternal:
1371  switch (count)
1372  {
1373  case 2:
1374  notchData.offset = width * .625;
1375  notches += createVInternalNotch(notchData, pathPoints);
1376  notchData.offset = -(width * .625);
1377  notches += createVInternalNotch(notchData, pathPoints);
1378  break;
1379  case 3:
1380  notchData.offset = 0;
1381  notches += createVInternalNotch(notchData, pathPoints);
1382  notchData.offset = width * 1.25;
1383  notches += createVInternalNotch(notchData, pathPoints);
1384  notchData.offset = -(width * 1.25);
1385  notches += createVInternalNotch(notchData, pathPoints);
1386  break;
1387  case 1:
1388  default:
1389  notchData.offset = 0;
1390  notches += createVInternalNotch(notchData, pathPoints);
1391  break;
1392  }
1393  break;
1394  case NotchType::VExternal:
1395  switch (count)
1396  {
1397  case 2:
1398  notchData.offset = width * .625;
1399  notches += createVExternalNotch(notchData, pathPoints);
1400  notchData.offset = -(width * .625);
1401  notches += createVExternalNotch(notchData, pathPoints);
1402  break;
1403  case 3:
1404  notchData.offset = 0;
1405  notches += createVExternalNotch(notchData, pathPoints);
1406  notchData.offset = width * 1.25;
1407  notches += createVExternalNotch(notchData, pathPoints);
1408  notchData.offset = -(width * 1.25);
1409  notches += createVExternalNotch(notchData, pathPoints);
1410  break;
1411  case 1:
1412  default:
1413  notchData.offset = 0;
1414  notches += createVExternalNotch(notchData, pathPoints);
1415  break;
1416  }
1417  break;
1418  case NotchType::Castle:
1419  switch (count)
1420  {
1421  case 2:
1422  notchData.offset = width * .625;
1423  notches += createCastleNotch(notchData, pathPoints);
1424  notchData.offset = -(width * .625);
1425  notches += createCastleNotch(notchData, pathPoints);
1426  break;
1427  case 3:
1428  notchData.offset = 0;
1429  notches += createCastleNotch(notchData, pathPoints);
1430  notchData.offset = width * 1.375;
1431  notches += createCastleNotch(notchData, pathPoints);
1432  notchData.offset = -(width * 1.375);
1433  notches += createCastleNotch(notchData, pathPoints);
1434  break;
1435  case 1:
1436  default:
1437  notchData.offset = 0;
1438  notches += createCastleNotch(notchData, pathPoints);
1439  break;
1440  }
1441  break;
1442  case NotchType::Diamond:
1443  switch (count)
1444  {
1445  case 2:
1446  notchData.offset = width * .625;
1447  notches += createDiamondNotch(notchData, pathPoints);
1448  notchData.offset = -(width * .625);
1449  notches += createDiamondNotch(notchData, pathPoints);
1450  break;
1451  case 3:
1452  notchData.offset = 0;
1453  notches += createDiamondNotch(notchData, pathPoints);
1454  notchData.offset = width * 1.375;
1455  notches += createDiamondNotch(notchData, pathPoints);
1456  notchData.offset = -(width * 1.375);
1457  notches += createDiamondNotch(notchData, pathPoints);
1458  break;
1459  case 1:
1460  default:
1461  notchData.offset = 0;
1462  notches += createDiamondNotch(notchData, pathPoints);
1463  break;
1464  }
1465  break;
1466  case NotchType::Slit:
1467  default:
1468  switch (count)
1469  {
1470  case 2:
1471  notchData.offset = width * .625;
1472  notches += createSlitNotch(notchData, pathPoints);
1473  notchData.offset = -(width * .625);
1474  notches += createSlitNotch(notchData, pathPoints);
1475  break;
1476  case 3:
1477  notchData.offset = 0;
1478  notches += createSlitNotch(notchData, pathPoints);
1479  notchData.offset = width * 1.25;
1480  notches += createSlitNotch(notchData, pathPoints);
1481  notchData.offset = -(width * 1.25);
1482  notches += createSlitNotch(notchData, pathPoints);
1483  break;
1484  case 1:
1485  default:
1486  notchData.offset = 0;
1487  notches += createSlitNotch(notchData, pathPoints);
1488  break;
1489  }
1490  }
1491  }
1492  }
1493  else
1494  {
1495  notchData.offset = 0;
1496  notches += createSlitNotch(notchData, pathPoints);
1497  }
1498 
1499  return notches;
1500 }
1501 
1502 QLineF VPiece::findIntersection(const QVector<QPointF> &pathPoints, const QLineF &line) const
1503 {
1504  QLineF tempLine = line;
1505  tempLine.setLength(tempLine.length()*1.5);
1506  QVector<QPointF> intersections = VAbstractCurve::CurveIntersectLine(pathPoints, tempLine);
1507  if (not intersections.isEmpty())
1508  {
1509  return QLineF(line.p1(), intersections.last());
1510  }
1511 
1512  return line;
1513 }
static QVector< QPointF > CurveIntersectLine(const QVector< QPointF > &points, const QLineF &line)
bool IsSeamAllowanceBuiltIn() const
bool IsSeamAllowance() const
bool isHideSeamLine() const
static bool IsEkvPointOnLine(const QPointF &iPoint, const QPointF &prevPoint, const QPointF &nextPoint)
static QVector< QPointF > Equidistant(const QVector< VSAPoint > &points, qreal width)
qreal GetSAWidth() const
static QLineF createParallelLine(const VSAPoint &p1, const VSAPoint &p2, qreal width)
void SetSAWidth(qreal value)
static QVector< QPointF > EkvPoint(const VSAPoint &p1Line1, const VSAPoint &p2Line1, const VSAPoint &p1Line2, const VSAPoint &p2Line2, qreal width)
EkvPoint return seam allowance points in place of intersection of two edges. Last points of two edges...
static qreal MaxLocalSA(const VSAPoint &p, qreal width)
void Swap(VAbstractPiece &piece) Q_DECL_NOTHROW
static QVector< QPointF > CheckLoops(const QVector< QPointF > &points)
CheckLoops seek and delete loops in equidistant.
static QVector< T > CorrectEquidistantPoints(const QVector< T > &points, bool removeFirstAndLast=true)
CorrectEquidistantPoints clear equivalent points and remove point on line from equdistant.
VAbstractPiece & operator=(const VAbstractPiece &piece)
VArc class for anticlockwise arc.
Definition: varc.h:74
QVector< QLineF > getSegments() const
Definition: varc.cpp:331
The VContainer class container of all variables.
Definition: vcontainer.h:141
const QSharedPointer< T > GeometricObject(const quint32 &id) const
Definition: vcontainer.h:266
VPiecePath GetPiecePath(quint32 id) const
Definition: vcontainer.cpp:198
const Unit * GetPatternUnit() const
Definition: vcontainer.cpp:599
static QVector< T > GetReversePoints(const QVector< T > &points)
GetReversePoint return revers container of points.
Definition: vgobject.h:145
static const double accuracyPointOnLine
Definition: vgobject.h:126
The VGrainlineData class holds information about a grainline like position, size, rotation and visibi...
The VPatternLabelData class holds the information about pattern info label geometry.
The VPieceLabelData class holds some information about a single piece like letter,...
Tool GetTypeTool() const
Definition: vpiecenode.cpp:161
quint32 GetId() const
Definition: vpiecenode.cpp:149
bool isExcluded() const
Definition: vpiecenode.cpp:411
NotchType getNotchType() const
Definition: vpiecenode.cpp:314
qreal getNotchAngle() const
Definition: vpiecenode.cpp:393
bool GetReverse() const
Definition: vpiecenode.cpp:173
qreal getNotchLength() const
Definition: vpiecenode.cpp:369
bool isNotch() const
Definition: vpiecenode.cpp:287
int getNotchCount() const
Definition: vpiecenode.cpp:405
NotchSubType getNotchSubType() const
Definition: vpiecenode.cpp:326
qreal getNotchWidth() const
Definition: vpiecenode.cpp:381
QVector< QPointF > PathPoints(const VContainer *data) const
Definition: vpiecepath.cpp:287
QVector< VSAPoint > SeamAllowancePoints(const VContainer *data, qreal width, bool reverse) const
Definition: vpiecepath.cpp:357
static QVector< VSAPoint > CurveSeamAllowanceSegment(const VContainer *data, const QVector< VPieceNode > &nodes, const QSharedPointer< VAbstractCurve > &curve, int i, bool reverse, qreal width)
Definition: vpiecepath.cpp:905
static int FindInLoopNotExcludedUp(int start, const QVector< VPieceNode > &nodes)
Definition: vpiecepath.cpp:818
QVector< VPointF > PathNodePoints(const VContainer *data, bool showExcluded=true) const
Definition: vpiecepath.cpp:328
QVector< VPieceNode > GetNodes() const
Definition: vpiecepath.cpp:227
static VSAPoint PreparePointEkv(const VPieceNode &node, const VContainer *data)
Definition: vpiecepath.cpp:890
static int FindInLoopNotExcludedDown(int start, const QVector< VPieceNode > &nodes)
Definition: vpiecepath.cpp:854
int indexOfNode(quint32 id) const
Definition: vpiecepath.cpp:507
Definition: vpiece.h:88
QVector< CustomSARecord > FilterRecords(QVector< CustomSARecord > records) const
Definition: vpiece.cpp:680
void setIsLocked(bool isLocked)
Definition: vpiece.cpp:394
QPainterPath SeamAllowancePath(const VContainer *data) const
Definition: vpiece.cpp:323
bool isNotchVisible(const QVector< VPieceNode > &path, int notchIndex) const
Definition: vpiece.cpp:889
QVector< VPieceNode > GetUnitedPath(const VContainer *data) const
Definition: vpiece.cpp:594
bool getSeamNotchSAPoint(const VSAPoint &previousSAPoint, const VSAPoint &notchSAPoint, const VSAPoint &nextSAPoint, const VContainer *data, QPointF &point) const
Definition: vpiece.cpp:842
VPieceLabelData & GetPatternPieceData()
Returns full access to the pattern piece data object.
Definition: vpiece.cpp:532
QVector< CustomSARecord > GetCustomSARecords() const
Definition: vpiece.cpp:444
bool getNotchSAPoint(const QVector< VPieceNode > &path, int index, const VContainer *data, VSAPoint &point) const
Definition: vpiece.cpp:758
bool getNotchPreviousSAPoints(const QVector< VPieceNode > &path, int index, const VSAPoint &notchSAPoint, const VContainer *data, VSAPoint &point) const
Definition: vpiece.cpp:775
QString getSeamAllowanceWidthFormula() const
Definition: vpiece.cpp:412
QSharedDataPointer< VPieceData > d
Definition: vpiece.h:160
QVector< QLineF > createNotchLines(const VContainer *data, const QVector< QPointF > &seamAllowance=QVector< QPointF >()) const
Definition: vpiece.cpp:275
QVector< VSAPoint > getNodeSAPoints(const QVector< VPieceNode > &path, int index, const VContainer *data) const
Definition: vpiece.cpp:731
void Swap(VPiece &piece) Q_DECL_NOTHROW
Definition: vpiece.cpp:124
QPainterPath getNotchesPath(const VContainer *data, const QVector< QPointF > &seamAllowance=QVector< QPointF >()) const
Definition: vpiece.cpp:352
QVector< QLineF > createBuiltInSaNotch(const QVector< VPieceNode > &path, const VSAPoint &previousSAPoint, const VSAPoint &notchSAPoint, const VSAPoint &nextSAPoint, const VContainer *data, int notchIndex, const QVector< QPointF > &pathPoints) const
Definition: vpiece.cpp:1074
bool isInLayout() const
Definition: vpiece.cpp:376
QVector< quint32 > GetInternalPaths() const
Definition: vpiece.cpp:426
QVector< QLineF > createTNotch(NotchData notchData, const QVector< QPointF > &pathPoints) const
Definition: vpiece.cpp:1132
QVector< QLineF > createNotch(const QVector< VPieceNode > &path, int previousIndex, int notchIndex, int nextIndex, const VContainer *data, const QVector< QPointF > &pathPoints=QVector< QPointF >()) const
Definition: vpiece.cpp:929
QVector< QLineF > createSlitNotch(NotchData notchData, const QVector< QPointF > &seamAllowance) const
Definition: vpiece.cpp:1117
void SetPath(const VPiecePath &path)
Definition: vpiece.cpp:168
void SetInLayout(bool inLayout)
Definition: vpiece.cpp:382
QVector< quint32 > missingAnchors(const VPiece &piece) const
Definition: vpiece.cpp:516
QVector< quint32 > getAnchors() const
Definition: vpiece.cpp:462
virtual ~VPiece()
Definition: vpiece.cpp:152
VPiece & operator=(const VPiece &piece)
Definition: vpiece.cpp:140
void setAnchors(const QVector< quint32 > &anchors)
Definition: vpiece.cpp:474
QVector< QPointF > SeamAllowancePoints(const VContainer *data) const
Definition: vpiece.cpp:188
QVector< QLineF > createVExternalNotch(NotchData notchData, const QVector< QPointF > &seamAllowance) const
Definition: vpiece.cpp:1237
static int IsCSAStart(const QVector< CustomSARecord > &records, quint32 id)
Definition: vpiece.cpp:1103
QPainterPath MainPathPath(const VContainer *data) const
Definition: vpiece.cpp:303
QVector< QLineF > createDiamondNotch(NotchData notchData, const QVector< QPointF > &seamAllowance) const
Definition: vpiece.cpp:1292
QVector< quint32 > MissingInternalPaths(const VPiece &piece) const
Definition: vpiece.cpp:510
void SetPatternPieceData(const VPieceLabelData &data)
Definition: vpiece.cpp:522
QVector< VPointF > MainPathNodePoints(const VContainer *data, bool showExcluded=false) const
Definition: vpiece.cpp:182
QVector< quint32 > MissingNodes(const VPiece &piece) const
MissingNodes find missing nodes in piece. When we deleted object in piece and return this piece need ...
Definition: vpiece.cpp:486
void SetCustomSARecords(const QVector< CustomSARecord > &records)
Definition: vpiece.cpp:456
QVector< QLineF > createVInternalNotch(NotchData notchData, const QVector< QPointF > &pathPoints) const
Definition: vpiece.cpp:1200
VPiece()
Definition: vpiece.cpp:128
void setSeamAllowanceWidthFormula(const QString &formula, qreal value)
Definition: vpiece.cpp:418
void SetInternalPaths(const QVector< quint32 > &iPaths)
Definition: vpiece.cpp:438
QVector< QLineF > createUNotch(const NotchData notchData, const QVector< QPointF > &seamAllowance) const
Definition: vpiece.cpp:1169
QVector< QLineF > createSeamAllowanceNotch(const QVector< VPieceNode > &path, VSAPoint &previousSAPoint, const VSAPoint &notchSAPoint, VSAPoint &nextSAPoint, const VContainer *data, int notchIndex, const QVector< QPointF > &pathPoints=QVector< QPointF >()) const
Definition: vpiece.cpp:984
void SetUnited(bool united)
Definition: vpiece.cpp:406
QLineF findIntersection(const QVector< QPointF > &seamAllowance, const QLineF &line) const
Definition: vpiece.cpp:1502
QVector< QPointF > MainPathPoints(const VContainer *data) const
Definition: vpiece.cpp:174
QVector< CustomSARecord > GetValidRecords() const
Definition: vpiece.cpp:655
bool IsUnited() const
Definition: vpiece.cpp:400
QVector< QLineF > createCastleNotch(const NotchData notchData, const QVector< QPointF > &seamAllowance) const
Definition: vpiece.cpp:1270
void SetPatternInfo(const VPatternLabelData &info)
Definition: vpiece.cpp:548
VGrainlineData & GetGrainlineGeometry()
VDetail::GetGrainlineGeometry full access to the grainline geometry object.
Definition: vpiece.cpp:578
QVector< QLineF > createNotches(NotchData notchData, const QVector< QPointF > &seamAllowance) const
Definition: vpiece.cpp:1308
VPatternLabelData & GetPatternInfo()
Returns full access to the pattern info geometry object.
Definition: vpiece.cpp:558
int getNextNotchSAPoints(const QVector< VPieceNode > &path, int index, const VSAPoint &notchSAPoint, const VContainer *data, VSAPoint &point) const
Definition: vpiece.cpp:808
QVector< quint32 > MissingCSAPath(const VPiece &piece) const
Definition: vpiece.cpp:492
bool isLocked() const
Definition: vpiece.cpp:388
VPiecePath GetPath() const
Definition: vpiece.cpp:156
The VPointF class keep data of point.
Definition: vpointf.h:75
The VSAPoint class seam allowance point.
Q_DECL_CONSTEXPR qreal GetSABefore() const
Q_DECL_CONSTEXPR qreal GetSAAfter() const
double ToPixel(double val, const Unit &unit)
Definition: def.cpp:231
NotchType
Definition: def.h:123
#define SCASSERT(cond)
Definition: def.h:317
NotchSubType
Definition: def.h:137
PiecePathType
Definition: def.h:157
@ NodeSplinePath
@ NodeSpline
@ NodeElArc
@ NodeArc
@ NodePoint
#define NULL_ID
Definition: ifcdef.h:76
QVector< quint32 > PieceMissingNodes(const QVector< quint32 > &d1Nodes, const QVector< quint32 > &d2Nodes)
Definition: vpiece.cpp:67
bool notchesPossible(const QVector< VPieceNode > &path)
Definition: vpiece.cpp:97
The CustomSA struct contains record about custom seam allowanse (SA).
Definition: def.h:510
quint32 endPoint
Definition: def.h:521
quint32 path
Definition: def.h:520
quint32 startPoint
Definition: def.h:519
qreal length
Definition: vpiece.h:68
qreal width
Definition: vpiece.h:69
qreal angle
Definition: vpiece.h:70
int count
Definition: vpiece.h:72
QLineF line
Definition: vpiece.h:65
NotchType type
Definition: vpiece.h:66
qreal offset
Definition: vpiece.h:71
NotchSubType subType
Definition: vpiece.h:67