]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Creating a circle by 3 points
authorazv <azv@opencascade.com>
Mon, 1 Feb 2016 13:25:36 +0000 (16:25 +0300)
committerazv <azv@opencascade.com>
Mon, 1 Feb 2016 13:25:36 +0000 (16:25 +0300)
src/PartSet/PartSet_icons.qrc
src/PartSet/icons/circle_3pt_32x32.png [new file with mode: 0644]
src/PartSet/icons/circle_pt_rad_32x32.png [new file with mode: 0644]
src/SketchPlugin/SketchPlugin_Circle.cpp
src/SketchPlugin/SketchPlugin_Circle.h
src/SketchPlugin/plugin-Sketch.xml

index 826d7fd117098817440528f42363ea8dc7bfd29e..c6e6324206d7289e84130740c7041a905fa33c8f 100644 (file)
@@ -6,6 +6,8 @@
      <file>icons/angle_down.png</file>
      <file>icons/arc.png</file>
      <file>icons/circle.png</file>
+     <file>icons/circle_pt_rad_32x32.png</file>
+     <file>icons/circle_3pt_32x32.png</file>
      <file>icons/color.png</file>
      <file>icons/point.png</file>
      <file>icons/plane.png</file>
diff --git a/src/PartSet/icons/circle_3pt_32x32.png b/src/PartSet/icons/circle_3pt_32x32.png
new file mode 100644 (file)
index 0000000..7c1fc49
Binary files /dev/null and b/src/PartSet/icons/circle_3pt_32x32.png differ
diff --git a/src/PartSet/icons/circle_pt_rad_32x32.png b/src/PartSet/icons/circle_pt_rad_32x32.png
new file mode 100644 (file)
index 0000000..d7621a9
Binary files /dev/null and b/src/PartSet/icons/circle_pt_rad_32x32.png differ
index 5dd78c10c01638afcd6f38ac2fe859a804c5ee8c..858c2e7efaf1fd77540610d742acb797bece4351 100644 (file)
 #include <ModelAPI_AttributeSelection.h>
 #include <ModelAPI_Validator.h>
 #include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeString.h>
 #include <ModelAPI_Session.h>
 
 #include <GeomAPI_Pnt2d.h>
 #include <GeomAPI_Circ.h>
+#include <GeomAPI_XY.h>
 #include <GeomDataAPI_Point2D.h>
 #include <GeomDataAPI_Dir.h>
 #include <GeomAlgoAPI_PointBuilder.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;
+  }
+
+  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;
+  }
+  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();
+    }
+
+    static const std::string DUMMY;
+    return DUMMY;
+  }
+}
+
+static void calculateCircleOnThreePoints(const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPnt,
+                                         const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPnt,
+                                         const std::shared_ptr<GeomAPI_Pnt2d>& theThirdPnt,
+                                               std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
+                                               double&                         theRadius);
+
+
 SketchPlugin_Circle::SketchPlugin_Circle()
     : SketchPlugin_SketchEntity()
 {
@@ -32,6 +86,13 @@ void SketchPlugin_Circle::initDerivedClassAttributes()
   data()->addAttribute(RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
   data()->addAttribute(EXTERNAL_ID(), ModelAPI_AttributeSelection::typeId());
   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EXTERNAL_ID());
+
+  data()->addAttribute(CIRCLE_TYPE(), ModelAPI_AttributeString::typeId());
+  data()->addAttribute(FIRST_POINT_ID(), GeomDataAPI_Point2D::typeId());
+  data()->addAttribute(SECOND_POINT_ID(), GeomDataAPI_Point2D::typeId());
+  data()->addAttribute(THIRD_POINT_ID(), GeomDataAPI_Point2D::typeId());
+  std::dynamic_pointer_cast<ModelAPI_AttributeString>(
+      data()->attribute(CIRCLE_TYPE()))->setValue(CIRCLE_TYPE_CENTER_AND_RADIUS());
 }
 
 void SketchPlugin_Circle::execute()
@@ -70,6 +131,46 @@ void SketchPlugin_Circle::execute()
   }
 }
 
