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()
53 void SketchPlugin_MacroCircle::initAttributes()
55 data()->addAttribute(CIRCLE_TYPE(), ModelAPI_AttributeString::typeId());
57 data()->addAttribute(CENTER_POINT_ID(), GeomDataAPI_Point2D::typeId());
58 data()->addAttribute(CENTER_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
59 data()->addAttribute(PASSED_POINT_ID(), GeomDataAPI_Point2D::typeId());
60 data()->addAttribute(PASSED_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
62 data()->addAttribute(FIRST_POINT_ID(), GeomDataAPI_Point2D::typeId());
63 data()->addAttribute(SECOND_POINT_ID(), GeomDataAPI_Point2D::typeId());
64 data()->addAttribute(THIRD_POINT_ID(), GeomDataAPI_Point2D::typeId());
65 data()->addAttribute(FIRST_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
66 data()->addAttribute(SECOND_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
67 data()->addAttribute(THIRD_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
69 data()->addAttribute(CIRCLE_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
70 data()->addAttribute(AUXILIARY_ID(), ModelAPI_AttributeBoolean::typeId());
72 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CENTER_POINT_REF_ID());
73 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PASSED_POINT_REF_ID());
74 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), FIRST_POINT_REF_ID());
75 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SECOND_POINT_REF_ID());
76 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), THIRD_POINT_REF_ID());
79 void SketchPlugin_MacroCircle::execute()
81 std::string aType = string(CIRCLE_TYPE())->value();
82 if (aType == CIRCLE_TYPE_BY_CENTER_AND_PASSED_POINTS())
83 createCircleByCenterAndPassed();
84 else if (aType == CIRCLE_TYPE_BY_THREE_POINTS())
85 createCircleByThreePoints();
88 void SketchPlugin_MacroCircle::createCircleByCenterAndPassed()
90 // Create circle feature.
91 std::shared_ptr<GeomAPI_Circ2d> aCircle = shapeByCenterAndPassed();
92 FeaturePtr aCircleFeature = createCircleFeature(aCircle);
94 // Create constraints.
95 SketchPlugin_Tools::createConstraint(this,
96 CENTER_POINT_REF_ID(),
97 aCircleFeature->attribute(SketchPlugin_Circle::CENTER_ID()),
100 SketchPlugin_Tools::createConstraint(this,
101 PASSED_POINT_REF_ID(),
103 aCircleFeature->lastResult(),
107 void SketchPlugin_MacroCircle::createCircleByThreePoints()
109 std::string aPointRef[3] = { FIRST_POINT_REF_ID(),
110 SECOND_POINT_REF_ID(),
111 THIRD_POINT_REF_ID() };
113 // Create circle feature.
114 std::shared_ptr<GeomAPI_Circ2d> aCircle = shapeByThreePoints();
115 FeaturePtr aCircleFeature = createCircleFeature(aCircle);
116 ResultPtr aCircleResult = aCircleFeature->lastResult();
118 // Create constraints.
119 for (int i = 0; i < 3; ++i)
120 SketchPlugin_Tools::createConstraint(this, aPointRef[i], AttributePtr(), aCircleResult, true);
123 FeaturePtr SketchPlugin_MacroCircle::createCircleFeature(
124 const std::shared_ptr<GeomAPI_Circ2d>& theCircle)
126 FeaturePtr aCircleFeature = sketch()->addFeature(SketchPlugin_Circle::ID());
127 std::shared_ptr<GeomAPI_Pnt2d> aCenter = theCircle->center();
128 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
129 aCircleFeature->attribute(SketchPlugin_Circle::CENTER_ID()))->setValue(aCenter->x(),
131 aCircleFeature->real(SketchPlugin_Circle::RADIUS_ID())->setValue(theCircle->radius());
132 aCircleFeature->boolean(SketchPlugin_Circle::AUXILIARY_ID())
133 ->setValue(boolean(AUXILIARY_ID())->value());
134 aCircleFeature->execute();
135 return aCircleFeature;
138 std::shared_ptr<GeomAPI_Circ2d> SketchPlugin_MacroCircle::shapeByCenterAndPassed()
140 AttributePtr aCenterAttr = attribute(CENTER_POINT_ID());
141 AttributePtr aPassedAttr = attribute(PASSED_POINT_ID());
142 if (!aCenterAttr->isInitialized() || !aPassedAttr->isInitialized())
143 return std::shared_ptr<GeomAPI_Circ2d>();
145 AttributeRefAttrPtr aPassedRef = refattr(PASSED_POINT_REF_ID());
146 // Calculate circle parameters
147 std::shared_ptr<GeomAPI_Pnt2d> aCenter =
148 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aCenterAttr)->pnt();
149 std::shared_ptr<GeomAPI_Pnt2d> aPassedPoint;
150 std::shared_ptr<GeomAPI_Shape> aTangentCurve;
151 SketchPlugin_Tools::convertRefAttrToPointOrTangentCurve(
152 aPassedRef, aPassedAttr, aTangentCurve, aPassedPoint);
155 std::shared_ptr<GeomAPI_Circ2d> aCircle;
157 std::shared_ptr<GeomAPI_Ax3> anAxis = SketchPlugin_Sketch::plane(sketch());
158 aCircle = std::shared_ptr<GeomAPI_Circ2d>(new GeomAPI_Circ2d(aCenter, aTangentCurve, anAxis));
160 aCircle = std::shared_ptr<GeomAPI_Circ2d>(new GeomAPI_Circ2d(aCenter, aPassedPoint));
164 std::shared_ptr<GeomAPI_Circ2d> SketchPlugin_MacroCircle::shapeByThreePoints()
166 std::string aPointAttr[3] = { FIRST_POINT_ID(),
169 std::string aPointRef[3] = { FIRST_POINT_REF_ID(),
170 SECOND_POINT_REF_ID(),
171 THIRD_POINT_REF_ID() };
172 std::shared_ptr<GeomAPI_Interface> aPassedEntities[3];
173 for (int aPntIndex = 0; aPntIndex < 3; ++aPntIndex) {
174 AttributePtr aPassedAttr = attribute(aPointAttr[aPntIndex]);
175 if (!aPassedAttr->isInitialized())
178 AttributeRefAttrPtr aPassedRef = refattr(aPointRef[aPntIndex]);
179 // calculate circle parameters
180 std::shared_ptr<GeomAPI_Pnt2d> aPassedPoint;
181 std::shared_ptr<GeomAPI_Shape> aTangentCurve;
182 SketchPlugin_Tools::convertRefAttrToPointOrTangentCurve(
183 aPassedRef, aPassedAttr, aTangentCurve, aPassedPoint);
186 aPassedEntities[aPntIndex] = aPassedPoint;
188 aPassedEntities[aPntIndex] = aTangentCurve;
191 std::shared_ptr<GeomAPI_Ax3> anAxis = SketchPlugin_Sketch::plane(sketch());
192 std::shared_ptr<GeomAPI_Circ2d> aCircle = std::shared_ptr<GeomAPI_Circ2d>(
193 new GeomAPI_Circ2d(aPassedEntities[0], aPassedEntities[1], aPassedEntities[2], anAxis));
194 if (!aCircle->implPtr<char>())
195 return std::shared_ptr<GeomAPI_Circ2d>();
199 std::shared_ptr<GeomAPI_Circ2d> SketchPlugin_MacroCircle::shapeByTwoPassedPoints()
201 std::string aPointAttr[2] = { FIRST_POINT_ID(),
203 std::string aPointRef[2] = { FIRST_POINT_REF_ID(),
204 SECOND_POINT_REF_ID() };
205 std::shared_ptr<GeomAPI_Pnt2d> aPassedPoints[2]; // there is possible only two passed points
206 std::shared_ptr<GeomAPI_Interface> aPassedEntities[3];
208 for (; aPntIndex < 2; ++aPntIndex) {
209 AttributePtr aPassedAttr = attribute(aPointAttr[aPntIndex]);
210 if (!aPassedAttr->isInitialized())
213 AttributeRefAttrPtr aPassedRef = refattr(aPointRef[aPntIndex]);
214 // calculate circle parameters
215 std::shared_ptr<GeomAPI_Pnt2d> aPassedPoint;
216 std::shared_ptr<GeomAPI_Shape> aTangentCurve;
217 SketchPlugin_Tools::convertRefAttrToPointOrTangentCurve(
218 aPassedRef, aPassedAttr, aTangentCurve, aPassedPoint);
221 aPassedEntities[aPntIndex] = aPassedPoint;
222 aPassedPoints[aPntIndex] = aPassedPoint;
224 aPassedEntities[aPntIndex] = aTangentCurve;
225 // if the circle is tangent to any curve,
226 // the third point will be initialized by the tangent point
227 aPassedEntities[2] = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aPassedAttr)->pnt();
231 return std::shared_ptr<GeomAPI_Circ2d>();
233 std::shared_ptr<GeomAPI_Circ2d> aCircle;
234 if (aPassedEntities[2]) {
235 std::shared_ptr<GeomAPI_Ax3> anAxis = SketchPlugin_Sketch::plane(sketch());
236 aCircle = std::shared_ptr<GeomAPI_Circ2d>(
237 new GeomAPI_Circ2d(aPassedEntities[0], aPassedEntities[1], aPassedEntities[2], anAxis));
239 // the circle is defined by two points, calculate its parameters manually
240 std::shared_ptr<GeomAPI_Pnt2d> aCenter(new GeomAPI_Pnt2d(
241 (aPassedPoints[0]->x() + aPassedPoints[1]->x()) * 0.5,
242 (aPassedPoints[0]->y() + aPassedPoints[1]->y()) * 0.5));
243 aCircle = std::shared_ptr<GeomAPI_Circ2d>(new GeomAPI_Circ2d(aCenter, aPassedPoints[0]));
245 if (!aCircle->implPtr<char>())
246 return std::shared_ptr<GeomAPI_Circ2d>();
250 AISObjectPtr SketchPlugin_MacroCircle::getAISObject(AISObjectPtr thePrevious)
252 SketchPlugin_Sketch* aSketch = sketch();
254 return AISObjectPtr();
257 // Create circle on the sketch plane
258 std::shared_ptr<GeomAPI_Circ2d> aCircleOnSketch;
259 std::string aType = string(CIRCLE_TYPE())->value();
260 if (aType == CIRCLE_TYPE_BY_CENTER_AND_PASSED_POINTS())
261 aCircleOnSketch = shapeByCenterAndPassed();
262 else if (aType == CIRCLE_TYPE_BY_THREE_POINTS()) {
263 if (attribute(THIRD_POINT_ID())->isInitialized())
264 aCircleOnSketch = shapeByThreePoints();
266 aCircleOnSketch = shapeByTwoPassedPoints();
269 if (!aCircleOnSketch)
270 return AISObjectPtr();
272 std::shared_ptr<GeomAPI_Pnt2d> aCenter2D = aCircleOnSketch->center();
273 double aRadius = aCircleOnSketch->radius();
275 // Compute a circle in 3D view.
276 std::shared_ptr<GeomAPI_Pnt> aCenter(aSketch->to3D(aCenter2D->x(), aCenter2D->y()));
277 std::shared_ptr<GeomDataAPI_Dir> aNDir =
278 std::dynamic_pointer_cast<GeomDataAPI_Dir>(
279 aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
280 std::shared_ptr<GeomAPI_Dir> aNormal = aNDir->dir();
281 GeomShapePtr aCircleShape = GeomAlgoAPI_EdgeBuilder::lineCircle(aCenter, aNormal, aRadius);
282 GeomShapePtr aCenterPointShape = GeomAlgoAPI_PointBuilder::vertex(aCenter);
283 if(!aCircleShape.get() || !aCenterPointShape.get()) {
284 return AISObjectPtr();
287 std::list<std::shared_ptr<GeomAPI_Shape> > aShapes;
288 aShapes.push_back(aCircleShape);
289 aShapes.push_back(aCenterPointShape);
291 std::shared_ptr<GeomAPI_Shape> aCompound = GeomAlgoAPI_CompoundBuilder::compound(aShapes);
292 AISObjectPtr anAIS = thePrevious;
294 anAIS.reset(new GeomAPI_AISObject());
296 anAIS->createShape(aCompound);
300 void SketchPlugin_MacroCircle::attributeChanged(const std::string& theID) {
301 double aRadius = 0.0;
302 // If circle type switched reset all attributes.
303 if(theID == CIRCLE_TYPE()) {
304 SketchPlugin_Tools::resetAttribute(this, CENTER_POINT_ID());
305 SketchPlugin_Tools::resetAttribute(this, CENTER_POINT_REF_ID());
306 SketchPlugin_Tools::resetAttribute(this, PASSED_POINT_ID());
307 SketchPlugin_Tools::resetAttribute(this, PASSED_POINT_REF_ID());
308 SketchPlugin_Tools::resetAttribute(this, FIRST_POINT_ID());
309 SketchPlugin_Tools::resetAttribute(this, FIRST_POINT_REF_ID());
310 SketchPlugin_Tools::resetAttribute(this, SECOND_POINT_ID());
311 SketchPlugin_Tools::resetAttribute(this, SECOND_POINT_REF_ID());
312 SketchPlugin_Tools::resetAttribute(this, THIRD_POINT_ID());
313 SketchPlugin_Tools::resetAttribute(this, THIRD_POINT_REF_ID());
314 } else if(theID == CENTER_POINT_ID() || theID == PASSED_POINT_ID()) {
315 std::shared_ptr<GeomDataAPI_Point2D> aCenterPointAttr =
316 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(CENTER_POINT_ID()));
317 if(!aCenterPointAttr->isInitialized()) {
320 std::shared_ptr<GeomDataAPI_Point2D> aPassedPointAttr =
321 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(PASSED_POINT_ID()));
322 if(!aPassedPointAttr->isInitialized()) {
326 aRadius = aCenterPointAttr->pnt()->distance(aPassedPointAttr->pnt());
327 } else if(theID == FIRST_POINT_ID() || theID == SECOND_POINT_ID() || theID == THIRD_POINT_ID()) {
328 std::shared_ptr<GeomAPI_Pnt2d> aPoints[3];
329 int aNbInitialized = 0;
330 for(int i = 1; i <= 3; ++i) {
331 std::shared_ptr<GeomDataAPI_Point2D> aCurPnt =
332 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(POINT_ID(i)));
333 if(aCurPnt->isInitialized())
334 aPoints[aNbInitialized++] = aCurPnt->pnt();
337 std::shared_ptr<GeomAPI_Circ2d> aCircle;
338 if(aNbInitialized == 1)
340 else if(aNbInitialized == 2)
341 aCircle = shapeByTwoPassedPoints();
343 aCircle = shapeByThreePoints();
345 aRadius = aCircle->radius();
348 AttributeDoublePtr aRadiusAttr = real(CIRCLE_RADIUS_ID());
349 bool aWasBlocked = data()->blockSendAttributeUpdated(true);
350 aRadiusAttr->setValue(aRadius);
351 data()->blockSendAttributeUpdated(aWasBlocked, false);