Salome HOME
bos#35152 [EDF] (2023-T1) Sketch Circle should allow user to position construction... 12/head
authorasozinov <alexey.sozinov@opencascade.com>
Fri, 23 Jun 2023 01:06:02 +0000 (02:06 +0100)
committerasozinov <alexey.sozinov@opencascade.com>
Wed, 25 Oct 2023 11:01:05 +0000 (12:01 +0100)
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

22 files changed:
src/GeomAlgoAPI/GeomAlgoAPI_EdgeBuilder.cpp
src/GeomAlgoAPI/GeomAlgoAPI_EdgeBuilder.h
src/SketchAPI/SketchAPI_Circle.cpp
src/SketchAPI/SketchAPI_Circle.h
src/SketchAPI/SketchAPI_MacroCircle.cpp
src/SketchAPI/SketchAPI_MacroCircle.h
src/SketchAPI/SketchAPI_Sketch.cpp
src/SketchAPI/SketchAPI_Sketch.h
src/SketchPlugin/SketchPlugin_Circle.cpp
src/SketchPlugin/SketchPlugin_Circle.h
src/SketchPlugin/SketchPlugin_MacroCircle.cpp
src/SketchPlugin/SketchPlugin_MacroCircle.h
src/SketchPlugin/Test/TestCreateCircleByCenterAndPassed.py
src/SketchPlugin/Test/TestCreateCircleByThreePoints.py
src/SketchPlugin/Test/TestCreateCircleChangeType.py
src/SketchPlugin/Test/TestMoveCircle.py
src/SketchPlugin/doc/circleFeature.rst
src/SketchPlugin/doc/images/Circle_panel_3pt.png
src/SketchPlugin/doc/images/Circle_panel_edit.png
src/SketchPlugin/doc/images/Circle_panel_pt_rad.png
src/SketchPlugin/plugin-Sketch.xml
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp

index f19425a48386f2660f571b9426c3d30e3478286b..86fe03d7b30a640cba5b53ce8f00af2c8848c396 100644 (file)
@@ -162,12 +162,16 @@ std::shared_ptr<GeomAPI_Edge> GeomAlgoAPI_EdgeBuilder::cylinderAxis(
 
 std::shared_ptr<GeomAPI_Edge> GeomAlgoAPI_EdgeBuilder::lineCircle(
     std::shared_ptr<GeomAPI_Pnt> theCenter, std::shared_ptr<GeomAPI_Dir> theNormal,
-    double theRadius)
+    double theRadius, double theRotationAngle)
 {
   const gp_Pnt& aCenter = theCenter->impl<gp_Pnt>();
   const gp_Dir& aDir = theNormal->impl<gp_Dir>();
 
+  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<GeomAPI_Edge> aRes(new GeomAPI_Edge);
index 4650740284a3cc4d6dc3c608abb146fc6306a86f..fabae078a16e914b50385bb73c9f11a81780a171 100644 (file)
@@ -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<GeomAPI_Edge> lineCircle(std::shared_ptr<GeomAPI_Pnt> theCenter,
                                                     std::shared_ptr<GeomAPI_Dir> theNormal,
-                                                    double theRadius);
+                                                    double theRadius,
+                                                    double theRotationAngle = 0.);
 
   /// Creates linear edge in a form of a circle by GeomAPI_Circle
   static std::shared_ptr<GeomAPI_Edge> lineCircle(std::shared_ptr<GeomAPI_Circ> theCircle);
index 41853fe1d06d0dc1a21d960eda2cbeb104ed6873..95d48f39706716786722bdf624af1ded13d85140 100644 (file)
@@ -26,6 +26,9 @@
 #include <ModelHighAPI_Selection.h>
 #include <ModelHighAPI_Tools.h>
 
+#include <SketchAPI_Point.h>
+#include <SketchPlugin_ConstraintCoincidenceInternal.h>
+
 //==================================================================================================
 SketchAPI_Circle::SketchAPI_Circle(const std::shared_ptr<ModelAPI_Feature> & theFeature)
 : SketchAPI_SketchEntity(theFeature)
