Salome HOME
oubli
[modules/shaper.git] / src / SketchAPI / SketchAPI_BSpline.cpp
index 9023d703bf3ccbd65b8551cc8731226b6bebed3c..971591e0a30ded40c271661de727a0c8f3f2f77f 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2020  CEA/DEN, EDF R&D
+// Copyright (C) 2019-2022  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
 
 #include <GeomAlgoAPI_EdgeBuilder.h>
 
+#include <Locale_Convert.h>
+
 #include <ModelHighAPI_Double.h>
 #include <ModelHighAPI_Dumper.h>
 #include <ModelHighAPI_Integer.h>
 #include <ModelHighAPI_Selection.h>
 #include <ModelHighAPI_Tools.h>
 
+#include <ModelAPI_Tools.h>
+
 #include <SketchPlugin_ConstraintCoincidenceInternal.h>
 #include <SketchPlugin_Line.h>
 #include <SketchPlugin_Point.h>
@@ -44,47 +48,11 @@ SketchAPI_BSpline::SketchAPI_BSpline(const std::shared_ptr<ModelAPI_Feature> & t
 }
 
 SketchAPI_BSpline::SketchAPI_BSpline(const std::shared_ptr<ModelAPI_Feature>& theFeature,
-                                     const std::list<GeomPnt2dPtr>& thePoles,
-                                     const std::list<ModelHighAPI_Double>& theWeights)
+                                     bool theInitialize)
   : SketchAPI_SketchEntity(theFeature)
 {
-  if (initialize()) {
-    setByDegreePolesAndWeights(ModelHighAPI_Integer(-1), thePoles, theWeights);
-  }
-}
-
-SketchAPI_BSpline::SketchAPI_BSpline(const std::shared_ptr<ModelAPI_Feature>& theFeature,
-                                     const int theDegree,
-                                     const std::list<GeomPnt2dPtr>& thePoles,
-                                     const std::list<ModelHighAPI_Double>& theWeights,
-                                     const std::list<ModelHighAPI_Double>& theKnots,
-                                     const std::list<ModelHighAPI_Integer>& theMults)
-  : SketchAPI_SketchEntity(theFeature)
-{
-  if (initialize()) {
-    if (theKnots.empty() || theMults.empty())
-      setByDegreePolesAndWeights(theDegree, thePoles, theWeights);
-    else
-      setByParameters(theDegree, thePoles, theWeights, theKnots, theMults);
-  }
-}
-
-SketchAPI_BSpline::SketchAPI_BSpline(const std::shared_ptr<ModelAPI_Feature>& theFeature,
-                                     const ModelHighAPI_Selection& theExternal)
-  : SketchAPI_SketchEntity(theFeature)
-{
-  if (initialize()) {
-    setByExternal(theExternal);
-  }
-}
-
-SketchAPI_BSpline::SketchAPI_BSpline(const std::shared_ptr<ModelAPI_Feature>& theFeature,
-                                     const std::string& theExternalName)
-  : SketchAPI_SketchEntity(theFeature)
-{
-  if (initialize()) {
-    setByExternalName(theExternalName);
-  }
+  if (theInitialize)
+    initialize();
 }
 
 SketchAPI_BSpline::~SketchAPI_BSpline()
@@ -133,7 +101,8 @@ void SketchAPI_BSpline::setByParameters(const ModelHighAPI_Integer& theDegree,
   fillAttribute(theKnots, knots());
   fillAttribute(theMults, multiplicities());
 
-  setStartAndEndPoints();
+  if (feature()->getKind() != SketchPlugin_BSplinePeriodic::ID())
+    setStartAndEndPoints();
   execute();
 }
 
@@ -149,12 +118,6 @@ void SketchAPI_BSpline::setByExternal(const ModelHighAPI_Selection & theExternal
   execute();
 }
 
