1 /************************************************************************
2  **
3  **  @file
4  **  @author Roman Telezhynskyi <dismine(at)gmail.com>
5  **  @date   3 11, 2016
6  **
7  **  @brief
8  **  @copyright
9  **  This source code is part of the Valentina project, a pattern making
10  **  program, whose allow create and modeling patterns of clothing.
11  **  Copyright (C) 2016 Valentina project
12  **  <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
13  **
14  **  Valentina is free software: you can redistribute it and/or modify
15  **  it under the terms of the GNU General Public License as published by
16  **  the Free Software Foundation, either version 3 of the License, or
17  **  (at your option) any later version.
18  **
19  **  Valentina is distributed in the hope that it will be useful,
20  **  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  **  GNU General Public License for more details.
23  **
24  **  You should have received a copy of the GNU General Public License
25  **  along with Valentina.  If not, see <http://www.gnu.org/licenses/>.
26  **
27  *************************************************************************/
28 
29 #include "vpiecenode.h"
30 #include "vpiecenode_p.h"
31 #include "vcontainer.h"
32 #include "calculator.h"
33 #include "vformula.h"
34 #include "../vmisc/vabstractvalapplication.h"
35 
36 #include <QDataStream>
37 #include <QtNumeric>
38 
39 const quint32 VPieceNodeData::streamHeader = 0x2198CBC8; // CRC-32Q string "VPieceNodeData"
40 const quint16 VPieceNodeData::classVersion = 1;
41 
42 //---------------------------------------------------------------------------------------------------------------------
VPieceNode()43 VPieceNode::VPieceNode()
44     : d(new VPieceNodeData)
45 {}
46 
47 //---------------------------------------------------------------------------------------------------------------------
VPieceNode(quint32 id,Tool typeTool,bool reverse)48 VPieceNode::VPieceNode(quint32 id, Tool typeTool, bool reverse)
49     : d(new VPieceNodeData(id, typeTool, reverse))
50 {}
51 
52 //---------------------------------------------------------------------------------------------------------------------
VPieceNode(const VPieceNode & node)53 VPieceNode::VPieceNode(const VPieceNode &node)
54     : d (node.d)
55 {}
56 
57 //---------------------------------------------------------------------------------------------------------------------
operator =(const VPieceNode & node)58 VPieceNode &VPieceNode::operator=(const VPieceNode &node)
59 {
60     if ( &node == this )
61     {
62         return *this;
63     }
64     d = node.d;
65     return *this;
66 }
67 
68 #ifdef Q_COMPILER_RVALUE_REFS
69 //---------------------------------------------------------------------------------------------------------------------
VPieceNode(const VPieceNode && node)70 VPieceNode::VPieceNode(const VPieceNode &&node) Q_DECL_NOTHROW
71     : d (node.d)
72 {}
73 
74 //---------------------------------------------------------------------------------------------------------------------
operator =(VPieceNode && node)75 VPieceNode &VPieceNode::operator=(VPieceNode &&node) Q_DECL_NOTHROW
76 {
77     std::swap(d, node.d);
78     return *this;
79 }
80 #endif
81 
82 //---------------------------------------------------------------------------------------------------------------------
~VPieceNode()83 VPieceNode::~VPieceNode()
84 {}
85 
86 // Friend functions
87 //---------------------------------------------------------------------------------------------------------------------
operator <<(QDataStream & out,const VPieceNode & p)88 QDataStream &operator<<(QDataStream &out, const VPieceNode &p)
89 {
90     out << *p.d;
91     return out;
92 }
93 
94 //---------------------------------------------------------------------------------------------------------------------
operator >>(QDataStream & in,VPieceNode & p)95 QDataStream &operator>>(QDataStream &in, VPieceNode &p)
96 {
97     in >> *p.d;
98     return in;
99 }
100 
101 //---------------------------------------------------------------------------------------------------------------------
GetId() const102 quint32 VPieceNode::GetId() const
103 {
104     return d->m_id;
105 }
106 
107 //---------------------------------------------------------------------------------------------------------------------
SetId(quint32 id)108 void VPieceNode::SetId(quint32 id)
109 {
110     d->m_id = id;
111 }
112 
113 //---------------------------------------------------------------------------------------------------------------------
GetTypeTool() const114 Tool VPieceNode::GetTypeTool() const
115 {
116     return d->m_typeTool;
117 }
118 
119 //---------------------------------------------------------------------------------------------------------------------
SetTypeTool(Tool value)120 void VPieceNode::SetTypeTool(Tool value)
121 {
122     d->m_typeTool = value;
123 }
124 
125 //---------------------------------------------------------------------------------------------------------------------
GetReverse() const126 bool VPieceNode::GetReverse() const
127 {
128     return d->m_reverse;
129 }
130 
131 //---------------------------------------------------------------------------------------------------------------------
SetReverse(bool reverse)132 void VPieceNode::SetReverse(bool reverse)
133 {
134     if (d->m_typeTool != Tool::NodePoint)
135     {
136         d->m_reverse = reverse;
137     }
138 }
139 
140 //---------------------------------------------------------------------------------------------------------------------
GetSABefore(const VContainer * data) const141 qreal VPieceNode::GetSABefore(const VContainer *data) const
142 {
143     if (d->m_formulaWidthBefore == currentSeamAllowance)
144     {
145         return -1;
146     }
147 
148     VFormula formula(d->m_formulaWidthBefore, data);
149     formula.setCheckZero(false);
150     formula.Eval();
151 
152     if (formula.error())
153     {
154         QString nodeName;
155         try
156         {
157             nodeName = data->GetGObject(d->m_id)->name();
158         }
159         catch (const VExceptionBadId &)
160         {}
161 
162         const QString errorMsg = QObject::tr("Cannot calculate seam allowance before for point '%1'. Reason: %2.")
163                 .arg(nodeName, formula.Reason());
164         VAbstractApplication::VApp()->IsPedantic() ? throw VException(errorMsg) :
165                                               qWarning() << VAbstractValApplication::warningMessageSignature + errorMsg;
166         return -1;
167     }
168     return formula.getDoubleValue();
169 }
170 
171 //---------------------------------------------------------------------------------------------------------------------
GetSABefore(const VContainer * data,Unit unit) const172 qreal VPieceNode::GetSABefore(const VContainer *data, Unit unit) const
173 {
174     if (d->m_formulaWidthBefore == currentSeamAllowance)
175     {
176         return -1;
177     }
178 
179     VFormula formula(d->m_formulaWidthBefore, data);
180     formula.setCheckZero(false);
181     formula.Eval();
182 
183     if (formula.error())
184     {
185         QString nodeName;
186         try
187         {
188             nodeName = data->GetGObject(d->m_id)->name();
189         }
190         catch (const VExceptionBadId &)
191         {}
192 
193         const QString errorMsg = QObject::tr("Cannot calculate seam allowance before for point '%1'. Reason: %2.")
194                 .arg(nodeName, formula.Reason());
195         VAbstractApplication::VApp()->IsPedantic() ? throw VException(errorMsg) :
196                                               qWarning() << VAbstractValApplication::warningMessageSignature + errorMsg;
197         return -1;
198     }
199 
200     qreal value = formula.getDoubleValue();
201     if (value >= 0)
202     {
203         value = ToPixel(value, unit);
204     }
205     return value;
206 }
207 
208 //---------------------------------------------------------------------------------------------------------------------
GetFormulaSABefore() const209 QString VPieceNode::GetFormulaSABefore() const
210 {
211     return d->m_formulaWidthBefore;
212 }
213 
214 //---------------------------------------------------------------------------------------------------------------------
SetFormulaSABefore(const QString & formula)215 void VPieceNode::SetFormulaSABefore(const QString &formula)
216 {
217     if (d->m_typeTool == Tool::NodePoint)
218     {
219         d->m_formulaWidthBefore = formula;
220     }
221 }
222 
223 //---------------------------------------------------------------------------------------------------------------------
GetSAAfter(const VContainer * data) const224 qreal VPieceNode::GetSAAfter(const VContainer *data) const
225 {
226     if (d->m_formulaWidthAfter == currentSeamAllowance)
227     {
228         return -1;
229     }
230 
231     VFormula formula(d->m_formulaWidthAfter, data);
232     formula.setCheckZero(false);
233     formula.Eval();
234 
235     if (formula.error())
236     {
237         QString nodeName;
238         try
239         {
240             nodeName = data->GetGObject(d->m_id)->name();
241         }
242         catch (const VExceptionBadId &)
243         {}
244 
245         const QString errorMsg = QObject::tr("Cannot calculate seam allowance after for point '%1'. Reason: %2.")
246                 .arg(nodeName, formula.Reason());
247         VAbstractApplication::VApp()->IsPedantic() ? throw VException(errorMsg) :
248                                               qWarning() << VAbstractValApplication::warningMessageSignature + errorMsg;
249         return -1;
250     }
251 
252     return formula.getDoubleValue();
253 }
254 
255 //---------------------------------------------------------------------------------------------------------------------
GetSAAfter(const VContainer * data,Unit unit) const256 qreal VPieceNode::GetSAAfter(const VContainer *data, Unit unit) const
257 {
258     if (d->m_formulaWidthAfter == currentSeamAllowance)
259     {
260         return -1;
261     }
262 
263     VFormula formula(d->m_formulaWidthAfter, data);
264     formula.setCheckZero(false);
265     formula.Eval();
266 
267     if (formula.error())
268     {
269         QString nodeName;
270         try
271         {
272             nodeName = data->GetGObject(d->m_id)->name();
273         }
274         catch (const VExceptionBadId &)
275         {}
276 
277         const QString errorMsg = QObject::tr("Cannot calculate seam allowance after for point '%1'. Reason: ")
278                 .arg(nodeName, formula.Reason());
279         VAbstractApplication::VApp()->IsPedantic() ? throw VException(errorMsg) :
280                                               qWarning() << VAbstractValApplication::warningMessageSignature + errorMsg;
281         return -1;
282     }
283 
284     qreal value = formula.getDoubleValue();
285 
286     if (value >= 0)
287     {
288         value = ToPixel(value, unit);
289     }
290     return value;
291 }
292 
293 //---------------------------------------------------------------------------------------------------------------------
GetFormulaSAAfter() const294 QString VPieceNode::GetFormulaSAAfter() const
295 {
296     return d->m_formulaWidthAfter;
297 }
298 
299 //---------------------------------------------------------------------------------------------------------------------
SetFormulaSAAfter(const QString & formula)300 void VPieceNode::SetFormulaSAAfter(const QString &formula)
301 {
302     if (d->m_typeTool == Tool::NodePoint)
303     {
304         d->m_formulaWidthAfter = formula;
305     }
306 }
307 
308 //---------------------------------------------------------------------------------------------------------------------
GetFormulaPassmarkLength() const309 QString VPieceNode::GetFormulaPassmarkLength() const
310 {
311     return d->m_formulaPassmarkLength;
312 }
313 
314 //---------------------------------------------------------------------------------------------------------------------
SetFormulaPassmarkLength(const QString & formula)315 void VPieceNode::SetFormulaPassmarkLength(const QString &formula)
316 {
317     if (d->m_typeTool == Tool::NodePoint)
318     {
319         d->m_formulaPassmarkLength = formula;
320     }
321 }
322 
323 //---------------------------------------------------------------------------------------------------------------------
GetPassmarkLength(const VContainer * data,Unit unit) const324 qreal VPieceNode::GetPassmarkLength(const VContainer *data, Unit unit) const
325 {
326     if (d->m_manualPassmarkLength)
327     {
328         VFormula formula(d->m_formulaPassmarkLength, data);
329         formula.setCheckZero(false);
330         formula.setCheckLessThanZero(false);
331         formula.Eval();
332 
333         if (formula.error())
334         {
335             QString nodeName;
336             try
337             {
338                 nodeName = data->GetGObject(d->m_id)->name();
339             }
340             catch (const VExceptionBadId &)
341             {}
342 
343             const QString errorMsg = QObject::tr("Cannot calculate passmark length for point '%1'. Reason: %2.")
344                     .arg(nodeName, formula.Reason());
345             VAbstractApplication::VApp()->IsPedantic() ? throw VException(errorMsg) :
346                                               qWarning() << VAbstractValApplication::warningMessageSignature + errorMsg;
347             return VSAPoint::maxPassmarkLength;
348         }
349 
350         return ToPixel(formula.getDoubleValue(), unit);
351     }
352     return -1;
353 }
354 
355 //---------------------------------------------------------------------------------------------------------------------
GetAngleType() const356 PieceNodeAngle VPieceNode::GetAngleType() const
357 {
358     return d->m_angleType;
359 }
360 
361 //---------------------------------------------------------------------------------------------------------------------
SetAngleType(PieceNodeAngle type)362 void VPieceNode::SetAngleType(PieceNodeAngle type)
363 {
364     if (d->m_typeTool == Tool::NodePoint)
365     {
366         d->m_angleType = type;
367     }
368 }
369 
370 //---------------------------------------------------------------------------------------------------------------------
IsPassmark() const371 bool VPieceNode::IsPassmark() const
372 {
373     return d->m_isPassmark;
374 }
375 
376 //---------------------------------------------------------------------------------------------------------------------
SetPassmark(bool passmark)377 void VPieceNode::SetPassmark(bool passmark)
378 {
379     if (GetTypeTool() == Tool::NodePoint)
380     {
381         d->m_isPassmark = passmark;
382     }
383 }
384 
385 //---------------------------------------------------------------------------------------------------------------------
IsMainPathNode() const386 bool VPieceNode::IsMainPathNode() const
387 {
388     return d->m_isMainPathNode;
389 }
390 
391 //---------------------------------------------------------------------------------------------------------------------
SetMainPathNode(bool value)392 void VPieceNode::SetMainPathNode(bool value)
393 {
394     d->m_isMainPathNode = value;
395 }
396 
397 //---------------------------------------------------------------------------------------------------------------------
GetPassmarkLineType() const398 PassmarkLineType VPieceNode::GetPassmarkLineType() const
399 {
400     return d->m_passmarkLineType;
401 }
402 
403 //---------------------------------------------------------------------------------------------------------------------
SetPassmarkLineType(PassmarkLineType lineType)404 void VPieceNode::SetPassmarkLineType(PassmarkLineType lineType)
405 {
406     d->m_passmarkLineType = lineType;
407 }
408 
409 //---------------------------------------------------------------------------------------------------------------------
GetPassmarkAngleType() const410 PassmarkAngleType VPieceNode::GetPassmarkAngleType() const
411 {
412     return d->m_passmarkAngleType;
413 }
414 
415 //---------------------------------------------------------------------------------------------------------------------
SetPassmarkAngleType(PassmarkAngleType angleType)416 void VPieceNode::SetPassmarkAngleType(PassmarkAngleType angleType)
417 {
418     d->m_passmarkAngleType = angleType;
419 }
420 
421 //---------------------------------------------------------------------------------------------------------------------
IsShowSecondPassmark() const422 bool VPieceNode::IsShowSecondPassmark() const
423 {
424     return d->m_isShowSecondPassmark;
425 }
426 
427 //---------------------------------------------------------------------------------------------------------------------
SetShowSecondPassmark(bool value)428 void VPieceNode::SetShowSecondPassmark(bool value)
429 {
430     d->m_isShowSecondPassmark = value;
431 }
432 
433 //---------------------------------------------------------------------------------------------------------------------
IsCheckUniqueness() const434 bool VPieceNode::IsCheckUniqueness() const
435 {
436     return d->m_checkUniqueness;
437 }
438 
439 //---------------------------------------------------------------------------------------------------------------------
SetCheckUniqueness(bool value)440 void VPieceNode::SetCheckUniqueness(bool value)
441 {
442     d->m_checkUniqueness = (d->m_typeTool == Tool::NodePoint ? value : true);
443 }
444 
445 //---------------------------------------------------------------------------------------------------------------------
IsManualPassmarkLength() const446 bool VPieceNode::IsManualPassmarkLength() const
447 {
448     return d->m_manualPassmarkLength;
449 }
450 
451 //---------------------------------------------------------------------------------------------------------------------
SetManualPassmarkLength(bool value)452 void VPieceNode::SetManualPassmarkLength(bool value)
453 {
454     d->m_manualPassmarkLength = value;
455 }
456 
457 //---------------------------------------------------------------------------------------------------------------------
IsExcluded() const458 bool VPieceNode::IsExcluded() const
459 {
460     return d->m_excluded;
461 }
462 
463 //---------------------------------------------------------------------------------------------------------------------
SetExcluded(bool exclude)464 void VPieceNode::SetExcluded(bool exclude)
465 {
466     d->m_excluded = exclude;
467 }
468