Salome HOME
Task 2.12. New entities: ellipses and arcs of ellipses (issue #3003)
authorazv <azv@opencascade.com>
Fri, 6 Sep 2019 05:36:27 +0000 (08:36 +0300)
committerazv <azv@opencascade.com>
Fri, 6 Sep 2019 13:43:42 +0000 (16:43 +0300)
* Introduce ellipse in SketchPlugin.
* Make ellipse processable by the solver.

28 files changed:
lcov_reports.sh
src/SketchPlugin/SketchPlugin_Ellipse.cpp
src/SketchPlugin/SketchPlugin_Ellipse.h
src/SketchPlugin/SketchPlugin_Line.cpp
src/SketchPlugin/SketchPlugin_MacroEllipse.cpp
src/SketchPlugin/SketchPlugin_MacroEllipse.h
src/SketchPlugin/SketchPlugin_Plugin.cpp
src/SketchPlugin/SketchPlugin_Sketch.cpp
src/SketchPlugin/SketchPlugin_Sketch.h
src/SketchPlugin/SketchPlugin_SketchEntity.h
src/SketchPlugin/icons/ellipse.png
src/SketchPlugin/icons/ellipse_axes_32x32.png [new file with mode: 0644]
src/SketchPlugin/icons/ellipse_cent_rad_32x32.png [new file with mode: 0644]
src/SketchPlugin/icons/elliptic_arc.png [new file with mode: 0644]
src/SketchPlugin/icons/radius_major.png [new file with mode: 0644]
src/SketchPlugin/icons/radius_minor.png [new file with mode: 0644]
src/SketchPlugin/plugin-Sketch.xml
src/SketchSolver/PlaneGCSSolver/CMakeLists.txt
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Defs.h
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_EdgeWrapper.cpp
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_EntityWrapper.h
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_FeatureBuilder.cpp
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.h
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp
src/SketchSolver/SketchSolver_ConstraintFixed.cpp
src/SketchSolver/SketchSolver_ConstraintMovement.cpp
src/SketchSolver/SketchSolver_ConstraintMovement.h

index ebd0c76a13e29732ac949a37e7704c597cd92cd7..cd094cf1528fb31670e24af8f0b45dfd6e2d4ce3 100755 (executable)
@@ -65,9 +65,6 @@ for MASK in $ALL; do
     mv -f covElse_res covElse
   fi
 done
-# remove SketchPlugin's Ellipse feature (unsupported yet)
-lcov -r covElse SketchPlugin*Ellipse* --output-file covElse_res -q
-mv -f covElse_res covElse
 rm -rf lcov_htmlElse
 genhtml covElse --output-directory lcov_htmlElse -q
 
index df323b1674c425972a5fd4967c57130812f71fd3..1c5f5fadd7aaf154197793d4987b4a48210264da 100644 (file)
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 
-// File:        SketchPlugin_Ellipse.cpp
-// Created:     26 April 2017
-// Author:      Artem ZHIDKOV
-
 #include <SketchPlugin_Ellipse.h>
 #include <SketchPlugin_Sketch.h>
 
 #include <GeomAlgoAPI_EdgeBuilder.h>
+
+#include <GeomAPI_Dir2d.h>
 #include <GeomAPI_Edge.h>
 #include <GeomAPI_Ellipse.h>
+#include <GeomAPI_Pnt2d.h>
+
 #include <GeomDataAPI_Point2D.h>
+
 #include <ModelAPI_AttributeDouble.h>
 #include <ModelAPI_ResultConstruction.h>
 #include <ModelAPI_Session.h>
@@ -44,7 +45,12 @@ SketchPlugin_Ellipse::SketchPlugin_Ellipse()
 void SketchPlugin_Ellipse::initDerivedClassAttributes()
 {
   data()->addAttribute(CENTER_ID(), GeomDataAPI_Point2D::typeId());
-  data()->addAttribute(FOCUS_ID(), GeomDataAPI_Point2D::typeId());
+  data()->addAttribute(FIRST_FOCUS_ID(), GeomDataAPI_Point2D::typeId());
+  data()->addAttribute(SECOND_FOCUS_ID(), GeomDataAPI_Point2D::typeId());
+  data()->addAttribute(MAJOR_AXIS_START_ID(), GeomDataAPI_Point2D::typeId());
+  data()->addAttribute(MAJOR_AXIS_END_ID(), GeomDataAPI_Point2D::typeId());
+  data()->addAttribute(MINOR_AXIS_START_ID(), GeomDataAPI_Point2D::typeId());
+  data()->addAttribute(MINOR_AXIS_END_ID(), GeomDataAPI_Point2D::typeId());
   data()->addAttribute(MAJOR_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
   data()->addAttribute(MINOR_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
 
@@ -59,52 +65,45 @@ void SketchPlugin_Ellipse::execute()
     return;
   }
 
-  // Compute a ellipse in 3D view.
-  std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr =
-      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
-  std::shared_ptr<GeomDataAPI_Point2D> aFocusAttr =
-      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(FOCUS_ID()));
-  AttributeDoublePtr aMajorRadiusAttr = real(MAJOR_RADIUS_ID());
-  AttributeDoublePtr aMinorRadiusAttr = real(MINOR_RADIUS_ID());
-  if (!aCenterAttr->isInitialized() ||
-      !aFocusAttr->isInitialized() ||
-      !aMajorRadiusAttr->isInitialized() ||
-      !aMinorRadiusAttr->isInitialized()) {
-    return;
-  }
-
-  double aMajorRadius = aMajorRadiusAttr->value();
-  double aMinorRadius = aMinorRadiusAttr->value();
-  if(aMajorRadius < tolerance || aMinorRadius < tolerance) {
-    return;
-  }
-
-  // Make a visible point.
-  SketchPlugin_Sketch::createPoint2DResult(this, aSketch, CENTER_ID(), 0);
-
-  std::shared_ptr<GeomDataAPI_Dir> aNDir = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
-      aSketch->attribute(SketchPlugin_Sketch::NORM_ID()));
+  // Calculate all characteristics of the ellipse.
+  fillCharacteristicPoints();
+
+  // Make visible points related to ellipse characteristics.
+  int aResultIndex = 0;
+  SketchPlugin_Sketch::createPoint2DResult(this, aSketch, CENTER_ID(), aResultIndex++);
+  SketchPlugin_Sketch::createPoint2DResult(this, aSketch, FIRST_FOCUS_ID(), aResultIndex++);
+  SketchPlugin_Sketch::createPoint2DResult(this, aSketch, SECOND_FOCUS_ID(), aResultIndex++);
+  SketchPlugin_Sketch::createPoint2DResult(this, aSketch, MAJOR_AXIS_START_ID(), aResultIndex++);
+  SketchPlugin_Sketch::createPoint2DResult(this, aSketch, MAJOR_AXIS_END_ID(), aResultIndex++);
+  SketchPlugin_Sketch::createPoint2DResult(this, aSketch, MINOR_AXIS_START_ID(), aResultIndex++);
+  SketchPlugin_Sketch::createPoint2DResult(this, aSketch, MINOR_AXIS_END_ID(), aResultIndex++);
+
+  // Make auxiliary axes
+  SketchPlugin_Sketch::createLine2DResult(this, aSketch,
+      MAJOR_AXIS_START_ID(), MAJOR_AXIS_END_ID(), aResultIndex++);
+  SketchPlugin_Sketch::createLine2DResult(this, aSketch,
+      MINOR_AXIS_START_ID(), MINOR_AXIS_END_ID(), aResultIndex++);
+
+  // Mark already created results auxiliary
+  myAuxiliaryResults.clear();
+  const std::list<ResultPtr>& aResults = results();
+  std::list<ResultPtr>::const_iterator anIt = aResults.begin();
+  for (int anIndex = 0; anIt != aResults.end() && anIndex < aResultIndex; ++anIt, ++anIndex)
+    myAuxiliaryResults.insert(*anIt);
 
   // Make a visible ellipse.
-  std::shared_ptr<GeomAPI_Pnt> aCenter(aSketch->to3D(aCenterAttr->x(), aCenterAttr->y()));
-  std::shared_ptr<GeomAPI_Pnt> aFocus(aSketch->to3D(aFocusAttr->x(), aFocusAttr->y()));
-  std::shared_ptr<GeomAPI_Dir> aNormal = aNDir->dir();
-  std::shared_ptr<GeomAPI_Dir> aMajorAxis(new GeomAPI_Dir(aFocus->x() - aCenter->x(),
-      aFocus->y() - aCenter->y(), aFocus->z() - aCenter->z()));
-
-  std::shared_ptr<GeomAPI_Shape> anEllipseShape =
-      GeomAlgoAPI_EdgeBuilder::ellipse(aCenter, aNormal, aMajorAxis, aMajorRadius, aMinorRadius);
-
-  std::shared_ptr<ModelAPI_ResultConstruction> aResult = document()->createConstruction(data(), 1);
-  aResult->setShape(anEllipseShape);
-  aResult->setIsInHistory(false);
-  setResult(aResult, 1);
+  createEllipse(aSketch, aResultIndex);
 }
 
 bool SketchPlugin_Ellipse::isFixed() {
   return data()->selection(EXTERNAL_ID())->context().get() != NULL;
 }
 
+bool SketchPlugin_Ellipse::isAuxiliary(ResultPtr theResult)
+{
+  return myAuxiliaryResults.find(theResult) != myAuxiliaryResults.end();
+}
+
 void SketchPlugin_Ellipse::attributeChanged(const std::string& theID) {
   // the second condition for unability to move external segments anywhere
   if (theID == EXTERNAL_ID() || isFixed()) {
@@ -125,7 +124,7 @@ void SketchPlugin_Ellipse::attributeChanged(const std::string& theID) {
       aCenterAttr->setValue(sketch()->to2D(anEllipse->center()));
 
       std::shared_ptr<GeomDataAPI_Point2D> aFocusAttr =
-          std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(FOCUS_ID()));
+          std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(FIRST_FOCUS_ID()));
       aFocusAttr->setValue(sketch()->to2D(anEllipse->firstFocus()));
 
       real(MAJOR_RADIUS_ID())->setValue(anEllipse->majorRadius());
@@ -133,3 +132,87 @@ void SketchPlugin_Ellipse::attributeChanged(const std::string& theID) {
     }
   }
 }
