From 0dc7bdf00c26e021c4b5e7a4e96f80e902cff6af Mon Sep 17 00:00:00 2001 From: azv Date: Sat, 25 Mar 2017 17:20:16 +0300 Subject: [PATCH] Issue #2024: Redesign of circle and arc of circle * Prepare shape for MacroArc according to already selected points. --- src/GeomAPI/GeomAPI_Circ2d.cpp | 6 +- src/SketchAPI/SketchAPI_MacroArc.cpp | 88 ++--- src/SketchAPI/SketchAPI_MacroArc.h | 44 +-- src/SketchPlugin/SketchPlugin_MacroArc.cpp | 373 +++++++++--------- src/SketchPlugin/SketchPlugin_MacroArc.h | 43 +- src/SketchPlugin/SketchPlugin_MacroCircle.cpp | 30 +- src/SketchPlugin/SketchPlugin_Tools.cpp | 22 ++ src/SketchPlugin/SketchPlugin_Tools.h | 11 + src/SketchPlugin/SketchPlugin_Validators.cpp | 69 ++-- src/SketchPlugin/SketchPlugin_Validators.h | 7 +- src/SketchPlugin/plugin-Sketch.xml | 25 +- 11 files changed, 369 insertions(+), 349 deletions(-) diff --git a/src/GeomAPI/GeomAPI_Circ2d.cpp b/src/GeomAPI/GeomAPI_Circ2d.cpp index 743b44db2..a50e343ca 100644 --- a/src/GeomAPI/GeomAPI_Circ2d.cpp +++ b/src/GeomAPI/GeomAPI_Circ2d.cpp @@ -67,10 +67,10 @@ public: double aFirst, aLast; TopLoc_Location aLoc; - CurveAdaptorPtr aCurve(new Geom2dAdaptor_Curve( - BRep_Tool::CurveOnSurface(anEdge, myPlane, aLoc, aFirst, aLast))); + Handle(Geom2d_Curve) aCurve = BRep_Tool::CurveOnSurface(anEdge, myPlane, aLoc, aFirst, aLast); + CurveAdaptorPtr aCurveAdaptor(new Geom2dAdaptor_Curve(aCurve, aFirst, aLast)); - myTangentShapes.push_back(aCurve); + myTangentShapes.push_back(aCurveAdaptor); } void addPassingPoint(const std::shared_ptr& thePoint) diff --git a/src/SketchAPI/SketchAPI_MacroArc.cpp b/src/SketchAPI/SketchAPI_MacroArc.cpp index 2fa73d5a3..a82f44a70 100644 --- a/src/SketchAPI/SketchAPI_MacroArc.cpp +++ b/src/SketchAPI/SketchAPI_MacroArc.cpp @@ -28,10 +28,10 @@ SketchAPI_MacroArc::SketchAPI_MacroArc(const std::shared_ptr & //================================================================================================ SketchAPI_MacroArc::SketchAPI_MacroArc(const std::shared_ptr& theFeature, - double theCenterX, double theCenterY, - double theStartX, double theStartY, - double theEndX, double theEndY, - bool theInversed) + double theCenterX, double theCenterY, + double theStartX, double theStartY, + double theEndX, double theEndY, + bool theInversed) : SketchAPI_SketchEntity(theFeature) { if(initialize()) { @@ -42,10 +42,10 @@ SketchAPI_MacroArc::SketchAPI_MacroArc(const std::shared_ptr& //================================================================================================ SketchAPI_MacroArc::SketchAPI_MacroArc(const std::shared_ptr& theFeature, - const std::shared_ptr& theCenter, - const std::shared_ptr& theStart, - const std::shared_ptr& theEnd, - bool theInversed) + const std::shared_ptr& theCenter, + const std::shared_ptr& theStart, + const std::shared_ptr& theEnd, + bool theInversed) : SketchAPI_SketchEntity(theFeature) { if(initialize()) { @@ -55,9 +55,9 @@ SketchAPI_MacroArc::SketchAPI_MacroArc(const std::shared_ptr& //================================================================================================ SketchAPI_MacroArc::SketchAPI_MacroArc(const std::shared_ptr& theFeature, - double theStartX, double theStartY, - double theEndX, double theEndY, - double thePassedX, double thePassedY) + double theStartX, double theStartY, + double theEndX, double theEndY, + double thePassedX, double thePassedY) : SketchAPI_SketchEntity(theFeature) { if (initialize()) { @@ -67,9 +67,9 @@ SketchAPI_MacroArc::SketchAPI_MacroArc(const std::shared_ptr& //=============================================================================================== SketchAPI_MacroArc::SketchAPI_MacroArc(const std::shared_ptr& theFeature, - const std::shared_ptr& theStart, - const std::shared_ptr& theEnd, - const std::shared_ptr& thePassed) + const std::shared_ptr& theStart, + const std::shared_ptr& theEnd, + const std::shared_ptr& thePassed) : SketchAPI_SketchEntity(theFeature) { if (initialize()) { @@ -79,9 +79,9 @@ SketchAPI_MacroArc::SketchAPI_MacroArc(const std::shared_ptr& //================================================================================================ SketchAPI_MacroArc::SketchAPI_MacroArc(const std::shared_ptr& theFeature, - const ModelHighAPI_RefAttr& theTangentPoint, - double theEndX, double theEndY, - bool theInversed) + const ModelHighAPI_RefAttr& theTangentPoint, + double theEndX, double theEndY, + bool theInversed) : SketchAPI_SketchEntity(theFeature) { if (initialize()) { @@ -91,9 +91,9 @@ SketchAPI_MacroArc::SketchAPI_MacroArc(const std::shared_ptr& //================================================================================================ SketchAPI_MacroArc::SketchAPI_MacroArc(const std::shared_ptr& theFeature, - const ModelHighAPI_RefAttr& theTangentPoint, - const std::shared_ptr& theEnd, - bool theInversed) + const ModelHighAPI_RefAttr& theTangentPoint, + const std::shared_ptr& theEnd, + bool theInversed) : SketchAPI_SketchEntity(theFeature) { if (initialize()) { @@ -109,14 +109,14 @@ SketchAPI_MacroArc::~SketchAPI_MacroArc() //================================================================================================ void SketchAPI_MacroArc::setByCenterStartEnd(double theCenterX, double theCenterY, - double theStartX, double theStartY, - double theEndX, double theEndY, - bool theInversed) + double theStartX, double theStartY, + double theEndX, double theEndY, + bool theInversed) { fillAttribute(SketchPlugin_MacroArc::ARC_TYPE_BY_CENTER_AND_POINTS(), myarcType); fillAttribute(center(), theCenterX, theCenterY); - fillAttribute(startPoint1(), theStartX, theStartY); - fillAttribute(endPoint1(), theEndX, theEndY); + fillAttribute(startPoint(), theStartX, theStartY); + fillAttribute(endPoint(), theEndX, theEndY); fillAttribute(theInversed, myreversed); execute(); @@ -124,14 +124,14 @@ void SketchAPI_MacroArc::setByCenterStartEnd(double theCenterX, double theCenter //================================================================================================ void SketchAPI_MacroArc::setByCenterStartEnd(const std::shared_ptr& theCenter, - const std::shared_ptr& theStart, - const std::shared_ptr& theEnd, - bool theInversed) + const std::shared_ptr& theStart, + const std::shared_ptr& theEnd, + bool theInversed) { fillAttribute(SketchPlugin_MacroArc::ARC_TYPE_BY_CENTER_AND_POINTS(), myarcType); fillAttribute(theCenter, mycenter); - fillAttribute(theStart, mystartPoint1); - fillAttribute(theEnd, myendPoint1); + fillAttribute(theStart, mystartPoint); + fillAttribute(theEnd, myendPoint); fillAttribute(theInversed, myreversed); execute(); @@ -139,12 +139,12 @@ void SketchAPI_MacroArc::setByCenterStartEnd(const std::shared_ptr& theStart, - const std::shared_ptr& theEnd, - const std::shared_ptr& thePassed) + const std::shared_ptr& theEnd, + const std::shared_ptr& thePassed) { fillAttribute(SketchPlugin_MacroArc::ARC_TYPE_BY_THREE_POINTS(), myarcType); - fillAttribute(theStart, mystartPoint2); - fillAttribute(theEnd, myendPoint2); + fillAttribute(theStart, mystartPoint); + fillAttribute(theEnd, myendPoint); fillAttribute(thePassed, mypassedPoint); execute(); @@ -165,12 +165,12 @@ void SketchAPI_MacroArc::setByStartEndPassed(const std::shared_ptr& theEnd, - bool theInversed) + const std::shared_ptr& theEnd, + bool theInversed) { fillAttribute(SketchPlugin_MacroArc::ARC_TYPE_BY_TANGENT_EDGE(), myarcType); fillAttribute(theTangentPoint, mytangentPoint); - fillAttribute(theEnd, myendPoint3); + fillAttribute(theEnd, myendPoint); fillAttribute(theInversed, myreversed); execute(); diff --git a/src/SketchAPI/SketchAPI_MacroArc.h b/src/SketchAPI/SketchAPI_MacroArc.h index c24e24750..9350e5427 100644 --- a/src/SketchAPI/SketchAPI_MacroArc.h +++ b/src/SketchAPI/SketchAPI_MacroArc.h @@ -79,31 +79,25 @@ public: SketchPlugin_MacroArc::ID(); } - INTERFACE_12(SketchPlugin_MacroArc::ID(), - arcType, SketchPlugin_MacroArc::ARC_TYPE(), - ModelAPI_AttributeString, /** Arc type */, - center, SketchPlugin_MacroArc::CENTER_POINT_ID(), - GeomDataAPI_Point2D, /** Center point */, - startPoint1, SketchPlugin_MacroArc::START_POINT_1_ID(), - GeomDataAPI_Point2D, /** Start point */, - endPoint1, SketchPlugin_MacroArc::END_POINT_1_ID(), - GeomDataAPI_Point2D, /** End point */, - startPoint2, SketchPlugin_MacroArc::START_POINT_2_ID(), - GeomDataAPI_Point2D, /** Start point */, - endPoint2, SketchPlugin_MacroArc::END_POINT_2_ID(), - GeomDataAPI_Point2D, /** End point */, - passedPoint, SketchPlugin_MacroArc::PASSED_POINT_ID(), - GeomDataAPI_Point2D, /** Passed point */, - tangentPoint, SketchPlugin_MacroArc::TANGENT_POINT_ID(), - ModelAPI_AttributeRefAttr, /** Tangent point */, - endPoint3, SketchPlugin_MacroArc::END_POINT_3_ID(), - GeomDataAPI_Point2D, /** End point */, - reversed, SketchPlugin_MacroArc::REVERSED_ID(), - ModelAPI_AttributeBoolean, /** Reversed flag */, - radius, SketchPlugin_MacroArc::RADIUS_ID(), - ModelAPI_AttributeDouble, /** Radius */, - angle, SketchPlugin_MacroArc::ANGLE_ID(), - ModelAPI_AttributeDouble, /** Angle */) + INTERFACE_9(SketchPlugin_MacroArc::ID(), + arcType, SketchPlugin_MacroArc::ARC_TYPE(), + ModelAPI_AttributeString, /** Arc type */, + center, SketchPlugin_MacroArc::CENTER_POINT_ID(), + GeomDataAPI_Point2D, /** Center point */, + startPoint, SketchPlugin_MacroArc::START_POINT_ID(), + GeomDataAPI_Point2D, /** Start point */, + endPoint, SketchPlugin_MacroArc::END_POINT_ID(), + GeomDataAPI_Point2D, /** End point */, + passedPoint, SketchPlugin_MacroArc::PASSED_POINT_ID(), + GeomDataAPI_Point2D, /** Passed point */, + tangentPoint, SketchPlugin_MacroArc::TANGENT_POINT_ID(), + ModelAPI_AttributeRefAttr, /** Tangent point */, + reversed, SketchPlugin_MacroArc::REVERSED_ID(), + ModelAPI_AttributeBoolean, /** Reversed flag */, + radius, SketchPlugin_MacroArc::RADIUS_ID(), + ModelAPI_AttributeDouble, /** Radius */, + angle, SketchPlugin_MacroArc::ANGLE_ID(), + ModelAPI_AttributeDouble, /** Angle */) private: diff --git a/src/SketchPlugin/SketchPlugin_MacroArc.cpp b/src/SketchPlugin/SketchPlugin_MacroArc.cpp index 6528ca247..c1affb736 100644 --- a/src/SketchPlugin/SketchPlugin_MacroArc.cpp +++ b/src/SketchPlugin/SketchPlugin_MacroArc.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -39,6 +40,13 @@ 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); +} + SketchPlugin_MacroArc::SketchPlugin_MacroArc() : SketchPlugin_SketchEntity(), @@ -51,15 +59,12 @@ void SketchPlugin_MacroArc::initAttributes() data()->addAttribute(ARC_TYPE(), ModelAPI_AttributeString::typeId()); data()->addAttribute(CENTER_POINT_ID(), GeomDataAPI_Point2D::typeId()); - data()->addAttribute(START_POINT_1_ID(), GeomDataAPI_Point2D::typeId()); - data()->addAttribute(END_POINT_1_ID(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(START_POINT_ID(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(END_POINT_ID(), GeomDataAPI_Point2D::typeId()); - data()->addAttribute(START_POINT_2_ID(), GeomDataAPI_Point2D::typeId()); - data()->addAttribute(END_POINT_2_ID(), GeomDataAPI_Point2D::typeId()); data()->addAttribute(PASSED_POINT_ID(), GeomDataAPI_Point2D::typeId()); data()->addAttribute(TANGENT_POINT_ID(), ModelAPI_AttributeRefAttr::typeId()); - data()->addAttribute(END_POINT_3_ID(), GeomDataAPI_Point2D::typeId()); data()->addAttribute(REVERSED_ID(), ModelAPI_AttributeBoolean::typeId()); @@ -87,185 +92,30 @@ 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_ID()); + SketchPlugin_Tools::resetAttribute(this, START_POINT_REF_ID()); + SketchPlugin_Tools::resetAttribute(this, END_POINT_ID()); + SketchPlugin_Tools::resetAttribute(this, END_POINT_REF_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, REVERSED_ID()); + SketchPlugin_Tools::resetAttribute(this, RADIUS_ID()); + SketchPlugin_Tools::resetAttribute(this, ANGLE_ID()); myCenter.reset(); myStart.reset(); myEnd.reset(); 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) { - boolean(REVERSED_ID())->setValue(true); - } else if(myParamBefore >= PI * 1.5 && aParameterNew <= PI / 2.0) { - boolean(REVERSED_ID())->setValue(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) { - boolean(REVERSED_ID())->setValue(true); - } else { - boolean(REVERSED_ID())->setValue(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(!boolean(REVERSED_ID())->value()) { - boolean(REVERSED_ID())->setValue(true); - } - } else if(myParamBefore >= PI * 1.5 && aParameterNew <= PI / 2.0) { - if(boolean(REVERSED_ID())->value()) { - boolean(REVERSED_ID())->setValue(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; @@ -334,17 +184,7 @@ AISObjectPtr SketchPlugin_MacroArc::getAISObject(AISObjectPtr thePrevious) void SketchPlugin_MacroArc::execute() { - // Create arc feature. - 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->execute(); + FeaturePtr anArcFeature = createArcFeature(); myCenter.reset(); myStart.reset(); @@ -392,3 +232,158 @@ void SketchPlugin_MacroArc::execute() false); } } + +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_ID())); + if (!aStartPointAttr->isInitialized()) + return; + + myCenter = aCenterPointAttr->pnt(); + myStart = aStartPointAttr->pnt(); + myEnd = myStart; + + AttributePoint2DPtr anEndPointAttr = + std::dynamic_pointer_cast(attribute(END_POINT_ID())); + if (!anEndPointAttr->isInitialized()) + return; + + GeomAPI_Circ2d aCircleForArc(myCenter, myStart); + + // End point should be a projection on circle. + bool aWasBlocked = data()->blockSendAttributeUpdated(true); + 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_ID())); + if (!aStartPointAttr->isInitialized()) + return; + + AttributePoint2DPtr anEndPointAttr = + std::dynamic_pointer_cast(attribute(END_POINT_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); + + 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(); + + 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_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(); + + std::shared_ptr anAxis = SketchPlugin_Sketch::plane(sketch()); + GeomAPI_Circ2d aCircle(myStart, myEnd, aTangentShape, anAxis); + myCenter = aCircle.center(); + + // rebuild circle to set start point equal to zero parameter + aCircle = GeomAPI_Circ2d(myCenter, myStart); + recalculateReversedFlagByEnd(aCircle); +} diff --git a/src/SketchPlugin/SketchPlugin_MacroArc.h b/src/SketchPlugin/SketchPlugin_MacroArc.h index aec30931c..0a191342c 100644 --- a/src/SketchPlugin/SketchPlugin_MacroArc.h +++ b/src/SketchPlugin/SketchPlugin_MacroArc.h @@ -13,6 +13,7 @@ #include +class GeomAPI_Circ2d; class GeomAPI_Pnt2d; /**\class SketchPlugin_MacroArc @@ -70,16 +71,9 @@ class SketchPlugin_MacroArc: public SketchPlugin_SketchEntity, } /// Start 2D point of the arc - inline static const std::string& START_POINT_1_ID() + inline static const std::string& START_POINT_ID() { - static const std::string ID = "start_point_1"; - return ID; - } - - /// Start 2D point of the arc - inline static const std::string& START_POINT_2_ID() - { - static const std::string ID = "start_point_2"; + static const std::string ID = "start_point"; return ID; } @@ -90,23 +84,9 @@ class SketchPlugin_MacroArc: public SketchPlugin_SketchEntity, } /// End 2D point of the arc - inline static const std::string& END_POINT_1_ID() - { - static const std::string ID = "end_point_1"; - return ID; - } - - /// End 2D point of the arc - inline static const std::string& END_POINT_2_ID() + inline static const std::string& END_POINT_ID() { - static const std::string ID = "end_point_2"; - return ID; - } - - /// End 2D point of the arc - inline static const std::string& END_POINT_3_ID() - { - static const std::string ID = "end_point_3"; + static const std::string ID = "end_point"; return ID; } @@ -191,6 +171,19 @@ class SketchPlugin_MacroArc: public SketchPlugin_SketchEntity, /// Use plugin manager for features creation. SketchPlugin_MacroArc(); +private: + /// Set fields for center, start and end points + void fillByCenterAndTwoPassed(); + /// Set fields for center, start and end points by selected passed points + void fillByThreePassedPoints(); + /// Set fields for center, start and end points by selected tangent edge + void fillByTangentEdge(); + + FeaturePtr createArcFeature(); + + void recalculateReversedFlagByEnd(const GeomAPI_Circ2d& theCurrentCircular); + void recalculateReversedFlagByPassed(const GeomAPI_Circ2d& theCurrentCircular); + private: std::shared_ptr myCenter; std::shared_ptr myStart; diff --git a/src/SketchPlugin/SketchPlugin_MacroCircle.cpp b/src/SketchPlugin/SketchPlugin_MacroCircle.cpp index d1bbbd65a..7232a6c37 100644 --- a/src/SketchPlugin/SketchPlugin_MacroCircle.cpp +++ b/src/SketchPlugin/SketchPlugin_MacroCircle.cpp @@ -85,27 +85,6 @@ void SketchPlugin_MacroCircle::execute() createCircleByThreePoints(); } -static void convertToPointOrTangent(const AttributeRefAttrPtr& theRefAttr, - const AttributePtr& theBaseAttr, - std::shared_ptr& thePassingPoint, - std::shared_ptr& theTangentCurve) -{ - AttributePtr anAttr = theBaseAttr; - if (theRefAttr->isObject()) { - FeaturePtr aTgFeature = ModelAPI_Feature::feature(theRefAttr->object()); - if (aTgFeature) { - if (aTgFeature->getKind() != SketchPlugin_Point::ID()) { - theTangentCurve = aTgFeature->lastResult()->shape(); - return; - } - anAttr = aTgFeature->attribute(SketchPlugin_Point::COORD_ID()); - } - } else - anAttr = theRefAttr->attr(); - - thePassingPoint = std::dynamic_pointer_cast(anAttr)->pnt(); -} - void SketchPlugin_MacroCircle::createCircleByCenterAndPassed() { // Create circle feature. @@ -169,7 +148,8 @@ std::shared_ptr SketchPlugin_MacroCircle::shapeByCenterAndPassed std::dynamic_pointer_cast(aCenterAttr)->pnt(); std::shared_ptr aPassedPoint; std::shared_ptr aTangentCurve; - convertToPointOrTangent(aPassedRef, aPassedAttr, aPassedPoint, aTangentCurve); + SketchPlugin_Tools::convertRefAttrToPointOrTangentCurve( + aPassedRef, aPassedAttr, aTangentCurve, aPassedPoint); // Build a circle std::shared_ptr aCircle; @@ -199,7 +179,8 @@ std::shared_ptr SketchPlugin_MacroCircle::shapeByThreePoints() // calculate circle parameters std::shared_ptr aPassedPoint; std::shared_ptr aTangentCurve; - convertToPointOrTangent(aPassedRef, aPassedAttr, aPassedPoint, aTangentCurve); + SketchPlugin_Tools::convertRefAttrToPointOrTangentCurve( + aPassedRef, aPassedAttr, aTangentCurve, aPassedPoint); if (aPassedPoint) aPassedEntities[aPntIndex] = aPassedPoint; @@ -233,7 +214,8 @@ std::shared_ptr SketchPlugin_MacroCircle::shapeByTwoPassedPoints // calculate circle parameters std::shared_ptr aPassedPoint; std::shared_ptr aTangentCurve; - convertToPointOrTangent(aPassedRef, aPassedAttr, aPassedPoint, aTangentCurve); + SketchPlugin_Tools::convertRefAttrToPointOrTangentCurve( + aPassedRef, aPassedAttr, aTangentCurve, aPassedPoint); if (aPassedPoint) { aPassedEntities[aPntIndex] = aPassedPoint; diff --git a/src/SketchPlugin/SketchPlugin_Tools.cpp b/src/SketchPlugin/SketchPlugin_Tools.cpp index 5758a6b7d..8e3dfabb4 100644 --- a/src/SketchPlugin/SketchPlugin_Tools.cpp +++ b/src/SketchPlugin/SketchPlugin_Tools.cpp @@ -199,4 +199,26 @@ void createConstraint(SketchPlugin_Feature* theFeature, } } } + +void convertRefAttrToPointOrTangentCurve(const AttributeRefAttrPtr& theRefAttr, + const AttributePtr& theDefaultAttr, + std::shared_ptr& theTangentCurve, + std::shared_ptr& thePassingPoint) +{ + AttributePtr anAttr = theDefaultAttr; + if (theRefAttr->isObject()) { + FeaturePtr aTgFeature = ModelAPI_Feature::feature(theRefAttr->object()); + if (aTgFeature) { + if (aTgFeature->getKind() != SketchPlugin_Point::ID()) { + theTangentCurve = aTgFeature->lastResult()->shape(); + return; + } + anAttr = aTgFeature->attribute(SketchPlugin_Point::COORD_ID()); + } + } else + anAttr = theRefAttr->attr(); + + thePassingPoint = std::dynamic_pointer_cast(anAttr)->pnt(); +} + } // namespace SketchPlugin_Tools diff --git a/src/SketchPlugin/SketchPlugin_Tools.h b/src/SketchPlugin/SketchPlugin_Tools.h index 622b63d68..cecc946fc 100644 --- a/src/SketchPlugin/SketchPlugin_Tools.h +++ b/src/SketchPlugin/SketchPlugin_Tools.h @@ -11,6 +11,7 @@ #include #include +#include #include class SketchPlugin_Feature; @@ -51,6 +52,16 @@ void createConstraint(SketchPlugin_Feature* theFeature, const AttributePtr theAttr, const ObjectPtr theObject, const bool theIsCanBeTangent); + +/// Creates passing point or tangent curve basing on the given attributes are initialized. +/// \param[in] theRefAttr prefered attribute to be converted +/// \param[in] theDefaultAttr default attribute if theRefAttr is not initialized +/// \param[out] theTangentCurve tangent curve if theRefAttr refers to an edge +/// \param[out] thePassingPoint passing point if theRefAttr does not refer to an edge +void convertRefAttrToPointOrTangentCurve(const AttributeRefAttrPtr& theRefAttr, + const AttributePtr& theDefaultAttr, + std::shared_ptr& theTangentCurve, + std::shared_ptr& thePassingPoint); }; // namespace SketchPlugin_Tools #endif // SKETCHPLUGIN_TOOLS_H_ \ No newline at end of file diff --git a/src/SketchPlugin/SketchPlugin_Validators.cpp b/src/SketchPlugin/SketchPlugin_Validators.cpp index 7b929019c..bffe18309 100755 --- a/src/SketchPlugin/SketchPlugin_Validators.cpp +++ b/src/SketchPlugin/SketchPlugin_Validators.cpp @@ -14,6 +14,7 @@ #include "SketchPlugin_ConstraintTangent.h" #include "SketchPlugin_Fillet.h" #include "SketchPlugin_Line.h" +#include "SketchPlugin_MacroArc.h" #include "SketchPlugin_MacroCircle.h" #include "SketchPlugin_Point.h" #include "SketchPlugin_Sketch.h" @@ -1110,11 +1111,12 @@ bool SketchPlugin_CirclePassedPointValidator::isValid( bool SketchPlugin_ThirdPointValidator::isValid( const AttributePtr& theAttribute, - const std::list&, + const std::list& theArguments, Events_InfoMessage& theError) const { FeaturePtr anOwner = ModelAPI_Feature::feature(theAttribute->owner()); - return arePointsNotOnLine(anOwner, theError) && arePointsNotSeparated(anOwner, theError); + return arePointsNotOnLine(anOwner, theError) && + arePointsNotSeparated(anOwner, theArguments, theError); } static std::shared_ptr toPoint(const FeaturePtr& theMacroCircle, @@ -1156,6 +1158,32 @@ static std::shared_ptr toPoint(const FeaturePtr& theMacroCircle, return aPoint; } +static void threePointsOfFeature(const FeaturePtr& theMacroFeature, + std::shared_ptr thePoints[3]) +{ + if (theMacroFeature->getKind() == SketchPlugin_MacroCircle::ID()) { + thePoints[0] = toPoint(theMacroFeature, + SketchPlugin_MacroCircle::FIRST_POINT_ID(), + SketchPlugin_MacroCircle::FIRST_POINT_REF_ID()); + thePoints[1] = toPoint(theMacroFeature, + SketchPlugin_MacroCircle::SECOND_POINT_ID(), + SketchPlugin_MacroCircle::SECOND_POINT_REF_ID()); + thePoints[2] = toPoint(theMacroFeature, + SketchPlugin_MacroCircle::THIRD_POINT_ID(), + SketchPlugin_MacroCircle::THIRD_POINT_REF_ID()); + } else if (theMacroFeature->getKind() == SketchPlugin_MacroArc::ID()) { + thePoints[0] = toPoint(theMacroFeature, + SketchPlugin_MacroArc::START_POINT_ID(), + SketchPlugin_MacroArc::START_POINT_REF_ID()); + thePoints[1] = toPoint(theMacroFeature, + SketchPlugin_MacroArc::END_POINT_ID(), + SketchPlugin_MacroArc::END_POINT_REF_ID()); + thePoints[2] = toPoint(theMacroFeature, + SketchPlugin_MacroArc::PASSED_POINT_ID(), + SketchPlugin_MacroArc::PASSED_POINT_REF_ID()); + } +} + static bool isPointsOnLine(const std::shared_ptr& thePoint1, const std::shared_ptr& thePoint2, const std::shared_ptr& thePoint3) @@ -1196,23 +1224,16 @@ static bool isOnSameSide(const std::shared_ptr& theCircle, } bool SketchPlugin_ThirdPointValidator::arePointsNotOnLine( - const FeaturePtr& theMacroCircle, + const FeaturePtr& theMacroFeature, Events_InfoMessage& theError) const { static const std::string aErrorPointsOnLine( "Selected points are on the same line"); - std::shared_ptr aFirstPoint = toPoint(theMacroCircle, - SketchPlugin_MacroCircle::FIRST_POINT_ID(), - SketchPlugin_MacroCircle::FIRST_POINT_REF_ID()); - std::shared_ptr aSecondPoint = toPoint(theMacroCircle, - SketchPlugin_MacroCircle::SECOND_POINT_ID(), - SketchPlugin_MacroCircle::SECOND_POINT_REF_ID()); - std::shared_ptr aThirdPoint = toPoint(theMacroCircle, - SketchPlugin_MacroCircle::THIRD_POINT_ID(), - SketchPlugin_MacroCircle::THIRD_POINT_REF_ID()); - - if (isPointsOnLine(aFirstPoint, aSecondPoint, aThirdPoint)) { + std::shared_ptr aPoints[3]; + threePointsOfFeature(theMacroFeature, aPoints); + + if (isPointsOnLine(aPoints[0], aPoints[1], aPoints[2])) { theError = aErrorPointsOnLine; return false; } @@ -1220,26 +1241,22 @@ bool SketchPlugin_ThirdPointValidator::arePointsNotOnLine( } bool SketchPlugin_ThirdPointValidator::arePointsNotSeparated( - const FeaturePtr& theMacroCircle, + const FeaturePtr& theMacroFeature, + const std::list& theArguments, Events_InfoMessage& theError) const { static const std::string aErrorPointsApart( "Selected entity is lying between first two points"); - AttributeRefAttrPtr aThirdPointRef = - theMacroCircle->refattr(SketchPlugin_MacroCircle::THIRD_POINT_REF_ID()); + AttributeRefAttrPtr aThirdPointRef = theMacroFeature->refattr(theArguments.front()); FeaturePtr aRefByThird; if (aThirdPointRef->isObject()) aRefByThird = ModelAPI_Feature::feature(aThirdPointRef->object()); if (!aRefByThird) return true; - std::shared_ptr aFirstPoint = toPoint(theMacroCircle, - SketchPlugin_MacroCircle::FIRST_POINT_ID(), - SketchPlugin_MacroCircle::FIRST_POINT_REF_ID()); - std::shared_ptr aSecondPoint = toPoint(theMacroCircle, - SketchPlugin_MacroCircle::SECOND_POINT_ID(), - SketchPlugin_MacroCircle::SECOND_POINT_REF_ID()); + std::shared_ptr aPoints[3]; + threePointsOfFeature(theMacroFeature, aPoints); std::shared_ptr aThirdShape = std::dynamic_pointer_cast(aRefByThird->lastResult()->shape()); @@ -1247,9 +1264,9 @@ bool SketchPlugin_ThirdPointValidator::arePointsNotSeparated( return true; SketchPlugin_Sketch* aSketch = - std::dynamic_pointer_cast(theMacroCircle)->sketch(); - std::shared_ptr aFirstPnt3D = aSketch->to3D(aFirstPoint->x(), aFirstPoint->y()); - std::shared_ptr aSecondPnt3D = aSketch->to3D(aSecondPoint->x(), aSecondPoint->y()); + std::dynamic_pointer_cast(theMacroFeature)->sketch(); + std::shared_ptr aFirstPnt3D = aSketch->to3D(aPoints[0]->x(), aPoints[0]->y()); + std::shared_ptr aSecondPnt3D = aSketch->to3D(aPoints[1]->x(), aPoints[1]->y()); bool isOk = true; if (aThirdShape->isLine()) diff --git a/src/SketchPlugin/SketchPlugin_Validators.h b/src/SketchPlugin/SketchPlugin_Validators.h index 3dfd9398d..441bd1793 100644 --- a/src/SketchPlugin/SketchPlugin_Validators.h +++ b/src/SketchPlugin/SketchPlugin_Validators.h @@ -344,17 +344,18 @@ class SketchPlugin_ThirdPointValidator : public ModelAPI_AttributeValidator //! \param theArguments arguments of the attribute //! \param theError error message virtual bool isValid(const AttributePtr& theAttribute, - const std::list&, + const std::list& theArguments, Events_InfoMessage& theError) const; private: //! returns true if three points have not been placed on the same line - bool arePointsNotOnLine(const FeaturePtr& theMacroCircle, + bool arePointsNotOnLine(const FeaturePtr& theMacroFeature, Events_InfoMessage& theError) const; //! returns true if the first two points have not been separated //! by a feature referred by thrid point - bool arePointsNotSeparated(const FeaturePtr& theMacroCircle, + bool arePointsNotSeparated(const FeaturePtr& theMacroFeature, + const std::list& theArguments, Events_InfoMessage& theError) const; }; diff --git a/src/SketchPlugin/plugin-Sketch.xml b/src/SketchPlugin/plugin-Sketch.xml index 646060b45..416f478d3 100644 --- a/src/SketchPlugin/plugin-Sketch.xml +++ b/src/SketchPlugin/plugin-Sketch.xml @@ -120,7 +120,7 @@ accept_expressions="0" enable_value="enable_by_preferences"> - + @@ -205,42 +205,47 @@ tooltip="Center of a circle" accept_expressions="0" enable_value="enable_by_preferences" /> - - - + - - + enable_value="enable_by_preferences"> + + - + enable_value="enable_by_preferences"> + + + + -