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