Salome HOME
7600903953f4cdd55607e11e3c5242c31dfa1864
[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                 return anAIS;
132               }
133             }
134           }
135         }
136       }
137     }
138   }
139   return AISObjectPtr();
140 }
141
142 void SketchPlugin_Arc::move(double theDeltaX, double theDeltaY)
143 {
144   std::shared_ptr<ModelAPI_Data> aData = data();
145   if (!aData->isValid())
146     return;
147
148   std::shared_ptr<GeomDataAPI_Point2D> aPoint1 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
149       aData->attribute(SketchPlugin_Arc::CENTER_ID()));
150   aPoint1->move(theDeltaX, theDeltaY);
151
152   myStartUpdate = true;
153   myEndUpdate = true;
154   std::shared_ptr<GeomDataAPI_Point2D> aPoint2 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
155       aData->attribute(SketchPlugin_Arc::START_ID()));
156   aPoint2->move(theDeltaX, theDeltaY);
157
158   std::shared_ptr<GeomDataAPI_Point2D> aPoint3 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
159       aData->attribute(SketchPlugin_Arc::END_ID()));
160   aPoint3->move(theDeltaX, theDeltaY);
161   myStartUpdate = false;
162   myEndUpdate = false;
163 }
164
165 double SketchPlugin_Arc::distanceToPoint(const std::shared_ptr<GeomAPI_Pnt2d>& thePoint)
166 {
167   double aDelta = 0;
168   std::shared_ptr<ModelAPI_Data> aData = data();
169
170   std::shared_ptr<GeomDataAPI_Point2D> aPoint1 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
171       aData->attribute(SketchPlugin_Arc::CENTER_ID()));
172   aDelta = aPoint1->pnt()->distance(thePoint);
173
174   std::shared_ptr<GeomDataAPI_Point2D> aPoint2 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
175       aData->attribute(SketchPlugin_Arc::START_ID()));
176   double aDistance = aPoint2->pnt()->distance(thePoint);
177   if (aDelta < aDistance)
178     aDelta = aDistance;
179
180   std::shared_ptr<GeomDataAPI_Point2D> aPoint3 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
181       aData->attribute(SketchPlugin_Arc::END_ID()));
182   aDistance = aPoint3->pnt()->distance(thePoint);
183   if (aDelta < aDistance)
184     aDelta = aDistance;
185
186   return aDelta;
187 }
188
189 bool SketchPlugin_Arc::isFixed() {
190   return data()->selection(EXTERNAL_ID())->context();
191 }
192
193 bool SketchPlugin_Arc::isFeatureValid()
194 {
195   std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr = std::dynamic_pointer_cast<
196       GeomDataAPI_Point2D>(data()->attribute(SketchPlugin_Arc::CENTER_ID()));
197   std::shared_ptr<GeomDataAPI_Point2D> aStartAttr = std::dynamic_pointer_cast<
198       GeomDataAPI_Point2D>(data()->attribute(SketchPlugin_Arc::START_ID()));
199   std::shared_ptr<GeomDataAPI_Point2D> anEndAttr = std::dynamic_pointer_cast<
200       GeomDataAPI_Point2D>(data()->attribute(SketchPlugin_Arc::END_ID()));
201
202   return aCenterAttr->isInitialized() && aStartAttr->isInitialized() && anEndAttr->isInitialized();
203 }
204
205 void SketchPlugin_Arc::attributeChanged(const std::string& theID)
206 {
207   std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr = std::dynamic_pointer_cast<
208       GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
209   if (!aCenterAttr->isInitialized())
210     return;
211   std::shared_ptr<GeomDataAPI_Point2D> aStartAttr = std::dynamic_pointer_cast<
212       GeomDataAPI_Point2D>(data()->attribute(START_ID()));
213   if (!aStartAttr->isInitialized())
214     return;
215   std::shared_ptr<GeomDataAPI_Point2D> anEndAttr = std::dynamic_pointer_cast<
216       GeomDataAPI_Point2D>(data()->attribute(END_ID()));
217   if (!anEndAttr->isInitialized())
218     return;
219
220   // update the points in accordance to the changed point changes
221   if (theID == END_ID() && !myEndUpdate) {
222     myEndUpdate = true;
223     // compute and change the arc end point
224     std::shared_ptr<GeomAPI_Circ2d> aCircleForArc(
225         new GeomAPI_Circ2d(aCenterAttr->pnt(), aStartAttr->pnt()));
226     std::shared_ptr<GeomAPI_Pnt2d> aProjection = aCircleForArc->project(anEndAttr->pnt());
227     if (aProjection && anEndAttr->pnt()->distance(aProjection) > tolerance)
228       anEndAttr->setValue(aProjection);
229     myEndUpdate = false;
230   } else if (theID == START_ID() && !myStartUpdate) {
231     myStartUpdate = true;
232     // compute and change the arc end point
233     std::shared_ptr<GeomAPI_Circ2d> aCircleForArc(
234         new GeomAPI_Circ2d(aCenterAttr->pnt(), anEndAttr->pnt()));
235     std::shared_ptr<GeomAPI_Pnt2d> aProjection = aCircleForArc->project(aStartAttr->pnt());
236     if (aProjection && aStartAttr->pnt()->distance(aProjection) > tolerance)
237       aStartAttr->setValue(aProjection);
238     myStartUpdate = false;
239   }
240 }