Salome HOME
Task #3230: Sketcher: create a curve passing through selected points or vertices...
[modules/shaper.git] / src / SketchSolver / PlaneGCSSolver / PlaneGCSSolver_FeatureBuilder.cpp
index 376bab37f6f266909a94645cd3e89b84d65c03e2..6499d1811e79e4d88fd64376320bca34644e576d 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+// Copyright (C) 2014-2020  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
 //
 // 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
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
-// See http://www.salome-platform.org/ or
-// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 
 #include <PlaneGCSSolver_FeatureBuilder.h>
+#include <PlaneGCSSolver_BooleanWrapper.h>
 #include <PlaneGCSSolver_EdgeWrapper.h>
+#include <PlaneGCSSolver_GeoExtensions.h>
 #include <PlaneGCSSolver_PointWrapper.h>
+#include <PlaneGCSSolver_PointArrayWrapper.h>
 #include <PlaneGCSSolver_ScalarWrapper.h>
+#include <PlaneGCSSolver_ScalarArrayWrapper.h>
+#include <PlaneGCSSolver_Tools.h>
 
 #include <SketchPlugin_Arc.h>
+#include <SketchPlugin_BSpline.h>
+#include <SketchPlugin_BSplinePeriodic.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>
 #include <GeomAPI_Pnt2d.h>
 #include <GeomAPI_XY.h>
 
-static bool isAttributeApplicable(const std::string& theAttrName,
-                                  const std::string& theOwnerName);
 
 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);
+static EntityWrapperPtr createEllipticArc(const AttributeEntityMap& theAttributes,
+                                          PlaneGCSSolver_Storage*   theStorage);
+template <typename TYPE>
+static EntityWrapperPtr createBSpline(const AttributeEntityMap& theAttributes);
 
 
 PlaneGCSSolver_FeatureBuilder::PlaneGCSSolver_FeatureBuilder(
@@ -58,7 +69,7 @@ EntityWrapperPtr PlaneGCSSolver_FeatureBuilder::createAttribute(
 {
   FeaturePtr anOwner = ModelAPI_Feature::feature(theAttribute->owner());
   EntityWrapperPtr anAttr;
-  if (isAttributeApplicable(theAttribute->id(), anOwner->getKind()))
+  if (PlaneGCSSolver_Tools::isAttributeApplicable(theAttribute->id(), anOwner->getKind()))
     anAttr = PlaneGCSSolver_AttributeBuilder::createAttribute(theAttribute);
   if (anAttr)
     myAttributes[theAttribute] = anAttr;
@@ -90,6 +101,17 @@ 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);
+  // Arc of ellipse
+  else if (aFeatureKind == SketchPlugin_EllipticArc::ID())
+    aResult = createEllipticArc(myAttributes, myStorage);
+  // B-spline curve
+  else if (aFeatureKind == SketchPlugin_BSpline::ID())
+    aResult = createBSpline<SketchPlugin_BSpline>(myAttributes);
+  else if (aFeatureKind == SketchPlugin_BSplinePeriodic::ID())
+    aResult = createBSpline<SketchPlugin_BSplinePeriodic>(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()) {
@@ -163,63 +185,170 @@ EntityWrapperPtr createArc(const AttributeEntityMap&    theAttributes,
                            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));
+  EdgeWrapperPtr anArcWrapper(new PlaneGCSSolver_EdgeWrapper(aNewArc));
+  anArcWrapper->setReversed(isReversed);
+  PlaneGCSSolver_Tools::recalculateArcParameters(anArcWrapper);
+
+  return anArcWrapper;
+}
 
-  *aNewArc->rad = aStart->distance(aCenter);
+EntityWrapperPtr createEllipse(const AttributeEntityMap& theAttributes)
+{
+  std::shared_ptr<GCS::Ellipse> aNewEllipse(new GCS::Ellipse);
 
-  std::shared_ptr<GeomAPI_Dir2d> aDir(new GeomAPI_Dir2d(aStart->xy()->decreased(aCenter->xy())));
-  *aNewArc->startAngle = OX->angle(aDir);
+  std::map<std::string, EntityWrapperPtr> anAdditionalAttributes;
 
-  aDir = std::shared_ptr<GeomAPI_Dir2d>(
-      new GeomAPI_Dir2d((*aNewArc->end.x) - aCenter->x(), (*aNewArc->end.y) - aCenter->y()));
-  *aNewArc->endAngle = OX->angle(aDir);
+  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;
+  }
 
-  return EntityWrapperPtr(new PlaneGCSSolver_EdgeWrapper(aNewArc));
+  EntityWrapperPtr anEllipseWrapper(new PlaneGCSSolver_EdgeWrapper(aNewEllipse));
+  anEllipseWrapper->setAdditionalAttributes(anAdditionalAttributes);
+  return anEllipseWrapper;
 }
 
