Salome HOME
Python API for periodic B-splines and unit-tests for creation and modification.
authorazv <azv@opencascade.com>
Fri, 24 Jan 2020 13:58:18 +0000 (16:58 +0300)
committerazv <azv@opencascade.com>
Mon, 27 Jan 2020 09:51:07 +0000 (12:51 +0300)
19 files changed:
src/SketchAPI/SketchAPI.i
src/SketchAPI/SketchAPI_BSpline.cpp
src/SketchAPI/SketchAPI_BSpline.h
src/SketchAPI/SketchAPI_Projection.cpp
src/SketchAPI/SketchAPI_Sketch.cpp
src/SketchAPI/SketchAPI_Sketch.h
src/SketchAPI/SketchAPI_SketchEntity.cpp
src/SketchPlugin/SketchPlugin_MacroBSpline.cpp
src/SketchPlugin/Test/TestConstraintCoincidenceBSpline.py [new file with mode: 0644]
src/SketchPlugin/Test/TestConstraintTangentBSpline.py
src/SketchPlugin/Test/TestCreateBSpline.py
src/SketchPlugin/Test/TestCreateBSplinePeriodic.py [new file with mode: 0644]
src/SketchPlugin/Test/TestMoveBSpline.py
src/SketchPlugin/Test/TestMoveBSplinePeriodic.py [new file with mode: 0644]
src/SketchPlugin/Test/TestPresentation.py
src/SketchPlugin/Test/TestProjectionBSplinePeriodic.py [new file with mode: 0644]
src/SketchPlugin/Test/TestRemoveBSpline.py
src/SketchPlugin/Test/TestRemoveBSplinePeriodic.py [new file with mode: 0644]
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_AttributeBuilder.cpp

index e2a43e68de85b6548f81e4730f70982d21f717b2..ad38d9c556d450ac0124df660f948462689a5df3 100644 (file)
@@ -49,6 +49,7 @@
 %feature("kwargs") SketchAPI_BSpline::controlPolygon;
 %feature("kwargs") SketchAPI_Ellipse::construction;
 %feature("kwargs") SketchAPI_EllipticArc::construction;
+%feature("kwargs") SketchAPI_Sketch::addSpline;
 %feature("kwargs") SketchAPI_Sketch::setAngle;
 
 // shared pointers
@@ -61,6 +62,7 @@
 %shared_ptr(SketchAPI_EllipticArc)
 %shared_ptr(SketchAPI_MacroEllipticArc)
 %shared_ptr(SketchAPI_BSpline)
+%shared_ptr(SketchAPI_BSplinePeriodic)
 %shared_ptr(SketchAPI_Constraint)
 %shared_ptr(SketchAPI_ConstraintAngle)
 %shared_ptr(SketchAPI_IntersectionPoint)
