Salome HOME
bos #24513 Dealing with conflicting constraints
[modules/shaper.git] / src / SketchPlugin / SketchPlugin_MacroEllipse.cpp
index 2effeb197a8835334e22abcff9225bc0d75ab7fe..d11764a6004e94ca8467d9ea9e4fe56e24007464 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2017-2019  CEA/DEN, EDF R&D
+// Copyright (C) 2017-2021  CEA/DEN, EDF R&D
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
@@ -44,6 +44,7 @@
 #include <GeomAlgoAPI_EdgeBuilder.h>
 #include <GeomAlgoAPI_PointBuilder.h>
 
+static const double TOLERANCE = 1.e-7;
 
 SketchPlugin_MacroEllipse::SketchPlugin_MacroEllipse()
 : SketchPlugin_SketchEntity(),
@@ -57,22 +58,34 @@ void SketchPlugin_MacroEllipse::initAttributes()
   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(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(PASSED_POINT_ID(), GeomDataAPI_Point2D::typeId());
   data()->addAttribute(PASSED_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
 
+  data()->addAttribute(MAJOR_AXIS_START_ID(), GeomDataAPI_Point2D::typeId());
+  data()->addAttribute(MAJOR_AXIS_START_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
+  data()->addAttribute(MAJOR_AXIS_END_ID(), GeomDataAPI_Point2D::typeId());
+  data()->addAttribute(MAJOR_AXIS_END_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
+  data()->addAttribute(PASSED_POINT_1_ID(), GeomDataAPI_Point2D::typeId());
+  data()->addAttribute(PASSED_POINT_1_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
+
   data()->addAttribute(MAJOR_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
   data()->addAttribute(MINOR_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
   data()->addAttribute(AUXILIARY_ID(), ModelAPI_AttributeBoolean::typeId());
 
   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(), CENTER_POINT_REF_ID());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(
+      getKind(), MAJOR_AXIS_POINT_REF_ID());
   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PASSED_POINT_REF_ID());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(
+      getKind(), MAJOR_AXIS_START_REF_ID());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), MAJOR_AXIS_END_REF_ID());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PASSED_POINT_1_REF_ID());
   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EDIT_ELLIPSE_TYPE());
 }
 