+
+bool SketchPlugin_Ellipse::fillCharacteristicPoints()
+{
+  std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr =
+      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
+  std::shared_ptr<GeomDataAPI_Point2D> aFocusAttr =
+      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(FIRST_FOCUS_ID()));
+
+  AttributeDoublePtr aMajorRadiusAttr = real(MAJOR_RADIUS_ID());
+  AttributeDoublePtr aMinorRadiusAttr = real(MINOR_RADIUS_ID());
+
+  if (!aCenterAttr->isInitialized() ||
+      !aFocusAttr->isInitialized() ||
+      !aMajorRadiusAttr->isInitialized() ||
+      !aMinorRadiusAttr->isInitialized()) {
+    return false;
+  }
+
+  double aMajorRadius = aMajorRadiusAttr->value();
+  double aMinorRadius = aMinorRadiusAttr->value();
+  if (aMajorRadius < tolerance || aMinorRadius < tolerance) {
+    return false;
+  }
+
+  data()->blockSendAttributeUpdated(true);
+  GeomPnt2dPtr aCenter2d = aCenterAttr->pnt();
+  GeomPnt2dPtr aFocus2d = aFocusAttr->pnt();
+  GeomDir2dPtr aMajorDir2d(new GeomAPI_Dir2d(aFocus2d->x() - aCenter2d->x(),
+    aFocus2d->y() - aCenter2d->y()));
+  GeomDir2dPtr aMinorDir2d(new GeomAPI_Dir2d(-aMajorDir2d->y(), aMajorDir2d->x()));
+  std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(SECOND_FOCUS_ID()))
+    ->setValue(2.0 * aCenter2d->x() - aFocus2d->x(), 2.0 * aCenter2d->y() - aFocus2d->y());
+  std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(MAJOR_AXIS_START_ID()))
+      ->setValue(aCenter2d->x() - aMajorDir2d->x() * aMajorRadius,
+                 aCenter2d->y() - aMajorDir2d->y() * aMajorRadius);
+  std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(MAJOR_AXIS_END_ID()))
+      ->setValue(aCenter2d->x() + aMajorDir2d->x() * aMajorRadius,
+                 aCenter2d->y() + aMajorDir2d->y() * aMajorRadius);
+  std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(MINOR_AXIS_START_ID()))
+      ->setValue(aCenter2d->x() - aMinorDir2d->x() * aMinorRadius,
+                 aCenter2d->y() - aMinorDir2d->y() * aMinorRadius);
+  std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(MINOR_AXIS_END_ID()))
+      ->setValue(aCenter2d->x() + aMinorDir2d->x() * aMinorRadius,
+                 aCenter2d->y() + aMinorDir2d->y() * aMinorRadius);
+  data()->blockSendAttributeUpdated(false);
+
+  return true;
+}
+
+void SketchPlugin_Ellipse::createEllipse(SketchPlugin_Sketch* theSketch, const int theResultIndex)
+{
+  // Compute a ellipse in 3D view.
+  std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr =
+    std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
+  std::shared_ptr<GeomDataAPI_Point2D> aFocusAttr =
+    std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(FIRST_FOCUS_ID()));
+
+  double aMajorRadius = real(MAJOR_RADIUS_ID())->value();
+  double aMinorRadius = real(MINOR_RADIUS_ID())->value();
+
+  std::shared_ptr<GeomDataAPI_Dir> aNDir = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+    theSketch->attribute(SketchPlugin_Sketch::NORM_ID()));
+
+  GeomPointPtr aCenter(theSketch->to3D(aCenterAttr->x(), aCenterAttr->y()));
+  GeomPointPtr aFocus(theSketch->to3D(aFocusAttr->x(), aFocusAttr->y()));
+  GeomDirPtr aNormal = aNDir->dir();
+  std::shared_ptr<GeomAPI_Shape> anEllipseShape;
+  if (aFocus->distance(aCenter) > tolerance) {
+    GeomDirPtr aMajorAxis(new GeomAPI_Dir(aFocus->x() - aCenter->x(),
+        aFocus->y() - aCenter->y(), aFocus->z() - aCenter->z()));
+
+    anEllipseShape =
+        GeomAlgoAPI_EdgeBuilder::ellipse(aCenter, aNormal, aMajorAxis, aMajorRadius, aMinorRadius);
+  }
+  else {
+    // build circle instead of ellipse
+    anEllipseShape = GeomAlgoAPI_EdgeBuilder::lineCircle(aCenter, aNormal, aMajorRadius);
+  }
+
+  ResultConstructionPtr aResult = document()->createConstruction(data(), theResultIndex);
+  aResult->setShape(anEllipseShape);
+  aResult->setIsInHistory(false);
+  setResult(aResult, theResultIndex);
+}
index e8c0252bdc623132a9a77246e12431636b670a7f..bfa0478a7e4f6bdae0148fb288d9439c968bd2f0 100644 (file)
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 
-// File:        SketchPlugin_Ellipse.h
-// Created:     26 April 2017
-// Author:      Artem ZHIDKOV
-
 #ifndef SketchPlugin_Ellipse_H_
 #define SketchPlugin_Ellipse_H_
 
@@ -49,9 +45,41 @@ class SketchPlugin_Ellipse: public SketchPlugin_SketchEntity
   }
 
   /// 2D point - focus of the ellipse
-  inline static const std::string& FOCUS_ID()
+  inline static const std::string& FIRST_FOCUS_ID()
+  {
+    static const std::string ID("ellipse_first_focus");
+    return ID;
+  }
+  /// 2D point - second focus of the ellipse
+  inline static const std::string& SECOND_FOCUS_ID()
+  {
+    static const std::string ID("ellipse_second_focus");
+    return ID;
+  }
+
+  /// 2D point - start point of major axis
+  inline static const std::string& MAJOR_AXIS_START_ID()
+  {
+    static const std::string ID("ellipse_major_axis_start_point");
+    return ID;
+  }
+  /// 2D point - end point of major axis
+  inline static const std::string& MAJOR_AXIS_END_ID()
   {
-    static const std::string ID("ellipse_focus");
+    static const std::string ID("ellipse_major_axis_end_point");
+    return ID;
+  }
+
+  /// 2D point - start point of minor axis
+  inline static const std::string& MINOR_AXIS_START_ID()
+  {
+    static const std::string ID("ellipse_minor_axis_start_point");
+    return ID;
+  }
+  /// 2D point - end point of minor axis
+  inline static const std::string& MINOR_AXIS_END_ID()
+  {
+    static const std::string ID("ellipse_minor_axis_end_point");
     return ID;
   }
 
@@ -88,9 +116,20 @@ class SketchPlugin_Ellipse: public SketchPlugin_SketchEntity
   /// Use plugin manager for features creation
   SketchPlugin_Ellipse();
 
+  /// Returns \c true if the result is marked as auxiliary
+  virtual bool isAuxiliary(ResultPtr theResult);
+
 protected:
   /// \brief Initializes attributes of derived class.
   virtual void initDerivedClassAttributes();
+
+private:
+  bool fillCharacteristicPoints();
+
+  void createEllipse(SketchPlugin_Sketch* theSketch, const int theResultIndex);
+
+private:
+  std::set<ResultPtr> myAuxiliaryResults;
 };
 
 #endif
index f68bf346b45bf124b9c24b11e00a60a9c26a675d..f01a332f296b0b90d751165547938b937376df3f 100644 (file)
 #include <ModelAPI_Validator.h>
 #include <ModelAPI_Session.h>
 
-#include <GeomAPI_Pnt.h>
+#include <GeomAPI_Edge.h>
 #include <GeomAPI_Lin2d.h>
+#include <GeomAPI_Pnt.h>
 #include <GeomAPI_Pnt2d.h>
 
-#include <GeomAlgoAPI_EdgeBuilder.h>
 #include <GeomDataAPI_Point2D.h>
 
 SketchPlugin_Line::SketchPlugin_Line()