index 9023d703bf3ccbd65b8551cc8731226b6bebed3c..e804d164b850d38acc37d9bcafd90e6347bbda3e 100644 (file)
@@ -44,47 +44,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 +97,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 +114,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();
@@ -212,8 +171,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>(
@@ -226,14 +186,14 @@ static void createSegment(const CompositeFeaturePtr& theSketch,
   aLineFeature->execute();
 
   std::ostringstream aName;
-  aName << theBSpline->name() << "_segment_" << theStartPoleIndex << "_" << theStartPoleIndex + 1;
+  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 +261,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 +404,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 +472,12 @@ void SketchAPI_BSpline::dumpControlPolygon(
     dumpList(theDumper, "auxiliary", anAuxiliary);
   theDumper << ")" << std::endl;
 }
+
+
+
+// =================================================================================================
+SketchAPI_BSplinePeriodic::SketchAPI_BSplinePeriodic(const FeaturePtr& theFeature)
+  : SketchAPI_BSpline(theFeature, false)
+{
+  initialize();
+}
index a72b2690a3a2640c6a5140faf12776eb5b043841..377a7b65dd0d89c79c2aaa27e81cc503af3c3f3f 100644 (file)
@@ -28,6 +28,7 @@
 #include <ModelAPI_AttributeDoubleArray.h>
 
 #include <SketchPlugin_BSpline.h>
+#include <SketchPlugin_BSplinePeriodic.h>
 
 #include <ModelHighAPI_Double.h>
 #include <ModelHighAPI_Integer.h>
@@ -44,51 +45,26 @@ public:
   SKETCHAPI_EXPORT
   explicit SketchAPI_BSpline(const std::shared_ptr<ModelAPI_Feature>& theFeature);
 
-  /// Constructor with values.
-  SKETCHAPI_EXPORT SketchAPI_BSpline(
-      const std::shared_ptr<ModelAPI_Feature>& theFeature,
-      const std::list<std::shared_ptr<GeomAPI_Pnt2d> >& thePoles,
-      const std::list<ModelHighAPI_Double>& theWeights = std::list<ModelHighAPI_Double>());
-
-  /// Constructor with values.
-  SKETCHAPI_EXPORT SketchAPI_BSpline(
-      const std::shared_ptr<ModelAPI_Feature>& theFeature,
-      const int theDegree,
-      const std::list<std::shared_ptr<GeomAPI_Pnt2d> >& thePoles,
-      const std::list<ModelHighAPI_Double>& theWeights = std::list<ModelHighAPI_Double>(),
-      const std::list<ModelHighAPI_Double>& theKnots = std::list<ModelHighAPI_Double>(),
-      const std::list<ModelHighAPI_Integer>& theMults = std::list<ModelHighAPI_Integer>());
-
-  /// Constructor with external.
-  SKETCHAPI_EXPORT
-  SketchAPI_BSpline(const std::shared_ptr<ModelAPI_Feature>& theFeature,
-                    const ModelHighAPI_Selection& theExternal);
-
-  /// Constructor with external.
-  SKETCHAPI_EXPORT
-  SketchAPI_BSpline(const std::shared_ptr<ModelAPI_Feature>& theFeature,
-                    const std::string& theExternalName);
-
   /// Destructor.
   SKETCHAPI_EXPORT
   virtual ~SketchAPI_BSpline();
 
   INTERFACE_8(SketchPlugin_BSpline::ID(),
-              poles, SketchPlugin_BSpline::POLES_ID(),
+              poles, SketchPlugin_BSplineBase::POLES_ID(),
               GeomDataAPI_Point2DArray, /** B-spline poles */,
-              weights, SketchPlugin_BSpline::WEIGHTS_ID(),
+              weights, SketchPlugin_BSplineBase::WEIGHTS_ID(),
               ModelAPI_AttributeDoubleArray, /** B-spline weights */,
-              knots, SketchPlugin_BSpline::KNOTS_ID(),
+              knots, SketchPlugin_BSplineBase::KNOTS_ID(),
               ModelAPI_AttributeDoubleArray, /** B-spline knots */,
-              multiplicities, SketchPlugin_BSpline::MULTS_ID(),
+              multiplicities, SketchPlugin_BSplineBase::MULTS_ID(),
               ModelAPI_AttributeIntArray, /** Knots multiplicities */,
-              degree, SketchPlugin_BSpline::DEGREE_ID(),
+              degree, SketchPlugin_BSplineBase::DEGREE_ID(),
               ModelAPI_AttributeInteger, /** B-spline degree */,
               startPoint, SketchPlugin_BSpline::START_ID(),
               GeomDataAPI_Point2D, /** First pole of B-spline */,
               endPoint, SketchPlugin_BSpline::END_ID(),
               GeomDataAPI_Point2D, /** Last pole of B-spline */,
-              external, SketchPlugin_BSpline::EXTERNAL_ID(),
+              external, SketchPlugin_BSplineBase::EXTERNAL_ID(),
               ModelAPI_AttributeSelection, /** External */)
 
   /// Set by poles and weights.
@@ -109,10 +85,6 @@ public:
   SKETCHAPI_EXPORT
   void setByExternal(const ModelHighAPI_Selection& theExternal);
 
-  /// Set by external name.
-  SKETCHAPI_EXPORT
-  void setByExternalName(const std::string& theExternalName);
-
   /// Generate list of construction points coincident with B-spline poles
   SKETCHAPI_EXPORT
   std::list<std::shared_ptr<SketchAPI_SketchEntity> > controlPoles(
@@ -129,6 +101,9 @@ public:
   SKETCHAPI_EXPORT
   virtual void dump(ModelHighAPI_Dumper& theDumper) const;
 
+protected:
+  SketchAPI_BSpline(const std::shared_ptr<ModelAPI_Feature>& theFeature, bool theInitialize);
+
 private:
   /// Initialize start and end points of B-spline and apply internal coincidence
   /// constraint to keep them on the corresponding pole.
@@ -156,4 +131,24 @@ private:
 /// Pointer on B-spline object.
 typedef std::shared_ptr<SketchAPI_BSpline> BSplinePtr;
 
+
+
+/// \class SketchAPI_BSplinePeriodic
+/// \ingroup CPPHighAPI
+/// \brief Interface for BSplinePeriodic feature.
+class SketchAPI_BSplinePeriodic : public SketchAPI_BSpline
+{
+public:
+  /// Constructor without values.
+  SKETCHAPI_EXPORT
+  explicit SketchAPI_BSplinePeriodic(const std::shared_ptr<ModelAPI_Feature>& theFeature);
+
+  /// Destructor.
+  SKETCHAPI_EXPORT
+  virtual ~SketchAPI_BSplinePeriodic() {}
+
+  static std::string ID() { return SketchPlugin_BSplinePeriodic::ID(); }
+  virtual std::string getID() { return SketchPlugin_BSplinePeriodic::ID(); }
+};
+
 #endif // SketchAPI_BSpline_H_
index 3e1a3f7898bab4a69781cc66aeba04c2f848a255..aa94fa895e1b89607d0198dafb243b84d94f2ef9 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <SketchPlugin_Line.h>
 #include <SketchPlugin_BSpline.h>
+#include <SketchPlugin_BSplinePeriodic.h>
 #include <SketchPlugin_Circle.h>
 #include <SketchPlugin_Ellipse.h>
 #include <SketchPlugin_EllipticArc.h>
@@ -112,6 +113,8 @@ std::shared_ptr<SketchAPI_SketchEntity> SketchAPI_Projection::createdFeature() c
     anEntity.reset(new SketchAPI_EllipticArc(aProjectedFeature));
   else if (aProjectedFeature->getKind() == SketchPlugin_BSpline::ID())
     anEntity.reset(new SketchAPI_BSpline(aProjectedFeature));
+  else if (aProjectedFeature->getKind() == SketchPlugin_BSplinePeriodic::ID())
+    anEntity.reset(new SketchAPI_BSplinePeriodic(aProjectedFeature));
   else if (aProjectedFeature->getKind() == SketchPlugin_Point::ID())
     anEntity.reset(new SketchAPI_Point(aProjectedFeature));
 
index f64f93fc682f76665cea02b67dc4a809d0c227f3..a93c26e05a1f586beb5f48ff95fd9ec369ea28c7 100644 (file)
@@ -699,37 +699,29 @@ std::shared_ptr<SketchAPI_EllipticArc> SketchAPI_Sketch::addEllipticArc(
 }
 
 //--------------------------------------------------------------------------------------
-std::shared_ptr<SketchAPI_BSpline> SketchAPI_Sketch::addSpline(
-    const std::list<std::shared_ptr<GeomAPI_Pnt2d> >& thePoles,
-    const std::list<ModelHighAPI_Double>& theWeights)
-{
-  FeaturePtr aFeature = compositeFeature()->addFeature(SketchPlugin_BSpline::ID());
-  return BSplinePtr(new SketchAPI_BSpline(aFeature, thePoles, theWeights));
-}
-
-std::shared_ptr<SketchAPI_BSpline> SketchAPI_Sketch::addSpline(
-    const int theDegree,
-    const std::list<std::shared_ptr<GeomAPI_Pnt2d> >& thePoles,
-    const std::list<ModelHighAPI_Double>& theWeights,
-    const std::list<ModelHighAPI_Double>& theKnots,
-    const std::list<ModelHighAPI_Integer>& theMults)
-{
-  FeaturePtr aFeature = compositeFeature()->addFeature(SketchPlugin_BSpline::ID());
-  return BSplinePtr(new SketchAPI_BSpline(aFeature,
-      theDegree, thePoles, theWeights, theKnots, theMults));
-}
 
 std::shared_ptr<SketchAPI_BSpline> SketchAPI_Sketch::addSpline(
-    const ModelHighAPI_Selection & theExternal)
-{
-  FeaturePtr aFeature = compositeFeature()->addFeature(SketchPlugin_BSpline::ID());
-  return BSplinePtr(new SketchAPI_BSpline(aFeature, theExternal));
-}
+    const ModelHighAPI_Selection & external,
+    const int degree,
+    const std::list<std::shared_ptr<GeomAPI_Pnt2d> >& poles,
+    const std::list<ModelHighAPI_Double>& weights,
+    const std::list<ModelHighAPI_Double>& knots,
+    const std::list<ModelHighAPI_Integer>& multiplicities,
+    const bool periodic)
+{
+  FeaturePtr aFeature = compositeFeature()->addFeature(
+    periodic ? SketchPlugin_BSplinePeriodic::ID() : SketchPlugin_BSpline::ID());
+
+  BSplinePtr aBSpline(periodic ? new SketchAPI_BSplinePeriodic(aFeature)
+                               : new SketchAPI_BSpline(aFeature));
+  if (external.variantType() != ModelHighAPI_Selection::VT_Empty)
+    aBSpline->setByExternal(external);
+  else if (knots.empty() || multiplicities.empty())
+    aBSpline->setByDegreePolesAndWeights(degree, poles, weights);
+  else
+    aBSpline->setByParameters(degree, poles, weights, knots, multiplicities);
 
-std::shared_ptr<SketchAPI_BSpline> SketchAPI_Sketch::addSpline(const std::string & theExternalName)
-{
-  FeaturePtr aFeature = compositeFeature()->addFeature(SketchPlugin_BSpline::ID());
-  return BSplinePtr(new SketchAPI_BSpline(aFeature, theExternalName));
+  return aBSpline;
 }
 
 //--------------------------------------------------------------------------------------
@@ -1250,7 +1242,8 @@ static std::shared_ptr<GeomAPI_Pnt2d> middlePoint(const ObjectPtr& theObject,
       aMiddlePoint = pointOnEllipse(aFeature);
     else if (aFeatureKind == SketchPlugin_EllipticArc::ID())
       aMiddlePoint = pointOnEllipse(aFeature, false);
-    else if (aFeatureKind == SketchPlugin_BSpline::ID())
+    else if (aFeatureKind == SketchPlugin_BSpline::ID() ||
+             aFeatureKind == SketchPlugin_BSplinePeriodic::ID())
       aMiddlePoint = middlePointOnBSpline(aFeature, theSketch);
   }
   return aMiddlePoint;
index 4ea404be6dc10a01ddc3b8fc55c09470132da644..ddbb1829186f83da593adb0520b1716aeed821cd 100644 (file)
@@ -30,6 +30,7 @@
 
 #include <ModelHighAPI_Interface.h>
 #include <ModelHighAPI_Macro.h>
+#include <ModelHighAPI_Selection.h>
 //--------------------------------------------------------------------------------------
 class ModelAPI_CompositeFeature;
 class ModelAPI_Object;
@@ -37,7 +38,6 @@ class ModelHighAPI_Double;
 class ModelHighAPI_Integer;
 class ModelHighAPI_RefAttr;
 class ModelHighAPI_Reference;
-class ModelHighAPI_Selection;
 class SketchAPI_Arc;
 class SketchAPI_MacroArc;
 class SketchAPI_Circle;
@@ -328,22 +328,14 @@ public:
   /// Add B-spline
   SKETCHAPI_EXPORT
   std::shared_ptr<SketchAPI_BSpline> addSpline(
-      const std::list<std::shared_ptr<GeomAPI_Pnt2d> >& thePoles,
-      const std::list<ModelHighAPI_Double>& theWeights = std::list<ModelHighAPI_Double>());
-  /// Add B-spline
-  SKETCHAPI_EXPORT
-  std::shared_ptr<SketchAPI_BSpline> addSpline(
-      const int theDegree,
-      const std::list<std::shared_ptr<GeomAPI_Pnt2d> >& thePoles,
-      const std::list<ModelHighAPI_Double>& theWeights = std::list<ModelHighAPI_Double>(),
-      const std::list<ModelHighAPI_Double>& theKnots = std::list<ModelHighAPI_Double>(),
-      const std::list<ModelHighAPI_Integer>& theMults = std::list<ModelHighAPI_Integer>());
-  /// Add B-spline
-  SKETCHAPI_EXPORT
-  std::shared_ptr<SketchAPI_BSpline> addSpline(const ModelHighAPI_Selection & theExternal);
-  /// Add B-spline
-  SKETCHAPI_EXPORT
-  std::shared_ptr<SketchAPI_BSpline> addSpline(const std::string & theExternalName);
+      const ModelHighAPI_Selection & external = ModelHighAPI_Selection(),
+      const int degree = -1,
+      const std::list<std::shared_ptr<GeomAPI_Pnt2d> >& poles =
+                                          std::list<std::shared_ptr<GeomAPI_Pnt2d> >(),
+      const std::list<ModelHighAPI_Double>& weights = std::list<ModelHighAPI_Double>(),
+      const std::list<ModelHighAPI_Double>& knots = std::list<ModelHighAPI_Double>(),
+      const std::list<ModelHighAPI_Integer>& multiplicities = std::list<ModelHighAPI_Integer>(),
+      const bool periodic = false);
 
   /// Add projection
   SKETCHAPI_EXPORT
index d169c52de4216d1433d8e58dafd556484b7c9f1a..fa56e6a5c95e1a46f20955d83e6e024390f3811a 100644 (file)
@@ -107,6 +107,10 @@ SketchAPI_SketchEntity::wrap(const std::list<std::shared_ptr<ModelAPI_Feature> >
       aResult.push_back(std::shared_ptr<SketchAPI_SketchEntity>(new SketchAPI_EllipticArc(*anIt)));
     else if ((*anIt)->getKind() == SketchPlugin_BSpline::ID())
       aResult.push_back(std::shared_ptr<SketchAPI_SketchEntity>(new SketchAPI_BSpline(*anIt)));
+    else if ((*anIt)->getKind() == SketchPlugin_BSplinePeriodic::ID()) {
+      aResult.push_back(
+          std::shared_ptr<SketchAPI_SketchEntity>(new SketchAPI_BSplinePeriodic(*anIt)));
+    }
     else if ((*anIt)->getKind() == SketchPlugin_Point::ID())
       aResult.push_back(std::shared_ptr<SketchAPI_SketchEntity>(new SketchAPI_Point(*anIt)));
     else if ((*anIt)->getKind() == SketchPlugin_IntersectionPoint::ID())
index 5f325dedfd9c55151618b9b839a241f3d6aff70b..a7591e3c5b8a019e994a8e605973b2edebb409fd 100644 (file)
@@ -154,35 +154,31 @@ FeaturePtr SketchPlugin_MacroBSpline::createBSplineFeature()
   FeaturePtr aBSpline = sketch()->addFeature(
       myIsPeriodic ? SketchPlugin_BSplinePeriodic::ID() : SketchPlugin_BSpline::ID());
 
-  aBSpline->integer(myIsPeriodic ? SketchPlugin_BSplinePeriodic::DEGREE_ID()
-                                 : SketchPlugin_BSpline::DEGREE_ID())->setValue(myDegree);
+  aBSpline->integer(SketchPlugin_BSplineBase::DEGREE_ID())->setValue(myDegree);
 
   AttributePoint2DArrayPtr aPoles = std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(
-      aBSpline->attribute(myIsPeriodic ? SketchPlugin_BSplinePeriodic::POLES_ID()
-                                       : SketchPlugin_BSpline::POLES_ID()));
+      aBSpline->attribute(SketchPlugin_BSplineBase::POLES_ID()));
   AttributePoint2DArrayPtr aPolesMacro =
       std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(attribute(POLES_ID()));
   aPoles->assign(aPolesMacro);
 
-  AttributeDoubleArrayPtr aWeights = aBSpline->data()->realArray(
-      myIsPeriodic ? SketchPlugin_BSplinePeriodic::WEIGHTS_ID()
-                   : SketchPlugin_BSpline::WEIGHTS_ID());
+  AttributeDoubleArrayPtr aWeights =
+      aBSpline->data()->realArray(SketchPlugin_BSplineBase::WEIGHTS_ID());
   AttributeDoubleArrayPtr aWeightsMacro = data()->realArray(WEIGHTS_ID());
   int aSize = aWeightsMacro->size();
   aWeights->setSize(aSize);
   for (int index = 0; index < aSize; ++index)
     aWeights->setValue(index, aWeightsMacro->value(index));
 
-  AttributeDoubleArrayPtr aKnots = aBSpline->data()->realArray(
-      myIsPeriodic ? SketchPlugin_BSplinePeriodic::KNOTS_ID() : SketchPlugin_BSpline::KNOTS_ID());
+  AttributeDoubleArrayPtr aKnots =
+      aBSpline->data()->realArray(SketchPlugin_BSplineBase::KNOTS_ID());
   aSize = (int)myKnots.size();
   aKnots->setSize(aSize);
   std::list<double>::iterator aKIt = myKnots.begin();
   for (int index = 0; index < aSize; ++index, ++aKIt)
     aKnots->setValue(index, *aKIt);
 
-  AttributeIntArrayPtr aMults = aBSpline->data()->intArray(
-      myIsPeriodic ? SketchPlugin_BSplinePeriodic::MULTS_ID() : SketchPlugin_BSpline::MULTS_ID());
+  AttributeIntArrayPtr aMults = aBSpline->data()->intArray(SketchPlugin_BSplineBase::MULTS_ID());
   aSize = (int)myMultiplicities.size();
   aMults->setSize(aSize);
   std::list<int>::iterator aMIt = myMultiplicities.begin();
diff --git a/src/SketchPlugin/Test/TestConstraintCoincidenceBSpline.py b/src/SketchPlugin/Test/TestConstraintCoincidenceBSpline.py
new file mode 100644 (file)
index 0000000..80ab412
--- /dev/null
@@ -0,0 +1,176 @@
+# Copyright (C) 2019-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
+# 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
+#
+
+"""
+    Test constraint coincidence applied for B-spline curve and its sub-results
+"""
+
+import unittest
+import math
+
+from salome.shaper import model
+
+from GeomAPI import *
+from SketchAPI import *
+
+__updated__ = "2020-01-21"
+
+class TestCoincidenceBSpline(unittest.TestCase):
+  def setUp(self):
+    model.begin()
+    self.myDocument = model.moduleDocument()
+    self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY"))
+
+    self.myPoles = [GeomAPI_Pnt2d(-10, -30), GeomAPI_Pnt2d(20, -15), GeomAPI_Pnt2d(-10, 0), GeomAPI_Pnt2d(20, 15), GeomAPI_Pnt2d(-10, 30)]
+    self.myWeights = [1, 3, 5, 3, 1]
+    self.mySpline = self.mySketch.addSpline(poles = self.myPoles, weights = self.myWeights)
+    self.myControlPoles = self.mySpline.controlPoles(auxiliary = [0, 1, 2, 3, 4])
+    self.myControlLines = self.mySpline.controlPolygon(auxiliary = [0, 1, 2, 3])
+
+    self.myDOF = len(self.myPoles) * 2
+    self.myOrigin = self.mySketch.addPoint("Origin")
+    self.myOX = self.mySketch.addLine("OX")
+    model.do()
+    self.myExpectFailure = False
+    self.myNbPoints = len(self.myPoles) + 1
+    self.myNbLines = len(self.myPoles)
+    self.myNbBSplines = 1
+    self.myNbInternalConstraints = len(self.myPoles) * 3 - 2
+    self.myNbCoincidences = 1
+
+  def tearDown(self):
+    model.end()
+    if self.myExpectFailure:
+      assert(self.mySketch.solverError() != ""), "PlaneGCS limitation: if you see this message, then PlaneGCS has solved the set of constraints correctly"
+      model.undo()
+    else:
+      self.checkDOF()
+      model.testNbSubFeatures(self.mySketch, "SketchPoint", self.myNbPoints)
+      model.testNbSubFeatures(self.mySketch, "SketchLine", self.myNbLines)
+      model.testNbSubFeatures(self.mySketch, "SketchBSpline", self.myNbBSplines)
+      model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidenceInternal", self.myNbInternalConstraints)
+      model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", self.myNbCoincidences)
+
+
+  def checkDOF(self):
+    self.assertEqual(model.dof(self.mySketch), self.myDOF)
+
+  def setCoincidentWithOrigin(self, thePoint):
+    self.mySketch.setCoincident(thePoint, self.myOrigin.coordinates())
+    self.myDOF -= 2
+    model.do()
+
+  def setCoincidentWithOX(self, thePoint):
+    self.mySketch.setCoincident(thePoint, self.myOX.result())
+    self.myDOF -= 1
+    model.do()
+
+  def assertPoles(self):
+    poles = self.mySpline.poles()
+    assert(poles.size() == len(self.myPoles))
+    for index in range(0, len(self.myPoles)):
+      self.assertPoints(self.myPoles[index], poles.pnt(index))
+
+  def assertPoints(self, thePoint1, thePoint2):
+    self.assertAlmostEqual(thePoint1.x(), thePoint2.x())
+    self.assertAlmostEqual(thePoint1.y(), thePoint2.y())
+
+  def assertPointOnLine(self, thePoint, theLineStart, theLineEnd):
+    vecP = [thePoint.x() - theLineStart.x(), thePoint.y() - theLineStart.y()]
+    vecL = [theLineEnd.x() - theLineStart.x(), theLineEnd.y() - theLineStart.y()]
+    dist = math.fabs(vecP[0] * vecL[1] - vecP[1] * vecL[0]) / math.hypot(vecL[0], vecL[1])
+    self.assertAlmostEqual(dist, 0.0)
+
+  def assertPointOnSpline(self, thePoint, theSpline):
+    point = GeomAPI_Pnt(thePoint.x(), thePoint.y(), 0.0)
+    bspline = GeomAPI_BSpline(GeomAPI_Curve(theSpline.results()[-1].resultSubShapePair()[0].shape()))
+    proj = bspline.project(point)
+    self.assertAlmostEqual(point.distance(proj), 0.0)
+
+
+  def test_origin_equal_start_point(self):
+    """ Test 1. Make start point of B-spline coincident with the Origin
+    """
+    self.setCoincidentWithOrigin(self.mySpline.startPoint())
+    self.myPoles[0].setX(0)
+    self.myPoles[0].setY(0)
+    self.assertPoles()
+
+  def test_origin_equal_end_point(self):
+    """ Test 2. Make end point of B-spline coincident with the Origin
+    """
+    self.setCoincidentWithOrigin(self.mySpline.endPoint())
+    self.myPoles[-1].setX(0)
+    self.myPoles[-1].setY(0)
+    self.assertPoles()
+
+  def test_origin_equal_pole(self):
+    """ Test 3. Make one of B-spline poles coincident with the Origin
+    """
+    self.setCoincidentWithOrigin(SketchAPI_Point(self.myControlPoles[1]).coordinates())
+    self.myPoles[1].setX(0)
+    self.myPoles[1].setY(0)
+    self.assertPoles()
+
+  def test_origin_on_bspline(self):
+    """ Test 4. (expected failure) Make Origin lying on the B-spline curve
+    """
+    self.mySketch.setCoincident(self.mySpline.defaultResult(), self.myOrigin.coordinates())
+    self.myDOF -= 1
+    model.do()
+    self.myExpectFailure = True
+
+  def test_point_on_bspline(self):
+    """ Test 5. Place free point on the B-spline curve
+    """
+    point = self.mySketch.addPoint(1, 0)
+    self.mySketch.setCoincident(self.myOX.defaultResult(), point.coordinates())
+    self.mySketch.setCoincident(self.mySpline.defaultResult(), point.coordinates())
+    model.do()
+    self.myNbPoints += 1
+    self.myNbCoincidences += 1
+    self.assertPointOnSpline(point.coordinates(), self.mySpline)
+
+
+  def test_start_point_on_axis(self):
+    """ Test 6. Make start point of B-spline coincident with the OX
+    """
+    self.setCoincidentWithOX(self.mySpline.startPoint())
+    self.myPoles[0].setY(0)
+    self.assertPoles()
+
+  def test_end_point_on_axis(self):
+    """ Test 7. Make end point of B-spline coincident with the OX
+    """
+    self.setCoincidentWithOX(self.mySpline.endPoint())
+    self.myPoles[-1].setY(0)
+    self.assertPoles()
+
+  def test_pole_on_axis(self):
+    """ Test 8. Make one of B-spline poles coincident with the OX
+    """
+    self.setCoincidentWithOX(SketchAPI_Point(self.myControlPoles[1]).coordinates())
+    self.myPoles[1].setY(0)
+    self.assertPoles()
+
+
+if __name__ == "__main__":
+    test_program = unittest.main(exit=False)
+    assert test_program.result.wasSuccessful(), "Test failed"
+    assert model.checkPythonDump()
index 0937fe247799a1eca086fd13c4d383e2751783b1..c5effe8c1ec226789454ad7db50094b5f688013d 100644 (file)
@@ -39,7 +39,7 @@ class TestTangentBSpline(unittest.TestCase):
     self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY"))
     self.myPoles = [GeomAPI_Pnt2d(-10, -30), GeomAPI_Pnt2d(20, -15), GeomAPI_Pnt2d(-10, 0), GeomAPI_Pnt2d(20, 15), GeomAPI_Pnt2d(-10, 30)]
     self.myWeights = [1, 3, 5, 3, 1]
-    self.mySpline = self.mySketch.addSpline(self.myPoles, self.myWeights)
+    self.mySpline = self.mySketch.addSpline(poles = self.myPoles, weights = self.myWeights)
     self.myControlPoles = self.mySpline.controlPoles(auxiliary = [0, 1, 2, 3, 4])
     self.myControlLines = self.mySpline.controlPolygon(auxiliary = [0, 1, 2, 3])
     model.do()
@@ -188,7 +188,7 @@ class TestTangentBSpline(unittest.TestCase):
   def test_spline_tangent(self):
     """ Test 6. Set tangency between two B-spline curves
     """
-    aSpline = self.mySketch.addSpline([(50, -20), (40, 0), (50, 20)])
+    aSpline = self.mySketch.addSpline(poles = [(50, -20), (40, 0), (50, 20)])
     self.myNbBSplines += 1
     self.myDOF += aSpline.poles().size() * 2
     model.do()
@@ -367,7 +367,7 @@ class TestTangentBSpline(unittest.TestCase):
   def test_spline_tangent_coincident_by_boundaries(self):
     """ Test 15. Set tangency between two B-spline curves coincident with B-spline start point
     """
-    aSpline = self.mySketch.addSpline([(50, -20), (40, 0), (50, 20)])
+    aSpline = self.mySketch.addSpline(poles = [(50, -20), (40, 0), (50, 20)])
     self.myNbBSplines += 1
     self.myDOF += aSpline.poles().size() * 2
     model.do()
@@ -449,7 +449,7 @@ class TestTangentBSpline(unittest.TestCase):
   def test_spline_tangent_coincident_by_aux(self):
     """ Test 19. Set tangency between two B-spline curves coincident with B-spline start point
     """
-    aSpline = self.mySketch.addSpline([(50, -20), (40, 0), (50, 20)])
+    aSpline = self.mySketch.addSpline(poles = [(50, -20), (40, 0), (50, 20)])
     self.myNbBSplines += 1
     self.myDOF += aSpline.poles().size() * 2
     model.do()
index 413c84b44a4efeafcd1247859331418342438629..0aa12ee4510b746a3ff986b56996f58739e0e172 100644 (file)
@@ -57,7 +57,7 @@ class TestBSpline(unittest.TestCase):
   def test_bspline_by_coordinates(self):
     """ Test 1. Create B-spline curve by coordinates of its poles
     """
-    self.mySpline = self.mySketch.addSpline(self.myPolesCoordinates)
+    self.mySpline = self.mySketch.addSpline(poles = self.myPolesCoordinates)
     self.myDOF += len(self.myPolesCoordinates) * 2
     self.myNbSplines += 1
     model.do()
@@ -69,7 +69,7 @@ class TestBSpline(unittest.TestCase):
   def test_bspline_by_poles(self):
     """ Test 2. Create B-spline curve by poles
     """
-    self.mySpline = self.mySketch.addSpline(self.myPoles)
+    self.mySpline = self.mySketch.addSpline(poles = self.myPoles)
     self.myDOF += len(self.myPoles) * 2
     self.myNbSplines += 1
     model.do()
@@ -82,7 +82,7 @@ class TestBSpline(unittest.TestCase):
     """ Test 3. Create B-spline curve by poles and degree
     """
     self.myDegree = 4
-    self.mySpline = self.mySketch.addSpline(self.myDegree, self.myPoles)
+    self.mySpline = self.mySketch.addSpline(degree = self.myDegree, poles = self.myPoles)
     self.myDOF += len(self.myPoles) * 2
     self.myNbSplines += 1
     model.do()
@@ -94,7 +94,7 @@ class TestBSpline(unittest.TestCase):
   def test_bspline_by_poles_and_weights(self):
     """ Test 4. Create B-spline curve by poles and weights
     """
-    self.mySpline = self.mySketch.addSpline(self.myPoles, [1, 2, 3, 2, 1])
+    self.mySpline = self.mySketch.addSpline(poles = self.myPoles, weights = [1, 2, 3, 2, 1])
     self.myDOF += len(self.myPoles) * 2
     self.myNbSplines += 1
     model.do()
@@ -122,11 +122,11 @@ class TestBSpline(unittest.TestCase):
                                (42.6953266459619, 76.8712491781612),
                                (54.1042604888826, 93.164895304981)
                               ]
-    self.mySpline = self.mySketch.addSpline(self.myDegree,
-                                            self.myPolesCoordinates,
-                                            [1, 1, 1, 1, 1, 1, 0.957903314642061, 0.95790331464206, 1, 1, 1, 1, 1, 1],
-                                            [-494.543457494654, 500, 507.372773368102, 1501.91623086297],
-                                            [6, 4, 4, 6])
+    self.mySpline = self.mySketch.addSpline(degree = self.myDegree,
+                                            poles = self.myPolesCoordinates,
+                                            weights = [1, 1, 1, 1, 1, 1, 0.957903314642061, 0.95790331464206, 1, 1, 1, 1, 1, 1],
+                                            knots = [-494.543457494654, 500, 507.372773368102, 1501.91623086297],
+                                            multiplicities = [6, 4, 4, 6])
     self.myDOF += len(self.myPolesCoordinates) * 2
     self.myNbSplines += 1
     model.do()
@@ -139,7 +139,7 @@ class TestBSpline(unittest.TestCase):
     """ Test 6. Create B-spline curve by 2 poles
     """
     self.myDegree = 1
-    self.mySpline = self.mySketch.addSpline(self.myPoles[:2])
+    self.mySpline = self.mySketch.addSpline(poles = self.myPoles[:2])
     self.myDOF += 4
     self.myNbSplines += 1
     model.do()
@@ -152,7 +152,7 @@ class TestBSpline(unittest.TestCase):
     """ Test 7. Create B-spline curve by 3 poles
     """
     self.myDegree = 2
-    self.mySpline = self.mySketch.addSpline(self.myPoles[:3])
+    self.mySpline = self.mySketch.addSpline(poles = self.myPoles[:3])
     self.myDOF += 6
     self.myNbSplines += 1
     model.do()
@@ -164,7 +164,7 @@ class TestBSpline(unittest.TestCase):
   def test_bspline_with_poles(self):
     """ Test 8. Create B-spline curve and points coincident with its poles
     """
-    self.mySpline = self.mySketch.addSpline(self.myPoles)
+    self.mySpline = self.mySketch.addSpline(poles = self.myPoles)
     self.mySpline.controlPoles(regular = [0, 2], auxiliary = [1, 3])
     self.myDOF += len(self.myPoles) * 2
     self.myNbSplines += 1
@@ -178,7 +178,7 @@ class TestBSpline(unittest.TestCase):
   def test_bspline_with_polygon(self):
     """ Test 9. Create B-spline curve and its control polygon
     """
-    self.mySpline = self.mySketch.addSpline(self.myPoles)
+    self.mySpline = self.mySketch.addSpline(poles = self.myPoles)
     self.mySpline.controlPolygon(regular = [0, 2], auxiliary = [1, 3])
     self.myDOF += len(self.myPoles) * 2
     self.myNbSplines += 1
diff --git a/src/SketchPlugin/Test/TestCreateBSplinePeriodic.py b/src/SketchPlugin/Test/TestCreateBSplinePeriodic.py
new file mode 100644 (file)
index 0000000..7cec4b0
--- /dev/null
@@ -0,0 +1,184 @@
+# Copyright (C) 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
+# 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
+#
+
+"""
+    Test creation of periodic B-spline curve
+"""
+
+import unittest
+from salome.shaper import model
+
+from GeomAPI import *
+from SketchAPI import *
+
+__updated__ = "2020-01-24"
+
+class TestBSplinePeriodic(unittest.TestCase):
+  def setUp(self):
+    model.begin()
+    self.myDocument = model.moduleDocument()
+    self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY"))
+    self.myPoles = [GeomAPI_Pnt2d(50., 50.), GeomAPI_Pnt2d(70., 70.), GeomAPI_Pnt2d(80., 30.), GeomAPI_Pnt2d(50., 10.), GeomAPI_Pnt2d(10., -30.)]
+    self.myPolesCoordinates = [(50., 50.), (70., 70.), (80., 30.), (50., 10.), (10., -30.)]
+    self.myDegree = 3;
+    self.myDOF = 0
+    self.myNbPoints = 0
+    self.myNbLines = 0
+    self.myNbSplines = 0
+
+  def tearDown(self):
+    self.checkDOF()
+    model.end()
+    model.testNbSubFeatures(self.mySketch, "SketchPoint", self.myNbPoints)
+    model.testNbSubFeatures(self.mySketch, "SketchLine", self.myNbLines)
+    model.testNbSubFeatures(self.mySketch, "SketchBSplinePeriodic", self.myNbSplines)
+
+
+  def checkDOF(self):
+    self.assertEqual(model.dof(self.mySketch), self.myDOF)
+
+
+  def test_bspline_by_coordinates(self):
+    """ Test 1. Create B-spline curve by coordinates of its poles
+    """
+    self.mySpline = self.mySketch.addSpline(poles = self.myPolesCoordinates, periodic = True)
+    self.myDOF += len(self.myPolesCoordinates) * 2
+    self.myNbSplines += 1
+    model.do()
+
+    assert(self.mySpline.feature())
+    assert(self.mySpline.feature().error() == "")
+    assert(self.mySpline.degree().value() == self.myDegree)
+
+  def test_bspline_by_poles(self):
+    """ Test 2. Create B-spline curve by poles
+    """
+    self.mySpline = self.mySketch.addSpline(poles = self.myPoles, periodic = True)
+    self.myDOF += len(self.myPoles) * 2
+    self.myNbSplines += 1
+    model.do()
+
+    assert(self.mySpline.feature())
+    assert(self.mySpline.feature().error() == "")
+    assert(self.mySpline.degree().value() == self.myDegree)
+
+  def test_bspline_by_degree_and_poles(self):
+    """ Test 3. Create B-spline curve by poles and degree
+    """
+    self.myDegree = 4
+    self.mySpline = self.mySketch.addSpline(degree = self.myDegree, poles = self.myPoles, periodic = True)
+    self.myDOF += len(self.myPoles) * 2
+    self.myNbSplines += 1
+    model.do()
+
+    assert(self.mySpline.feature())
+    assert(self.mySpline.feature().error() == "")
+    assert(self.mySpline.degree().value() == self.myDegree)
+
+  def test_bspline_by_poles_and_weights(self):
+    """ Test 4. Create B-spline curve by poles and weights
+    """
+    self.mySpline = self.mySketch.addSpline(poles = self.myPoles, weights = [1, 2, 3, 2, 1], periodic = True)
+    self.myDOF += len(self.myPoles) * 2
+    self.myNbSplines += 1
+    model.do()
+
+    assert(self.mySpline.feature())
+    assert(self.mySpline.feature().error() == "")
+    assert(self.mySpline.degree().value() == self.myDegree)
+
+  def test_bspline_by_parametric(self):
+    """ Test 5. Create B-spline curve by whole set of parameters
+    """
+    self.myDegree = 3
+    self.myPolesCoordinates = [(-10, 0), (-20, 20), (0, 10), (20, 20),
+                               (10, 0), (20, -20), (0, -10), (-20, -20)
+                              ]
+    self.mySpline = self.mySketch.addSpline(degree = self.myDegree,
+                                            poles = self.myPolesCoordinates,
+                                            weights = [1, 1, 1, 1, 1, 1, 1, 1],
+                                            knots = [0, 1, 2, 3, 4, 5, 6, 7, 8],
+                                            multiplicities = [1, 1, 1, 1, 1, 1, 1, 1, 1],
+                                            periodic = True)
+    self.myDOF += len(self.myPolesCoordinates) * 2
+    self.myNbSplines += 1
+    model.do()
+
+    assert(self.mySpline.feature())
+    assert(self.mySpline.feature().error() == "")
+    assert(self.mySpline.degree().value() == self.myDegree)
+
+  def test_bspline_linear(self):
+    """ Test 6. Create B-spline curve by 2 poles
+    """
+    self.myDegree = 1
+    self.mySpline = self.mySketch.addSpline(poles = self.myPoles[:2], periodic = True)
+    self.myDOF += 4
+    self.myNbSplines += 1
+    model.do()
+
+    assert(self.mySpline.feature())
+    assert(self.mySpline.feature().error() == "")
+    assert(self.mySpline.degree().value() == self.myDegree)
+
+  def test_bspline_parabola(self):
+    """ Test 7. Create B-spline curve by 3 poles
+    """
+    self.myDegree = 2
+    self.mySpline = self.mySketch.addSpline(poles = self.myPoles[:3], periodic = True)
+    self.myDOF += 6
+    self.myNbSplines += 1
+    model.do()
+
+    assert(self.mySpline.feature())
+    assert(self.mySpline.feature().error() == "")
+    assert(self.mySpline.degree().value() == self.myDegree)
+
+  def test_bspline_with_poles(self):
+    """ Test 8. Create B-spline curve and points coincident with its poles
+    """
+    self.mySpline = self.mySketch.addSpline(poles = self.myPoles, periodic = True)
+    self.mySpline.controlPoles(regular = [0, 2], auxiliary = [1, 3])
+    self.myDOF += len(self.myPoles) * 2
+    self.myNbSplines += 1
+    self.myNbPoints += 4
+    model.do()
+
+    assert(self.mySpline.feature())
+    assert(self.mySpline.feature().error() == "")
+    assert(self.mySpline.degree().value() == self.myDegree)
+
+  def test_bspline_with_polygon(self):
+    """ Test 9. Create B-spline curve and its control polygon
+    """
+    self.mySpline = self.mySketch.addSpline(poles = self.myPoles, periodic = True)
+    self.mySpline.controlPolygon(regular = [0, 2], auxiliary = [1, 3])
+    self.myDOF += len(self.myPoles) * 2
+    self.myNbSplines += 1
+    self.myNbLines += 4
+    model.do()
+
+    assert(self.mySpline.feature())
+    assert(self.mySpline.feature().error() == "")
+    assert(self.mySpline.degree().value() == self.myDegree)
+
+if __name__ == "__main__":
+    test_program = unittest.main(exit=False)
+    assert test_program.result.wasSuccessful(), "Test failed"
+    assert model.checkPythonDump()
index eb71bffc84ed010a4db72d803a2e513b6e76e6f1..3e01ac72dab9630e28ad0a35f5875daf26768f56 100644 (file)
@@ -40,7 +40,7 @@ class TestMoveBSpline(unittest.TestCase):
                     GeomAPI_Pnt2d(80., 30.),
                     GeomAPI_Pnt2d(50., 10.),
                     GeomAPI_Pnt2d(90., -30.)]
