1 // Copyright (C) 2014-2017 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
20 #include "SketchPlugin_MacroArc.h"
22 #include "SketchPlugin_Arc.h"
23 #include "SketchPlugin_ConstraintTangent.h"
24 #include "SketchPlugin_Sketch.h"
25 #include "SketchPlugin_Tools.h"
26 #include "SketchPlugin_MacroArcReentrantMessage.h"
28 #include <ModelAPI_AttributeDouble.h>
29 #include <ModelAPI_AttributeRefAttr.h>
30 #include <ModelAPI_AttributeString.h>
31 #include <ModelAPI_Events.h>
32 #include <ModelAPI_Session.h>
33 #include <ModelAPI_Validator.h>
35 #include <GeomAPI_Circ.h>
36 #include <GeomAPI_Circ2d.h>
37 #include <GeomAPI_Curve.h>
38 #include <GeomAPI_Dir2d.h>
39 #include <GeomAPI_Edge.h>
40 #include <GeomAPI_Lin.h>
41 #include <GeomAPI_Lin2d.h>
42 #include <GeomAPI_Pnt2d.h>
43 #include <GeomAPI_Vertex.h>
44 #include <GeomAPI_XY.h>
45 #include <GeomAPI_ShapeIterator.h>
47 #include <GeomDataAPI_Point2D.h>
48 #include <GeomDataAPI_Dir.h>
50 #include <GeomAlgoAPI_Circ2dBuilder.h>
51 #include <GeomAlgoAPI_EdgeBuilder.h>
52 #include <GeomAlgoAPI_CompoundBuilder.h>
53 #include <GeomAlgoAPI_PointBuilder.h>
58 const double tolerance = 1e-7;
59 const double paramTolerance = 1.e-4;
60 const double PI = 3.141592653589793238463;
62 static void projectPointOnCircle(AttributePoint2DPtr& thePoint, const GeomAPI_Circ2d& theCircle)
64 std::shared_ptr<GeomAPI_Pnt2d> aProjection = theCircle.project(thePoint->pnt());
66 thePoint->setValue(aProjection);
69 static void intersectShapeAndCircle(const GeomShapePtr& theShape,
70 const GeomAPI_Circ2d& theCircle,
71 const SketchPlugin_Sketch* theSketch,
72 AttributePoint2DPtr& theIntersection)
74 if (!theShape->isEdge())
75 return projectPointOnCircle(theIntersection, theCircle);
77 // convert shape to unbounded
78 std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge(theShape));
79 if (anEdge->isLine()) {
80 static const double HALF_SIZE = 1.e6;
81 std::shared_ptr<GeomAPI_XYZ> aLoc = anEdge->line()->location()->xyz();
82 std::shared_ptr<GeomAPI_XYZ> aDir = anEdge->line()->direction()->xyz();
84 std::shared_ptr<GeomAPI_Pnt> aStart(
85 new GeomAPI_Pnt(aLoc->added(aDir->multiplied(-HALF_SIZE))));
86 std::shared_ptr<GeomAPI_Pnt> aEnd(
87 new GeomAPI_Pnt(aLoc->added(aDir->multiplied(HALF_SIZE))));
88 anEdge = GeomAlgoAPI_EdgeBuilder::line(aStart, aEnd);
89 } else if (anEdge->isArc()) {
90 std::shared_ptr<GeomAPI_Circ> aCircle = anEdge->circle();
91 anEdge = GeomAlgoAPI_EdgeBuilder::lineCircle(
92 aCircle->center(), aCircle->normal(), aCircle->radius());
95 // convert 2D circle to 3D object
96 std::shared_ptr<GeomAPI_Pnt2d> aCenter2d = theCircle.center();
97 std::shared_ptr<GeomAPI_Pnt> aCenter(theSketch->to3D(aCenter2d->x(), aCenter2d->y()));
98 std::shared_ptr<GeomDataAPI_Dir> aNDir = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
99 const_cast<SketchPlugin_Sketch*>(theSketch)->attribute(SketchPlugin_Sketch::NORM_ID()));
100 std::shared_ptr<GeomAPI_Dir> aNormal(new GeomAPI_Dir(aNDir->x(), aNDir->y(), aNDir->z()));
102 GeomShapePtr aCircleShape =
103 GeomAlgoAPI_EdgeBuilder::lineCircle(aCenter, aNormal, theCircle.radius());
105 GeomShapePtr anInter = anEdge->intersect(aCircleShape);
106 std::shared_ptr<GeomAPI_Pnt2d> anInterPnt;
108 return projectPointOnCircle(theIntersection, theCircle);
109 if (anInter->isVertex()) {
110 std::shared_ptr<GeomAPI_Vertex> aVertex(new GeomAPI_Vertex(anInter));
111 anInterPnt = theSketch->to2D(aVertex->point());
112 } else if (anInter->isCompound()) {
113 double aMinDist = 1.e300;
115 GeomAPI_ShapeIterator anIt(anInter);
116 for (; anIt.more(); anIt.next()) {
117 GeomShapePtr aCurrent = anIt.current();
118 if (!aCurrent->isVertex())
120 std::shared_ptr<GeomAPI_Vertex> aVertex(new GeomAPI_Vertex(aCurrent));
121 std::shared_ptr<GeomAPI_Pnt2d> aPnt = theSketch->to2D(aVertex->point());
122 double aDist = aPnt->distance(theIntersection->pnt());
123 if (aDist < aMinDist) {
129 if(anInterPnt.get()) {
130 theIntersection->setValue(anInterPnt);
135 SketchPlugin_MacroArc::SketchPlugin_MacroArc()
136 : SketchPlugin_SketchEntity(),
141 void SketchPlugin_MacroArc::initAttributes()
143 data()->addAttribute(ARC_TYPE(), ModelAPI_AttributeString::typeId());
145 data()->addAttribute(CENTER_POINT_ID(), GeomDataAPI_Point2D::typeId());
146 data()->addAttribute(START_POINT_1_ID(), GeomDataAPI_Point2D::typeId());
147 data()->addAttribute(END_POINT_1_ID(), GeomDataAPI_Point2D::typeId());
149 data()->addAttribute(START_POINT_2_ID(), GeomDataAPI_Point2D::typeId());
150 data()->addAttribute(END_POINT_2_ID(), GeomDataAPI_Point2D::typeId());
151 data()->addAttribute(PASSED_POINT_ID(), GeomDataAPI_Point2D::typeId());
153 data()->addAttribute(TANGENT_POINT_ID(), ModelAPI_AttributeRefAttr::typeId());
154 data()->addAttribute(END_POINT_3_ID(), GeomDataAPI_Point2D::typeId());
156 data()->addAttribute(REVERSED_ID(), ModelAPI_AttributeBoolean::typeId());
158 data()->addAttribute(RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
159 data()->addAttribute(ANGLE_ID(), ModelAPI_AttributeDouble::typeId());
161 data()->addAttribute(AUXILIARY_ID(), ModelAPI_AttributeBoolean::typeId());
163 data()->addAttribute(CENTER_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
164 data()->addAttribute(START_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
165 data()->addAttribute(END_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
166 data()->addAttribute(PASSED_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
168 data()->addAttribute(EDIT_ARC_TYPE_ID(), ModelAPI_AttributeString::typeId());
170 boolean(REVERSED_ID())->setValue(false);
171 string(EDIT_ARC_TYPE_ID())->setValue("");
173 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CENTER_POINT_REF_ID());
174 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), START_POINT_REF_ID());
175 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), END_POINT_REF_ID());
176 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PASSED_POINT_REF_ID());
177 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EDIT_ARC_TYPE_ID());
180 void SketchPlugin_MacroArc::attributeChanged(const std::string& theID)
182 std::string anArcType = string(ARC_TYPE())->value();
184 // If arc type switched reset according attributes.
185 if(theID == ARC_TYPE()) {
186 SketchPlugin_Tools::resetAttribute(this, CENTER_POINT_ID());
187 SketchPlugin_Tools::resetAttribute(this, CENTER_POINT_REF_ID());
188 SketchPlugin_Tools::resetAttribute(this, START_POINT_1_ID());
189 SketchPlugin_Tools::resetAttribute(this, START_POINT_REF_ID());
190 SketchPlugin_Tools::resetAttribute(this, END_POINT_1_ID());
191 SketchPlugin_Tools::resetAttribute(this, END_POINT_REF_ID());
192 SketchPlugin_Tools::resetAttribute(this, START_POINT_2_ID());
193 SketchPlugin_Tools::resetAttribute(this, END_POINT_2_ID());
194 SketchPlugin_Tools::resetAttribute(this, PASSED_POINT_ID());
195 SketchPlugin_Tools::resetAttribute(this, PASSED_POINT_REF_ID());
196 SketchPlugin_Tools::resetAttribute(this, TANGENT_POINT_ID());
197 SketchPlugin_Tools::resetAttribute(this, END_POINT_3_ID());
198 SketchPlugin_Tools::resetAttribute(this, REVERSED_ID());
199 SketchPlugin_Tools::resetAttribute(this, RADIUS_ID());
200 SketchPlugin_Tools::resetAttribute(this, ANGLE_ID());
205 boolean(REVERSED_ID())->setValue(false);
207 } else if(anArcType == ARC_TYPE_BY_CENTER_AND_POINTS())
208 fillByCenterAndTwoPassed();
209 else if(anArcType == ARC_TYPE_BY_THREE_POINTS())
210 fillByThreePassedPoints();
211 else if(anArcType == ARC_TYPE_BY_TANGENT_EDGE())
216 if(myCenter.get() && myStart.get()) {
217 aRadius = myCenter->distance(myStart);
219 if(myStart->isEqual(myEnd)) {
222 GeomAPI_Circ2d aCircleForArc(myCenter, myStart);
223 double aStartParam, anEndParam;
224 aCircleForArc.parameter(myStart, paramTolerance, aStartParam);
225 aCircleForArc.parameter(myEnd, paramTolerance, anEndParam);
226 anAngle = (anEndParam - aStartParam) / PI * 180.0;
227 if(boolean(REVERSED_ID())->value()) anAngle = 360.0 - anAngle;
232 bool aWasBlocked = data()->blockSendAttributeUpdated(true);
234 // center attribute is used in processEvent() to set reference to reentrant arc
235 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(CENTER_POINT_ID()))
236 ->setValue(myCenter);
238 real(RADIUS_ID())->setValue(aRadius);
239 real(ANGLE_ID())->setValue(anAngle);
240 data()->blockSendAttributeUpdated(aWasBlocked, false);
243 GeomShapePtr SketchPlugin_MacroArc::getArcShape(bool isBound)
245 if(!myStart.get() || !myEnd.get() || !myCenter.get()) {
246 return GeomShapePtr();
249 SketchPlugin_Sketch* aSketch = sketch();
251 return GeomShapePtr();
254 std::shared_ptr<GeomAPI_Pnt> aCenter(aSketch->to3D(myCenter->x(), myCenter->y()));
255 std::shared_ptr<GeomAPI_Pnt> aStart(aSketch->to3D(myStart->x(), myStart->y()));
256 std::shared_ptr<GeomAPI_Pnt> anEnd(aSketch->to3D(myEnd->x(), myEnd->y()));
257 std::shared_ptr<GeomDataAPI_Dir> aNDir =
258 std::dynamic_pointer_cast<GeomDataAPI_Dir>(aSketch->attribute(SketchPlugin_Sketch::NORM_ID()));
259 std::shared_ptr<GeomAPI_Dir> aNormal(new GeomAPI_Dir(aNDir->x(), aNDir->y(), aNDir->z()));
261 GeomShapePtr anArcShape;
263 anArcShape = boolean(REVERSED_ID())->value() ?
264 GeomAlgoAPI_EdgeBuilder::lineCircleArc(aCenter, anEnd, aStart, aNormal)
265 : GeomAlgoAPI_EdgeBuilder::lineCircleArc(aCenter, aStart, anEnd, aNormal);
267 double aRadius = aCenter->distance(aStart);
268 anArcShape = GeomAlgoAPI_EdgeBuilder::lineCircle(aCenter, aNormal, aRadius);
274 AISObjectPtr SketchPlugin_MacroArc::getAISObject(AISObjectPtr thePrevious)
276 if(!myStart.get() || !myEnd.get() || !myCenter.get()) {
277 return AISObjectPtr();
280 SketchPlugin_Sketch* aSketch = sketch();
282 return AISObjectPtr();
285 GeomShapePtr anArcShape = getArcShape();
286 std::shared_ptr<GeomAPI_Pnt> aCenter = aSketch->to3D(myCenter->x(), myCenter->y());;
287 GeomShapePtr aCenterPointShape = GeomAlgoAPI_PointBuilder::vertex(aCenter);
289 if(!anArcShape.get() || !aCenterPointShape.get()) {
290 return AISObjectPtr();
293 std::list<std::shared_ptr<GeomAPI_Shape> > aShapes;
294 aShapes.push_back(anArcShape);
295 aShapes.push_back(aCenterPointShape);
297 std::shared_ptr<GeomAPI_Shape> aCompound = GeomAlgoAPI_CompoundBuilder::compound(aShapes);
298 AISObjectPtr anAIS = thePrevious;
300 anAIS.reset(new GeomAPI_AISObject());
302 anAIS->createShape(aCompound);
306 void SketchPlugin_MacroArc::execute()
308 FeaturePtr anArcFeature = createArcFeature();
314 // Create constraints.
315 std::string anArcType = string(ARC_TYPE())->value();
316 if(anArcType == ARC_TYPE_BY_CENTER_AND_POINTS()) {
317 SketchPlugin_Tools::createConstraint(this,
318 CENTER_POINT_REF_ID(),
319 anArcFeature->attribute(SketchPlugin_Arc::CENTER_ID()),
322 SketchPlugin_Tools::createConstraint(this,
323 START_POINT_REF_ID(),
324 anArcFeature->attribute(SketchPlugin_Arc::START_ID()),
327 SketchPlugin_Tools::createConstraint(this,
329 anArcFeature->attribute(SketchPlugin_Arc::END_ID()),
332 } else if(anArcType == ARC_TYPE_BY_THREE_POINTS()) {
333 SketchPlugin_Tools::createConstraint(this,
334 START_POINT_REF_ID(),
335 anArcFeature->attribute(SketchPlugin_Arc::START_ID()),
338 SketchPlugin_Tools::createConstraint(this,
340 anArcFeature->attribute(SketchPlugin_Arc::END_ID()),
343 SketchPlugin_Tools::createConstraint(this,
344 PASSED_POINT_REF_ID(),
346 anArcFeature->lastResult(),
348 } else if(anArcType == ARC_TYPE_BY_TANGENT_EDGE()) {
349 // constraints for tangent arc
350 SketchPlugin_Tools::createConstraint(this,
352 anArcFeature->attribute(SketchPlugin_Arc::START_ID()),
355 FeaturePtr aTangent = sketch()->addFeature(SketchPlugin_ConstraintTangent::ID());
356 AttributeRefAttrPtr aRefAttrA = aTangent->refattr(SketchPlugin_Constraint::ENTITY_A());
357 AttributeRefAttrPtr aTgPntRefAttr = refattr(TANGENT_POINT_ID());
358 FeaturePtr aTgFeature = ModelAPI_Feature::feature(aTgPntRefAttr->attr()->owner());
359 aRefAttrA->setObject(aTgFeature->lastResult());
360 AttributeRefAttrPtr aRefAttrB = aTangent->refattr(SketchPlugin_Constraint::ENTITY_B());
361 aRefAttrB->setObject(anArcFeature->lastResult());
362 // constraint for end point
363 SketchPlugin_Tools::createConstraint(this,
365 anArcFeature->attribute(SketchPlugin_Arc::END_ID()),
370 // message to init reentrant operation
371 static Events_ID anId = SketchPlugin_MacroArcReentrantMessage::eventId();
372 std::shared_ptr<SketchPlugin_MacroArcReentrantMessage> aMessage = std::shared_ptr
373 <SketchPlugin_MacroArcReentrantMessage>(new SketchPlugin_MacroArcReentrantMessage(anId, this));
375 std::string anEditArcType = string(EDIT_ARC_TYPE_ID())->value();
376 aMessage->setTypeOfCreation(!anEditArcType.empty() ? anEditArcType : anArcType);
377 aMessage->setCreatedFeature(anArcFeature);
378 Events_Loop::loop()->send(aMessage);
381 std::string SketchPlugin_MacroArc::processEvent(const std::shared_ptr<Events_Message>& theMessage)
383 std::string aFilledAttributeName;
384 std::shared_ptr<SketchPlugin_MacroArcReentrantMessage> aReentrantMessage =
385 std::dynamic_pointer_cast<SketchPlugin_MacroArcReentrantMessage>(theMessage);
386 if (aReentrantMessage.get()) {
387 FeaturePtr aCreatedFeature = aReentrantMessage->createdFeature();
388 std::string anArcType = aReentrantMessage->typeOfCreation();
390 string(ARC_TYPE())->setValue(anArcType);
392 aFilledAttributeName = ARC_TYPE();
393 if(anArcType == ARC_TYPE_BY_TANGENT_EDGE()) {
394 aFilledAttributeName = TANGENT_POINT_ID();
395 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
396 attribute(aFilledAttributeName));
397 FeaturePtr aCreatedFeature = aReentrantMessage->createdFeature();
398 aRefAttr->setAttr(aCreatedFeature->attribute(SketchPlugin_Arc::END_ID()));
401 ObjectPtr anObject = aReentrantMessage->selectedObject();
402 AttributePtr anAttribute = aReentrantMessage->selectedAttribute();
403 std::shared_ptr<GeomAPI_Pnt2d> aClickedPoint = aReentrantMessage->clickedPoint();
405 if (aClickedPoint.get() && (anObject.get() || anAttribute.get())) {
406 if (anArcType == ARC_TYPE_BY_CENTER_AND_POINTS() ||
407 anArcType == ARC_TYPE_BY_THREE_POINTS()) {
408 std::string aReferenceAttributeName;
409 if (anArcType == ARC_TYPE_BY_CENTER_AND_POINTS()) {
410 aFilledAttributeName = CENTER_POINT_ID();
411 aReferenceAttributeName = CENTER_POINT_REF_ID();
414 aFilledAttributeName = START_POINT_2_ID();
415 aReferenceAttributeName = START_POINT_REF_ID();
417 // fill 2d point attribute
418 AttributePoint2DPtr aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
419 attribute(aFilledAttributeName));
420 aPointAttr->setValue(aClickedPoint);
421 // fill reference attribute
422 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
423 attribute(aReferenceAttributeName));
424 if (aRefAttr.get()) {
425 if (anAttribute.get()) {
426 if (!anAttribute->owner().get() || !anAttribute->owner()->data()->isValid()) {
427 FeaturePtr aCreatedFeature = aReentrantMessage->createdFeature();
428 if (aCreatedFeature.get()) {
429 std::string anID = anAttribute->id();
431 if (anID == END_POINT_1_ID() || anID == END_POINT_2_ID() ||
432 anID == END_POINT_3_ID())
433 anArcID = SketchPlugin_Arc::END_ID();
434 else if (anID == START_POINT_1_ID() || anID ==START_POINT_2_ID())
435 anArcID = SketchPlugin_Arc::START_ID();
436 else if (anID == CENTER_POINT_ID())
437 anArcID = SketchPlugin_Arc::CENTER_ID();
438 anAttribute = aCreatedFeature->attribute(anArcID);
441 aRefAttr->setAttr(anAttribute);
443 else if (anObject.get()) {
444 // if presentation of previous reentrant macro arc is used, the object is invalid,
445 // we should use result of previous feature of the message(Arc)
446 if (!anObject->data()->isValid()) {
447 FeaturePtr aCreatedFeature = aReentrantMessage->createdFeature();
448 if (aCreatedFeature.get())
449 anObject = aCreatedFeature->lastResult();
451 aRefAttr->setObject(anObject);
457 Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
459 return aFilledAttributeName;
462 FeaturePtr SketchPlugin_MacroArc::createArcFeature()
464 FeaturePtr anArcFeature = sketch()->addFeature(SketchPlugin_Arc::ID());
465 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
466 anArcFeature->attribute(SketchPlugin_Arc::CENTER_ID()))->setValue(myCenter);
467 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
468 anArcFeature->attribute(SketchPlugin_Arc::START_ID()))->setValue(myStart);
469 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
470 anArcFeature->attribute(SketchPlugin_Arc::END_ID()))->setValue(myEnd);
471 anArcFeature->boolean(SketchPlugin_Arc::REVERSED_ID())
472 ->setValue(boolean(REVERSED_ID())->value());
473 anArcFeature->boolean(SketchPlugin_Arc::AUXILIARY_ID())
474 ->setValue(boolean(AUXILIARY_ID())->value());
475 anArcFeature->execute();
480 void SketchPlugin_MacroArc::fillByCenterAndTwoPassed()
482 AttributePoint2DPtr aCenterPointAttr =
483 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(CENTER_POINT_ID()));
484 if (!aCenterPointAttr->isInitialized())
487 AttributePoint2DPtr aStartPointAttr =
488 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(START_POINT_1_ID()));
489 if (!aStartPointAttr->isInitialized())
492 myCenter = aCenterPointAttr->pnt();
493 myStart = aStartPointAttr->pnt();
496 AttributePoint2DPtr anEndPointAttr =
497 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(END_POINT_1_ID()));
498 if (!anEndPointAttr->isInitialized())
501 GeomAPI_Circ2d aCircleForArc(myCenter, myStart);
503 bool aWasBlocked = data()->blockSendAttributeUpdated(true);
504 // check the end point is referred to another feature
505 GeomShapePtr aRefShape;
506 AttributeRefAttrPtr aEndPointRefAttr = refattr(END_POINT_REF_ID());
507 if (aEndPointRefAttr && aEndPointRefAttr->isInitialized()) {
508 if (aEndPointRefAttr->isObject()) {
509 FeaturePtr aFeature = ModelAPI_Feature::feature(aEndPointRefAttr->object());
511 aRefShape = aFeature->lastResult()->shape();
515 // Calculate end point as an intersection between circle and another shape
516 intersectShapeAndCircle(aRefShape, aCircleForArc, sketch(), anEndPointAttr);
518 // End point should be a projection on circle.
519 projectPointOnCircle(anEndPointAttr, aCircleForArc);
521 data()->blockSendAttributeUpdated(aWasBlocked, false);
522 myEnd = anEndPointAttr->pnt();
524 // update the REVERSED flag
525 recalculateReversedFlagByEnd(aCircleForArc);
528 void SketchPlugin_MacroArc::recalculateReversedFlagByEnd(const GeomAPI_Circ2d& theCurrentCircular)
530 double aParameterNew = 0.0;
531 if(theCurrentCircular.parameter(myEnd, paramTolerance, aParameterNew)) {
532 if(myParamBefore <= PI / 2.0 && aParameterNew >= PI * 1.5) {
533 boolean(REVERSED_ID())->setValue(true);
534 } else if(myParamBefore >= PI * 1.5 && aParameterNew <= PI / 2.0) {
535 boolean(REVERSED_ID())->setValue(false);
538 myParamBefore = aParameterNew;
541 void SketchPlugin_MacroArc::fillByThreePassedPoints()
543 AttributePoint2DPtr aStartPointAttr =
544 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(START_POINT_2_ID()));
545 if (!aStartPointAttr->isInitialized())
548 AttributePoint2DPtr anEndPointAttr =
549 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(END_POINT_2_ID()));
550 if (!anEndPointAttr->isInitialized())
553 myStart = aStartPointAttr->pnt();
554 myEnd = anEndPointAttr->pnt();
556 AttributePoint2DPtr aPassedPointAttr =
557 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(PASSED_POINT_ID()));
558 if (aPassedPointAttr->isInitialized()) {
559 std::shared_ptr<GeomAPI_Pnt2d> aPassedPnt;
560 std::shared_ptr<GeomAPI_Shape> aTangentCurve;
561 SketchPlugin_Tools::convertRefAttrToPointOrTangentCurve(
562 refattr(PASSED_POINT_REF_ID()), aPassedPointAttr, aTangentCurve, aPassedPnt);
564 GeomAlgoAPI_Circ2dBuilder aCircBuilder(SketchPlugin_Sketch::plane(sketch()));
565 aCircBuilder.addPassingPoint(myStart);
566 aCircBuilder.addPassingPoint(myEnd);
568 aCircBuilder.addTangentCurve(aTangentCurve);
569 aCircBuilder.setClosestPoint(aPassedPointAttr->pnt());
571 aCircBuilder.addPassingPoint(aPassedPnt);
573 std::shared_ptr<GeomAPI_Circ2d> aCircle = aCircBuilder.circle();
576 myCenter = aCircle->center();
578 aCircle = std::shared_ptr<GeomAPI_Circ2d>(new GeomAPI_Circ2d(myCenter, myStart));
579 recalculateReversedFlagByPassed(*aCircle);
581 myCenter.reset(new GeomAPI_Pnt2d(myStart->xy()->added(myEnd->xy())->multiplied(0.5)));
584 void SketchPlugin_MacroArc::recalculateReversedFlagByPassed(
585 const GeomAPI_Circ2d& theCurrentCircular)
587 AttributePoint2DPtr aPassedAttr =
588 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(PASSED_POINT_ID()));
589 std::shared_ptr<GeomAPI_Pnt2d> aPassed = theCurrentCircular.project(aPassedAttr->pnt());
591 double aEndParam, aPassedParam;
592 theCurrentCircular.parameter(myEnd, paramTolerance, aEndParam);
593 theCurrentCircular.parameter(aPassed, paramTolerance, aPassedParam);
595 if(aPassedParam > aEndParam)
596 boolean(REVERSED_ID())->setValue(true);
598 boolean(REVERSED_ID())->setValue(false);
600 myParamBefore = aEndParam;
603 void SketchPlugin_MacroArc::fillByTangentEdge()
605 AttributeRefAttrPtr aTangentAttr = refattr(TANGENT_POINT_ID());
606 if (!aTangentAttr->isInitialized())
609 AttributePoint2DPtr aTangentPointAttr =
610 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aTangentAttr->attr());
611 if (!aTangentPointAttr->isInitialized())
614 AttributePoint2DPtr anEndPointAttr =
615 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(END_POINT_3_ID()));
616 if (!anEndPointAttr->isInitialized())
619 myStart = aTangentPointAttr->pnt();
620 myEnd = anEndPointAttr->pnt();
621 if (myStart->isEqual(myEnd))
624 // obtain a shape the tangent point belongs to
625 FeaturePtr aTangentFeature = ModelAPI_Feature::feature(aTangentPointAttr->owner());
626 std::shared_ptr<GeomAPI_Shape> aTangentShape = aTangentFeature->lastResult()->shape();
628 GeomAlgoAPI_Circ2dBuilder aCircBuilder(SketchPlugin_Sketch::plane(sketch()));
629 aCircBuilder.addPassingPoint(myStart);
630 aCircBuilder.addPassingPoint(myEnd);
631 aCircBuilder.addTangentCurve(aTangentShape);
633 std::shared_ptr<GeomAPI_Circ2d> aCircle = aCircBuilder.circle();
636 myCenter = aCircle->center();
638 // rebuild circle to set start point equal to zero parameter
639 aCircle = std::shared_ptr<GeomAPI_Circ2d>(new GeomAPI_Circ2d(myCenter, myStart));
640 recalculateReversedFlagByEnd(*aCircle);