@@ -68,18 +68,7 @@ void SketchPlugin_Line::execute()
     std::shared_ptr<GeomDataAPI_Point2D> anEndAttr = std::dynamic_pointer_cast<
         GeomDataAPI_Point2D>(data()->attribute(END_ID()));
     if (aStartAttr->isInitialized() && anEndAttr->isInitialized()) {
-      std::shared_ptr<GeomAPI_Pnt> aStart(aSketch->to3D(aStartAttr->x(), aStartAttr->y()));
-      std::shared_ptr<GeomAPI_Pnt> anEnd(aSketch->to3D(anEndAttr->x(), anEndAttr->y()));
-      //std::cout<<"Execute line "<<aStart->x()<<" "<<aStart->y()<<" "<<aStart->z()<<" - "
-      //  <<anEnd->x()<<" "<<anEnd->y()<<" "<<anEnd->z()<<std::endl;
-      // make linear edge
-      std::shared_ptr<GeomAPI_Edge> anEdge = GeomAlgoAPI_EdgeBuilder::line(aStart, anEnd);
-      // store the result
-      std::shared_ptr<ModelAPI_ResultConstruction> aConstr = document()->createConstruction(
-          data());
-      aConstr->setShape(anEdge);
-      aConstr->setIsInHistory(false);
-      setResult(aConstr);
+      SketchPlugin_Sketch::createLine2DResult(this, aSketch, START_ID(), END_ID());
 
       static Events_ID anId = ModelAPI_EventReentrantMessage::eventId();
       std::shared_ptr<ModelAPI_EventReentrantMessage> aMessage = std::shared_ptr
index 5bc378e9a05ad01eaaf240eb5ce292bda2adfe3a..f46286af69e6be9d1e958e4a344074d122f5a71b 100644 (file)
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 
-// File:        SketchPlugin_MacroEllipse.cpp
-// Created:     26 April 2017
-// Author:      Artem ZHIDKOV
-
 #include <SketchPlugin_MacroEllipse.h>
 
 #include <SketchPlugin_Ellipse.h>
+#include <SketchPlugin_MacroArcReentrantMessage.h>
 #include <SketchPlugin_Tools.h>
 #include <SketchPlugin_Sketch.h>
 
 #include <ModelAPI_AttributeDouble.h>
 #include <ModelAPI_AttributeRefAttr.h>
-#include <ModelAPI_EventReentrantMessage.h>
+#include <ModelAPI_AttributeString.h>
 #include <ModelAPI_Session.h>
 #include <ModelAPI_Validator.h>
 #include <ModelAPI_Events.h>
@@ -37,7 +34,6 @@
 #include <GeomDataAPI_Point2D.h>
 
 #include <GeomAPI_Dir2d.h>
-#include <GeomAPI_Pnt2d.h>
 #include <GeomAPI_Ellipse2d.h>
 #include <GeomAPI_Vertex.h>
 
@@ -55,10 +51,13 @@ SketchPlugin_MacroEllipse::SketchPlugin_MacroEllipse()
 
 void SketchPlugin_MacroEllipse::initAttributes()
 {
-  data()->addAttribute(CENTER_POINT_ID(), GeomDataAPI_Point2D::typeId());
-  data()->addAttribute(CENTER_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
-  data()->addAttribute(MAJOR_AXIS_POINT_ID(), GeomDataAPI_Point2D::typeId());
-  data()->addAttribute(MAJOR_AXIS_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
+  data()->addAttribute(ELLIPSE_TYPE(), ModelAPI_AttributeString::typeId());
+  data()->addAttribute(EDIT_ELLIPSE_TYPE(), ModelAPI_AttributeString::typeId());
+
+  data()->addAttribute(FIRST_POINT_ID(), GeomDataAPI_Point2D::typeId());
+  data()->addAttribute(FIRST_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
+  data()->addAttribute(SECOND_POINT_ID(), GeomDataAPI_Point2D::typeId());
+  data()->addAttribute(SECOND_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
   data()->addAttribute(PASSED_POINT_ID(), GeomDataAPI_Point2D::typeId());
   data()->addAttribute(PASSED_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
 
@@ -66,20 +65,31 @@ void SketchPlugin_MacroEllipse::initAttributes()
   data()->addAttribute(MINOR_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
   data()->addAttribute(AUXILIARY_ID(), ModelAPI_AttributeBoolean::typeId());
 
-  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CENTER_POINT_REF_ID());
-  ModelAPI_Session::get()->validators()->
-      registerNotObligatory(getKind(), MAJOR_AXIS_POINT_REF_ID());
+  string(EDIT_ELLIPSE_TYPE())->setValue("");
+
+  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(), PASSED_POINT_REF_ID());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EDIT_ELLIPSE_TYPE());
 }
 
 void SketchPlugin_MacroEllipse::execute()
 {
   FeaturePtr anEllipse = createEllipseFeature();
-  constraintsForEllipse(anEllipse);
+
+  std::string aType = string(ELLIPSE_TYPE())->value();
+  if (aType == ELLIPSE_TYPE_BY_CENTER_AXIS_POINT())
+    constraintsForEllipseByCenterAxisAndPassed(anEllipse);
+  else if (aType == ELLIPSE_TYPE_BY_AXIS_AND_POINT())
+    constraintsForEllipseByMajoxAxisAndPassed(anEllipse);
 
   // message to init reentrant operation
-  static Events_ID anId = ModelAPI_EventReentrantMessage::eventId();
-  ReentrantMessagePtr aMessage(new ModelAPI_EventReentrantMessage(anId, this));
+  static Events_ID anId = SketchPlugin_MacroArcReentrantMessage::eventId();
+  std::shared_ptr<SketchPlugin_MacroArcReentrantMessage> aMessage = std::shared_ptr
+    <SketchPlugin_MacroArcReentrantMessage>(new SketchPlugin_MacroArcReentrantMessage(anId, this));
+
+  std::string anEditType = string(EDIT_ELLIPSE_TYPE())->value();
+  aMessage->setTypeOfCreation(!anEditType.empty() ? anEditType : aType);
   aMessage->setCreatedFeature(anEllipse);
   Events_Loop::loop()->send(aMessage);
 }
@@ -87,79 +97,105 @@ void SketchPlugin_MacroEllipse::execute()
 void SketchPlugin_MacroEllipse::attributeChanged(const std::string& theID)
 {
   static const int NB_POINTS = 3;
-  std::string aPointAttrName[NB_POINTS] = { CENTER_POINT_ID(),
-                                            MAJOR_AXIS_POINT_ID(),
+  std::string aPointAttrName[NB_POINTS] = { FIRST_POINT_ID(),
+                                            SECOND_POINT_ID(),
                                             PASSED_POINT_ID() };
-  std::string aPointRefName[NB_POINTS] = { CENTER_POINT_REF_ID(),
-                                           MAJOR_AXIS_POINT_REF_ID(),
+  std::string aPointRefName[NB_POINTS] = { FIRST_POINT_REF_ID(),
+                                           SECOND_POINT_REF_ID(),
                                            PASSED_POINT_REF_ID() };
 
-  int aNbInitialized = 0;
-  std::shared_ptr<GeomAPI_Pnt2d> anEllipsePoints[NB_POINTS];
+  // type of ellipse switched, thus reset all attributes
+  if (theID == ELLIPSE_TYPE()) {
+    for (int aPntIndex = 0; aPntIndex < NB_POINTS; ++aPntIndex) {
+      SketchPlugin_Tools::resetAttribute(this, aPointAttrName[aPntIndex]);
+      SketchPlugin_Tools::resetAttribute(this, aPointRefName[aPntIndex]);
+    }
+  }
+  else {
+    int aNbInitialized = 0;
+    GeomPnt2dPtr anEllipsePoints[NB_POINTS];
+
+    for (int aPntIndex = 0; aPntIndex < NB_POINTS; ++aPntIndex) {
+      AttributePtr aPointAttr = attribute(aPointAttrName[aPntIndex]);
+      if (!aPointAttr->isInitialized())
+        continue;
+
+      AttributeRefAttrPtr aPointRef = refattr(aPointRefName[aPntIndex]);
+      // calculate ellipse parameters
+      GeomPnt2dPtr aPassedPoint;
+      GeomShapePtr aTangentCurve;
+      SketchPlugin_Tools::convertRefAttrToPointOrTangentCurve(
+        aPointRef, aPointAttr, aTangentCurve, aPassedPoint);
 
-  for (int aPntIndex = 0; aPntIndex < NB_POINTS; ++aPntIndex) {
-    AttributePtr aPointAttr = attribute(aPointAttrName[aPntIndex]);
-    if (!aPointAttr->isInitialized())
-      continue;
+      anEllipsePoints[aNbInitialized++] = aPassedPoint;
+    }
 
-    AttributeRefAttrPtr aPointRef = refattr(aPointRefName[aPntIndex]);
-    // calculate ellipse parameters
-    std::shared_ptr<GeomAPI_Pnt2d> aPassedPoint;
-    std::shared_ptr<GeomAPI_Shape> aTangentCurve;
-    SketchPlugin_Tools::convertRefAttrToPointOrTangentCurve(
-        aPointRef, aPointAttr, aTangentCurve, aPassedPoint);
+    if (aNbInitialized <= 1)
+      return; // too few points for the ellipse
 
-    anEllipsePoints[aNbInitialized++] = aPassedPoint;
-  }
+    if (string(ELLIPSE_TYPE())->value() == ELLIPSE_TYPE_BY_AXIS_AND_POINT()) {
+      // ellipse is given by major axis and passing point,
+      // recalculate the first point to be a center
+      anEllipsePoints[0]->setX(0.5 * (anEllipsePoints[0]->x() + anEllipsePoints[1]->x()));
+      anEllipsePoints[0]->setY(0.5 * (anEllipsePoints[0]->y() + anEllipsePoints[1]->y()));
+    }
 
-  std::shared_ptr<GeomAPI_Ellipse2d> anEllipse;
-  if (aNbInitialized == 2) {
-    std::shared_ptr<GeomAPI_Dir2d> aXDir(new GeomAPI_Dir2d(
-        anEllipsePoints[1]->x() - anEllipsePoints[0]->x(),
-        anEllipsePoints[1]->y() - anEllipsePoints[0]->y()));
-    double aMajorRad = anEllipsePoints[1]->distance(anEllipsePoints[0]);
-    anEllipse = std::shared_ptr<GeomAPI_Ellipse2d>(
-        new GeomAPI_Ellipse2d(anEllipsePoints[0], aXDir, aMajorRad, 0.5 * aMajorRad));
-  } else if (aNbInitialized == 3) {
-    anEllipse = std::shared_ptr<GeomAPI_Ellipse2d>(
+    std::shared_ptr<GeomAPI_Ellipse2d> anEllipse;
+    if (aNbInitialized == 2) {
+      GeomDir2dPtr aXDir(new GeomAPI_Dir2d(anEllipsePoints[1]->x() - anEllipsePoints[0]->x(),
+                                           anEllipsePoints[1]->y() - anEllipsePoints[0]->y()));
+      double aMajorRad = anEllipsePoints[1]->distance(anEllipsePoints[0]);
+      anEllipse = std::shared_ptr<GeomAPI_Ellipse2d>(
+          new GeomAPI_Ellipse2d(anEllipsePoints[0], aXDir, aMajorRad, 0.5 * aMajorRad));
+    }
+    else if (aNbInitialized == 3) {
+      anEllipse = std::shared_ptr<GeomAPI_Ellipse2d>(
         new GeomAPI_Ellipse2d(anEllipsePoints[0], anEllipsePoints[1], anEllipsePoints[2]));
-  }
+    }
 
-  if (!anEllipse || anEllipse->implPtr<void>() == 0)
-    return;
+    if (!anEllipse || anEllipse->implPtr<void>() == 0)
+      return;
 
-  myCenter = anEllipse->center();
-  myFocus = anEllipse->firstFocus();
-  myMajorRadius = anEllipse->majorRadius();
-  myMinorRadius = anEllipse->minorRadius();
+    myCenter = anEllipse->center();
+    myFocus = anEllipse->firstFocus();
+    myMajorRadius = anEllipse->majorRadius();
+    myMinorRadius = anEllipse->minorRadius();
 
-  AttributeDoublePtr aMajorRadiusAttr = real(MAJOR_RADIUS_ID());
-  AttributeDoublePtr aMinorRadiusAttr = real(MINOR_RADIUS_ID());
+    AttributeDoublePtr aMajorRadiusAttr = real(MAJOR_RADIUS_ID());
+    AttributeDoublePtr aMinorRadiusAttr = real(MINOR_RADIUS_ID());
 
-  bool aWasBlocked = data()->blockSendAttributeUpdated(true);
-  // center attribute is used in processEvent() to set reference to reentrant arc
-  std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(CENTER_POINT_ID()))->setValue(myCenter);
-  aMajorRadiusAttr->setValue(myMajorRadius);
-  aMinorRadiusAttr->setValue(myMinorRadius);
-  data()->blockSendAttributeUpdated(aWasBlocked, false);
+    bool aWasBlocked = data()->blockSendAttributeUpdated(true);
+    // center attribute is used in processEvent() to set reference to reentrant arc
+////    std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(FIRST_POINT_ID()))
+////        ->setValue(myCenter);
+    aMajorRadiusAttr->setValue(myMajorRadius);
+    aMinorRadiusAttr->setValue(myMinorRadius);
+    data()->blockSendAttributeUpdated(aWasBlocked, false);
+  }
 }
 
+// LCOV_EXCL_START
 std::string SketchPlugin_MacroEllipse::processEvent(
                                               const std::shared_ptr<Events_Message>& theMessage)
 {
   std::string aFilledAttributeName;
 
-  ReentrantMessagePtr aReentrantMessage =
-        std::dynamic_pointer_cast<ModelAPI_EventReentrantMessage>(theMessage);
+  std::shared_ptr<SketchPlugin_MacroArcReentrantMessage> aReentrantMessage =
+      std::dynamic_pointer_cast<SketchPlugin_MacroArcReentrantMessage>(theMessage);
   if (aReentrantMessage) {
     FeaturePtr aCreatedFeature = aReentrantMessage->createdFeature();
+    std::string anEllipseType = aReentrantMessage->typeOfCreation();
+
+    string(ELLIPSE_TYPE())->setValue(anEllipseType);
+
+    aFilledAttributeName = ELLIPSE_TYPE();
     ObjectPtr anObject = aReentrantMessage->selectedObject();
     AttributePtr anAttribute = aReentrantMessage->selectedAttribute();
     std::shared_ptr<GeomAPI_Pnt2d> aClickedPoint = aReentrantMessage->clickedPoint();
 
     if (aClickedPoint && (anObject || anAttribute)) {
-      aFilledAttributeName = CENTER_POINT_ID();
-      std::string aReferenceAttributeName = CENTER_POINT_REF_ID();
+      aFilledAttributeName = FIRST_POINT_ID();
+      std::string aReferenceAttributeName = FIRST_POINT_REF_ID();
 
       // fill 2d point attribute
       AttributePoint2DPtr aPointAttr =
@@ -171,37 +207,64 @@ std::string SketchPlugin_MacroEllipse::processEvent(
           std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(attribute(aReferenceAttributeName));
       if (anAttribute) {
         if (!anAttribute->owner() || !anAttribute->owner()->data()->isValid()) {
-          if (aCreatedFeature && anAttribute->id() == CENTER_POINT_ID())
-            anAttribute = aCreatedFeature->attribute(SketchPlugin_Ellipse::CENTER_ID());
+          if (aCreatedFeature && anAttribute->id() == FIRST_POINT_ID())
+            anAttribute = aCreatedFeature->attribute(
+                anEllipseType == ELLIPSE_TYPE_BY_CENTER_AXIS_POINT() ?
+                SketchPlugin_Ellipse::CENTER_ID() :
+                SketchPlugin_Ellipse::MAJOR_AXIS_START_ID());
         }
         aRefAttr->setAttr(anAttribute);
       }
       else if (anObject.get()) {
-        // if presentation of previous reentrant macro arc is used, the object is invalid,
-        // we should use result of previous feature of the message(Arc)
-        if (!anObject->data()->isValid())
-          anObject = aCreatedFeature->lastResult();
-        aRefAttr->setObject(anObject);
+        // if attribute is NULL, only object is defined, it should be processed outside
+        // the feature because it might be an external feature, that will be
+        // removed/created again after restart operation
+        // #2468 - Crash when sketching circles successively on a repetition
+        aFilledAttributeName = ELLIPSE_TYPE();
       }
     }
     Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
   }
   return aFilledAttributeName;
 }
+// LCOV_EXCL_STOP
 
-void SketchPlugin_MacroEllipse::constraintsForEllipse(FeaturePtr theEllipseFeature)
+void SketchPlugin_MacroEllipse::constraintsForEllipseByCenterAxisAndPassed(
+    FeaturePtr theEllipseFeature)
 {
+  // tangency on-the-fly is not applicable for ellipses
+  static const bool isTangencyApplicable = false;
   // Create constraints.
   SketchPlugin_Tools::createCoincidenceOrTangency(
-      this, CENTER_POINT_REF_ID(),
+      this, FIRST_POINT_REF_ID(),
       theEllipseFeature->attribute(SketchPlugin_Ellipse::CENTER_ID()),
-      ObjectPtr(), false);
+      ObjectPtr(), isTangencyApplicable);
+  SketchPlugin_Tools::createCoincidenceOrTangency(
+      this, SECOND_POINT_REF_ID(),
+      theEllipseFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_END_ID()),
+      ObjectPtr(), isTangencyApplicable);
+  SketchPlugin_Tools::createCoincidenceOrTangency(
+      this, PASSED_POINT_REF_ID(), AttributePtr(),
+      theEllipseFeature->lastResult(), isTangencyApplicable);
+}
+
+void SketchPlugin_MacroEllipse::constraintsForEllipseByMajoxAxisAndPassed(
+    FeaturePtr theEllipseFeature)
+{
+  // tangency on-the-fly is not applicable for ellipses
+  static const bool isTangencyApplicable = false;
+  // Create constraints.
+  SketchPlugin_Tools::createCoincidenceOrTangency(
+      this, FIRST_POINT_REF_ID(),
+      theEllipseFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_START_ID()),
+      ObjectPtr(), isTangencyApplicable);
   SketchPlugin_Tools::createCoincidenceOrTangency(
-      this, MAJOR_AXIS_POINT_REF_ID(), AttributePtr(),
-      theEllipseFeature->lastResult(), true);
+      this, SECOND_POINT_REF_ID(),
+      theEllipseFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_END_ID()),
+      ObjectPtr(), isTangencyApplicable);
   SketchPlugin_Tools::createCoincidenceOrTangency(
       this, PASSED_POINT_REF_ID(), AttributePtr(),
-      theEllipseFeature->lastResult(), true);
+      theEllipseFeature->lastResult(), isTangencyApplicable);
 }
 
 FeaturePtr SketchPlugin_MacroEllipse::createEllipseFeature()
@@ -213,7 +276,7 @@ FeaturePtr SketchPlugin_MacroEllipse::createEllipseFeature()
   aCenterAttr->setValue(myCenter->x(), myCenter->y());
 
   AttributePoint2DPtr aFocusAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-      aEllipseFeature->attribute(SketchPlugin_Ellipse::FOCUS_ID()));