-    self.mySpline = self.mySketch.addSpline(self.myPoles)
+    self.mySpline = self.mySketch.addSpline(poles = self.myPoles)
     self.myDOF = len(self.myPoles) * 2
     model.do()
     self.checkDOF()
diff --git a/src/SketchPlugin/Test/TestMoveBSplinePeriodic.py b/src/SketchPlugin/Test/TestMoveBSplinePeriodic.py
new file mode 100644 (file)
index 0000000..d7c702a
--- /dev/null
@@ -0,0 +1,205 @@
+# Copyright (C) 2019-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
+# 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
+#
+
+"""
+    Test movement of the periodic B-spline curve
+"""
+
+import unittest
+import math
+from GeomAPI import *
+from GeomDataAPI import geomDataAPI_Point2DArray
+from SketchAPI import *
+from salome.shaper import model
+
+__updated__ = "2020-01-20"
+
+class TestMoveBSpline(unittest.TestCase):
+  def setUp(self):
+    model.begin()
+    self.myDocument = model.moduleDocument()
+    self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY"))
+    self.myPoles = [GeomAPI_Pnt2d(20., 50.),
+                    GeomAPI_Pnt2d(70., 70.),
+                    GeomAPI_Pnt2d(80., 30.),
+                    GeomAPI_Pnt2d(50., -10.),
+                    GeomAPI_Pnt2d(90., -30.)]
+    self.mySpline = self.mySketch.addSpline(poles = self.myPoles, periodic = True)
+    self.myDOF = len(self.myPoles) * 2
+    model.do()
+    self.checkDOF()
+
+  def tearDown(self):
+    self.checkDOF()
+    model.end()
+
+  def checkDOF(self):
+    self.assertEqual(model.dof(self.mySketch), self.myDOF)
+
+  def checkPointCoordinates(self, thePoint, theCoordinates):
+    aCoord = []
+    if issubclass(type(theCoordinates), GeomAPI_Pnt2d):
+      aCoord = [theCoordinates.x(), theCoordinates.y()]
+    else:
+      aCoord = theCoordinates
+    DIGITS = 7 - math.floor(math.log10(math.hypot(aCoord[0], aCoord[1])))
+    self.assertAlmostEqual(thePoint.x(), aCoord[0], DIGITS)
+    self.assertAlmostEqual(thePoint.y(), aCoord[1], DIGITS)
+
+  def checkPoles(self, theBSpline, theCoordinates):
+    poles = theBSpline.poles()
+    for index, point in zip(range(0, len(theCoordinates)), theCoordinates):
+      self.checkPointCoordinates(poles.pnt(index), point)
+
+  def fixPoint(self, thePoint):
+    self.mySketch.setFixed(thePoint)
+    self.myDOF -= 2
+    model.do()
+    self.checkDOF()
+
+
+  def test_move_free_bspline(self):
+    """ Test 1. Movement of a free B-spline dragging the edge
+    """
+    oldPosition = GeomAPI_Edge(self.mySpline.defaultResult().shape()).middlePoint()
+    newPosition = GeomAPI_Pnt2d(120., 90.)
+    self.mySketch.move(self.mySpline.defaultResult(), newPosition)
+    model.do()
+
+    # plane is XOY, no need to project oldPosition point
+    dx = newPosition.x() - oldPosition.x()
+    dy = newPosition.y() - oldPosition.y()
+
+    newPoles = []
+    for pole in self.myPoles:
+      newPoles.append(GeomAPI_Pnt2d(pole.x() + dx, pole.y() + dy))
+    self.checkPoles(self.mySpline, newPoles)
+
+
+  def test_move_fixed_bspline(self):
+    """ Test 2. Movement of a fully fixed B-spline
+    """
+    self.mySketch.setFixed(self.mySpline.defaultResult())
+    self.myDOF = 0
+    model.do()
+
+    newPosition = GeomAPI_Pnt2d(120., 90.)
+    self.mySketch.move(self.mySpline.defaultResult(), newPosition)
+    model.do()
+
+    self.checkPoles(self.mySpline, self.myPoles)
+
+
+  def test_move_bspline_with_fixed_pole(self):
+    """ Test 3. Movement of a B-spline curve with fixed pole
+    """
+    [Point_1, Point_2, Point_3, Point_4, Point_5] = self.mySpline.controlPoles(auxiliary = [0, 1, 2, 3, 4])
+    model.do()
+
+    self.fixPoint(Point_2.defaultResult())
+    model.do()
+
+    oldPosition = GeomAPI_Edge(self.mySpline.defaultResult().shape()).middlePoint()
+    newPosition = GeomAPI_Pnt2d(120., 90.)
+    self.mySketch.move(self.mySpline.defaultResult(), newPosition)
+    model.do()
+
+    # plane is XOY, no need to project oldPosition point
+    dx = newPosition.x() - oldPosition.x()
+    dy = newPosition.y() - oldPosition.y()
+
+    newPoles = []
+    for pole in self.myPoles:
+      newPoles.append(GeomAPI_Pnt2d(pole.x() + dx, pole.y() + dy))
+    newPoles[1].setX(newPoles[1].x() - dx)
+    newPoles[1].setY(newPoles[1].y() - dy)
+    self.checkPoles(self.mySpline, newPoles)
+
+
+  def test_move_bspline_with_fixed_segment(self):
+    """ Test 4. Movement of a B-spline curve with fixed control segment
+    """
+    [Line_1, Line_2, Line_3, Line_4, Line_5] = self.mySpline.controlPolygon(auxiliary = [0, 1, 2, 3, 4])
+    model.do()
+
+    self.mySketch.setFixed(Line_1.defaultResult())
+    self.myDOF -= 4
+    model.do()
+
+    oldPosition = GeomAPI_Edge(self.mySpline.defaultResult().shape()).middlePoint()
+    newPosition = GeomAPI_Pnt2d(120., 90.)
+    self.mySketch.move(self.mySpline.defaultResult(), newPosition)
+    model.do()
+
+    # plane is XOY, no need to project oldPosition point
+    dx = newPosition.x() - oldPosition.x()
+    dy = newPosition.y() - oldPosition.y()
+
+    newPoles = [self.myPoles[0], self.myPoles[1]]
+    for pole in self.myPoles[2:]:
+      newPoles.append(GeomAPI_Pnt2d(pole.x() + dx, pole.y() + dy))
+    self.checkPoles(self.mySpline, newPoles)
+
+
+  def test_move_pole_of_free_bspline(self):
+    """ Test 5. Movement of a pole of a B-spline curve
+    """
+    [Point_1, Point_2, Point_3, Point_4, Point_5] = self.mySpline.controlPoles(auxiliary = [0, 1, 2, 3, 4])
+    [Line_1, Line_2, Line_3, Line_4, Line_5] = self.mySpline.controlPolygon(auxiliary = [0, 1, 2, 3, 4])
+    model.do()
+
+    newPoles = self.myPoles
+
+    newPoles[2].setX(newPoles[2].x() + 20.)
+    newPoles[2].setY(newPoles[2].y() + 20.)
+    self.mySketch.move(SketchAPI_Point(Point_3).coordinates(), newPoles[2])
+    model.do()
+
+    self.checkPoles(self.mySpline, newPoles)
+
+  def test_move_segment_of_free_bspline(self):
+    """ Test 6. Movement of a control segment of a B-spline curve
+    """
+    [Point_1, Point_2, Point_3, Point_4, Point_5] = self.mySpline.controlPoles(auxiliary = [0, 1, 2, 3, 4])
+    [Line_1, Line_2, Line_3, Line_4, Line_5] = self.mySpline.controlPolygon(auxiliary = [0, 1, 2, 3, 4])
+    model.do()
+
+    oldPosition = GeomAPI_Pnt2d(0.5 * (self.myPoles[2].x() + self.myPoles[3].x()),
+                                0.5 * (self.myPoles[2].y() + self.myPoles[3].y()))
+    newPosition = GeomAPI_Pnt2d(120., 90.)
+    self.mySketch.move(SketchAPI_Line(Line_3).defaultResult(), newPosition)
+    model.do()
+
+    dx = newPosition.x() - oldPosition.x()
+    dy = newPosition.y() - oldPosition.y()
+
+    newPoles = self.myPoles
+    newPoles[2].setX(newPoles[2].x() + dx)
+    newPoles[2].setY(newPoles[2].y() + dy)
+    newPoles[3].setX(newPoles[3].x() + dx)
+    newPoles[3].setY(newPoles[3].y() + dy)
+
+    self.checkPoles(self.mySpline, newPoles)
+
+
+
+if __name__ == "__main__":
+    test_program = unittest.main(exit=False)
+    assert test_program.result.wasSuccessful(), "Test failed"
+    assert model.checkPythonDump()
index 2b675b4ceeaec9263cd121585b7761f00982fbe7..2f09005efa5edcc31a874e5dc5b4c4cedabd3e7d 100644 (file)
@@ -175,3 +175,22 @@ aWeights.setValue(3, 1)
 aBSpline.boolean("need_control_poly").setValue(True)
 assert(featureToPresentation(aBSpline).getAISObject(None) is not None)
 aSession.finishOperation()