+AISObjectPtr SketchPlugin_Circle::getAISObject(AISObjectPtr thePrevious)
+{
+  SketchPlugin_Sketch* aSketch = sketch();
+  if (aSketch) {
+    // compute a circle point in 3D view
+    std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr = std::dynamic_pointer_cast<
+        GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
+    AttributeDoublePtr aRadiusAttr = 
+        std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(attribute(RADIUS_ID()));
+    if (aCenterAttr->isInitialized() && aRadiusAttr->isInitialized()) {
+        std::shared_ptr<GeomAPI_Pnt> aCenter(aSketch->to3D(aCenterAttr->x(), aCenterAttr->y()));
+
+        // make a visible circle
+        std::shared_ptr<GeomDataAPI_Dir> aNDir = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+            aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
+        std::shared_ptr<GeomAPI_Dir> aNormal = aNDir->dir();
+
+        double aRadius = aRadiusAttr->value();
+        std::shared_ptr<GeomAPI_Shape> aCircleShape = GeomAlgoAPI_EdgeBuilder::lineCircle(
+            aCenter, aNormal, aRadius);
+        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);
+          aShapes.push_back(aCenterPointShape);
+          aShapes.push_back(aCircleShape);
+
+          std::shared_ptr<GeomAPI_Shape> aCompound = GeomAlgoAPI_CompoundBuilder::compound(aShapes);
+          AISObjectPtr anAIS = thePrevious;
+          if (!anAIS)
+            anAIS = AISObjectPtr(new GeomAPI_AISObject);
+          anAIS->createShape(aCompound);
+          anAIS->setWidth(3);
+          return anAIS;
+        }
+    }
+  }
+  return AISObjectPtr();
+}
+
 void SketchPlugin_Circle::move(double theDeltaX, double theDeltaY)
 {
   std::shared_ptr<ModelAPI_Data> aData = data();
@@ -99,4 +200,108 @@ void SketchPlugin_Circle::attributeChanged(const std::string& theID) {
       real(RADIUS_ID())->setValue(aCirc->radius());
     }
   }
+  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()) {
+    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);
+
+    std::shared_ptr<GeomAPI_Pnt2d> aPoints[3];
+    int aNbInitialized = 0;
+    for (int i = 1; i <= 3; ++i) {
+      std::shared_ptr<GeomDataAPI_Point2D> aCurPnt =
+          std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(POINT_ID(i)));
+      if (aCurPnt->isInitialized())
+        aPoints[aNbInitialized++] = aCurPnt->pnt();
+    }
+
+    std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr = std::dynamic_pointer_cast<
+        GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
+    AttributeDoublePtr aRadiusAttr = 
+      std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(data()->attribute(RADIUS_ID()));
+
+    if (aNbInitialized == 1)
+      aCenterAttr->setValue(aPoints[0]->x(), aPoints[0]->y());
+    else if (aNbInitialized == 2) {
+      std::shared_ptr<GeomAPI_XY> aCoord =
+          aPoints[0]->xy()->added(aPoints[1]->xy())->multiplied(0.5);
+      double aRadius = aPoints[0]->distance(aPoints[1]) * 0.5;
+      aCenterAttr->setValue(aCoord->x(), aCoord->y());
+      aRadiusAttr->setValue(aRadius);
+    } else {
+      std::shared_ptr<GeomAPI_Pnt2d> aCenter;
+      double aRadius;
+      calculateCircleOnThreePoints(aPoints[0], aPoints[1], aPoints[2], aCenter, aRadius);
+      if (aCenter) {
+        aCenterAttr->setValue(aCenter->x(), aCenter->y());
+        aRadiusAttr->setValue(aRadius);
+      }
+    }
+
+    data()->blockSendAttributeUpdated(false);
+  }
+}
+
+
+
+
+// ==========   Auxiliary functions   =========================
+void calculateCircleOnThreePoints(const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPnt,
+                                  const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPnt,
+                                  const std::shared_ptr<GeomAPI_Pnt2d>& theThirdPnt,
+                                        std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
+                                        double&                         theRadius)
+{
+  std::shared_ptr<GeomAPI_XY> aVec12 = theSecondPnt->xy()->decreased(theFirstPnt->xy());
+  std::shared_ptr<GeomAPI_XY> aVec23 = theThirdPnt->xy()->decreased(theSecondPnt->xy());
+  std::shared_ptr<GeomAPI_XY> aVec31 = theFirstPnt->xy()->decreased(theThirdPnt->xy());
+  // square of parallelogram
+  double aSquare2 = aVec12->cross(aVec23);
+  aSquare2 *= aSquare2 * 2.0;
+  if (aSquare2 < 1.e-20)
+    return;
+  // coefficients to calculate center
+  double aCoeff1 = aVec23->dot(aVec23) / aSquare2 * aVec12->dot(aVec31->multiplied(-1.0));
+  double aCoeff2 = aVec31->dot(aVec31) / aSquare2 * aVec23->dot(aVec12->multiplied(-1.0));
+  double aCoeff3 = aVec12->dot(aVec12) / aSquare2 * aVec31->dot(aVec23->multiplied(-1.0));
+  // center
+  std::shared_ptr<GeomAPI_XY> aCenter = theFirstPnt->xy()->multiplied(aCoeff1)->added(
+      theSecondPnt->xy()->multiplied(aCoeff2))->added(theThirdPnt->xy()->multiplied(aCoeff3));
+  theCenter = std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(aCenter));
+  // radius
+  theRadius = theFirstPnt->distance(theCenter);
 }
