Salome HOME
refs #30 - Sketch base GUI: create, draw lines
[modules/shaper.git] / src / PartSet / PartSet_OperationSketchLine.cpp
1 // File:        PartSet_OperationSketchLine.h
2 // Created:     20 Apr 2014
3 // Author:      Natalia ERMOLAEVA
4
5 #include <PartSet_OperationSketchLine.h>
6
7 #include <PartSet_Tools.h>
8
9 #include <SketchPlugin_Feature.h>
10 #include <GeomDataAPI_Point2D.h>
11 #include <ModelAPI_Data.h>
12 #include <ModelAPI_Document.h>
13
14 #include <Geom_Line.hxx>
15 #include <gp_Lin.hxx>
16
17 #include <XGUI_ViewerPrs.h>
18
19 #include <SketchPlugin_Line.h>
20
21 #include <V3d_View.hxx>
22 #include <TopoDS_Vertex.hxx>
23 #include <TopoDS.hxx>
24 #include <BRep_Tool.hxx>
25
26 #ifdef _DEBUG
27 #include <QDebug>
28 #endif
29
30 #include <QMouseEvent>
31
32 using namespace std;
33
34 PartSet_OperationSketchLine::PartSet_OperationSketchLine(const QString& theId,
35                                                   QObject* theParent,
36                                               boost::shared_ptr<ModelAPI_Feature> theFeature)
37 : PartSet_OperationSketchBase(theId, theParent), mySketch(theFeature),
38   myPointSelectionMode(SM_FirstPoint)
39 {
40 }
41
42 PartSet_OperationSketchLine::~PartSet_OperationSketchLine()
43 {
44 }
45
46 bool PartSet_OperationSketchLine::isGranted() const
47 {
48   return true;
49 }
50
51 std::list<int> PartSet_OperationSketchLine::getSelectionModes(boost::shared_ptr<ModelAPI_Feature> theFeature) const
52 {
53   return std::list<int>();
54 }
55
56 void PartSet_OperationSketchLine::init(boost::shared_ptr<ModelAPI_Feature> theFeature)
57 {
58   if (!theFeature)
59     return;
60   // use the last point of the previous feature as the first of the new one
61   boost::shared_ptr<ModelAPI_Data> aData = theFeature->data();
62   myInitPoint = boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(LINE_ATTR_END));
63 }
64
65 void PartSet_OperationSketchLine::mouseReleased(QMouseEvent* theEvent, Handle(V3d_View) theView,
66                                                 const std::list<XGUI_ViewerPrs>& theSelected)
67 {
68   gp_Pnt aPoint = PartSet_Tools::ConvertClickToPoint(theEvent->pos(), theView);
69
70   if (!theSelected.empty()) {
71     XGUI_ViewerPrs aPrs = theSelected.front();
72     const TopoDS_Shape& aShape = aPrs.shape();
73     if (!aShape.IsNull()) {
74       if (aShape.ShapeType() == TopAbs_VERTEX) {
75         const TopoDS_Vertex& aVertex = TopoDS::Vertex(aShape);
76         if (!aVertex.IsNull())
77           aPoint = BRep_Tool::Pnt(aVertex);
78       }
79       else if (aShape.ShapeType() == TopAbs_EDGE) {
80         boost::shared_ptr<ModelAPI_Feature> aFeature = aPrs.feature();
81         if (!aFeature)
82           return;
83         double X0, X1, X2, X3;
84         double Y0, Y1, Y2, Y3;
85         getLinePoint(aFeature, LINE_ATTR_START, X2, Y2);
86         getLinePoint(aFeature, LINE_ATTR_END, X3, Y3);
87
88         if (myPointSelectionMode == SM_SecondPoint) {
89           getLinePoint(feature(), LINE_ATTR_START, X0, Y0);
90           PartSet_Tools::ConvertTo2D(aPoint, mySketch, theView, X1, Y1);
91
92           double aX, anY;
93           PartSet_Tools::IntersectLines(X0, Y0, X1, Y1, X2, Y2, X3, Y3, aX, anY);
94
95           setLinePoint(aX, anY, LINE_ATTR_END);
96           commit();
97           emit featureConstructed(feature(), FM_Deactivation);
98           emit launchOperation(PartSet_OperationSketchLine::Type(), feature());
99           return;
100         }
101
102       }
103     }
104   }
105
106   switch (myPointSelectionMode)
107   {
108     case SM_FirstPoint: {
109       setLinePoint(aPoint, theView, LINE_ATTR_START);
110       myPointSelectionMode = SM_SecondPoint;
111     }
112     break;
113     case SM_SecondPoint: {
114       setLinePoint(aPoint, theView, LINE_ATTR_END);
115       commit();
116       emit featureConstructed(feature(), FM_Deactivation);
117       emit launchOperation(PartSet_OperationSketchLine::Type(), feature());
118     }
119     break;
120     default:
121       break;
122   }
123 }
124
125 void PartSet_OperationSketchLine::mouseMoved(QMouseEvent* theEvent, Handle(V3d_View) theView)
126 {
127   switch (myPointSelectionMode)
128   {
129     case SM_SecondPoint:
130     {
131       gp_Pnt aPoint = PartSet_Tools::ConvertClickToPoint(theEvent->pos(), theView);
132       setLinePoint(aPoint, theView, LINE_ATTR_END);
133     }
134     break;
135     default:
136       break;
137   }
138 }
139
140 void PartSet_OperationSketchLine::keyReleased(const int theKey)
141 {
142   switch (theKey) {
143     case Qt::Key_Escape: {
144       abort();
145     }
146     break;
147     case Qt::Key_Return: {
148       abort();
149       emit launchOperation(PartSet_OperationSketchLine::Type(), boost::shared_ptr<ModelAPI_Feature>());
150     }
151     break;
152     default:
153     break;
154   }
155 }
156
157 void PartSet_OperationSketchLine::startOperation()
158 {
159   PartSet_OperationSketchBase::startOperation();
160   myPointSelectionMode = !myInitPoint ? SM_FirstPoint : SM_SecondPoint;
161   emit multiSelectionEnabled(false);
162 }
163
164 void PartSet_OperationSketchLine::abortOperation()
165 {
166   emit featureConstructed(feature(), FM_Abort);
167   PartSet_OperationSketchBase::abortOperation();
168 }
169
170 void PartSet_OperationSketchLine::stopOperation()
171 {
172   PartSet_OperationSketchBase::stopOperation();
173   emit multiSelectionEnabled(true);
174 }
175
176 boost::shared_ptr<ModelAPI_Feature> PartSet_OperationSketchLine::createFeature()
177 {
178   boost::shared_ptr<ModelAPI_Feature> aNewFeature = ModuleBase_Operation::createFeature();
179   if (mySketch) {
180     boost::shared_ptr<SketchPlugin_Feature> aFeature = 
181                            boost::dynamic_pointer_cast<SketchPlugin_Feature>(mySketch);
182
183     aFeature->addSub(aNewFeature);
184   }
185   if (myInitPoint) {
186     boost::shared_ptr<ModelAPI_Data> aData = aNewFeature->data();
187     boost::shared_ptr<GeomDataAPI_Point2D> aPoint = boost::dynamic_pointer_cast<GeomDataAPI_Point2D>
188                                                                 (aData->attribute(LINE_ATTR_START));
189     aPoint->setValue(myInitPoint->x(), myInitPoint->y());
190   }
191
192   emit featureConstructed(aNewFeature, FM_Activation);
193   return aNewFeature;
194 }
195
196 void PartSet_OperationSketchLine::getLinePoint(boost::shared_ptr<ModelAPI_Feature> theFeature,
197                                                const std::string& theAttribute,
198                                                double& theX, double& theY)
199 {
200   if (!theFeature)
201     return;
202   boost::shared_ptr<ModelAPI_Data> aData = theFeature->data();
203   boost::shared_ptr<GeomDataAPI_Point2D> aPoint =
204         boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(theAttribute));
205   theX = aPoint->x();
206   theY = aPoint->y();
207 }
208
209 void PartSet_OperationSketchLine::setLinePoint(double theX, double theY,
210                                                const std::string& theAttribute)
211 {
212   boost::shared_ptr<ModelAPI_Data> aData = feature()->data();
213   boost::shared_ptr<GeomDataAPI_Point2D> aPoint =
214         boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(theAttribute));
215   aPoint->setValue(theX, theY);
216 }
217
218 void PartSet_OperationSketchLine::setLinePoint(const gp_Pnt& thePoint,
219                                                Handle(V3d_View) theView,
220                                                const std::string& theAttribute)
221 {
222   double aX, anY;
223   PartSet_Tools::ConvertTo2D(thePoint, mySketch, theView, aX, anY);
224   boost::shared_ptr<ModelAPI_Data> aData = feature()->data();
225   boost::shared_ptr<GeomDataAPI_Point2D> aPoint =
226         boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(theAttribute));
227   aPoint->setValue(aX, anY);
228 }