-void SketchAPI_BSpline::setByExternalName(const std::string & theExternalName)
-{
-  fillAttribute(ModelHighAPI_Selection("EDGE", theExternalName), external());
-  execute();
-}
-
 static CompositeFeaturePtr sketchForFeature(FeaturePtr theFeature)
 {
   const std::set<AttributePtr>& aRefs = theFeature->data()->refsToMe();
@@ -193,8 +156,9 @@ static void createPole(const CompositeFeaturePtr& theSketch,
   aPointFeature->reference(SketchPlugin_Point::PARENT_ID())->setValue(theBSpline);
   aPointFeature->execute();
 
-  std::ostringstream aName;
-  aName << theBSpline->name() << "_" << thePoles->id() << "_" << thePoleIndex;
+  std::wostringstream aName;
+  aName << theBSpline->name() << "_" << Locale::Convert::toWString(thePoles->id())
+                              << "_" << thePoleIndex;
   aPointFeature->data()->setName(aName.str());
   aPointFeature->lastResult()->data()->setName(aName.str());
 
@@ -212,8 +176,9 @@ static void createSegment(const CompositeFeaturePtr& theSketch,
                           const bool theAuxiliary,
                           std::list<FeaturePtr>& theEntities)
 {
+  int aEndPoleIndex = (theStartPoleIndex + 1) % thePoles->size();
   GeomPnt2dPtr aStartPoint = thePoles->pnt(theStartPoleIndex);
-  GeomPnt2dPtr aEndPoint = thePoles->pnt(theStartPoleIndex + 1);
+  GeomPnt2dPtr aEndPoint = thePoles->pnt(aEndPoleIndex);
 
   FeaturePtr aLineFeature = theSketch->addFeature(SketchPlugin_Line::ID());
   AttributePoint2DPtr aLineStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
@@ -225,15 +190,15 @@ static void createSegment(const CompositeFeaturePtr& theSketch,
   aLineFeature->reference(SketchPlugin_Point::PARENT_ID())->setValue(theBSpline);
   aLineFeature->execute();
 
-  std::ostringstream aName;
-  aName << theBSpline->name() << "_segment_" << theStartPoleIndex << "_" << theStartPoleIndex + 1;
+  std::wostringstream aName;
+  aName << theBSpline->name() << "_segment_" << theStartPoleIndex << "_" << aEndPoleIndex;
   aLineFeature->data()->setName(aName.str());
   aLineFeature->lastResult()->data()->setName(aName.str());
 
   aLineFeature->boolean(SketchPlugin_Line::AUXILIARY_ID())->setValue(theAuxiliary);
 
   createInternalConstraint(theSketch, aLineStart, thePoles, theStartPoleIndex);
-  createInternalConstraint(theSketch, aLineEnd, thePoles, theStartPoleIndex + 1);
+  createInternalConstraint(theSketch, aLineEnd, thePoles, aEndPoleIndex);
 
   theEntities.push_back(aLineFeature);
 }
@@ -301,10 +266,13 @@ void SketchAPI_BSpline::getDefaultParameters(
          it != theWeights.end(); ++it)
       aWeights.push_back(it->value());
 
+    bool isPeriodic = feature()->getKind() == SketchPlugin_BSplinePeriodic::ID();
     if (theDegree.intValue() < 0)
-      aBSplineCurve.reset(new GeomAPI_BSpline2d(thePoles, aWeights));
-    else
-      aBSplineCurve.reset(new GeomAPI_BSpline2d(theDegree.intValue(), thePoles, aWeights));
+      aBSplineCurve.reset(new GeomAPI_BSpline2d(thePoles, aWeights, isPeriodic));
+    else {
+      aBSplineCurve.reset(new GeomAPI_BSpline2d(theDegree.intValue(), thePoles, aWeights,
+                                                std::list<double>(), std::list<int>(), isPeriodic));
+    }
   }
   catch (...) {
     // cannot build a B-spline curve
@@ -441,12 +409,14 @@ void SketchAPI_BSpline::dump(ModelHighAPI_Dumper& theDumper) const
 
     theDumper << aBase << " = " << aSketchName << ".addSpline(";
     if (!isDefaultDegree)
-      theDumper << degree() << ", ";
-    theDumper << poles();
+      theDumper << "degree = " << degree() << ", ";
+    theDumper << "poles = " << poles();
     if (!isDefaultWeights)
-      theDumper << ", " << weights();
+      theDumper << ", weights = " << weights();
     if (!isDefaultKnotsMults)
-      theDumper << ", " << knots() << ", " << multiplicities();
+      theDumper << ", knots = " << knots() << ", multiplicities = " << multiplicities();
+    if (aBase->getKind() == SketchPlugin_BSplinePeriodic::ID())
+      theDumper << ", periodic = True";
     theDumper << ")" << std::endl;
   }
   // dump "auxiliary" flag if necessary
@@ -507,3 +477,52 @@ void SketchAPI_BSpline::dumpControlPolygon(
     dumpList(theDumper, "auxiliary", anAuxiliary);
   theDumper << ")" << std::endl;
 }
+
+static void setCoordinates(const FeaturePtr& theFeature,
+                           const std::string& theAttrName,
+                           const GeomPnt2dPtr& theCoordinates)
+{
+  AttributePoint2DPtr aPoint =
+      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theFeature->attribute(theAttrName));
+  aPoint->setValue(theCoordinates);
+}
+
+bool SketchAPI_BSpline::insertPole(const int theIndex,
+                                   const GeomPnt2dPtr& theCoordinates,
+                                   const ModelHighAPI_Double& theWeight)
+{
+  std::ostringstream anActionName;
+  anActionName << SketchPlugin_BSplineBase::ADD_POLE_ACTION_ID() << "#" << theIndex;
+  bool isOk = feature()->customAction(anActionName.str());
+  if (isOk) {
+    int anIndex = theIndex + 1;
+    if (feature()->getKind() == SketchPlugin_BSpline::ID() && anIndex + 1 >= poles()->size())
+      anIndex = poles()->size() - 2;
+    // initialize coordinates and weight of new pole
+    poles()->setPnt(anIndex, theCoordinates);
+    weights()->setValue(anIndex, theWeight.value());
+
+    // update coordinates of points of control polygon
+    std::map<int, FeaturePtr> aPoints, aLines;
+    collectAuxiliaryFeatures(feature(), aPoints, aLines);
+    std::map<int, FeaturePtr>::iterator aFound = aPoints.find(anIndex);
+    if (aFound != aPoints.end())
+      setCoordinates(aFound->second, SketchPlugin_Point::COORD_ID(), theCoordinates);
+    aFound = aLines.find(anIndex);
+    if (aFound != aLines.end())
+      setCoordinates(aFound->second, SketchPlugin_Line::START_ID(), theCoordinates);
+    aFound = aLines.find(anIndex - 1);
+    if (aFound != aLines.end())
+      setCoordinates(aFound->second, SketchPlugin_Line::END_ID(), theCoordinates);
+  }
+  return isOk;
+}
+
+
+
+// =================================================================================================
+SketchAPI_BSplinePeriodic::SketchAPI_BSplinePeriodic(const FeaturePtr& theFeature)
+  : SketchAPI_BSpline(theFeature, false)
+{
+  initialize();
+}