Salome HOME
Merge remote-tracking branch 'remotes/origin/HighLevelDump'
[modules/shaper.git] / src / SketchPlugin / SketchPlugin_Circle.cpp
index f252df658aec33b08ba84de96b6d1de0512e733f..babdd6f14e01dcff3da73c1b76c1f4f01ac1a09f 100644 (file)
@@ -17,6 +17,7 @@
 #include <GeomAPI_Pnt2d.h>
 #include <GeomAPI_Circ.h>
 #include <GeomAPI_Circ2d.h>
+#include <GeomAPI_Vertex.h>
 #include <GeomAPI_XY.h>
 #include <GeomDataAPI_Point2D.h>
 #include <GeomDataAPI_Dir.h>
 #include <GeomAlgoAPI_EdgeBuilder.h>
 #include <GeomAlgoAPI_CompoundBuilder.h>
 
-namespace {
-  static const std::string& CIRCLE_TYPE()
-  {
-    static const std::string TYPE("CircleType");
-    return TYPE;
-  }
-  static const std::string& CIRCLE_TYPE_CENTER_AND_RADIUS()
-  {
-    static const std::string TYPE("CenterRadius");
-    return TYPE;
-  }
-  static const std::string& CIRCLE_TYPE_THREE_POINTS()
-  {
-    static const std::string TYPE("ThreePoints");
-    return TYPE;
-  }
+#include <cmath>
 
-  static const std::string& FIRST_POINT_ID()
-  {
-    static const std::string FIRST_PNT("FirstPoint");
-    return FIRST_PNT;
-  }
-  static const std::string& SECOND_POINT_ID()
-  {
-    static const std::string SECOND_PNT("SecondPoint");
-    return SECOND_PNT;
-  }
-  static const std::string& THIRD_POINT_ID()
-  {
-    static const std::string THIRD_PNT("ThirdPoint");
-    return THIRD_PNT;
-  }
+const double tolerance = 1e-7;
+
+namespace {
   static const std::string& POINT_ID(int theIndex)
   {
     switch (theIndex) {
-    case 1: return FIRST_POINT_ID();
-    case 2: return SECOND_POINT_ID();
-    case 3: return THIRD_POINT_ID();
+    case 1: return SketchPlugin_Circle::FIRST_POINT_ID();
+    case 2: return SketchPlugin_Circle::SECOND_POINT_ID();
+    case 3: return SketchPlugin_Circle::THIRD_POINT_ID();
     }
 
     static const std::string DUMMY;
@@ -149,7 +123,7 @@ AISObjectPtr SketchPlugin_Circle::getAISObject(AISObjectPtr thePrevious)
         if (aCircleShape && aRadius != 0) {
           std::list<std::shared_ptr<GeomAPI_Shape> > aShapes;
           // make a visible point
-          std::shared_ptr<GeomAPI_Shape> aCenterPointShape = GeomAlgoAPI_PointBuilder::point(aCenter);
+          std::shared_ptr<GeomAPI_Shape> aCenterPointShape = GeomAlgoAPI_PointBuilder::vertex(aCenter);
           aShapes.push_back(aCenterPointShape);
           aShapes.push_back(aCircleShape);
 
@@ -170,15 +144,23 @@ bool SketchPlugin_Circle::isFeatureValid()
 {
   std::shared_ptr<GeomDataAPI_Point2D> aCenter = 
       std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(CENTER_ID()));
-  std::shared_ptr<GeomDataAPI_Point2D> aFirstPnt =
-      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(FIRST_POINT_ID()));
-  std::shared_ptr<GeomDataAPI_Point2D> aSecondPnt =
-      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(SECOND_POINT_ID()));
-  std::shared_ptr<GeomDataAPI_Point2D> aThirdPnt =
-      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(THIRD_POINT_ID()));
+  bool aValid = aCenter->isInitialized();
 
-  return aCenter->isInitialized() && aFirstPnt->isInitialized() &&
-         aSecondPnt->isInitialized() && aThirdPnt->isInitialized();
+  std::string aType = std::dynamic_pointer_cast<ModelAPI_AttributeString>(
+                                         data()->attribute(CIRCLE_TYPE()))->value();
+  if (aType == CIRCLE_TYPE_THREE_POINTS()) {
+    std::shared_ptr<GeomDataAPI_Point2D> aFirstPnt =
+        std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(FIRST_POINT_ID()));
+    std::shared_ptr<GeomDataAPI_Point2D> aSecondPnt =
+        std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(SECOND_POINT_ID()));
+    std::shared_ptr<GeomDataAPI_Point2D> aThirdPnt =
+        std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(THIRD_POINT_ID()));
+    aValid = aValid &&
+             aFirstPnt->isInitialized() &&
+             aSecondPnt->isInitialized() &&
+             aThirdPnt->isInitialized();
+  }
+  return aValid;
 }
 
 void SketchPlugin_Circle::move(double theDeltaX, double theDeltaY)