@@ -37,22 +40,22 @@ SketchAPI_Circle::SketchAPI_Circle(const std::shared_ptr<ModelAPI_Feature> & the
 SketchAPI_Circle::SketchAPI_Circle(const std::shared_ptr<ModelAPI_Feature>& 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<ModelAPI_Feature>& theFeature,
                                    const std::shared_ptr<GeomAPI_Pnt2d>& 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<AttributePtr>& aRefs = feature()->data()->refsToMe();
+  for (std::set<AttributePtr>::const_iterator anIt = aRefs.begin(); anIt != aRefs.end(); ++anIt)
+    if ((*anIt)->id() == SketchPlugin_Sketch::FEATURES_ID())
+    {
+      aSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>((*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<GeomDataAPI_Point2D>(
+    aPointFeature->attribute(SketchPlugin_Point::COORD_ID()));
+
+  GeomPnt2dPtr aPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+    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<ModelAPI_AttributeRefAttr>(
+    aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
+  aRefAttr->setAttr(feature()->attribute(SketchPlugin_Circle::ROTATE_ID()));
+
+  aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+    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<GeomAPI_Pnt2d>& 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_SketchEntity> SketchAPI_Circle::createdPoint() const
+{
+  std::shared_ptr<SketchAPI_SketchEntity> 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<SketchAPI_SketchEntity> 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);
index dcc58c7153b8aadcfc5a718f10feebd0f4909b74..96744ebf5cf42fe0f9c8e594611fa003e70e0d4d 100644 (file)
@@ -42,13 +42,15 @@ public:
   SketchAPI_Circle(const std::shared_ptr<ModelAPI_Feature>& theFeature,
                    double theCenterX,
                    double theCenterY,
-                   double theRadius);
+                   double theRadius,
+                   double theAngle);
 
   /// Constructor with values.
   SKETCHAPI_EXPORT
   SketchAPI_Circle(const std::shared_ptr<ModelAPI_Feature>& theFeature,
                    const std::shared_ptr<GeomAPI_Pnt2d>& 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<GeomAPI_Pnt2d>& theCenter, double theRadius);
+  void setByCenterAndRadius(const std::shared_ptr<GeomAPI_Pnt2d>& 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<SketchAPI_SketchEntity> createdPoint() const;
+
   /// Dump wrapped feature
   SKETCHAPI_EXPORT
   virtual void dump(ModelHighAPI_Dumper& theDumper) const;
+
+private:
+  void createPoint();
 };
 
 /// Pointer on Circle object.
index f5e459a407c5343d524dd51f019453d3a9e78980..64089321421253a697f567044c716a66cd0c904c 100644 (file)
@@ -26,6 +26,9 @@
 #include <ModelHighAPI_Selection.h>
 #include <ModelHighAPI_Tools.h>
 
+#include <SketchAPI_Point.h>
+#include <SketchPlugin_ConstraintCoincidenceInternal.h>
+
 //==================================================================================================
 SketchAPI_MacroCircle::SketchAPI_MacroCircle(const std::shared_ptr<ModelAPI_Feature>& theFeature)
 : SketchAPI_SketchEntity(theFeature)
@@ -38,22 +41,24 @@ SketchAPI_MacroCircle::SketchAPI_MacroCircle(const std::shared_ptr<ModelAPI_Feat
                                              double theCenterX,
                                              double theCenterY,
                                              double thePassedX,
-                                             double thePassedY)
+                                             double thePassedY,
+                                             double theAngle)
 : SketchAPI_SketchEntity(theFeature)
 {
   if(initialize()) {
-    setByCenterAndPassedPoints(theCenterX, theCenterY, thePassedX, thePassedY);
+    setByCenterAndPassedPoints(theCenterX, theCenterY, thePassedX, thePassedY, theAngle);
   }
 }
 
 //==================================================================================================
 SketchAPI_MacroCircle::SketchAPI_MacroCircle(const std::shared_ptr<ModelAPI_Feature>& theFeature,
                                              const std::shared_ptr<GeomAPI_Pnt2d>& theCenterPoint,
-                                             const std::shared_ptr<GeomAPI_Pnt2d>& thePassedPoint)
+                                             const std::shared_ptr<GeomAPI_Pnt2d>& 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<ModelAPI_Feat
 SketchAPI_MacroCircle::SketchAPI_MacroCircle(const std::shared_ptr<ModelAPI_Feature>& 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<ModelAPI_Feat
 SketchAPI_MacroCircle::SketchAPI_MacroCircle(const std::shared_ptr<ModelAPI_Feature>& theFeature,
                                              const std::shared_ptr<GeomAPI_Pnt2d>& thePoint1,
                                              const std::shared_ptr<GeomAPI_Pnt2d>& thePoint2,
-                                             const std::shared_ptr<GeomAPI_Pnt2d>& thePoint3)
+                                             const std::shared_ptr<GeomAPI_Pnt2d>& 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<GeomAPI_Pnt2d>& theCenterPoint,
-    const std::shared_ptr<GeomAPI_Pnt2d>& thePassedPoint)
+    const std::shared_ptr<GeomAPI_Pnt2d>& 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<GeomAPI_Pnt2d>& thePoint1,
                                              const std::shared_ptr<GeomAPI_Pnt2d>& thePoint2,
-                                             const std::shared_ptr<GeomAPI_Pnt2d>& thePoint3)
+                                             const std::shared_ptr<GeomAPI_Pnt2d>& 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_SketchEntity> SketchAPI_MacroCircle::createdPoint() const
+{
+  std::shared_ptr<SketchAPI_SketchEntity> 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;
+}
index 725edeacba82f16b2e5a647fbb6f84f2c40308ee..ee278b9f9af806508e08271df4d73ab24b3ce99f 100644 (file)
@@ -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<ModelAPI_Feature>& theFeature,
                         const std::shared_ptr<GeomAPI_Pnt2d>& theCenterPoint,
-                        const std::shared_ptr<GeomAPI_Pnt2d>& thePassedPoint);
+                        const std::shared_ptr<GeomAPI_Pnt2d>& thePassedPoint,
+                        double theAngle);
 
   /// Constructor with values.
   SKETCHAPI_EXPORT
   SketchAPI_MacroCircle(const std::shared_ptr<ModelAPI_Feature>& 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<ModelAPI_Feature>& theFeature,
                         const std::shared_ptr<GeomAPI_Pnt2d>& thePoint1,
                         const std::shared_ptr<GeomAPI_Pnt2d>& thePoint2,
-                        const std::shared_ptr<GeomAPI_Pnt2d>& thePoint3);
+                        const std::shared_ptr<GeomAPI_Pnt2d>& 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<SketchAPI_SketchEntity> 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<GeomAPI_Pnt2d>& theCenterPoint,
-                                  const std::shared_ptr<GeomAPI_Pnt2d>& thePassedPoint);
+                                  const std::shared_ptr<GeomAPI_Pnt2d>& 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<GeomAPI_Pnt2d>& thePoint1,
                         const std::shared_ptr<GeomAPI_Pnt2d>& thePoint2,
