From: asozinov Date: Fri, 23 Jun 2023 01:06:02 +0000 (+0100) Subject: bos#35152 [EDF] (2023-T1) Sketch Circle should allow user to position construction... X-Git-Tag: V9_12_0b1~9 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;ds=sidebyside;h=f64e1300ed35bb1e9a2486cdb5713355e832dd39;hp=a75b67fb7c1a4d8bf4acec94ecd441a48415634d;p=modules%2Fshaper.git bos#35152 [EDF] (2023-T1) Sketch Circle should allow user to position construction point WIll be modified Sketch Circle feature: Current implementation provide possibility change sewing point and rotate this point Sketch.addCircleWithPoint(CenterPoint, Radius, Angle) Sketch.addCircleWithPoint(CenterPoint, PassedPoint, Angle) Sketch.addCircleWithPoint(PassPoint1, PassPoint2, PassPoint3, Angle) Get new point: SketchCircle.createdPoint() //Last modification (06/07/23): change comment --- diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_EdgeBuilder.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_EdgeBuilder.cpp index f19425a48..86fe03d7b 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_EdgeBuilder.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_EdgeBuilder.cpp @@ -162,12 +162,16 @@ std::shared_ptr GeomAlgoAPI_EdgeBuilder::cylinderAxis( std::shared_ptr GeomAlgoAPI_EdgeBuilder::lineCircle( std::shared_ptr theCenter, std::shared_ptr theNormal, - double theRadius) + double theRadius, double theRotationAngle) { const gp_Pnt& aCenter = theCenter->impl(); const gp_Dir& aDir = theNormal->impl(); + gp_Ax1 anAx(aCenter, aDir); + gp_Circ aCircle(gp_Ax2(aCenter, aDir), theRadius); + if (Abs(theRotationAngle) > 1.e-7) // Tolerance + aCircle.Rotate(anAx, theRotationAngle); BRepBuilderAPI_MakeEdge anEdgeBuilder(aCircle); std::shared_ptr aRes(new GeomAPI_Edge); diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_EdgeBuilder.h b/src/GeomAlgoAPI/GeomAlgoAPI_EdgeBuilder.h index 465074028..fabae078a 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_EdgeBuilder.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_EdgeBuilder.h @@ -65,7 +65,8 @@ class GEOMALGOAPI_EXPORT GeomAlgoAPI_EdgeBuilder /// Creates linear edge in a form of a circle by a point and a circle radius static std::shared_ptr lineCircle(std::shared_ptr theCenter, std::shared_ptr theNormal, - double theRadius); + double theRadius, + double theRotationAngle = 0.); /// Creates linear edge in a form of a circle by GeomAPI_Circle static std::shared_ptr lineCircle(std::shared_ptr theCircle); diff --git a/src/SketchAPI/SketchAPI_Circle.cpp b/src/SketchAPI/SketchAPI_Circle.cpp index 41853fe1d..95d48f397 100644 --- a/src/SketchAPI/SketchAPI_Circle.cpp +++ b/src/SketchAPI/SketchAPI_Circle.cpp @@ -26,6 +26,9 @@ #include #include +#include +#include + //================================================================================================== SketchAPI_Circle::SketchAPI_Circle(const std::shared_ptr & theFeature) : SketchAPI_SketchEntity(theFeature) @@ -37,22 +40,22 @@ SketchAPI_Circle::SketchAPI_Circle(const std::shared_ptr & the SketchAPI_Circle::SketchAPI_Circle(const std::shared_ptr& theFeature, double theCenterX, double theCenterY, - double theRadius) + double theRadius, double theAngle) : SketchAPI_SketchEntity(theFeature) { if(initialize()) { - setByCenterAndRadius(theCenterX, theCenterY, theRadius); + setByCenterAndRadius(theCenterX, theCenterY, theRadius, theAngle); } } //================================================================================================== SketchAPI_Circle::SketchAPI_Circle(const std::shared_ptr& theFeature, const std::shared_ptr& theCenter, - double theRadius) + double theRadius, double theAngle) : SketchAPI_SketchEntity(theFeature) { if(initialize()) { - setByCenterAndRadius(theCenter, theRadius); + setByCenterAndRadius(theCenter, theRadius, theAngle); } } @@ -82,23 +85,90 @@ SketchAPI_Circle::~SketchAPI_Circle() } +// Create point on circle line +void SketchAPI_Circle::createPoint() +{ + // Find sketch + CompositeFeaturePtr aSketch; + const std::set& aRefs = feature()->data()->refsToMe(); + for (std::set::const_iterator anIt = aRefs.begin(); anIt != aRefs.end(); ++anIt) + if ((*anIt)->id() == SketchPlugin_Sketch::FEATURES_ID()) + { + aSketch = std::dynamic_pointer_cast((*anIt)->owner()); + break; + } + if (!aSketch) + return; + + // create point on line + FeaturePtr aPointFeature = aSketch->addFeature(SketchPlugin_Point::ID()); + aPointFeature->reference(SketchPlugin_Point::PARENT_ID())->setValue(feature()); + + AttributePoint2DPtr aCoord = std::dynamic_pointer_cast( + aPointFeature->attribute(SketchPlugin_Point::COORD_ID())); + + GeomPnt2dPtr aPnt = std::dynamic_pointer_cast( + feature()->attribute(SketchPlugin_Circle::ROTATE_ID()))->pnt(); + + aCoord->setValue(aPnt); + aPointFeature->execute(); + + FeaturePtr aConstraint = aSketch->addFeature(SketchPlugin_ConstraintCoincidenceInternal::ID()); + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast( + aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A())); + aRefAttr->setAttr(feature()->attribute(SketchPlugin_Circle::ROTATE_ID())); + + aRefAttr = std::dynamic_pointer_cast( + aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B())); + aRefAttr->setAttr(aCoord); + + feature()->reference(SketchPlugin_Circle::ROTATE_REF_ID())->setValue(aPointFeature); +} + //================================================================================================== -void SketchAPI_Circle::setByCenterAndRadius(double theCenterX, double theCenterY, double theRadius) +void SketchAPI_Circle::setByCenterAndRadius(double theCenterX, double theCenterY, + double theRadius, double theAngle) { fillAttribute(center(), theCenterX, theCenterY); fillAttribute(theRadius, myradius); + fillAttribute(theAngle, myangle); - execute(); + bool isNeedPoint = + feature()->integer(SketchPlugin_Circle::VERSION_ID())->value() > SketchPlugin_Circle::THE_VERSION_0; + if (isNeedPoint) + { + fillAttribute(theAngle, angle()); + + execute(); + createPoint(); + } + else + { + execute(); + } } //================================================================================================== void SketchAPI_Circle::setByCenterAndRadius(const std::shared_ptr& theCenter, - double theRadius) + double theRadius, double theAngle) { fillAttribute(theCenter, mycenter); fillAttribute(theRadius, myradius); - execute(); + bool isNeedPoint = + feature()->integer(SketchPlugin_Circle::VERSION_ID())->value() > SketchPlugin_Circle::THE_VERSION_0; + + if (isNeedPoint) + { + fillAttribute(theAngle, angle()); + + execute(); + createPoint(); + } + else + { + execute(); + } } //================================================================================================== @@ -141,6 +211,32 @@ void SketchAPI_Circle::setRadius(double theRadius) execute(); } +//================================================================================================== +void SketchAPI_Circle::setAngle(double theAngle) +{ + fillAttribute(ModelHighAPI_Double(theAngle), myangle); + + execute(); +} + +//================================================================================================== +// Return created point +std::shared_ptr SketchAPI_Circle::createdPoint() const +{ + std::shared_ptr anEnt; + + AttributeReferencePtr anRef = feature()->reference(SketchPlugin_Circle::ROTATE_REF_ID()); + if (!anRef->isInitialized()) + return anEnt; + + FeaturePtr aFeature = ModelAPI_Feature::feature(anRef->value()); + if (aFeature && aFeature->getKind() == SketchPlugin_Point::ID()) + { + anEnt = std::shared_ptr < SketchAPI_SketchEntity>(new SketchAPI_Point(aFeature)); + } + return anEnt; +} + //================================================================================================== void SketchAPI_Circle::dump(ModelHighAPI_Dumper& theDumper) const { @@ -151,13 +247,26 @@ void SketchAPI_Circle::dump(ModelHighAPI_Dumper& theDumper) const const std::string& aSketchName = theDumper.parentName(aBase); AttributeSelectionPtr anExternal = aBase->selection(SketchPlugin_SketchEntity::EXTERNAL_ID()); + std::string aComName = aBase->integer(SketchPlugin_Circle::VERSION_ID())->value() > SketchPlugin_Circle::THE_VERSION_0 ? + "addCircleWithPoint" : "addCircle"; + if (anExternal->context()) { // circle is external - theDumper << aBase << " = " << aSketchName << ".addCircle(" << anExternal << ")" << std::endl; - } else { - // circle given by center and radius - theDumper << aBase << " = " << aSketchName << ".addCircle(" - << center() << ", " << radius() << ")" << std::endl; + theDumper << aBase << " = " << aSketchName << "." << aComName << "(" << anExternal << ")" << std::endl; + } + else {// circle given by center and radius + theDumper << aBase << " = " << aSketchName << "." << aComName << "(" << center() << ", " << radius(); + if (aBase->integer(SketchPlugin_Circle::VERSION_ID())->value() > SketchPlugin_Circle::THE_VERSION_0) + { + theDumper << ", " << angle() << ")" << std::endl; + std::shared_ptr aPoint = createdPoint(); + if (aPoint) + theDumper << aPoint->feature() << " = " << theDumper.name(aBase) << ".createdPoint()" << std::endl; + } + else + { + theDumper << ")" << std::endl; + } } // dump "auxiliary" flag if necessary SketchAPI_SketchEntity::dump(theDumper); diff --git a/src/SketchAPI/SketchAPI_Circle.h b/src/SketchAPI/SketchAPI_Circle.h index dcc58c715..96744ebf5 100644 --- a/src/SketchAPI/SketchAPI_Circle.h +++ b/src/SketchAPI/SketchAPI_Circle.h @@ -42,13 +42,15 @@ public: SketchAPI_Circle(const std::shared_ptr& theFeature, double theCenterX, double theCenterY, - double theRadius); + double theRadius, + double theAngle); /// Constructor with values. SKETCHAPI_EXPORT SketchAPI_Circle(const std::shared_ptr& theFeature, const std::shared_ptr& theCenter, - double theRadius); + double theRadius, + double theAngle); /// Constructor with values. SKETCHAPI_EXPORT @@ -64,21 +66,25 @@ public: SKETCHAPI_EXPORT virtual ~SketchAPI_Circle(); - INTERFACE_3(SketchPlugin_Circle::ID(), + INTERFACE_4(SketchPlugin_Circle::ID(), center, SketchPlugin_Circle::CENTER_ID(), GeomDataAPI_Point2D, /** Center point */, radius, SketchPlugin_Circle::RADIUS_ID(), ModelAPI_AttributeDouble, /** Radius */, external, SketchPlugin_Circle::EXTERNAL_ID(), - ModelAPI_AttributeSelection, /** External */) + ModelAPI_AttributeSelection, /** External */, + angle, SketchPlugin_Circle::ANGLE_ID(), + ModelAPI_AttributeDouble, /** Angle */) /// Set by center and radius. SKETCHAPI_EXPORT - void setByCenterAndRadius(double theCenterX, double theCenterY, double theRadius); + void setByCenterAndRadius(double theCenterX, double theCenterY, + double theRadius, double theAngle); /// Set by center and radius. SKETCHAPI_EXPORT - void setByCenterAndRadius(const std::shared_ptr& theCenter, double theRadius); + void setByCenterAndRadius(const std::shared_ptr& theCenter, + double theRadius, double theAngle); /// Set by external. SKETCHAPI_EXPORT @@ -100,9 +106,20 @@ public: SKETCHAPI_EXPORT void setRadius(double theRadius); + /// Set angle. + SKETCHAPI_EXPORT + void setAngle(double theAngle); + + /// Returns created points on circle + SKETCHAPI_EXPORT + std::shared_ptr createdPoint() const; + /// Dump wrapped feature SKETCHAPI_EXPORT virtual void dump(ModelHighAPI_Dumper& theDumper) const; + +private: + void createPoint(); }; /// Pointer on Circle object. diff --git a/src/SketchAPI/SketchAPI_MacroCircle.cpp b/src/SketchAPI/SketchAPI_MacroCircle.cpp index f5e459a40..640893214 100644 --- a/src/SketchAPI/SketchAPI_MacroCircle.cpp +++ b/src/SketchAPI/SketchAPI_MacroCircle.cpp @@ -26,6 +26,9 @@ #include #include +#include +#include + //================================================================================================== SketchAPI_MacroCircle::SketchAPI_MacroCircle(const std::shared_ptr& theFeature) : SketchAPI_SketchEntity(theFeature) @@ -38,22 +41,24 @@ SketchAPI_MacroCircle::SketchAPI_MacroCircle(const std::shared_ptr& theFeature, const std::shared_ptr& theCenterPoint, - const std::shared_ptr& thePassedPoint) + const std::shared_ptr& thePassedPoint, + double theAngle) : SketchAPI_SketchEntity(theFeature) { if(initialize()) { - setByCenterAndPassedPoints(theCenterPoint, thePassedPoint); + setByCenterAndPassedPoints(theCenterPoint, thePassedPoint, theAngle); } } @@ -61,11 +66,12 @@ SketchAPI_MacroCircle::SketchAPI_MacroCircle(const std::shared_ptr& theFeature, double theX1, double theY1, double theX2, double theY2, - double theX3, double theY3) + double theX3, double theY3, + double theAngle) : SketchAPI_SketchEntity(theFeature) { if(initialize()) { - setByThreePoints(theX1, theY1, theX2, theY2, theX3, theY3); + setByThreePoints(theX1, theY1, theX2, theY2, theX3, theY3, theAngle); } } @@ -73,11 +79,12 @@ SketchAPI_MacroCircle::SketchAPI_MacroCircle(const std::shared_ptr& theFeature, const std::shared_ptr& thePoint1, const std::shared_ptr& thePoint2, - const std::shared_ptr& thePoint3) + const std::shared_ptr& thePoint3, + double theAngle) : SketchAPI_SketchEntity(theFeature) { if(initialize()) { - setByThreePoints(thePoint1, thePoint2, thePoint3); + setByThreePoints(thePoint1, thePoint2, thePoint3, theAngle); } } @@ -90,49 +97,95 @@ SketchAPI_MacroCircle::~SketchAPI_MacroCircle() void SketchAPI_MacroCircle::setByCenterAndPassedPoints(double theCenterX, double theCenterY, double thePassedX, - double thePassedY) + double thePassedY, + double theAngle) { fillAttribute(SketchPlugin_MacroCircle::CIRCLE_TYPE_BY_CENTER_AND_PASSED_POINTS(), mycircleType); fillAttribute(centerPoint(), theCenterX, theCenterY); fillAttribute(passedPoint(), thePassedX, thePassedY); + bool isNeedPoint = + feature()->integer(SketchPlugin_MacroCircle::VERSION_ID())->value() > 0; + + if (isNeedPoint) + fillAttribute(theAngle, angle()); + execute(); } //================================================================================================== void SketchAPI_MacroCircle::setByCenterAndPassedPoints( const std::shared_ptr& theCenterPoint, - const std::shared_ptr& thePassedPoint) + const std::shared_ptr& thePassedPoint, + double theAngle) { fillAttribute(SketchPlugin_MacroCircle::CIRCLE_TYPE_BY_CENTER_AND_PASSED_POINTS(), mycircleType); fillAttribute(theCenterPoint, mycenterPoint); fillAttribute(thePassedPoint, mypassedPoint); + bool isNeedPoint = + feature()->integer(SketchPlugin_MacroCircle::VERSION_ID())->value() > 0; + + if (isNeedPoint) + fillAttribute(theAngle, angle()); + execute(); } //================================================================================================== void SketchAPI_MacroCircle::setByThreePoints(double theX1, double theY1, double theX2, double theY2, - double theX3, double theY3) + double theX3, double theY3, + double theAngle) { fillAttribute(SketchPlugin_MacroCircle::CIRCLE_TYPE_BY_THREE_POINTS(), mycircleType); fillAttribute(firstPoint(), theX1, theY1); fillAttribute(secondPoint(), theX2, theY2); fillAttribute(thirdPoint(), theX3, theY3); + bool isNeedPoint = + feature()->integer(SketchPlugin_MacroCircle::VERSION_ID())->value() > 0; + + if (isNeedPoint) + fillAttribute(theAngle, angle()); + execute(); } //================================================================================================== void SketchAPI_MacroCircle::setByThreePoints(const std::shared_ptr& thePoint1, const std::shared_ptr& thePoint2, - const std::shared_ptr& thePoint3) + const std::shared_ptr& thePoint3, + double theAngle) { fillAttribute(SketchPlugin_MacroCircle::CIRCLE_TYPE_BY_THREE_POINTS(), mycircleType); fillAttribute(thePoint1, myfirstPoint); fillAttribute(thePoint2, mysecondPoint); fillAttribute(thePoint3, mythirdPoint); + bool isNeedPoint = + feature()->integer(SketchPlugin_MacroCircle::VERSION_ID())->value() > 0; + + if (isNeedPoint) + fillAttribute(theAngle, angle()); + execute(); } + +// return created point +std::shared_ptr SketchAPI_MacroCircle::createdPoint() const +{ + std::shared_ptr anEnt; + + AttributeRefAttrPtr anRef = feature()->refattr(SketchPlugin_MacroCircle::ROTATE_POINT_REF_ID()); + if (!anRef->isInitialized()) + return anEnt; + + ObjectPtr aPointObj = anRef->object(); + FeaturePtr aFeature = ModelAPI_Feature::feature(aPointObj); + if (aFeature && aFeature->getKind() == SketchPlugin_Point::ID()) + { + anEnt = std::shared_ptr < SketchAPI_SketchEntity>(new SketchAPI_Point(aFeature)); + } + return anEnt; +} diff --git a/src/SketchAPI/SketchAPI_MacroCircle.h b/src/SketchAPI/SketchAPI_MacroCircle.h index 725edeacb..ee278b9f9 100644 --- a/src/SketchAPI/SketchAPI_MacroCircle.h +++ b/src/SketchAPI/SketchAPI_MacroCircle.h @@ -43,33 +43,37 @@ public: double theCenterX, double theCenterY, double thePassedX, - double thePassedY); + double thePassedY, + double theAngle); /// Constructor with values. SKETCHAPI_EXPORT SketchAPI_MacroCircle(const std::shared_ptr& theFeature, const std::shared_ptr& theCenterPoint, - const std::shared_ptr& thePassedPoint); + const std::shared_ptr& thePassedPoint, + double theAngle); /// Constructor with values. SKETCHAPI_EXPORT SketchAPI_MacroCircle(const std::shared_ptr& theFeature, double theX1, double theY1, double theX2, double theY2, - double theX3, double theY3); + double theX3, double theY3, + double theAngle); /// Constructor with values. SKETCHAPI_EXPORT SketchAPI_MacroCircle(const std::shared_ptr& theFeature, const std::shared_ptr& thePoint1, const std::shared_ptr& thePoint2, - const std::shared_ptr& thePoint3); + const std::shared_ptr& thePoint3, + double theAngle); /// Destructor. SKETCHAPI_EXPORT virtual ~SketchAPI_MacroCircle(); - INTERFACE_6(SketchPlugin_MacroCircle::ID(), + INTERFACE_7(SketchPlugin_MacroCircle::ID(), circleType, SketchPlugin_MacroCircle::CIRCLE_TYPE(), ModelAPI_AttributeString, /** Circle type */, centerPoint, SketchPlugin_MacroCircle::CENTER_POINT_ID(), @@ -81,26 +85,35 @@ public: secondPoint, SketchPlugin_MacroCircle::SECOND_POINT_ID(), GeomDataAPI_Point2D, /** Second point */, thirdPoint, SketchPlugin_MacroCircle::THIRD_POINT_ID(), - GeomDataAPI_Point2D, /** Third point */) + GeomDataAPI_Point2D, /** Third point */, + angle, SketchPlugin_MacroCircle::CIRCLE_ROTATE_ANGLE_ID(), + ModelAPI_AttributeDouble, /** Angle */) + /// Returns created points on circle + SKETCHAPI_EXPORT + std::shared_ptr createdPoint() const; private: /// Set by center and passed points. void setByCenterAndPassedPoints(double theCenterX, double theCenterY, - double thePassedX, double thePassedY); + double thePassedX, double thePassedY, + double theAngle); /// Set by center and passed points. void setByCenterAndPassedPoints(const std::shared_ptr& theCenterPoint, - const std::shared_ptr& thePassedPoint); + const std::shared_ptr& thePassedPoint, + double theAngle); /// Set by three points. void setByThreePoints(double theX1, double theY1, double theX2, double theY2, - double theX3, double theY3); + double theX3, double theY3, + double theAngle); /// Set by three points. void setByThreePoints(const std::shared_ptr& thePoint1, const std::shared_ptr& thePoint2, - const std::shared_ptr& thePoint3); + const std::shared_ptr& thePoint3, + double theAngle); }; /// Pointer on Circle object. diff --git a/src/SketchAPI/SketchAPI_Sketch.cpp b/src/SketchAPI/SketchAPI_Sketch.cpp index b0836ae12..3c30c146a 100644 --- a/src/SketchAPI/SketchAPI_Sketch.cpp +++ b/src/SketchAPI/SketchAPI_Sketch.cpp @@ -589,25 +589,31 @@ std::shared_ptr SketchAPI_Sketch::addRectangleCentered( return aRect; } +// Old way for create circle //-------------------------------------------------------------------------------------- +[[deprecated("Use addCircleWithPoint method instead.")]] std::shared_ptr SketchAPI_Sketch::addCircle(double theCenterX, double theCenterY, double theRadius) { std::shared_ptr aFeature = compositeFeature()->addFeature(SketchPlugin_Circle::ID()); - return CirclePtr(new SketchAPI_Circle(aFeature, theCenterX, theCenterY, theRadius)); + fillAttribute(SketchPlugin_Circle::THE_VERSION_0, aFeature->integer(SketchPlugin_Circle::VERSION_ID())); + return CirclePtr(new SketchAPI_Circle(aFeature, theCenterX, theCenterY, theRadius, 0)); } +[[deprecated("Use addCircleWithPoint method instead.")]] std::shared_ptr SketchAPI_Sketch::addCircle( const std::shared_ptr& theCenter, double theRadius) { std::shared_ptr aFeature = compositeFeature()->addFeature(SketchPlugin_Circle::ID()); - return CirclePtr(new SketchAPI_Circle(aFeature, theCenter, theRadius)); + fillAttribute(SketchPlugin_Circle::THE_VERSION_0, aFeature->integer(SketchPlugin_Circle::VERSION_ID())); + return CirclePtr(new SketchAPI_Circle(aFeature, theCenter, theRadius, 0)); } +[[deprecated("Use addCircleWithPoint method instead.")]] std::shared_ptr SketchAPI_Sketch::addCircle(double theCenterX, double theCenterY, double thePassedX, @@ -615,30 +621,37 @@ std::shared_ptr SketchAPI_Sketch::addCircle(double theCen { std::shared_ptr aFeature = compositeFeature()->addFeature(SketchPlugin_MacroCircle::ID()); + fillAttribute(SketchPlugin_Circle::THE_VERSION_0, aFeature->integer(SketchPlugin_MacroCircle::VERSION_ID())); return MacroCirclePtr(new SketchAPI_MacroCircle(aFeature, theCenterX, theCenterY, - thePassedX, thePassedY)); + thePassedX, thePassedY, 0)); } +[[deprecated("Use addCircleWithPoint method instead.")]] std::shared_ptr SketchAPI_Sketch::addCircle( const std::shared_ptr& theCenterPoint, const std::shared_ptr& thePassedPoint) { std::shared_ptr aFeature = compositeFeature()->addFeature(SketchPlugin_MacroCircle::ID()); - return MacroCirclePtr(new SketchAPI_MacroCircle(aFeature, theCenterPoint, thePassedPoint)); + fillAttribute(SketchPlugin_Circle::THE_VERSION_0, aFeature->integer(SketchPlugin_MacroCircle::VERSION_ID())); + return MacroCirclePtr(new SketchAPI_MacroCircle(aFeature, theCenterPoint, thePassedPoint, 0)); } +[[deprecated("Use addCircleWithPoint method instead.")]] std::shared_ptr SketchAPI_Sketch::addCircle(double theX1, double theY1, double theX2, double theY2, double theX3, double theY3) { std::shared_ptr aFeature = compositeFeature()->addFeature(SketchPlugin_MacroCircle::ID()); + fillAttribute(SketchPlugin_Circle::THE_VERSION_0, aFeature->integer(SketchPlugin_MacroCircle::VERSION_ID())); + return MacroCirclePtr(new SketchAPI_MacroCircle(aFeature, theX1, theY1, theX2, theY2, - theX3, theY3)); + theX3, theY3, 0)); } +[[deprecated("Use addCircleWithPoint method instead.")]] std::shared_ptr SketchAPI_Sketch::addCircle( const std::shared_ptr& thePoint1, const std::shared_ptr& thePoint2, @@ -646,9 +659,11 @@ std::shared_ptr SketchAPI_Sketch::addCircle( { std::shared_ptr aFeature = compositeFeature()->addFeature(SketchPlugin_MacroCircle::ID()); - return MacroCirclePtr(new SketchAPI_MacroCircle(aFeature, thePoint1, thePoint2, thePoint3)); + fillAttribute(SketchPlugin_Circle::THE_VERSION_0, aFeature->integer(SketchPlugin_Circle::VERSION_ID())); + return MacroCirclePtr(new SketchAPI_MacroCircle(aFeature, thePoint1, thePoint2, thePoint3, 0)); } +[[deprecated("Use addCircleWithPoint method instead.")]] std::shared_ptr SketchAPI_Sketch::addCircle(const ModelHighAPI_Selection & theExternal) { @@ -657,6 +672,7 @@ std::shared_ptr return CirclePtr(new SketchAPI_Circle(aFeature, theExternal)); } +[[deprecated("Use addCircleWithPoint method instead.")]] std::shared_ptr SketchAPI_Sketch::addCircle(const std::wstring & theExternalName) { std::shared_ptr aFeature = @@ -664,6 +680,88 @@ std::shared_ptr SketchAPI_Sketch::addCircle(const std::wstring return CirclePtr(new SketchAPI_Circle(aFeature, theExternalName)); } +// New way for create Circle +//-------------------------------------------------------------------------------------- +std::shared_ptr SketchAPI_Sketch::addCircleWithPoint(double theCenterX, + double theCenterY, + double theRadius, + double theAngle) +{ + std::shared_ptr aFeature = + compositeFeature()->addFeature(SketchPlugin_Circle::ID()); + return CirclePtr(new SketchAPI_Circle(aFeature, theCenterX, theCenterY, theRadius, theAngle)); +} + +std::shared_ptr SketchAPI_Sketch::addCircleWithPoint( + const std::shared_ptr& theCenter, + double theRadius, + double theAngle) +{ + std::shared_ptr aFeature = + compositeFeature()->addFeature(SketchPlugin_Circle::ID()); + return CirclePtr(new SketchAPI_Circle(aFeature, theCenter, theRadius, theAngle)); +} + +std::shared_ptr SketchAPI_Sketch::addCircleWithPoint(double theCenterX, + double theCenterY, + double thePassedX, + double thePassedY, + double theAngle) +{ + std::shared_ptr aFeature = + compositeFeature()->addFeature(SketchPlugin_MacroCircle::ID()); + return MacroCirclePtr(new SketchAPI_MacroCircle(aFeature, theCenterX, theCenterY, + thePassedX, thePassedY, theAngle)); +} + +std::shared_ptr SketchAPI_Sketch::addCircleWithPoint( + const std::shared_ptr& theCenterPoint, + const std::shared_ptr& thePassedPoint, + double theAngle) +{ + std::shared_ptr aFeature = + compositeFeature()->addFeature(SketchPlugin_MacroCircle::ID()); + return MacroCirclePtr(new SketchAPI_MacroCircle(aFeature, theCenterPoint, thePassedPoint, theAngle)); +} + +std::shared_ptr SketchAPI_Sketch::addCircleWithPoint(double theX1, double theY1, + double theX2, double theY2, + double theX3, double theY3, + double theAngle) +{ + std::shared_ptr aFeature = + compositeFeature()->addFeature(SketchPlugin_MacroCircle::ID()); + return MacroCirclePtr(new SketchAPI_MacroCircle(aFeature, theX1, theY1, + theX2, theY2, + theX3, theY3, theAngle)); +} + +std::shared_ptr SketchAPI_Sketch::addCircleWithPoint( + const std::shared_ptr& thePoint1, + const std::shared_ptr& thePoint2, + const std::shared_ptr& thePoint3, + double theAngle) +{ + std::shared_ptr aFeature = + compositeFeature()->addFeature(SketchPlugin_MacroCircle::ID()); + return MacroCirclePtr(new SketchAPI_MacroCircle(aFeature, thePoint1, thePoint2, thePoint3, theAngle)); +} + +std::shared_ptr +SketchAPI_Sketch::addCircleWithPoint(const ModelHighAPI_Selection& theExternal) +{ + std::shared_ptr aFeature = + compositeFeature()->addFeature(SketchPlugin_Circle::ID()); + return CirclePtr(new SketchAPI_Circle(aFeature, theExternal)); +} + +std::shared_ptr SketchAPI_Sketch::addCircleWithPoint(const std::wstring& theExternalName) +{ + std::shared_ptr aFeature = + compositeFeature()->addFeature(SketchPlugin_Circle::ID()); + return CirclePtr(new SketchAPI_Circle(aFeature, theExternalName)); +} + //-------------------------------------------------------------------------------------- std::shared_ptr SketchAPI_Sketch::addArc(double theCenterX, double theCenterY, double theStartX, double theStartY, diff --git a/src/SketchAPI/SketchAPI_Sketch.h b/src/SketchAPI/SketchAPI_Sketch.h index 993e6ef90..7f2fa98ea 100644 --- a/src/SketchAPI/SketchAPI_Sketch.h +++ b/src/SketchAPI/SketchAPI_Sketch.h @@ -187,45 +187,96 @@ public: const std::pair, ModelHighAPI_RefAttr> & theCenter, const std::pair, ModelHighAPI_RefAttr> & theCorner); - /// Add circle + /// Add circle. + /// [DEPRECATED]: use addCircleWithPoint() instead. SKETCHAPI_EXPORT std::shared_ptr addCircle( double theCenterX, double theCenterY, double theRadius); - /// Add circle + /// Add circle. + /// [DEPRECATED]: use addCircleWithPoint() instead. SKETCHAPI_EXPORT std::shared_ptr addCircle( const std::shared_ptr& theCenter, double theRadius); - /// Add circle + /// Add circle. + /// [DEPRECATED]: use addCircleWithPoint() instead. SKETCHAPI_EXPORT std::shared_ptr addCircle( double theCenterX, double theCenterY, double thePassedX, double thePassedY); - /// Add circle + /// Add circle. + /// [DEPRECATED]: use addCircleWithPoint() instead. SKETCHAPI_EXPORT std::shared_ptr addCircle( const std::shared_ptr& theCenterPoint, const std::shared_ptr& thePassedPoint); - /// Add circle + /// Add circle. + /// [DEPRECATED]: use addCircleWithPoint() instead. SKETCHAPI_EXPORT std::shared_ptr addCircle( double theX1, double theY1, double theX2, double theY2, double theX3, double theY3); - /// Add circle + /// Add circle. + /// [DEPRECATED]: use addCircleWithPoint() instead. SKETCHAPI_EXPORT std::shared_ptr addCircle( const std::shared_ptr& thePoint1, const std::shared_ptr& thePoint2, const std::shared_ptr& thePoint3); - /// Add circle + /// Add circle. + /// [DEPRECATED]: use addCircleWithPoint() instead. SKETCHAPI_EXPORT std::shared_ptr addCircle(const ModelHighAPI_Selection & theExternal); - /// Add circle + /// Add circle. + /// [DEPRECATED]: use addCircleWithPoint() instead. SKETCHAPI_EXPORT std::shared_ptr addCircle(const std::wstring & theExternalName); + /// Add circle with point + SKETCHAPI_EXPORT + std::shared_ptr addCircleWithPoint( + double theCenterX, double theCenterY, + double theRadius, double theAngle); + /// Add circle with point + SKETCHAPI_EXPORT + std::shared_ptr addCircleWithPoint( + const std::shared_ptr& theCenter, + double theRadius, double theAngle); + /// Add circle with point + SKETCHAPI_EXPORT + std::shared_ptr addCircleWithPoint( + double theCenterX, double theCenterY, + double thePassedX, double thePassedY, + double theAngle); + /// Add circle with point + SKETCHAPI_EXPORT + std::shared_ptr addCircleWithPoint( + const std::shared_ptr& theCenterPoint, + const std::shared_ptr& thePassedPoint, + double theAngle); + /// Add circle with point + SKETCHAPI_EXPORT + std::shared_ptr addCircleWithPoint( + double theX1, double theY1, + double theX2, double theY2, + double theX3, double theY3, + double theAngle); + /// Add circle with point + SKETCHAPI_EXPORT + std::shared_ptr addCircleWithPoint( + const std::shared_ptr& thePoint1, + const std::shared_ptr& thePoint2, + const std::shared_ptr& thePoint3, + double theAngle); + /// Add circle with point + SKETCHAPI_EXPORT + std::shared_ptr addCircleWithPoint(const ModelHighAPI_Selection& theExternal); + /// Add circle with point + SKETCHAPI_EXPORT + std::shared_ptr addCircleWithPoint(const std::wstring& theExternalName); + /// Add arc SKETCHAPI_EXPORT std::shared_ptr addArc( diff --git a/src/SketchPlugin/SketchPlugin_Circle.cpp b/src/SketchPlugin/SketchPlugin_Circle.cpp index c0eecf508..86d5721e8 100644 --- a/src/SketchPlugin/SketchPlugin_Circle.cpp +++ b/src/SketchPlugin/SketchPlugin_Circle.cpp @@ -19,16 +19,22 @@ #include "SketchPlugin_Circle.h" #include "SketchPlugin_Sketch.h" +#include "SketchPlugin_Tools.h" #include #include #include +#include +#include #include #include #include #include +#include +#include #include #include +#include #include #include #include @@ -41,6 +47,7 @@ #include const double tolerance = 1e-7; +const double PI = 3.141592653589793238463; SketchPlugin_Circle::SketchPlugin_Circle() @@ -51,10 +58,27 @@ SketchPlugin_Circle::SketchPlugin_Circle() void SketchPlugin_Circle::initDerivedClassAttributes() { data()->addAttribute(CENTER_ID(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(ROTATE_ID(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(ROTATE_REF_ID(), ModelAPI_AttributeReference::typeId()); data()->addAttribute(RADIUS_ID(), ModelAPI_AttributeDouble::typeId()); + data()->addAttribute(ANGLE_ID(), ModelAPI_AttributeDouble::typeId()); + + // While exist addCircle without creating point. + AttributeIntegerPtr aVerAttr = std::dynamic_pointer_cast( + data()->addAttribute(VERSION_ID(), ModelAPI_AttributeInteger::typeId())); + aVerAttr->setIsArgument(false); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), VERSION_ID()); + if (!aVerAttr->isInitialized()) { + // this is a newly created feature (not read from file), + // so, initialize the latest version + aVerAttr->setValue(SketchPlugin_Circle::THE_VERSION_1); + } data()->addAttribute(EXTERNAL_ID(), ModelAPI_AttributeSelection::typeId()); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EXTERNAL_ID()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), ROTATE_ID()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), ROTATE_REF_ID()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), ANGLE_ID()); } void SketchPlugin_Circle::execute() @@ -68,6 +92,7 @@ void SketchPlugin_Circle::execute() std::shared_ptr aCenterAttr = std::dynamic_pointer_cast(data()->attribute(CENTER_ID())); AttributeDoublePtr aRadiusAttr = real(RADIUS_ID()); + AttributeDoublePtr anAngleAttr = real(ANGLE_ID()); if(!aCenterAttr->isInitialized() || !aRadiusAttr->isInitialized()) { return; } @@ -77,7 +102,10 @@ void SketchPlugin_Circle::execute() return; } - // Make a visible point. + if (!anAngleAttr->isInitialized()) + anAngleAttr->setValue(0); + + // Make a visible center point. SketchPlugin_Sketch::createPoint2DResult(this, sketch(), CENTER_ID(), 0); // Make a visible circle. @@ -86,8 +114,21 @@ void SketchPlugin_Circle::execute() aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID())); std::shared_ptr aNormal(new GeomAPI_Dir(aNDir->x(), aNDir->y(), aNDir->z())); - std::shared_ptr aCircleShape = - GeomAlgoAPI_EdgeBuilder::lineCircle(aCenter, aNormal, aRadius); + std::shared_ptr aCircleShape; + if (integer(VERSION_ID())->value() > SketchPlugin_Circle::THE_VERSION_0) + { + double aValAn = anAngleAttr->value(); + aCircleShape = GeomAlgoAPI_EdgeBuilder::lineCircle(aCenter, aNormal, aRadius, aValAn / 180 * PI); + + // Update corrdinates for point on circle + bool aWasBlocked = data()->blockSendAttributeUpdated(true); + GeomPnt2dPtr aCircleSewPoint = aSketch->to2D(aCircleShape->firstPoint()); + std::dynamic_pointer_cast(data()->attribute(ROTATE_ID())) + ->setValue(aCircleSewPoint->x(), aCircleSewPoint->y()); + data()->blockSendAttributeUpdated(aWasBlocked, false); + } + else + aCircleShape = GeomAlgoAPI_EdgeBuilder::lineCircle(aCenter, aNormal, aRadius); std::shared_ptr aResult = document()->createConstruction(data(), 1); aResult->setShape(aCircleShape); @@ -116,7 +157,37 @@ void SketchPlugin_Circle::attributeChanged(const std::string& theID) { std::shared_ptr aCenterAttr = std::dynamic_pointer_cast(attribute(CENTER_ID())); aCenterAttr->setValue(sketch()->to2D(aCirc->center())); + real(RADIUS_ID())->setValue(aCirc->radius()); + real(ANGLE_ID())->setValue(0); + } + } + else if (integer(VERSION_ID())->value() > SketchPlugin_Circle::THE_VERSION_0 && + theID == ROTATE_ID()) + { + // get cricle from results + std::shared_ptr aSelection; + ResultPtr aCircleRes = lastResult(); + if (aCircleRes) + aSelection = aCircleRes->shape(); + if (aSelection && !aSelection->isNull() && aSelection->isEdge()) { + std::shared_ptr anEdge(new GeomAPI_Edge(aSelection)); + std::shared_ptr aCirc = anEdge->circle(); + + // Get point and project it on line + std::shared_ptr aNewPntRot = + std::dynamic_pointer_cast(attribute(ROTATE_ID())); + GeomPointPtr aPntRot3D = aCirc->project( sketch()->to3D(aNewPntRot->x(), aNewPntRot->y())); + + // Compute new angle + GeomPointPtr aNorm = sketch()->to3D(real(RADIUS_ID())->value(), 0); + double aStartParam, anEndParam; + aCirc->parameter(aPntRot3D, 1.e-4, anEndParam); + aCirc->parameter(aNorm, 1.e-4, aStartParam); + + bool aWasBlocked = data()->blockSendAttributeUpdated(true); + real(ANGLE_ID())->setValue((anEndParam - aStartParam) / PI * 180.0); + data()->blockSendAttributeUpdated(aWasBlocked, false); } } } diff --git a/src/SketchPlugin/SketchPlugin_Circle.h b/src/SketchPlugin/SketchPlugin_Circle.h index c5035fba2..0f620d7a7 100644 --- a/src/SketchPlugin/SketchPlugin_Circle.h +++ b/src/SketchPlugin/SketchPlugin_Circle.h @@ -45,6 +45,20 @@ class SketchPlugin_Circle: public SketchPlugin_SketchEntity return ID; } + /// 2D point - rotate of the circle + inline static const std::string& ROTATE_ID() + { + static const std::string ID("circle_rotate"); + return ID; + } + + /// Contain created point as feature + inline static const std::string& ROTATE_REF_ID() + { + static const std::string ID("circle_rotate_point"); + return ID; + } + /// Radius of the circle inline static const std::string& RADIUS_ID() { @@ -52,6 +66,13 @@ class SketchPlugin_Circle: public SketchPlugin_SketchEntity return ID; } + /// Angle of rotation sewing point of the circle + inline static const std::string& ANGLE_ID() + { + static const std::string ID("circle_angle"); + return ID; + } + /// Returns the kind of a feature SKETCHPLUGIN_EXPORT virtual const std::string& getKind() { @@ -59,6 +80,16 @@ class SketchPlugin_Circle: public SketchPlugin_SketchEntity return MY_KIND; } + static const int THE_VERSION_0 = 0; + static const int THE_VERSION_1 = 20232206; + + /// Attribute name of the version of Circle feature + inline static const std::string& VERSION_ID() + { + static const std::string MY_VERSION_ID("version"); + return MY_VERSION_ID; + } + /// Returns true is sketch element is under the rigid constraint SKETCHPLUGIN_EXPORT virtual bool isFixed(); diff --git a/src/SketchPlugin/SketchPlugin_MacroCircle.cpp b/src/SketchPlugin/SketchPlugin_MacroCircle.cpp index 2725d0be9..4f107ebe5 100644 --- a/src/SketchPlugin/SketchPlugin_MacroCircle.cpp +++ b/src/SketchPlugin/SketchPlugin_MacroCircle.cpp @@ -23,10 +23,14 @@ #include "SketchPlugin_Point.h" #include "SketchPlugin_Tools.h" #include "SketchPlugin_MacroArcReentrantMessage.h" +#include +#include #include #include #include +#include +#include #include #include #include @@ -35,8 +39,10 @@ #include #include +#include #include #include +#include #include #include @@ -63,7 +69,8 @@ namespace { SketchPlugin_MacroCircle::SketchPlugin_MacroCircle() : SketchPlugin_SketchEntity(), - myRadius(0.0) + myRadius(0.0), + myAngle(0.0) { } @@ -84,17 +91,39 @@ void SketchPlugin_MacroCircle::initAttributes() data()->addAttribute(SECOND_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId()); data()->addAttribute(THIRD_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId()); + // Attrs for rotation point + data()->addAttribute(ROTATE_POINT_ID(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(ROTATE_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId()); + data()->addAttribute(CIRCLE_RADIUS_ID(), ModelAPI_AttributeDouble::typeId()); + data()->addAttribute(CIRCLE_ROTATE_ANGLE_ID(), ModelAPI_AttributeDouble::typeId()); data()->addAttribute(AUXILIARY_ID(), ModelAPI_AttributeBoolean::typeId()); - string(EDIT_CIRCLE_TYPE())->setValue(""); + // When circle create using addCircle command, angle is not define and new point nor create + // This lines must be removed when command for create circle without additional point will be removed from SHAPER + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CIRCLE_ROTATE_ANGLE_ID()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), ROTATE_POINT_ID()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), ROTATE_POINT_REF_ID()); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CENTER_POINT_REF_ID()); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PASSED_POINT_REF_ID()); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), FIRST_POINT_REF_ID()); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SECOND_POINT_REF_ID()); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), THIRD_POINT_REF_ID()); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EDIT_CIRCLE_TYPE()); + + // While exist addCircle without creating point. + AttributeIntegerPtr aVerAttr = std::dynamic_pointer_cast( + data()->addAttribute(VERSION_ID(), ModelAPI_AttributeInteger::typeId())); + aVerAttr->setIsArgument(false); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), VERSION_ID()); + if (!aVerAttr->isInitialized()) { + // this is a newly created feature (not read from file), + // so, initialize the latest version + aVerAttr->setValue(SketchPlugin_Circle::THE_VERSION_1); + } + + string(EDIT_CIRCLE_TYPE())->setValue(""); } void SketchPlugin_MacroCircle::execute() @@ -191,6 +220,12 @@ void SketchPlugin_MacroCircle::constraintsForCircleByCenterAndPassed(FeaturePtr SketchPlugin_Tools::createCoincidenceOrTangency( this, PASSED_POINT_REF_ID(), AttributePtr(), theCircleFeature->lastResult(), true); + + if (integer(VERSION_ID())->value() > SketchPlugin_Circle::THE_VERSION_0) + SketchPlugin_Tools::createCoincidenceOrTangency( + this, ROTATE_POINT_REF_ID(), + AttributePtr(), + theCircleFeature->lastResult(), false); } void SketchPlugin_MacroCircle::constraintsForCircleByThreePoints(FeaturePtr theCircleFeature) @@ -205,6 +240,66 @@ void SketchPlugin_MacroCircle::constraintsForCircleByThreePoints(FeaturePtr theC SketchPlugin_Tools::createCoincidenceOrTangency( this, aPointRef[i], AttributePtr(), aCircleResult, true); } + + if (integer(VERSION_ID())->value() > SketchPlugin_Circle::THE_VERSION_0) + SketchPlugin_Tools::createCoincidenceOrTangency( + this, ROTATE_POINT_REF_ID(), + AttributePtr(), + aCircleResult, false); +} + +void SketchPlugin_MacroCircle::computeNewAngle(std::shared_ptr& theCircle) +{ + if (integer(VERSION_ID())->value() < SketchPlugin_Circle::THE_VERSION_1) + return; + + AttributePtr aRotateAtr = attribute(ROTATE_POINT_ID()); + if (aRotateAtr->isInitialized()) + { + AttributeRefAttrPtr aRotRef = refattr(ROTATE_POINT_REF_ID()); + std::shared_ptr aRotPoit; + std::shared_ptr aTangentCurve; + SketchPlugin_Tools::convertRefAttrToPointOrTangentCurve( + aRotRef, aRotateAtr, aTangentCurve, aRotPoit); + + myRotPoint = theCircle->project(aRotPoit); + + std::shared_ptr aNorm(new GeomAPI_Pnt2d(myRadius, 0)); + double anEndParam, aStartParam; + theCircle->parameter(myRotPoint, 1.e-4, anEndParam); + theCircle->parameter(aNorm, 1.e-4, aStartParam); + myAngle = (anEndParam - aStartParam) / 3.14 * 180.0; + } + else + { + std::shared_ptr aRotPoit = + std::shared_ptr(new GeomAPI_Pnt2d(myCenter->x() + myRadius, myCenter->y())); + myRotPoint = theCircle->project(aRotPoit); + std::dynamic_pointer_cast(attribute(ROTATE_POINT_ID()))->setValue(myRotPoint); + myAngle = 0; + } +} + +static FeaturePtr CreatePoint(FeaturePtr theCircleFeature, + GeomPnt2dPtr thePoint) +{ + SketchPlugin_Sketch* aSketch = + std::dynamic_pointer_cast(theCircleFeature)->sketch(); + + // create point at sewing point of circle + FeaturePtr aPointFeature = aSketch->addFeature(SketchPlugin_Point::ID()); + aPointFeature->reference(SketchPlugin_Point::PARENT_ID())->setValue(theCircleFeature); + + AttributePoint2DPtr aCoord = std::dynamic_pointer_cast( + aPointFeature->attribute(SketchPlugin_Point::COORD_ID())); + aCoord->setValue(thePoint); + aPointFeature->execute(); + + SketchPlugin_Tools::createConstraintAttrAttr(aSketch, SketchPlugin_ConstraintCoincidenceInternal::ID(), + theCircleFeature->attribute(SketchPlugin_Circle::ROTATE_ID()), aCoord); + + theCircleFeature->reference(SketchPlugin_Circle::ROTATE_REF_ID())->setValue(aPointFeature); + return aPointFeature; } FeaturePtr SketchPlugin_MacroCircle::createCircleFeature() @@ -213,10 +308,23 @@ FeaturePtr SketchPlugin_MacroCircle::createCircleFeature() std::dynamic_pointer_cast( aCircleFeature->attribute(SketchPlugin_Circle::CENTER_ID()))->setValue(myCenter->x(), myCenter->y()); + if (integer(VERSION_ID())->value() > SketchPlugin_Circle::THE_VERSION_0) + { + aCircleFeature->real(SketchPlugin_Circle::ANGLE_ID())->setValue(myAngle); + } aCircleFeature->real(SketchPlugin_Circle::RADIUS_ID())->setValue(myRadius); + aCircleFeature->integer(SketchPlugin_Circle::VERSION_ID())->setValue(integer(VERSION_ID())->value()); aCircleFeature->boolean(SketchPlugin_Circle::AUXILIARY_ID()) ->setValue(boolean(AUXILIARY_ID())->value()); + aCircleFeature->execute(); + + if (integer(VERSION_ID())->value() > SketchPlugin_Circle::THE_VERSION_0) + { + // Create point + FeaturePtr aNPoint = CreatePoint(aCircleFeature, myRotPoint); + } + return aCircleFeature; } @@ -258,6 +366,8 @@ void SketchPlugin_MacroCircle::fillByCenterAndPassed() if (aCircle) { myCenter = aCircle->center(); myRadius = aCircle->radius(); + + computeNewAngle(aCircle); } } @@ -299,6 +409,8 @@ void SketchPlugin_MacroCircle::fillByThreePoints() if (aCircle) { myCenter = aCircle->center(); myRadius = aCircle->radius(); + + computeNewAngle(aCircle); } } @@ -356,25 +468,30 @@ void SketchPlugin_MacroCircle::fillByTwoPassedPoints() if (aCircle) { myCenter = aCircle->center(); myRadius = aCircle->radius(); + + computeNewAngle(aCircle); } } AISObjectPtr SketchPlugin_MacroCircle::getAISObject(AISObjectPtr thePrevious) { SketchPlugin_Sketch* aSketch = sketch(); - if(!aSketch || !myCenter || myRadius == 0) { + if (!aSketch || !myCenter || myRadius == 0) { return AISObjectPtr(); } // Compute a circle in 3D view. 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::dynamic_pointer_cast( + aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID())); std::shared_ptr aNormal = aNDir->dir(); - GeomShapePtr aCircleShape = GeomAlgoAPI_EdgeBuilder::lineCircle(aCenter, aNormal, myRadius); + GeomShapePtr aCircleShape = GeomAlgoAPI_EdgeBuilder::lineCircle(aCenter, aNormal, myRadius, + attribute(ROTATE_POINT_ID())->isInitialized() ? myAngle / 180 * 3.14 : 0); + GeomShapePtr aCenterPointShape = GeomAlgoAPI_PointBuilder::vertex(aCenter); - if(!aCircleShape.get() || !aCenterPointShape.get()) { + + if (!aCircleShape.get() || !aCenterPointShape.get()) { return AISObjectPtr(); } @@ -382,6 +499,18 @@ AISObjectPtr SketchPlugin_MacroCircle::getAISObject(AISObjectPtr thePrevious) aShapes.push_back(aCircleShape); aShapes.push_back(aCenterPointShape); + // For addCircle command skip creating point + if (integer(VERSION_ID())->value() > SketchPlugin_Circle::THE_VERSION_0) + { + std::shared_ptr aRotPoint; + if (myRotPoint.get()) + aRotPoint = std::shared_ptr(aSketch->to3D(myRotPoint->x(), myRotPoint->y())); + else + aRotPoint = std::shared_ptr(aSketch->to3D(myCenter->x() + myRadius, myCenter->y())); + GeomShapePtr aNewPnt = GeomAlgoAPI_PointBuilder::vertex(aRotPoint); + aShapes.push_back(aNewPnt); + } + std::shared_ptr aCompound = GeomAlgoAPI_CompoundBuilder::compound(aShapes); AISObjectPtr anAIS = thePrevious; if(!anAIS.get()) { @@ -395,9 +524,25 @@ AISObjectPtr SketchPlugin_MacroCircle::getAISObject(AISObjectPtr thePrevious) return anAIS; } +namespace +{ + static bool isRotPoint(const std::string& theID, const std::string& theCurType, const std::string& theType) + { + return theCurType == theType + && (theID == SketchPlugin_MacroCircle::ROTATE_POINT_ID() || theID == SketchPlugin_MacroCircle::ROTATE_POINT_REF_ID()); + } +} + void SketchPlugin_MacroCircle::attributeChanged(const std::string& theID) { + std::shared_ptr aCircle; // If circle type switched reset all attributes. if(theID == CIRCLE_TYPE()) { + if (integer(VERSION_ID())->value() > SketchPlugin_Circle::THE_VERSION_0) + { + SketchPlugin_Tools::resetAttribute(this, ROTATE_POINT_ID()); + SketchPlugin_Tools::resetAttribute(this, ROTATE_POINT_REF_ID()); + } + SketchPlugin_Tools::resetAttribute(this, CENTER_POINT_ID()); SketchPlugin_Tools::resetAttribute(this, CENTER_POINT_REF_ID()); SketchPlugin_Tools::resetAttribute(this, PASSED_POINT_ID()); @@ -409,11 +554,13 @@ void SketchPlugin_MacroCircle::attributeChanged(const std::string& theID) { SketchPlugin_Tools::resetAttribute(this, THIRD_POINT_ID()); SketchPlugin_Tools::resetAttribute(this, THIRD_POINT_REF_ID()); } else if(theID == CENTER_POINT_ID() || theID == PASSED_POINT_ID() || - theID == CENTER_POINT_REF_ID() || theID == PASSED_POINT_REF_ID()) + theID == CENTER_POINT_REF_ID() || theID == PASSED_POINT_REF_ID() || + isRotPoint(theID, string(CIRCLE_TYPE())->value(), CIRCLE_TYPE_BY_CENTER_AND_PASSED_POINTS())) fillByCenterAndPassed(); else if(theID == FIRST_POINT_ID() || theID == FIRST_POINT_REF_ID() || theID == SECOND_POINT_ID() || theID == SECOND_POINT_REF_ID() || - theID == THIRD_POINT_ID() || theID == THIRD_POINT_REF_ID()) { + theID == THIRD_POINT_ID() || theID == THIRD_POINT_REF_ID() || + isRotPoint(theID, string(CIRCLE_TYPE())->value(), CIRCLE_TYPE_BY_THREE_POINTS())) { std::shared_ptr aPoints[3]; int aNbInitialized = 0; for(int i = 1; i <= 3; ++i) { @@ -432,12 +579,29 @@ void SketchPlugin_MacroCircle::attributeChanged(const std::string& theID) { } AttributeDoublePtr aRadiusAttr = real(CIRCLE_RADIUS_ID()); + 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); } + + if (integer(VERSION_ID())->value() > SketchPlugin_Circle::THE_VERSION_0) + { + AttributeDoublePtr anAngleAttr = real(CIRCLE_ROTATE_ANGLE_ID()); + + if (myRotPoint.get()) + { + AttributePoint2DPtr aPointAttr = std::dynamic_pointer_cast(attribute(ROTATE_POINT_ID())); + aPointAttr->setValue(myRotPoint); + } + + if (anAngleAttr->isInitialized()) + anAngleAttr->setValue(myAngle); + } + aRadiusAttr->setValue(myRadius); + data()->blockSendAttributeUpdated(aWasBlocked, false); } diff --git a/src/SketchPlugin/SketchPlugin_MacroCircle.h b/src/SketchPlugin/SketchPlugin_MacroCircle.h index c810eb061..d5b45c59f 100644 --- a/src/SketchPlugin/SketchPlugin_MacroCircle.h +++ b/src/SketchPlugin/SketchPlugin_MacroCircle.h @@ -87,6 +87,19 @@ class SketchPlugin_MacroCircle: public SketchPlugin_SketchEntity, return ID; } + /// 2D point - center of the circle. + inline static const std::string& ROTATE_POINT_ID() + { + static const std::string ID("rotate_point"); + return ID; + } + + /// Reference for center point selection. + inline static const std::string& ROTATE_POINT_REF_ID() + { + static const std::string ID("rotate_point_ref"); + return ID; + } /// 2D point - passed point of the circle inline static const std::string& PASSED_POINT_ID() { @@ -150,6 +163,21 @@ class SketchPlugin_MacroCircle: public SketchPlugin_SketchEntity, return ID; } + /// Rotate angle of the circle + inline static const std::string& CIRCLE_ROTATE_ANGLE_ID() + { + static const std::string ID("circle_angle"); + return ID; + } + + /// Attribute name of the version of Circle feature + /// Need for compability with old way of creating circle + inline static const std::string& VERSION_ID() + { + static const std::string MY_VERSION_ID("version"); + return MY_VERSION_ID; + } + /// Returns the kind of a feature SKETCHPLUGIN_EXPORT virtual const std::string& getKind() { @@ -191,11 +219,15 @@ private: void constraintsForCircleByCenterAndPassed(FeaturePtr theCircleFeature); void constraintsForCircleByThreePoints(FeaturePtr theCircleFeature); + void computeNewAngle(std::shared_ptr& theCircle); + FeaturePtr createCircleFeature(); private: std::shared_ptr myCenter; + std::shared_ptr myRotPoint; double myRadius; + double myAngle; }; #endif diff --git a/src/SketchPlugin/Test/TestCreateCircleByCenterAndPassed.py b/src/SketchPlugin/Test/TestCreateCircleByCenterAndPassed.py index 14c3c554e..7e5ba93c0 100644 --- a/src/SketchPlugin/Test/TestCreateCircleByCenterAndPassed.py +++ b/src/SketchPlugin/Test/TestCreateCircleByCenterAndPassed.py @@ -33,7 +33,7 @@ from SketchAPI import SketchAPI_Sketch from salome.shaper import model import math -__updated__ = "2017-03-22" +__updated__ = "2023-06-28" #========================================================================= @@ -68,6 +68,13 @@ def verifyTangentCircleLine(theCircle, theLine): aDistCL = model.distancePointLine(aCenter, theLine) assert math.fabs(aDistCL - aRadius) < TOLERANCE, "Circle and line are not tangent" +#========================================================================= +# Set old version of Circle for avoid create point. +#========================================================================= +def setVersionOfCircle(theCircle, theVersion): + aCircleVersion = theCircle.integer("version") + assert (type(aCircleVersion) == ModelAPI_AttributeInteger) + aCircleVersion.setValue(theVersion) #========================================================================= # Start of test @@ -100,6 +107,7 @@ aCircleCenter = geomDataAPI_Point2D(aCircle.attribute("circle_center")) assert (not aCircleCenter.isInitialized()) aCircleRadius = aCircle.real("circle_radius") assert (type(aCircleRadius) == ModelAPI_AttributeDouble) +setVersionOfCircle(aCircle, 0) # ModelAPI_AttributeDouble.typeId() is checked in ModelAPI_TestConstants assert (aCircleRadius.attributeType() == ModelAPI_AttributeDouble.typeId()) aCircleCenter.setValue(-25., -25) @@ -133,6 +141,7 @@ assert (not aCirclePassed.isInitialized()) aCircleType = aCircle.string("circle_type") assert (not aCircleType.isInitialized()) aCircleType.setValue("circle_type_by_center_and_passed_points") +setVersionOfCircle(aCircle, 0) aCircleCenter.setValue(-25., -25) aCirclePassed.setValue(0., -25.) aRadius = model.distancePointPoint(aCircleCenter, aCirclePassed) @@ -166,6 +175,7 @@ aCircleType = aCircle.string("circle_type") assert (not aCircleType.isInitialized()) # initialize attributes aCircleType.setValue("circle_type_by_center_and_passed_points") +setVersionOfCircle(aCircle, 0) aCenterRef.setObject(aPoint.lastResult()) aCenter.setValue(aPointCoord.pnt()) aPassedRef.setAttr(aPrevCenter) @@ -205,6 +215,7 @@ aPassedRef = aCircle.refattr("passed_point_ref") aCircleType = aCircle.string("circle_type") # initialize attributes aCircleType.setValue("circle_type_by_center_and_passed_points") +setVersionOfCircle(aCircle, 0) aCenterRef.setObject(aLine.lastResult()) anExpectedCenter = [(aLineStart[0] + aLineEnd[0]) * 0.5, (aLineStart[1] + aLineEnd[1]) * 0.5] aCenter.setValue(anExpectedCenter[0], anExpectedCenter[1]) @@ -239,6 +250,7 @@ aPassedRef = aCircle.refattr("passed_point_ref") aCircleType = aCircle.string("circle_type") # initialize attributes aCircleType.setValue("circle_type_by_center_and_passed_points") +setVersionOfCircle(aCircle, 0) anExpectedCenter = [(aLineStart[0] + aLineEnd[0]) * 0.5 + 10., (aLineStart[1] + aLineEnd[1]) * 0.5] aCenter.setValue(anExpectedCenter[0], anExpectedCenter[1]) aPassedRef.setObject(aLine.lastResult()) @@ -268,6 +280,7 @@ aPassedRef = aCircle.refattr("passed_point_ref") aCircleType = aCircle.string("circle_type") # initialize attributes aCircleType.setValue("circle_type_by_center_and_passed_points") +setVersionOfCircle(aCircle, 0) aCenterRef.setObject(aLine.lastResult()) aCenter.setValue(anExpectedCenter[0], anExpectedCenter[1]) aPassedRef.setObject(aLine.lastResult()) @@ -280,6 +293,37 @@ aDocument.removeFeature(aCircle) aSession.finishOperation() assert (aSketchFeature.numberOfSubs() == 12) +#========================================================================= +# Test 6. Create a circle with point on circle line (addCircleWithPoint) +#========================================================================= +# create new circle +aSession.startOperation() +aCircle = aSketchFeature.addFeature("SketchMacroCircle") +aCenter = geomDataAPI_Point2D(aCircle.attribute("center_point")) +aCenterRef = aCircle.refattr("center_point_ref") +aPassed = geomDataAPI_Point2D(aCircle.attribute("passed_point")) +aPassedRef = aCircle.refattr("passed_point_ref") +aCircleType = aCircle.string("circle_type") +aCircleAngle = aCircle.real("circle_angle") +# initialize attributes +aCircleType.setValue("circle_type_by_center_and_passed_points") +setVersionOfCircle(aCircle, 20232206) +aCenter.setValue(35., -35) +anExpectedCenter = [35., -35] +aPassed.setValue(45., -35) +aCircleAngle.setValue(90.) +anExpectedRot = [45., -35] +aSession.finishOperation() +assert (aSketchFeature.numberOfSubs() == 15) +# verify newly created circle +aCircle = model.lastSubFeature(aSketchFeature, "SketchCircle") +aCenter = geomDataAPI_Point2D(aCircle.attribute("circle_center")) +aRotPoint = geomDataAPI_Point2D(aCircle.attribute("circle_rotate")) +model.assertPoint(aCenter, anExpectedCenter) +model.assertPoint(aRotPoint, anExpectedRot) +model.testNbSubFeatures(aSketch, "SketchConstraintCoincidence", 3) +model.testNbSubFeatures(aSketch, "SketchConstraintTangent", 2) + #========================================================================= # End of test #========================================================================= diff --git a/src/SketchPlugin/Test/TestCreateCircleByThreePoints.py b/src/SketchPlugin/Test/TestCreateCircleByThreePoints.py index 29c2f1988..4c8a5cdfd 100644 --- a/src/SketchPlugin/Test/TestCreateCircleByThreePoints.py +++ b/src/SketchPlugin/Test/TestCreateCircleByThreePoints.py @@ -33,7 +33,7 @@ from SketchAPI import SketchAPI_Sketch from salome.shaper import model import math -__updated__ = "2017-03-22" +__updated__ = "2023-06-28" #========================================================================= @@ -82,6 +82,13 @@ def verifyTangentCircleLine(theCircle, theLine): aDistCL = model.distancePointLine(aCenter, theLine) assert math.fabs(aDistCL - aRadius) < TOLERANCE, "Circle and line are not tangent" +#========================================================================= +# Set old version of Circle for avoid create point. +#========================================================================= +def setOldVersionOfCircleFeature(theCircle): + aCircleVersion = theCircle.integer("version") + assert (type(aCircleVersion) == ModelAPI_AttributeInteger) + aCircleVersion.setValue(0) #========================================================================= # Start of test @@ -121,6 +128,7 @@ assert (not aCirclePnt3.isInitialized()) aCircleType = aCircle.string("circle_type") assert (not aCircleType.isInitialized()) aCircleType.setValue("circle_type_by_three_points") +setOldVersionOfCircleFeature(aCircle) aCirclePnt1.setValue(expectedCenter[0] - expectedRadius, expectedCenter[1]) aCirclePnt2.setValue(expectedCenter[0] + expectedRadius, expectedCenter[1]) aCirclePnt3.setValue(expectedCenter[0], expectedCenter[1] + expectedRadius) @@ -162,6 +170,7 @@ aCirclePnt3Ref = aCircle.refattr("third_point_ref") aCircleType = aCircle.string("circle_type") # initialize attributes aCircleType.setValue("circle_type_by_three_points") +setOldVersionOfCircleFeature(aCircle) aCirclePnt1Ref.setAttr(aPrevCenter) aCirclePnt1.setValue(aPrevCenter.pnt()) aCirclePnt2Ref.setObject(aPoint.lastResult()) @@ -209,6 +218,7 @@ aCirclePnt1Ref = aCircle.refattr("first_point_ref") aCirclePnt2Ref = aCircle.refattr("second_point_ref") aCirclePnt3Ref = aCircle.refattr("third_point_ref") aCircleType = aCircle.string("circle_type") +setOldVersionOfCircleFeature(aCircle) # initialize attributes aCircleType.setValue("circle_type_by_three_points") aCirclePnt1Ref.setObject(aPrevCircle.lastResult()) @@ -248,6 +258,7 @@ aCirclePnt3Ref = aCircle.refattr("third_point_ref") aCircleType = aCircle.string("circle_type") # initialize attributes aCircleType.setValue("circle_type_by_three_points") +setOldVersionOfCircleFeature(aCircle) aCirclePnt1Ref.setAttr(aStartPnt) aCirclePnt1.setValue(aStartPnt.pnt()) aCirclePnt2Ref.setAttr(aEndPnt) @@ -279,6 +290,7 @@ aCirclePnt3Ref = aCircle.refattr("third_point_ref") aCircleType = aCircle.string("circle_type") # initialize attributes aCircleType.setValue("circle_type_by_three_points") +setOldVersionOfCircleFeature(aCircle) aCirclePnt1.setValue(aLineStart[0] + aDistanceFromLine, aLineStart[1]) aCirclePnt2.setValue(aLineStart[0] - aDistanceFromLine, aLineStart[1]) aCirclePnt3Ref.setObject(aLine.lastResult()) @@ -324,6 +336,7 @@ aCirclePnt3Ref = aCircle.refattr("third_point_ref") aCircleType = aCircle.string("circle_type") # initialize attributes aCircleType.setValue("circle_type_by_three_points") +setOldVersionOfCircleFeature(aCircle) aCirclePnt1.setValue(0, 0) aCirclePnt2Ref.setObject(SketchLine_1.feature().lastResult()) aCirclePnt2.setValue(SketchLine_1.startPoint().x(), SketchLine_1.startPoint().y()) @@ -353,6 +366,7 @@ aCirclePnt3Ref = aCircle.refattr("third_point_ref") aCircleType = aCircle.string("circle_type") # initialize attributes aCircleType.setValue("circle_type_by_three_points") +setOldVersionOfCircleFeature(aCircle) aCirclePnt1.setValue(0, 0) aCirclePnt2Ref.setObject(SketchCircle_3.feature().lastResult()) aCirclePnt2.setValue(40, 0) @@ -382,6 +396,7 @@ aCirclePnt3Ref = aCircle.refattr("third_point_ref") aCircleType = aCircle.string("circle_type") # initialize attributes aCircleType.setValue("circle_type_by_three_points") +setOldVersionOfCircleFeature(aCircle) aCirclePnt1.setValue(0, 0) aCirclePnt2Ref.setObject(SketchLine_3.feature().lastResult()) aCirclePnt2.setValue(30, 0) @@ -411,6 +426,7 @@ aCirclePnt3Ref = aCircle.refattr("third_point_ref") aCircleType = aCircle.string("circle_type") # initialize attributes aCircleType.setValue("circle_type_by_three_points") +setOldVersionOfCircleFeature(aCircle) aCirclePnt1Ref.setObject(SketchLine_1.feature().lastResult()) aCirclePnt1.setValue(20, 0) aCirclePnt2Ref.setObject(SketchLine_2.feature().lastResult()) @@ -442,6 +458,7 @@ aCirclePnt3Ref = aCircle.refattr("third_point_ref") aCircleType = aCircle.string("circle_type") # initialize attributes aCircleType.setValue("circle_type_by_three_points") +setOldVersionOfCircleFeature(aCircle) aCirclePnt1Ref.setObject(SketchLine_1.feature().lastResult()) aCirclePnt1.setValue(20, 0) aCirclePnt2Ref.setObject(SketchLine_2.feature().lastResult()) @@ -473,6 +490,7 @@ aCirclePnt3Ref = aCircle.refattr("third_point_ref") aCircleType = aCircle.string("circle_type") # initialize attributes aCircleType.setValue("circle_type_by_three_points") +setOldVersionOfCircleFeature(aCircle) aCirclePnt1Ref.setObject(SketchCircle_1.feature().lastResult()) aCirclePnt1.setValue(10, 0) aCirclePnt2Ref.setObject(SketchCircle_2.feature().lastResult()) @@ -489,6 +507,44 @@ verifyTangentCircles(aCircle, SketchCircle_3.feature()) model.testNbSubFeatures(Sketch_1, "SketchConstraintCoincidence", 0) model.testNbSubFeatures(Sketch_1, "SketchConstraintTangent", 15) +#========================================================================= +# Test 12. Create a circle with point on circle line (addCircleWithPoint) +#========================================================================= +# create new circle +aSession.startOperation() +aCircle = aSketchFeature.addFeature("SketchMacroCircle") +aCirclePnt1 = geomDataAPI_Point2D(aCircle.attribute("first_point")) +aCirclePnt2 = geomDataAPI_Point2D(aCircle.attribute("second_point")) +aCirclePnt3 = geomDataAPI_Point2D(aCircle.attribute("third_point")) +aCirclePnt1Ref = aCircle.refattr("first_point_ref") +aCirclePnt2Ref = aCircle.refattr("second_point_ref") +aCirclePnt3Ref = aCircle.refattr("third_point_ref") +aCircleType = aCircle.string("circle_type") +aCircleAngle = aCircle.real("circle_angle") +# initialize attributes +aCircleType.setValue("circle_type_by_three_points") +aCirclePnt1Ref.setObject(SketchCircle_1.feature().lastResult()) +aCirclePnt1.setValue(20, 0) +aCirclePnt2Ref.setObject(SketchCircle_2.feature().lastResult()) +aCirclePnt2.setValue(40, 20) +aCirclePnt3Ref.setObject(SketchCircle_3.feature().lastResult()) +aCirclePnt3.setValue(50, 0) +aCircleAngle.setValue(180.) +anExpectedRot = [60.853417638885404, 4.3837725517883515] +aSession.finishOperation() +assert (aSketchFeature.numberOfSubs() == 33) +# verify newly created circle +aCircle = model.lastSubFeature(aSketchFeature, "SketchCircle") +aCenter = geomDataAPI_Point2D(aCircle.attribute("circle_center")) +aRotPoint = geomDataAPI_Point2D(aCircle.attribute("circle_rotate")) +model.assertPoint(aCenter, [35.2879593663427, 5.1151837465370855]) +model.assertPoint(aCirclePnt1, [20, 0]) +model.assertPoint(aCirclePnt2, [40, 20]) +model.assertPoint(aCirclePnt3, [50., 0.]) +model.assertPoint(aRotPoint, anExpectedRot) +model.testNbSubFeatures(aSketch, "SketchConstraintCoincidence", 3) +model.testNbSubFeatures(aSketch, "SketchConstraintTangent", 3) + #========================================================================= # End of test #========================================================================= diff --git a/src/SketchPlugin/Test/TestCreateCircleChangeType.py b/src/SketchPlugin/Test/TestCreateCircleChangeType.py index 803561bfc..c3bfdf523 100644 --- a/src/SketchPlugin/Test/TestCreateCircleChangeType.py +++ b/src/SketchPlugin/Test/TestCreateCircleChangeType.py @@ -181,7 +181,7 @@ aPassedPoint.setValue(aLineEnd.pnt()) aSession.finishOperation() aRadius = model.distancePointPoint(aLineStart, aLineEnd) -NB_FEATURES_EXPECTED = 4 # line, circle and two coincidences +NB_FEATURES_EXPECTED = 6 # line, circle, point on circle and three coincidences assert (aSketchFeature.numberOfSubs() == NB_FEATURES_EXPECTED), "Number of features in sketch {}, expected {}".format(aSketchFeature.numberOfSubs(), NB_FEATURES_EXPECTED) verifyLastCircle(aSketchFeature, aLineStart.x(), aLineStart.y(), aRadius) diff --git a/src/SketchPlugin/Test/TestMoveCircle.py b/src/SketchPlugin/Test/TestMoveCircle.py index b48900e2b..0bdcdbf10 100644 --- a/src/SketchPlugin/Test/TestMoveCircle.py +++ b/src/SketchPlugin/Test/TestMoveCircle.py @@ -35,7 +35,7 @@ class TestMoveCircle(unittest.TestCase): self.myCenter = [70., 50.] self.myRadius = 20. self.myCircle = self.mySketch.addCircle(self.myCenter[0], self.myCenter[1], self.myRadius) - self.myDOF = 3 + self.myDOF = 5 model.do() self.checkDOF() diff --git a/src/SketchPlugin/doc/circleFeature.rst b/src/SketchPlugin/doc/circleFeature.rst index b729a6d4d..fa24e9e29 100644 --- a/src/SketchPlugin/doc/circleFeature.rst +++ b/src/SketchPlugin/doc/circleFeature.rst @@ -3,7 +3,7 @@ Circle ====== -The feature Circle creates a circle in the current Sketch. +The feature Circle creates a circle and point on line in the current Sketch. To add a new Circle to the Sketch: @@ -32,14 +32,31 @@ By center and passed point .. figure:: images/Circle_panel_pt_rad.png :align: center -Click in the view once to set the center point, then move the mouse and click a second time to set the passed point. +Click in the view once to set the center point, then move the mouse and click a second time to set the passed point and finally +click third time to set point on the line. - When entering a center point by selecting either a point or a segment, a Coincident constraint is created. - When entering a passing point by selecting a point, a Coincident constraint is also created. - When entering a passing point by selecting a segment, a Tangent constraint is created. +- Point on the line show sewing point for circle. If rotate this point, sewing point also will be changed + **TUI Command**: +.. py:function:: Sketch_1.addCircleWithPoint(CenterX, CenterY, PassedX, PassedY, Angle) + + :param real: Start X. + :param real: Start Y. + :param real: Passed X. + :param real: Passed Y. + :param real: Rotation angle for sewing point + :return: Result object. + +.. py:function:: SketchCircle_1.createdPoint() + :return: Created point on circle line + +This method is deprecated, please, use addCircleWithPoint + .. py:function:: Sketch_1.addCircle(CenterX, CenterY, PassedX, PassedY) :param real: Start X. @@ -55,13 +72,31 @@ By three points :align: center Click in the view once to set the first passed point, then move the mouse and click a second time to set the second passed point -and finally move the mouse and click a third time to set the last passed point. +then move the mouse and click a third time to set the last passed point, and finally +click last time to set point on the line. - When entering a passing point by selecting a point, a Coincident constraint is created. - When entering a passing point by selecting a segment, a Tangent constraint is created. +- Point on the line show sewing point for circle. If rotate this point, sewing point also will be changed **TUI Command**: +.. py:function:: Sketch_1.addCircleWithPoint(X1, Y1, X2, Y2, X3, Y3, Angle) + + :param real: Start X. + :param real: Start Y. + :param real: Passed X. + :param real: Passed Y. + :param real: End X. + :param real: End Y. + :param real: Rotation angle for sewing point + :return: Result object. + +.. py:function:: SketchCircle_1.createdPoint() + :return: Created point on circle line + +This method is deprecated, please, use addCircleWithPoint + .. py:function:: Sketch_1.addCircle(X1, Y1, X2, Y2, X3, Y3) :param real: Start X. diff --git a/src/SketchPlugin/doc/images/Circle_panel_3pt.png b/src/SketchPlugin/doc/images/Circle_panel_3pt.png index c837accbf..88b1cfbc7 100644 Binary files a/src/SketchPlugin/doc/images/Circle_panel_3pt.png and b/src/SketchPlugin/doc/images/Circle_panel_3pt.png differ diff --git a/src/SketchPlugin/doc/images/Circle_panel_edit.png b/src/SketchPlugin/doc/images/Circle_panel_edit.png index c9983f2ec..ed2d315f6 100644 Binary files a/src/SketchPlugin/doc/images/Circle_panel_edit.png and b/src/SketchPlugin/doc/images/Circle_panel_edit.png differ diff --git a/src/SketchPlugin/doc/images/Circle_panel_pt_rad.png b/src/SketchPlugin/doc/images/Circle_panel_pt_rad.png index e171e58fe..f8067213c 100644 Binary files a/src/SketchPlugin/doc/images/Circle_panel_pt_rad.png and b/src/SketchPlugin/doc/images/Circle_panel_pt_rad.png differ diff --git a/src/SketchPlugin/plugin-Sketch.xml b/src/SketchPlugin/plugin-Sketch.xml index f69c00040..ab5488d0a 100644 --- a/src/SketchPlugin/plugin-Sketch.xml +++ b/src/SketchPlugin/plugin-Sketch.xml @@ -65,6 +65,11 @@ tooltip="Center coordinates" accept_expressions="0" enable_value="enable_by_preferences"/> + + + + diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp index 1f0fd0e7c..8f6ff982d 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp @@ -480,7 +480,8 @@ bool PlaneGCSSolver_Tools::isAttributeApplicable(const std::string& theAttrName, } else if (theOwnerName == SketchPlugin_Circle::ID()) { return theAttrName == SketchPlugin_Circle::CENTER_ID() || - theAttrName == SketchPlugin_Circle::RADIUS_ID(); + theAttrName == SketchPlugin_Circle::RADIUS_ID() || + theAttrName == SketchPlugin_Circle::ROTATE_ID(); } else if (theOwnerName == SketchPlugin_Line::ID()) { return theAttrName == SketchPlugin_Line::START_ID() ||