+
+# Test presentation for MacroBSplinePeriodic on low-level
+aSession.startOperation()
+aBSplineP = aSketchFeature.addFeature("SketchMacroBSplinePeriodic")
+aPoles = geomDataAPI_Point2DArray(aBSplineP.attribute("poles"))
+aPoles.setSize(4)
+aPoles.setPnt(0, 0, 0)
+aPoles.setPnt(1, 10, 0)
+aPoles.setPnt(2, 10, 10)
+aPoles.setPnt(3, 0, 10)
+aWeights = aBSplineP.data().realArray("weights")
+aWeights.setSize(4)
+aWeights.setValue(0, 1)
+aWeights.setValue(1, 2)
+aWeights.setValue(2, 2)
+aWeights.setValue(3, 1)
+aBSplineP.boolean("need_control_poly").setValue(True)
+assert(featureToPresentation(aBSplineP).getAISObject(None) is not None)
+aSession.finishOperation()
diff --git a/src/SketchPlugin/Test/TestProjectionBSplinePeriodic.py b/src/SketchPlugin/Test/TestProjectionBSplinePeriodic.py
new file mode 100644 (file)
index 0000000..2ebd6b1
--- /dev/null
@@ -0,0 +1,78 @@
+# Copyright (C) 2019-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
+# 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
+#
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 5, 10, 180)
+Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Cylinder_1_1/Face_5"))
+SketchCircle_1 = Sketch_1.addCircle(-0.9379111501048892, 5.54816019935757, 2.957303770750356)
+model.do()
+ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2r")], model.selection(), [model.selection("SOLID", "Cylinder_1_1")])
+Rotation_1 = model.addRotation(Part_1_doc, [model.selection("SOLID", "ExtrusionCut_1_1")], model.selection("EDGE", "PartSet/OX"), 45)
+Edge_1 = model.addEdge(Part_1_doc, [model.selection("EDGE", "[Rotation_1_1/MF:Rotated&Cylinder_1_1/Face_1][Rotation_1_1/MF:Rotated&Sketch_1/SketchCircle_1_2]")], False)
+
+Sketch_2 = model.addSketch(Part_1_doc, model.standardPlane("XOY"))
+SketchProjection_1 = Sketch_2.addProjection(model.selection("EDGE", "Edge_1_1"), True)
+SketchBSpline_1 = SketchProjection_1.createdFeature()
+model.do()
+
+Sketch_3 = model.addSketch(Part_1_doc, model.standardPlane("XOZ"))
+SketchProjection_2 = Sketch_3.addProjection(model.selection("EDGE", "Edge_1_1"), True)
+SketchBSpline_2 = SketchProjection_2.createdFeature()
+model.do()
+
+Sketch_4 = model.addSketch(Part_1_doc, model.standardPlane("YOZ"))
+SketchProjection_3 = Sketch_4.addProjection(model.selection("EDGE", "Edge_1_1"), True)
+SketchBSpline_3 = SketchProjection_3.createdFeature()
+model.do()
+
+model.end()
+
+from GeomAPI import *
+import math
+
+TOLERANCE = 1.e-7
+
+def checkProjection(theBSpline3D, theBSpline2D, theFlags):
+    assert(theBSpline2D.isEdge() and theBSpline2D.edge().isBSpline())
+    poles2D = GeomAPI_BSpline(GeomAPI_Curve(theBSpline2D)).poles()
+    poles3D = theBSpline3D.poles()
+    assert(poles2D.size() == poles3D.size())
+    for p2d, p3d in zip(poles2D, poles3D):
+        assert(math.fabs((p2d.x() - p3d.x()) * theFlags.x()) < TOLERANCE and
+               math.fabs((p2d.y() - p3d.y()) * theFlags.y()) < TOLERANCE and
+               math.fabs((p2d.z() - p3d.z()) * theFlags.z()) < TOLERANCE)
+
+
+bspline0 = GeomAPI_BSpline(GeomAPI_Curve(Edge_1.results()[-1].resultSubShapePair()[0].shape()))
+
+bsplineShape1 = SketchBSpline_1.results()[-1].resultSubShapePair()[0].shape()
+checkProjection(bspline0, bsplineShape1, GeomAPI_Pnt(1, 1, 0))
+
+bsplineShape2 = SketchBSpline_2.results()[-1].resultSubShapePair()[0].shape()
+checkProjection(bspline0, bsplineShape2, GeomAPI_Pnt(1, 0, 1))
+
+bsplineShape3 = SketchBSpline_3.results()[-1].resultSubShapePair()[0].shape()
+checkProjection(bspline0, bsplineShape3, GeomAPI_Pnt(0, 1, 1))
+
+assert(model.checkPythonDump())
index d9f4461c1ff76e0b179d1425fed6e05f5a56130c..05da29875bdc4a308027a0fecdec6868ff8fc173 100644 (file)
 from salome.shaper import model
 from ModelAPI import *
 
