Salome HOME
Fix crash on importing salome.shaper.model
[modules/shaper.git] / src / SketchAPI / SketchAPI_Sketch.cpp
index b2ca766988edd68862c7c6894ec35672e5de608e..5a8d9ce21a3158b9ca52667fb5f933721915feba 100644 (file)
@@ -53,6 +53,7 @@
 #include <ModelHighAPI_Tools.h>
 //--------------------------------------------------------------------------------------
 #include "SketchAPI_Arc.h"
+#include "SketchAPI_BSpline.h"
 #include "SketchAPI_Circle.h"
 #include "SketchAPI_Ellipse.h"
 #include "SketchAPI_EllipticArc.h"
@@ -75,6 +76,8 @@
 #include <GeomAPI_ShapeExplorer.h>
 #include <GeomAPI_XY.h>
 #include <GeomAlgoAPI_SketchBuilder.h>
+
+#include <algorithm>
 #include <cmath>
 //--------------------------------------------------------------------------------------
 SketchAPI_Sketch::SketchAPI_Sketch(
@@ -695,6 +698,32 @@ std::shared_ptr<SketchAPI_EllipticArc> SketchAPI_Sketch::addEllipticArc(
   return EllipticArcPtr(new SketchAPI_EllipticArc(aFeature, theExternalName));
 }
 
+//--------------------------------------------------------------------------------------
+
+std::shared_ptr<SketchAPI_BSpline> SketchAPI_Sketch::addSpline(
+    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);
+
+  return aBSpline;
+}
+
 //--------------------------------------------------------------------------------------
 std::shared_ptr<SketchAPI_Projection> SketchAPI_Sketch::addProjection(
     const ModelHighAPI_Selection & theExternalFeature,
@@ -798,16 +827,38 @@ std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::addTrim(
 std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setAngle(
     const ModelHighAPI_RefAttr & theLine1,
     const ModelHighAPI_RefAttr & theLine2,
-    const ModelHighAPI_Double & theValue)
+    const ModelHighAPI_Double & theValue,
+    const std::string& theType)
 {
   std::shared_ptr<ModelAPI_Feature> aFeature =
       compositeFeature()->addFeature(SketchPlugin_ConstraintAngle::ID());
-  fillAttribute(SketcherPrs_Tools::ANGLE_DIRECT,
-      aFeature->integer(SketchPlugin_ConstraintAngle::TYPE_ID()));
-  // fill the value before llines to avoid calculation of angle value by the Angle feature
+
+  const int aVersion = theType.empty() ? SketchPlugin_ConstraintAngle::THE_VERSION_0
+                                       : SketchPlugin_ConstraintAngle::THE_VERSION_1;
+  fillAttribute(aVersion, aFeature->integer(SketchPlugin_ConstraintAngle::VERSION_ID()));
+
+  int aType = (int)SketcherPrs_Tools::ANGLE_DIRECT;
+  fillAttribute(aType, aFeature->integer(SketchPlugin_ConstraintAngle::PREV_TYPE_ID()));
+  fillAttribute(aType, aFeature->integer(SketchPlugin_ConstraintAngle::TYPE_ID()));
+
+  if (aVersion == SketchPlugin_ConstraintAngle::THE_VERSION_0)
+    fillAttribute(theValue, aFeature->real(SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID()));
+
   fillAttribute(theLine1, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A()));
   fillAttribute(theLine2, aFeature->refattr(SketchPlugin_Constraint::ENTITY_B()));
-  fillAttribute(theValue, aFeature->real(SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID()));
+
+  if (aVersion == SketchPlugin_ConstraintAngle::THE_VERSION_1) {
+    std::string aTypeLC = theType;
+    std::transform(aTypeLC.begin(), aTypeLC.end(), aTypeLC.begin(), ::tolower);
+    if (aTypeLC == "supplementary")
+      aType = (int)SketcherPrs_Tools::ANGLE_COMPLEMENTARY;
+    else if (aTypeLC == "backward")
+      aType = (int)SketcherPrs_Tools::ANGLE_BACKWARD;
+
+    fillAttribute(aType, aFeature->integer(SketchPlugin_ConstraintAngle::TYPE_ID()));
+    fillAttribute(theValue, aFeature->real(SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID()));
+  }
+
   aFeature->execute();
   return InterfacePtr(new ModelHighAPI_Interface(aFeature));
 }
