1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
3 // File: SketchPlugin_Arc.cpp
4 // Created: 26 Apr 2014
5 // Author: Artem ZHIDKOV
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>
15 #include <GeomAPI_Circ2d.h>
16 #include <GeomAPI_Circ.h>
17 #include <GeomAPI_Pnt2d.h>
18 #include <GeomDataAPI_Point2D.h>
19 #include <GeomDataAPI_Dir.h>
20 #include <GeomAlgoAPI_PointBuilder.h>
21 #include <GeomAlgoAPI_EdgeBuilder.h>
22 #include <GeomAlgoAPI_CompoundBuilder.h>
24 const double tolerance = 1e-7;
26 SketchPlugin_Arc::SketchPlugin_Arc()
27 : SketchPlugin_SketchEntity()
29 myStartUpdate = false;
33 void SketchPlugin_Arc::initAttributes()
35 SketchPlugin_SketchEntity::initAttributes();
37 data()->addAttribute(CENTER_ID(), GeomDataAPI_Point2D::typeId());
38 data()->addAttribute(START_ID(), GeomDataAPI_Point2D::typeId());
39 data()->addAttribute(END_ID(), GeomDataAPI_Point2D::typeId());
40 data()->addAttribute(EXTERNAL_ID(), ModelAPI_AttributeSelection::typeId());
41 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EXTERNAL_ID());
44 void SketchPlugin_Arc::execute()
46 SketchPlugin_Sketch* aSketch = sketch();
47 // result for the arc is set only when all obligatory attributes are initialized,
48 // otherwise AIS object is used to visualize the arc's preview
49 if (aSketch && isFeatureValid()) {
50 // compute a circle point in 3D view
51 std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr = std::dynamic_pointer_cast<
52 GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
53 // compute the arc start point
54 std::shared_ptr<GeomDataAPI_Point2D> aStartAttr = std::dynamic_pointer_cast<
55 GeomDataAPI_Point2D>(data()->attribute(START_ID()));
57 std::shared_ptr<GeomAPI_Pnt> aCenter(aSketch->to3D(aCenterAttr->x(), aCenterAttr->y()));
58 // make a visible point
59 std::shared_ptr<GeomAPI_Shape> aCenterPointShape = GeomAlgoAPI_PointBuilder::point(aCenter);
60 std::shared_ptr<ModelAPI_ResultConstruction> aConstr1 = document()->createConstruction(
62 aConstr1->setShape(aCenterPointShape);
63 aConstr1->setIsInHistory(false);
64 setResult(aConstr1, 0);
66 // make a visible circle
67 std::shared_ptr<GeomDataAPI_Dir> aNDir = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
68 aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
69 std::shared_ptr<GeomAPI_Dir> aNormal = aNDir->dir();
70 std::shared_ptr<GeomAPI_Pnt> aStartPoint(aSketch->to3D(aStartAttr->x(), aStartAttr->y()));
72 // compute and change the arc end point
73 std::shared_ptr<GeomDataAPI_Point2D> anEndAttr = std::dynamic_pointer_cast<
74 GeomDataAPI_Point2D>(data()->attribute(END_ID()));
75 /* must be automatically done in attributeChanged
76 std::shared_ptr<GeomAPI_Circ2d> aCircleForArc(
77 new GeomAPI_Circ2d(aCenterAttr->pnt(), aStartAttr->pnt()));
78 std::shared_ptr<GeomAPI_Pnt2d> aProjection = aCircleForArc->project(anEndAttr->pnt());
79 if (aProjection && anEndAttr->pnt()->distance(aProjection) > tolerance)
80 anEndAttr->setValue(aProjection);
82 std::shared_ptr<GeomAPI_Pnt> aEndPoint(aSketch->to3D(anEndAttr->x(), anEndAttr->y()));
84 std::shared_ptr<GeomAPI_Shape> aCircleShape = GeomAlgoAPI_EdgeBuilder::lineCircleArc(
85 aCenter, aStartPoint, aEndPoint, aNormal);
87 std::shared_ptr<ModelAPI_ResultConstruction> aConstr2 = document()->createConstruction(
89 aConstr2->setShape(aCircleShape);
90 aConstr2->setIsInHistory(false);
91 setResult(aConstr2, 1);
96 AISObjectPtr SketchPlugin_Arc::getAISObject(AISObjectPtr thePrevious)
98 SketchPlugin_Sketch* aSketch = sketch();
100 // if the feature is valid, the execute() method should be performed, AIS object is empty
101 if (!isFeatureValid()) {
102 // compute a circle point in 3D view
103 std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr = std::dynamic_pointer_cast<
104 GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
105 if (aCenterAttr->isInitialized()) {
106 std::shared_ptr<GeomAPI_Pnt> aCenter(aSketch->to3D(aCenterAttr->x(), aCenterAttr->y()));
108 std::shared_ptr<GeomDataAPI_Point2D> aStartAttr = std::dynamic_pointer_cast<
109 GeomDataAPI_Point2D>(data()->attribute(SketchPlugin_Arc::START_ID()));
110 if (aStartAttr->isInitialized()) {
111 // make a visible circle
112 std::shared_ptr<GeomDataAPI_Dir> aNDir = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
113 aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
114 bool aHasPlane = aNDir && !(aNDir->x() == 0 && aNDir->y() == 0 && aNDir->z() == 0);
116 std::shared_ptr<GeomAPI_Dir> aNormal = aNDir->dir();
117 std::shared_ptr<GeomAPI_Pnt> aStartPoint(aSketch->to3D(aStartAttr->x(), aStartAttr->y()));
118 std::shared_ptr<GeomAPI_Shape> aCircleShape = GeomAlgoAPI_EdgeBuilder::lineCircleArc(
119 aCenter, aStartPoint, aStartPoint, aNormal);
121 std::list<std::shared_ptr<GeomAPI_Shape> > aShapes;
122 // make a visible point
123 std::shared_ptr<GeomAPI_Shape> aCenterPointShape = GeomAlgoAPI_PointBuilder::point(aCenter);
124 aShapes.push_back(aCenterPointShape);
126 aShapes.push_back(aCircleShape);
127 if (!aShapes.empty())
129 std::shared_ptr<GeomAPI_Shape> aCompound = GeomAlgoAPI_CompoundBuilder::compound(aShapes);
130 AISObjectPtr anAIS = thePrevious;
132 anAIS = AISObjectPtr(new GeomAPI_AISObject);
133 anAIS->createShape(aCompound);
143 return AISObjectPtr();
146 void SketchPlugin_Arc::move(double theDeltaX, double theDeltaY)
148 std::shared_ptr<ModelAPI_Data> aData = data();
149 if (!aData->isValid())
152 myStartUpdate = 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);
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;
164 std::shared_ptr<GeomDataAPI_Point2D> aPoint1 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
165 aData->attribute(SketchPlugin_Arc::CENTER_ID()));
166 aPoint1->move(theDeltaX, theDeltaY);
169 double SketchPlugin_Arc::distanceToPoint(const std::shared_ptr<GeomAPI_Pnt2d>& thePoint)
172 std::shared_ptr<ModelAPI_Data> aData = data();
174 std::shared_ptr<GeomDataAPI_Point2D> aPoint1 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
175 aData->attribute(SketchPlugin_Arc::CENTER_ID()));
176 aDelta = aPoint1->pnt()->distance(thePoint);
178 std::shared_ptr<GeomDataAPI_Point2D> aPoint2 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
179 aData->attribute(SketchPlugin_Arc::START_ID()));
180 double aDistance = aPoint2->pnt()->distance(thePoint);
181 if (aDelta < aDistance)
184 std::shared_ptr<GeomDataAPI_Point2D> aPoint3 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
185 aData->attribute(SketchPlugin_Arc::END_ID()));
186 aDistance = aPoint3->pnt()->distance(thePoint);
187 if (aDelta < aDistance)
193 bool SketchPlugin_Arc::isFixed() {
194 return data()->selection(EXTERNAL_ID())->context().get() != NULL;
197 bool SketchPlugin_Arc::isFeatureValid()
199 std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr = std::dynamic_pointer_cast<
200 GeomDataAPI_Point2D>(data()->attribute(SketchPlugin_Arc::CENTER_ID()));
201 std::shared_ptr<GeomDataAPI_Point2D> aStartAttr = std::dynamic_pointer_cast<
202 GeomDataAPI_Point2D>(data()->attribute(SketchPlugin_Arc::START_ID()));
203 std::shared_ptr<GeomDataAPI_Point2D> anEndAttr = std::dynamic_pointer_cast<
204 GeomDataAPI_Point2D>(data()->attribute(SketchPlugin_Arc::END_ID()));
206 return aCenterAttr->isInitialized() && aStartAttr->isInitialized() && anEndAttr->isInitialized();
209 void SketchPlugin_Arc::attributeChanged(const std::string& theID)
211 std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr = std::dynamic_pointer_cast<
212 GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
213 std::shared_ptr<GeomDataAPI_Point2D> aStartAttr = std::dynamic_pointer_cast<
214 GeomDataAPI_Point2D>(data()->attribute(START_ID()));
215 std::shared_ptr<GeomDataAPI_Point2D> anEndAttr = std::dynamic_pointer_cast<
216 GeomDataAPI_Point2D>(data()->attribute(END_ID()));
217 if (theID == EXTERNAL_ID()) {
218 std::shared_ptr<GeomAPI_Shape> aSelection = data()->selection(EXTERNAL_ID())->value();
219 // update arguments due to the selection value
220 if (aSelection && !aSelection->isNull() && aSelection->isEdge()) {
221 std::shared_ptr<GeomAPI_Edge> anEdge( new GeomAPI_Edge(aSelection));
222 std::shared_ptr<GeomAPI_Circ> aCirc = anEdge->circle();
224 aStartAttr->setValue(sketch()->to2D(anEdge->firstPoint()));
225 anEndAttr->setValue(sketch()->to2D(anEdge->lastPoint()));
226 aCenterAttr->setValue(sketch()->to2D(aCirc->center()));
231 if (!aCenterAttr->isInitialized())
233 if (!aStartAttr->isInitialized())
235 if (!anEndAttr->isInitialized())
238 // update the points in accordance to the changed point changes
239 if (theID == END_ID() && !myEndUpdate) {
241 // compute and change the arc end point
242 std::shared_ptr<GeomAPI_Circ2d> aCircleForArc(
243 new GeomAPI_Circ2d(aCenterAttr->pnt(), aStartAttr->pnt()));
244 std::shared_ptr<GeomAPI_Pnt2d> aProjection = aCircleForArc->project(anEndAttr->pnt());
245 if (aProjection && anEndAttr->pnt()->distance(aProjection) > tolerance)
246 anEndAttr->setValue(aProjection);
248 } else if (theID == START_ID() && !myStartUpdate) {
249 myStartUpdate = true;
250 // compute and change the arc end point
251 std::shared_ptr<GeomAPI_Circ2d> aCircleForArc(
252 new GeomAPI_Circ2d(aCenterAttr->pnt(), anEndAttr->pnt()));
253 std::shared_ptr<GeomAPI_Pnt2d> aProjection = aCircleForArc->project(aStartAttr->pnt());
254 if (aProjection && aStartAttr->pnt()->distance(aProjection) > tolerance)
255 aStartAttr->setValue(aProjection);
256 myStartUpdate = false;
257 } else if (theID == CENTER_ID() && !myEndUpdate) {
259 // compute and change the arc end point
260 std::shared_ptr<GeomAPI_Circ2d> aCircleForArc(
261 new GeomAPI_Circ2d(aCenterAttr->pnt(), aStartAttr->pnt()));
262 std::shared_ptr<GeomAPI_Pnt2d> aProjection = aCircleForArc->project(anEndAttr->pnt());
263 if (aProjection && anEndAttr->pnt()->distance(aProjection) > tolerance)
264 anEndAttr->setValue(aProjection);