-def assertNbSubs(theSketch, theNbPoints, theNbLines, theNbEllipses, theNbInternalConstraints):
+def assertNbSubs(theSketch, theNbPoints, theNbLines, theNbSplines, theNbInternalConstraints):
     model.testNbSubFeatures(theSketch, "SketchPoint", theNbPoints)
     model.testNbSubFeatures(theSketch, "SketchLine", theNbLines)
-    model.testNbSubFeatures(theSketch, "SketchBSpline", theNbEllipses)
+    model.testNbSubFeatures(theSketch, "SketchBSpline", theNbSplines)
     model.testNbSubFeatures(theSketch, "SketchConstraintCoincidenceInternal", theNbInternalConstraints)
 
 model.begin()
@@ -36,7 +36,7 @@ Part_1 = model.addPart(partSet)
 Part_1_doc = Part_1.document()
 Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
 SketchBSpline_1_poles = [(-30, -10), (-15, 20), (0, -10), (15, 20), (30, -10)]
-SketchBSpline_1 = Sketch_1.addSpline(SketchBSpline_1_poles)
+SketchBSpline_1 = Sketch_1.addSpline(poles = SketchBSpline_1_poles)
 controlPoles = SketchBSpline_1.controlPoles(auxiliary = [0, 1, 2, 3, 4])
 controlLines = SketchBSpline_1.controlPolygon(auxiliary = [0, 1, 2, 3])
 model.do()