@@ -819,11 +870,13 @@ std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setAngleComplementary(
 {
   std::shared_ptr<ModelAPI_Feature> aFeature =
       compositeFeature()->addFeature(SketchPlugin_ConstraintAngle::ID());
+  fillAttribute(SketchPlugin_ConstraintAngle::THE_VERSION_0,
+      aFeature->integer(SketchPlugin_ConstraintAngle::VERSION_ID()));
   fillAttribute(SketcherPrs_Tools::ANGLE_COMPLEMENTARY,
       aFeature->integer(SketchPlugin_ConstraintAngle::TYPE_ID()));
+  fillAttribute(theValue, aFeature->real(SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID()));
   fillAttribute(theLine1, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A()));
   fillAttribute(theLine2, aFeature->refattr(SketchPlugin_Constraint::ENTITY_B()));
-  fillAttribute(theValue, aFeature->real(SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID()));
   aFeature->execute();
   return InterfacePtr(new ModelHighAPI_Interface(aFeature));
 }
@@ -835,11 +888,13 @@ std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setAngleBackward(
 {
   std::shared_ptr<ModelAPI_Feature> aFeature =
       compositeFeature()->addFeature(SketchPlugin_ConstraintAngle::ID());
+  fillAttribute(SketchPlugin_ConstraintAngle::THE_VERSION_0,
+      aFeature->integer(SketchPlugin_ConstraintAngle::VERSION_ID()));
   fillAttribute(SketcherPrs_Tools::ANGLE_BACKWARD,
       aFeature->integer(SketchPlugin_ConstraintAngle::TYPE_ID()));
+  fillAttribute(theValue, aFeature->real(SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID()));
   fillAttribute(theLine1, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A()));
   fillAttribute(theLine2, aFeature->refattr(SketchPlugin_Constraint::ENTITY_B()));
-  fillAttribute(theValue, aFeature->real(SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID()));
   aFeature->execute();
   return InterfacePtr(new ModelHighAPI_Interface(aFeature));
 }
@@ -1156,7 +1211,16 @@ static std::shared_ptr<GeomAPI_Pnt2d> pointOnEllipse(const FeaturePtr& theFeatur
   return aMajorAxisEnd ? aMajorAxisEnd->pnt() : std::shared_ptr<GeomAPI_Pnt2d>();
 }
 
-static std::shared_ptr<GeomAPI_Pnt2d> middlePoint(const ObjectPtr& theObject)
+static std::shared_ptr<GeomAPI_Pnt2d> middlePointOnBSpline(const FeaturePtr& theFeature,
+                                                           SketchAPI_Sketch* theSketch)
+{
+  GeomAPI_Edge anEdge(theFeature->lastResult()->shape());
+  GeomPointPtr aMiddle = anEdge.middlePoint();
+  return theSketch->to2D(aMiddle);
+}
+
+static std::shared_ptr<GeomAPI_Pnt2d> middlePoint(const ObjectPtr& theObject,
+                                                  SketchAPI_Sketch* theSketch)
 {
   std::shared_ptr<GeomAPI_Pnt2d> aMiddlePoint;
   FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
@@ -1175,6 +1239,9 @@ 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() ||
+             aFeatureKind == SketchPlugin_BSplinePeriodic::ID())
+      aMiddlePoint = middlePointOnBSpline(aFeature, theSketch);
   }
   return aMiddlePoint;
 }
@@ -1189,7 +1256,7 @@ void SketchAPI_Sketch::move(const ModelHighAPI_RefAttr& theMovedEntity,
   if (aMessage->movedAttribute())
     anOriginalPosition = pointCoordinates(aMessage->movedAttribute());
   else
-    anOriginalPosition = middlePoint(aMessage->movedObject());
+    anOriginalPosition = middlePoint(aMessage->movedObject(), this);
 
   if (!anOriginalPosition)
     return; // something has gone wrong, do not process movement
@@ -1395,5 +1462,7 @@ void SketchAPI_Sketch::dump(ModelHighAPI_Dumper& theDumper) const
       theDumper << *aFIt;
     }
     theDumper << "\n" << aSpaceShift << " ])" << std::endl;
+    // call model.do() for correct update of the document's labels related to the changed faces
+    theDumper << "model.do()" << std::endl;
   }
 }