index 941d90f229b3ccd6faa0b9fb8ad636e30dadb99d..fe0ca3a423963dcb39ca593be5b92b54eb57d0af 100644 (file)
@@ -16,7 +16,7 @@
  * \ingroup Plugins
  * \brief Feature for creation of the new circle in PartSet.
  */
-class SketchPlugin_Circle : public SketchPlugin_SketchEntity 
+class SketchPlugin_Circle : public SketchPlugin_SketchEntity, public GeomAPI_IPresentable
 {
  public:
   /// Circle feature kind
@@ -58,7 +58,6 @@ class SketchPlugin_Circle : public SketchPlugin_SketchEntity
   SKETCHPLUGIN_EXPORT virtual const void addSub(const FeaturePtr& theFeature)
   {
   }
-  ;
 
   /// Moves the feature
   /// \param theDeltaX the delta for X coordinate is moved
@@ -68,6 +67,9 @@ class SketchPlugin_Circle : public SketchPlugin_SketchEntity
   /// Called on change of any argument-attribute of this object
   SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID);
 
+  /// Returns the AIS preview
+  virtual AISObjectPtr getAISObject(AISObjectPtr thePrevious);
+
   /// Use plugin manager for features creation
   SketchPlugin_Circle();
 
index 79de2c5d7002c02a490d7089eed9b1ba8e7b6769..dbe93b228a4ffdef41719a7fbd9d5597a9b0e74a 100644 (file)
         <boolvalue id="Auxiliary" label="Auxiliary" default="false" tooltip="Construction element" obligatory="0"/>
         <validator id="GeomValidators_Different" parameters="StartPoint,EndPoint"/>
       </feature>
-      <feature id="SketchCircle" title="Circle" tooltip="Create circle" icon=":icons/circle.png">
-        <sketch-2dpoint_selector id="CircleCenter" accept_expressions="0" title="Center" tooltip="Center coordinates"/>
-        <point2ddistance id="CircleRadius" accept_expressions="0" first_point="CircleCenter" label="Radius:" min="0" step="1.0" default="0" icon=":icons/radius.png" tooltip="Set radius">
-          <validator id="GeomValidators_Positive"/>
-        </point2ddistance>
+
+      <!-- SketchCircle -->
+      <feature 
+        id="SketchCircle"
+        title="Circle"
+        tooltip="Create circle"
+        icon=":icons/circle.png">
+        <toolbox id="CircleType">
+          <box id="CenterRadius" title="Center and radius" icon=":icons/circle_pt_rad_32x32.png">
+            <sketch-2dpoint_selector id="CircleCenter" accept_expressions="0" title="Center" tooltip="Center coordinates"/>
+            <point2ddistance id="CircleRadius" accept_expressions="0" first_point="CircleCenter" label="Radius:" min="0" step="1.0" default="0" icon=":icons/radius.png" tooltip="Set radius">
+              <validator id="GeomValidators_Positive"/>
+            </point2ddistance>
+          </box>
+          <box id="ThreePoints" title="Tree points" icon=":icons/circle_3pt_32x32.png">
+            <sketch-2dpoint_selector id="FirstPoint" accept_expressions="0" title="First point" tooltip="First point"/>
+            <sketch-2dpoint_selector id="SecondPoint" accept_expressions="0" title="Second point" tooltip="Second point"/>
+            <sketch-2dpoint_selector id="ThirdPoint" accept_expressions="0" title="Third point" tooltip="Third point"/>
+          </box>
+        </toolbox>
         <boolvalue id="Auxiliary" label="Auxiliary" default="false" tooltip="Construction element" obligatory="0"/>
       </feature>
+
       <feature id="SketchArc" title="Arc" tooltip="Create arc" icon=":icons/arc.png">
         <sketch-2dpoint_selector id="ArcCenter" accept_expressions="0" title="Center" tooltip="Center of a circle"/>
         <sketch-2dpoint_selector id="ArcStartPoint" accept_expressions="0" title="Start point" tooltip="Start point"/>