@@ -91,7 +91,7 @@ model.begin()
 partSet = model.moduleDocument()
 Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
 SketchBSpline_2_poles = [(-30, -10), (-15, -40), (0, -10), (15, -40), (30, -10)]
-SketchBSpline_2 = Sketch_2.addSpline(SketchBSpline_2_poles)
+SketchBSpline_2 = Sketch_2.addSpline(poles = SketchBSpline_2_poles)
 controlPoles2 = SketchBSpline_2.controlPoles(auxiliary = [0, 1, 2, 3, 4])
 controlLines2 = SketchBSpline_2.controlPolygon(auxiliary = [0, 1, 2, 3])
 model.do()
diff --git a/src/SketchPlugin/Test/TestRemoveBSplinePeriodic.py b/src/SketchPlugin/Test/TestRemoveBSplinePeriodic.py
new file mode 100644 (file)
index 0000000..4e9d3eb
--- /dev/null
@@ -0,0 +1,108 @@
+# Copyright (C) 2019-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
+# 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
+#
+
+"""
+    Test removing peridoc B-spline curve and its construstion elements
+"""
+
+from salome.shaper import model
+from ModelAPI import *
+
+def assertNbSubs(theSketch, theNbPoints, theNbLines, theNbSplines, theNbInternalConstraints):
+    model.testNbSubFeatures(theSketch, "SketchPoint", theNbPoints)
+    model.testNbSubFeatures(theSketch, "SketchLine", theNbLines)
+    model.testNbSubFeatures(theSketch, "SketchBSplinePeriodic", theNbSplines)
+    model.testNbSubFeatures(theSketch, "SketchConstraintCoincidenceInternal", theNbInternalConstraints)
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchBSpline_1_poles = [(-30, -10), (-15, 20), (0, -10), (15, 20), (30, -10)]
+SketchBSpline_1 = Sketch_1.addSpline(poles = SketchBSpline_1_poles, periodic = True)
+controlPoles = SketchBSpline_1.controlPoles(auxiliary = [0, 1, 2, 3, 4])
+controlLines = SketchBSpline_1.controlPolygon(auxiliary = [0, 1, 2, 3, 4])
+model.do()
+model.end()
+
+DEFAULT_DOF = len(SketchBSpline_1_poles) * 2
+DEFAULT_POINTS = len(SketchBSpline_1_poles)
+DEFAULT_LINES = len(SketchBSpline_1_poles)
+DEFAULT_BSPLINES = 1
+DEAFULT_INTERNALS = len(controlPoles) + len(controlLines) * 2
+
+assertNbSubs(Sketch_1, DEFAULT_POINTS, DEFAULT_LINES, DEFAULT_BSPLINES, DEAFULT_INTERNALS)
+assert(model.dof(Sketch_1) == DEFAULT_DOF)
+
+# Test 1. Remove auxiliary points one by one.
+for pnt in controlPoles:
+    model.begin()
+    removeFeaturesAndReferences(FeatureSet([pnt.feature()]))
+    model.end()
+
+    assertNbSubs(Sketch_1, DEFAULT_POINTS - 1, DEFAULT_LINES, DEFAULT_BSPLINES, DEAFULT_INTERNALS - 1)
+    assert(model.dof(Sketch_1) == DEFAULT_DOF)
+    model.undo()
+    assertNbSubs(Sketch_1, DEFAULT_POINTS, DEFAULT_LINES, DEFAULT_BSPLINES, DEAFULT_INTERNALS)
+    assert(model.dof(Sketch_1) == DEFAULT_DOF)
+
+# Test 2. Remove auxiliary lines one by one.
+for ln in controlLines:
+    model.begin()
+    removeFeaturesAndReferences(FeatureSet([ln.feature()]))
+    model.end()
+
+    assertNbSubs(Sketch_1, DEFAULT_POINTS, DEFAULT_LINES - 1, DEFAULT_BSPLINES, DEAFULT_INTERNALS - 2)
+    assert(model.dof(Sketch_1) == DEFAULT_DOF)
+    model.undo()
+    assertNbSubs(Sketch_1, DEFAULT_POINTS, DEFAULT_LINES, DEFAULT_BSPLINES, DEAFULT_INTERNALS)
+    assert(model.dof(Sketch_1) == DEFAULT_DOF)
+
+# Test 3. Remove the B-spline curve.
+model.begin()
+removeFeaturesAndReferences(FeatureSet([SketchBSpline_1.feature()]))
+model.end()
+
+assertNbSubs(Sketch_1, 0, 0, 0, 0)
+assert(model.dof(Sketch_1) == 0)
+model.undo()
+assertNbSubs(Sketch_1, DEFAULT_POINTS, DEFAULT_LINES, DEFAULT_BSPLINES, DEAFULT_INTERNALS)
+assert(model.dof(Sketch_1) == DEFAULT_DOF)
+
+# Test 4. Remove some construction elements, make non-auxiliary a couple of the rest and check the dumping.
+model.begin()
+partSet = model.moduleDocument()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchBSpline_2_poles = [(-30, -10), (-15, -40), (0, -10), (15, -40), (30, -10)]
+SketchBSpline_2 = Sketch_2.addSpline(poles = SketchBSpline_2_poles, periodic = True)
+controlPoles2 = SketchBSpline_2.controlPoles(auxiliary = [0, 1, 2, 3, 4])
+controlLines2 = SketchBSpline_2.controlPolygon(auxiliary = [0, 1, 2, 3, 4])
+model.do()
+model.end()
+
+model.begin()
+controlPoles2[1].setAuxiliary(False)
+controlLines2[2].setAuxiliary(False)
+removeFeaturesAndReferences(FeatureSet([controlPoles2[2].feature(), controlLines2[0].feature()]))
+model.end()
+
+assertNbSubs(Sketch_2, DEFAULT_POINTS - 1, DEFAULT_LINES - 1, DEFAULT_BSPLINES, DEAFULT_INTERNALS - 3)
+
+assert(model.checkPythonDump())
index 988a3c5a4d676b6e1a9041d7053dc44b98e2c79f..3323048d406494dd26deb0b750ad1abc59989325 100644 (file)
@@ -89,10 +89,9 @@ static EntityWrapperPtr createScalar(const AttributePtr&     theAttribute,
      (theAttribute->id() == SketchPlugin_MultiRotation::ANGLE_ID() &&
       anOwner->getKind() == SketchPlugin_MultiRotation::ID()))
     aWrapper = ScalarWrapperPtr(new PlaneGCSSolver_AngleWrapper(createParameter(theStorage)));
-  else if ((anOwner->getKind() == SketchPlugin_BSpline::ID() &&
-            theAttribute->id() == SketchPlugin_BSpline::DEGREE_ID()) ||
-           (anOwner->getKind() == SketchPlugin_BSplinePeriodic::ID() &&
-            theAttribute->id() == SketchPlugin_BSplinePeriodic::DEGREE_ID()))
+  else if ((anOwner->getKind() == SketchPlugin_BSpline::ID() ||
+            anOwner->getKind() == SketchPlugin_BSplinePeriodic::ID()) &&
+           theAttribute->id() == SketchPlugin_BSplineBase::DEGREE_ID())
     // Degree of B-spline is not processed by the solver
     aWrapper = ScalarWrapperPtr(new PlaneGCSSolver_ScalarWrapper(createParameter(nullptr)));
   else