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_Ax2.h>
16 #include <GeomAPI_Circ2d.h>
17 #include <GeomAPI_Circ.h>
18 #include <GeomAPI_Pnt2d.h>
19 #include <GeomDataAPI_Point2D.h>
20 #include <GeomDataAPI_Dir.h>
21 #include <GeomAlgoAPI_PointBuilder.h>
22 #include <GeomAlgoAPI_EdgeBuilder.h>
23 #include <GeomAlgoAPI_CompoundBuilder.h>
27 const double tolerance = 1e-7;
28 const double paramTolerance = 1.e-4;
29 const double PI =3.141592653589793238463;
32 SketchPlugin_Arc::SketchPlugin_Arc()
33 : SketchPlugin_SketchEntity()
35 myStartUpdate = false;
44 void SketchPlugin_Arc::initDerivedClassAttributes()
46 data()->addAttribute(CENTER_ID(), GeomDataAPI_Point2D::typeId());
47 data()->addAttribute(START_ID(), GeomDataAPI_Point2D::typeId());
48 std::shared_ptr<GeomDataAPI_Point2D> anEndAttr = std::dynamic_pointer_cast<
49 GeomDataAPI_Point2D>(data()->addAttribute(END_ID(), GeomDataAPI_Point2D::typeId()));
50 data()->addAttribute(EXTERNAL_ID(), ModelAPI_AttributeSelection::typeId());
51 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EXTERNAL_ID());
53 data()->addAttribute(INVERSED_ID(), ModelAPI_AttributeBoolean::typeId());
54 AttributeBooleanPtr isInversed =
55 std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(attribute(INVERSED_ID()));
56 if (!isInversed->isInitialized())
57 isInversed->setValue(false);
59 // get the initial values
60 if (anEndAttr->isInitialized()) {
61 myXEndBefore = anEndAttr->x();
62 myYEndBefore = anEndAttr->y();
66 void SketchPlugin_Arc::execute()
68 SketchPlugin_Sketch* aSketch = sketch();
69 // result for the arc is set only when all obligatory attributes are initialized,
70 // otherwise AIS object is used to visualize the arc's preview
71 if (aSketch && isFeatureValid()) {
72 // compute a circle point in 3D view
73 std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr = std::dynamic_pointer_cast<
74 GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
75 // compute the arc start point
76 std::shared_ptr<GeomDataAPI_Point2D> aStartAttr = std::dynamic_pointer_cast<
77 GeomDataAPI_Point2D>(data()->attribute(START_ID()));
79 std::shared_ptr<GeomAPI_Pnt> aCenter(aSketch->to3D(aCenterAttr->x(), aCenterAttr->y()));
80 // make a visible point
81 std::shared_ptr<GeomAPI_Shape> aCenterPointShape = GeomAlgoAPI_PointBuilder::point(aCenter);
82 std::shared_ptr<ModelAPI_ResultConstruction> aConstr1 = document()->createConstruction(
84 aConstr1->setShape(aCenterPointShape);
85 aConstr1->setIsInHistory(false);
86 setResult(aConstr1, 0);
88 // make a visible circle
89 std::shared_ptr<GeomDataAPI_Dir> aNDir = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
90 aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
91 std::shared_ptr<GeomAPI_Dir> aNormal = aNDir->dir();
92 std::shared_ptr<GeomAPI_Pnt> aStartPoint(aSketch->to3D(aStartAttr->x(), aStartAttr->y()));
94 // compute and change the arc end point
95 std::shared_ptr<GeomDataAPI_Point2D> anEndAttr = std::dynamic_pointer_cast<
96 GeomDataAPI_Point2D>(data()->attribute(END_ID()));
97 std::shared_ptr<GeomAPI_Circ2d> aCircleForArc(
98 new GeomAPI_Circ2d(aCenterAttr->pnt(), aStartAttr->pnt()));
99 std::shared_ptr<GeomAPI_Pnt2d> aProjection = aCircleForArc->project(anEndAttr->pnt());
100 if (aProjection && anEndAttr->pnt()->distance(aProjection) > tolerance)
101 anEndAttr->setValue(aProjection);
102 std::shared_ptr<GeomAPI_Pnt> aEndPoint(aSketch->to3D(anEndAttr->x(), anEndAttr->y()));
103 AttributeBooleanPtr isInversed =
104 std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(attribute(INVERSED_ID()));
106 std::shared_ptr<GeomAPI_Dir> anXDir(new GeomAPI_Dir(aStartPoint->xyz()->decreased(aCenter->xyz())));
107 std::shared_ptr<GeomAPI_Ax2> anAx2(new GeomAPI_Ax2(aCenter, aNormal, anXDir));
108 std::shared_ptr<GeomAPI_Circ> aCirc(new GeomAPI_Circ(anAx2, aCenter->distance(aStartPoint)));
109 double aParameterNew = 0.0;
110 if(aCirc->parameter(aEndPoint, paramTolerance, aParameterNew)) {
111 if(0 <= myParamBefore && myParamBefore <= PI / 2.0
112 && PI * 1.5 <= aParameterNew && aParameterNew <= PI * 2.0) {
113 isInversed->setValue(true);
114 } else if(PI * 1.5 <= myParamBefore && myParamBefore <= PI * 2.0
115 && 0 <= aParameterNew && aParameterNew <= PI / 2.0) {
116 isInversed->setValue(false);
119 myParamBefore = aParameterNew;
121 std::shared_ptr<GeomAPI_Shape> aCircleShape;
122 if(!isInversed->value()) {
123 aCircleShape = GeomAlgoAPI_EdgeBuilder::lineCircleArc(aCenter, aStartPoint, aEndPoint, aNormal);
125 aCircleShape = GeomAlgoAPI_EdgeBuilder::lineCircleArc(aCenter, aEndPoint, aStartPoint, aNormal);
129 std::shared_ptr<ModelAPI_ResultConstruction> aConstr2 = document()->createConstruction(
131 aConstr2->setShape(aCircleShape);
132 aConstr2->setIsInHistory(false);
133 setResult(aConstr2, 1);
138 AISObjectPtr SketchPlugin_Arc::getAISObject(AISObjectPtr thePrevious)
140 SketchPlugin_Sketch* aSketch = sketch();
142 // if the feature is valid, the execute() method should be performed, AIS object is empty
143 if (!isFeatureValid()) {
144 // compute a circle point in 3D view
145 std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr = std::dynamic_pointer_cast<
146 GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
147 if (aCenterAttr->isInitialized()) {
148 std::shared_ptr<GeomAPI_Pnt> aCenter(aSketch->to3D(aCenterAttr->x(), aCenterAttr->y()));
150 std::shared_ptr<GeomDataAPI_Point2D> aStartAttr = std::dynamic_pointer_cast<
151 GeomDataAPI_Point2D>(data()->attribute(SketchPlugin_Arc::START_ID()));
152 if (aStartAttr->isInitialized()) {
153 // make a visible circle
154 std::shared_ptr<GeomDataAPI_Dir> aNDir = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
155 aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
156 bool aHasPlane = aNDir && !(aNDir->x() == 0 && aNDir->y() == 0 && aNDir->z() == 0);
158 std::shared_ptr<GeomAPI_Dir> aNormal = aNDir->dir();
159 std::shared_ptr<GeomAPI_Pnt> aStartPoint(aSketch->to3D(aStartAttr->x(), aStartAttr->y()));
160 std::shared_ptr<GeomAPI_Shape> aCircleShape = GeomAlgoAPI_EdgeBuilder::lineCircleArc(
161 aCenter, aStartPoint, aStartPoint, aNormal);
163 std::list<std::shared_ptr<GeomAPI_Shape> > aShapes;
164 // make a visible point
165 std::shared_ptr<GeomAPI_Shape> aCenterPointShape = GeomAlgoAPI_PointBuilder::point(aCenter);
166 aShapes.push_back(aCenterPointShape);
168 aShapes.push_back(aCircleShape);
169 if (!aShapes.empty())
171 std::shared_ptr<GeomAPI_Shape> aCompound = GeomAlgoAPI_CompoundBuilder::compound(aShapes);
172 AISObjectPtr anAIS = thePrevious;
174 anAIS = AISObjectPtr(new GeomAPI_AISObject);
175 anAIS->createShape(aCompound);
185 return AISObjectPtr();
188 void SketchPlugin_Arc::move(double theDeltaX, double theDeltaY)
190 std::shared_ptr<ModelAPI_Data> aData = data();
191 if (!aData->isValid())
194 myStartUpdate = true;
196 std::shared_ptr<GeomDataAPI_Point2D> aPoint2 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
197 aData->attribute(SketchPlugin_Arc::START_ID()));
198 aPoint2->move(theDeltaX, theDeltaY);
200 std::shared_ptr<GeomDataAPI_Point2D> aPoint3 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
201 aData->attribute(SketchPlugin_Arc::END_ID()));
202 aPoint3->move(theDeltaX, theDeltaY);
203 myStartUpdate = false;
206 std::shared_ptr<GeomDataAPI_Point2D> aPoint1 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
207 aData->attribute(SketchPlugin_Arc::CENTER_ID()));
208 aPoint1->move(theDeltaX, theDeltaY);
211 bool SketchPlugin_Arc::isFixed() {
212 return data()->selection(EXTERNAL_ID())->context().get() != NULL;
215 bool SketchPlugin_Arc::isFeatureValid()
217 std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr = std::dynamic_pointer_cast<
218 GeomDataAPI_Point2D>(data()->attribute(SketchPlugin_Arc::CENTER_ID()));
219 std::shared_ptr<GeomDataAPI_Point2D> aStartAttr = std::dynamic_pointer_cast<
220 GeomDataAPI_Point2D>(data()->attribute(SketchPlugin_Arc::START_ID()));
221 std::shared_ptr<GeomDataAPI_Point2D> anEndAttr = std::dynamic_pointer_cast<
222 GeomDataAPI_Point2D>(data()->attribute(SketchPlugin_Arc::END_ID()));
224 return aCenterAttr->isInitialized() && aStartAttr->isInitialized() && anEndAttr->isInitialized();
227 void SketchPlugin_Arc::attributeChanged(const std::string& theID)
229 std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr = std::dynamic_pointer_cast<
230 GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
231 std::shared_ptr<GeomDataAPI_Point2D> aStartAttr = std::dynamic_pointer_cast<
232 GeomDataAPI_Point2D>(data()->attribute(START_ID()));
233 std::shared_ptr<GeomDataAPI_Point2D> anEndAttr = std::dynamic_pointer_cast<
234 GeomDataAPI_Point2D>(data()->attribute(END_ID()));
235 // the second condition for unability to move external segments anywhere
236 if (theID == EXTERNAL_ID() || isFixed()) {
237 std::shared_ptr<GeomAPI_Shape> aSelection = data()->selection(EXTERNAL_ID())->value();
238 // update arguments due to the selection value
239 if (aSelection && !aSelection->isNull() && aSelection->isEdge()) {
240 std::shared_ptr<GeomAPI_Edge> anEdge( new GeomAPI_Edge(aSelection));
241 std::shared_ptr<GeomAPI_Circ> aCirc = anEdge->circle();
243 aStartAttr->setValue(sketch()->to2D(anEdge->firstPoint()));
244 anEndAttr->setValue(sketch()->to2D(anEdge->lastPoint()));
245 aCenterAttr->setValue(sketch()->to2D(aCirc->center()));
250 if (!isFeatureValid())
253 // update the points in accordance to the changed point changes
254 if (theID == CENTER_ID() && !myEndUpdate) {
256 // compute and change the arc end point
257 std::shared_ptr<GeomAPI_Circ2d> aCircleForArc(
258 new GeomAPI_Circ2d(aCenterAttr->pnt(), aStartAttr->pnt()));
259 std::shared_ptr<GeomAPI_Pnt2d> aProjection = aCircleForArc->project(anEndAttr->pnt());
260 if (aProjection && anEndAttr->pnt()->distance(aProjection) > tolerance)
261 anEndAttr->setValue(aProjection);
266 void SketchPlugin_Arc::setReversed(bool isReversed)
268 std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(attribute(INVERSED_ID()))->setValue(isReversed);
272 bool SketchPlugin_Arc::isReversed()
274 return std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(attribute(INVERSED_ID()))->value();