1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
3 // File: SketchPlugin_MacroCircle.cpp
4 // Created: 26 May 2014
5 // Author: Artem ZHIDKOV
7 #include "SketchPlugin_MacroCircle.h"
9 #include "SketchPlugin_Circle.h"
10 #include "SketchPlugin_Point.h"
11 #include "SketchPlugin_Tools.h"
13 #include <ModelAPI_AttributeDouble.h>
14 #include <ModelAPI_AttributeRefAttr.h>
15 #include <ModelAPI_AttributeString.h>
16 #include <ModelAPI_Session.h>
17 #include <ModelAPI_Validator.h>
19 #include <GeomDataAPI_Dir.h>
20 #include <GeomDataAPI_Point2D.h>
22 #include <GeomAPI_Circ2d.h>
23 #include <GeomAPI_Pnt2d.h>
24 #include <GeomAPI_Vertex.h>
26 #include <GeomAlgoAPI_CompoundBuilder.h>
27 #include <GeomAlgoAPI_EdgeBuilder.h>
28 #include <GeomAlgoAPI_PointBuilder.h>
31 const double tolerance = 1e-7;
34 static const std::string& POINT_ID(int theIndex)
37 case 1: return SketchPlugin_MacroCircle::FIRST_POINT_ID();
38 case 2: return SketchPlugin_MacroCircle::SECOND_POINT_ID();
39 case 3: return SketchPlugin_MacroCircle::THIRD_POINT_ID();
42 static const std::string DUMMY;
48 SketchPlugin_MacroCircle::SketchPlugin_MacroCircle()
49 : SketchPlugin_SketchEntity(),
54 void SketchPlugin_MacroCircle::initAttributes()
56 data()->addAttribute(CIRCLE_TYPE(), ModelAPI_AttributeString::typeId());
58 data()->addAttribute(CENTER_POINT_ID(), GeomDataAPI_Point2D::typeId());
59 data()->addAttribute(CENTER_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
60 data()->addAttribute(PASSED_POINT_ID(), GeomDataAPI_Point2D::typeId());
61 data()->addAttribute(PASSED_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
63 data()->addAttribute(FIRST_POINT_ID(), GeomDataAPI_Point2D::typeId());
64 data()->addAttribute(SECOND_POINT_ID(), GeomDataAPI_Point2D::typeId());
65 data()->addAttribute(THIRD_POINT_ID(), GeomDataAPI_Point2D::typeId());
66 data()->addAttribute(FIRST_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
67 data()->addAttribute(SECOND_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
68 data()->addAttribute(THIRD_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
70 data()->addAttribute(CIRCLE_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
71 data()->addAttribute(AUXILIARY_ID(), ModelAPI_AttributeBoolean::typeId());
73 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CENTER_POINT_REF_ID());
74 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PASSED_POINT_REF_ID());
75 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), FIRST_POINT_REF_ID());
76 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SECOND_POINT_REF_ID());
77 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), THIRD_POINT_REF_ID());
80 void SketchPlugin_MacroCircle::execute()
82 FeaturePtr aCircle = createCircleFeature();
84 std::string aType = string(CIRCLE_TYPE())->value();
85 if (aType == CIRCLE_TYPE_BY_CENTER_AND_PASSED_POINTS())
86 constraintsForCircleByCenterAndPassed(aCircle);
87 else if (aType == CIRCLE_TYPE_BY_THREE_POINTS())
88 constraintsForCircleByThreePoints(aCircle);
91 void SketchPlugin_MacroCircle::constraintsForCircleByCenterAndPassed(FeaturePtr theCircleFeature)
93 // Create constraints.
94 SketchPlugin_Tools::createConstraint(
95 this, CENTER_POINT_REF_ID(),
96 theCircleFeature->attribute(SketchPlugin_Circle::CENTER_ID()),
98 SketchPlugin_Tools::createConstraint(
99 this, PASSED_POINT_REF_ID(), AttributePtr(),
100 theCircleFeature->lastResult(), true);
103 void SketchPlugin_MacroCircle::constraintsForCircleByThreePoints(FeaturePtr theCircleFeature)
105 std::string aPointRef[3] = { FIRST_POINT_REF_ID(),
106 SECOND_POINT_REF_ID(),
107 THIRD_POINT_REF_ID() };
109 // Create constraints.
110 ResultPtr aCircleResult = theCircleFeature->lastResult();
111 for (int i = 0; i < 3; ++i)
112 SketchPlugin_Tools::createConstraint(this, aPointRef[i], AttributePtr(), aCircleResult, true);
115 FeaturePtr SketchPlugin_MacroCircle::createCircleFeature()
117 FeaturePtr aCircleFeature = sketch()->addFeature(SketchPlugin_Circle::ID());
118 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
119 aCircleFeature->attribute(SketchPlugin_Circle::CENTER_ID()))->setValue(myCenter->x(),
121 aCircleFeature->real(SketchPlugin_Circle::RADIUS_ID())->setValue(myRadius);
122 aCircleFeature->boolean(SketchPlugin_Circle::AUXILIARY_ID())
123 ->setValue(boolean(AUXILIARY_ID())->value());
124 aCircleFeature->execute();
125 return aCircleFeature;
128 void SketchPlugin_MacroCircle::fillByCenterAndPassed()
130 AttributePtr aCenterAttr = attribute(CENTER_POINT_ID());
131 AttributePtr aPassedAttr = attribute(PASSED_POINT_ID());
132 if (!aCenterAttr->isInitialized() || !aPassedAttr->isInitialized())
135 AttributeRefAttrPtr aPassedRef = refattr(PASSED_POINT_REF_ID());
136 // Calculate circle parameters
137 std::shared_ptr<GeomAPI_Pnt2d> aCenter =
138 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aCenterAttr)->pnt();
139 std::shared_ptr<GeomAPI_Pnt2d> aPassedPoint;
140 std::shared_ptr<GeomAPI_Shape> aTangentCurve;
141 SketchPlugin_Tools::convertRefAttrToPointOrTangentCurve(
142 aPassedRef, aPassedAttr, aTangentCurve, aPassedPoint);
145 std::shared_ptr<GeomAPI_Circ2d> aCircle;
147 std::shared_ptr<GeomAPI_Ax3> anAxis = SketchPlugin_Sketch::plane(sketch());
148 aCircle = std::shared_ptr<GeomAPI_Circ2d>(new GeomAPI_Circ2d(aCenter, aTangentCurve, anAxis));
150 aCircle = std::shared_ptr<GeomAPI_Circ2d>(new GeomAPI_Circ2d(aCenter, aPassedPoint));
151 if (aCircle->implPtr<char>()) {
152 myCenter = aCircle->center();
153 myRadius = aCircle->radius();
157 void SketchPlugin_MacroCircle::fillByThreePoints()
159 std::string aPointAttr[3] = { FIRST_POINT_ID(),
162 std::string aPointRef[3] = { FIRST_POINT_REF_ID(),
163 SECOND_POINT_REF_ID(),
164 THIRD_POINT_REF_ID() };
165 std::shared_ptr<GeomAPI_Interface> aPassedEntities[3];
166 for (int aPntIndex = 0; aPntIndex < 3; ++aPntIndex) {
167 AttributePtr aPassedAttr = attribute(aPointAttr[aPntIndex]);
168 if (!aPassedAttr->isInitialized())
171 AttributeRefAttrPtr aPassedRef = refattr(aPointRef[aPntIndex]);
172 // calculate circle parameters
173 std::shared_ptr<GeomAPI_Pnt2d> aPassedPoint;
174 std::shared_ptr<GeomAPI_Shape> aTangentCurve;
175 SketchPlugin_Tools::convertRefAttrToPointOrTangentCurve(
176 aPassedRef, aPassedAttr, aTangentCurve, aPassedPoint);
179 aPassedEntities[aPntIndex] = aPassedPoint;
181 aPassedEntities[aPntIndex] = aTangentCurve;
184 std::shared_ptr<GeomAPI_Ax3> anAxis = SketchPlugin_Sketch::plane(sketch());
185 std::shared_ptr<GeomAPI_Circ2d> aCircle = std::shared_ptr<GeomAPI_Circ2d>(
186 new GeomAPI_Circ2d(aPassedEntities[0], aPassedEntities[1], aPassedEntities[2], anAxis));
187 if (aCircle->implPtr<char>()) {
188 myCenter = aCircle->center();
189 myRadius = aCircle->radius();
193 void SketchPlugin_MacroCircle::fillByTwoPassedPoints()
195 std::string aPointAttr[2] = { FIRST_POINT_ID(),
197 std::string aPointRef[2] = { FIRST_POINT_REF_ID(),
198 SECOND_POINT_REF_ID() };
199 std::shared_ptr<GeomAPI_Pnt2d> aPassedPoints[2]; // there is possible only two passed points
200 std::shared_ptr<GeomAPI_Interface> aPassedEntities[3];
202 for (; aPntIndex < 2; ++aPntIndex) {
203 AttributePtr aPassedAttr = attribute(aPointAttr[aPntIndex]);
204 if (!aPassedAttr->isInitialized())
207 AttributeRefAttrPtr aPassedRef = refattr(aPointRef[aPntIndex]);
208 // calculate circle parameters
209 std::shared_ptr<GeomAPI_Pnt2d> aPassedPoint;
210 std::shared_ptr<GeomAPI_Shape> aTangentCurve;
211 SketchPlugin_Tools::convertRefAttrToPointOrTangentCurve(
212 aPassedRef, aPassedAttr, aTangentCurve, aPassedPoint);
215 aPassedEntities[aPntIndex] = aPassedPoint;
216 aPassedPoints[aPntIndex] = aPassedPoint;
218 aPassedEntities[aPntIndex] = aTangentCurve;
219 // if the circle is tangent to any curve,
220 // the third point will be initialized by the tangent point
221 aPassedEntities[2] = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aPassedAttr)->pnt();
227 std::shared_ptr<GeomAPI_Circ2d> aCircle;
228 if (aPassedEntities[2]) {
229 std::shared_ptr<GeomAPI_Ax3> anAxis = SketchPlugin_Sketch::plane(sketch());
230 aCircle = std::shared_ptr<GeomAPI_Circ2d>(
231 new GeomAPI_Circ2d(aPassedEntities[0], aPassedEntities[1], aPassedEntities[2], anAxis));
233 // the circle is defined by two points, calculate its parameters manually
234 std::shared_ptr<GeomAPI_Pnt2d> aCenter(new GeomAPI_Pnt2d(
235 (aPassedPoints[0]->x() + aPassedPoints[1]->x()) * 0.5,
236 (aPassedPoints[0]->y() + aPassedPoints[1]->y()) * 0.5));
237 aCircle = std::shared_ptr<GeomAPI_Circ2d>(new GeomAPI_Circ2d(aCenter, aPassedPoints[0]));
239 if (aCircle->implPtr<char>()) {
240 myCenter = aCircle->center();
241 myRadius = aCircle->radius();
245 AISObjectPtr SketchPlugin_MacroCircle::getAISObject(AISObjectPtr thePrevious)
247 SketchPlugin_Sketch* aSketch = sketch();
248 if(!aSketch || !myCenter || myRadius == 0) {
249 return AISObjectPtr();
252 // Compute a circle in 3D view.
253 std::shared_ptr<GeomAPI_Pnt> aCenter(aSketch->to3D(myCenter->x(), myCenter->y()));
254 std::shared_ptr<GeomDataAPI_Dir> aNDir =
255 std::dynamic_pointer_cast<GeomDataAPI_Dir>(
256 aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
257 std::shared_ptr<GeomAPI_Dir> aNormal = aNDir->dir();
258 GeomShapePtr aCircleShape = GeomAlgoAPI_EdgeBuilder::lineCircle(aCenter, aNormal, myRadius);
259 GeomShapePtr aCenterPointShape = GeomAlgoAPI_PointBuilder::vertex(aCenter);
260 if(!aCircleShape.get() || !aCenterPointShape.get()) {
261 return AISObjectPtr();
264 std::list<std::shared_ptr<GeomAPI_Shape> > aShapes;
265 aShapes.push_back(aCircleShape);
266 aShapes.push_back(aCenterPointShape);
268 std::shared_ptr<GeomAPI_Shape> aCompound = GeomAlgoAPI_CompoundBuilder::compound(aShapes);
269 AISObjectPtr anAIS = thePrevious;
271 anAIS.reset(new GeomAPI_AISObject());
273 anAIS->createShape(aCompound);
277 void SketchPlugin_MacroCircle::attributeChanged(const std::string& theID) {
278 double aRadius = 0.0;
279 // If circle type switched reset all attributes.
280 if(theID == CIRCLE_TYPE()) {
281 SketchPlugin_Tools::resetAttribute(this, CENTER_POINT_ID());
282 SketchPlugin_Tools::resetAttribute(this, CENTER_POINT_REF_ID());
283 SketchPlugin_Tools::resetAttribute(this, PASSED_POINT_ID());
284 SketchPlugin_Tools::resetAttribute(this, PASSED_POINT_REF_ID());
285 SketchPlugin_Tools::resetAttribute(this, FIRST_POINT_ID());
286 SketchPlugin_Tools::resetAttribute(this, FIRST_POINT_REF_ID());
287 SketchPlugin_Tools::resetAttribute(this, SECOND_POINT_ID());
288 SketchPlugin_Tools::resetAttribute(this, SECOND_POINT_REF_ID());
289 SketchPlugin_Tools::resetAttribute(this, THIRD_POINT_ID());
290 SketchPlugin_Tools::resetAttribute(this, THIRD_POINT_REF_ID());
291 } else if(theID == CENTER_POINT_ID() || theID == PASSED_POINT_ID() ||
292 theID == CENTER_POINT_REF_ID() || theID == PASSED_POINT_REF_ID())
293 fillByCenterAndPassed();
294 else if(theID == FIRST_POINT_ID() || theID == FIRST_POINT_REF_ID() ||
295 theID == SECOND_POINT_ID() || theID == SECOND_POINT_REF_ID() ||
296 theID == THIRD_POINT_ID() || theID == THIRD_POINT_REF_ID()) {
297 std::shared_ptr<GeomAPI_Pnt2d> aPoints[3];
298 int aNbInitialized = 0;
299 for(int i = 1; i <= 3; ++i) {
300 std::shared_ptr<GeomDataAPI_Point2D> aCurPnt =
301 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(POINT_ID(i)));
302 if(aCurPnt->isInitialized())
303 aPoints[aNbInitialized++] = aCurPnt->pnt();
306 if(aNbInitialized == 1)
308 else if(aNbInitialized == 2)
309 fillByTwoPassedPoints();
314 AttributeDoublePtr aRadiusAttr = real(CIRCLE_RADIUS_ID());
315 bool aWasBlocked = data()->blockSendAttributeUpdated(true);
316 aRadiusAttr->setValue(myRadius);
317 data()->blockSendAttributeUpdated(aWasBlocked, false);