+      aEllipseFeature->attribute(SketchPlugin_Ellipse::FIRST_FOCUS_ID()));
   aFocusAttr->setValue(myFocus->x(), myFocus->y());
 
   aEllipseFeature->real(SketchPlugin_Ellipse::MAJOR_RADIUS_ID())->setValue(myMajorRadius);
@@ -236,10 +299,10 @@ AISObjectPtr SketchPlugin_MacroEllipse::getAISObject(AISObjectPtr thePrevious)
       aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
 
   // Compute a ellipse in 3D view.
-  std::shared_ptr<GeomAPI_Pnt> aCenter(aSketch->to3D(myCenter->x(), myCenter->y()));
-  std::shared_ptr<GeomAPI_Pnt> aFocus(aSketch->to3D(myFocus->x(), myFocus->y()));
-  std::shared_ptr<GeomAPI_Dir> aNormal = aNDir->dir();
-  std::shared_ptr<GeomAPI_Dir> aMajorAxis(new GeomAPI_Dir(aFocus->x() - aCenter->x(),
+  GeomPointPtr aCenter(aSketch->to3D(myCenter->x(), myCenter->y()));
+  GeomPointPtr aFocus(aSketch->to3D(myFocus->x(), myFocus->y()));
+  GeomDirPtr aNormal = aNDir->dir();
+  GeomDirPtr aMajorAxis(new GeomAPI_Dir(aFocus->x() - aCenter->x(),
       aFocus->y() - aCenter->y(), aFocus->z() - aCenter->z()));
 
   std::shared_ptr<GeomAPI_Shape> anEllipseShape =
index 8d374df5c8dbc59c5f057052fac8b2a194ccfc8e..5b7d2945a6876518c46578c26e4a2fcb60de8c54 100644 (file)
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 
-// File:        SketchPlugin_MacroEllipse.h
-// Created:     26 April 2017
-// Author:      Artem ZHIDKOV
-
 #ifndef SketchPlugin_MacroEllipse_H_
 #define SketchPlugin_MacroEllipse_H_
 
@@ -48,35 +44,58 @@ class SketchPlugin_MacroEllipse: public SketchPlugin_SketchEntity,
     return ID;
   }
 
-  /// 2D point - center of the ellipse.
-  inline static const std::string& CENTER_POINT_ID()
+  static const std::string& ELLIPSE_TYPE()
+  {
+    static const std::string ID("ellipse_type");
+    return ID;
+  }
+
+  static const std::string& ELLIPSE_TYPE_BY_CENTER_AXIS_POINT()
+  {
+    static const std::string ID("by_center_axis_point");
+    return ID;
+  }
+  static const std::string& ELLIPSE_TYPE_BY_AXIS_AND_POINT()
+  {
+    static const std::string ID("by_major_axis_and_point");
+    return ID;
+  }
+
+  static const std::string& EDIT_ELLIPSE_TYPE()
+  {
+    static const std::string ID("edit_ellipse_type");
+    return ID;
+  }
+
+  /// Attribute for the first point selected during ellipse creation.
+  inline static const std::string& FIRST_POINT_ID()
   {
-    static const std::string ID("center_point");
+    static const std::string ID("first_point");
     return ID;
   }
 
-  /// Reference for center point selection.
-  inline static const std::string& CENTER_POINT_REF_ID()
+  /// Reference to the first selected point.
+  inline static const std::string& FIRST_POINT_REF_ID()
   {
-    static const std::string ID("center_point_ref");
+    static const std::string ID("first_point_ref");
     return ID;
   }
 
-  /// 2D point - major axis point of the ellipse.
-  inline static const std::string& MAJOR_AXIS_POINT_ID()
+  /// Attribute for the second point selected during ellipse creation.
+  inline static const std::string& SECOND_POINT_ID()
   {
-    static const std::string ID("major_axis_point");
+    static const std::string ID("second_point");
     return ID;
   }
 
-  /// Reference for major axis point selection.
-  inline static const std::string& MAJOR_AXIS_POINT_REF_ID()
+  /// Reference to the second selected point.
+  inline static const std::string& SECOND_POINT_REF_ID()
   {
-    static const std::string ID("major_axis_point_ref");
+    static const std::string ID("second_point_ref");
     return ID;
   }
 
-  /// 2D point - passed point of the ellipse
+  /// Attribute for the third point selected during ellipse creation.
   inline static const std::string& PASSED_POINT_ID()
   {
     static const std::string ID("passed_point");
@@ -93,14 +112,14 @@ class SketchPlugin_MacroEllipse: public SketchPlugin_SketchEntity,
   /// Major radius of the ellipse
   inline static const std::string& MAJOR_RADIUS_ID()
   {
-    static const std::string ID("ellipse_major_radius");
+    static const std::string ID("major_radius");
     return ID;
   }
 
   /// Minor radius of the ellipse
   inline static const std::string& MINOR_RADIUS_ID()
   {
-    static const std::string ID("ellipse_minor_radius");
+    static const std::string ID("minor_radius");
     return ID;
   }
 
@@ -139,7 +158,8 @@ class SketchPlugin_MacroEllipse: public SketchPlugin_SketchEntity,
   SketchPlugin_MacroEllipse();
 
 private:
-  void constraintsForEllipse(FeaturePtr theEllipseFeature);
+  void constraintsForEllipseByCenterAxisAndPassed(FeaturePtr theEllipseFeature);
+  void constraintsForEllipseByMajoxAxisAndPassed(FeaturePtr theEllipseFeature);
 
   FeaturePtr createEllipseFeature();
 
index 67d4e4656695938703899b92bf24ecd2ef18f0ae..3958b491c49ebd5f546e79f1014d37a5aa9ae0e5 100644 (file)
@@ -317,6 +317,7 @@ std::shared_ptr<ModelAPI_FeatureStateMessage> SketchPlugin_Plugin
       aMsg->setState(SketchPlugin_Trim::ID(), aHasSketchPlane);
       aMsg->setState(SketchPlugin_MacroArc::ID(), aHasSketchPlane);
       aMsg->setState(SketchPlugin_MacroCircle::ID(), aHasSketchPlane);
+      aMsg->setState(SketchPlugin_MacroEllipse::ID(), aHasSketchPlane);
       aMsg->setState(SketchPlugin_ConstraintDistanceHorizontal::ID(), aHasSketchPlane);
       aMsg->setState(SketchPlugin_ConstraintDistanceVertical::ID(), aHasSketchPlane);
       // SketchRectangle is a python feature, so its ID is passed just as a string
index 0daeb330d810e76a3eea6ac3d964764e15bc607e..9c247446cfeeebb6d666134c7616727e45c15c1f 100644 (file)
@@ -377,6 +377,35 @@ void SketchPlugin_Sketch::createPoint2DResult(ModelAPI_Feature* theFeature,
   theFeature->setResult(aResult, theIndex);
 }
 
+void SketchPlugin_Sketch::createLine2DResult(ModelAPI_Feature* theFeature,
+                                             SketchPlugin_Sketch* theSketch,
+                                             const std::string& theStartAttrID,
+                                             const std::string& theEndAttrID,
+                                             const int theIndex)
+{
+  std::shared_ptr<GeomDataAPI_Point2D> aStartAttr =
+      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theFeature->attribute(theStartAttrID));
+  std::shared_ptr<GeomDataAPI_Point2D> anEndAttr =
+      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theFeature->attribute(theEndAttrID));
+
+  if (!aStartAttr || !aStartAttr->isInitialized() ||
+      !anEndAttr || !anEndAttr->isInitialized())
+    return;
+
+  std::shared_ptr<GeomAPI_Pnt> aStart(theSketch->to3D(aStartAttr->x(), aStartAttr->y()));
+  std::shared_ptr<GeomAPI_Pnt> anEnd(theSketch->to3D(anEndAttr->x(), anEndAttr->y()));
+  //std::cout<<"Execute line "<<aStart->x()<<" "<<aStart->y()<<" "<<aStart->z()<<" - "
+  //  <<anEnd->x()<<" "<<anEnd->y()<<" "<<anEnd->z()<<std::endl;
+  // make linear edge
+  std::shared_ptr<GeomAPI_Edge> anEdge = GeomAlgoAPI_EdgeBuilder::line(aStart, anEnd);
+  // store the result
+  std::shared_ptr<ModelAPI_ResultConstruction> aResult =
+      theFeature->document()->createConstruction(theFeature->data(), theIndex);
+  aResult->setShape(anEdge);
+  aResult->setIsInHistory(false);
+  theFeature->setResult(aResult, theIndex);
+}
+
 FeaturePtr SketchPlugin_Sketch::addUniqueNamedCopiedFeature(FeaturePtr theFeature,
                                                             SketchPlugin_Sketch* theSketch,
                                                             const bool theIsCopy)