-                        const std::shared_ptr<GeomAPI_Pnt2d>& thePoint3);
+                        const std::shared_ptr<GeomAPI_Pnt2d>& thePoint3,
+                        double theAngle);
 };
 
 /// Pointer on Circle object.
index b0836ae1219b50013cf6d621c3b1fd29646b7f09..3c30c146a1f915867aaef34d71fab54c1c2c9262 100644 (file)
@@ -589,25 +589,31 @@ std::shared_ptr<SketchAPI_Rectangle> SketchAPI_Sketch::addRectangleCentered(
   return aRect;
 }
 
+// Old way for create circle
 //--------------------------------------------------------------------------------------
+[[deprecated("Use addCircleWithPoint method instead.")]]
 std::shared_ptr<SketchAPI_Circle> SketchAPI_Sketch::addCircle(double theCenterX,
                                                               double theCenterY,
                                                               double theRadius)
 {
   std::shared_ptr<ModelAPI_Feature> 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_Circle> SketchAPI_Sketch::addCircle(
                                     const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
                                     double theRadius)
 {
   std::shared_ptr<ModelAPI_Feature> 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_MacroCircle> SketchAPI_Sketch::addCircle(double theCenterX,
                                                                    double theCenterY,
                                                                    double thePassedX,
@@ -615,30 +621,37 @@ std::shared_ptr<SketchAPI_MacroCircle> SketchAPI_Sketch::addCircle(double theCen
 {
   std::shared_ptr<ModelAPI_Feature> 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_MacroCircle> SketchAPI_Sketch::addCircle(
     const std::shared_ptr<GeomAPI_Pnt2d>& theCenterPoint,
     const std::shared_ptr<GeomAPI_Pnt2d>& thePassedPoint)
 {
   std::shared_ptr<ModelAPI_Feature> 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_MacroCircle> SketchAPI_Sketch::addCircle(double theX1, double theY1,
                                                                    double theX2, double theY2,
                                                                    double theX3, double theY3)
 {
   std::shared_ptr<ModelAPI_Feature> 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_MacroCircle> SketchAPI_Sketch::addCircle(
     const std::shared_ptr<GeomAPI_Pnt2d>& thePoint1,
     const std::shared_ptr<GeomAPI_Pnt2d>& thePoint2,
@@ -646,9 +659,11 @@ std::shared_ptr<SketchAPI_MacroCircle> SketchAPI_Sketch::addCircle(
 {
   std::shared_ptr<ModelAPI_Feature> 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_Circle>
   SketchAPI_Sketch::addCircle(const ModelHighAPI_Selection & theExternal)
 {
@@ -657,6 +672,7 @@ std::shared_ptr<SketchAPI_Circle>
   return CirclePtr(new SketchAPI_Circle(aFeature, theExternal));
 }
 
+[[deprecated("Use addCircleWithPoint method instead.")]]
 std::shared_ptr<SketchAPI_Circle> SketchAPI_Sketch::addCircle(const std::wstring & theExternalName)
 {
   std::shared_ptr<ModelAPI_Feature> aFeature =
@@ -664,6 +680,88 @@ std::shared_ptr<SketchAPI_Circle> SketchAPI_Sketch::addCircle(const std::wstring
   return CirclePtr(new SketchAPI_Circle(aFeature, theExternalName));
 }
 
+// New way for create Circle
+//--------------------------------------------------------------------------------------
+std::shared_ptr<SketchAPI_Circle> SketchAPI_Sketch::addCircleWithPoint(double theCenterX,
+  double theCenterY,
+  double theRadius,
+  double theAngle)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature =
+    compositeFeature()->addFeature(SketchPlugin_Circle::ID());
+  return CirclePtr(new SketchAPI_Circle(aFeature, theCenterX, theCenterY, theRadius, theAngle));
+}
+
+std::shared_ptr<SketchAPI_Circle> SketchAPI_Sketch::addCircleWithPoint(
+  const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
+  double theRadius,
+  double theAngle)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature =
+    compositeFeature()->addFeature(SketchPlugin_Circle::ID());
+  return CirclePtr(new SketchAPI_Circle(aFeature, theCenter, theRadius, theAngle));
+}
+
+std::shared_ptr<SketchAPI_MacroCircle> SketchAPI_Sketch::addCircleWithPoint(double theCenterX,
+  double theCenterY,
+  double thePassedX,
+  double thePassedY,
+  double theAngle)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature =
+    compositeFeature()->addFeature(SketchPlugin_MacroCircle::ID());
+  return MacroCirclePtr(new SketchAPI_MacroCircle(aFeature, theCenterX, theCenterY,
+    thePassedX, thePassedY, theAngle));
+}
+
+std::shared_ptr<SketchAPI_MacroCircle> SketchAPI_Sketch::addCircleWithPoint(
+  const std::shared_ptr<GeomAPI_Pnt2d>& theCenterPoint,
+  const std::shared_ptr<GeomAPI_Pnt2d>& thePassedPoint,
+  double theAngle)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature =
+    compositeFeature()->addFeature(SketchPlugin_MacroCircle::ID());
+  return MacroCirclePtr(new SketchAPI_MacroCircle(aFeature, theCenterPoint, thePassedPoint, theAngle));
+}
+
+std::shared_ptr<SketchAPI_MacroCircle> SketchAPI_Sketch::addCircleWithPoint(double theX1, double theY1,
+  double theX2, double theY2,
+  double theX3, double theY3,
+  double theAngle)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature =
+    compositeFeature()->addFeature(SketchPlugin_MacroCircle::ID());
+  return MacroCirclePtr(new SketchAPI_MacroCircle(aFeature, theX1, theY1,
+    theX2, theY2,
+    theX3, theY3, theAngle));
+}
+
+std::shared_ptr<SketchAPI_MacroCircle> SketchAPI_Sketch::addCircleWithPoint(
+  const std::shared_ptr<GeomAPI_Pnt2d>& thePoint1,
+  const std::shared_ptr<GeomAPI_Pnt2d>& thePoint2,
+  const std::shared_ptr<GeomAPI_Pnt2d>& thePoint3,
+  double theAngle)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature =
+    compositeFeature()->addFeature(SketchPlugin_MacroCircle::ID());
+  return MacroCirclePtr(new SketchAPI_MacroCircle(aFeature, thePoint1, thePoint2, thePoint3, theAngle));
+}
+
+std::shared_ptr<SketchAPI_Circle>
+SketchAPI_Sketch::addCircleWithPoint(const ModelHighAPI_Selection& theExternal)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature =
+    compositeFeature()->addFeature(SketchPlugin_Circle::ID());
+  return CirclePtr(new SketchAPI_Circle(aFeature, theExternal));
+}
+
+std::shared_ptr<SketchAPI_Circle> SketchAPI_Sketch::addCircleWithPoint(const std::wstring& theExternalName)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature =
+    compositeFeature()->addFeature(SketchPlugin_Circle::ID());
+  return CirclePtr(new SketchAPI_Circle(aFeature, theExternalName));
+}
+
 //--------------------------------------------------------------------------------------
 std::shared_ptr<SketchAPI_Arc> SketchAPI_Sketch::addArc(double theCenterX, double theCenterY,
                                                         double theStartX, double theStartY,
index 993e6ef901536e95e39316e17c17c648863da9bd..7f2fa98ea31fef627833078d25504f9835eee8c9 100644 (file)
@@ -187,45 +187,96 @@ public:
       const std::pair<std::shared_ptr<GeomAPI_Pnt2d>, ModelHighAPI_RefAttr> & theCenter,
       const std::pair<std::shared_ptr<GeomAPI_Pnt2d>, ModelHighAPI_RefAttr> & theCorner);
 
-  /// Add circle
+  /// Add circle.
+  /// [DEPRECATED]: use addCircleWithPoint() instead.
   SKETCHAPI_EXPORT
   std::shared_ptr<SketchAPI_Circle> addCircle(
       double theCenterX, double theCenterY,
       double theRadius);
-  /// Add circle
+  /// Add circle.
+  /// [DEPRECATED]: use addCircleWithPoint() instead.
   SKETCHAPI_EXPORT
   std::shared_ptr<SketchAPI_Circle> addCircle(
       const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
       double theRadius);
-  /// Add circle
+  /// Add circle.
+  /// [DEPRECATED]: use addCircleWithPoint() instead.
   SKETCHAPI_EXPORT
   std::shared_ptr<SketchAPI_MacroCircle> addCircle(
       double theCenterX, double theCenterY,
       double thePassedX, double thePassedY);
-  /// Add circle
+  /// Add circle.
+  /// [DEPRECATED]: use addCircleWithPoint() instead.
   SKETCHAPI_EXPORT
   std::shared_ptr<SketchAPI_MacroCircle> addCircle(
       const std::shared_ptr<GeomAPI_Pnt2d>& theCenterPoint,
       const std::shared_ptr<GeomAPI_Pnt2d>& thePassedPoint);
-  /// Add circle
+  /// Add circle.
+  /// [DEPRECATED]: use addCircleWithPoint() instead.
   SKETCHAPI_EXPORT
   std::shared_ptr<SketchAPI_MacroCircle> 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<SketchAPI_MacroCircle> addCircle(
       const std::shared_ptr<GeomAPI_Pnt2d>& thePoint1,
       const std::shared_ptr<GeomAPI_Pnt2d>& thePoint2,
       const std::shared_ptr<GeomAPI_Pnt2d>& thePoint3);
-  /// Add circle
+  /// Add circle.
+  /// [DEPRECATED]: use addCircleWithPoint() instead.
   SKETCHAPI_EXPORT
   std::shared_ptr<SketchAPI_Circle> addCircle(const ModelHighAPI_Selection & theExternal);
-  /// Add circle
+  /// Add circle.
+  /// [DEPRECATED]: use addCircleWithPoint() instead.
   SKETCHAPI_EXPORT
   std::shared_ptr<SketchAPI_Circle> addCircle(const std::wstring & theExternalName);
 
+  /// Add circle with point
+  SKETCHAPI_EXPORT
+    std::shared_ptr<SketchAPI_Circle> addCircleWithPoint(
+      double theCenterX, double theCenterY,
+      double theRadius, double theAngle);
+  /// Add circle with point
+  SKETCHAPI_EXPORT
+    std::shared_ptr<SketchAPI_Circle> addCircleWithPoint(
+      const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
+      double theRadius, double theAngle);
+  /// Add circle with point
+  SKETCHAPI_EXPORT
+    std::shared_ptr<SketchAPI_MacroCircle> addCircleWithPoint(
+      double theCenterX, double theCenterY,
+      double thePassedX, double thePassedY,
+      double theAngle);
+  /// Add circle with point
+  SKETCHAPI_EXPORT
+    std::shared_ptr<SketchAPI_MacroCircle> addCircleWithPoint(
+      const std::shared_ptr<GeomAPI_Pnt2d>& theCenterPoint,
+      const std::shared_ptr<GeomAPI_Pnt2d>& thePassedPoint,
+      double theAngle);
+  /// Add circle with point
+  SKETCHAPI_EXPORT
+    std::shared_ptr<SketchAPI_MacroCircle> addCircleWithPoint(
+      double theX1, double theY1,
+      double theX2, double theY2,
+      double theX3, double theY3,
+      double theAngle);
+  /// Add circle with point
+  SKETCHAPI_EXPORT
+    std::shared_ptr<SketchAPI_MacroCircle> addCircleWithPoint(
+      const std::shared_ptr<GeomAPI_Pnt2d>& thePoint1,
+      const std::shared_ptr<GeomAPI_Pnt2d>& thePoint2,
+      const std::shared_ptr<GeomAPI_Pnt2d>& thePoint3,
+      double theAngle);
+  /// Add circle with point
+  SKETCHAPI_EXPORT
+    std::shared_ptr<SketchAPI_Circle> addCircleWithPoint(const ModelHighAPI_Selection& theExternal);
+  /// Add circle with point
+  SKETCHAPI_EXPORT
+    std::shared_ptr<SketchAPI_Circle> addCircleWithPoint(const std::wstring& theExternalName);
+
   /// Add arc
   SKETCHAPI_EXPORT
   std::shared_ptr<SketchAPI_Arc> addArc(
index c0eecf508b5a1d3b81a67c4b4094fa04003521e7..86d5721e8d9c14f4da5a1cc14c30f5e998c09c37 100644 (file)
 
 #include "SketchPlugin_Circle.h"
 #include "SketchPlugin_Sketch.h"
+#include "SketchPlugin_Tools.h"
 #include <ModelAPI_Data.h>
 #include <ModelAPI_ResultConstruction.h>
 #include <ModelAPI_AttributeSelection.h>
+#include <ModelAPI_AttributeReference.h>
+#include <ModelAPI_AttributeInteger.h>
 #include <ModelAPI_Validator.h>
 #include <ModelAPI_AttributeDouble.h>
 #include <ModelAPI_AttributeString.h>
 #include <ModelAPI_Session.h>
+#include <SketchPlugin_Point.h>
+#include <SketchPlugin_ConstraintCoincidenceInternal.h>
 
 #include <GeomAPI_Pnt2d.h>
 #include <GeomAPI_Circ.h>
+#include <GeomAPI_Dir2d.h>
 #include <GeomAPI_Circ2d.h>
 #include <GeomAPI_Vertex.h>
 #include <GeomAPI_XY.h>
@@ -41,6 +47,7 @@
 #include <cmath>
 
 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<ModelAPI_AttributeInteger>(
+    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<GeomDataAPI_Point2D> aCenterAttr =
       std::dynamic_pointer_cast<GeomDataAPI_Point2D>(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<GeomAPI_Dir> aNormal(new GeomAPI_Dir(aNDir->x(), aNDir->y(), aNDir->z()));
 
-  std::shared_ptr<GeomAPI_Shape> aCircleShape =
-      GeomAlgoAPI_EdgeBuilder::lineCircle(aCenter, aNormal, aRadius);
+  std::shared_ptr<GeomAPI_Edge> 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<GeomDataAPI_Point2D>(data()->attribute(ROTATE_ID()))
+      ->setValue(aCircleSewPoint->x(), aCircleSewPoint->y());
+    data()->blockSendAttributeUpdated(aWasBlocked, false);
+  }
+  else
+    aCircleShape = GeomAlgoAPI_EdgeBuilder::lineCircle(aCenter, aNormal, aRadius);
 
   std::shared_ptr<ModelAPI_ResultConstruction> aResult = document()->createConstruction(data(), 1);
   aResult->setShape(aCircleShape);
@@ -116,7 +157,37 @@ void SketchPlugin_Circle::attributeChanged(const std::string& theID) {
       std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr =
         std::dynamic_pointer_cast<GeomDataAPI_Point2D>(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<GeomAPI_Shape> aSelection;
+    ResultPtr aCircleRes = lastResult();
+    if (aCircleRes)
+      aSelection = aCircleRes->shape();
+    if (aSelection && !aSelection->isNull() && aSelection->isEdge()) {
+      std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge(aSelection));
+      std::shared_ptr<GeomAPI_Circ> aCirc = anEdge->circle();
+
+      // Get point and project it on line
+      std::shared_ptr<GeomDataAPI_Point2D> aNewPntRot =
+        std::dynamic_pointer_cast<GeomDataAPI_Point2D>(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);
     }
   }
 }
index c5035fba26b9603e6b762ec420bcad3240218412..0f620d7a7459121405337e6310773b7e285a4c0d 100644 (file)
@@ -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();
 
index 2725d0be9fc9821c053a44173cf6b1afbb0ac09f..4f107ebe594766f134bf74112a1862925f84b5a4 100644 (file)
 #include "SketchPlugin_Point.h"
 #include "SketchPlugin_Tools.h"
 #include "SketchPlugin_MacroArcReentrantMessage.h"
+#include <SketchPlugin_ConstraintCoincidenceInternal.h>
 
+#include <Locale_Convert.h>
 #include <ModelAPI_AttributeDouble.h>
 #include <ModelAPI_AttributeRefAttr.h>
 #include <ModelAPI_AttributeString.h>
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_AttributeReference.h>
 #include <ModelAPI_Session.h>
 #include <ModelAPI_Validator.h>
 #include <ModelAPI_Events.h>
 #include <GeomDataAPI_Point2D.h>
 
 #include <GeomAPI_Circ2d.h>
+#include <GeomAPI_Dir2d.h>
 #include <GeomAPI_Pnt2d.h>
 #include <GeomAPI_Vertex.h>
+#include <GeomAPI_Ax1.h>
 
 #include <GeomAlgoAPI_Circ2dBuilder.h>
 #include <GeomAlgoAPI_CompoundBuilder.h>
@@ -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<ModelAPI_AttributeInteger>(
+    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<GeomAPI_Circ2d>& 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<GeomAPI_Pnt2d> aRotPoit;
+    std::shared_ptr<GeomAPI_Shape> aTangentCurve;
+    SketchPlugin_Tools::convertRefAttrToPointOrTangentCurve(
+      aRotRef, aRotateAtr, aTangentCurve, aRotPoit);
+
+    myRotPoint = theCircle->project(aRotPoit);
+
+    std::shared_ptr<GeomAPI_Pnt2d> 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<GeomAPI_Pnt2d> aRotPoit =
+      std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(myCenter->x() + myRadius, myCenter->y()));
+    myRotPoint = theCircle->project(aRotPoit);
+    std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(ROTATE_POINT_ID()))->setValue(myRotPoint);
+    myAngle = 0;
+  }
+}
+
+static FeaturePtr CreatePoint(FeaturePtr theCircleFeature,
+                              GeomPnt2dPtr thePoint)
+{
+  SketchPlugin_Sketch* aSketch =
+    std::dynamic_pointer_cast<SketchPlugin_Feature>(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<GeomDataAPI_Point2D>(
+    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<GeomDataAPI_Point2D>(
       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<GeomAPI_Pnt> aCenter(aSketch->to3D(myCenter->x(), myCenter->y()));
   std::shared_ptr<GeomDataAPI_Dir> aNDir =
-      std::dynamic_pointer_cast<GeomDataAPI_Dir>(
-          aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
+    std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+      aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
   std::shared_ptr<GeomAPI_Dir> 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<GeomAPI_Pnt> aRotPoint;
+    if (myRotPoint.get())
+      aRotPoint = std::shared_ptr<GeomAPI_Pnt>(aSketch->to3D(myRotPoint->x(), myRotPoint->y()));
+    else
+      aRotPoint = std::shared_ptr<GeomAPI_Pnt>(aSketch->to3D(myCenter->x() + myRadius, myCenter->y()));
+    GeomShapePtr aNewPnt = GeomAlgoAPI_PointBuilder::vertex(aRotPoint);
+    aShapes.push_back(aNewPnt);
+  }
+
   std::shared_ptr<GeomAPI_Shape> 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 <GeomAPI_Circ2d> 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<GeomAPI_Pnt2d> 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<GeomDataAPI_Point2D>(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<GeomDataAPI_Point2D>(attribute(ROTATE_POINT_ID()));
+      aPointAttr->setValue(myRotPoint);
+    }
+
+    if (anAngleAttr->isInitialized())
+      anAngleAttr->setValue(myAngle);
+  }
+
   aRadiusAttr->setValue(myRadius);
+
   data()->blockSendAttributeUpdated(aWasBlocked, false);
 }
index c810eb06191d1a56c5313777c9af01e086e2f2ff..d5b45c59f738152d187c5f5234b76360f65c010d 100644 (file)
@@ -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<GeomAPI_Circ2d>& theCircle);
+
   FeaturePtr createCircleFeature();
 
 private:
   std::shared_ptr<GeomAPI_Pnt2d> myCenter;
+  std::shared_ptr<GeomAPI_Pnt2d> myRotPoint;
   double                         myRadius;
+  double                         myAngle;
 };
 
 #endif
index 14c3c554ecad26e6e733d541f8e12fa23a989d59..7e5ba93c0f82b6b63f2d4fc5a82be2743dbe8992 100644 (file)
@@ -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
 #=========================================================================
index 29c2f1988426006c3ea8178946ab12c25e8f2467..4c8a5cdfd564357807709e15ca19aa4d04c9ca04 100644 (file)
@@ -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
 #=========================================================================
index 803561bfc96db13ddb5b8370f7261d8efd164206..c3bfdf523fdc45fe11bfce95eb8b50a506de28cd 100644 (file)
@@ -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)
 
