Salome HOME
Task 2.12. New entities: ellipses and arcs of ellipses (issue #3003)
[modules/shaper.git] / src / SketchSolver / PlaneGCSSolver / PlaneGCSSolver_FeatureBuilder.cpp
index a0ffc362f8f68ef8f9426a5c588952f137e7981b..400319aed4bd9804a46ec5c2c118da1d8473c9d7 100644 (file)
@@ -1,16 +1,33 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File:    PlaneGCSSolver_AttributeBuilder.cpp
-// Created: 10 Feb 2017
-// Author:  Artem ZHIDKOV
+// Copyright (C) 2014-2019  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
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
 
 #include <PlaneGCSSolver_FeatureBuilder.h>
-#include <PlaneGCSSolver_EntityWrapper.h>
+#include <PlaneGCSSolver_EdgeWrapper.h>
 #include <PlaneGCSSolver_PointWrapper.h>
 #include <PlaneGCSSolver_ScalarWrapper.h>
+#include <PlaneGCSSolver_BooleanWrapper.h>
+#include <PlaneGCSSolver_Tools.h>
 
 #include <SketchPlugin_Arc.h>
 #include <SketchPlugin_Circle.h>
+#include <SketchPlugin_Ellipse.h>
+#include <SketchPlugin_EllipticArc.h>
 #include <SketchPlugin_IntersectionPoint.h>
 #include <SketchPlugin_Line.h>
 #include <SketchPlugin_Point.h>
@@ -25,8 +42,10 @@ static bool isAttributeApplicable(const std::string& theAttrName,
 static EntityWrapperPtr createLine(const AttributeEntityMap& theAttributes);
 static EntityWrapperPtr createCircle(const AttributeEntityMap& theAttributes);
 static EntityWrapperPtr createArc(const AttributeEntityMap&    theAttributes,
-                                  PlaneGCSSolver_Storage*      theStorage,
-                                  std::list<GCSConstraintPtr>& theArcConstraints);
+                                  PlaneGCSSolver_Storage*      theStorage);
+static EntityWrapperPtr createEllipse(const AttributeEntityMap& theAttributes);
+static EntityWrapperPtr createEllipticArc(const AttributeEntityMap& theAttributes,
+                                          PlaneGCSSolver_Storage*   theStorage);
 
 
 PlaneGCSSolver_FeatureBuilder::PlaneGCSSolver_FeatureBuilder(
@@ -76,7 +95,13 @@ EntityWrapperPtr PlaneGCSSolver_FeatureBuilder::createFeature(FeaturePtr theFeat
     aResult = createCircle(myAttributes);
   // Arc
   else if (aFeatureKind == SketchPlugin_Arc::ID())
-    aResult = createArc(myAttributes, myStorage, myFeatureConstraints);
+    aResult = createArc(myAttributes, myStorage);
+  // Ellipse
+  else if (aFeatureKind == SketchPlugin_Ellipse::ID())
+    aResult = createEllipse(myAttributes);
+  // Arc of ellipse
+  else if (aFeatureKind == SketchPlugin_EllipticArc::ID())
+    aResult = createEllipticArc(myAttributes, myStorage);
   // 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()) {
@@ -117,7 +142,7 @@ EntityWrapperPtr createLine(const AttributeEntityMap& theAttributes)
       aNewLine->p2 = *(aPoint->point());
   }
 
-  return EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(aNewLine));
+  return EntityWrapperPtr(new PlaneGCSSolver_EdgeWrapper(aNewLine));
 }
 
 EntityWrapperPtr createCircle(const AttributeEntityMap& theAttributes)
@@ -138,7 +163,7 @@ EntityWrapperPtr createCircle(const AttributeEntityMap& theAttributes)
     }
   }
 
-  return EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(aNewCircle));
+  return EntityWrapperPtr(new PlaneGCSSolver_EdgeWrapper(aNewCircle));
 }
 
 static double* createParameter(PlaneGCSSolver_Storage* theStorage)