index 124ff670c0e843d1a9a0fbbc124bb2f4bd0da732..7f63c5bb2ca4643eee898b0878d9ba81f3528389 100644 (file)
@@ -230,6 +230,18 @@ class SketchPlugin_Sketch : public ModelAPI_CompositeFeature, public GeomAPI_ICu
                                   SketchPlugin_Sketch* theSketch,
                                   const std::string& theAttributeID, const int theIndex);
 
+  /// \brief Create a result for the segment given by a pair of attributes
+  /// \param theFeature a source feature
+  /// \param theSketch a sketch intance
+  /// \param theStartAttrID an attribute string
+  /// \param theEndAttrID an attribute string
+  /// \param theIndex an index of the result
+  static void createLine2DResult(ModelAPI_Feature* theFeature,
+                                 SketchPlugin_Sketch* theSketch,
+                                 const std::string& theStartAttrID,
+                                 const std::string& theEndAttrID,
+                                 const int theIndex = 0);
+
   /// Add new feature and fill the data of the feature by the data of the parameter feature.
   /// The name of the created feature stays unique.
   /// \param theFeature a source feature
index c207dd72b264b3f279483e3fa17021978e59a006..1a736ad58ca4dbe422ae319d1f9877c8e43c82da 100644 (file)
@@ -112,6 +112,10 @@ class SketchPlugin_SketchEntity : public SketchPlugin_Feature, public GeomAPI_IC
   }
 
 // LCOV_EXCL_START
+  /// Returns \c true if the result is marked as auxiliary
+  virtual bool isAuxiliary(ResultPtr theResult)
+  { return false; }
+
   /// Customize presentation of the feature
   virtual bool customisePresentation(ResultPtr theResult, AISObjectPtr thePrs,
                                      std::shared_ptr<GeomAPI_ICustomPrs> theDefaultPrs)
@@ -142,7 +146,8 @@ class SketchPlugin_SketchEntity : public SketchPlugin_Feature, public GeomAPI_IC
     std::vector<int> aColor;
     std::shared_ptr<ModelAPI_AttributeBoolean> anAuxiliaryAttr =
                                     data()->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID());
-    bool isConstruction = anAuxiliaryAttr.get() != NULL && anAuxiliaryAttr->value();
+    bool isConstruction = (anAuxiliaryAttr.get() != NULL && anAuxiliaryAttr->value())
+                       || isAuxiliary(theResult);
     if (isConstruction) {
       aColor = Config_PropManager::color("Visualization", "sketch_auxiliary_color");
     }
index 6f311635df843c220850f9dc54ac7459bf1c15db..e94e6c8317561df57a7fbae1bbeee6d1d4bc6f4b 100644 (file)
Binary files a/src/SketchPlugin/icons/ellipse.png and b/src/SketchPlugin/icons/ellipse.png differ
diff --git a/src/SketchPlugin/icons/ellipse_axes_32x32.png b/src/SketchPlugin/icons/ellipse_axes_32x32.png
new file mode 100644 (file)
index 0000000..a1a83d5
Binary files /dev/null and b/src/SketchPlugin/icons/ellipse_axes_32x32.png differ
diff --git a/src/SketchPlugin/icons/ellipse_cent_rad_32x32.png b/src/SketchPlugin/icons/ellipse_cent_rad_32x32.png
new file mode 100644 (file)
index 0000000..5781d8c
Binary files /dev/null and b/src/SketchPlugin/icons/ellipse_cent_rad_32x32.png differ
diff --git a/src/SketchPlugin/icons/elliptic_arc.png b/src/SketchPlugin/icons/elliptic_arc.png
new file mode 100644 (file)
index 0000000..03c87c0
Binary files /dev/null and b/src/SketchPlugin/icons/elliptic_arc.png differ
diff --git a/src/SketchPlugin/icons/radius_major.png b/src/SketchPlugin/icons/radius_major.png
new file mode 100644 (file)
index 0000000..ef86a07
Binary files /dev/null and b/src/SketchPlugin/icons/radius_major.png differ
diff --git a/src/SketchPlugin/icons/radius_minor.png b/src/SketchPlugin/icons/radius_minor.png
new file mode 100644 (file)
index 0000000..3be332a
Binary files /dev/null and b/src/SketchPlugin/icons/radius_minor.png differ
index 89f8ddea1ee4948fdde866a75e75db11cd609bf9..e26d1dd44fd905ac9059a3dbc2b1f8a0c2d84273 100644 (file)
@@ -5,6 +5,7 @@
         id="Sketch"
         nested="SketchPoint SketchIntersectionPoint SketchLine
                 SketchCircle SketchMacroCircle SketchArc SketchMacroArc
+                SketchEllipse SketchMacroEllipse
                 SketchRectangle
                 SketchProjection
                 SketchConstraintLength SketchConstraintRadius SketchConstraintDistance SketchConstraintDistanceHorizontal SketchConstraintDistanceVertical
       </feature>
     </group>
 
-<excluded>
     <group id="Elliptic geometry">
       <!-- SketchEllipse is a hidden feature. It is created inside SketchMacroEllipse. -->
       <feature id="SketchEllipse"
                                  tooltip="Center coordinates"
                                  accept_expressions="0"
                                  enable_value="enable_by_preferences"/>
-        <sketch-2dpoint_selector id="ellipse_focus"
-                                 title="Focus"
+        <sketch-2dpoint_selector id="ellipse_first_focus"
+                                 title="First focus"
                                  tooltip="Focus coordinates"
                                  accept_expressions="0"
                                  enable_value="enable_by_preferences"/>
+        <sketch-2dpoint_selector id="ellipse_second_focus"
+                                 title="Second focus"
+                                 tooltip="Focus coordinates"
+                                 accept_expressions="0"
+                                 enable_value="enable_by_preferences"/>
+        <sketch-2dpoint_selector id="ellipse_major_axis_start_point"
+                                 title="Major axis start"
+                                 tooltip="Coordinates of point on negative direction of major axis"
+                                 accept_expressions="0"
+                                 enable_value="enable_by_preferences"/>
+        <sketch-2dpoint_selector id="ellipse_major_axis_end_point"
+                                 title="Major axis end"
+                                 tooltip="Coordinates of point on positive direction of major axis"
+                                 accept_expressions="0"
+                                 enable_value="enable_by_preferences"/>
+        <sketch-2dpoint_selector id="ellipse_minor_axis_start_point"
+                                 title="Minor axis start"
+                                 tooltip="Coordinates of point on negative direction of minor axis"
+                                 accept_expressions="0"
+                                 enable_value="enable_by_preferences"/>
+        <sketch-2dpoint_selector id="ellipse_minor_axis_end_point"
+                                 title="Minor axis end"
+                                 tooltip="Coordinates of point on positive direction of minor axis"
+                                 accept_expressions="0"
+                                 enable_value="enable_by_preferences"/>
         <labelvalue id="ellipse_major_radius"
-                    icon="icons/Sketch/radius.png"
+                    icon="icons/Sketch/radius_major.png"
                     label="Major radius:"
                     tooltip="Set major radius"
                     default="computed"
                     enable_value="enable_by_preferences">
         </labelvalue>
         <labelvalue id="ellipse_minor_radius"
-                    icon="icons/Sketch/radius.png"
+                    icon="icons/Sketch/radius_minor.png"
                     label="Minor radius:"
                     tooltip="Set minor radius"
                     default="computed"
                title="Ellipse"
                tooltip="Create ellipse"
                helpfile="ellipseFeature.html">
-        <sketch-2dpoint_selector id="center_point"
-                                 reference_attribute="center_point_ref"
-                                 title="Center point"
-                                 tooltip="Center point coordinates"
-                                 accept_expressions="0"
-                                 enable_value="enable_by_preferences"/>
-        <sketch-2dpoint_selector id="major_axis_point"
-                                 reference_attribute="major_axis_point_ref"
-                                 title="Major axis point"
-                                 tooltip="Major axis point coordinates"
-                                 accept_expressions="0"
-                                 enable_value="enable_by_preferences"/>
-        <sketch-2dpoint_selector id="passed_point"
-                                 reference_attribute="passed_point_ref"
-                                 title="Passed point"
-                                 tooltip="Passed point coordinates"
-                                 accept_expressions="0"
-                                 enable_value="enable_by_preferences">
-<!--          <validator id="SketchPlugin_CirclePassedPointValidator"/> -->
-        </sketch-2dpoint_selector>
+        <toolbox id="ellipse_type" modified_in_edit="edit_ellipse_type">
+          <box id="by_center_axis_point"
+               icon="icons/Sketch/ellipse_cent_rad_32x32.png"
+               title="Center, major semi-axis and passing point">
+            <sketch-2dpoint_selector id="first_point"
+                                     reference_attribute="first_point_ref"
+                                     title="Center point"
+                                     tooltip="Center point coordinates"
+                                     accept_expressions="0"
+                                     enable_value="enable_by_preferences"/>
+            <sketch-2dpoint_selector id="second_point"
+                                     reference_attribute="second_point_ref"
+                                     title="Major axis point"
+                                     tooltip="Major axis point coordinates"
+                                     accept_expressions="0"
+                                     enable_value="enable_by_preferences"/>
+            <sketch-2dpoint_selector id="passed_point"
+                                     reference_attribute="passed_point_ref"
+                                     title="Passed point"
+                                     tooltip="Passed point coordinates"
+                                     accept_expressions="0"
+                                     enable_value="enable_by_preferences">
+              <!--          <validator id="SketchPlugin_CirclePassedPointValidator"/> -->
+            </sketch-2dpoint_selector>
+          </box>
+          <box id="by_major_axis_and_point"
+               icon="icons/Sketch/ellipse_axes_32x32.png"
+               title="Major axis and passing point">
+            <sketch-2dpoint_selector id="first_point"
+                                     reference_attribute="first_point_ref"
+                                     title="Major axis start point"
+                                     tooltip="Major axis start point coordinates"
+                                     accept_expressions="0"
+                                     enable_value="enable_by_preferences"/>
+            <sketch-2dpoint_selector id="second_point"
+                                     reference_attribute="second_point_ref"
+                                     title="Major axis end point"
+                                     tooltip="Major axis end point coordinates"
+                                     accept_expressions="0"
+                                     enable_value="enable_by_preferences"/>
+            <sketch-2dpoint_selector id="passed_point"
+                                     reference_attribute="passed_point_ref"
+                                     title="Passed point"
+                                     tooltip="Passed point coordinates"
+                                     accept_expressions="0"
+                                     enable_value="enable_by_preferences"/>
+          </box>
+        </toolbox>
 <!--        <validator id="GeomValidators_Different" parameters="center_point_ref,passed_point_ref"/> -->
