X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchPlugin%2FSketchPlugin_MacroArc.cpp;h=936163dc6f011938e67ca43afd9ecf1f6136adb3;hb=46c0759fa291dad10b713cf02b341d6e9e60c1a4;hp=de876dc966b433630f81fa2bd1f576587de39421;hpb=a2ab2dc339b560c7309540e1f10b6ad60e5ed0af;p=modules%2Fshaper.git diff --git a/src/SketchPlugin/SketchPlugin_MacroArc.cpp b/src/SketchPlugin/SketchPlugin_MacroArc.cpp index de876dc96..936163dc6 100644 --- a/src/SketchPlugin/SketchPlugin_MacroArc.cpp +++ b/src/SketchPlugin/SketchPlugin_MacroArc.cpp @@ -1,19 +1,35 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> - -// File: SketchPlugin_MacroArc.cpp -// Created: 26 Apr 2014 -// Author: Artem ZHIDKOV +// Copyright (C) 2014-2020 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// #include "SketchPlugin_MacroArc.h" #include "SketchPlugin_Arc.h" +#include "SketchPlugin_ConstraintPerpendicular.h" #include "SketchPlugin_ConstraintTangent.h" #include "SketchPlugin_Sketch.h" #include "SketchPlugin_Tools.h" +#include "SketchPlugin_MacroArcReentrantMessage.h" #include #include #include +#include #include #include @@ -27,12 +43,15 @@ #include #include #include +#include #include #include -#include + +#include #include #include +#include // for sqrt on Linux #include @@ -48,6 +67,71 @@ static void projectPointOnCircle(AttributePoint2DPtr& thePoint, const GeomAPI_Ci 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(), @@ -70,6 +154,9 @@ void SketchPlugin_MacroArc::initAttributes() data()->addAttribute(TANGENT_POINT_ID(), ModelAPI_AttributeRefAttr::typeId()); data()->addAttribute(END_POINT_3_ID(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(TRANSVERSAL_POINT_ID(), ModelAPI_AttributeRefAttr::typeId()); + data()->addAttribute(END_POINT_4_ID(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(REVERSED_ID(), ModelAPI_AttributeBoolean::typeId()); data()->addAttribute(RADIUS_ID(), ModelAPI_AttributeDouble::typeId()); @@ -82,12 +169,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) @@ -108,6 +199,8 @@ void SketchPlugin_MacroArc::attributeChanged(const std::string& theID) 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, TRANSVERSAL_POINT_ID()); + SketchPlugin_Tools::resetAttribute(this, END_POINT_4_ID()); SketchPlugin_Tools::resetAttribute(this, REVERSED_ID()); SketchPlugin_Tools::resetAttribute(this, RADIUS_ID()); SketchPlugin_Tools::resetAttribute(this, ANGLE_ID()); @@ -122,7 +215,9 @@ void SketchPlugin_MacroArc::attributeChanged(const std::string& theID) else if(anArcType == ARC_TYPE_BY_THREE_POINTS()) fillByThreePassedPoints(); else if(anArcType == ARC_TYPE_BY_TANGENT_EDGE()) - fillByTangentEdge(); + fillByEdge(false); + else if (anArcType == ARC_TYPE_BY_TRANSVERSAL_LINE()) + fillByEdge(true); double aRadius = 0; double anAngle = 0; @@ -143,12 +238,17 @@ void SketchPlugin_MacroArc::attributeChanged(const std::string& theID) } 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() +GeomShapePtr SketchPlugin_MacroArc::getArcShape(bool isBound) { if(!myStart.get() || !myEnd.get() || !myCenter.get()) { return GeomShapePtr(); @@ -166,31 +266,31 @@ GeomShapePtr SketchPlugin_MacroArc::getArcShape() 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 = boolean(REVERSED_ID())->value() ? - GeomAlgoAPI_EdgeBuilder::lineCircleArc(aCenter, anEnd, aStart, aNormal) - : GeomAlgoAPI_EdgeBuilder::lineCircleArc(aCenter, aStart, anEnd, aNormal); + 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()) { + GeomShapePtr anArcShape = getArcShape(); + if(!anArcShape.get()) return AISObjectPtr(); - } SketchPlugin_Sketch* aSketch = sketch(); - if(!aSketch) { - return AISObjectPtr(); - } - - GeomShapePtr anArcShape = getArcShape(); std::shared_ptr aCenter = aSketch->to3D(myCenter->x(), myCenter->y());; GeomShapePtr aCenterPointShape = GeomAlgoAPI_PointBuilder::vertex(aCenter); - if(!anArcShape.get() || !aCenterPointShape.get()) { + if(!aCenterPointShape.get()) return AISObjectPtr(); - } std::list > aShapes; aShapes.push_back(anArcShape); @@ -202,6 +302,7 @@ AISObjectPtr SketchPlugin_MacroArc::getAISObject(AISObjectPtr thePrevious) anAIS.reset(new GeomAPI_AISObject()); } anAIS->createShape(aCompound); + SketchPlugin_Tools::customizeFeaturePrs(anAIS, boolean(AUXILIARY_ID())->value()); return anAIS; } @@ -216,60 +317,165 @@ void SketchPlugin_MacroArc::execute() // Create constraints. std::string anArcType = string(ARC_TYPE())->value(); if(anArcType == ARC_TYPE_BY_CENTER_AND_POINTS()) { - SketchPlugin_Tools::createConstraint(this, + SketchPlugin_Tools::createCoincidenceOrTangency(this, CENTER_POINT_REF_ID(), anArcFeature->attribute(SketchPlugin_Arc::CENTER_ID()), ObjectPtr(), false); - SketchPlugin_Tools::createConstraint(this, + SketchPlugin_Tools::createCoincidenceOrTangency(this, START_POINT_REF_ID(), anArcFeature->attribute(SketchPlugin_Arc::START_ID()), ObjectPtr(), false); - SketchPlugin_Tools::createConstraint(this, + SketchPlugin_Tools::createCoincidenceOrTangency(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, + SketchPlugin_Tools::createCoincidenceOrTangency(this, START_POINT_REF_ID(), anArcFeature->attribute(SketchPlugin_Arc::START_ID()), ObjectPtr(), false); - SketchPlugin_Tools::createConstraint(this, + SketchPlugin_Tools::createCoincidenceOrTangency(this, END_POINT_REF_ID(), anArcFeature->attribute(SketchPlugin_Arc::END_ID()), ObjectPtr(), false); - SketchPlugin_Tools::createConstraint(this, + SketchPlugin_Tools::createCoincidenceOrTangency(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(), + } else { + // coincident with connection point + const std::string& aPointAttr = anArcType == ARC_TYPE_BY_TANGENT_EDGE() ? + TANGENT_POINT_ID() : TRANSVERSAL_POINT_ID(); + SketchPlugin_Tools::createCoincidenceOrTangency(this, + aPointAttr, 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()); + // tangent or perpendicular constraint + FeaturePtr aStartPointConstraint; + if (anArcType == ARC_TYPE_BY_TANGENT_EDGE()) + aStartPointConstraint = sketch()->addFeature(SketchPlugin_ConstraintTangent::ID()); + else + aStartPointConstraint = sketch()->addFeature(SketchPlugin_ConstraintPerpendicular::ID()); + // setting attributes of the start point constraint + AttributeRefAttrPtr aRefAttrA = + aStartPointConstraint->refattr(SketchPlugin_Constraint::ENTITY_A()); + AttributeRefAttrPtr aTgPntRefAttr = refattr(aPointAttr); FeaturePtr aTgFeature = ModelAPI_Feature::feature(aTgPntRefAttr->attr()->owner()); aRefAttrA->setObject(aTgFeature->lastResult()); - AttributeRefAttrPtr aRefAttrB = aTangent->refattr(SketchPlugin_Constraint::ENTITY_B()); + AttributeRefAttrPtr aRefAttrB = + aStartPointConstraint->refattr(SketchPlugin_Constraint::ENTITY_B()); aRefAttrB->setObject(anArcFeature->lastResult()); // constraint for end point - SketchPlugin_Tools::createConstraint(this, + SketchPlugin_Tools::createCoincidenceOrTangency(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); } +// LCOV_EXCL_START +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 = refattr(aFilledAttributeName); + aRefAttr->setAttr(aCreatedFeature->attribute(SketchPlugin_Arc::END_ID())); + } + else if (anArcType == ARC_TYPE_BY_TRANSVERSAL_LINE()) { + AttributeRefAttrPtr aRefAttr = refattr(TRANSVERSAL_POINT_ID()); + AttributePtr anAttribute = aReentrantMessage->selectedAttribute(); + if (anAttribute) { + aRefAttr->setAttr(anAttribute); + aFilledAttributeName = TRANSVERSAL_POINT_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()) { + 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 attribute is NULL, only object is defined, it should be processed outside + // the feature because it might be an external feature, that will be + // removed/created again after restart operation + // #2468 - Crash when sketching circles successively on a repetition + aFilledAttributeName = ARC_TYPE(); + } + } + } + } + } + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED)); + } + return aFilledAttributeName; +} +// LCOV_EXCL_STOP + FeaturePtr SketchPlugin_MacroArc::createArcFeature() { FeaturePtr anArcFeature = sketch()->addFeature(SketchPlugin_Arc::ID()); @@ -310,10 +516,28 @@ void SketchPlugin_MacroArc::fillByCenterAndTwoPassed() return; GeomAPI_Circ2d aCircleForArc(myCenter, myStart); + // avoid degerated arc, when the center and the start points are equal + if (!aCircleForArc.implPtr()) + return; - // End point should be a projection on circle. bool aWasBlocked = data()->blockSendAttributeUpdated(true); - projectPointOnCircle(anEndPointAttr, aCircleForArc); + // 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(); @@ -357,17 +581,22 @@ void SketchPlugin_MacroArc::fillByThreePassedPoints() SketchPlugin_Tools::convertRefAttrToPointOrTangentCurve( refattr(PASSED_POINT_REF_ID()), aPassedPointAttr, aTangentCurve, aPassedPnt); - std::shared_ptr aPassed; - if (aTangentCurve) - aPassed = aTangentCurve; - else - aPassed = aPassedPnt; - - std::shared_ptr anAxis = SketchPlugin_Sketch::plane(sketch()); - GeomAPI_Circ2d aCircle(myStart, myEnd, aPassed, anAxis); - myCenter = aCircle.center(); + 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(); - recalculateReversedFlagByPassed(aCircle); + 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))); } @@ -391,36 +620,48 @@ void SketchPlugin_MacroArc::recalculateReversedFlagByPassed( myParamBefore = aEndParam; } -void SketchPlugin_MacroArc::fillByTangentEdge() +void SketchPlugin_MacroArc::fillByEdge(bool theTransversal) { - AttributeRefAttrPtr aTangentAttr = refattr(TANGENT_POINT_ID()); + const std::string& aStartPoint = theTransversal ? TRANSVERSAL_POINT_ID() : TANGENT_POINT_ID(); + const std::string& aEndPoint = theTransversal ? END_POINT_4_ID() : END_POINT_3_ID(); + + AttributeRefAttrPtr aTangentAttr = refattr(aStartPoint); if (!aTangentAttr->isInitialized()) return; - AttributePoint2DPtr aTangentPointAttr = + AttributePoint2DPtr aConnectionPointAttr = std::dynamic_pointer_cast(aTangentAttr->attr()); - if (!aTangentPointAttr->isInitialized()) + if (!aConnectionPointAttr->isInitialized()) return; AttributePoint2DPtr anEndPointAttr = - std::dynamic_pointer_cast(attribute(END_POINT_3_ID())); + std::dynamic_pointer_cast(attribute(aEndPoint)); if (!anEndPointAttr->isInitialized()) return; - myStart = aTangentPointAttr->pnt(); + myStart = aConnectionPointAttr->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(); + FeaturePtr aConnectedFeature = ModelAPI_Feature::feature(aConnectionPointAttr->owner()); + std::shared_ptr aTangentShape = aConnectedFeature->lastResult()->shape(); + + GeomAlgoAPI_Circ2dBuilder aCircBuilder(SketchPlugin_Sketch::plane(sketch())); + aCircBuilder.addPassingPoint(myStart); + aCircBuilder.addPassingPoint(myEnd); + if (theTransversal) + aCircBuilder.setTransversalLine(aTangentShape); + else + aCircBuilder.addTangentCurve(aTangentShape); - std::shared_ptr anAxis = SketchPlugin_Sketch::plane(sketch()); - GeomAPI_Circ2d aCircle(myStart, myEnd, aTangentShape, anAxis); - myCenter = aCircle.center(); + std::shared_ptr aCircle = aCircBuilder.circle(); + if (!aCircle) + return; + myCenter = aCircle->center(); // rebuild circle to set start point equal to zero parameter - aCircle = GeomAPI_Circ2d(myCenter, myStart); - recalculateReversedFlagByEnd(aCircle); + aCircle = std::shared_ptr(new GeomAPI_Circ2d(myCenter, myStart)); + recalculateReversedFlagByEnd(*aCircle); }