@@ -100,12 +113,25 @@ void SketchPlugin_MacroEllipse::execute()
 void SketchPlugin_MacroEllipse::attributeChanged(const std::string& theID)
 {
   static const int NB_POINTS = 3;
-  std::string aPointAttrName[NB_POINTS] = { FIRST_POINT_ID(),
-                                            SECOND_POINT_ID(),
-                                            PASSED_POINT_ID() };
-  std::string aPointRefName[NB_POINTS] = { FIRST_POINT_REF_ID(),
-                                           SECOND_POINT_REF_ID(),
-                                           PASSED_POINT_REF_ID() };
+  std::string aPointAttrName[NB_POINTS];
+  std::string aPointRefName[NB_POINTS];
+  if (string(ELLIPSE_TYPE())->value() == ELLIPSE_TYPE_BY_CENTER_AXIS_POINT()) {
+    aPointAttrName[0] = CENTER_POINT_ID();
+    aPointAttrName[1] = MAJOR_AXIS_POINT_ID();
+    aPointAttrName[2] = PASSED_POINT_ID();
+    aPointRefName[0] = CENTER_POINT_REF_ID();
+    aPointRefName[1] = MAJOR_AXIS_POINT_REF_ID();
+    aPointRefName[2] = PASSED_POINT_REF_ID();
+  } else if (string(ELLIPSE_TYPE())->value() == ELLIPSE_TYPE_BY_AXIS_AND_POINT()) {
+    aPointAttrName[0] = MAJOR_AXIS_START_ID();
+    aPointAttrName[1] = MAJOR_AXIS_END_ID();
+    aPointAttrName[2] = PASSED_POINT_1_ID();
+    aPointRefName[0] = MAJOR_AXIS_START_REF_ID();
+    aPointRefName[1] = MAJOR_AXIS_END_REF_ID();
+    aPointRefName[2] = PASSED_POINT_1_REF_ID();
+  }
+  else
+    return;
 
   // type of ellipse switched, thus reset all attributes
   if (theID == ELLIPSE_TYPE()) {
@@ -144,6 +170,9 @@ void SketchPlugin_MacroEllipse::attributeChanged(const std::string& theID)
       anEllipsePoints[0]->setY(0.5 * (anEllipsePoints[0]->y() + anEllipsePoints[1]->y()));
     }
 
+    if (anEllipsePoints[0]->distance(anEllipsePoints[1]) < TOLERANCE)
+      return; // ellipse is not valid
+
     std::shared_ptr<GeomAPI_Ellipse2d> anEllipse;
     if (aNbInitialized == 2) {
       GeomDir2dPtr aXDir(new GeomAPI_Dir2d(anEllipsePoints[1]->x() - anEllipsePoints[0]->x(),
@@ -195,8 +224,12 @@ std::string SketchPlugin_MacroEllipse::processEvent(
     std::shared_ptr<GeomAPI_Pnt2d> aClickedPoint = aReentrantMessage->clickedPoint();
 
     if (aClickedPoint && (anObject || anAttribute)) {
-      aFilledAttributeName = FIRST_POINT_ID();
-      std::string aReferenceAttributeName = FIRST_POINT_REF_ID();
+      aFilledAttributeName = CENTER_POINT_ID();
+      std::string aReferenceAttributeName = CENTER_POINT_REF_ID();
+      if (anEllipseType == ELLIPSE_TYPE_BY_AXIS_AND_POINT()) {
+        aFilledAttributeName = MAJOR_AXIS_START_ID();
+        aReferenceAttributeName = MAJOR_AXIS_START_REF_ID();
+      }
 
       // fill 2d point attribute
       AttributePoint2DPtr aPointAttr =
@@ -208,7 +241,7 @@ 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() == FIRST_POINT_ID())
+          if (aCreatedFeature && anAttribute->id() == CENTER_POINT_ID())
             anAttribute = aCreatedFeature->attribute(
                 anEllipseType == ELLIPSE_TYPE_BY_CENTER_AXIS_POINT() ?
                 SketchPlugin_Ellipse::CENTER_ID() :
@@ -237,16 +270,19 @@ void SketchPlugin_MacroEllipse::constraintsForEllipseByCenterAxisAndPassed(
   static const bool isTangencyApplicable = false;
   // Create constraints.
   SketchPlugin_Tools::createCoincidenceOrTangency(
-      this, FIRST_POINT_REF_ID(),
+      this, CENTER_POINT_REF_ID(),
       theEllipseFeature->attribute(SketchPlugin_Ellipse::CENTER_ID()),
       ObjectPtr(), isTangencyApplicable);
   SketchPlugin_Tools::createCoincidenceOrTangency(
-      this, SECOND_POINT_REF_ID(),
+      this, MAJOR_AXIS_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);
+  // make coincidence only if PASSED_POINT_REF_ID() refers a point but not an object
+  if (!refattr(PASSED_POINT_REF_ID())->isObject()) {
+    SketchPlugin_Tools::createCoincidenceOrTangency(
+        this, PASSED_POINT_REF_ID(), AttributePtr(),
+        theEllipseFeature->lastResult(), isTangencyApplicable);
+  }
 }
 
 void SketchPlugin_MacroEllipse::constraintsForEllipseByMajoxAxisAndPassed(
@@ -256,16 +292,19 @@ void SketchPlugin_MacroEllipse::constraintsForEllipseByMajoxAxisAndPassed(
   static const bool isTangencyApplicable = false;
   // Create constraints.
   SketchPlugin_Tools::createCoincidenceOrTangency(
-      this, FIRST_POINT_REF_ID(),
+      this, MAJOR_AXIS_START_REF_ID(),
       theEllipseFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_START_ID()),
       ObjectPtr(), isTangencyApplicable);
   SketchPlugin_Tools::createCoincidenceOrTangency(
-      this, SECOND_POINT_REF_ID(),
+      this, MAJOR_AXIS_END_REF_ID(),
       theEllipseFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_END_ID()),
       ObjectPtr(), isTangencyApplicable);
-  SketchPlugin_Tools::createCoincidenceOrTangency(
-      this, PASSED_POINT_REF_ID(), AttributePtr(),
-      theEllipseFeature->lastResult(), isTangencyApplicable);
+  // make coincidence only if PASSED_POINT_REF_ID() refers a point but not an object
+  if (!refattr(PASSED_POINT_1_REF_ID())->isObject()) {
+    SketchPlugin_Tools::createCoincidenceOrTangency(
+        this, PASSED_POINT_1_REF_ID(), AttributePtr(),
+        theEllipseFeature->lastResult(), isTangencyApplicable);
+  }
 }
 
 FeaturePtr SketchPlugin_MacroEllipse::createEllipseFeature()
@@ -289,63 +328,31 @@ FeaturePtr SketchPlugin_MacroEllipse::createEllipseFeature()
   aEllipseFeature->execute();
 
   // create auxiliary points
-  createAuxiliaryPoint(aEllipseFeature->attribute(SketchPlugin_Ellipse::FIRST_FOCUS_ID()));
-  createAuxiliaryPoint(aEllipseFeature->attribute(SketchPlugin_Ellipse::SECOND_FOCUS_ID()));
-  createAuxiliaryPoint(aEllipseFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_START_ID()));
-  createAuxiliaryPoint(aEllipseFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_END_ID()));
-  createAuxiliaryPoint(aEllipseFeature->attribute(SketchPlugin_Ellipse::MINOR_AXIS_START_ID()));
-  createAuxiliaryPoint(aEllipseFeature->attribute(SketchPlugin_Ellipse::MINOR_AXIS_END_ID()));
+  SketchPlugin_Tools::createAuxiliaryPointOnEllipse(
+      aEllipseFeature, SketchPlugin_Ellipse::CENTER_ID());
+  SketchPlugin_Tools::createAuxiliaryPointOnEllipse(
+      aEllipseFeature, SketchPlugin_Ellipse::FIRST_FOCUS_ID());
+  SketchPlugin_Tools::createAuxiliaryPointOnEllipse(
+      aEllipseFeature, SketchPlugin_Ellipse::SECOND_FOCUS_ID());
+  SketchPlugin_Tools::createAuxiliaryPointOnEllipse(
+      aEllipseFeature, SketchPlugin_Ellipse::MAJOR_AXIS_START_ID());
+  SketchPlugin_Tools::createAuxiliaryPointOnEllipse(
+      aEllipseFeature, SketchPlugin_Ellipse::MAJOR_AXIS_END_ID());
+  SketchPlugin_Tools::createAuxiliaryPointOnEllipse(
+      aEllipseFeature, SketchPlugin_Ellipse::MINOR_AXIS_START_ID());
+  SketchPlugin_Tools::createAuxiliaryPointOnEllipse(
+      aEllipseFeature, SketchPlugin_Ellipse::MINOR_AXIS_END_ID());
   // create auxiliary axes
-  createAuxiliaryAxis(aEllipseFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_START_ID()),
-                      aEllipseFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_END_ID()));
-  createAuxiliaryAxis(aEllipseFeature->attribute(SketchPlugin_Ellipse::MINOR_AXIS_START_ID()),
-                      aEllipseFeature->attribute(SketchPlugin_Ellipse::MINOR_AXIS_END_ID()));
+  SketchPlugin_Tools::createAuxiliaryAxisOfEllipse(aEllipseFeature,
+                      SketchPlugin_Ellipse::MAJOR_AXIS_START_ID(),
+                      SketchPlugin_Ellipse::MAJOR_AXIS_END_ID());
+  SketchPlugin_Tools::createAuxiliaryAxisOfEllipse(aEllipseFeature,
+                      SketchPlugin_Ellipse::MINOR_AXIS_START_ID(),
+                      SketchPlugin_Ellipse::MINOR_AXIS_END_ID());
 
   return aEllipseFeature;
 }
 
