X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchPlugin%2FSketchPlugin_MacroArc.cpp;h=5bbb322358f90792c725358c6a973603614ec281;hb=dfaa54ec6f09d6849c3e767d2d43e1a00935075b;hp=381326476f89da728a16c91b3a9c6c57d171db39;hpb=7ce002afbdd690bc3b278a15fe88439af53ac9e7;p=modules%2Fshaper.git diff --git a/src/SketchPlugin/SketchPlugin_MacroArc.cpp b/src/SketchPlugin/SketchPlugin_MacroArc.cpp index 381326476..5bbb32235 100644 --- a/src/SketchPlugin/SketchPlugin_MacroArc.cpp +++ b/src/SketchPlugin/SketchPlugin_MacroArc.cpp @@ -6,17 +6,22 @@ #include "SketchPlugin_MacroArc.h" +#include "SketchPlugin_Arc.h" +#include "SketchPlugin_ConstraintTangent.h" #include "SketchPlugin_Sketch.h" #include "SketchPlugin_Tools.h" +#include "SketchPlugin_MacroArcReentrantMessage.h" #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -24,12 +29,15 @@ #include #include #include +#include #include #include -#include + +#include #include #include +#include // for sqrt on Linux #include @@ -38,10 +46,81 @@ const double tolerance = 1e-7; const double paramTolerance = 1.e-4; const double PI = 3.141592653589793238463; +static void projectPointOnCircle(AttributePoint2DPtr& thePoint, const GeomAPI_Circ2d& theCircle) +{ + std::shared_ptr aProjection = theCircle.project(thePoint->pnt()); + if(aProjection.get()) + thePoint->setValue(aProjection); +} + +static void intersectShapeAndCircle(const GeomShapePtr& theShape, + const GeomAPI_Circ2d& theCircle, + const SketchPlugin_Sketch* theSketch, + AttributePoint2DPtr& theIntersection) +{ + if (!theShape->isEdge()) + return projectPointOnCircle(theIntersection, theCircle); + + // convert shape to unbounded + std::shared_ptr anEdge(new GeomAPI_Edge(theShape)); + if (anEdge->isLine()) { + static const double HALF_SIZE = 1.e6; + std::shared_ptr aLoc = anEdge->line()->location()->xyz(); + std::shared_ptr aDir = anEdge->line()->direction()->xyz(); + + std::shared_ptr aStart( + new GeomAPI_Pnt(aLoc->added(aDir->multiplied(-HALF_SIZE)))); + std::shared_ptr aEnd( + new GeomAPI_Pnt(aLoc->added(aDir->multiplied(HALF_SIZE)))); + anEdge = GeomAlgoAPI_EdgeBuilder::line(aStart, aEnd); + } else if (anEdge->isArc()) { + std::shared_ptr aCircle = anEdge->circle(); + anEdge = GeomAlgoAPI_EdgeBuilder::lineCircle( + aCircle->center(), aCircle->normal(), aCircle->radius()); + } + + // convert 2D circle to 3D object + std::shared_ptr aCenter2d = theCircle.center(); + std::shared_ptr aCenter(theSketch->to3D(aCenter2d->x(), aCenter2d->y())); + std::shared_ptr aNDir = std::dynamic_pointer_cast( + const_cast(theSketch)->attribute(SketchPlugin_Sketch::NORM_ID())); + std::shared_ptr aNormal(new GeomAPI_Dir(aNDir->x(), aNDir->y(), aNDir->z())); + + GeomShapePtr aCircleShape = + GeomAlgoAPI_EdgeBuilder::lineCircle(aCenter, aNormal, theCircle.radius()); + + GeomShapePtr anInter = anEdge->intersect(aCircleShape); + std::shared_ptr anInterPnt; + if (!anInter) + return projectPointOnCircle(theIntersection, theCircle); + if (anInter->isVertex()) { + std::shared_ptr aVertex(new GeomAPI_Vertex(anInter)); + anInterPnt = theSketch->to2D(aVertex->point()); + } else if (anInter->isCompound()) { + double aMinDist = 1.e300; + + GeomAPI_ShapeIterator anIt(anInter); + for (; anIt.more(); anIt.next()) { + GeomShapePtr aCurrent = anIt.current(); + if (!aCurrent->isVertex()) + continue; + std::shared_ptr aVertex(new GeomAPI_Vertex(aCurrent)); + std::shared_ptr aPnt = theSketch->to2D(aVertex->point()); + double aDist = aPnt->distance(theIntersection->pnt()); + if (aDist < aMinDist) { + aMinDist = aDist; + anInterPnt = aPnt; + } + } + } + if(anInterPnt.get()) { + theIntersection->setValue(anInterPnt); + } +} + SketchPlugin_MacroArc::SketchPlugin_MacroArc() : SketchPlugin_SketchEntity(), - myIsInversed(false), myParamBefore(0.0) { } @@ -61,6 +140,8 @@ void SketchPlugin_MacroArc::initAttributes() data()->addAttribute(TANGENT_POINT_ID(), ModelAPI_AttributeRefAttr::typeId()); data()->addAttribute(END_POINT_3_ID(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(REVERSED_ID(), ModelAPI_AttributeBoolean::typeId()); + data()->addAttribute(RADIUS_ID(), ModelAPI_AttributeDouble::typeId()); data()->addAttribute(ANGLE_ID(), ModelAPI_AttributeDouble::typeId()); @@ -71,10 +152,16 @@ void SketchPlugin_MacroArc::initAttributes() data()->addAttribute(END_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId()); data()->addAttribute(PASSED_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId()); + data()->addAttribute(EDIT_ARC_TYPE_ID(), ModelAPI_AttributeString::typeId()); + + boolean(REVERSED_ID())->setValue(false); + string(EDIT_ARC_TYPE_ID())->setValue(""); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CENTER_POINT_REF_ID()); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), START_POINT_REF_ID()); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), END_POINT_REF_ID()); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PASSED_POINT_REF_ID()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EDIT_ARC_TYPE_ID()); } void SketchPlugin_MacroArc::attributeChanged(const std::string& theID) @@ -83,185 +170,33 @@ void SketchPlugin_MacroArc::attributeChanged(const std::string& theID) // If arc type switched reset according attributes. if(theID == ARC_TYPE()) { - std::string aType = string(ARC_TYPE())->value(); - if(aType == ARC_TYPE_BY_CENTER_AND_POINTS()) { - SketchPlugin_Tools::resetAttribute(this, CENTER_POINT_ID()); - SketchPlugin_Tools::resetAttribute(this, CENTER_POINT_REF_ID()); - SketchPlugin_Tools::resetAttribute(this, START_POINT_1_ID()); - SketchPlugin_Tools::resetAttribute(this, START_POINT_REF_ID()); - SketchPlugin_Tools::resetAttribute(this, END_POINT_1_ID()); - SketchPlugin_Tools::resetAttribute(this, END_POINT_REF_ID()); - } else if(aType == ARC_TYPE_BY_THREE_POINTS()) { - SketchPlugin_Tools::resetAttribute(this, START_POINT_2_ID()); - SketchPlugin_Tools::resetAttribute(this, START_POINT_REF_ID()); - SketchPlugin_Tools::resetAttribute(this, END_POINT_2_ID()); - SketchPlugin_Tools::resetAttribute(this, END_POINT_REF_ID()); - SketchPlugin_Tools::resetAttribute(this, PASSED_POINT_ID()); - SketchPlugin_Tools::resetAttribute(this, PASSED_POINT_REF_ID()); - } else if(aType == ARC_TYPE_BY_TANGENT_EDGE()) { - SketchPlugin_Tools::resetAttribute(this, TANGENT_POINT_ID()); - SketchPlugin_Tools::resetAttribute(this, END_POINT_3_ID()); - SketchPlugin_Tools::resetAttribute(this, END_POINT_REF_ID()); - } + SketchPlugin_Tools::resetAttribute(this, CENTER_POINT_ID()); + SketchPlugin_Tools::resetAttribute(this, CENTER_POINT_REF_ID()); + SketchPlugin_Tools::resetAttribute(this, START_POINT_1_ID()); + SketchPlugin_Tools::resetAttribute(this, START_POINT_REF_ID()); + SketchPlugin_Tools::resetAttribute(this, END_POINT_1_ID()); + SketchPlugin_Tools::resetAttribute(this, END_POINT_REF_ID()); + SketchPlugin_Tools::resetAttribute(this, START_POINT_2_ID()); + SketchPlugin_Tools::resetAttribute(this, END_POINT_2_ID()); + SketchPlugin_Tools::resetAttribute(this, PASSED_POINT_ID()); + SketchPlugin_Tools::resetAttribute(this, PASSED_POINT_REF_ID()); + SketchPlugin_Tools::resetAttribute(this, TANGENT_POINT_ID()); + SketchPlugin_Tools::resetAttribute(this, END_POINT_3_ID()); + SketchPlugin_Tools::resetAttribute(this, REVERSED_ID()); + SketchPlugin_Tools::resetAttribute(this, RADIUS_ID()); + SketchPlugin_Tools::resetAttribute(this, ANGLE_ID()); myCenter.reset(); myStart.reset(); myEnd.reset(); - myIsInversed = false; + boolean(REVERSED_ID())->setValue(false); myParamBefore = 0.0; - } else if(anArcType == ARC_TYPE_BY_CENTER_AND_POINTS()) { - std::shared_ptr aCenterPointAttr = - std::dynamic_pointer_cast(attribute(CENTER_POINT_ID())); - if(!aCenterPointAttr->isInitialized()) { - return; - } - std::shared_ptr aStartPointAttr = - std::dynamic_pointer_cast(attribute(START_POINT_1_ID())); - if(!aStartPointAttr->isInitialized()) { - return; - } - - myCenter = aCenterPointAttr->pnt(); - myStart = aStartPointAttr->pnt(); - myEnd = myStart; - - std::shared_ptr anEndPointAttr = - std::dynamic_pointer_cast(attribute(END_POINT_1_ID())); - if(anEndPointAttr->isInitialized()) { - // End point should be a projection on circle. - GeomAPI_Circ2d aCircleForArc(myCenter, myStart); - std::shared_ptr aProjection = aCircleForArc.project(anEndPointAttr->pnt()); - if(aProjection.get()) { - bool aWasBlocked = data()->blockSendAttributeUpdated(true); - anEndPointAttr->setValue(aProjection); - data()->blockSendAttributeUpdated(aWasBlocked, false); - } - myEnd = anEndPointAttr->pnt(); - - double aParameterNew = 0.0; - if(aCircleForArc.parameter(myEnd, paramTolerance, aParameterNew)) { - if(myParamBefore <= PI / 2.0 && aParameterNew >= PI * 1.5) { - myIsInversed = true; - } else if(myParamBefore >= PI * 1.5 && aParameterNew <= PI / 2.0) { - myIsInversed = false; - } - } - myParamBefore = aParameterNew; - } - } else if(anArcType == ARC_TYPE_BY_THREE_POINTS()) { - std::shared_ptr aStartPointAttr = - std::dynamic_pointer_cast(attribute(START_POINT_2_ID())); - if(!aStartPointAttr->isInitialized()) { - return; - } - std::shared_ptr anEndPointAttr = - std::dynamic_pointer_cast(attribute(END_POINT_2_ID())); - if(!anEndPointAttr->isInitialized()) { - return; - } - - myStart = aStartPointAttr->pnt(); - myEnd = anEndPointAttr->pnt(); - - std::shared_ptr aPassedPointAttr = - std::dynamic_pointer_cast(attribute(PASSED_POINT_ID())); - if(aPassedPointAttr->isInitialized()) { - std::shared_ptr aPassed = aPassedPointAttr->pnt(); - GeomAPI_Circ2d aCircle(myStart, myEnd, aPassed); - myCenter = aCircle.center(); - aCircle = GeomAPI_Circ2d(myCenter, myStart); - double anEndParam, aPassedParam; - aCircle.parameter(myEnd, paramTolerance, anEndParam); - aCircle.parameter(aPassed, paramTolerance, aPassedParam); - if(aPassedParam > anEndParam) { - myIsInversed = true; - } else { - myIsInversed = false; - } - } else { - std::shared_ptr aDir = myEnd->xy()->decreased(myStart->xy())->multiplied(0.5); - double x = aDir->x(); - double y = aDir->y(); - aDir->setX(x - y); - aDir->setY(y + x); - myCenter.reset(new GeomAPI_Pnt2d(myStart->xy()->added(aDir))); - } - } else if(anArcType == ARC_TYPE_BY_TANGENT_EDGE()) { - AttributeRefAttrPtr aTangentAttr = refattr(TANGENT_POINT_ID()); - if(!aTangentAttr->isInitialized()) { - return; - } - std::shared_ptr aTangentPointAttr = - std::dynamic_pointer_cast(aTangentAttr->attr()); - if(!aTangentPointAttr->isInitialized()) { - return; - } - std::shared_ptr anEndPointAttr = - std::dynamic_pointer_cast(attribute(END_POINT_3_ID())); - if(!anEndPointAttr->isInitialized()) { - return; - } - - myStart = aTangentPointAttr->pnt(); - myEnd = anEndPointAttr->pnt(); - - if(myStart->isEqual(myEnd)) { - return; - } - - SketchPlugin_Sketch* aSketch = sketch(); - if(!aSketch) { - return; - } - - std::shared_ptr anOrthoDir; - FeaturePtr aTangFeature = ModelAPI_Feature::feature(aTangentPointAttr->owner()); - std::shared_ptr aTangEdge = - std::dynamic_pointer_cast(aTangFeature->lastResult()->shape()); - if(aTangEdge->isLine()) { - std::shared_ptr aDir = aTangEdge->line()->direction(); - std::shared_ptr aPnt(new GeomAPI_Pnt(aDir->x(), aDir->y(), aDir->z())); - std::shared_ptr aPnt2d = aSketch->to2D(aPnt); - anOrthoDir = std::shared_ptr(new GeomAPI_Dir2d(-aPnt2d->y(), aPnt2d->x())); - } - else if (aTangEdge->isArc()) { - std::shared_ptr aCenter = aTangEdge->circle()->center(); - std::shared_ptr aCenter2d = aSketch->to2D(aCenter); - anOrthoDir = std::shared_ptr( - new GeomAPI_Dir2d(myStart->xy()->decreased(aCenter2d->xy()))); - } - - // compute parameters of the middle perpendicular - std::shared_ptr aEndPntCoord = myEnd->xy(); - std::shared_ptr aTempDir = aEndPntCoord->decreased(myStart->xy()); - std::shared_ptr aMidDir(new GeomAPI_Dir2d(-aTempDir->y(), aTempDir->x())); - std::shared_ptr aMidPnt( - new GeomAPI_Pnt2d(aEndPntCoord->added(myStart->xy())->multiplied(0.5))); - - // compute center of arc by calculating intersection of - // orthogonal line and middle perpendicular - std::shared_ptr anOrthoLine(new GeomAPI_Lin2d(myStart, anOrthoDir)); - std::shared_ptr aMiddleLine(new GeomAPI_Lin2d(aMidPnt, aMidDir)); - std::shared_ptr aCenter = anOrthoLine->intersect(aMiddleLine); - if(aCenter) { - myCenter = aCenter; - } - - GeomAPI_Circ2d aCircleForArc(myCenter, myStart); - double aParameterNew = 0.0; - if(aCircleForArc.parameter(myEnd, paramTolerance, aParameterNew)) { - if(myParamBefore <= PI / 2.0 && aParameterNew >= PI * 1.5) { - if(!myIsInversed) { - myIsInversed = true; - } - } else if(myParamBefore >= PI * 1.5 && aParameterNew <= PI / 2.0) { - if(myIsInversed) { - myIsInversed = false; - } - } - } - myParamBefore = aParameterNew; - } + } else if(anArcType == ARC_TYPE_BY_CENTER_AND_POINTS()) + fillByCenterAndTwoPassed(); + else if(anArcType == ARC_TYPE_BY_THREE_POINTS()) + fillByThreePassedPoints(); + else if(anArcType == ARC_TYPE_BY_TANGENT_EDGE()) + fillByTangentEdge(); double aRadius = 0; double anAngle = 0; @@ -276,17 +211,53 @@ void SketchPlugin_MacroArc::attributeChanged(const std::string& theID) aCircleForArc.parameter(myStart, paramTolerance, aStartParam); aCircleForArc.parameter(myEnd, paramTolerance, anEndParam); anAngle = (anEndParam - aStartParam) / PI * 180.0; - if(myIsInversed) anAngle = 360.0 - anAngle; + if(boolean(REVERSED_ID())->value()) anAngle = 360.0 - anAngle; } } } bool aWasBlocked = data()->blockSendAttributeUpdated(true); + if(myCenter.get()) { + // center attribute is used in processEvent() to set reference to reentrant arc + std::dynamic_pointer_cast(attribute(CENTER_POINT_ID())) + ->setValue(myCenter); + } real(RADIUS_ID())->setValue(aRadius); real(ANGLE_ID())->setValue(anAngle); data()->blockSendAttributeUpdated(aWasBlocked, false); } +GeomShapePtr SketchPlugin_MacroArc::getArcShape(bool isBound) +{ + if(!myStart.get() || !myEnd.get() || !myCenter.get()) { + return GeomShapePtr(); + } + + SketchPlugin_Sketch* aSketch = sketch(); + if(!aSketch) { + return GeomShapePtr(); + } + + std::shared_ptr aCenter(aSketch->to3D(myCenter->x(), myCenter->y())); + std::shared_ptr aStart(aSketch->to3D(myStart->x(), myStart->y())); + std::shared_ptr anEnd(aSketch->to3D(myEnd->x(), myEnd->y())); + std::shared_ptr aNDir = + std::dynamic_pointer_cast(aSketch->attribute(SketchPlugin_Sketch::NORM_ID())); + std::shared_ptr aNormal(new GeomAPI_Dir(aNDir->x(), aNDir->y(), aNDir->z())); + + GeomShapePtr anArcShape; + if (isBound) { + anArcShape = boolean(REVERSED_ID())->value() ? + GeomAlgoAPI_EdgeBuilder::lineCircleArc(aCenter, anEnd, aStart, aNormal) + : GeomAlgoAPI_EdgeBuilder::lineCircleArc(aCenter, aStart, anEnd, aNormal); + } else { + double aRadius = aCenter->distance(aStart); + anArcShape = GeomAlgoAPI_EdgeBuilder::lineCircle(aCenter, aNormal, aRadius); + } + + return anArcShape; +} + AISObjectPtr SketchPlugin_MacroArc::getAISObject(AISObjectPtr thePrevious) { if(!myStart.get() || !myEnd.get() || !myCenter.get()) { @@ -298,17 +269,8 @@ AISObjectPtr SketchPlugin_MacroArc::getAISObject(AISObjectPtr thePrevious) return AISObjectPtr(); } - std::shared_ptr aStart = aSketch->to3D(myStart->x(), myStart->y()); - std::shared_ptr anEnd = aSketch->to3D(myEnd->x(), myEnd->y()); + GeomShapePtr anArcShape = getArcShape(); std::shared_ptr aCenter = aSketch->to3D(myCenter->x(), myCenter->y());; - - std::shared_ptr aNDir = - std::dynamic_pointer_cast( - aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID())); - std::shared_ptr aNormal = aNDir->dir(); - GeomShapePtr anArcShape = myIsInversed ? - GeomAlgoAPI_EdgeBuilder::lineCircleArc(aCenter, anEnd, aStart, aNormal) - : GeomAlgoAPI_EdgeBuilder::lineCircleArc(aCenter, aStart, anEnd, aNormal); GeomShapePtr aCenterPointShape = GeomAlgoAPI_PointBuilder::vertex(aCenter); if(!anArcShape.get() || !aCenterPointShape.get()) { @@ -330,4 +292,335 @@ AISObjectPtr SketchPlugin_MacroArc::getAISObject(AISObjectPtr thePrevious) void SketchPlugin_MacroArc::execute() { + FeaturePtr anArcFeature = createArcFeature(); + + myCenter.reset(); + myStart.reset(); + myEnd.reset(); + + // Create constraints. + std::string anArcType = string(ARC_TYPE())->value(); + if(anArcType == ARC_TYPE_BY_CENTER_AND_POINTS()) { + SketchPlugin_Tools::createConstraint(this, + CENTER_POINT_REF_ID(), + anArcFeature->attribute(SketchPlugin_Arc::CENTER_ID()), + ObjectPtr(), + false); + SketchPlugin_Tools::createConstraint(this, + START_POINT_REF_ID(), + anArcFeature->attribute(SketchPlugin_Arc::START_ID()), + ObjectPtr(), + false); + SketchPlugin_Tools::createConstraint(this, + END_POINT_REF_ID(), + anArcFeature->attribute(SketchPlugin_Arc::END_ID()), + ObjectPtr(), + false); + } else if(anArcType == ARC_TYPE_BY_THREE_POINTS()) { + SketchPlugin_Tools::createConstraint(this, + START_POINT_REF_ID(), + anArcFeature->attribute(SketchPlugin_Arc::START_ID()), + ObjectPtr(), + false); + SketchPlugin_Tools::createConstraint(this, + END_POINT_REF_ID(), + anArcFeature->attribute(SketchPlugin_Arc::END_ID()), + ObjectPtr(), + false); + SketchPlugin_Tools::createConstraint(this, + PASSED_POINT_REF_ID(), + AttributePtr(), + anArcFeature->lastResult(), + true); + } else if(anArcType == ARC_TYPE_BY_TANGENT_EDGE()) { + // constraints for tangent arc + SketchPlugin_Tools::createConstraint(this, + TANGENT_POINT_ID(), + anArcFeature->attribute(SketchPlugin_Arc::START_ID()), + ObjectPtr(), + false); + FeaturePtr aTangent = sketch()->addFeature(SketchPlugin_ConstraintTangent::ID()); + AttributeRefAttrPtr aRefAttrA = aTangent->refattr(SketchPlugin_Constraint::ENTITY_A()); + AttributeRefAttrPtr aTgPntRefAttr = refattr(TANGENT_POINT_ID()); + FeaturePtr aTgFeature = ModelAPI_Feature::feature(aTgPntRefAttr->attr()->owner()); + aRefAttrA->setObject(aTgFeature->lastResult()); + AttributeRefAttrPtr aRefAttrB = aTangent->refattr(SketchPlugin_Constraint::ENTITY_B()); + aRefAttrB->setObject(anArcFeature->lastResult()); + // constraint for end point + SketchPlugin_Tools::createConstraint(this, + END_POINT_REF_ID(), + anArcFeature->attribute(SketchPlugin_Arc::END_ID()), + ObjectPtr(), + false); + } + + // message to init reentrant operation + static Events_ID anId = SketchPlugin_MacroArcReentrantMessage::eventId(); + std::shared_ptr aMessage = std::shared_ptr + (new SketchPlugin_MacroArcReentrantMessage(anId, this)); + + std::string anEditArcType = string(EDIT_ARC_TYPE_ID())->value(); + aMessage->setTypeOfCreation(!anEditArcType.empty() ? anEditArcType : anArcType); + aMessage->setCreatedFeature(anArcFeature); + Events_Loop::loop()->send(aMessage); +} + +std::string SketchPlugin_MacroArc::processEvent(const std::shared_ptr& theMessage) +{ + std::string aFilledAttributeName; + std::shared_ptr aReentrantMessage = + std::dynamic_pointer_cast(theMessage); + if (aReentrantMessage.get()) { + FeaturePtr aCreatedFeature = aReentrantMessage->createdFeature(); + std::string anArcType = aReentrantMessage->typeOfCreation(); + + string(ARC_TYPE())->setValue(anArcType); + + aFilledAttributeName = ARC_TYPE(); + if(anArcType == ARC_TYPE_BY_TANGENT_EDGE()) { + aFilledAttributeName = TANGENT_POINT_ID(); + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast( + attribute(aFilledAttributeName)); + FeaturePtr aCreatedFeature = aReentrantMessage->createdFeature(); + aRefAttr->setAttr(aCreatedFeature->attribute(SketchPlugin_Arc::END_ID())); + } + else { + ObjectPtr anObject = aReentrantMessage->selectedObject(); + AttributePtr anAttribute = aReentrantMessage->selectedAttribute(); + std::shared_ptr aClickedPoint = aReentrantMessage->clickedPoint(); + + if (aClickedPoint.get() && (anObject.get() || anAttribute.get())) { + if (anArcType == ARC_TYPE_BY_CENTER_AND_POINTS() || + anArcType == ARC_TYPE_BY_THREE_POINTS()) { + std::string aReferenceAttributeName; + if (anArcType == ARC_TYPE_BY_CENTER_AND_POINTS()) { + aFilledAttributeName = CENTER_POINT_ID(); + aReferenceAttributeName = CENTER_POINT_REF_ID(); + } + else { + aFilledAttributeName = START_POINT_2_ID(); + aReferenceAttributeName = START_POINT_REF_ID(); + } + // fill 2d point attribute + AttributePoint2DPtr aPointAttr = std::dynamic_pointer_cast( + attribute(aFilledAttributeName)); + aPointAttr->setValue(aClickedPoint); + // fill reference attribute + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast( + attribute(aReferenceAttributeName)); + if (aRefAttr.get()) { + if (anAttribute.get()) { + if (!anAttribute->owner().get() || !anAttribute->owner()->data()->isValid()) { + FeaturePtr aCreatedFeature = aReentrantMessage->createdFeature(); + if (aCreatedFeature.get()) { + std::string anID = anAttribute->id(); + std::string anArcID; + if (anID == END_POINT_1_ID() || anID == END_POINT_2_ID() || + anID == END_POINT_3_ID()) + anArcID = SketchPlugin_Arc::END_ID(); + else if (anID == START_POINT_1_ID() || anID ==START_POINT_2_ID()) + anArcID = SketchPlugin_Arc::START_ID(); + else if (anID == CENTER_POINT_ID()) + anArcID = SketchPlugin_Arc::CENTER_ID(); + anAttribute = aCreatedFeature->attribute(anArcID); + } + } + aRefAttr->setAttr(anAttribute); + } + else if (anObject.get()) { + // if presentation of previous reentrant macro arc is used, the object is invalid, + // we should use result of previous feature of the message(Arc) + if (!anObject->data()->isValid()) { + FeaturePtr aCreatedFeature = aReentrantMessage->createdFeature(); + if (aCreatedFeature.get()) + anObject = aCreatedFeature->lastResult(); + } + aRefAttr->setObject(anObject); + } + } + } + } + } + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED)); + } + return aFilledAttributeName; +} + +FeaturePtr SketchPlugin_MacroArc::createArcFeature() +{ + FeaturePtr anArcFeature = sketch()->addFeature(SketchPlugin_Arc::ID()); + std::dynamic_pointer_cast( + anArcFeature->attribute(SketchPlugin_Arc::CENTER_ID()))->setValue(myCenter); + std::dynamic_pointer_cast( + anArcFeature->attribute(SketchPlugin_Arc::START_ID()))->setValue(myStart); + std::dynamic_pointer_cast( + anArcFeature->attribute(SketchPlugin_Arc::END_ID()))->setValue(myEnd); + anArcFeature->boolean(SketchPlugin_Arc::REVERSED_ID()) + ->setValue(boolean(REVERSED_ID())->value()); + anArcFeature->boolean(SketchPlugin_Arc::AUXILIARY_ID()) + ->setValue(boolean(AUXILIARY_ID())->value()); + anArcFeature->execute(); + + return anArcFeature; +} + +void SketchPlugin_MacroArc::fillByCenterAndTwoPassed() +{ + AttributePoint2DPtr aCenterPointAttr = + std::dynamic_pointer_cast(attribute(CENTER_POINT_ID())); + if (!aCenterPointAttr->isInitialized()) + return; + + AttributePoint2DPtr aStartPointAttr = + std::dynamic_pointer_cast(attribute(START_POINT_1_ID())); + if (!aStartPointAttr->isInitialized()) + return; + + myCenter = aCenterPointAttr->pnt(); + myStart = aStartPointAttr->pnt(); + myEnd = myStart; + + AttributePoint2DPtr anEndPointAttr = + std::dynamic_pointer_cast(attribute(END_POINT_1_ID())); + if (!anEndPointAttr->isInitialized()) + return; + + GeomAPI_Circ2d aCircleForArc(myCenter, myStart); + + bool aWasBlocked = data()->blockSendAttributeUpdated(true); + // check the end point is referred to another feature + GeomShapePtr aRefShape; + AttributeRefAttrPtr aEndPointRefAttr = refattr(END_POINT_REF_ID()); + if (aEndPointRefAttr && aEndPointRefAttr->isInitialized()) { + if (aEndPointRefAttr->isObject()) { + FeaturePtr aFeature = ModelAPI_Feature::feature(aEndPointRefAttr->object()); + if (aFeature) + aRefShape = aFeature->lastResult()->shape(); + } + } + if (aRefShape) { + // Calculate end point as an intersection between circle and another shape + intersectShapeAndCircle(aRefShape, aCircleForArc, sketch(), anEndPointAttr); + } else { + // End point should be a projection on circle. + projectPointOnCircle(anEndPointAttr, aCircleForArc); + } + data()->blockSendAttributeUpdated(aWasBlocked, false); + myEnd = anEndPointAttr->pnt(); + + // update the REVERSED flag + recalculateReversedFlagByEnd(aCircleForArc); +} + +void SketchPlugin_MacroArc::recalculateReversedFlagByEnd(const GeomAPI_Circ2d& theCurrentCircular) +{ + double aParameterNew = 0.0; + if(theCurrentCircular.parameter(myEnd, paramTolerance, aParameterNew)) { + if(myParamBefore <= PI / 2.0 && aParameterNew >= PI * 1.5) { + boolean(REVERSED_ID())->setValue(true); + } else if(myParamBefore >= PI * 1.5 && aParameterNew <= PI / 2.0) { + boolean(REVERSED_ID())->setValue(false); + } + } + myParamBefore = aParameterNew; +} + +void SketchPlugin_MacroArc::fillByThreePassedPoints() +{ + AttributePoint2DPtr aStartPointAttr = + std::dynamic_pointer_cast(attribute(START_POINT_2_ID())); + if (!aStartPointAttr->isInitialized()) + return; + + AttributePoint2DPtr anEndPointAttr = + std::dynamic_pointer_cast(attribute(END_POINT_2_ID())); + if (!anEndPointAttr->isInitialized()) + return; + + myStart = aStartPointAttr->pnt(); + myEnd = anEndPointAttr->pnt(); + + AttributePoint2DPtr aPassedPointAttr = + std::dynamic_pointer_cast(attribute(PASSED_POINT_ID())); + if (aPassedPointAttr->isInitialized()) { + std::shared_ptr aPassedPnt; + std::shared_ptr aTangentCurve; + SketchPlugin_Tools::convertRefAttrToPointOrTangentCurve( + refattr(PASSED_POINT_REF_ID()), aPassedPointAttr, aTangentCurve, aPassedPnt); + + GeomAlgoAPI_Circ2dBuilder aCircBuilder(SketchPlugin_Sketch::plane(sketch())); + aCircBuilder.addPassingPoint(myStart); + aCircBuilder.addPassingPoint(myEnd); + if (aTangentCurve) { + aCircBuilder.addTangentCurve(aTangentCurve); + aCircBuilder.setClosestPoint(aPassedPointAttr->pnt()); + } else + aCircBuilder.addPassingPoint(aPassedPnt); + + std::shared_ptr aCircle = aCircBuilder.circle(); + if (!aCircle) + return; + myCenter = aCircle->center(); + + aCircle = std::shared_ptr(new GeomAPI_Circ2d(myCenter, myStart)); + recalculateReversedFlagByPassed(*aCircle); + } else + myCenter.reset(new GeomAPI_Pnt2d(myStart->xy()->added(myEnd->xy())->multiplied(0.5))); +} + +void SketchPlugin_MacroArc::recalculateReversedFlagByPassed( + const GeomAPI_Circ2d& theCurrentCircular) +{ + AttributePoint2DPtr aPassedAttr = + std::dynamic_pointer_cast(attribute(PASSED_POINT_ID())); + std::shared_ptr aPassed = theCurrentCircular.project(aPassedAttr->pnt()); + + double aEndParam, aPassedParam; + theCurrentCircular.parameter(myEnd, paramTolerance, aEndParam); + theCurrentCircular.parameter(aPassed, paramTolerance, aPassedParam); + + if(aPassedParam > aEndParam) + boolean(REVERSED_ID())->setValue(true); + else + boolean(REVERSED_ID())->setValue(false); + + myParamBefore = aEndParam; +} + +void SketchPlugin_MacroArc::fillByTangentEdge() +{ + AttributeRefAttrPtr aTangentAttr = refattr(TANGENT_POINT_ID()); + if (!aTangentAttr->isInitialized()) + return; + + AttributePoint2DPtr aTangentPointAttr = + std::dynamic_pointer_cast(aTangentAttr->attr()); + if (!aTangentPointAttr->isInitialized()) + return; + + AttributePoint2DPtr anEndPointAttr = + std::dynamic_pointer_cast(attribute(END_POINT_3_ID())); + if (!anEndPointAttr->isInitialized()) + return; + + myStart = aTangentPointAttr->pnt(); + myEnd = anEndPointAttr->pnt(); + if (myStart->isEqual(myEnd)) + return; + + // obtain a shape the tangent point belongs to + FeaturePtr aTangentFeature = ModelAPI_Feature::feature(aTangentPointAttr->owner()); + std::shared_ptr aTangentShape = aTangentFeature->lastResult()->shape(); + + GeomAlgoAPI_Circ2dBuilder aCircBuilder(SketchPlugin_Sketch::plane(sketch())); + aCircBuilder.addPassingPoint(myStart); + aCircBuilder.addPassingPoint(myEnd); + aCircBuilder.addTangentCurve(aTangentShape); + + std::shared_ptr aCircle = aCircBuilder.circle(); + myCenter = aCircle->center(); + + // rebuild circle to set start point equal to zero parameter + aCircle = std::shared_ptr(new GeomAPI_Circ2d(myCenter, myStart)); + recalculateReversedFlagByEnd(*aCircle); }