@@ -147,63 +172,120 @@ static double* createParameter(PlaneGCSSolver_Storage* theStorage)
 }
 
 EntityWrapperPtr createArc(const AttributeEntityMap&    theAttributes,
-                           PlaneGCSSolver_Storage*      theStorage,
-                           std::list<GCSConstraintPtr>& theArcConstraints)
+                           PlaneGCSSolver_Storage*      theStorage)
 {
   std::shared_ptr<GCS::Arc> aNewArc(new GCS::Arc);
+  BooleanWrapperPtr isReversed;
 
   // Base attributes of arc (center, start and end points)
   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)
-      continue;
-
-    if (anIt->first->id() == SketchPlugin_Arc::CENTER_ID())
-      aNewArc->center = *(aPoint->point());
-    else if (anIt->first->id() == SketchPlugin_Arc::START_ID())
-      aNewArc->start = *(aPoint->point());
-    else if (anIt->first->id() == SketchPlugin_Arc::END_ID())
-      aNewArc->end = *(aPoint->point());
+    if (aPoint) {
+      if (anIt->first->id() == SketchPlugin_Arc::CENTER_ID())
+        aNewArc->center = *(aPoint->point());
+      else if (anIt->first->id() == SketchPlugin_Arc::START_ID())
+        aNewArc->start = *(aPoint->point());
+      else if (anIt->first->id() == SketchPlugin_Arc::END_ID())
+        aNewArc->end = *(aPoint->point());
+    }
+    else {
+      // reversed flag
+      isReversed = std::dynamic_pointer_cast<PlaneGCSSolver_BooleanWrapper>(anIt->second);
+    }
   }
 
-  // Additional atrtributes of arc necessary for PlaneGCS solver
+  // Additional attributes of arc necessary for PlaneGCS solver
   // (start and end angles, radius)
   aNewArc->startAngle = createParameter(theStorage);
   aNewArc->endAngle   = createParameter(theStorage);
   aNewArc->rad        = createParameter(theStorage);
 
-  static std::shared_ptr<GeomAPI_Dir2d> OX(new GeomAPI_Dir2d(1.0, 0.0));
-  std::shared_ptr<GeomAPI_Pnt2d> aCenter(
-      new GeomAPI_Pnt2d(*aNewArc->center.x, *aNewArc->center.y));
-  std::shared_ptr<GeomAPI_Pnt2d> aStart(
-      new GeomAPI_Pnt2d(*aNewArc->start.x, *aNewArc->start.y));
-
-  *aNewArc->rad = aStart->distance(aCenter);
-
-  std::shared_ptr<GeomAPI_Dir2d> aDir(new GeomAPI_Dir2d(aStart->xy()->decreased(aCenter->xy())));
-  *aNewArc->startAngle = OX->angle(aDir);
-
-  aDir = std::shared_ptr<GeomAPI_Dir2d>(
-      new GeomAPI_Dir2d((*aNewArc->end.x) - aCenter->x(), (*aNewArc->end.y) - aCenter->y()));
-  *aNewArc->endAngle = OX->angle(aDir);
-
-  if (theStorage) {
-    // Additional constaints to fix arc's extra DoF (if the arc is not external):
-    // 1. distances from center till start and end points are equal to radius
-    theArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance(
-        aNewArc->center, aNewArc->start, aNewArc->rad)));
-    theArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance(
-        aNewArc->center, aNewArc->end, aNewArc->rad)));
-    // 2. angles of start and end points should be equal to the arc angles
-    theArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PAngle(
-        aNewArc->center, aNewArc->start, aNewArc->startAngle)));
-    theArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PAngle(
-        aNewArc->center, aNewArc->end, aNewArc->endAngle)));
+  EdgeWrapperPtr anArcWrapper(new PlaneGCSSolver_EdgeWrapper(aNewArc));
+  anArcWrapper->setReversed(isReversed);
+  PlaneGCSSolver_Tools::recalculateArcParameters(anArcWrapper);
+
+  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;
+}
+
+EntityWrapperPtr createEllipticArc(const AttributeEntityMap& theAttributes,
+                                   PlaneGCSSolver_Storage*   theStorage)
+{
+  std::shared_ptr<GCS::ArcOfEllipse> aNewArc(new GCS::ArcOfEllipse);
+
+  BooleanWrapperPtr isReversed;
+  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_EllipticArc::CENTER_ID())
+        aNewArc->center = *(aPoint->point());
+      else if (anIt->first->id() == SketchPlugin_EllipticArc::FIRST_FOCUS_ID())
+        aNewArc->focus1 = *(aPoint->point());
+      else if (anIt->first->id() == SketchPlugin_EllipticArc::START_POINT_ID())
+        aNewArc->start = *(aPoint->point());
+      else if (anIt->first->id() == SketchPlugin_EllipticArc::END_POINT_ID())
+        aNewArc->end = *(aPoint->point());
+      else
+        anAdditionalAttributes[anIt->first->id()] = anIt->second;
+    }
+    else if (anIt->first->id() == SketchPlugin_EllipticArc::MINOR_RADIUS_ID()) {
+      ScalarWrapperPtr aScalar =
+          std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(anIt->second);
+      aNewArc->radmin = aScalar->scalar();
+    }
+    else if (anIt->first->id() == SketchPlugin_EllipticArc::REVERSED_ID())
+      isReversed = std::dynamic_pointer_cast<PlaneGCSSolver_BooleanWrapper>(anIt->second);
+    else
+      anAdditionalAttributes[anIt->first->id()] = anIt->second;
   }
 