-        <labelvalue id="ellipse_major_radius"
-                    icon="icons/Sketch/radius.png"
+        <labelvalue id="major_radius"
+                    icon="icons/Sketch/radius_major.png"
                     label="Major radius:"
                     tooltip="Set major radius"
                     default="computed"
                     enable_value="enable_by_preferences">
           <validator id="GeomValidators_Positive"/>
         </labelvalue>
-        <labelvalue id="ellipse_minor_radius"
-                    icon="icons/Sketch/radius.png"
+        <labelvalue id="minor_radius"
+                    icon="icons/Sketch/radius_minor.png"
                     label="Minor radius:"
                     tooltip="Set minor radius"
                     default="computed"
                    obligatory="0"/>
       </feature>
     </group>
-</excluded>
 
     <group id="Projection">
       <!-- Projected feature -->
index af72c4b13ae4870766f82a8dec15ce2b84fdfcda..fab1f0356d3f363e00fff20140a125395f3172e9 100644 (file)
@@ -25,7 +25,7 @@ SET(PLANEGCSSOLVER_HEADERS
     PlaneGCSSolver_Storage.h
     PlaneGCSSolver_ConstraintWrapper.h
     PlaneGCSSolver_EdgeWrapper.h
-    PlaneGCSSolver_EdgeWrapper.h
+    PlaneGCSSolver_EntityWrapper.h
     PlaneGCSSolver_PointWrapper.h
     PlaneGCSSolver_ScalarWrapper.h
     PlaneGCSSolver_AngleWrapper.h
index e4851a295ecabfb4ef47d728373ed6a2874ef584..e63fa6b91f026513468a6005dc3b94020879e265 100644 (file)
@@ -50,7 +50,9 @@ enum SketchSolver_EntityType {
   ENTITY_POINT,
   ENTITY_LINE,
   ENTITY_CIRCLE,
-  ENTITY_ARC
+  ENTITY_ARC,
+  ENTITY_ELLIPSE,
+  ENTITY_ELLIPTICAL_ARC
 };
 
 /// Types of constraints
index 7ec36cf236a33507de548cfad7bde4f137c137a5..bb8af7873db682ede8da9d82bf456dce45599a9c 100644 (file)
@@ -31,6 +31,11 @@ PlaneGCSSolver_EdgeWrapper::PlaneGCSSolver_EdgeWrapper(const GCSCurvePtr theEnti
     else {
       std::shared_ptr<GCS::Circle> aCircle = std::dynamic_pointer_cast<GCS::Circle>(myEntity);
       if (aCircle) myType = ENTITY_CIRCLE;
+      else {
+        std::shared_ptr<GCS::Ellipse> anEllipse =
+            std::dynamic_pointer_cast<GCS::Ellipse>(myEntity);
+        if (anEllipse) myType = ENTITY_ELLIPSE;
+      }
     }
   }
 }
@@ -62,5 +67,9 @@ bool PlaneGCSSolver_EdgeWrapper::isDegenerated() const
     return aSqRadius < aSqTol || aSqRadius > aMaxRadius * aMaxRadius || // <- arc radius
            anAngleDiff < anAngleTol || fabs(anAngleDiff - 2*PI) < anAngleTol; // <- arc angle
   }
+  else if (myType == ENTITY_ELLIPSE) {
+    std::shared_ptr<GCS::Ellipse> anEllipse = std::dynamic_pointer_cast<GCS::Ellipse>(myEntity);
+    return *anEllipse->radmin < tolerance;
+  }
   return false;
 }
index 0d224cbdb017bdd434389665fa2e8abb3e66263b..5eceaf63c5c20f1d63906b4584d4ee401b24eabc 100644 (file)
@@ -28,6 +28,9 @@
 #include <list>
 #include <memory>
 
+class PlaneGCSSolver_EntityWrapper;
+typedef std::shared_ptr<PlaneGCSSolver_EntityWrapper> EntityWrapperPtr;
+
 /**
  *  Wrapper providing operations with entities regardless the solver.
  */
@@ -45,10 +48,16 @@ public:
   /// \brief Return the External flag
   bool isExternal() const { return myExternal; }
 
+  /// \brief Store names of attributes and their values if necessary
+  void setAdditionalAttributes(const std::map<std::string, EntityWrapperPtr>& theAttribues)
+  { myAdditionalAttributes = theAttribues; }
+  /// \brief Return the list of additional attributes
+  const std::map<std::string, EntityWrapperPtr>& additionalAttributes() const
+  { return myAdditionalAttributes; }
+
 private:
   bool myExternal;
+  std::map<std::string, EntityWrapperPtr> myAdditionalAttributes;
 };
 
-typedef std::shared_ptr<PlaneGCSSolver_EntityWrapper> EntityWrapperPtr;
-
 #endif
index d491a00490cda396fd0909b8ad7a105e97f2b39b..4755eb6bfd449e0b7ae74efa8a9e23cbb6f02129 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <SketchPlugin_Arc.h>
 #include <SketchPlugin_Circle.h>
+#include <SketchPlugin_Ellipse.h>
 #include <SketchPlugin_IntersectionPoint.h>
 #include <SketchPlugin_Line.h>
 #include <SketchPlugin_Point.h>
@@ -40,6 +41,7 @@ static EntityWrapperPtr createLine(const AttributeEntityMap& theAttributes);
 static EntityWrapperPtr createCircle(const AttributeEntityMap& theAttributes);
 static EntityWrapperPtr createArc(const AttributeEntityMap&    theAttributes,
                                   PlaneGCSSolver_Storage*      theStorage);