index b48900e2b89f651f10f4d88382aca6320ee5cb69..0bdcdbf10322933be3e80fde6f3de5d967e0cd66 100644 (file)
@@ -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()
 
index b729a6d4d9cc46ef4e537c8f46b16ac59c4a0c14..fa24e9e29f0d68ad2f963454652f78afd8270c82 100644 (file)
@@ -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.
index c837accbf164d852ace07cf9f9ddec1359b363b0..88b1cfbc7d42fae8719ef7ed3a6b016426dfc124 100644 (file)
Binary files a/src/SketchPlugin/doc/images/Circle_panel_3pt.png and b/src/SketchPlugin/doc/images/Circle_panel_3pt.png differ
index c9983f2ecb3e68333c9a119c0726fcd7781dca1c..ed2d315f6d25173da2e572998a20cea7d81de514 100644 (file)
Binary files a/src/SketchPlugin/doc/images/Circle_panel_edit.png and b/src/SketchPlugin/doc/images/Circle_panel_edit.png differ
index e171e58fe265334a7917eda6885efdf9b97acc58..f8067213cbd25c2de2bfbab1c0ecb671daea294f 100644 (file)
Binary files a/src/SketchPlugin/doc/images/Circle_panel_pt_rad.png and b/src/SketchPlugin/doc/images/Circle_panel_pt_rad.png differ
index f69c000407226b8282d0d5d588caeadb0b69c460..ab5488d0a4b0dabfe2a6023674fb4b915453da26 100644 (file)
                                  tooltip="Center coordinates"
                                  accept_expressions="0"
                                  enable_value="enable_by_preferences"/>
