1 /************************************************************************
2  **
3  **  @file   vistoolspline.cpp
4  **  @author Roman Telezhynskyi <dismine(at)gmail.com>
5  **  @date   18 8, 2014
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) 2013-2015 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 "vistoolspline.h"
30 
31 #include <QLineF>
32 #include <QPainterPath>
33 #include <QSharedPointer>
34 #include <Qt>
35 #include <new>
36 
37 #include "../ifc/ifcdef.h"
38 #include "../vgeometry/vabstractcurve.h"
39 #include "../vgeometry/vgeometrydef.h"
40 #include "../vgeometry/vpointf.h"
41 #include "../vgeometry/vspline.h"
42 #include "../vpatterndb/vcontainer.h"
43 #include "../vwidgets/vcontrolpointspline.h"
44 #include "../vwidgets/scalesceneitems.h"
45 #include "../visualization.h"
46 #include "vispath.h"
47 #include "../vmisc/vmodifierkey.h"
48 
49 const int EMPTY_ANGLE = -1;
50 
51 //---------------------------------------------------------------------------------------------------------------------
VisToolSpline(const VContainer * data,QGraphicsItem * parent)52 VisToolSpline::VisToolSpline(const VContainer *data, QGraphicsItem *parent)
53     : VisPath(data, parent),
54       object4Id(NULL_ID),
55       point1(nullptr),
56       point4(nullptr),
57       angle1(EMPTY_ANGLE),
58       angle2(EMPTY_ANGLE),
59       kAsm1(1),
60       kAsm2(1),
61       kCurve(1),
62       isLeftMousePressed(false),
63       p2Selected(false),
64       p3Selected(false),
65       p2(),
66       p3(),
67       controlPoints()
68 {
69     point1 = InitPoint(supportColor, this);
70     point4 = InitPoint(supportColor, this); //-V656
71 
72     auto *controlPoint1 = new VControlPointSpline(1, SplinePointPosition::FirstPoint, this);
73     controlPoint1->hide();
74     controlPoints.append(controlPoint1);
75 
76     auto *controlPoint2 = new VControlPointSpline(1, SplinePointPosition::LastPoint, this);
77     controlPoint2->hide();
78     controlPoints.append(controlPoint2);
79 }
80 
81 //---------------------------------------------------------------------------------------------------------------------
~VisToolSpline()82 VisToolSpline::~VisToolSpline()
83 {
84     emit ToolTip(QString());
85 }
86 
87 //---------------------------------------------------------------------------------------------------------------------
RefreshGeometry()88 void VisToolSpline::RefreshGeometry()
89 {
90     //Radius of point circle, but little bigger. Need handle with hover sizes.
91     const static qreal radius = ScaledRadius(SceneScale(VAbstractValApplication::VApp()->getCurrentScene()))*1.5;
92 
93     if (object1Id > NULL_ID)
94     {
95         const auto first = Visualization::data->GeometricObject<VPointF>(object1Id);
96         DrawPoint(point1, static_cast<QPointF>(*first), supportColor);
97 
98         if (mode == Mode::Creation)
99         {
100             if (isLeftMousePressed && not p2Selected)
101             {
102                 p2 = Visualization::scenePos;
103                 controlPoints[0]->RefreshCtrlPoint(1, SplinePointPosition::FirstPoint, p2,
104                                                    static_cast<QPointF>(*first));
105 
106                 if (not controlPoints[0]->isVisible())
107                 {
108                     if (QLineF(static_cast<QPointF>(*first), p2).length() > radius)
109                     {
110                         controlPoints[0]->show();
111                     }
112                     else
113                     {
114                         p2 = static_cast<QPointF>(*first);
115                     }
116                 }
117             }
118             else
119             {
120                 p2Selected = true;
121             }
122         }
123 
124         if (object4Id <= NULL_ID)
125         {
126             VSpline spline(*first, p2, Visualization::scenePos, VPointF(Visualization::scenePos));
127             spline.SetApproximationScale(m_approximationScale);
128             DrawPath(this, spline.GetPath(), mainColor, lineStyle, Qt::RoundCap);
129         }
130         else
131         {
132             const auto second = Visualization::data->GeometricObject<VPointF>(object4Id);
133             DrawPoint(point4, static_cast<QPointF>(*second), supportColor);
134 
135             if (mode == Mode::Creation)
136             {
137                 if (isLeftMousePressed && not p3Selected)
138                 {
139                     QLineF ctrlLine (static_cast<QPointF>(*second), Visualization::scenePos);
140                     ctrlLine.setAngle(ctrlLine.angle()+180);
141                     p3 = ctrlLine.p2();
142                     controlPoints[1]->RefreshCtrlPoint(1, SplinePointPosition::LastPoint, p3,
143                                                        static_cast<QPointF>(*second));
144 
145                     if (not controlPoints[1]->isVisible())
146                     {
147                         if (QLineF(static_cast<QPointF>(*second), p3).length() > radius)
148                         {
149                             controlPoints[1]->show();
150                         }
151                         else
152                         {
153                             p3 = static_cast<QPointF>(*second);
154                         }
155                     }
156                 }
157                 else
158                 {
159                     p3Selected = true;
160                 }
161             }
162 
163             if (VFuzzyComparePossibleNulls(angle1, EMPTY_ANGLE) || VFuzzyComparePossibleNulls(angle2, EMPTY_ANGLE))
164             {
165                 VSpline spline(*first, p2, p3, *second);
166                 spline.SetApproximationScale(m_approximationScale);
167                 DrawPath(this, spline.GetPath(), mainColor, lineStyle, Qt::RoundCap);
168             }
169             else
170             {
171                 VSpline spline(*first, *second, angle1, angle2, kAsm1, kAsm2, kCurve);
172                 spline.SetApproximationScale(m_approximationScale);
173                 DrawPath(this, spline.GetPath(), spline.DirectionArrows(), mainColor, lineStyle, Qt::RoundCap);
174                 Visualization::toolTip = tr("Use <b>%1</b> for sticking angle!")
175                         .arg(VModifierKey::Shift());
176                 emit ToolTip(Visualization::toolTip);
177             }
178         }
179     }
180 }
181 
182 //---------------------------------------------------------------------------------------------------------------------
setObject4Id(const quint32 & value)183 void VisToolSpline::setObject4Id(const quint32 &value)
184 {
185     object4Id = value;
186 }
187 
188 //---------------------------------------------------------------------------------------------------------------------
SetAngle1(const qreal & value)189 void VisToolSpline::SetAngle1(const qreal &value)
190 {
191     angle1 = value;
192 }
193 
194 //---------------------------------------------------------------------------------------------------------------------
SetAngle2(const qreal & value)195 void VisToolSpline::SetAngle2(const qreal &value)
196 {
197     angle2 = value;
198 }
199 
200 //---------------------------------------------------------------------------------------------------------------------
SetKAsm1(const qreal & value)201 void VisToolSpline::SetKAsm1(const qreal &value)
202 {
203     kAsm1 = value;
204 }
205 
206 //---------------------------------------------------------------------------------------------------------------------
SetKAsm2(const qreal & value)207 void VisToolSpline::SetKAsm2(const qreal &value)
208 {
209     kAsm2 = value;
210 }
211 
212 //---------------------------------------------------------------------------------------------------------------------
SetKCurve(const qreal & value)213 void VisToolSpline::SetKCurve(const qreal &value)
214 {
215     kCurve = value;
216 }
217 
218 //---------------------------------------------------------------------------------------------------------------------
GetP2() const219 QPointF VisToolSpline::GetP2() const
220 {
221     return p2;
222 }
223 
224 //---------------------------------------------------------------------------------------------------------------------
GetP3() const225 QPointF VisToolSpline::GetP3() const
226 {
227     return p3;
228 }
229 
230 //---------------------------------------------------------------------------------------------------------------------
MouseLeftPressed()231 void VisToolSpline::MouseLeftPressed()
232 {
233     if (mode == Mode::Creation)
234     {
235         isLeftMousePressed = true;
236     }
237 }
238 
239 //---------------------------------------------------------------------------------------------------------------------
MouseLeftReleased()240 void VisToolSpline::MouseLeftReleased()
241 {
242     if (mode == Mode::Creation)
243     {
244         isLeftMousePressed = false;
245         RefreshGeometry();
246     }
247 }
248