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_Circ.h>
25 #include <GeomAPI_Vertex.h>
26 #include <GeomAPI_XY.h>
28 #include <GeomAlgoAPI_CompoundBuilder.h>
29 #include <GeomAlgoAPI_EdgeBuilder.h>
30 #include <GeomAlgoAPI_PointBuilder.h>
33 const double tolerance = 1e-7;
36 static const std::string& POINT_ID(int theIndex)
39 case 1: return SketchPlugin_MacroCircle::FIRST_POINT_ID();
40 case 2: return SketchPlugin_MacroCircle::SECOND_POINT_ID();
41 case 3: return SketchPlugin_MacroCircle::THIRD_POINT_ID();
44 static const std::string DUMMY;
50 SketchPlugin_MacroCircle::SketchPlugin_MacroCircle()
51 : SketchPlugin_SketchEntity(),
56 void SketchPlugin_MacroCircle::initAttributes()
58 data()->addAttribute(CIRCLE_TYPE(), ModelAPI_AttributeString::typeId());
60 data()->addAttribute(CENTER_POINT_ID(), GeomDataAPI_Point2D::typeId());
61 data()->addAttribute(CENTER_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
62 data()->addAttribute(PASSED_POINT_ID(), GeomDataAPI_Point2D::typeId());
63 data()->addAttribute(PASSED_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
65 data()->addAttribute(FIRST_POINT_ID(), GeomDataAPI_Point2D::typeId());
66 data()->addAttribute(SECOND_POINT_ID(), GeomDataAPI_Point2D::typeId());
67 data()->addAttribute(THIRD_POINT_ID(), GeomDataAPI_Point2D::typeId());
68 data()->addAttribute(FIRST_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
69 data()->addAttribute(SECOND_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
70 data()->addAttribute(THIRD_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
72 data()->addAttribute(CIRCLE_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
73 data()->addAttribute(AUXILIARY_ID(), ModelAPI_AttributeBoolean::typeId());
75 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CENTER_POINT_REF_ID());
76 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PASSED_POINT_REF_ID());
77 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), FIRST_POINT_REF_ID());
78 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SECOND_POINT_REF_ID());
79 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), THIRD_POINT_REF_ID());
82 void SketchPlugin_MacroCircle::execute()
84 std::string aType = string(CIRCLE_TYPE())->value();
85 if (aType == CIRCLE_TYPE_BY_CENTER_AND_PASSED_POINTS())
86 createCircleByCenterAndPassed();
87 else if (aType == CIRCLE_TYPE_BY_THREE_POINTS())
88 createCircleByThreePoints();
94 static void convertToPointOrTangent(const AttributeRefAttrPtr& theRefAttr,
95 const AttributePtr& theBaseAttr,
96 std::shared_ptr<GeomAPI_Pnt2d>& thePassingPoint,
97 std::shared_ptr<GeomAPI_Shape>& theTangentCurve)
99 AttributePtr anAttr = theBaseAttr;
100 if (theRefAttr->isObject()) {
101 FeaturePtr aTgFeature = ModelAPI_Feature::feature(theRefAttr->object());
103 if (aTgFeature->getKind() != SketchPlugin_Point::ID()) {
104 theTangentCurve = aTgFeature->lastResult()->shape();
107 anAttr = aTgFeature->attribute(SketchPlugin_Point::COORD_ID());
110 anAttr = theRefAttr->attr();
112 thePassingPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr)->pnt();
115 void SketchPlugin_MacroCircle::createCircleByCenterAndPassed()
117 AttributePtr aPassedAttr = attribute(PASSED_POINT_ID());
118 AttributeRefAttrPtr aPassedRef = refattr(PASSED_POINT_REF_ID());
119 // Calculate circle parameters
120 std::shared_ptr<GeomAPI_Pnt2d> aCenter =
121 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(CENTER_POINT_ID()))->pnt();
122 std::shared_ptr<GeomAPI_Pnt2d> aPassedPoint;
123 std::shared_ptr<GeomAPI_Shape> aTangentCurve;
124 convertToPointOrTangent(aPassedRef, aPassedAttr, aPassedPoint, aTangentCurve);
127 std::shared_ptr<GeomAPI_Circ2d> aCircle;
129 std::shared_ptr<GeomAPI_Ax3> anAxis = SketchPlugin_Sketch::plane(sketch());
130 aCircle = std::shared_ptr<GeomAPI_Circ2d>(new GeomAPI_Circ2d(aCenter, aTangentCurve, anAxis));
132 aCircle = std::shared_ptr<GeomAPI_Circ2d>(new GeomAPI_Circ2d(aCenter, aPassedPoint));
134 // Create circle feature.
135 FeaturePtr aCircleFeature = createCircleFeature(aCircle);
137 // Create constraints.
138 SketchPlugin_Tools::createConstraint(this,
139 CENTER_POINT_REF_ID(),
140 aCircleFeature->attribute(SketchPlugin_Circle::CENTER_ID()),
143 SketchPlugin_Tools::createConstraint(this,
144 PASSED_POINT_REF_ID(),
146 aCircleFeature->lastResult(),
150 void SketchPlugin_MacroCircle::createCircleByThreePoints()
152 std::string aPointAttr[3] = { FIRST_POINT_ID(),
155 std::string aPointRef[3] = { FIRST_POINT_REF_ID(),
156 SECOND_POINT_REF_ID(),
157 THIRD_POINT_REF_ID() };
158 std::shared_ptr<GeomAPI_Interface> aPassedEntities[3];
159 for (int i = 0; i < 3; ++i) {
160 AttributePtr aPassedAttr = attribute(aPointAttr[i]);
161 AttributeRefAttrPtr aPassedRef = refattr(aPointRef[i]);
162 // calculate circle parameters
163 std::shared_ptr<GeomAPI_Pnt2d> aPassedPoint;
164 std::shared_ptr<GeomAPI_Shape> aTangentCurve;
165 convertToPointOrTangent(aPassedRef, aPassedAttr, aPassedPoint, aTangentCurve);
168 aPassedEntities[i] = aPassedPoint;
170 aPassedEntities[i] = aTangentCurve;
173 std::shared_ptr<GeomAPI_Ax3> anAxis = SketchPlugin_Sketch::plane(sketch());
174 std::shared_ptr<GeomAPI_Circ2d> aCircle = std::shared_ptr<GeomAPI_Circ2d>(
175 new GeomAPI_Circ2d(aPassedEntities[0], aPassedEntities[1], aPassedEntities[2], anAxis));
177 // Create circle feature.
178 FeaturePtr aCircleFeature = createCircleFeature(aCircle);
179 ResultPtr aCircleResult = aCircleFeature->lastResult();
181 // Create constraints.
182 for (int i = 0; i < 3; ++i)
183 SketchPlugin_Tools::createConstraint(this, aPointRef[i], AttributePtr(), aCircleResult, true);
186 FeaturePtr SketchPlugin_MacroCircle::createCircleFeature(
187 const std::shared_ptr<GeomAPI_Circ2d>& theCircle)
189 FeaturePtr aCircleFeature = sketch()->addFeature(SketchPlugin_Circle::ID());
190 std::shared_ptr<GeomAPI_Pnt2d> aCenter = theCircle->center();
191 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
192 aCircleFeature->attribute(SketchPlugin_Circle::CENTER_ID()))->setValue(aCenter->x(),
194 aCircleFeature->real(SketchPlugin_Circle::RADIUS_ID())->setValue(theCircle->radius());
195 aCircleFeature->boolean(SketchPlugin_Circle::AUXILIARY_ID())
196 ->setValue(boolean(AUXILIARY_ID())->value());
197 aCircleFeature->execute();
198 return aCircleFeature;
201 AISObjectPtr SketchPlugin_MacroCircle::getAISObject(AISObjectPtr thePrevious)
203 if(!myCenter.get() || myRadius < tolerance) {
204 return AISObjectPtr();
207 SketchPlugin_Sketch* aSketch = sketch();
209 return AISObjectPtr();
212 // Compute a circle in 3D view.
213 std::shared_ptr<GeomAPI_Pnt> aCenter(aSketch->to3D(myCenter->x(), myCenter->y()));
214 std::shared_ptr<GeomDataAPI_Dir> aNDir =
215 std::dynamic_pointer_cast<GeomDataAPI_Dir>(
216 aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
217 std::shared_ptr<GeomAPI_Dir> aNormal = aNDir->dir();
218 GeomShapePtr aCircleShape = GeomAlgoAPI_EdgeBuilder::lineCircle(aCenter, aNormal, myRadius);
219 GeomShapePtr aCenterPointShape = GeomAlgoAPI_PointBuilder::vertex(aCenter);
220 if(!aCircleShape.get() || !aCenterPointShape.get()) {
221 return AISObjectPtr();
224 std::list<std::shared_ptr<GeomAPI_Shape> > aShapes;
225 aShapes.push_back(aCircleShape);
226 aShapes.push_back(aCenterPointShape);
228 std::shared_ptr<GeomAPI_Shape> aCompound = GeomAlgoAPI_CompoundBuilder::compound(aShapes);
229 AISObjectPtr anAIS = thePrevious;
231 anAIS.reset(new GeomAPI_AISObject());
233 anAIS->createShape(aCompound);
237 void SketchPlugin_MacroCircle::attributeChanged(const std::string& theID) {
238 // If circle type switched reset according attributes.
239 if(theID == CIRCLE_TYPE()) {
240 std::string aType = string(CIRCLE_TYPE())->value();
241 if(aType == CIRCLE_TYPE_BY_CENTER_AND_PASSED_POINTS()) {
242 SketchPlugin_Tools::resetAttribute(this, CENTER_POINT_ID());
243 SketchPlugin_Tools::resetAttribute(this, CENTER_POINT_REF_ID());
244 SketchPlugin_Tools::resetAttribute(this, PASSED_POINT_ID());
245 SketchPlugin_Tools::resetAttribute(this, PASSED_POINT_REF_ID());
246 } else if(aType == CIRCLE_TYPE_BY_THREE_POINTS()) {
247 SketchPlugin_Tools::resetAttribute(this, FIRST_POINT_ID());
248 SketchPlugin_Tools::resetAttribute(this, FIRST_POINT_REF_ID());
249 SketchPlugin_Tools::resetAttribute(this, SECOND_POINT_ID());
250 SketchPlugin_Tools::resetAttribute(this, SECOND_POINT_REF_ID());
251 SketchPlugin_Tools::resetAttribute(this, THIRD_POINT_ID());
252 SketchPlugin_Tools::resetAttribute(this, THIRD_POINT_REF_ID());
256 } else if(theID == CENTER_POINT_ID() || theID == PASSED_POINT_ID()) {
257 std::shared_ptr<GeomDataAPI_Point2D> aCenterPointAttr =
258 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(CENTER_POINT_ID()));
259 if(!aCenterPointAttr->isInitialized()) {
262 std::shared_ptr<GeomDataAPI_Point2D> aPassedPointAttr =
263 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(PASSED_POINT_ID()));
264 if(!aPassedPointAttr->isInitialized()) {
268 myCenter = aCenterPointAttr->pnt();
269 myRadius = myCenter->distance(aPassedPointAttr->pnt());
270 } else if(theID == FIRST_POINT_ID() || theID == SECOND_POINT_ID() || theID == THIRD_POINT_ID()) {
271 std::shared_ptr<GeomAPI_Pnt2d> aPoints[3];
272 int aNbInitialized = 0;
273 for(int i = 1; i <= 3; ++i) {
274 std::shared_ptr<GeomDataAPI_Point2D> aCurPnt =
275 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(POINT_ID(i)));
276 if(aCurPnt->isInitialized())
277 aPoints[aNbInitialized++] = aCurPnt->pnt();
280 if(aNbInitialized == 1) {
282 } else if(aNbInitialized == 2) {
283 std::shared_ptr<GeomAPI_XY> aCenterXY =
284 aPoints[0]->xy()->added(aPoints[1]->xy())->multiplied(0.5);
285 myCenter.reset(new GeomAPI_Pnt2d(aCenterXY->x(), aCenterXY->y()));
286 myRadius = aPoints[0]->distance(aPoints[1]) * 0.5;
288 std::shared_ptr<GeomAPI_Circ2d> aCircle(
289 new GeomAPI_Circ2d(aPoints[0], aPoints[1], aPoints[2]));
290 myCenter = aCircle->center();
292 myRadius = aCircle->radius();
297 AttributeDoublePtr aRadiusAttr = real(CIRCLE_RADIUS_ID());
298 bool aWasBlocked = data()->blockSendAttributeUpdated(true);
299 aRadiusAttr->setValue(myRadius);
300 data()->blockSendAttributeUpdated(aWasBlocked, false);