Seamly2D
Code documentation
union_tool.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  ** @file union_tool.cpp
3  ** @author Douglas S Caskey
4  ** @date Dec 27, 2022
5  **
6  ** @copyright
7  ** Copyright (C) 2017 - 2022 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 vtooluniondetails.cpp
28  ** @author Roman Telezhynskyi <dismine(at)gmail.com>
29  ** @date 26 12, 2013
30  **
31  ** @brief
32  ** @copyright
33  ** This source code is part of the Valentina project, a pattern making
34  ** program, whose allow create and modeling patterns of clothing.
35  ** Copyright (C) 2013-2015 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 "union_tool.h"
54 
55 #include <QByteArray>
56 #include <QDomNodeList>
57 #include <QFileInfo>
58 #include <QHash>
59 #include <QLineF>
60 #include <QMessageLogger>
61 #include <QSharedPointer>
62 #include <QStaticStringData>
63 #include <QStringData>
64 #include <QStringDataPtr>
65 #include <QUndoStack>
66 #include <QtDebug>
67 #include <new>
68 
69 #include "pattern_piece_tool.h"
70 #include "vdatatool.h"
71 #include "vnodedetail.h"
73 #include "nodeDetails/vnodearc.h"
75 #include "nodeDetails/vnodepoint.h"
79 #include "../dialogs/tools/dialogtool.h"
80 #include "../dialogs/tools/union_dialog.h"
81 #include "../ifc/xml/vabstractconverter.h"
82 #include "../ifc/xml/vdomdocument.h"
83 #include "../ifc/xml/vlabeltemplateconverter.h"
84 #include "../ifc/xml/vpatternconverter.h"
85 #include "../vformat/vlabeltemplate.h"
86 #include "../vgeometry/varc.h"
87 #include "../vgeometry/vellipticalarc.h"
88 #include "../vgeometry/vsplinepath.h"
89 #include "../vgeometry/vabstractcubicbezier.h"
90 #include "../vgeometry/vabstractcubicbezierpath.h"
91 #include "../vgeometry/vgeometrydef.h"
92 #include "../vgeometry/vpointf.h"
93 #include "../vgeometry/vspline.h"
94 #include "../vgeometry/vsplinepoint.h"
95 #include "../vmisc/vcommonsettings.h"
96 #include "../vmisc/diagnostic.h"
97 #include "../vmisc/logging.h"
98 #include "../vmisc/vabstractapplication.h"
99 #include "../vpatterndb/vcontainer.h"
100 #include "../vpatterndb/vpiecepath.h"
101 #include "../vpatterndb/vpiecenode.h"
102 #include "../vpatterndb/floatItemData/vgrainlinedata.h"
103 #include "../vpatterndb/floatItemData/vpatternlabeldata.h"
104 #include "../vpatterndb/floatItemData/vpiecelabeldata.h"
105 
106 const QString UnionTool::ToolType = QStringLiteral("union");
107 const QString UnionTool::TagUnionPiece = QStringLiteral("unionPiece");
108 const QString UnionTool::TagNode = QStringLiteral("node");
109 const QString UnionTool::TagChildren = QStringLiteral("children");
110 const QString UnionTool::TagChild = QStringLiteral("child");
111 const QString UnionTool::AttrIndexD1 = QStringLiteral("indexD1");
112 const QString UnionTool::AttrIndexD2 = QStringLiteral("indexD2");
113 const QString UnionTool::AttrIdObject = QStringLiteral("idObject");
114 const QString UnionTool::AttrNodeType = QStringLiteral("nodeType");
115 const QString UnionTool::NodeTypeContour = QStringLiteral("Contour");
116 const QString UnionTool::NodeTypeModeling = QStringLiteral("Modeling");
117 
118 QT_WARNING_PUSH
119 QT_WARNING_DISABLE_CLANG("-Wmissing-prototypes")
120 QT_WARNING_DISABLE_INTEL(1418)
121 
122 Q_LOGGING_CATEGORY(vToolUnion, "v.toolUnion")
123 
125 
126 namespace
127 {
128 //---------------------------------------------------------------------------------------------------------------------
129 VPiecePath GetPiecePath(int piece, VAbstractPattern *doc, quint32 id)
130 {
131  const QDomElement tool = doc->elementById(id, VAbstractPattern::TagTools);
132  if (tool.isNull())
133  {
134  VException e(QString("Can't get tool by id='%1'.").arg(id));
135  throw e;
136  }
137 
138  const QDomNodeList nodesList = tool.childNodes();
139  for (qint32 i = 0; i < nodesList.size(); ++i)
140  {
141  const QDomElement element = nodesList.at(i).toElement();
142  if (not element.isNull() && element.tagName() == UnionTool::TagUnionPiece && i+1 == piece)
143  {
144  const QDomNodeList pieceList = element.childNodes();
145  for (qint32 j = 0; j < pieceList.size(); ++j)
146  {
147  const QDomElement element = pieceList.at(j).toElement();
148  if (not element.isNull() && element.tagName() == VAbstractPattern::TagNodes)
149  {
150  return VAbstractPattern::ParsePieceNodes(element);
151  }
152  }
153  }
154  }
155 
156  return VPiecePath();
157 }
158 
159 //---------------------------------------------------------------------------------------------------------------------
161 {
162  return GetPiecePath(1, doc, id);
163 }
164 
165 //---------------------------------------------------------------------------------------------------------------------
167 {
168  return GetPiecePath(2, doc, id);
169 }
170 
171 //---------------------------------------------------------------------------------------------------------------------
173 {
174  const QDomElement tool = doc->elementById(id, VAbstractPattern::TagTools);
175  if (tool.isNull())
176  {
177  VException e(QString("Can't get tool by id='%1'.").arg(id));
178  throw e;
179  }
180 
181  const QDomNodeList nodesList = tool.childNodes();
182  for (qint32 i = 0; i < nodesList.size(); ++i)
183  {
184  const QDomElement element = nodesList.at(i).toElement();
185  if (not element.isNull() && element.tagName() == UnionTool::TagUnionPiece && i+1 == 2)
186  {
187  const QDomNodeList pieceList = element.childNodes();
188  for (qint32 j = 0; j < pieceList.size(); ++j)
189  {
190  const QDomElement element = pieceList.at(j).toElement();
191  if (not element.isNull() && element.tagName() == PatternPieceTool::TagCSA)
192  {
194  }
195  }
196  }
197  }
198 
199  return QVector<CustomSARecord>();
200 }
201 
202 //---------------------------------------------------------------------------------------------------------------------
204 {
205  const QDomElement tool = doc->elementById(id, VAbstractPattern::TagTools);
206  if (tool.isNull())
207  {
208  VException e(QString("Can't get tool by id='%1'.").arg(id));
209  throw e;
210  }
211 
212  const QDomNodeList nodesList = tool.childNodes();
213  for (qint32 i = 0; i < nodesList.size(); ++i)
214  {
215  const QDomElement element = nodesList.at(i).toElement();
216  if (not element.isNull() && element.tagName() == UnionTool::TagUnionPiece && i+1 == 2)
217  {
218  const QDomNodeList pieceList = element.childNodes();
219  for (qint32 j = 0; j < pieceList.size(); ++j)
220  {
221  const QDomElement element = pieceList.at(j).toElement();
222  if (not element.isNull() && element.tagName() == PatternPieceTool::TagIPaths)
223  {
225  }
226  }
227  }
228  }
229 
230  return QVector<quint32>();
231 }
232 
233 //---------------------------------------------------------------------------------------------------------------------
235 {
236  const QDomElement tool = doc->elementById(id, VAbstractPattern::TagTools);
237  if (tool.isNull())
238  {
239  VException e(QString("Can't get tool by id='%1'.").arg(id));
240  throw e;
241  }
242 
243  const QDomNodeList nodesList = tool.childNodes();
244  for (qint32 i = 0; i < nodesList.size(); ++i)
245  {
246  const QDomElement element = nodesList.at(i).toElement();
247  if (not element.isNull() && element.tagName() == UnionTool::TagUnionPiece && i+1 == 2)
248  {
249  const QDomNodeList pieceList = element.childNodes();
250  for (qint32 j = 0; j < pieceList.size(); ++j)
251  {
252  const QDomElement element = pieceList.at(j).toElement();
253  if (not element.isNull() && element.tagName() == PatternPieceTool::TagAnchors)
254  {
255  return VAbstractPattern::ParsePieceAnchors(element);
256  }
257  }
258  }
259  }
260 
261  return QVector<quint32>();
262 }
263 
264 //---------------------------------------------------------------------------------------------------------------------
265 QString getBlockName(VAbstractPattern *doc, quint32 piece1_Id, quint32 piece2_Id)
266 {
267  const QDomElement piece1 = doc->elementById(piece1_Id, VAbstractPattern::TagPiece);
268  if (piece1.isNull())
269  {
270  return QString();
271  }
272 
273  const QDomElement piece2 = doc->elementById(piece2_Id, VAbstractPattern::TagPiece);
274  if (piece2.isNull())
275  {
276  return QString();
277  }
278 
279  const QDomElement block1 = piece1.parentNode().parentNode().toElement();
280  if (block1.isNull() || not block1.hasAttribute(VAbstractPattern::AttrName))
281  {
282  return QString();
283  }
284 
285  const QDomElement block2 = piece2.parentNode().parentNode().toElement();
286  if (block2.isNull() || not block2.hasAttribute(VAbstractPattern::AttrName))
287  {
288  return QString();
289  }
290 
291  const QString block1Name = block1.attribute(VAbstractPattern::AttrName);
292  const QString block2Name = block2.attribute(VAbstractPattern::AttrName);
293 
294  if (block1Name == block2Name)
295  {
296  return block1Name;
297  }
298 
299  const QDomElement pattern = block1.parentNode().toElement();
300  if (pattern.isNull())
301  {
302  return QString();
303  }
304 
305  int piece1_Index = 0;
306  int piece2_Index = 0;
307  const QDomNodeList blockList = pattern.elementsByTagName(VAbstractPattern::TagDraftBlock);
308  for (int i=0; i < blockList.size(); ++i)
309  {
310  const QDomElement draftBlockElement = blockList.at(i).toElement();
311  if (draftBlockElement == block1)
312  {
313  piece1_Index = i;
314  }
315 
316  if (draftBlockElement == block2)
317  {
318  piece2_Index = i;
319  }
320  }
321 
322  if (piece1_Index >= piece2_Index)
323  {
324  return block1Name;
325  }
326  else
327  {
328  return block2Name;
329  }
330 }
331 
332 //---------------------------------------------------------------------------------------------------------------------
333 /**
334  * @brief BiasRotatePoint bias and rotate point.
335  * @param point point.
336  * @param dx bias x axis.
337  * @param dy bias y axis.
338  * @param pRotate point rotation.
339  * @param angle angle rotation.
340  */
341 void BiasRotatePoint(VPointF *point, qreal dx, qreal dy, const QPointF &pRotate, qreal angle)
342 {
343  point->setX(point->x()+dx);
344  point->setY(point->y()+dy);
345  QLineF line(pRotate, static_cast<QPointF>(*point));
346  line.setAngle(line.angle()+angle);
347  point->setX(line.p2().x());
348  point->setY(line.p2().y());
349 }
350 
351 //---------------------------------------------------------------------------------------------------------------------
352 void PointsOnEdge(const VPiecePath &path, quint32 index, VPointF &p1, VPointF &p2, VContainer *data)
353 {
354  VPieceNode piece2_Pt1;
355  VPieceNode piece2_Pt2;
356  path.NodeOnEdge(index, piece2_Pt1, piece2_Pt2);
357  p1 = VPointF(*data->GeometricObject<VPointF>(piece2_Pt1.GetId()));
358  p2 = VPointF(*data->GeometricObject<VPointF>(piece2_Pt2.GetId()));
359 }
360 
361 //---------------------------------------------------------------------------------------------------------------------
362 void UnionInitParameters(const UnionToolInitData &initData, const VPiecePath &piece1Path, const VPiecePath &piece2Path,
363  VPieceNode &piece1_Pt1, qreal &dx, qreal &dy, qreal &angle)
364 {
365  VPieceNode piece1_Pt2;
366  piece1Path.NodeOnEdge(initData.piece1_Index, piece1_Pt1, piece1_Pt2);
367  Q_UNUSED(piece1_Pt2)
368 
369  VPointF point1;
370  VPointF point2;
371  PointsOnEdge(piece1Path, initData.piece1_Index, point1, point2, initData.data);
372 
373  VPointF point3;
374  VPointF point4;
375  PointsOnEdge(piece2Path, initData.piece2_Index, point3, point4, initData.data);
376 
377  dx = point1.x() - point4.x();
378  dy = point1.y() - point4.y();
379 
380  point3.setX(point3.x()+dx);
381  point3.setY(point3.y()+dy);
382 
383  point4.setX(point4.x()+dx);
384  point4.setY(point4.y()+dy);
385 
386  const QLineF p4p3 = QLineF(static_cast<QPointF>(point4), static_cast<QPointF>(point3));
387  const QLineF p1p2 = QLineF(static_cast<QPointF>(point1), static_cast<QPointF>(point2));
388 
389  angle = p4p3.angleTo(p1p2);
390 }
391 
392 //---------------------------------------------------------------------------------------------------------------------
393 quint32 AddNodePoint(const VPieceNode &node, const UnionToolInitData &initData, quint32 idTool,
394  QVector<quint32> &children, const QString &blockName, qreal dx, qreal dy,
395  quint32 pRotate, qreal angle)
396 {
397  QScopedPointer<VPointF> point(new VPointF(*initData.data->GeometricObject<VPointF>(node.GetId())));
398  point->setMode(Draw::Modeling);
399 
400  if (not qFuzzyIsNull(dx) || not qFuzzyIsNull(dy) || pRotate != NULL_ID)
401  {
402  BiasRotatePoint(point.data(), dx, dy, static_cast<QPointF>(*initData.data->GeometricObject<VPointF>(pRotate)),
403  angle);
404  }
405 
406  QScopedPointer<VPointF> point1(new VPointF(*point));
407 
408  const quint32 objectId = initData.data->AddGObject(point.take());
409  children.append(objectId);
410  point1->setMode(Draw::Modeling);
411  const quint32 id = initData.data->AddGObject(point1.take());
412  VNodePoint::Create(initData.doc, initData.data, initData.scene, id, objectId, Document::FullParse, Source::FromTool,
413  blockName, idTool);
414  return id;
415 }
416 
417 //---------------------------------------------------------------------------------------------------------------------
418 quint32 AddAnchorPoint(quint32 id, const UnionToolInitData &initData, quint32 idTool, QVector<quint32> &children,
419  const QString &blockName, qreal dx, qreal dy, quint32 pRotate, qreal angle)
420 {
421  QScopedPointer<VPointF> point(new VPointF(*initData.data->GeometricObject<VPointF>(id)));
422  point->setMode(Draw::Modeling);
423 
424  if (not qFuzzyIsNull(dx) || not qFuzzyIsNull(dy) || pRotate != NULL_ID)
425  {
426  BiasRotatePoint(point.data(), dx, dy, static_cast<QPointF>(*initData.data->GeometricObject<VPointF>(pRotate)),
427  angle);
428  }
429 
430  QScopedPointer<VPointF> point1(new VPointF(*point));
431 
432  const quint32 objectId = initData.data->AddGObject(point.take());
433  children.append(objectId);
434  point1->setMode(Draw::Modeling);
435  const quint32 anchorId = initData.data->AddGObject(point1.take());
436  AnchorPointTool::Create(anchorId, objectId, 0, initData.doc, initData.data, Document::FullParse,
437  Source::FromTool, blockName, idTool);
438  return anchorId;
439 }
440 
441 //---------------------------------------------------------------------------------------------------------------------
442 quint32 AddNodeArc(const VPieceNode &node, const UnionToolInitData &initData, quint32 idTool,
443  QVector<quint32> &children, const QString &blockName, qreal dx, qreal dy,
444  quint32 pRotate, qreal angle)
445 {
446  const QSharedPointer<VArc> arc = initData.data->GeometricObject<VArc>(node.GetId());
447  VPointF p1 = VPointF(arc->GetP1(), "A", 0, 0);
448  VPointF p2 = VPointF(arc->GetP2(), "A", 0, 0);
449  QScopedPointer<VPointF> center(new VPointF(arc->GetCenter()));
450 
451  if (not qFuzzyIsNull(dx) || not qFuzzyIsNull(dy) || pRotate != NULL_ID)
452  {
453  const QPointF p = static_cast<QPointF>(*initData.data->GeometricObject<VPointF>(pRotate));
454 
455  BiasRotatePoint(&p1, dx, dy, p, angle);
456  BiasRotatePoint(&p2, dx, dy, p, angle);
457  BiasRotatePoint(center.data(), dx, dy, p, angle);
458  }
459 
460  QLineF l1(static_cast<QPointF>(*center), static_cast<QPointF>(p1));
461  QLineF l2(static_cast<QPointF>(*center), static_cast<QPointF>(p2));
462  center->setMode(Draw::Modeling);
463  VPointF *tmpCenter = center.take();
464  const quint32 idCenter = initData.data->AddGObject(tmpCenter);
465  Q_UNUSED(idCenter)
466  QScopedPointer<VArc> arc1(new VArc(*tmpCenter, arc->GetRadius(), arc->GetFormulaRadius(), l1.angle(),
467  QString().setNum(l1.angle()), l2.angle(), QString().setNum(l2.angle())));
468  arc1->setMode(Draw::Modeling);
469 
470  QScopedPointer<VArc>arc2(new VArc(*arc1));
471 
472  const quint32 objectId = initData.data->AddGObject(arc1.take());
473  children.append(objectId);
474 
475  arc2->setMode(Draw::Modeling);
476  const quint32 id = initData.data->AddGObject(arc2.take());
477 
478  VNodeArc::Create(initData.doc, initData.data, id, objectId, Document::FullParse, Source::FromTool, blockName,
479  idTool);
480  return id;
481 }
482 
483 //---------------------------------------------------------------------------------------------------------------------
484 quint32 AddNodeElArc(const VPieceNode &node, const UnionToolInitData &initData, quint32 idTool,
485  QVector<quint32> &children, const QString &blockName, qreal dx, qreal dy,
486  quint32 pRotate, qreal angle)
487 {
489  VPointF p1 = VPointF(arc->GetP1(), "A", 0, 0);
490  VPointF p2 = VPointF(arc->GetP2(), "A", 0, 0);
491  QScopedPointer<VPointF> center(new VPointF(arc->GetCenter()));
492 
493  if (not qFuzzyIsNull(dx) || not qFuzzyIsNull(dy) || pRotate != NULL_ID)
494  {
495  const QPointF p = static_cast<QPointF>(*initData.data->GeometricObject<VPointF>(pRotate));
496 
497  BiasRotatePoint(&p1, dx, dy, p, angle);
498  BiasRotatePoint(&p2, dx, dy, p, angle);
499  BiasRotatePoint(center.data(), dx, dy, p, angle);
500  }
501 
502  QLineF l1(static_cast<QPointF>(*center), static_cast<QPointF>(p1));
503  QLineF l2(static_cast<QPointF>(*center), static_cast<QPointF>(p2));
504  center->setMode(Draw::Modeling);
505  VPointF *tmpCenter = center.take();
506  quint32 idCenter = initData.data->AddGObject(tmpCenter);
507  Q_UNUSED(idCenter)
508  QScopedPointer<VEllipticalArc> arc1(new VEllipticalArc (*tmpCenter, arc->GetRadius1(), arc->GetRadius2(),
509  arc->GetFormulaRadius1(), arc->GetFormulaRadius2(),
510  l1.angle(), QString().setNum(l1.angle()), l2.angle(),
511  QString().setNum(l2.angle()), 0, "0"));
512  arc1->setMode(Draw::Modeling);
513 
514  QScopedPointer<VEllipticalArc> arc2(new VEllipticalArc(*arc1));
515 
516  const quint32 objectId = initData.data->AddGObject(arc1.take());
517  children.append(objectId);
518 
519  arc2->setMode(Draw::Modeling);
520  const quint32 id = initData.data->AddGObject(arc2.take());
521 
522  VNodeEllipticalArc::Create(initData.doc, initData.data, id, objectId, Document::FullParse, Source::FromTool,
523  blockName, idTool);
524  return id;
525 }
526 
527 //---------------------------------------------------------------------------------------------------------------------
528 quint32 AddNodeSpline(const VPieceNode &node, const UnionToolInitData &initData, quint32 idTool,
529  QVector<quint32> &children, const QString &blockName, qreal dx, qreal dy,
530  quint32 pRotate, qreal angle)
531 {
533  initData.data->GeometricObject<VAbstractCubicBezier>(node.GetId());
534 
535  QScopedPointer<VPointF> p1(new VPointF(spline->GetP1()));
536  VPointF p2 = VPointF(spline->GetP2());
537  VPointF p3 = VPointF(spline->GetP3());
538  QScopedPointer<VPointF> p4(new VPointF(spline->GetP4()));
539 
540  if (not qFuzzyIsNull(dx) || not qFuzzyIsNull(dy) || pRotate != NULL_ID)
541  {
542  const QPointF p = static_cast<QPointF>(*initData.data->GeometricObject<VPointF>(pRotate));
543 
544  BiasRotatePoint(p1.data(), dx, dy, p, angle);
545  BiasRotatePoint(&p2, dx, dy, p, angle);
546  BiasRotatePoint(&p3, dx, dy, p, angle);
547  BiasRotatePoint(p4.data(), dx, dy, p, angle);
548  }
549 
550  VSpline *spl = new VSpline(*p1, static_cast<QPointF>(p2), static_cast<QPointF>(p3), *p4, 0, Draw::Modeling);
551  const quint32 objectId = initData.data->AddGObject(spl);
552  children.append(objectId);
553 
554  VSpline *spl1 = new VSpline(*spl);
555  spl1->setMode(Draw::Modeling);
556  const quint32 id = initData.data->AddGObject(spl1);
557  VNodeSpline::Create(initData.doc, initData.data, id, objectId, Document::FullParse, Source::FromTool, blockName,
558  idTool);
559  return id;
560 }
561 
562 //---------------------------------------------------------------------------------------------------------------------
563 quint32 AddNodeSplinePath(const VPieceNode &node, const UnionToolInitData &initData, quint32 idTool,
564  QVector<quint32> &children, const QString &blockName, qreal dx, qreal dy,
565  quint32 pRotate, qreal angle)
566 {
567  QScopedPointer<VSplinePath> path(new VSplinePath());
568  path->setMode(Draw::Modeling);
571  for (qint32 i = 1; i <= splinePath->CountSubSpl(); ++i)
572  {
573  const VSpline spline = splinePath->GetSpline(i);
574 
575  QScopedPointer<VPointF> p1(new VPointF(spline.GetP1()));
576  VPointF p2 = VPointF(spline.GetP2());
577  VPointF p3 = VPointF(spline.GetP3());
578  QScopedPointer<VPointF> p4(new VPointF(spline.GetP4()));
579  if (not qFuzzyIsNull(dx) || not qFuzzyIsNull(dy) || pRotate != NULL_ID)
580  {
581  const QPointF p = static_cast<QPointF>(*initData.data->GeometricObject<VPointF>(pRotate));
582 
583  BiasRotatePoint(p1.data(), dx, dy, p, angle);
584  BiasRotatePoint(&p2, dx, dy, p, angle);
585  BiasRotatePoint(&p3, dx, dy, p, angle);
586  BiasRotatePoint(p4.data(), dx, dy, p, angle);
587  }
588 
589  VSpline spl = VSpline(*p1, static_cast<QPointF>(p2), static_cast<QPointF>(p3), *p4);
590  if (i==1)
591  {
592  const qreal angle1 = spl.GetStartAngle()+180;
593  const QString angle1F = QString().number(angle1);
594 
595  path->append(VSplinePoint(*p1, angle1, angle1F, spl.GetStartAngle(), spl.GetStartAngleFormula(),
596  0, "0", spline.GetC1Length(), spline.GetC1LengthFormula()));
597  }
598 
599  const qreal angle2 = spl.GetEndAngle()+180;
600  const QString angle2F = QString().number(angle2);
601  qreal pL2 = 0;
602  QString pL2F("0");
603  if (i+1 <= splinePath->CountSubSpl())
604  {
605  const VSpline nextSpline = splinePath->GetSpline(i+1);
606  pL2 = nextSpline.GetC1Length();
607  pL2F = nextSpline.GetC1LengthFormula();
608  }
609 
610  path->append(VSplinePoint(*p4, spl.GetEndAngle(), spl.GetEndAngleFormula(), angle2, angle2F,
611  spline.GetC2Length(), spline.GetC2LengthFormula(), pL2, pL2F));
612  }
613  QScopedPointer<VSplinePath> path1(new VSplinePath(*path));
614 
615  const quint32 objectId = initData.data->AddGObject(path.take());
616  children.append(objectId);
617 
618  path1->setMode(Draw::Modeling);
619  const quint32 id = initData.data->AddGObject(path1.take());
620 
621  VNodeSplinePath::Create(initData.doc, initData.data, id, objectId, Document::FullParse, Source::FromTool, blockName,
622  idTool);
623  return id;
624 }
625 
626 //---------------------------------------------------------------------------------------------------------------------
627 /**
628  * @brief AddNodeToNewPath create union adding one node at a time.
629  */
630 void AddNodeToNewPath(const UnionToolInitData &initData, VPiecePath &newPath, VPieceNode node,
631  quint32 idTool, QVector<quint32> &children, const QString &blockName, qreal dx = 0, qreal dy = 0,
632  quint32 pRotate = NULL_ID, qreal angle = 0);
633 
634 void AddNodeToNewPath(const UnionToolInitData &initData, VPiecePath &newPath, VPieceNode node,
635  quint32 idTool, QVector<quint32> &children, const QString &blockName, qreal dx, qreal dy,
636  quint32 pRotate, qreal angle)
637 {
638  quint32 id = 0;
639  switch (node.GetTypeTool())
640  {
641  case (Tool::NodePoint):
642  id = AddNodePoint(node, initData, idTool, children, blockName, dx, dy, pRotate, angle);
643  break;
644  case (Tool::NodeArc):
645  id = AddNodeArc(node, initData, idTool, children, blockName, dx, dy, pRotate, angle);
646  break;
647  case (Tool::NodeElArc):
648  id = AddNodeElArc(node, initData, idTool, children, blockName, dx, dy, pRotate, angle);
649  break;
650  case (Tool::NodeSpline):
651  id = AddNodeSpline(node, initData, idTool, children, blockName, dx, dy, pRotate, angle);
652  break;
653  case (Tool::NodeSplinePath):
654  id = AddNodeSplinePath(node, initData, idTool, children, blockName, dx, dy, pRotate, angle);
655  break;
656  default:
657  qDebug()<<"May be wrong tool type!!! Ignoring."<<Q_FUNC_INFO;
658  break;
659  }
660 
661  node.SetId(id);
662  newPath.Append(node);
663 }
664 
665 //---------------------------------------------------------------------------------------------------------------------
666 void FindIndexJ(qint32 piece2Points, const VPiecePath &piece2Path, quint32 piece2_Index, qint32 &j)
667 {
668  if (piece2Points == 0)
669  {
670  VPieceNode node1;
671  VPieceNode node2;
672  piece2Path.NodeOnEdge(piece2_Index, node1, node2);
673  const VPiecePath removedPiece = piece2Path.RemoveEdge(piece2_Index);
674  const int k = removedPiece.indexOfNode(node2.GetId());
675  SCASSERT(k != -1)
676  if (k == removedPiece.CountNodes()-1)
677  {//We have last node in piece, we wil begin from 0
678  j = 0;
679  }
680  else
681  {// Continue from next node
682  j = k+1;
683  }
684  }
685 }
686 
687 //---------------------------------------------------------------------------------------------------------------------
688 QDomElement GetTagChildren(VAbstractPattern *doc, quint32 id)
689 {
690  QDomElement toolUnion = doc->elementById(id, VAbstractPattern::TagTools);
691  if (toolUnion.isNull())
692  {
693  VException e(QString("Can't get tool by id='%1'.").arg(id));
694  throw e;
695  }
696 
697  QDomElement tagChildren = toolUnion.firstChildElement(UnionTool::TagChildren);
698 
699  if (tagChildren.isNull())
700  {
701  tagChildren = doc->createElement(UnionTool::TagChildren);
702  toolUnion.appendChild(tagChildren);
703  }
704 
705  return tagChildren;
706 }
707 
708 //---------------------------------------------------------------------------------------------------------------------
709 void SaveChildren(VAbstractPattern *doc, quint32 id, QDomElement section, const QVector<quint32> &children)
710 {
711  if (children.size() > 0)
712  {
713  for (int i=0; i<children.size(); ++i)
714  {
715  QDomElement tagChild = doc->createElement(UnionTool::TagChild);
716  tagChild.appendChild(doc->createTextNode(QString().setNum(children.at(i))));
717  section.appendChild(tagChild);
718  }
719 
720  GetTagChildren(doc, id).appendChild(section);
721  }
722 }
723 
724 //---------------------------------------------------------------------------------------------------------------------
725 void SaveNodesChildren(VAbstractPattern *doc, quint32 id, const QVector<quint32> &children)
726 {
727  SaveChildren(doc, id, doc->createElement(VAbstractPattern::TagNodes), children);
728 }
729 
730 //---------------------------------------------------------------------------------------------------------------------
731 void SaveCSAChildren(VAbstractPattern *doc, quint32 id, const QVector<quint32> &children)
732 {
733  SaveChildren(doc, id, doc->createElement(PatternPieceTool::TagCSA), children);
734 }
735 
736 //---------------------------------------------------------------------------------------------------------------------
737 void SaveInternalPathsChildren(VAbstractPattern *doc, quint32 id, const QVector<quint32> &children)
738 {
739  SaveChildren(doc, id, doc->createElement(PatternPieceTool::TagIPaths), children);
740 }
741 
742 //---------------------------------------------------------------------------------------------------------------------
743 void SaveAnchorsChildren(VAbstractPattern *doc, quint32 id, const QVector<quint32> &children)
744 {
745  SaveChildren(doc, id, doc->createElement(PatternPieceTool::TagAnchors), children);
746 }
747 
748 //---------------------------------------------------------------------------------------------------------------------
749 QVector<quint32> GetChildren(VAbstractPattern *doc, quint32 id, const QString &tagName)
750 {
751  const QDomElement toolUnion = doc->elementById(id, VAbstractPattern::TagTools);
752  if (toolUnion.isNull())
753  {
754  return QVector<quint32>();
755  }
756 
757  const QDomElement tagChildren = toolUnion.firstChildElement(UnionTool::TagChildren);
758  if (tagChildren.isNull())
759  {
760  return QVector<quint32>();
761  }
762 
763  const QDomElement tagNodes = tagChildren.firstChildElement(tagName);
764  if (tagNodes.isNull())
765  {
766  return QVector<quint32>();
767  }
768 
769  QVector<quint32> childrenId;
770  const QDomNodeList listChildren = tagNodes.elementsByTagName(UnionTool::TagChild);
771  for (int i=0; i < listChildren.size(); ++i)
772  {
773  const QDomElement domElement = listChildren.at(i).toElement();
774  if (not domElement.isNull())
775  {
776  childrenId.append(domElement.text().toUInt());
777  }
778  }
779  return childrenId;
780 }
781 
782 //---------------------------------------------------------------------------------------------------------------------
784 {
785  return GetChildren(doc, id, VAbstractPattern::TagNodes);
786 }
787 
788 //---------------------------------------------------------------------------------------------------------------------
790 {
791  return GetChildren(doc, id, PatternPieceTool::TagCSA);
792 }
793 
794 //---------------------------------------------------------------------------------------------------------------------
796 {
797  return GetChildren(doc, id, PatternPieceTool::TagIPaths);
798 }
799 
800 //---------------------------------------------------------------------------------------------------------------------
802 {
803  return GetChildren(doc, id, PatternPieceTool::TagAnchors);
804 }
805 
806 //---------------------------------------------------------------------------------------------------------------------
807 quint32 TakeNextId(QVector<quint32> &children)
808 {
809  quint32 idChild = NULL_ID;
810  if (not children.isEmpty())
811  {
812  idChild = children.takeFirst();
813  }
814  else
815  {
816  idChild = NULL_ID;
817  }
818  return idChild;
819 }
820 
821 //---------------------------------------------------------------------------------------------------------------------
822 void UpdateNodePoint(VContainer *data, const VPieceNode &node, QVector<quint32> &children, qreal dx, qreal dy,
823  quint32 pRotate, qreal angle)
824 {
825  QScopedPointer<VPointF> point(new VPointF(*data->GeometricObject<VPointF>(node.GetId())));
826  point->setMode(Draw::Modeling);
827  if (not qFuzzyIsNull(dx) || not qFuzzyIsNull(dy) || pRotate != NULL_ID)
828  {
829  BiasRotatePoint(point.data(), dx, dy, static_cast<QPointF>(*data->GeometricObject<VPointF>(pRotate)), angle);
830  }
831  data->UpdateGObject(TakeNextId(children), point.take());
832 }
833 
834 //---------------------------------------------------------------------------------------------------------------------
835 void UpdateNodeArc(VContainer *data, const VPieceNode &node, QVector<quint32> &children, qreal dx, qreal dy,
836  quint32 pRotate, qreal angle)
837 {
838  const QSharedPointer<VArc> arc = data->GeometricObject<VArc>(node.GetId());
839  VPointF p1 = VPointF(arc->GetP1());
840  VPointF p2 = VPointF(arc->GetP2());
841  QScopedPointer<VPointF> center(new VPointF(arc->GetCenter()));
842 
843  if (not qFuzzyIsNull(dx) || not qFuzzyIsNull(dy) || pRotate != NULL_ID)
844  {
845  const QPointF p = static_cast<QPointF>(*data->GeometricObject<VPointF>(pRotate));
846 
847  BiasRotatePoint(&p1, dx, dy, p, angle);
848  BiasRotatePoint(&p2, dx, dy, p, angle);
849  BiasRotatePoint(center.data(), dx, dy, p, angle);
850  }
851 
852  QLineF l1(static_cast<QPointF>(*center), static_cast<QPointF>(p1));
853  QLineF l2(static_cast<QPointF>(*center), static_cast<QPointF>(p2));
854 
855  QScopedPointer<VArc> arc1(new VArc(*center, arc->GetRadius(), arc->GetFormulaRadius(), l1.angle(),
856  QString().setNum(l1.angle()), l2.angle(), QString().setNum(l2.angle())));
857  arc1->setMode(Draw::Modeling);
858  data->UpdateGObject(TakeNextId(children), arc1.take());
859 }
860 
861 //---------------------------------------------------------------------------------------------------------------------
862 void UpdateNodeElArc(VContainer *data, const VPieceNode &node, QVector<quint32> &children, qreal dx, qreal dy,
863  quint32 pRotate, qreal angle)
864 {
866  VPointF p1 = VPointF(arc->GetP1());
867  VPointF p2 = VPointF(arc->GetP2());
868  QScopedPointer<VPointF> center(new VPointF(arc->GetCenter()));
869 
870  if (not qFuzzyIsNull(dx) || not qFuzzyIsNull(dy) || pRotate != NULL_ID)
871  {
872  const QPointF p = static_cast<QPointF>(*data->GeometricObject<VPointF>(pRotate));
873 
874  BiasRotatePoint(&p1, dx, dy, p, angle);
875  BiasRotatePoint(&p2, dx, dy, p, angle);
876  BiasRotatePoint(center.data(), dx, dy, p, angle);
877  }
878 
879  QLineF l1(static_cast<QPointF>(*center), static_cast<QPointF>(p1));
880  QLineF l2(static_cast<QPointF>(*center), static_cast<QPointF>(p2));
881 
882  QScopedPointer<VEllipticalArc> arc1(new VEllipticalArc (*center, arc->GetRadius1(), arc->GetRadius2(),
883  arc->GetFormulaRadius1(), arc->GetFormulaRadius2(),
884  l1.angle(), QString().setNum(l1.angle()), l2.angle(),
885  QString().setNum(l2.angle()), 0, "0"));
886  arc1->setMode(Draw::Modeling);
887  data->UpdateGObject(TakeNextId(children), arc1.take());
888 }
889 
890 //---------------------------------------------------------------------------------------------------------------------
891 void UpdateNodeSpline(VContainer *data, const VPieceNode &node, QVector<quint32> &children, qreal dx, qreal dy,
892  quint32 pRotate, qreal angle)
893 {
896 
897  QScopedPointer<VPointF> p1(new VPointF(spline->GetP1()));
898  VPointF p2 = VPointF(spline->GetP2());
899  VPointF p3 = VPointF(spline->GetP3());
900  QScopedPointer<VPointF> p4(new VPointF(spline->GetP4()));
901 
902  if (not qFuzzyIsNull(dx) || not qFuzzyIsNull(dy) || pRotate != NULL_ID)
903  {
904  const QPointF p = static_cast<QPointF>(*data->GeometricObject<VPointF>(pRotate));
905 
906  BiasRotatePoint(p1.data(), dx, dy, p, angle);
907  BiasRotatePoint(&p2, dx, dy, p, angle);
908  BiasRotatePoint(&p3, dx, dy, p, angle);
909  BiasRotatePoint(p4.data(), dx, dy, p, angle);
910  }
911 
912  QScopedPointer<VSpline> spl(new VSpline(*p1, static_cast<QPointF>(p2), static_cast<QPointF>(p3), *p4, 0,
913  Draw::Modeling));
914  data->UpdateGObject(TakeNextId(children), spl.take());
915 }
916 
917 //---------------------------------------------------------------------------------------------------------------------
918 void UpdateNodeSplinePath(VContainer *data, const VPieceNode &node, QVector<quint32> &children, qreal dx, qreal dy,
919  quint32 pRotate, qreal angle)
920 {
921  QScopedPointer<VSplinePath> path(new VSplinePath());
922  path->setMode(Draw::Modeling);
925  SCASSERT(splinePath != nullptr)
926  for (qint32 i = 1; i <= splinePath->CountSubSpl(); ++i)
927  {
928  const VSpline spline = splinePath->GetSpline(i);
929 
930  QScopedPointer<VPointF> p1(new VPointF(spline.GetP1()));
931  VPointF p2 = VPointF(spline.GetP2());
932  VPointF p3 = VPointF(spline.GetP3());
933  QScopedPointer<VPointF> p4(new VPointF(spline.GetP4()));
934 
935  if (not qFuzzyIsNull(dx) || not qFuzzyIsNull(dy) || pRotate != NULL_ID)
936  {
937  const QPointF p = static_cast<QPointF>(*data->GeometricObject<VPointF>(pRotate));
938 
939  BiasRotatePoint(p1.data(), dx, dy, p, angle);
940  BiasRotatePoint(&p2, dx, dy, p, angle);
941  BiasRotatePoint(&p3, dx, dy, p, angle);
942  BiasRotatePoint(p4.data(), dx, dy, p, angle);
943  }
944 
945  VSpline spl = VSpline(*p1, static_cast<QPointF>(p2), static_cast<QPointF>(p3), *p4);
946  if (i==1)
947  {
948  const qreal angle1 = spl.GetStartAngle()+180;
949  const QString angle1F = QString().number(angle1);
950 
951  path->append(VSplinePoint(*p1, angle1, angle1F, spl.GetStartAngle(), spl.GetStartAngleFormula(),
952  0, "0", spline.GetC1Length(), spline.GetC1LengthFormula()));
953  }
954 
955  const qreal angle2 = spl.GetEndAngle()+180;
956  const QString angle2F = QString().number(angle2);
957 
958  qreal pL2 = 0;
959  QString pL2F("0");
960  if (i+1 <= splinePath->CountSubSpl())
961  {
962  const VSpline nextSpline = splinePath->GetSpline(i+1);
963  pL2 = nextSpline.GetC1Length();
964  pL2F = nextSpline.GetC1LengthFormula();
965  }
966 
967  path->append(VSplinePoint(*p4, spl.GetEndAngle(), spl.GetEndAngleFormula(), angle2, angle2F,
968  spline.GetC2Length(), spline.GetC2LengthFormula(), pL2, pL2F));
969  }
970  data->UpdateGObject(TakeNextId(children), path.take());
971 }
972 
973 //---------------------------------------------------------------------------------------------------------------------
974 /**
975  * @brief UpdateNodes update nodes of union.
976  * @param data container with variables.
977  * @param node piece's node.
978  * @param children list ids of all children.
979  * @param dx bias node x axis.
980  * @param dy bias node y axis.
981  * @param pRotate point rotation.
982  * @param angle angle rotation.
983  */
984 void UpdatePathNode(VContainer *data, const VPieceNode &node, QVector<quint32> &children,
985  qreal dx = 0, qreal dy = 0, quint32 pRotate = NULL_ID, qreal angle = 0);
986 void UpdatePathNode(VContainer *data, const VPieceNode &node, QVector<quint32> &children, qreal dx, qreal dy,
987  quint32 pRotate, qreal angle)
988 {
989  switch (node.GetTypeTool())
990  {
991  case (Tool::NodePoint):
992  UpdateNodePoint(data, node, children, dx, dy, pRotate, angle);
993  break;
994  case (Tool::NodeArc):
995  UpdateNodeArc(data, node, children, dx, dy, pRotate, angle);
996  break;
997  case (Tool::NodeElArc):
998  UpdateNodeElArc(data, node, children, dx, dy, pRotate, angle);
999  break;
1000  case (Tool::NodeSpline):
1001  UpdateNodeSpline(data, node, children, dx, dy, pRotate, angle);
1002  break;
1003  case (Tool::NodeSplinePath):
1004  UpdateNodeSplinePath(data, node, children, dx, dy, pRotate, angle);
1005  break;
1006  default:
1007  qDebug()<<"May be wrong tool type!!! Ignoring."<<Q_FUNC_INFO;
1008  break;
1009  }
1010 }
1011 
1012 //---------------------------------------------------------------------------------------------------------------------
1013 void CreateUnitedNodes(VPiece &newPiece, const VPiece &piece1, const VPiece &piece2, quint32 id, const QString &blockName,
1014  const UnionToolInitData &initData, qreal dx, qreal dy, quint32 pRotate, qreal angle)
1015 {
1016  const VPiecePath piece1Path = piece1.GetPath().RemoveEdge(initData.piece1_Index);
1017  const VPiecePath piece2Path = piece2.GetPath().RemoveEdge(initData.piece2_Index);
1018 
1019  const qint32 piece1NodeCount = piece1Path.CountNodes();
1020  const qint32 piece2NodeCount = piece2Path.CountNodes();
1021 
1022  qint32 piece2Points = 0; //Keeps number points the second piece, what we have already added.
1023  qint32 i = 0;
1024  QVector<quint32> children;
1025  VPiecePath newPath;
1026  const int piece1_Pt1_Index = piece1.GetPath().indexOfNode(pRotate);
1027  do
1028  {
1029  AddNodeToNewPath(initData, newPath, piece1Path.at(i), id, children, blockName);
1030  ++i;
1031  if (i > piece1_Pt1_Index && piece2Points < piece2NodeCount-1)
1032  {
1033  qint32 j = 0;
1034  FindIndexJ(piece2Points, piece2.GetPath(), initData.piece2_Index, j);
1035  do
1036  {
1037  if (j >= piece2NodeCount)
1038  {
1039  j=0;
1040  }
1041  AddNodeToNewPath(initData, newPath, piece2Path.at(j), id, children, blockName, dx, dy, pRotate, angle);
1042  ++piece2Points;
1043  ++j;
1044  } while (piece2Points < piece2NodeCount-1);
1045  }
1046  } while (i < piece1NodeCount);
1047 
1048  newPiece.SetPath(newPath);
1049 
1050  SCASSERT(not children.isEmpty())
1051  SaveNodesChildren(initData.doc, id, children);
1052 }
1053 
1054 //---------------------------------------------------------------------------------------------------------------------
1055 void createCSAUnion(VPiece &newPiece, const VPiece &d, QVector<quint32> &children, quint32 id,
1056  const QString &blockName, const UnionToolInitData &initData, qreal dx, qreal dy,
1057  quint32 pRotate, qreal angle)
1058 {
1059  QVector<quint32> nodeChildren;
1060  for(int i=0; i < d.GetCustomSARecords().size(); ++i)
1061  {
1062  CustomSARecord record = d.GetCustomSARecords().at(i);
1063  const VPiecePath path = initData.data->GetPiecePath(record.path);
1064  VPiecePath newPath = path;
1065  newPath.Clear();//Clear nodes
1066  for (int i=0; i < path.CountNodes(); ++i)
1067  {
1068  AddNodeToNewPath(initData, newPath, path.at(i), id, nodeChildren, blockName, dx, dy, pRotate, angle);
1069  }
1070  const quint32 idPath = initData.data->AddPiecePath(newPath);
1071  VToolInternalPath::Create(idPath, newPath, NULL_ID, initData.scene, initData.doc, initData.data, initData.parse,
1072  Source::FromTool, blockName, id);
1073  record.path = idPath;
1074  newPiece.GetCustomSARecords().append(record);
1075  nodeChildren.prepend(idPath);
1076  }
1077  children += nodeChildren;
1078 }
1079 
1080 //---------------------------------------------------------------------------------------------------------------------
1081 void CreateUnitedCSA(VPiece &newPiece, const VPiece &piece1, const VPiece &piece2, quint32 id, const QString &blockName,
1082  const UnionToolInitData &initData, qreal dx, qreal dy, quint32 pRotate, qreal angle)
1083 {
1084  for (int i = 0; i < piece1.GetCustomSARecords().size(); ++i)
1085  {
1086  newPiece.GetCustomSARecords().append(piece1.GetCustomSARecords().at(i));
1087  }
1088 
1089  QVector<quint32> children;
1090  createCSAUnion(newPiece, piece2, children, id, blockName, initData, dx, dy, pRotate, angle);
1091  SaveCSAChildren(initData.doc, id, children);
1092 }
1093 
1094 //---------------------------------------------------------------------------------------------------------------------
1095 void createUnionInternalPaths(VPiece &newPiece, const VPiece &d, QVector<quint32> &children, quint32 id,
1096  const QString &blockName, const UnionToolInitData &initData, qreal dx,
1097  qreal dy, quint32 pRotate, qreal angle)
1098 {
1099  QVector<quint32> nodeChildren;
1100  for(int i=0; i < d.GetInternalPaths().size(); ++i)
1101  {
1102  const VPiecePath path = initData.data->GetPiecePath(d.GetInternalPaths().at(i));
1103  VPiecePath newPath = path;
1104  newPath.Clear();//Clear nodes
1105 
1106  for (int i=0; i < path.CountNodes(); ++i)
1107  {
1108  AddNodeToNewPath(initData, newPath, path.at(i), id, nodeChildren, blockName, dx, dy, pRotate, angle);
1109  }
1110  const quint32 idPath = initData.data->AddPiecePath(newPath);
1111  VToolInternalPath::Create(idPath, newPath, NULL_ID, initData.scene, initData.doc, initData.data, initData.parse,
1112  Source::FromTool, blockName, id);
1113  newPiece.GetInternalPaths().append(idPath);
1114  nodeChildren.prepend(idPath);
1115  }
1116  children += nodeChildren;
1117 }
1118 
1119 //---------------------------------------------------------------------------------------------------------------------
1120 void CreateUnitedInternalPaths(VPiece &newPiece, const VPiece &piece1, const VPiece &piece2, quint32 id,
1121  const QString &blockName, const UnionToolInitData &initData, qreal dx, qreal dy,
1122  quint32 pRotate, qreal angle)
1123 {
1124  for (int i = 0; i < piece1.GetInternalPaths().size(); ++i)
1125  {
1126  newPiece.GetInternalPaths().append(piece1.GetInternalPaths().at(i));
1127  }
1128 
1129  QVector<quint32> children;
1130  createUnionInternalPaths(newPiece, piece2, children, id, blockName, initData, dx, dy, pRotate, angle);
1131 
1132  SaveInternalPathsChildren(initData.doc, id, children);
1133 }
1134 
1135 //---------------------------------------------------------------------------------------------------------------------
1136 void createUnionAnchors(VPiece &newPiece, const VPiece &d, QVector<quint32> &children, quint32 idTool,
1137  const QString &blockName, const UnionToolInitData &initData, qreal dx, qreal dy,
1138  quint32 pRotate, qreal angle)
1139 {
1140  QVector<quint32> nodeChildren;
1141  for(int i=0; i < d.getAnchors().size(); ++i)
1142  {
1143  const quint32 id = AddAnchorPoint(d.getAnchors().at(i), initData, idTool, children, blockName, dx, dy, pRotate, angle);
1144  newPiece.getAnchors().append(id);
1145  nodeChildren.prepend(id);
1146  }
1147  children += nodeChildren;
1148 }
1149 
1150 //---------------------------------------------------------------------------------------------------------------------
1151 void createUnitedAnchors(VPiece &newPiece, const VPiece &piece1, const VPiece &piece2, quint32 id, const QString &blockName,
1152  const UnionToolInitData &initData, qreal dx, qreal dy, quint32 pRotate, qreal angle)
1153 {
1154  for (int i = 0; i < piece1.getAnchors().size(); ++i)
1155  {
1156  newPiece.getAnchors().append(piece1.getAnchors().at(i));
1157  }
1158 
1159  QVector<quint32> children;
1160  createUnionAnchors(newPiece, piece2, children, id, blockName, initData, dx, dy, pRotate, angle);
1161  SaveAnchorsChildren(initData.doc, id, children);
1162 }
1163 
1164 //---------------------------------------------------------------------------------------------------------------------
1165 void UpdateUnitedNodes(quint32 id, const UnionToolInitData &initData, qreal dx, qreal dy, quint32 pRotate,
1166  qreal angle)
1167 {
1168  const VPiecePath piece1Path = GetPiece1MainPath(initData.doc, id);
1169  const VPiecePath piece1REPath = piece1Path.RemoveEdge(initData.piece1_Index);
1170 
1171  const VPiecePath piece2Path = GetPiece2MainPath(initData.doc, id);
1172  const VPiecePath piece2REPath = piece2Path.RemoveEdge(initData.piece2_Index);
1173 
1174  const qint32 piece1NodeCount = piece1REPath.CountNodes();
1175  const qint32 piece2NodeCount = piece2REPath.CountNodes();
1176 
1177  QVector<quint32> children = GetNodesChildren(initData.doc, id);
1178  if (not children.isEmpty())
1179  {
1180  // This check need for backward compatibility
1181  // Remove check and "else" part if min version is 0.3.2
1182  Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 3, 2),
1183  "Time to refactor the code.");
1184  if (children.size() == piece1NodeCount + piece2NodeCount-1)
1185  {
1186  qint32 piece2Points = 0; //Keeps number points the second piece, what we have already added.
1187  qint32 i = 0;
1188  const int indexOfNode = piece1Path.indexOfNode(pRotate);
1189  do
1190  {
1191  UpdatePathNode(initData.data, piece1REPath.at(i), children);
1192  ++i;
1193  if (i > indexOfNode && piece2Points < piece2NodeCount-1)
1194  {
1195  qint32 j = 0;
1196  FindIndexJ(piece2Points, piece2Path, initData.piece2_Index, j);
1197  do
1198  {
1199  if (j >= piece2NodeCount)
1200  {
1201  j=0;
1202  }
1203  UpdatePathNode(initData.data, piece2REPath.at(j), children, dx, dy, pRotate, angle);
1204  ++piece2Points;
1205  ++j;
1206  } while (piece2Points < piece2NodeCount-1);
1207  }
1208  } while (i<piece1NodeCount);
1209  }
1210  else // remove if min version is 0.3.2
1211  {
1212  qint32 piece2Points = 0; //Keeps number points the second piece, what we have already added.
1213  qint32 i = 0;
1214  const int indexOfNode = piece1Path.indexOfNode(pRotate);
1215  do
1216  {
1217  ++i;
1218  if (i > indexOfNode)
1219  {
1220  const int childrenCount = children.size();
1221  qint32 j = 0;
1222  FindIndexJ(piece2Points, piece2Path, initData.piece2_Index, j);
1223  do
1224  {
1225  if (j >= piece2NodeCount)
1226  {
1227  j=0;
1228  }
1229  UpdatePathNode(initData.data, piece2REPath.at(j), children, dx, dy, pRotate, angle);
1230  ++piece2Points;
1231  ++j;
1232  } while (piece2Points < childrenCount);
1233  break;
1234  }
1235  } while (i<piece1NodeCount);
1236  }
1237  }
1238 }
1239 
1240 //---------------------------------------------------------------------------------------------------------------------
1241 void createUnionPaths(const UnionToolInitData &initData, qreal dx, qreal dy, quint32 pRotate,
1242  qreal angle, const QVector<quint32> &records, QVector<quint32> children)
1243 {
1244  for (int i=0; i < records.size(); ++i)
1245  {
1246  const VPiecePath path = initData.data->GetPiecePath(records.at(i));
1247  const quint32 updatedId = TakeNextId(children);
1248 
1249  VPiecePath updatedPath(path);
1250  updatedPath.Clear();
1251 
1252  for (int j=0; j < path.CountNodes(); ++j)
1253  {
1254  const VPieceNode &node = path.at(j);
1255  const quint32 id = TakeNextId(children);
1256  updatedPath.Append(VPieceNode(id, node.GetTypeTool(), node.GetReverse()));
1257  QVector<quint32> nodeChildren = {id};
1258  UpdatePathNode(initData.data, path.at(j), nodeChildren, dx, dy, pRotate, angle);
1259  }
1260  initData.data->UpdatePiecePath(updatedId, updatedPath);
1261  }
1262 }
1263 
1264 //---------------------------------------------------------------------------------------------------------------------
1265 void updateUnionCSA(quint32 id, const UnionToolInitData &initData, qreal dx, qreal dy, quint32 pRotate,
1266  qreal angle, const QVector<CustomSARecord> &records)
1267 {
1268  QVector<quint32> idRecords;
1269  for (int i = 0; i < records.size(); ++i)
1270  {
1271  idRecords.append(records.at(i).path);
1272  }
1273  createUnionPaths(initData, dx, dy, pRotate, angle, idRecords, GetCSAChildren(initData.doc, id));
1274 }
1275 
1276 //---------------------------------------------------------------------------------------------------------------------
1277 void updateUnionInternalPaths(quint32 id, const UnionToolInitData &initData, qreal dx, qreal dy,
1278  quint32 pRotate, qreal angle, const QVector<quint32> &records)
1279 {
1280  createUnionPaths(initData, dx, dy, pRotate, angle, records, GetInternalPathsChildren(initData.doc, id));
1281 }
1282 
1283 //---------------------------------------------------------------------------------------------------------------------
1284 void updateUnionAnchors(quint32 id, const UnionToolInitData &initData, qreal dx, qreal dy,
1285  quint32 pRotate, qreal angle, const QVector<quint32> &records)
1286 {
1287  QVector<quint32> children = getAnchorChildren(initData.doc, id);
1288 
1289  for (int i = 0; i < records.size(); ++i)
1290  {
1291  QScopedPointer<VPointF> point(new VPointF(*initData.data->GeometricObject<VPointF>(records.at(i))));
1292  point->setMode(Draw::Modeling);
1293  if (not qFuzzyIsNull(dx) || not qFuzzyIsNull(dy) || pRotate != NULL_ID)
1294  {
1295  BiasRotatePoint(point.data(), dx, dy,
1296  static_cast<QPointF>(*initData.data->GeometricObject<VPointF>(pRotate)), angle);
1297  }
1298  initData.data->UpdateGObject(TakeNextId(children), point.take());
1299  }
1300 }
1301 
1302 //---------------------------------------------------------------------------------------------------------------------
1303 void createUnion(quint32 id, const UnionToolInitData &initData, qreal dx, qreal dy, quint32 pRotate,
1304  qreal angle)
1305 {
1306  const QString blockName = getBlockName(initData.doc, initData.piece1_Id, initData.piece2_Id);
1307  SCASSERT(not blockName.isEmpty())
1308 
1309  const VPiece piece1 = initData.data->GetPiece(initData.piece1_Id);
1310  const VPiece piece2 = initData.data->GetPiece(initData.piece2_Id);
1311 
1312  VPiece newPiece;
1313 
1314  CreateUnitedNodes(newPiece, piece1, piece2, id, blockName, initData, dx, dy, pRotate, angle);
1315  CreateUnitedCSA(newPiece, piece1, piece2, id, blockName, initData, dx, dy, pRotate, angle);
1316  CreateUnitedInternalPaths(newPiece, piece1, piece2, id, blockName, initData, dx, dy, pRotate, angle);
1317  createUnitedAnchors(newPiece, piece1, piece2, id, blockName, initData, dx, dy, pRotate, angle);
1318 
1319  VPiecePath path = newPiece.GetPath();
1320  const QRectF rect = QPolygonF(path.PathPoints(initData.data)).boundingRect();
1321 
1322  newPiece.SetName(QObject::tr("Union piece"));
1323  newPiece.SetSeamAllowance(qApp->Settings()->getDefaultSeamAllowanceVisibilty());
1324  newPiece.GetPatternInfo().SetVisible(qApp->Settings()->showPatternLabels());
1325  newPiece.GetPatternInfo().SetLabelWidth(QString::number(qApp->Settings()->getDefaultLabelWidth()));
1326  newPiece.GetPatternInfo().SetLabelHeight(QString::number(qApp->Settings()->getDefaultLabelHeight()));
1327  qreal width = newPiece.GetPatternInfo().GetLabelWidth().toDouble();
1328  qreal height = newPiece.GetPatternInfo().GetLabelHeight().toDouble();
1329  qreal xPos = rect.left() + (rect.width()/2.0 - width)/2.0;
1330  qreal yPos = rect.center().y() - height/2.0;
1331  newPiece.GetPatternInfo().SetPos(QPointF(xPos, yPos));
1332 
1333  newPiece.GetPatternPieceData().SetVisible(qApp->Settings()->showPieceLabels());
1334  newPiece.GetPatternPieceData().SetLabelWidth(QString::number(qApp->Settings()->getDefaultLabelWidth()));
1335  newPiece.GetPatternPieceData().SetLabelHeight(QString::number(qApp->Settings()->getDefaultLabelHeight()));
1336  QString filename = qApp->Settings()->getDefaultPieceTemplate();
1337  if (QFileInfo(filename).exists())
1338  {
1339  VLabelTemplate labelTemplate;
1340  labelTemplate.setXMLContent(VLabelTemplateConverter(filename).Convert());
1341  newPiece.GetPatternPieceData().SetLabelTemplate(labelTemplate.ReadLines());
1342  }
1343 
1344  width = newPiece.GetPatternPieceData().GetLabelWidth().toDouble();
1345  height = newPiece.GetPatternPieceData().GetLabelHeight().toDouble();
1346  xPos = rect.center().x() + (rect.width()/2.0 - width)/2.0;
1347  yPos = rect.center().y() - height/2.0;
1348  newPiece.GetPatternPieceData().SetPos(QPointF(xPos, yPos));
1349 
1350  newPiece.GetGrainlineGeometry().SetVisible(qApp->Settings()->getDefaultGrainlineVisibilty());
1351  newPiece.GetGrainlineGeometry().SetLength(QString::number(qApp->Settings()->getDefaultGrainlineLength()));
1352  qreal length = newPiece.GetGrainlineGeometry().GetLength().toDouble();
1353  xPos = rect.center().x();
1354  yPos = rect.center().y();
1355  newPiece.GetGrainlineGeometry().SetPos(QPointF(xPos, yPos + length/2.0));
1356 
1357  QString formulaSAWidth = piece1.getSeamAllowanceWidthFormula();
1358  newPiece.setSeamAllowanceWidthFormula(formulaSAWidth, piece1.GetSAWidth());
1359  newPiece.SetMx(piece1.GetMx());
1360  newPiece.SetMy(piece1.GetMy());
1361  newPiece.SetUnited(true);
1362  PatternPieceTool::Create(0, newPiece, formulaSAWidth, initData.scene, initData.doc, initData.data,
1363  initData.parse, Source::FromTool, blockName);
1364 
1365  auto removeUnionPiece = [initData](quint32 id)
1366  {
1367  PatternPieceTool *pieceTool = qobject_cast<PatternPieceTool*>(VAbstractPattern::getTool(id));
1368  SCASSERT(pieceTool != nullptr);
1369  bool ask = false;
1370  pieceTool->Remove(ask);
1371  // We do not call full parse, so will need more to do more cleaning than usually
1372  initData.doc->RemoveTool(id);
1373  initData.data->RemovePiece(id);
1374  };
1375 
1376  if (!initData.retainPieces && !piece1.isLocked() && !piece2.isLocked())
1377  {
1378  removeUnionPiece(initData.piece1_Id);
1379  removeUnionPiece(initData.piece2_Id);
1380  }
1381 }
1382 
1383 //---------------------------------------------------------------------------------------------------------------------
1384 void updateUnion(quint32 id, const UnionToolInitData &initData, qreal dx, qreal dy, quint32 pRotate,
1385  qreal angle)
1386 {
1387  UpdateUnitedNodes(id, initData, dx, dy, pRotate, angle);
1388  updateUnionCSA(id, initData, dx, dy, pRotate, angle, GetPiece2CSAPaths(initData.doc, id));
1389  updateUnionInternalPaths(id, initData, dx, dy, pRotate, angle, GetPiece2InternalPaths(initData.doc, id));
1390  updateUnionAnchors(id, initData, dx, dy, pRotate, angle, GetPiece2Anchors(initData.doc, id));
1391 }
1392 
1393 //---------------------------------------------------------------------------------------------------------------------
1394 void unitePieces(quint32 id, const UnionToolInitData &initData)
1395 {
1396  VPieceNode piece1_Pt1;
1397  qreal dx = 0;
1398  qreal dy = 0;
1399  qreal angle = 0;
1400 
1401  if (initData.typeCreation == Source::FromGui)
1402  {
1403  const VPiece piece1 = initData.data->GetPiece(initData.piece1_Id);
1404  const VPiece piece2 = initData.data->GetPiece(initData.piece2_Id);
1405  UnionInitParameters(initData, piece1.GetPath(), piece2.GetPath(), piece1_Pt1, dx, dy, angle);
1406  createUnion(id, initData, dx, dy, piece1_Pt1.GetId(), angle);
1407  }
1408  else
1409  {
1410  const VPiecePath piece1Path = GetPiece1MainPath(initData.doc, id);
1411  const VPiecePath piece2Path = GetPiece2MainPath(initData.doc, id);
1412  UnionInitParameters(initData, piece1Path, piece2Path, piece1_Pt1, dx, dy, angle);
1413  updateUnion(id, initData, dx, dy, piece1_Pt1.GetId(), angle);
1414  }
1415 }
1416 } // static functions
1417 
1418 //---------------------------------------------------------------------------------------------------------------------
1419 /**
1420  * @brief UnionTool costructor.
1421  * @param id object id in container.
1422  * @param initData global init data.
1423  * @param parent parent object.
1424  */
1425 UnionTool::UnionTool(quint32 id, const UnionToolInitData &initData,
1426  QObject *parent)
1427  : VAbstractTool(initData.doc, initData.data, id, parent)
1428  , piece1_Id(initData.piece1_Id)
1429  , piece2_Id(initData.piece2_Id)
1430  , piece1_Index(initData.piece1_Index)
1431  , piece2_Index(initData.piece2_Index)
1432 {
1433  _referens = 0;
1434  ToolCreation(initData.typeCreation);
1435 }
1436 
1437 //---------------------------------------------------------------------------------------------------------------------
1438 QString UnionTool::getTagName() const
1439 {
1441 }
1442 
1443 //---------------------------------------------------------------------------------------------------------------------
1445 {
1446  Q_UNUSED(show)
1447 }
1448 
1449 //---------------------------------------------------------------------------------------------------------------------
1451 {
1453  if (_referens == 1)
1454  {
1455  const QVector<quint32> objects = GetReferenceObjects();
1456  for(int i = 0; i < objects.size(); ++i)
1457  {
1458  doc->IncrementReferens(objects.at(i));
1459  }
1460 
1461  QDomElement domElement = doc->elementById(m_id, getTagName());
1462  if (domElement.isElement())
1463  {
1465  }
1466  }
1467 }
1468 
1469 //---------------------------------------------------------------------------------------------------------------------
1471 {
1473  if (_referens == 0)
1474  {
1475  const QVector<quint32> objects = GetReferenceObjects();
1476  for(int i = 0; i < objects.size(); ++i)
1477  {
1478  doc->DecrementReferens(objects.at(i));
1479  }
1480 
1481  QDomElement domElement = doc->elementById(m_id, getTagName());
1482  if (domElement.isElement())
1483  {
1485  }
1486  }
1487 }
1488 
1489 //---------------------------------------------------------------------------------------------------------------------
1490 void UnionTool::GroupVisibility(quint32 object, bool visible)
1491 {
1492  Q_UNUSED(object)
1493  Q_UNUSED(visible)
1494 }
1495 
1496 //---------------------------------------------------------------------------------------------------------------------
1497 /**
1498  * @brief Create help create tool from GUI.
1499  * @param dialog dialog.
1500  * @param doc dom document container.
1501  * @param data container with variables.
1502  */
1504  VAbstractPattern *doc, VContainer *data)
1505 {
1506  SCASSERT(not dialog.isNull())
1507  QSharedPointer<UnionDialog> dialogTool = dialog.objectCast<UnionDialog>();
1508  SCASSERT(not dialogTool.isNull())
1509 
1510  UnionToolInitData initData;
1511  initData.piece1_Id = dialogTool->getPiece1Id();
1512  initData.piece2_Id = dialogTool->getPiece2Id();
1513  initData.piece1_Index = static_cast<quint32>(dialogTool->getPiece1Index());
1514  initData.piece2_Index = static_cast<quint32>(dialogTool->getPiece2Index());
1515  initData.scene = scene;
1516  initData.doc = doc;
1517  initData.data = data;
1518  initData.parse = Document::FullParse;
1519  initData.typeCreation = Source::FromGui;
1520  initData.retainPieces = dialogTool->retainPieces();
1521 
1522  qApp->getUndoStack()->beginMacro(tr("union pieces"));
1523  UnionTool* tool = Create(0, initData);
1524  qApp->getUndoStack()->endMacro();
1525  return tool;
1526 }
1527 
1528 //---------------------------------------------------------------------------------------------------------------------
1529 /**
1530  * @brief Create help create tool.
1531  * @param _id tool id, 0 if tool doesn't exist yet.
1532  * @param initData contains all init data.
1533  */
1534 UnionTool* UnionTool::Create(const quint32 _id, const UnionToolInitData &initData)
1535 {
1536  UnionTool *tool = nullptr;
1537  quint32 id = _id;
1538  if (initData.typeCreation == Source::FromGui)
1539  {
1540  id = VContainer::getNextId();
1541  }
1542  else
1543  {
1544  if (initData.parse != Document::FullParse)
1545  {
1546  initData.doc->UpdateToolData(id, initData.data);
1547  }
1548  }
1549 
1550  //First add tool to file
1551  if (initData.parse == Document::FullParse)
1552  {
1553  VAbstractTool::AddRecord(id, Tool::Union, initData.doc);
1554  //Scene doesn't show this tool, so doc will destroy this object.
1555  tool = new UnionTool(id, initData);
1556  VAbstractPattern::AddTool(id, tool);
1557  // Unfortunatelly doc will destroy all objects only in the end, but we should delete them before each FullParse
1558  initData.doc->AddToolOnRemove(tool);
1559  }
1560  unitePieces(id, initData);
1561  return tool;
1562 }
1563 
1564 //---------------------------------------------------------------------------------------------------------------------
1565 /**
1566  * @brief AddToFile add tag with Information about tool into file.
1567  */
1569 {
1570  QDomElement domElement = doc->createElement(getTagName());
1571 
1572  doc->SetAttribute(domElement, VDomDocument::AttrId, m_id);
1573  doc->SetAttribute(domElement, AttrType, ToolType);
1574  doc->SetAttribute(domElement, AttrIndexD1, piece1_Index);
1575  doc->SetAttribute(domElement, AttrIndexD2, piece2_Index);
1576 
1577  addPiece(domElement, data.GetPiece(piece1_Id));
1578  addPiece(domElement, data.GetPiece(piece2_Id));
1579 
1580  AddToModeling(domElement);
1581 }
1582 
1583 //---------------------------------------------------------------------------------------------------------------------
1584 /**
1585  * @brief addPiece add piece to xml file.
1586  * @param domElement tag in xml tree.
1587  * @param piece piece.
1588  */
1589 void UnionTool::addPiece(QDomElement &domElement, const VPiece &piece) const
1590 {
1591  QDomElement element = doc->createElement(TagUnionPiece);
1592 
1593  // nodes
1594  PatternPieceTool::AddNodes(doc, element, piece);
1595  //custom seam allowance
1598  PatternPieceTool::addAnchors(doc, element, piece.getAnchors());
1599 
1600  domElement.appendChild(element);
1601 }
1602 
1603 //---------------------------------------------------------------------------------------------------------------------
1604 /**
1605  * @brief AddToModeling add tool to xml tree.
1606  * @param domElement tag in xml tree.
1607  */
1608 void UnionTool::AddToModeling(const QDomElement &domElement)
1609 {
1610  const QString blockName = getBlockName(doc, piece1_Id, piece2_Id);
1611  SCASSERT(not blockName.isEmpty())
1612 
1613  QDomElement modeling = doc->getDraftBlockElement(blockName).firstChildElement(VAbstractPattern::TagModeling);
1614  if (not modeling.isNull())
1615  {
1616  modeling.appendChild(domElement);
1617  }
1618  else
1619  {
1620  qCCritical(vToolUnion, "Can't find tag %s.", qUtf8Printable(VAbstractPattern::TagModeling));
1621  return;
1622  }
1623 }
1624 
1625 //---------------------------------------------------------------------------------------------------------------------
1627 {
1628  QVector<quint32> list;
1629  const QDomElement tool = doc->elementById(m_id, getTagName());
1630  if (tool.isNull())
1631  {
1632  return list;
1633  }
1634 
1635  const QStringList parts = QStringList() << VAbstractPattern::TagNodes /*0*/
1636  << PatternPieceTool::TagCSA /*1*/
1639 
1640  const QDomNodeList nodesList = tool.childNodes();
1641  for (qint32 i = 0; i < nodesList.size(); ++i)
1642  {
1643  const QDomElement element = nodesList.at(i).toElement();
1644  if (not element.isNull() && element.tagName() == UnionTool::TagUnionPiece)
1645  {
1646  const QDomNodeList pieceList = element.childNodes();
1647  for (qint32 j = 0; j < pieceList.size(); ++j)
1648  {
1649  const QDomElement element = pieceList.at(j).toElement();
1650  if (not element.isNull())
1651  {
1652  switch (parts.indexOf(element.tagName()))
1653  {
1654  case 0://VAbstractPattern::TagNodes
1655  list += ReferenceObjects(element, TagNode, AttrIdObject);
1656  break;
1657  case 1://PatternPieceTool::TagCSA
1658  case 2://PatternPieceTool::TagIPaths
1661  break;
1662  case 3://PatternPieceTool::TagAnchors
1663  {
1664  const QDomNodeList children = element.childNodes();
1665  for (qint32 i = 0; i < children.size(); ++i)
1666  {
1667  const QDomElement record = children.at(i).toElement();
1668  if (not record.isNull() && record.tagName() == PatternPieceTool::TagRecord)
1669  {
1670  list.append(record.text().toUInt());
1671  }
1672  }
1673  break;
1674  }
1675  default:
1676  break;
1677  }
1678  }
1679  }
1680  }
1681  }
1682  return list;
1683 }
1684 
1685 //---------------------------------------------------------------------------------------------------------------------
1686 QVector<quint32> UnionTool::ReferenceObjects(const QDomElement &root, const QString &tag,
1687  const QString &attribute) const
1688 {
1689  QVector<quint32> objects;
1690 
1691  const QDomNodeList list = root.childNodes();
1692  for (qint32 i = 0; i < list.size(); ++i)
1693  {
1694  const QDomElement element = list.at(i).toElement();
1695  if (not element.isNull() && element.tagName() == tag)
1696  {
1697  const quint32 id = doc->GetParametrUInt(element, attribute, NULL_ID_STR);
1698  if (id > NULL_ID)
1699  {
1700  objects.append(id);
1701  }
1702  }
1703  }
1704 
1705  return objects;
1706 }
static AnchorPointTool * Create(QSharedPointer< DialogTool > dialog, VAbstractPattern *doc, VContainer *data)
static const QString TagCSA
static PatternPieceTool * Create(QSharedPointer< DialogTool > dialog, VMainGraphicsScene *scene, VAbstractPattern *doc, VContainer *data)
static void AddCSARecords(VAbstractPattern *doc, QDomElement &domElement, const QVector< CustomSARecord > &records)
static void AddInternalPaths(VAbstractPattern *doc, QDomElement &domElement, const QVector< quint32 > &paths)
static const QString TagRecord
static void addAnchors(VAbstractPattern *doc, QDomElement &domElement, const QVector< quint32 > &anchors)
static const QString TagAnchors
static const QString TagIPaths
The UnionDialog class dialog for Union Tool.
Definition: union_dialog.h:75
The UnionTool class tool union details.
Definition: union_tool.h:105
static const QString AttrIndexD2
Definition: union_tool.h:118
QVector< quint32 > GetReferenceObjects() const
virtual void incrementReferens() Q_DECL_OVERRIDE
incrementReferens increment referens.
virtual void decrementReferens() Q_DECL_OVERRIDE
decrementReferens decrement referens.
virtual void ShowVisualization(bool show) Q_DECL_OVERRIDE
quint32 piece2_Index
piece1_Index index edge in first detail.
Definition: union_tool.h:148
static const QString TagNode
Definition: union_tool.h:114
quint32 piece1_Id
Definition: union_tool.h:145
virtual QString getTagName() const Q_DECL_OVERRIDE
void AddToModeling(const QDomElement &domElement)
AddToModeling add tool to xml tree.
static const QString NodeTypeContour
Definition: union_tool.h:121
virtual void AddToFile() Q_DECL_OVERRIDE
AddToFile add tag with Information about tool into file.
static const QString TagChild
Definition: union_tool.h:116
void addPiece(QDomElement &domElement, const VPiece &d) const
addPiece add piece to xml file.
static const QString TagUnionPiece
Definition: union_tool.h:113
virtual void GroupVisibility(quint32 object, bool visible) Q_DECL_OVERRIDE
static const QString ToolType
Definition: union_tool.h:112
static const QString TagChildren
Definition: union_tool.h:115
QVector< quint32 > ReferenceObjects(const QDomElement &root, const QString &tag, const QString &attribute) const
UnionTool(quint32 id, const UnionToolInitData &initData, QObject *parent=nullptr)
piece2_Index index edge in second detail.
static UnionTool * Create(QSharedPointer< DialogTool > dialog, VMainGraphicsScene *scene, VAbstractPattern *doc, VContainer *data)
Create help create tool from GUI.
static const QString NodeTypeModeling
Definition: union_tool.h:122
static const QString AttrIdObject
Definition: union_tool.h:119
quint32 piece1_Index
d2 second detail id.
Definition: union_tool.h:147
quint32 piece2_Id
d1 first detail id.
Definition: union_tool.h:146
static const QString AttrIndexD1
Definition: union_tool.h:117
static const QString AttrNodeType
Definition: union_tool.h:120
void SetPos(const QPointF &ptPos)
void AddToolOnRemove(VDataTool *tool)
static QVector< quint32 > ParsePieceAnchors(const QDomElement &domElement)
virtual void UpdateToolData(const quint32 &id, VContainer *data)=0
static const QString TagModeling
virtual void IncrementReferens(quint32 id) const =0
QDomElement getDraftBlockElement(const QString &name)
static void AddTool(quint32 id, VDataTool *tool)
AddTool add tool to list tools.
static const QString TagTools
static const QString AttrPath
static VDataTool * getTool(quint32 id)
getTool return tool from tool list.
static void RemoveTool(quint32 id)
static const QString TagDraftBlock
static QVector< CustomSARecord > ParsePieceCSARecords(const QDomElement &domElement)
static VPiecePath ParsePieceNodes(const QDomElement &domElement)
static const QString TagPiece
static const QString AttrName
virtual void DecrementReferens(quint32 id) const =0
static const QString TagNodes
static QVector< quint32 > ParsePieceInternalPaths(const QDomElement &domElement)
void SetMx(qreal value)
qreal GetSAWidth() const
qreal GetMx() const
void SetName(const QString &value)
void SetSeamAllowance(bool value)
qreal GetMy() const
void SetMy(qreal value)
The VAbstractTool abstract class for all tools.
Definition: vabstracttool.h:80
static void AddNodes(VAbstractPattern *doc, QDomElement &domElement, const VPiecePath &path)
static const QString AttrInUse
Definition: vabstracttool.h:89
VAbstractPattern * doc
doc dom document container
virtual void ToolCreation(const Source &typeCreation)
static void AddRecord(const quint32 id, const Tool &toolType, VAbstractPattern *doc)
AddRecord add record about tool in history.
const quint32 m_id
id object id.
VArc class for anticlockwise arc.
Definition: varc.h:74
The VContainer class container of all variables.
Definition: vcontainer.h:141
void RemovePiece(quint32 id)
Definition: vcontainer.cpp:487
static quint32 getNextId()
getNextId generate next unique id
Definition: vcontainer.cpp:251
void UpdatePiecePath(quint32 id, const VPiecePath &path)
Definition: vcontainer.cpp:518
const QSharedPointer< T > GeometricObject(const quint32 &id) const
Definition: vcontainer.h:266
VPiecePath GetPiecePath(quint32 id) const
Definition: vcontainer.cpp:198
quint32 AddGObject(VGObject *obj)
AddGObject add new GObject to container.
Definition: vcontainer.cpp:216
quint32 AddPiecePath(const VPiecePath &path)
Definition: vcontainer.cpp:233
void UpdateGObject(quint32 id, T *obj)
UpdateGObject update GObject by id.
Definition: vcontainer.h:374
VPiece GetPiece(quint32 id) const
Definition: vcontainer.cpp:185
virtual void decrementReferens()
decrementReferens decrement referens.
Definition: vdatatool.cpp:74
quint32 _referens
_referens keep count tools what use this tool. If value more than 1 you can't delete tool.
Definition: vdatatool.h:87
virtual void incrementReferens()
incrementReferens increment referens.
Definition: vdatatool.h:126
VContainer data
data container with data
Definition: vdatatool.h:84
QDomElement elementById(quint32 id, const QString &tagName=QString())
static quint32 GetParametrUInt(const QDomElement &domElement, const QString &name, const QString &defValue)
Returns the long long value of the given attribute. RENAME: GetParameterLongLong?
static void SetParametrUsage(QDomElement &domElement, const QString &name, const NodeUsage &value)
void SetAttribute(QDomElement &domElement, const QString &name, const T &value) const
SetAttribute set attribute in pattern file. Replace "," by ".".
Definition: vdomdocument.h:185
static const QString AttrId
Definition: vdomdocument.h:108
virtual void setXMLContent(const QString &fileName)
The VException class parent for all exception. Could be use for abstract exception.
Definition: vexception.h:66
void setMode(const Draw &value)
setMode set mode creation.
Definition: vgobject.cpp:178
void SetLength(const QString &qsLen)
QString GetLength() const
QVector< VLabelTemplateLine > ReadLines() const
The VMainGraphicsScene class main scene.
static void Create(VAbstractPattern *doc, VContainer *data, quint32 id, quint32 idArc, const Document &parse, const Source &typeCreation, const QString &blockName=QString(), const quint32 &idTool=0)
Create help create tool.
Definition: vnodearc.cpp:96
static void Create(VAbstractPattern *doc, VContainer *data, quint32 id, quint32 idArc, const Document &parse, const Source &typeCreation, const QString &blockName=QString(), const quint32 &idTool=NULL_ID)
static void Create(VAbstractPattern *doc, VContainer *data, VMainGraphicsScene *scene, quint32 id, quint32 idPoint, const Document &parse, const Source &typeCreation, const QString &blockName=QString(), const quint32 &idTool=0)
Create help create tool.
Definition: vnodepoint.cpp:134
static void Create(VAbstractPattern *doc, VContainer *data, quint32 id, quint32 idSpline, const Document &parse, const Source &typeCreation, const QString &blockName=QString(), const quint32 &idTool=0)
Create help create tool.
static VNodeSpline * Create(VAbstractPattern *doc, VContainer *data, quint32 id, quint32 idSpline, const Document &parse, const Source &typeCreation, const QString &blockName=QString(), const quint32 &idTool=0)
Create help create tool.
Definition: vnodespline.cpp:97
static Q_DECL_CONSTEXPR const int PatternMinVer
void SetLabelHeight(const QString &dLabelH)
QString GetLabelWidth() const
void SetLabelWidth(const QString &dLabelW)
QString GetLabelHeight() const
void SetLabelTemplate(const QVector< VLabelTemplateLine > &lines)
Tool GetTypeTool() const
Definition: vpiecenode.cpp:161
quint32 GetId() const
Definition: vpiecenode.cpp:149
bool GetReverse() const
Definition: vpiecenode.cpp:173
void SetId(quint32 id)
Definition: vpiecenode.cpp:155
QVector< QPointF > PathPoints(const VContainer *data) const
Definition: vpiecepath.cpp:287
qint32 CountNodes() const
Definition: vpiecepath.cpp:209
void NodeOnEdge(quint32 index, VPieceNode &p1, VPieceNode &p2) const
NodeOnEdge return nodes located on edge with index.
Definition: vpiecepath.cpp:519
void Clear()
Definition: vpiecepath.cpp:203
void Append(const VPieceNode &node)
Definition: vpiecepath.cpp:197
VPiecePath RemoveEdge(quint32 index) const
RemoveEdge return path without edge with index.
Definition: vpiecepath.cpp:652
const VPieceNode & at(int indx) const
Definition: vpiecepath.cpp:221
int indexOfNode(quint32 id) const
Definition: vpiecepath.cpp:507
Definition: vpiece.h:88
VPieceLabelData & GetPatternPieceData()
Returns full access to the pattern piece data object.
Definition: vpiece.cpp:532
QVector< CustomSARecord > GetCustomSARecords() const
Definition: vpiece.cpp:444
QString getSeamAllowanceWidthFormula() const
Definition: vpiece.cpp:412
QVector< quint32 > GetInternalPaths() const
Definition: vpiece.cpp:426
void SetPath(const VPiecePath &path)
Definition: vpiece.cpp:168
QVector< quint32 > getAnchors() const
Definition: vpiece.cpp:462
void setSeamAllowanceWidthFormula(const QString &formula, qreal value)
Definition: vpiece.cpp:418
void SetUnited(bool united)
Definition: vpiece.cpp:406
VGrainlineData & GetGrainlineGeometry()
VDetail::GetGrainlineGeometry full access to the grainline geometry object.
Definition: vpiece.cpp:578
VPatternLabelData & GetPatternInfo()
Returns full access to the pattern info geometry object.
Definition: vpiece.cpp:558
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
void setX(const qreal &value)
setX set x coordinate
Definition: vpointf.cpp:233
void setY(const qreal &value)
setY set y coordinate
Definition: vpointf.cpp:253
qreal y() const
y return y coordinate
Definition: vpointf.cpp:243
qreal x() const
x return x coordinate
Definition: vpointf.cpp:223
The VSplinePath class keep information about splinePath.
Definition: vsplinepath.h:72
The VSplinePoint class keep information about point in spline path. Each point have two angles and tw...
Definition: vsplinepoint.h:108
VSpline class that implements the spline.
Definition: vspline.h:75
virtual qreal GetC2Length() const Q_DECL_OVERRIDE
Definition: vspline.cpp:385
virtual VPointF GetP4() const Q_DECL_OVERRIDE
GetP4 return last spline point.
Definition: vspline.cpp:321
QString GetC1LengthFormula() const
Definition: vspline.cpp:391
virtual qreal GetStartAngle() const Q_DECL_OVERRIDE
GetAngle1 return first angle control line.
Definition: vspline.cpp:337
virtual VPointF GetP1() const Q_DECL_OVERRIDE
GetP1 return first spline point.
Definition: vspline.cpp:281
virtual VPointF GetP2() const Q_DECL_OVERRIDE
GetP2 return first control point.
Definition: vspline.cpp:297
QString GetStartAngleFormula() const
Definition: vspline.cpp:353
QString GetEndAngleFormula() const
Definition: vspline.cpp:359
virtual qreal GetC1Length() const Q_DECL_OVERRIDE
Definition: vspline.cpp:379
virtual VPointF GetP3() const Q_DECL_OVERRIDE
GetP3 return second control point.
Definition: vspline.cpp:309
QString GetC2LengthFormula() const
Definition: vspline.cpp:397
virtual qreal GetEndAngle() const Q_DECL_OVERRIDE
GetAngle2 return second angle control line.
Definition: vspline.cpp:347
static VToolInternalPath * Create(QSharedPointer< DialogTool > dialog, VMainGraphicsScene *scene, VAbstractPattern *doc, VContainer *data)
#define SCASSERT(cond)
Definition: def.h:317
@ NodeSplinePath
@ NodeSpline
@ NodeElArc
@ NodeArc
@ NodePoint
const QString AttrType
Definition: ifcdef.cpp:73
#define NULL_ID
Definition: ifcdef.h:76
#define NULL_ID_STR
Definition: ifcdef.h:77
void SaveInternalPathsChildren(VAbstractPattern *doc, quint32 id, const QVector< quint32 > &children)
Definition: union_tool.cpp:737
void updateUnion(quint32 id, const UnionToolInitData &initData, qreal dx, qreal dy, quint32 pRotate, qreal angle)
void UpdateNodeSpline(VContainer *data, const VPieceNode &node, QVector< quint32 > &children, qreal dx, qreal dy, quint32 pRotate, qreal angle)
Definition: union_tool.cpp:891
void UpdateNodeArc(VContainer *data, const VPieceNode &node, QVector< quint32 > &children, qreal dx, qreal dy, quint32 pRotate, qreal angle)
Definition: union_tool.cpp:835
VPiecePath GetPiece2MainPath(VAbstractPattern *doc, quint32 id)
Definition: union_tool.cpp:166
void unitePieces(quint32 id, const UnionToolInitData &initData)
QVector< CustomSARecord > GetPiece2CSAPaths(VAbstractPattern *doc, quint32 id)
Definition: union_tool.cpp:172
void createCSAUnion(VPiece &newPiece, const VPiece &d, QVector< quint32 > &children, quint32 id, const QString &blockName, const UnionToolInitData &initData, qreal dx, qreal dy, quint32 pRotate, qreal angle)
void SaveCSAChildren(VAbstractPattern *doc, quint32 id, const QVector< quint32 > &children)
Definition: union_tool.cpp:731
void UpdatePathNode(VContainer *data, const VPieceNode &node, QVector< quint32 > &children, qreal dx=0, qreal dy=0, quint32 pRotate=NULL_ID, qreal angle=0)
UpdateNodes update nodes of union.
Definition: union_tool.cpp:986
void createUnionInternalPaths(VPiece &newPiece, const VPiece &d, QVector< quint32 > &children, quint32 id, const QString &blockName, const UnionToolInitData &initData, qreal dx, qreal dy, quint32 pRotate, qreal angle)
quint32 AddAnchorPoint(quint32 id, const UnionToolInitData &initData, quint32 idTool, QVector< quint32 > &children, const QString &blockName, qreal dx, qreal dy, quint32 pRotate, qreal angle)
Definition: union_tool.cpp:418
QVector< quint32 > GetInternalPathsChildren(VAbstractPattern *doc, quint32 id)
Definition: union_tool.cpp:795
quint32 AddNodePoint(const VPieceNode &node, const UnionToolInitData &initData, quint32 idTool, QVector< quint32 > &children, const QString &blockName, qreal dx, qreal dy, quint32 pRotate, qreal angle)
Definition: union_tool.cpp:393
void updateUnionAnchors(quint32 id, const UnionToolInitData &initData, qreal dx, qreal dy, quint32 pRotate, qreal angle, const QVector< quint32 > &records)
VPiecePath GetPiecePath(int piece, VAbstractPattern *doc, quint32 id)
Definition: union_tool.cpp:129
QString getBlockName(VAbstractPattern *doc, quint32 piece1_Id, quint32 piece2_Id)
Definition: union_tool.cpp:265
QVector< quint32 > GetCSAChildren(VAbstractPattern *doc, quint32 id)
Definition: union_tool.cpp:789
void createUnion(quint32 id, const UnionToolInitData &initData, qreal dx, qreal dy, quint32 pRotate, qreal angle)
void AddNodeToNewPath(const UnionToolInitData &initData, VPiecePath &newPath, VPieceNode node, quint32 idTool, QVector< quint32 > &children, const QString &blockName, qreal dx=0, qreal dy=0, quint32 pRotate=NULL_ID, qreal angle=0)
AddNodeToNewPath create union adding one node at a time.
Definition: union_tool.cpp:634
VPiecePath GetPiece1MainPath(VAbstractPattern *doc, quint32 id)
Definition: union_tool.cpp:160
QVector< quint32 > GetChildren(VAbstractPattern *doc, quint32 id, const QString &tagName)
Definition: union_tool.cpp:749
void createUnionPaths(const UnionToolInitData &initData, qreal dx, qreal dy, quint32 pRotate, qreal angle, const QVector< quint32 > &records, QVector< quint32 > children)
void UnionInitParameters(const UnionToolInitData &initData, const VPiecePath &piece1Path, const VPiecePath &piece2Path, VPieceNode &piece1_Pt1, qreal &dx, qreal &dy, qreal &angle)
Definition: union_tool.cpp:362
void UpdateUnitedNodes(quint32 id, const UnionToolInitData &initData, qreal dx, qreal dy, quint32 pRotate, qreal angle)
quint32 AddNodeArc(const VPieceNode &node, const UnionToolInitData &initData, quint32 idTool, QVector< quint32 > &children, const QString &blockName, qreal dx, qreal dy, quint32 pRotate, qreal angle)
Definition: union_tool.cpp:442
QVector< quint32 > GetPiece2Anchors(VAbstractPattern *doc, quint32 id)
Definition: union_tool.cpp:234
void SaveNodesChildren(VAbstractPattern *doc, quint32 id, const QVector< quint32 > &children)
Definition: union_tool.cpp:725
void PointsOnEdge(const VPiecePath &path, quint32 index, VPointF &p1, VPointF &p2, VContainer *data)
Definition: union_tool.cpp:352
void updateUnionCSA(quint32 id, const UnionToolInitData &initData, qreal dx, qreal dy, quint32 pRotate, qreal angle, const QVector< CustomSARecord > &records)
void createUnionAnchors(VPiece &newPiece, const VPiece &d, QVector< quint32 > &children, quint32 idTool, const QString &blockName, const UnionToolInitData &initData, qreal dx, qreal dy, quint32 pRotate, qreal angle)
void UpdateNodeElArc(VContainer *data, const VPieceNode &node, QVector< quint32 > &children, qreal dx, qreal dy, quint32 pRotate, qreal angle)
Definition: union_tool.cpp:862
QDomElement GetTagChildren(VAbstractPattern *doc, quint32 id)
Definition: union_tool.cpp:688
QVector< quint32 > getAnchorChildren(VAbstractPattern *doc, quint32 id)
Definition: union_tool.cpp:801
void CreateUnitedInternalPaths(VPiece &newPiece, const VPiece &piece1, const VPiece &piece2, quint32 id, const QString &blockName, const UnionToolInitData &initData, qreal dx, qreal dy, quint32 pRotate, qreal angle)
QVector< quint32 > GetPiece2InternalPaths(VAbstractPattern *doc, quint32 id)
Definition: union_tool.cpp:203
quint32 TakeNextId(QVector< quint32 > &children)
Definition: union_tool.cpp:807
quint32 AddNodeSplinePath(const VPieceNode &node, const UnionToolInitData &initData, quint32 idTool, QVector< quint32 > &children, const QString &blockName, qreal dx, qreal dy, quint32 pRotate, qreal angle)
Definition: union_tool.cpp:563
void UpdateNodePoint(VContainer *data, const VPieceNode &node, QVector< quint32 > &children, qreal dx, qreal dy, quint32 pRotate, qreal angle)
Definition: union_tool.cpp:822
void CreateUnitedNodes(VPiece &newPiece, const VPiece &piece1, const VPiece &piece2, quint32 id, const QString &blockName, const UnionToolInitData &initData, qreal dx, qreal dy, quint32 pRotate, qreal angle)
QVector< quint32 > GetNodesChildren(VAbstractPattern *doc, quint32 id)
Definition: union_tool.cpp:783
void FindIndexJ(qint32 piece2Points, const VPiecePath &piece2Path, quint32 piece2_Index, qint32 &j)
Definition: union_tool.cpp:666
quint32 AddNodeSpline(const VPieceNode &node, const UnionToolInitData &initData, quint32 idTool, QVector< quint32 > &children, const QString &blockName, qreal dx, qreal dy, quint32 pRotate, qreal angle)
Definition: union_tool.cpp:528
quint32 AddNodeElArc(const VPieceNode &node, const UnionToolInitData &initData, quint32 idTool, QVector< quint32 > &children, const QString &blockName, qreal dx, qreal dy, quint32 pRotate, qreal angle)
Definition: union_tool.cpp:484
void CreateUnitedCSA(VPiece &newPiece, const VPiece &piece1, const VPiece &piece2, quint32 id, const QString &blockName, const UnionToolInitData &initData, qreal dx, qreal dy, quint32 pRotate, qreal angle)
void createUnitedAnchors(VPiece &newPiece, const VPiece &piece1, const VPiece &piece2, quint32 id, const QString &blockName, const UnionToolInitData &initData, qreal dx, qreal dy, quint32 pRotate, qreal angle)
void updateUnionInternalPaths(quint32 id, const UnionToolInitData &initData, qreal dx, qreal dy, quint32 pRotate, qreal angle, const QVector< quint32 > &records)
void SaveChildren(VAbstractPattern *doc, quint32 id, QDomElement section, const QVector< quint32 > &children)
Definition: union_tool.cpp:709
void SaveAnchorsChildren(VAbstractPattern *doc, quint32 id, const QVector< quint32 > &children)
Definition: union_tool.cpp:743
void BiasRotatePoint(VPointF *point, qreal dx, qreal dy, const QPointF &pRotate, qreal angle)
BiasRotatePoint bias and rotate point.
Definition: union_tool.cpp:341
void UpdateNodeSplinePath(VContainer *data, const VPieceNode &node, QVector< quint32 > &children, qreal dx, qreal dy, quint32 pRotate, qreal angle)
Definition: union_tool.cpp:918
The CustomSA struct contains record about custom seam allowanse (SA).
Definition: def.h:510
quint32 path
Definition: def.h:520
Source typeCreation
Definition: union_tool.h:97
VAbstractPattern * doc
Definition: union_tool.h:94
Document parse
Definition: union_tool.h:96
VContainer * data
Definition: union_tool.h:95
quint32 piece1_Index
Definition: union_tool.h:91
quint32 piece2_Id
Definition: union_tool.h:90
VMainGraphicsScene * scene
Definition: union_tool.h:93
quint32 piece1_Id
Definition: union_tool.h:89
quint32 piece2_Index
Definition: union_tool.h:92
#define CONVERTER_VERSION_CHECK(major, minor, patch)
#define qApp
Definition: vapplication.h:67
@ Modeling