+static EntityWrapperPtr createEllipse(const AttributeEntityMap& theAttributes);
 
 
 PlaneGCSSolver_FeatureBuilder::PlaneGCSSolver_FeatureBuilder(
@@ -90,6 +92,9 @@ EntityWrapperPtr PlaneGCSSolver_FeatureBuilder::createFeature(FeaturePtr theFeat
   // Arc
   else if (aFeatureKind == SketchPlugin_Arc::ID())
     aResult = createArc(myAttributes, myStorage);
+  // Ellipse
+  else if (aFeatureKind == SketchPlugin_Ellipse::ID())
+    aResult = createEllipse(myAttributes);
   // Point (it has low probability to be an attribute of constraint, so it is checked at the end)
   else if (aFeatureKind == SketchPlugin_Point::ID() ||
            aFeatureKind == SketchPlugin_IntersectionPoint::ID()) {
@@ -210,6 +215,38 @@ EntityWrapperPtr createArc(const AttributeEntityMap&    theAttributes,
   return anArcWrapper;
 }
 
+EntityWrapperPtr createEllipse(const AttributeEntityMap& theAttributes)
+{
+  std::shared_ptr<GCS::Ellipse> aNewEllipse(new GCS::Ellipse);
+
+  std::map<std::string, EntityWrapperPtr> anAdditionalAttributes;
+
+  AttributeEntityMap::const_iterator anIt = theAttributes.begin();
+  for (; anIt != theAttributes.end(); ++anIt) {
+    std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
+        std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anIt->second);
+    if (aPoint) {
+      if (anIt->first->id() == SketchPlugin_Ellipse::CENTER_ID())
+        aNewEllipse->center = *(aPoint->point());
+      else if (anIt->first->id() == SketchPlugin_Ellipse::FIRST_FOCUS_ID())
+        aNewEllipse->focus1 = *(aPoint->point());
+      else
+        anAdditionalAttributes[anIt->first->id()] = anIt->second;
+    }
+    else if (anIt->first->id() == SketchPlugin_Ellipse::MINOR_RADIUS_ID()) {
+      ScalarWrapperPtr aScalar =
+          std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(anIt->second);
+      aNewEllipse->radmin = aScalar->scalar();
+    }
+    else
+      anAdditionalAttributes[anIt->first->id()] = anIt->second;
+  }
+
+  EntityWrapperPtr anEllipseWrapper(new PlaneGCSSolver_EdgeWrapper(aNewEllipse));
+  anEllipseWrapper->setAdditionalAttributes(anAdditionalAttributes);
+  return anEllipseWrapper;
+}
+
 bool isAttributeApplicable(const std::string& theAttrName, const std::string& theOwnerName)
 {
   if (theOwnerName == SketchPlugin_Arc::ID()) {
@@ -226,6 +263,17 @@ bool isAttributeApplicable(const std::string& theAttrName, const std::string& th
     return theAttrName == SketchPlugin_Line::START_ID() ||
            theAttrName == SketchPlugin_Line::END_ID();
   }
+  else if (theOwnerName == SketchPlugin_Ellipse::ID()) {
+    return theAttrName == SketchPlugin_Ellipse::CENTER_ID() ||
+           theAttrName == SketchPlugin_Ellipse::FIRST_FOCUS_ID() ||
+           theAttrName == SketchPlugin_Ellipse::SECOND_FOCUS_ID() ||
+           theAttrName == SketchPlugin_Ellipse::MAJOR_AXIS_START_ID() ||
+           theAttrName == SketchPlugin_Ellipse::MAJOR_AXIS_END_ID() ||
+           theAttrName == SketchPlugin_Ellipse::MINOR_AXIS_START_ID() ||
+           theAttrName == SketchPlugin_Ellipse::MINOR_AXIS_END_ID() ||
+           theAttrName == SketchPlugin_Ellipse::MAJOR_RADIUS_ID() ||
+           theAttrName == SketchPlugin_Ellipse::MINOR_RADIUS_ID();
+  }
 
   // suppose that all remaining features are points
   return theAttrName == SketchPlugin_Point::COORD_ID();
index 5c8cebe53ff3a75fc0fa3ac47e2419adc3867411..ba86322fde9254c5123f0eb2e229346daac567bd 100644 (file)
@@ -34,6 +34,7 @@
 #include <GeomAPI_XY.h>
 #include <GeomDataAPI_Point2D.h>
 #include <ModelAPI_AttributeRefAttr.h>
+#include <SketchPlugin_Ellipse.h>
 #include <SketchPlugin_Projection.h>
 
 #include <cmath>
@@ -195,7 +196,7 @@ bool PlaneGCSSolver_Storage::update(FeaturePtr theFeature, bool theForce)
     // (do not want to add several copies of it while adding attributes)
     aRelated = createFeature(theFeature, &aBuilder);
     myFeatureMap[theFeature] = aRelated;
-    createArcConstraints(aRelated);
+    createAuxiliaryConstraints(aRelated);
     isUpdated = true;
   }
 
@@ -265,7 +266,7 @@ void PlaneGCSSolver_Storage::makeExternal(const EntityWrapperPtr& theEntity)
   if (theEntity->isExternal())
     return;
 
-  removeArcConstraints(theEntity);
+  removeAuxiliaryConstraints(theEntity);
 
   GCS::SET_pD aParameters = PlaneGCSSolver_Tools::parameters(theEntity);
   mySketchSolver->removeParameters(aParameters);
@@ -282,17 +283,17 @@ void PlaneGCSSolver_Storage::makeNonExternal(const EntityWrapperPtr& theEntity)
   mySketchSolver->addParameters(aParameters);
   theEntity->setExternal(false);
 
-  createArcConstraints(theEntity);
+  createAuxiliaryConstraints(theEntity);
 
   myNeedToResolve = true;
 }
 
 
-void PlaneGCSSolver_Storage::createArcConstraints(const EntityWrapperPtr& theArc)
+static void createArcConstraints(const EntityWrapperPtr& theArc,
+                                 const SolverPtr& theSolver,
+                                 const ConstraintID theConstraintID,
+                                 std::map<EntityWrapperPtr, ConstraintWrapperPtr>& theConstraints)
 {
-  if (!theArc || theArc->type() != ENTITY_ARC || theArc->isExternal())
-    return;
-
   EdgeWrapperPtr anEdge = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theArc);
   std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(anEdge->entity());
 
@@ -300,39 +301,110 @@ void PlaneGCSSolver_Storage::createArcConstraints(const EntityWrapperPtr& theArc
   std::list<GCSConstraintPtr> anArcConstraints;
   // constrain the start point on the arc
   anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintCurveValue(
-      anArc->start, anArc->start.x, *anArc, anArc->startAngle)));
+    anArc->start, anArc->start.x, *anArc, anArc->startAngle)));
   anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintCurveValue(
-      anArc->start, anArc->start.y, *anArc, anArc->startAngle)));
+    anArc->start, anArc->start.y, *anArc, anArc->startAngle)));
   // constrain the end point on the arc
   anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintCurveValue(
-      anArc->end, anArc->end.x, *anArc, anArc->endAngle)));
+    anArc->end, anArc->end.x, *anArc, anArc->endAngle)));
   anArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintCurveValue(
-      anArc->end, anArc->end.y, *anArc, anArc->endAngle)));
+    anArc->end, anArc->end.y, *anArc, anArc->endAngle)));
+
+  ConstraintWrapperPtr aWrapper(
+    new PlaneGCSSolver_ConstraintWrapper(anArcConstraints, CONSTRAINT_UNKNOWN));
+  aWrapper->setId(theConstraintID);
+  constraintsToSolver(aWrapper, theSolver);
+
+  theConstraints[theArc] = aWrapper;
+}
+
+static void createEllipseConstraints(
+    const EntityWrapperPtr& theEllipse,
+    const SolverPtr& theSolver,
+    const ConstraintID theConstraintID,
+    std::map<EntityWrapperPtr, ConstraintWrapperPtr>& theConstraints)
+{
+  EdgeWrapperPtr anEdge = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theEllipse);
+  std::shared_ptr<GCS::Ellipse> anEllipse =
+      std::dynamic_pointer_cast<GCS::Ellipse>(anEdge->entity());
+
+  // Additional constaints to fix ellipse's extra points
+  std::list<GCSConstraintPtr> anEllipseConstraints;
+
+  const std::map<std::string, EntityWrapperPtr>& anAttributes = theEllipse->additionalAttributes();
+  for (std::map<std::string, EntityWrapperPtr>::const_iterator anIt = anAttributes.begin();
+       anIt != anAttributes.end(); ++anIt) {
+    std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
+        std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anIt->second);
+    if (!aPoint)
+      continue;
+
+    GCS::InternalAlignmentType anAlignmentX, anAlignmentY;
+    if (anIt->first == SketchPlugin_Ellipse::SECOND_FOCUS_ID())
+      anAlignmentX = GCS::EllipseFocus2X;
+    else if (anIt->first == SketchPlugin_Ellipse::MAJOR_AXIS_START_ID())
+      anAlignmentX = GCS::EllipseNegativeMajorX;
+    else if (anIt->first == SketchPlugin_Ellipse::MAJOR_AXIS_END_ID())
+      anAlignmentX = GCS::EllipsePositiveMajorX;
+    else if (anIt->first == SketchPlugin_Ellipse::MINOR_AXIS_START_ID())
+      anAlignmentX = GCS::EllipseNegativeMinorX;
+    else if (anIt->first == SketchPlugin_Ellipse::MINOR_AXIS_END_ID())
+      anAlignmentX = GCS::EllipsePositiveMinorX;
+
+    anEllipseConstraints.push_back(GCSConstraintPtr(
+        new GCS::ConstraintInternalAlignmentPoint2Ellipse(*anEllipse, *(aPoint->point()), anAlignmentX)));
+    anAlignmentY = (GCS::InternalAlignmentType)((int)anAlignmentX + 1);
+    anEllipseConstraints.push_back(GCSConstraintPtr(
+        new GCS::ConstraintInternalAlignmentPoint2Ellipse(*anEllipse, *(aPoint->point()), anAlignmentY)));
+  }
+
+  // constraint to bind the major radius value
+  std::shared_ptr<PlaneGCSSolver_PointWrapper> aMajorAxisStart =
+      std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(
+      anAttributes.at(SketchPlugin_Ellipse::MAJOR_AXIS_START_ID()));
+  ScalarWrapperPtr aMajorRadius =
+      std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(
+      anAttributes.at(SketchPlugin_Ellipse::MAJOR_RADIUS_ID()));
+  anEllipseConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance(
+      anEllipse->center, *(aMajorAxisStart->point()), aMajorRadius->scalar())));
 
   ConstraintWrapperPtr aWrapper(
-      new PlaneGCSSolver_ConstraintWrapper(anArcConstraints, CONSTRAINT_UNKNOWN));
-  aWrapper->setId(++myConstraintLastID);
-  constraintsToSolver(aWrapper, mySketchSolver);
+    new PlaneGCSSolver_ConstraintWrapper(anEllipseConstraints, CONSTRAINT_UNKNOWN));
+  aWrapper->setId(theConstraintID);
+  constraintsToSolver(aWrapper, theSolver);
 
-  myArcConstraintMap[theArc] = aWrapper;
+  theConstraints[theEllipse] = aWrapper;
 }
 
-void PlaneGCSSolver_Storage::removeArcConstraints(const EntityWrapperPtr& theArc)
+void PlaneGCSSolver_Storage::createAuxiliaryConstraints(const EntityWrapperPtr& theEntity)
+{
+  if (!theEntity || theEntity->isExternal())
+    return;
+
+  if (theEntity->type() == ENTITY_ARC)
+    createArcConstraints(theEntity, mySketchSolver, ++myConstraintLastID, myAuxConstraintMap);
+  else if (theEntity->type() == ENTITY_ELLIPSE)
+    createEllipseConstraints(theEntity, mySketchSolver, ++myConstraintLastID, myAuxConstraintMap);
+}
+
+void PlaneGCSSolver_Storage::removeAuxiliaryConstraints(const EntityWrapperPtr& theEntity)
 {
   std::map<EntityWrapperPtr, ConstraintWrapperPtr>::iterator
-      aFound = myArcConstraintMap.find(theArc);
-  if (aFound != myArcConstraintMap.end()) {
+      aFound = myAuxConstraintMap.find(theEntity);
+  if (aFound != myAuxConstraintMap.end()) {
     mySketchSolver->removeConstraint(aFound->second->id());
-    myArcConstraintMap.erase(aFound);
+    myAuxConstraintMap.erase(aFound);
   }
 }
 
 void PlaneGCSSolver_Storage::adjustParametrizationOfArcs()
 {
-  std::map<EntityWrapperPtr, ConstraintWrapperPtr>::iterator anIt = myArcConstraintMap.begin();
-  for (; anIt != myArcConstraintMap.end(); ++anIt) {
+  std::map<EntityWrapperPtr, ConstraintWrapperPtr>::iterator anIt = myAuxConstraintMap.begin();
+  for (; anIt != myAuxConstraintMap.end(); ++anIt) {
     EdgeWrapperPtr anEdge = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(anIt->first);
     std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(anEdge->entity());
+    if (!anArc)
+      continue;
     // tune start angle of the arc to be in [0, 2PI]
     while (*anArc->startAngle < -PI)
       *anArc->startAngle += 2.0 * PI;
@@ -417,7 +489,7 @@ void PlaneGCSSolver_Storage::removeInvalidEntities()
         aDestroyer.remove(aFIter->second);
 
       // remove invalid arc
-      removeArcConstraints(aFIter->second);
+      removeAuxiliaryConstraints(aFIter->second);
     }
   std::list<FeaturePtr>::const_iterator anInvFIt = anInvalidFeatures.begin();
   for (; anInvFIt != anInvalidFeatures.end(); ++anInvFIt)
index 107e4205dd89c20ccbbcf367bcf2ea9efce3b071..cfa195c5ca3eb616029048513879c090f5388442 100644 (file)
@@ -88,7 +88,7 @@ public:
 
   /// \brief Check the storage has constraints
   virtual bool isEmpty() const
-  { return SketchSolver_Storage::isEmpty() && myArcConstraintMap.empty(); }
+  { return SketchSolver_Storage::isEmpty() && myAuxConstraintMap.empty(); }
 
   /// \brief Make parametrization of arcs consistent.
   ///        Forward arcs should have the last parameter greater than the first parameter.
@@ -104,14 +104,17 @@ private:
   EntityWrapperPtr createAttribute(const AttributePtr&           theAttribute,
                                    PlaneGCSSolver_EntityBuilder* theBuilder);
 
-  void createArcConstraints(const EntityWrapperPtr& theArc);
-  void removeArcConstraints(const EntityWrapperPtr& theArc);
+  /// \brief Create additional constaints:
+  ///        * for arc to fix extra parameters;
+  ///        * for ellipse to keep auxiliary points on their places
+  void createAuxiliaryConstraints(const EntityWrapperPtr& theEntity);
+  void removeAuxiliaryConstraints(const EntityWrapperPtr& theEntity);
 
 private:
   ConstraintID myConstraintLastID;   ///< identifier of last added constraint
 
-  /// additional constraints for correct processing of the arcs
-  std::map<EntityWrapperPtr, ConstraintWrapperPtr> myArcConstraintMap;
+  /// additional constraints for correct processing of the arcs, ellipses, elliptical arcs
+  std::map<EntityWrapperPtr, ConstraintWrapperPtr> myAuxConstraintMap;
 
   /// list of removed constraints to notify solver
   std::list<GCSConstraintPtr> myRemovedConstraints;
index e90def0d2bce33d7fda69f0ee79ce14671aa1386..d5ff3cb3dd4cd057f9c99d134328171743617c7d 100644 (file)
@@ -114,6 +114,7 @@ static GCS::SET_pD pointParameters(const PointWrapperPtr& thePoint);
 static GCS::SET_pD lineParameters(const EdgeWrapperPtr& theLine);
 static GCS::SET_pD circleParameters(const EdgeWrapperPtr& theCircle);
 static GCS::SET_pD arcParameters(const EdgeWrapperPtr& theArc);
+static GCS::SET_pD ellipseParameters(const EdgeWrapperPtr& theEllipse);
 
 
 
@@ -296,6 +297,8 @@ GCS::SET_pD PlaneGCSSolver_Tools::parameters(const EntityWrapperPtr& theEntity)
     return circleParameters(GCS_EDGE_WRAPPER(theEntity));
   case ENTITY_ARC:
     return arcParameters(GCS_EDGE_WRAPPER(theEntity));
+  case ENTITY_ELLIPSE:
+    return ellipseParameters(GCS_EDGE_WRAPPER(theEntity));
   default: break;
   }
   return GCS::SET_pD();
@@ -346,6 +349,13 @@ ConstraintWrapperPtr createConstraintPointOnEntity(
         new GCS::ConstraintP2PDistance(*(thePoint->point()), aCirc->center, aCirc->rad));
     break;
     }
+  case ENTITY_ELLIPSE:
+  case ENTITY_ELLIPTICAL_ARC: {
+    std::shared_ptr<GCS::Ellipse> anEllipse =
+        std::dynamic_pointer_cast<GCS::Ellipse>(theEntity->entity());
+    aNewConstr = GCSConstraintPtr(new GCS::ConstraintPointOnEllipse(*(thePoint->point()), *anEllipse));
+    break;
+    }
   default:
     return ConstraintWrapperPtr();
   }