+        <sketch-2dpoint_selector id="circle_rotate"
+                                 title="Rotate"
+                                 tooltip="Rotate coordinates"
+                                 accept_expressions="0"
+                                 enable_value="enable_by_preferences"/>
         <labelvalue id="circle_radius"
                     icon="icons/Sketch/radius.png"
                     label="Radius"
                                      enable_value="enable_by_preferences">
               <validator id="SketchPlugin_CirclePassedPointValidator"/>
             </sketch-2dpoint_selector>
+            <sketch-2dpoint_selector id="rotate_point"
+                                      reference_attribute="rotate_point_ref"
+                                      title="Rotate point"
+                                      tooltip="Rotate point coordinates"
+                                      accept_expressions="0"
+                                      enable_value="enable_by_preferences"/>
             <validator id="GeomValidators_Different" parameters="center_point_ref,passed_point_ref"/>
+            <validator id="GeomValidators_Different" parameters="center_point_ref,rotate_point_ref"/>
           </box>
           <box id="circle_type_by_three_points"
                icon="icons/Sketch/circle_3pt_32x32.png"
               <validator id="SketchPlugin_DifferentReference" parameters="first_point_ref,second_point_ref,third_point_ref"/>
               <validator id="SketchPlugin_ThirdPointValidator" parameters="third_point_ref"/>
             </sketch-2dpoint_selector>
+            <sketch-2dpoint_selector id="rotate_point"
+                                      reference_attribute="rotate_point_ref"
+                                      title="Rotate point"
+                                      tooltip="Rotate point coordinates"
+                                      accept_expressions="0"
+                                      enable_value="enable_by_preferences"/>
             <validator id="GeomValidators_Different" parameters="first_point_ref,second_point_ref,third_point_ref"/>
           </box>
         </toolbox>
index 1f0fd0e7c6d34ec09bc6f7b6bbe845a17d878cd1..8f6ff982d5051425ec8d0ec75d51db6de6c65f06 100644 (file)
@@ -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() ||