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_ConstraintCoincidence.h"
11 #include "SketchPlugin_Point.h"
12 #include "SketchPlugin_Tools.h"
14 #include <ModelAPI_Data.h>
15 #include <ModelAPI_Events.h>
16 #include <ModelAPI_ResultConstruction.h>
17 #include <ModelAPI_AttributeSelection.h>
18 #include <ModelAPI_Validator.h>
19 #include <ModelAPI_AttributeDouble.h>
20 #include <ModelAPI_AttributeRefAttr.h>
21 #include <ModelAPI_AttributeString.h>
22 #include <ModelAPI_Session.h>
24 #include <GeomAPI_Pnt2d.h>
25 #include <GeomAPI_Circ.h>
26 #include <GeomAPI_Vertex.h>
27 #include <GeomAPI_XY.h>
28 #include <GeomDataAPI_Point2D.h>
29 #include <GeomDataAPI_Dir.h>
30 #include <GeomAlgoAPI_PointBuilder.h>
31 #include <GeomAlgoAPI_EdgeBuilder.h>
32 #include <GeomAlgoAPI_CompoundBuilder.h>
35 const double tolerance = 1e-7;
38 static const std::string& POINT_ID(int theIndex)
41 case 1: return SketchPlugin_MacroCircle::FIRST_POINT_ID();
42 case 2: return SketchPlugin_MacroCircle::SECOND_POINT_ID();
43 case 3: return SketchPlugin_MacroCircle::THIRD_POINT_ID();
46 static const std::string DUMMY;
52 SketchPlugin_MacroCircle::SketchPlugin_MacroCircle()
53 : SketchPlugin_SketchEntity(),
58 void SketchPlugin_MacroCircle::initAttributes()
60 data()->addAttribute(CIRCLE_TYPE(), ModelAPI_AttributeString::typeId());
62 data()->addAttribute(CENTER_POINT_ID(), GeomDataAPI_Point2D::typeId());
63 data()->addAttribute(CENTER_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
64 data()->addAttribute(PASSED_POINT_ID(), GeomDataAPI_Point2D::typeId());
65 data()->addAttribute(PASSED_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
67 data()->addAttribute(FIRST_POINT_ID(), GeomDataAPI_Point2D::typeId());
68 data()->addAttribute(SECOND_POINT_ID(), GeomDataAPI_Point2D::typeId());
69 data()->addAttribute(THIRD_POINT_ID(), GeomDataAPI_Point2D::typeId());
70 data()->addAttribute(FIRST_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
71 data()->addAttribute(SECOND_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
72 data()->addAttribute(THIRD_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
74 data()->addAttribute(CIRCLE_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
75 data()->addAttribute(AUXILIARY_ID(), ModelAPI_AttributeBoolean::typeId());
77 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CENTER_POINT_REF_ID());
78 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PASSED_POINT_REF_ID());
79 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), FIRST_POINT_REF_ID());
80 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SECOND_POINT_REF_ID());
81 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), THIRD_POINT_REF_ID());
84 void SketchPlugin_MacroCircle::execute()
86 std::string aType = string(CIRCLE_TYPE())->value();
87 if (aType == CIRCLE_TYPE_BY_CENTER_AND_PASSED_POINTS())
88 createCircleByCenterAndPassed();
89 else if (aType == CIRCLE_TYPE_BY_THREE_POINTS())
90 createCircleByThreePoints();
96 static void convertToPointOrTangent(const AttributeRefAttrPtr& theRefAttr,
97 const AttributePtr& theBaseAttr,
98 std::shared_ptr<GeomAPI_Pnt2d>& thePassingPoint,
99 std::shared_ptr<GeomAPI_Shape>& theTangentCurve)
101 AttributePtr anAttr = theBaseAttr;
102 if (theRefAttr->isObject()) {
103 FeaturePtr aTgFeature = ModelAPI_Feature::feature(theRefAttr->object());
105 if (aTgFeature->getKind() != SketchPlugin_Point::ID()) {
106 theTangentCurve = aTgFeature->lastResult()->shape();
109 anAttr = aTgFeature->attribute(SketchPlugin_Point::COORD_ID());
112 anAttr = theRefAttr->attr();
114 thePassingPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr)->pnt();
117 void SketchPlugin_MacroCircle::createCircleByCenterAndPassed()
119 AttributePtr aPassedAttr = attribute(PASSED_POINT_ID());
120 AttributeRefAttrPtr aPassedRef = refattr(PASSED_POINT_REF_ID());
121 // Calculate circle parameters
122 std::shared_ptr<GeomAPI_Pnt2d> aCenter =
123 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(CENTER_POINT_ID()))->pnt();
124 std::shared_ptr<GeomAPI_Pnt2d> aPassedPoint;
125 std::shared_ptr<GeomAPI_Shape> aTangentCurve;
126 convertToPointOrTangent(aPassedRef, aPassedAttr, aPassedPoint, aTangentCurve);
129 std::shared_ptr<GeomAPI_Circ2d> aCircle;
131 std::shared_ptr<GeomAPI_Ax3> anAxis = SketchPlugin_Sketch::plane(sketch());
132 aCircle = std::shared_ptr<GeomAPI_Circ2d>(new GeomAPI_Circ2d(aCenter, aTangentCurve, anAxis));
134 aCircle = std::shared_ptr<GeomAPI_Circ2d>(new GeomAPI_Circ2d(aCenter, aPassedPoint));
136 // Create circle feature.
137 FeaturePtr aCircleFeature = createCircleFeature(aCircle);
139 // Create constraints.
140 SketchPlugin_Tools::createConstraint(this,
141 CENTER_POINT_REF_ID(),
142 aCircleFeature->attribute(SketchPlugin_Circle::CENTER_ID()),
145 SketchPlugin_Tools::createConstraint(this,
146 PASSED_POINT_REF_ID(),
148 aCircleFeature->lastResult(),
152 void SketchPlugin_MacroCircle::createCircleByThreePoints()
154 std::string aPointAttr[3] = { FIRST_POINT_ID(),
157 std::string aPointRef[3] = { FIRST_POINT_REF_ID(),
158 SECOND_POINT_REF_ID(),
159 THIRD_POINT_REF_ID() };
160 std::shared_ptr<GeomAPI_Interface> aPassedEntities[3];
161 for (int i = 0; i < 3; ++i) {
162 AttributePtr aPassedAttr = attribute(aPointAttr[i]);
163 AttributeRefAttrPtr aPassedRef = refattr(aPointRef[i]);
164 // calculate circle parameters
165 std::shared_ptr<GeomAPI_Pnt2d> aPassedPoint;
166 std::shared_ptr<GeomAPI_Shape> aTangentCurve;
167 convertToPointOrTangent(aPassedRef, aPassedAttr, aPassedPoint, aTangentCurve);
170 aPassedEntities[i] = aPassedPoint;
172 aPassedEntities[i] = aTangentCurve;
175 std::shared_ptr<GeomAPI_Ax3> anAxis = SketchPlugin_Sketch::plane(sketch());
176 std::shared_ptr<GeomAPI_Circ2d> aCircle = std::shared_ptr<GeomAPI_Circ2d>(
177 new GeomAPI_Circ2d(aPassedEntities[0], aPassedEntities[1], aPassedEntities[2], anAxis));
179 // Create circle feature.
180 FeaturePtr aCircleFeature = createCircleFeature(aCircle);
181 ResultPtr aCircleResult = aCircleFeature->lastResult();
183 // Create constraints.
184 for (int i = 0; i < 3; ++i)
185 SketchPlugin_Tools::createConstraint(this, aPointRef[i], NULL, aCircleResult, true);
188 FeaturePtr SketchPlugin_MacroCircle::createCircleFeature(
189 const std::shared_ptr<GeomAPI_Circ2d>& theCircle)
191 FeaturePtr aCircleFeature = sketch()->addFeature(SketchPlugin_Circle::ID());
192 std::shared_ptr<GeomAPI_Pnt2d> aCenter = theCircle->center();
193 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
194 aCircleFeature->attribute(SketchPlugin_Circle::CENTER_ID()))->setValue(aCenter->x(),
196 aCircleFeature->real(SketchPlugin_Circle::RADIUS_ID())->setValue(theCircle->radius());
197 aCircleFeature->boolean(SketchPlugin_Circle::AUXILIARY_ID())
198 ->setValue(boolean(AUXILIARY_ID())->value());
199 aCircleFeature->execute();
200 return aCircleFeature;
203 AISObjectPtr SketchPlugin_MacroCircle::getAISObject(AISObjectPtr thePrevious)
205 if(!myCenter.get() || myRadius < tolerance) {
206 return AISObjectPtr();
209 SketchPlugin_Sketch* aSketch = sketch();
211 return AISObjectPtr();
214 // Compute a circle in 3D view.
215 std::shared_ptr<GeomAPI_Pnt> aCenter(aSketch->to3D(myCenter->x(), myCenter->y()));
216 std::shared_ptr<GeomDataAPI_Dir> aNDir =
217 std::dynamic_pointer_cast<GeomDataAPI_Dir>(
218 aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
219 std::shared_ptr<GeomAPI_Dir> aNormal = aNDir->dir();
220 GeomShapePtr aCircleShape = GeomAlgoAPI_EdgeBuilder::lineCircle(aCenter, aNormal, myRadius);
221 GeomShapePtr aCenterPointShape = GeomAlgoAPI_PointBuilder::vertex(aCenter);
222 if(!aCircleShape.get() || !aCenterPointShape.get()) {
223 return AISObjectPtr();
226 std::list<std::shared_ptr<GeomAPI_Shape> > aShapes;
227 aShapes.push_back(aCircleShape);
228 aShapes.push_back(aCenterPointShape);
230 std::shared_ptr<GeomAPI_Shape> aCompound = GeomAlgoAPI_CompoundBuilder::compound(aShapes);
231 AISObjectPtr anAIS = thePrevious;
233 anAIS.reset(new GeomAPI_AISObject());
235 anAIS->createShape(aCompound);
239 void SketchPlugin_MacroCircle::attributeChanged(const std::string& theID) {
240 // If circle type switched reset according attributes.
241 if(theID == CIRCLE_TYPE()) {
242 std::string aType = string(CIRCLE_TYPE())->value();
243 if(aType == CIRCLE_TYPE_BY_CENTER_AND_PASSED_POINTS()) {
244 resetAttribute(CENTER_POINT_ID());
245 resetAttribute(PASSED_POINT_ID());
246 } else if(aType == CIRCLE_TYPE_BY_THREE_POINTS()) {
247 resetAttribute(FIRST_POINT_ID());
248 resetAttribute(SECOND_POINT_ID());
249 resetAttribute(THIRD_POINT_ID());
253 } else if(theID == CENTER_POINT_ID() || theID == PASSED_POINT_ID()) {
254 std::shared_ptr<GeomDataAPI_Point2D> aCenterPointAttr =
255 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(CENTER_POINT_ID()));
256 if(!aCenterPointAttr->isInitialized()) {
259 std::shared_ptr<GeomDataAPI_Point2D> aPassedPointAttr =
260 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(PASSED_POINT_ID()));
261 if(!aPassedPointAttr->isInitialized()) {
265 myCenter = aCenterPointAttr->pnt();
266 myRadius = myCenter->distance(aPassedPointAttr->pnt());
267 } else if(theID == FIRST_POINT_ID() || theID == SECOND_POINT_ID() || theID == THIRD_POINT_ID()) {
268 std::shared_ptr<GeomAPI_Pnt2d> aPoints[3];
269 int aNbInitialized = 0;
270 for(int i = 1; i <= 3; ++i) {
271 std::shared_ptr<GeomDataAPI_Point2D> aCurPnt =
272 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(POINT_ID(i)));
273 if(aCurPnt->isInitialized())
274 aPoints[aNbInitialized++] = aCurPnt->pnt();
277 if(aNbInitialized == 1) {
279 } else if(aNbInitialized == 2) {
280 std::shared_ptr<GeomAPI_XY> aCenterXY =
281 aPoints[0]->xy()->added(aPoints[1]->xy())->multiplied(0.5);
282 myCenter.reset(new GeomAPI_Pnt2d(aCenterXY->x(), aCenterXY->y()));
283 myRadius = aPoints[0]->distance(aPoints[1]) * 0.5;
285 std::shared_ptr<GeomAPI_Circ2d> aCircle(
286 new GeomAPI_Circ2d(aPoints[0], aPoints[1], aPoints[2]));
287 myCenter = aCircle->center();
289 myRadius = aCircle->radius();
294 AttributeDoublePtr aRadiusAttr = real(CIRCLE_RADIUS_ID());
295 bool aWasBlocked = data()->blockSendAttributeUpdated(true);
296 aRadiusAttr->setValue(myRadius);
297 data()->blockSendAttributeUpdated(aWasBlocked, false);
300 void SketchPlugin_MacroCircle::resetAttribute(const std::string& theId)
302 AttributePtr anAttr = attribute(theId);