@@ -567,7 +577,19 @@ ConstraintWrapperPtr createConstraintEqual(
     std::shared_ptr<GCS::Circle> aCirc2 =
         std::dynamic_pointer_cast<GCS::Circle>(theEntity2->entity());
 
-    aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintEqual(aCirc1->rad, aCirc2->rad)));
+    if (aCirc1 && aCirc2)
+      aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintEqual(aCirc1->rad, aCirc2->rad)));
+    else {
+      std::shared_ptr<GCS::Ellipse> anEllipse1 =
+          std::dynamic_pointer_cast<GCS::Ellipse>(theEntity1->entity());
+      std::shared_ptr<GCS::Ellipse> anEllipse2 =
+          std::dynamic_pointer_cast<GCS::Ellipse>(theEntity2->entity());
+
+      aConstrList.push_back(GCSConstraintPtr(
+          new GCS::ConstraintEqual(anEllipse1->radmin, anEllipse2->radmin)));
+      aConstrList.push_back(GCSConstraintPtr(
+          new GCS::ConstraintEqualMajorAxesConic(anEllipse1.get(), anEllipse2.get())));
+    }
   }
 
   std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
@@ -628,3 +650,16 @@ GCS::SET_pD arcParameters(const EdgeWrapperPtr& theArc)
   aParams.insert(anArc->rad);
   return aParams;
 }
+
+GCS::SET_pD ellipseParameters(const EdgeWrapperPtr& theEllipse)
+{
+  GCS::SET_pD aParams;
+  std::shared_ptr<GCS::Ellipse> anEllipse =
+      std::dynamic_pointer_cast<GCS::Ellipse>(theEllipse->entity());
+  aParams.insert(anEllipse->center.x);
+  aParams.insert(anEllipse->center.y);
+  aParams.insert(anEllipse->focus1.x);
+  aParams.insert(anEllipse->focus1.y);
+  aParams.insert(anEllipse->radmin);
+  return aParams;
+}
index f61c8a49a73f0c2fef25146bdd5bd1fc72f989c2..2cb63252265c06075bd09ba2a14edc6c0344314e 100644 (file)
@@ -141,6 +141,16 @@ GCS::VEC_pD toParameters(const EntityWrapperPtr& theEntity)
     aParameters.push_back(anArc->endAngle);
     break;
     }
+  case ENTITY_ELLIPSE: {
+    std::shared_ptr<GCS::Ellipse> anEllipse =
+        std::dynamic_pointer_cast<GCS::Ellipse>(anEntity->entity());
+    aParameters.push_back(anEllipse->center.x);
+    aParameters.push_back(anEllipse->center.y);
+    aParameters.push_back(anEllipse->focus1.x);
+    aParameters.push_back(anEllipse->focus1.y);
+    aParameters.push_back(anEllipse->radmin);
+    break;
+    }
   default:
     break;
   }
index fdc4b0e78ff85afa6e34be69fb70fc3341219d67..1c752f47d6e1945128607ff05e9631935983aa9c 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <SketchPlugin_Arc.h>
 #include <SketchPlugin_Circle.h>
+#include <SketchPlugin_Ellipse.h>
 #include <SketchPlugin_Line.h>
 #include <SketchPlugin_Point.h>
 
 
 #include <GeomAPI_Pnt2d.h>
 
+#include <cmath>
+
+static GCS::Point createGCSPoint(double* x, double* y)
+{
+  GCS::Point aPoint;
+  aPoint.x = x;
+  aPoint.y = y;
+  return aPoint;
+}
+
 
 SketchSolver_ConstraintMovement::SketchSolver_ConstraintMovement(FeaturePtr theFeature)
   : SketchSolver_ConstraintFixed(ConstraintPtr()),
@@ -78,7 +89,8 @@ static bool isSimpleMove(FeaturePtr theMovedFeature, AttributePtr theDraggedPoin
 {
   bool isSimple = true;
 #ifdef CHANGE_RADIUS_WHILE_MOVE
-  if (theMovedFeature->getKind() == SketchPlugin_Circle::ID())
+  if (theMovedFeature->getKind() == SketchPlugin_Circle::ID() ||
+      theMovedFeature->getKind() == SketchPlugin_Ellipse::ID())
     isSimple = (theDraggedPoint.get() != 0);
   else if (theMovedFeature->getKind() == SketchPlugin_Arc::ID()) {
     isSimple = (theDraggedPoint.get() != 0 &&
@@ -117,8 +129,14 @@ ConstraintWrapperPtr SketchSolver_ConstraintMovement::initMovement()
   else {
     if (myDraggedPoint) // start or end point of arc has been moved
       aConstraint = fixArcExtremity(anEntity);
-    else // arc or circle has been moved
+    else if (anEntity->type() == ENTITY_CIRCLE || anEntity->type() == ENTITY_ARC) {
+      // arc or circle has been moved
       aConstraint = fixPointOnCircle(anEntity);
+    }
+    else if (anEntity->type() == ENTITY_ELLIPSE || anEntity->type() == ENTITY_ELLIPTICAL_ARC) {
+      // ellipse or elliptical arc has been moved
+      aConstraint = fixPointOnEllipse(anEntity);
+    }
   }
 
   return aConstraint;
@@ -172,9 +190,7 @@ ConstraintWrapperPtr SketchSolver_ConstraintMovement::fixPointOnCircle(
   myFixedValues.push_back(*aCircular->center.y);
 
   // create a moved point
-  GCS::Point aPointOnCircle;
-  aPointOnCircle.x = &myFixedValues[0];
-  aPointOnCircle.y = &myFixedValues[1];
+  GCS::Point aPointOnCircle = createGCSPoint(&myFixedValues[0], &myFixedValues[1]);
 
   std::list<GCSConstraintPtr> aConstraints;
   // point-on-circle
@@ -197,6 +213,69 @@ ConstraintWrapperPtr SketchSolver_ConstraintMovement::fixPointOnCircle(
       new PlaneGCSSolver_ConstraintWrapper(aConstraints, getType()));
 }
 
+ConstraintWrapperPtr SketchSolver_ConstraintMovement::fixPointOnEllipse(
+    const EntityWrapperPtr& theConic)
+{
+  static const double scale = 0.01;
+  static const int nbParams = 6;
+  myFixedValues.reserve(nbParams); // moved point; center and focus of ellipse
+
+  EdgeWrapperPtr anEdge = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theConic);
+  std::shared_ptr<GCS::Ellipse> aConic = std::dynamic_pointer_cast<GCS::Ellipse>(anEdge->entity());
+
+  // major axis direction
+  double dx = *aConic->focus1.x - *aConic->center.x;
+  double dy = *aConic->focus1.y - *aConic->center.y;
+  double norm = sqrt(dx * dx + dy* dy);
+  if (norm < tolerance) {
+    dx = 1.0;
+    dy = 0.0;
+  }
+  else {
+    dx /= norm;
+    dy /= norm;
+  }
+
+  double aMajorRad = aConic->getRadMaj();
+
+  // initialize fixed values
+  myFixedValues.push_back(*aConic->center.x + dx * aMajorRad);
+  myFixedValues.push_back(*aConic->center.y + dy * aMajorRad);
+  myFixedValues.push_back(*aConic->center.x);
+  myFixedValues.push_back(*aConic->center.y);
+  myFixedValues.push_back(*aConic->focus1.x);
+  myFixedValues.push_back(*aConic->focus1.y);
+
+  // create a moved point
+  GCS::Point aPointOnEllipse = createGCSPoint(&myFixedValues[0], &myFixedValues[1]);
+
+  std::list<GCSConstraintPtr> aConstraints;
+  // point-on-circle
+  GCSConstraintPtr aNewConstraint(
+    new GCS::ConstraintPointOnEllipse(aPointOnEllipse, *aConic));
+  aNewConstraint->rescale(scale);
+  aConstraints.push_back(aNewConstraint);
+  // fixed center (x)
+  aNewConstraint = GCSConstraintPtr(
+    new GCS::ConstraintEqual(&myFixedValues[2], aConic->center.x));
+  aNewConstraint->rescale(scale);
+  aConstraints.push_back(aNewConstraint);
+  // fixed center (y)
+  aNewConstraint = GCSConstraintPtr(
+    new GCS::ConstraintEqual(&myFixedValues[3], aConic->center.y));
+  aNewConstraint->rescale(scale);
+  aConstraints.push_back(aNewConstraint);
+  // focus on the major axis
+  GCS::Point aStartPoint = createGCSPoint(&myFixedValues[2], &myFixedValues[3]);
+  GCS::Point aEndPoint   = createGCSPoint(&myFixedValues[4], &myFixedValues[5]);
+  aNewConstraint = GCSConstraintPtr(
+    new GCS::ConstraintPointOnLine(aConic->focus1, aStartPoint, aEndPoint));
+  aNewConstraint->rescale(scale);
+  aConstraints.push_back(aNewConstraint);
+
+  return ConstraintWrapperPtr(
+    new PlaneGCSSolver_ConstraintWrapper(aConstraints, getType()));
+}
 
 void SketchSolver_ConstraintMovement::startPoint(
     const std::shared_ptr<GeomAPI_Pnt2d>& theStartPoint)
index 1735a70b0488bc1c5e562cbd1fd4bb06495166cf..4d14eb42d771d1231a41d285e8b8d3462d70fbf1 100644 (file)
@@ -66,9 +66,12 @@ protected:
   /// \brief Create constraint to fix moved arc extremity
   ConstraintWrapperPtr fixArcExtremity(const EntityWrapperPtr& theArcExtremity);
 
-  /// \brief Creat constraint to fix moved point on circle/arc
+  /// \brief Create constraint to fix moved point on circle/arc
   ConstraintWrapperPtr fixPointOnCircle(const EntityWrapperPtr& theCircular);
 
+  /// \brief Create constraint to fix moved point on ellipse/elliptical arc
+  ConstraintWrapperPtr fixPointOnEllipse(const EntityWrapperPtr& theConic);
+
 private:
   FeaturePtr       myMovedFeature; ///< fixed feature (if set, myBaseConstraint should be NULL)
   AttributePtr     myDraggedPoint; ///< one of the feature points which has been moved