@@ -207,6 +189,12 @@ void SketchPlugin_Circle::attributeChanged(const std::string& theID) {
   // the second condition for unability to move external segments anywhere
   if (theID == EXTERNAL_ID() || isFixed()) {
     std::shared_ptr<GeomAPI_Shape> aSelection = data()->selection(EXTERNAL_ID())->value();
+    if (!aSelection) {
+      // empty shape in selection shows that the shape is equal to context
+      ResultPtr anExtRes = selection(EXTERNAL_ID())->context();
+      if (anExtRes)
+        aSelection = anExtRes->shape();
+    }
     // update arguments due to the selection value
     if (aSelection && !aSelection->isNull() && aSelection->isEdge()) {
       std::shared_ptr<GeomAPI_Edge> anEdge( new GeomAPI_Edge(aSelection));
@@ -220,43 +208,15 @@ void SketchPlugin_Circle::attributeChanged(const std::string& theID) {
   else if (theID == CENTER_ID() || theID == RADIUS_ID()) {
     std::string aType = std::dynamic_pointer_cast<ModelAPI_AttributeString>(
       data()->attribute(CIRCLE_TYPE()))->value();
-    if (aType == CIRCLE_TYPE_THREE_POINTS())
-      return;
-
-    std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr =
-        std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(CENTER_ID()));
-    if (!aCenterAttr->isInitialized())
-      return;
-    AttributeDoublePtr aRadiusAttr = 
-      std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(attribute(RADIUS_ID()));
-    if (!aRadiusAttr->isInitialized())
-      return;
-
-    // check the execute() was called and the shape was built
-    if (!lastResult())
-      return;
-
-    data()->blockSendAttributeUpdated(true);
-    std::shared_ptr<GeomDataAPI_Point2D> aFirstPnt =
-        std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(FIRST_POINT_ID()));
-    std::shared_ptr<GeomDataAPI_Point2D> aSecondPnt =
-        std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(SECOND_POINT_ID()));
-    std::shared_ptr<GeomDataAPI_Point2D> aThirdPnt =
-        std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(THIRD_POINT_ID()));
-    double aRadius = aRadiusAttr->value();
-    aFirstPnt->setValue(aCenterAttr->x() + aRadius, aCenterAttr->y());
-    aSecondPnt->setValue(aCenterAttr->x(), aCenterAttr->y() + aRadius);
-    aThirdPnt->setValue(aCenterAttr->x() - aRadius, aCenterAttr->y());
-    data()->blockSendAttributeUpdated(false);
-  }
-  else if (theID == FIRST_POINT_ID() || theID == SECOND_POINT_ID() || theID == THIRD_POINT_ID()) {
+    if (aType == CIRCLE_TYPE_THREE_POINTS() && lastResult())  // adjust data from the solver
+      adjustThreePoints();
+  } else if (theID == FIRST_POINT_ID() || theID == SECOND_POINT_ID() || theID == THIRD_POINT_ID()) {
+    // support the center and radius attributes enev in other mode: solver uses them
     std::string aType = std::dynamic_pointer_cast<ModelAPI_AttributeString>(
       data()->attribute(CIRCLE_TYPE()))->value();
     if (aType == CIRCLE_TYPE_CENTER_AND_RADIUS())
       return;
-
-    data()->blockSendAttributeUpdated(true);
-
+    data()->blockSendAttributeUpdated(true); // to modify two attributes at once
     std::shared_ptr<GeomAPI_Pnt2d> aPoints[3];
     int aNbInitialized = 0;
     for (int i = 1; i <= 3; ++i) {
@@ -290,7 +250,43 @@ void SketchPlugin_Circle::attributeChanged(const std::string& theID) {
         aRadiusAttr->setValue(aRadius);
       }
     }
+    data()->blockSendAttributeUpdated(false, false);
 
-    data()->blockSendAttributeUpdated(false);
+  } else if (theID == CIRCLE_TYPE()) { // if switched to 3 points mode, adjust the needed attributes
+    std::string aType = std::dynamic_pointer_cast<ModelAPI_AttributeString>(
+      data()->attribute(CIRCLE_TYPE()))->value();
+    if (aType == CIRCLE_TYPE_THREE_POINTS()) {
+      adjustThreePoints();
+    }
+  }
+}
+
+void SketchPlugin_Circle::adjustThreePoints()
+{
+  std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr =
+      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(CENTER_ID()));
+  if (!aCenterAttr->isInitialized())
+    return;
+  AttributeDoublePtr aRadiusAttr = 
+    std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(attribute(RADIUS_ID()));
+  if (!aRadiusAttr->isInitialized())
+    return;
+
+  data()->blockSendAttributeUpdated(true);
+  std::shared_ptr<GeomDataAPI_Point2D> aFirstPnt =
+      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(FIRST_POINT_ID()));
+  std::shared_ptr<GeomDataAPI_Point2D> aSecondPnt =
+      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(SECOND_POINT_ID()));
+  std::shared_ptr<GeomDataAPI_Point2D> aThirdPnt =
+      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(THIRD_POINT_ID()));
+  double aRadius = aRadiusAttr->value();
+
+  if (fabs(aFirstPnt->pnt()->distance(aCenterAttr->pnt()) - aRadius) > tolerance ||
+      fabs(aSecondPnt->pnt()->distance(aCenterAttr->pnt()) - aRadius) > tolerance ||
+      fabs(aThirdPnt->pnt()->distance(aCenterAttr->pnt()) - aRadius) > tolerance) {
+    aFirstPnt->setValue(aCenterAttr->x() + aRadius, aCenterAttr->y());
+    aSecondPnt->setValue(aCenterAttr->x(), aCenterAttr->y() + aRadius);
+    aThirdPnt->setValue(aCenterAttr->x() - aRadius, aCenterAttr->y());
   }
+  data()->blockSendAttributeUpdated(false, false);
 }