-  return EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(aNewArc));
+  // Additional attributes of elliptic arc necessary for PlaneGCS solver (start and end angles)
+  aNewArc->startAngle = createParameter(theStorage);
+  aNewArc->endAngle = createParameter(theStorage);
+
+  EdgeWrapperPtr anEllipseWrapper(new PlaneGCSSolver_EdgeWrapper(aNewArc));
+  anEllipseWrapper->setReversed(isReversed);
+  anEllipseWrapper->setAdditionalAttributes(anAdditionalAttributes);
+  PlaneGCSSolver_Tools::recalculateArcParameters(anEllipseWrapper);
+
+  return anEllipseWrapper;
 }
 
 bool isAttributeApplicable(const std::string& theAttrName, const std::string& theOwnerName)
@@ -211,7 +293,8 @@ bool isAttributeApplicable(const std::string& theAttrName, const std::string& th
   if (theOwnerName == SketchPlugin_Arc::ID()) {
     return theAttrName == SketchPlugin_Arc::CENTER_ID() ||
            theAttrName == SketchPlugin_Arc::START_ID() ||
-           theAttrName == SketchPlugin_Arc::END_ID();
+           theAttrName == SketchPlugin_Arc::END_ID() ||
+           theAttrName == SketchPlugin_Arc::REVERSED_ID();
   }
   else if (theOwnerName == SketchPlugin_Circle::ID()) {
     return theAttrName == SketchPlugin_Circle::CENTER_ID() ||
@@ -221,6 +304,31 @@ 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();
+  }
+  else if (theOwnerName == SketchPlugin_EllipticArc::ID()) {
+    return theAttrName == SketchPlugin_EllipticArc::CENTER_ID() ||
+           theAttrName == SketchPlugin_EllipticArc::FIRST_FOCUS_ID() ||
+           theAttrName == SketchPlugin_EllipticArc::SECOND_FOCUS_ID() ||
+           theAttrName == SketchPlugin_EllipticArc::MAJOR_AXIS_START_ID() ||
+           theAttrName == SketchPlugin_EllipticArc::MAJOR_AXIS_END_ID() ||
+           theAttrName == SketchPlugin_EllipticArc::MINOR_AXIS_START_ID() ||
+           theAttrName == SketchPlugin_EllipticArc::MINOR_AXIS_END_ID() ||
+           theAttrName == SketchPlugin_EllipticArc::MAJOR_RADIUS_ID() ||
+           theAttrName == SketchPlugin_EllipticArc::MINOR_RADIUS_ID() ||
+           theAttrName == SketchPlugin_EllipticArc::START_POINT_ID() ||
+           theAttrName == SketchPlugin_EllipticArc::END_POINT_ID() ||
+           theAttrName == SketchPlugin_EllipticArc::REVERSED_ID();
+  }
 
   // suppose that all remaining features are points
   return theAttrName == SketchPlugin_Point::COORD_ID();