-void SketchPlugin_MacroEllipse::createAuxiliaryPoint(const AttributePtr& theEllipsePoint)
-{
-  FeaturePtr aPointFeature = sketch()->addFeature(SketchPlugin_Point::ID());
-  aPointFeature->boolean(SketchPlugin_Point::AUXILIARY_ID())->setValue(true);
-
-  AttributePoint2DPtr anElPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theEllipsePoint);
-
-  AttributePoint2DPtr aCoord = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-      aPointFeature->attribute(SketchPlugin_Point::COORD_ID()));
-  aCoord->setValue(anElPoint->x(), anElPoint->y());
-
-  createInternalConstraint(anElPoint, aCoord);
-}
-
-void SketchPlugin_MacroEllipse::createAuxiliaryAxis(const AttributePtr& theStartPoint,
-                                                    const AttributePtr& theEndPoint)
-{
-  FeaturePtr aLineFeature = sketch()->addFeature(SketchPlugin_Line::ID());
-  aLineFeature->boolean(SketchPlugin_Point::AUXILIARY_ID())->setValue(true);
-
-  AttributePoint2DPtr aStartPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theStartPoint);
-  AttributePoint2DPtr aEndPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theEndPoint);
-
-  AttributePoint2DPtr aLineStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-      aLineFeature->attribute(SketchPlugin_Line::START_ID()));
-  aLineStart->setValue(aStartPoint->x(), aStartPoint->y());
-
-  AttributePoint2DPtr aLineEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-      aLineFeature->attribute(SketchPlugin_Line::END_ID()));
-  aLineEnd->setValue(aEndPoint->x(), aEndPoint->y());
-
-  createInternalConstraint(aStartPoint, aLineStart);
-  createInternalConstraint(aEndPoint, aLineEnd);
-}
-
-void SketchPlugin_MacroEllipse::createInternalConstraint(const AttributePtr& thePoint1,
-                                                         const AttributePtr& thePoint2)
-{
-  SketchPlugin_Tools::createConstraintAttrAttr(
-      sketch(), SketchPlugin_ConstraintCoincidenceInternal::ID(), thePoint1, thePoint2);
-}
-
 AISObjectPtr SketchPlugin_MacroEllipse::getAISObject(AISObjectPtr thePrevious)
 {
   SketchPlugin_Sketch* aSketch = sketch();
@@ -377,5 +384,9 @@ AISObjectPtr SketchPlugin_MacroEllipse::getAISObject(AISObjectPtr thePrevious)
   if (!anAIS)
     anAIS.reset(new GeomAPI_AISObject());
   anAIS->createShape(aCompound);
+
+  // Modify attributes
+  SketchPlugin_Tools::customizeFeaturePrs(anAIS, boolean(AUXILIARY_ID())->value());
+
   return anAIS;
 }