-bool isAttributeApplicable(const std::string& theAttrName, const std::string& theOwnerName)
+EntityWrapperPtr createEllipticArc(const AttributeEntityMap& theAttributes,
+                                   PlaneGCSSolver_Storage*   theStorage)
 {
-  if (theOwnerName == SketchPlugin_Arc::ID()) {
-    return theAttrName == SketchPlugin_Arc::CENTER_ID() ||
-           theAttrName == SketchPlugin_Arc::START_ID() ||
-           theAttrName == SketchPlugin_Arc::END_ID();
-  }
-  else if (theOwnerName == SketchPlugin_Circle::ID()) {
-    return theAttrName == SketchPlugin_Circle::CENTER_ID() ||
-           theAttrName == SketchPlugin_Circle::RADIUS_ID();
+  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;
   }
-  else if (theOwnerName == SketchPlugin_Line::ID()) {
-    return theAttrName == SketchPlugin_Line::START_ID() ||
-           theAttrName == SketchPlugin_Line::END_ID();
+
+  // 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;
+}
+
+template <typename TYPE>
+EntityWrapperPtr createBSpline(const AttributeEntityMap& theAttributes)
+{
+  std::shared_ptr<GCS::BSplineImpl> aNewSpline(new GCS::BSplineImpl);
+
+  aNewSpline->degree = 3;
+  aNewSpline->periodic = std::is_same<TYPE, SketchPlugin_BSplinePeriodic>();
+
+  std::map<std::string, EntityWrapperPtr> anAdditionalAttributes;
+
+  AttributeEntityMap::const_iterator anIt = theAttributes.begin();
+  for (; anIt != theAttributes.end(); ++anIt) {
+    const std::string& anAttrID = anIt->first->id();
+    if (anAttrID == TYPE::POLES_ID()) {
+      PointArrayWrapperPtr anArray =
+          std::dynamic_pointer_cast<PlaneGCSSolver_PointArrayWrapper>(anIt->second);
+
+      int aSize = anArray->size();
+      aNewSpline->poles.reserve(aSize);
+      for (int anIndex = 0; anIndex < aSize; ++anIndex)
+        aNewSpline->poles.push_back(*anArray->value(anIndex)->point());
+
+      aNewSpline->start = aNewSpline->poles.front();
+      aNewSpline->end = aNewSpline->poles.back();
+    }
+    else if (anAttrID == TYPE::DEGREE_ID()) {
+      ScalarWrapperPtr aScalar =
+          std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(anIt->second);
+      aNewSpline->degree = (int)aScalar->value();
+    }
+    else if (anAttrID == SketchPlugin_BSpline::START_ID() ||
+             anAttrID == SketchPlugin_BSpline::END_ID()) {
+      anAdditionalAttributes[anAttrID] = anIt->second;
+    }
+    else {
+      ScalarArrayWrapperPtr anArray =
+          std::dynamic_pointer_cast<PlaneGCSSolver_ScalarArrayWrapper>(anIt->second);
+      if (anAttrID == TYPE::WEIGHTS_ID())
+        aNewSpline->weights = anArray->array();
+      else if (anAttrID == TYPE::KNOTS_ID())
+        aNewSpline->knots = anArray->array();
+      else if (anAttrID == TYPE::MULTS_ID()) {
+        const GCS::VEC_pD& aValues = anArray->array();
+        aNewSpline->mult.reserve(aValues.size());
+        for (GCS::VEC_pD::const_iterator anIt = aValues.begin(); anIt != aValues.end(); ++anIt)
+          aNewSpline->mult.push_back((int)(**anIt));
+      }
+    }
   }
 
-  // suppose that all remaining features are points
-  return theAttrName == SketchPlugin_Point::COORD_ID();
+  EdgeWrapperPtr aWrapper(new PlaneGCSSolver_EdgeWrapper(aNewSpline));
+  aWrapper->setAdditionalAttributes(anAdditionalAttributes);
+  return aWrapper;
 }