Salome HOME
Merge branch 'Dev_0.7.1' of newgeom:newgeom.git into Dev_0.7.1
[modules/shaper.git] / src / SketchPlugin / SketchPlugin_Arc.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
2
3 // File:        SketchPlugin_Arc.cpp
4 // Created:     26 Apr 2014
5 // Author:      Artem ZHIDKOV
6
7 #include "SketchPlugin_Arc.h"
8 #include "SketchPlugin_Sketch.h"
9 #include <ModelAPI_Data.h>
10 #include <ModelAPI_ResultConstruction.h>
11 #include <ModelAPI_AttributeSelection.h>
12 #include <ModelAPI_Validator.h>
13 #include <ModelAPI_Session.h>
14
15 #include <GeomAPI_Circ2d.h>
16 #include <GeomAPI_Pnt2d.h>
17 #include <GeomDataAPI_Point2D.h>
18 #include <GeomDataAPI_Dir.h>
19 #include <GeomAlgoAPI_PointBuilder.h>
20 #include <GeomAlgoAPI_EdgeBuilder.h>
21 #include <GeomAlgoAPI_CompoundBuilder.h>
22
23 const double tolerance = 1e-7;
24
25 SketchPlugin_Arc::SketchPlugin_Arc()
26     : SketchPlugin_Feature()
27 {
28   myStartUpdate = false;
29   myEndUpdate = false;
30 }
31
32 void SketchPlugin_Arc::initAttributes()
33 {
34   data()->addAttribute(CENTER_ID(), GeomDataAPI_Point2D::type());
35   data()->addAttribute(START_ID(), GeomDataAPI_Point2D::type());
36   data()->addAttribute(END_ID(), GeomDataAPI_Point2D::type());
37   data()->addAttribute(EXTERNAL_ID(), ModelAPI_AttributeSelection::type());
38   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EXTERNAL_ID());
39 }
40
41 void SketchPlugin_Arc::execute()
42 {
43   SketchPlugin_Sketch* aSketch = sketch();
44   // result for the arc is set only when all obligatory attributes are initialized,
45   // otherwise AIS object is used to visualize the arc's preview
46   if (aSketch && isFeatureValid()) {
47     // compute a circle point in 3D view
48     std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr = std::dynamic_pointer_cast<
49         GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
50     // compute the arc start point
51     std::shared_ptr<GeomDataAPI_Point2D> aStartAttr = std::dynamic_pointer_cast<
52         GeomDataAPI_Point2D>(data()->attribute(START_ID()));
53
54     std::shared_ptr<GeomAPI_Pnt> aCenter(aSketch->to3D(aCenterAttr->x(), aCenterAttr->y()));
55     // make a visible point
56     std::shared_ptr<GeomAPI_Shape> aCenterPointShape = GeomAlgoAPI_PointBuilder::point(aCenter);
57     std::shared_ptr<ModelAPI_ResultConstruction> aConstr1 = document()->createConstruction(
58         data(), 0);
59     aConstr1->setShape(aCenterPointShape);
60     aConstr1->setIsInHistory(false);
61     setResult(aConstr1, 0);
62
63     // make a visible circle
64     std::shared_ptr<GeomDataAPI_Dir> aNDir = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
65         aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
66     std::shared_ptr<GeomAPI_Dir> aNormal = aNDir->dir();
67     std::shared_ptr<GeomAPI_Pnt> aStartPoint(aSketch->to3D(aStartAttr->x(), aStartAttr->y()));
68
69     // compute and change the arc end point
70     std::shared_ptr<GeomDataAPI_Point2D> anEndAttr = std::dynamic_pointer_cast<
71         GeomDataAPI_Point2D>(data()->attribute(END_ID()));
72     /* must be automatically done in attributeChanged
73     std::shared_ptr<GeomAPI_Circ2d> aCircleForArc(
74         new GeomAPI_Circ2d(aCenterAttr->pnt(), aStartAttr->pnt()));
75     std::shared_ptr<GeomAPI_Pnt2d> aProjection = aCircleForArc->project(anEndAttr->pnt());
76     if (aProjection && anEndAttr->pnt()->distance(aProjection) > tolerance)
77       anEndAttr->setValue(aProjection);
78     */
79     std::shared_ptr<GeomAPI_Pnt> aEndPoint(aSketch->to3D(anEndAttr->x(), anEndAttr->y()));
80
81     std::shared_ptr<GeomAPI_Shape> aCircleShape = GeomAlgoAPI_EdgeBuilder::lineCircleArc(
82         aCenter, aStartPoint, aEndPoint, aNormal);
83     if (aCircleShape) {
84       std::shared_ptr<ModelAPI_ResultConstruction> aConstr2 = document()->createConstruction(
85           data(), 1);
86       aConstr2->setShape(aCircleShape);
87       aConstr2->setIsInHistory(false);
88       setResult(aConstr2, 1);
89     }
90   }
91 }
92
93 AISObjectPtr SketchPlugin_Arc::getAISObject(AISObjectPtr thePrevious)
94 {
95   SketchPlugin_Sketch* aSketch = sketch();
96   if (aSketch) {
97     // if the feature is valid, the execute() method should be performed, AIS object is empty
98     if (!isFeatureValid()) {
99       // compute a circle point in 3D view
100       std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr = std::dynamic_pointer_cast<
101           GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
102       if (aCenterAttr->isInitialized()) {
103         std::shared_ptr<GeomAPI_Pnt> aCenter(aSketch->to3D(aCenterAttr->x(), aCenterAttr->y()));
104
105         std::shared_ptr<GeomDataAPI_Point2D> aStartAttr = std::dynamic_pointer_cast<
106             GeomDataAPI_Point2D>(data()->attribute(SketchPlugin_Arc::START_ID()));
107         if (aStartAttr->isInitialized()) {
108           // make a visible circle
109           std::shared_ptr<GeomDataAPI_Dir> aNDir = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
110               aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
111           bool aHasPlane = aNDir && !(aNDir->x() == 0 && aNDir->y() == 0 && aNDir->z() == 0);
112           if (aHasPlane) {
113             std::shared_ptr<GeomAPI_Dir> aNormal = aNDir->dir();
114             std::shared_ptr<GeomAPI_Pnt> aStartPoint(aSketch->to3D(aStartAttr->x(), aStartAttr->y()));
115             std::shared_ptr<GeomAPI_Shape> aCircleShape = GeomAlgoAPI_EdgeBuilder::lineCircleArc(
116                                                             aCenter, aStartPoint, aStartPoint, aNormal);
117             if (aCircleShape) {
118               std::list<std::shared_ptr<GeomAPI_Shape> > aShapes;
119               // make a visible point
120               std::shared_ptr<GeomAPI_Shape> aCenterPointShape = GeomAlgoAPI_PointBuilder::point(aCenter);
121               aShapes.push_back(aCenterPointShape);
122
123               aShapes.push_back(aCircleShape);
124               if (!aShapes.empty())
125               {
126                 std::shared_ptr<GeomAPI_Shape> aCompound = GeomAlgoAPI_CompoundBuilder::compound(aShapes);
127                 AISObjectPtr anAIS = thePrevious;
128                 if (!anAIS)
129                   anAIS = AISObjectPtr(new GeomAPI_AISObject);
130                 anAIS->createShape(aCompound);
131                 anAIS->setWidth(3);
132                 return anAIS;
133               }
134             }
135           }
136         }
137       }
138     }
139   }
140   return AISObjectPtr();
141 }
142
143 void SketchPlugin_Arc::move(double theDeltaX, double theDeltaY)
144 {
145   std::shared_ptr<ModelAPI_Data> aData = data();
146   if (!aData->isValid())
147     return;
148
149   std::shared_ptr<GeomDataAPI_Point2D> aPoint1 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
150       aData->attribute(SketchPlugin_Arc::CENTER_ID()));
151   aPoint1->move(theDeltaX, theDeltaY);
152
153   myStartUpdate = true;
154   myEndUpdate = true;
155   std::shared_ptr<GeomDataAPI_Point2D> aPoint2 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
156       aData->attribute(SketchPlugin_Arc::START_ID()));
157   aPoint2->move(theDeltaX, theDeltaY);
158
159   std::shared_ptr<GeomDataAPI_Point2D> aPoint3 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
160       aData->attribute(SketchPlugin_Arc::END_ID()));
161   aPoint3->move(theDeltaX, theDeltaY);
162   myStartUpdate = false;
163   myEndUpdate = false;
164 }
165
166 double SketchPlugin_Arc::distanceToPoint(const std::shared_ptr<GeomAPI_Pnt2d>& thePoint)
167 {
168   double aDelta = 0;
169   std::shared_ptr<ModelAPI_Data> aData = data();
170
171   std::shared_ptr<GeomDataAPI_Point2D> aPoint1 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
172       aData->attribute(SketchPlugin_Arc::CENTER_ID()));
173   aDelta = aPoint1->pnt()->distance(thePoint);
174
175   std::shared_ptr<GeomDataAPI_Point2D> aPoint2 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
176       aData->attribute(SketchPlugin_Arc::START_ID()));
177   double aDistance = aPoint2->pnt()->distance(thePoint);
178   if (aDelta < aDistance)
179     aDelta = aDistance;
180
181   std::shared_ptr<GeomDataAPI_Point2D> aPoint3 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
182       aData->attribute(SketchPlugin_Arc::END_ID()));
183   aDistance = aPoint3->pnt()->distance(thePoint);
184   if (aDelta < aDistance)
185     aDelta = aDistance;
186
187   return aDelta;
188 }
189
190 bool SketchPlugin_Arc::isFixed() {
191   return data()->selection(EXTERNAL_ID())->context().get();
192 }
193
194 bool SketchPlugin_Arc::isFeatureValid()
195 {
196   std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr = std::dynamic_pointer_cast<
197       GeomDataAPI_Point2D>(data()->attribute(SketchPlugin_Arc::CENTER_ID()));
198   std::shared_ptr<GeomDataAPI_Point2D> aStartAttr = std::dynamic_pointer_cast<
199       GeomDataAPI_Point2D>(data()->attribute(SketchPlugin_Arc::START_ID()));
200   std::shared_ptr<GeomDataAPI_Point2D> anEndAttr = std::dynamic_pointer_cast<
201       GeomDataAPI_Point2D>(data()->attribute(SketchPlugin_Arc::END_ID()));
202
203   return aCenterAttr->isInitialized() && aStartAttr->isInitialized() && anEndAttr->isInitialized();
204 }
205
206 void SketchPlugin_Arc::attributeChanged(const std::string& theID)
207 {
208   std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr = std::dynamic_pointer_cast<
209       GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
210   if (!aCenterAttr->isInitialized())
211     return;
212   std::shared_ptr<GeomDataAPI_Point2D> aStartAttr = std::dynamic_pointer_cast<
213       GeomDataAPI_Point2D>(data()->attribute(START_ID()));
214   if (!aStartAttr->isInitialized())
215     return;
216   std::shared_ptr<GeomDataAPI_Point2D> anEndAttr = std::dynamic_pointer_cast<
217       GeomDataAPI_Point2D>(data()->attribute(END_ID()));
218   if (!anEndAttr->isInitialized())
219     return;
220
221   // update the points in accordance to the changed point changes
222   if (theID == END_ID() && !myEndUpdate) {
223     myEndUpdate = true;
224     // compute and change the arc end point
225     std::shared_ptr<GeomAPI_Circ2d> aCircleForArc(
226         new GeomAPI_Circ2d(aCenterAttr->pnt(), aStartAttr->pnt()));
227     std::shared_ptr<GeomAPI_Pnt2d> aProjection = aCircleForArc->project(anEndAttr->pnt());
228     if (aProjection && anEndAttr->pnt()->distance(aProjection) > tolerance)
229       anEndAttr->setValue(aProjection);
230     myEndUpdate = false;
231   } else if (theID == START_ID() && !myStartUpdate) {
232     myStartUpdate = true;
233     // compute and change the arc end point
234     std::shared_ptr<GeomAPI_Circ2d> aCircleForArc(
235         new GeomAPI_Circ2d(aCenterAttr->pnt(), anEndAttr->pnt()));
236     std::shared_ptr<GeomAPI_Pnt2d> aProjection = aCircleForArc->project(aStartAttr->pnt());
237     if (aProjection && aStartAttr->pnt()->distance(aProjection) > tolerance)
238       aStartAttr->setValue(aProjection);
239     myStartUpdate = false;
240   } else if (theID == CENTER_ID() && !myEndUpdate) {
241     myEndUpdate = true;
242     // compute and change the arc end point
243     std::shared_ptr<GeomAPI_Circ2d> aCircleForArc(
244         new GeomAPI_Circ2d(aCenterAttr->pnt(), aStartAttr->pnt()));
245     std::shared_ptr<GeomAPI_Pnt2d> aProjection = aCircleForArc->project(anEndAttr->pnt());
246     if (aProjection && anEndAttr->pnt()->distance(aProjection) > tolerance)
247       anEndAttr->setValue(aProjection);
248     myEndUpdate = false;
249   }
250 }