Salome HOME
updated copyright message
[modules/shaper.git] / src / SketchAPI / SketchAPI_Sketch.cpp
index d9fff77cebdb054398ca78d6a3ba6589f84605ea..823897f5a6e2213e98c2a0e07d3fa8fd79e7f0ec 100644 (file)
@@ -1,11 +1,22 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-// Name   : SketchAPI_Sketch.cpp
-// Purpose:
+// Copyright (C) 2014-2023  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
 //
-// History:
-// 07/06/16 - Sergey POKHODENKO - Creation of the file
 
-//--------------------------------------------------------------------------------------
 #include "SketchAPI_Sketch.h"
 //--------------------------------------------------------------------------------------
 #include <SketchPlugin_Constraint.h>
@@ -13,6 +24,8 @@
 #include <SketchPlugin_ConstraintCoincidence.h>
 #include <SketchPlugin_ConstraintCollinear.h>
 #include <SketchPlugin_ConstraintDistance.h>
+#include <SketchPlugin_ConstraintDistanceHorizontal.h>
+#include <SketchPlugin_ConstraintDistanceVertical.h>
 #include <SketchPlugin_ConstraintEqual.h>
 #include <SketchPlugin_Fillet.h>
 #include <SketchPlugin_ConstraintHorizontal.h>
 #include <SketchPlugin_ConstraintPerpendicular.h>
 #include <SketchPlugin_ConstraintRadius.h>
 #include <SketchPlugin_ConstraintRigid.h>
-#include <SketchPlugin_ConstraintSplit.h>
+#include <SketchPlugin_CurveFitting.h>
 #include <SketchPlugin_Trim.h>
+#include <SketchPlugin_Split.h>
 #include <SketchPlugin_ConstraintTangent.h>
 #include <SketchPlugin_ConstraintVertical.h>
+#include <SketchPlugin_MacroBSpline.h>
+#include <SketchPlugin_SketchCopy.h>
+#include <SketchPlugin_Offset.h>
 #include <SketcherPrs_Tools.h>
 //--------------------------------------------------------------------------------------
+#include <ModelAPI_Events.h>
 #include <ModelAPI_CompositeFeature.h>
 #include <ModelAPI_ResultConstruction.h>
 #include <ModelHighAPI_Double.h>
 #include <ModelHighAPI_Tools.h>
 //--------------------------------------------------------------------------------------
 #include "SketchAPI_Arc.h"
+#include "SketchAPI_BSpline.h"
 #include "SketchAPI_Circle.h"
+#include "SketchAPI_Ellipse.h"
+#include "SketchAPI_EllipticArc.h"
 #include "SketchAPI_IntersectionPoint.h"
 #include "SketchAPI_Line.h"
+#include "SketchAPI_MacroArc.h"
+#include "SketchAPI_MacroCircle.h"
+#include "SketchAPI_MacroEllipse.h"
+#include "SketchAPI_MacroEllipticArc.h"
 #include "SketchAPI_Mirror.h"
+#include "SketchAPI_Offset.h"
 #include "SketchAPI_Point.h"
 #include "SketchAPI_Projection.h"
 #include "SketchAPI_Rectangle.h"
 #include "SketchAPI_Rotation.h"
 #include "SketchAPI_Translation.h"
 //--------------------------------------------------------------------------------------
+#include <GeomAPI_Curve.h>
+#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_PlanarEdges.h>
+#include <GeomAPI_ShapeExplorer.h>
+#include <GeomAPI_XY.h>
+#include <GeomAlgoAPI_SketchBuilder.h>
+
+#include <algorithm>
+#include <cmath>
+//--------------------------------------------------------------------------------------
 SketchAPI_Sketch::SketchAPI_Sketch(
     const std::shared_ptr<ModelAPI_Feature> & theFeature)
 : ModelHighAPI_Interface(theFeature)
@@ -107,6 +143,25 @@ void SketchAPI_Sketch::setPlane(const std::shared_ptr<GeomAPI_Ax3> & thePlane)
   execute();
 }
 
+void SketchAPI_Sketch::setPlane(const ModelHighAPI_Selection & thePlane,
+                                bool theRemoveExternalDependency)
+{
+  FeaturePtr aSketch = feature();
+
+  DocumentPtr aDoc = aSketch->document();
+  bool useVisible = false;
+  FeaturePtr aCurFeatureBefore = aDoc->currentFeature(useVisible);
+  aDoc->setCurrentFeature(aSketch, useVisible);
+
+  if (theRemoveExternalDependency)
+    aSketch->customAction(SketchPlugin_Sketch::ACTION_REMOVE_EXTERNAL());
+
+  setExternal(thePlane);
+
+  aDoc->setCurrentFeature(aCurFeatureBefore, useVisible);
+}
+
+//--------------------------------------------------------------------------------------
 void SketchAPI_Sketch::setExternal(const ModelHighAPI_Selection & theExternal)
 {
   fillAttribute(theExternal, myexternal);
@@ -168,7 +223,7 @@ SketchPtr addSketch(const std::shared_ptr<ModelAPI_Document> & thePart,
 }
 
 SketchPtr addSketch(const std::shared_ptr<ModelAPI_Document> & thePart,
-                    const std::string & theExternalName)
+                    const std::wstring & theExternalName)
 {
   std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(SketchAPI_Sketch::ID());
   return SketchPtr(
@@ -182,6 +237,95 @@ SketchPtr addSketch(const std::shared_ptr<ModelAPI_Document> & thePart,
   return SketchPtr(new SketchAPI_Sketch(aFeature, thePlaneObject));
 }
 
+//--------------------------------------------------------------------------------------
+SketchPtr copySketch(const std::shared_ptr<ModelAPI_Document> & thePart,
+                     const SketchPtr & theSketch)
+{
+  FeaturePtr aCopyer = thePart->addFeature(SketchPlugin_SketchCopy::ID());
+  aCopyer->reference(SketchPlugin_SketchCopy::BASE_ID())->setValue(theSketch->feature());
+  aCopyer->execute();
+
+  FeaturePtr aNewSketch = thePart->nextFeature(aCopyer);
+
+  // perform removing the macro-feature
+  thePart->removeFeature(aCopyer);
+  apply();
+
+  return SketchPtr(new SketchAPI_Sketch(aNewSketch));
+}
+
+
+//--------------------------------------------------------------------------------------
+std::list< std::shared_ptr<SketchAPI_Point> > SketchAPI_Sketch::getFreePoints()
+{
+  std::list< std::shared_ptr<SketchAPI_Point> > aFreePoints;
+  std::list<ResultPtr> aPoints = SketcherPrs_Tools::getFreePoints(compositeFeature());
+  for (std::list<ResultPtr>::iterator anIt = aPoints.begin(); anIt != aPoints.end(); ++anIt) {
+    FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt);
+    PointPtr aPoint(new SketchAPI_Point(aFeature));
+    aFreePoints.push_back(aPoint);
+  }
+  return aFreePoints;
+}
+
+//--------------------------------------------------------------------------------------
+static GeomCurvePtr untrimmedCurve(GeomShapePtr theShape)
+{
+  GeomCurvePtr aCurve(new GeomAPI_Curve(theShape));
+  if (aCurve->isTrimmed())
+    aCurve = aCurve->basisCurve();
+  return aCurve;
+}
+
+void SketchAPI_Sketch::changeFacesOrder(
+    const std::list<std::list<ModelHighAPI_Selection> >& theFaces)
+{
+  // collect faces of the sketch
+  ResultConstructionPtr aSketchResult =
+      std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(feature()->lastResult());
+  if (!aSketchResult) {
+    // sketch is nested to a boolean operation, thus, it has no result yet.
+    feature()->execute();
+    aSketchResult =
+        std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(feature()->lastResult());
+  }
+  std::list<GeomFacePtr> aFaces;
+  int aFacesNum = aSketchResult->facesNum();
+  for (int i = 0; i < aFacesNum; ++i)
+    aFaces.push_back(aSketchResult->face(i));
+  // find new faces order according to the given lists of edges
+  std::list<GeomFacePtr> aNewFacesOrder;
+  std::list<std::list<ModelHighAPI_Selection> >::const_iterator anIt = theFaces.begin();
+  for (; anIt != theFaces.end(); ++anIt) {
+    // find the appropriate face
+    std::list<GeomFacePtr>::iterator aFIt = aFaces.begin();
+    for (; aFIt != aFaces.end(); ++aFIt) {
+      std::list<ModelHighAPI_Selection>::const_iterator aEdgeIt = anIt->begin();
+      GeomAPI_ShapeExplorer aFExp(*aFIt, GeomAPI_Shape::EDGE);
+      for (; aEdgeIt != anIt->end() && aFExp.more(); ++aEdgeIt, aFExp.next()) {
+        ResultPtr aCurRes = aEdgeIt->resultSubShapePair().first;
+        if (!aCurRes)
+          break;
+        GeomCurvePtr aCurve1 = untrimmedCurve(aCurRes->shape());
+        GeomCurvePtr aCurve2 = untrimmedCurve(aFExp.current());
+        if (!aCurve1->isEqual(aCurve2))
+          break;
+      }
+
+      if (aEdgeIt == anIt->end() && !aFExp.more()) {
+        // face is found
+        aNewFacesOrder.push_back(*aFIt);
+        aFaces.erase(aFIt);
+        break;
+      }
+    }
+  }
+  // place the rest faces at the end of new faces list
+  if (!aFaces.empty())
+    aNewFacesOrder.insert(aNewFacesOrder.end(), aFaces.begin(), aFaces.end());
+  // update the result of the sketch with the new order of faces
+  aSketchResult->setFacesOrder(aNewFacesOrder);
+}
 
 //--------------------------------------------------------------------------------------
 std::shared_ptr<SketchAPI_Point> SketchAPI_Sketch::addPoint(
@@ -205,7 +349,7 @@ std::shared_ptr<SketchAPI_Point>
     compositeFeature()->addFeature(SketchPlugin_Point::ID());
   return PointPtr(new SketchAPI_Point(aFeature, theExternal));
 }
-std::shared_ptr<SketchAPI_Point> SketchAPI_Sketch::addPoint(const std::string & theExternalName)
+std::shared_ptr<SketchAPI_Point> SketchAPI_Sketch::addPoint(const std::wstring & theExternalName)
 {
   std::shared_ptr<ModelAPI_Feature> aFeature =
     compositeFeature()->addFeature(SketchPlugin_Point::ID());
@@ -214,18 +358,24 @@ std::shared_ptr<SketchAPI_Point> SketchAPI_Sketch::addPoint(const std::string &
 
 //--------------------------------------------------------------------------------------
 std::shared_ptr<SketchAPI_IntersectionPoint> SketchAPI_Sketch::addIntersectionPoint(
-    const ModelHighAPI_Selection & theExternal)
+    const ModelHighAPI_Selection & theExternal,
+    bool theKeepResult)
 {
   std::shared_ptr<ModelAPI_Feature> aFeature =
     compositeFeature()->addFeature(SketchPlugin_IntersectionPoint::ID());
-  return IntersectionPointPtr(new SketchAPI_IntersectionPoint(aFeature, theExternal));
+  IntersectionPointPtr anIntersection(new SketchAPI_IntersectionPoint(aFeature, theExternal));
+  anIntersection->setIncludeToResult(theKeepResult);
+  return anIntersection;
 }
 std::shared_ptr<SketchAPI_IntersectionPoint> SketchAPI_Sketch::addIntersectionPoint(
-    const std::string & theExternalName)
+    const std::wstring & theExternalName,
+    bool theKeepResult)
 {
   std::shared_ptr<ModelAPI_Feature> aFeature =
     compositeFeature()->addFeature(SketchPlugin_IntersectionPoint::ID());
-  return IntersectionPointPtr(new SketchAPI_IntersectionPoint(aFeature, theExternalName));
+  IntersectionPointPtr anIntersection(new SketchAPI_IntersectionPoint(aFeature, theExternalName));
+  anIntersection->setIncludeToResult(theKeepResult);
+  return anIntersection;
 }
 
 //--------------------------------------------------------------------------------------
@@ -251,7 +401,7 @@ std::shared_ptr<SketchAPI_Line>
     compositeFeature()->addFeature(SketchPlugin_Line::ID());
   return LinePtr(new SketchAPI_Line(aFeature, theExternal));
 }
-std::shared_ptr<SketchAPI_Line> SketchAPI_Sketch::addLine(const std::string & theExternalName)
+std::shared_ptr<SketchAPI_Line> SketchAPI_Sketch::addLine(const std::wstring & theExternalName)
 {
   std::shared_ptr<ModelAPI_Feature> aFeature =
     compositeFeature()->addFeature(SketchPlugin_Line::ID());
@@ -275,6 +425,49 @@ std::shared_ptr<SketchAPI_Rectangle> SketchAPI_Sketch::addRectangle(
   return RectanglePtr(new SketchAPI_Rectangle(aFeature, theStartPoint, theEndPoint));
 }
 
+static std::shared_ptr<GeomAPI_Pnt2d> pointCoordinates(
+    const std::pair<std::shared_ptr<GeomAPI_Pnt2d>, ModelHighAPI_RefAttr> & thePoint)
+{
+  if (thePoint.first)
+    return thePoint.first;
+
+  AttributePtr anAttr = thePoint.second.attr();
+  if (thePoint.second.object()) {
+    FeaturePtr aFeature = ModelAPI_Feature::feature(thePoint.second.object());
+    if (aFeature)
+      anAttr = aFeature->attribute(SketchPlugin_Point::COORD_ID());
+  }
+
+  std::shared_ptr<GeomDataAPI_Point2D> aPntAttr =
+      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr);
+  if (aPntAttr)
+    return aPntAttr->pnt();
+  return std::shared_ptr<GeomAPI_Pnt2d>();
+}
+
+std::shared_ptr<SketchAPI_Rectangle> SketchAPI_Sketch::addRectangleCentered(
+    const std::pair<std::shared_ptr<GeomAPI_Pnt2d>, ModelHighAPI_RefAttr> & theCenter,
+    const std::pair<std::shared_ptr<GeomAPI_Pnt2d>, ModelHighAPI_RefAttr> & theCorner)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature =
+    compositeFeature()->addFeature(SketchAPI_Rectangle::ID());
+  RectanglePtr aRect(new SketchAPI_Rectangle(aFeature));
+  fillAttribute("RectangleTypeCentered", aRect->type());
+  if (!theCenter.second.isEmpty())
+    fillAttribute(theCenter.second, aRect->centerPointRef());
+  fillAttribute(pointCoordinates(theCenter), aRect->centerPoint());
+  fillAttribute(pointCoordinates(theCorner), aRect->cornerPoint());
+  aRect->execute();
+
+  if (!theCorner.second.isEmpty() && aRect->linesList()->size() > 1) {
+    // get start point of the last line in rectangle and apply coindidence constraint
+    FeaturePtr aLine = ModelAPI_Feature::feature(aRect->linesList()->object(3));
+    AttributePtr aEndPnt = aLine->attribute(SketchPlugin_Line::START_ID());
+    setCoincident(ModelHighAPI_RefAttr(aEndPnt), theCorner.second);
+  }
+  return aRect;
+}
+
 //--------------------------------------------------------------------------------------
 std::shared_ptr<SketchAPI_Circle> SketchAPI_Sketch::addCircle(double theCenterX,
                                                               double theCenterY,
@@ -294,23 +487,45 @@ std::shared_ptr<SketchAPI_Circle> SketchAPI_Sketch::addCircle(
   return CirclePtr(new SketchAPI_Circle(aFeature, theCenter, theRadius));
 }
 
-std::shared_ptr<SketchAPI_Circle> SketchAPI_Sketch::addCircle(double theX1, double theY1,
-                                                              double theX2, double theY2,
-                                                              double theX3, double theY3)
+std::shared_ptr<SketchAPI_MacroCircle> SketchAPI_Sketch::addCircle(double theCenterX,
+                                                                   double theCenterY,
+                                                                   double thePassedX,
+                                                                   double thePassedY)
 {
   std::shared_ptr<ModelAPI_Feature> aFeature =
-    compositeFeature()->addFeature(SketchPlugin_Circle::ID());
-  return CirclePtr(new SketchAPI_Circle(aFeature, theX1, theY1, theX2, theY2, theX3, theY3));
+    compositeFeature()->addFeature(SketchPlugin_MacroCircle::ID());
+  return MacroCirclePtr(new SketchAPI_MacroCircle(aFeature, theCenterX, theCenterY,
+                                                            thePassedX, thePassedY));
 }
 
-std::shared_ptr<SketchAPI_Circle> SketchAPI_Sketch::addCircle(
-                                                const std::shared_ptr<GeomAPI_Pnt2d>& thePoint1,
-                                                const std::shared_ptr<GeomAPI_Pnt2d>& thePoint2,
-                                                const std::shared_ptr<GeomAPI_Pnt2d>& thePoint3)
+std::shared_ptr<SketchAPI_MacroCircle> SketchAPI_Sketch::addCircle(
+    const std::shared_ptr<GeomAPI_Pnt2d>& theCenterPoint,
+    const std::shared_ptr<GeomAPI_Pnt2d>& thePassedPoint)
 {
   std::shared_ptr<ModelAPI_Feature> aFeature =
-    compositeFeature()->addFeature(SketchPlugin_Circle::ID());
-  return CirclePtr(new SketchAPI_Circle(aFeature, thePoint1, thePoint2, thePoint3));
+    compositeFeature()->addFeature(SketchPlugin_MacroCircle::ID());
+  return MacroCirclePtr(new SketchAPI_MacroCircle(aFeature, theCenterPoint, thePassedPoint));
+}
+
+std::shared_ptr<SketchAPI_MacroCircle> SketchAPI_Sketch::addCircle(double theX1, double theY1,
+                                                                   double theX2, double theY2,
+                                                                   double theX3, double theY3)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature =
+    compositeFeature()->addFeature(SketchPlugin_MacroCircle::ID());
+  return MacroCirclePtr(new SketchAPI_MacroCircle(aFeature, theX1, theY1,
+                                                            theX2, theY2,
+                                                            theX3, theY3));
+}
+
+std::shared_ptr<SketchAPI_MacroCircle> SketchAPI_Sketch::addCircle(
+    const std::shared_ptr<GeomAPI_Pnt2d>& thePoint1,
+    const std::shared_ptr<GeomAPI_Pnt2d>& thePoint2,
+    const std::shared_ptr<GeomAPI_Pnt2d>& thePoint3)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature =
+    compositeFeature()->addFeature(SketchPlugin_MacroCircle::ID());
+  return MacroCirclePtr(new SketchAPI_MacroCircle(aFeature, thePoint1, thePoint2, thePoint3));
 }
 
 std::shared_ptr<SketchAPI_Circle>
@@ -321,9 +536,8 @@ std::shared_ptr<SketchAPI_Circle>
   return CirclePtr(new SketchAPI_Circle(aFeature, theExternal));
 }
 
-std::shared_ptr<SketchAPI_Circle> SketchAPI_Sketch::addCircle(const std::string & theExternalName)
+std::shared_ptr<SketchAPI_Circle> SketchAPI_Sketch::addCircle(const std::wstring & theExternalName)
 {
-  // TODO(spo): Add constraint SketchConstraintRigid like in PythonAPI. Is it necessary?
   std::shared_ptr<ModelAPI_Feature> aFeature =
     compositeFeature()->addFeature(SketchPlugin_Circle::ID());
   return CirclePtr(new SketchAPI_Circle(aFeature, theExternalName));
@@ -355,46 +569,58 @@ std::shared_ptr<SketchAPI_Arc> SketchAPI_Sketch::addArc(
   return ArcPtr(new SketchAPI_Arc(aFeature, theCenter, theStart, theEnd, theInversed));
 }
 
-std::shared_ptr<SketchAPI_Arc> SketchAPI_Sketch::addArc(double theStartX, double theStartY,
+std::shared_ptr<SketchAPI_MacroArc> SketchAPI_Sketch::addArc(double theStartX, double theStartY,
                                                         double theEndX, double theEndY,
                                                         double thePassedX, double thePassedY)
 {
   std::shared_ptr<ModelAPI_Feature> aFeature =
-    compositeFeature()->addFeature(SketchPlugin_Arc::ID());
-  return ArcPtr(new SketchAPI_Arc(aFeature,
-                                  theStartX, theStartY,
-                                  theEndX, theEndY,
-                                  thePassedX, thePassedY));
+    compositeFeature()->addFeature(SketchPlugin_MacroArc::ID());
+  return MacroArcPtr(new SketchAPI_MacroArc(aFeature,
+                                       theStartX, theStartY,
+                                       theEndX, theEndY,
+                                       thePassedX, thePassedY));
 }
 
-std::shared_ptr<SketchAPI_Arc> SketchAPI_Sketch::addArc(
+std::shared_ptr<SketchAPI_MacroArc> SketchAPI_Sketch::addArc(
                                                 const std::shared_ptr<GeomAPI_Pnt2d>& theStart,
                                                 const std::shared_ptr<GeomAPI_Pnt2d>& theEnd,
                                                 const std::shared_ptr<GeomAPI_Pnt2d>& thePassed)
 {
   std::shared_ptr<ModelAPI_Feature> aFeature =
-    compositeFeature()->addFeature(SketchPlugin_Arc::ID());
-  return ArcPtr(new SketchAPI_Arc(aFeature, theStart, theEnd, thePassed));
+    compositeFeature()->addFeature(SketchPlugin_MacroArc::ID());
+  return MacroArcPtr(new SketchAPI_MacroArc(aFeature, theStart, theEnd, thePassed));
 }
 
-std::shared_ptr<SketchAPI_Arc> SketchAPI_Sketch::addArc(
+std::shared_ptr<SketchAPI_MacroArc> SketchAPI_Sketch::addArc(
                                                 const ModelHighAPI_RefAttr& theTangentPoint,
                                                 double theEndX, double theEndY,
-                                                bool theInversed)
+                                                bool theInversed,
+                                                bool theTransversal)
 {
   std::shared_ptr<ModelAPI_Feature> aFeature =
-    compositeFeature()->addFeature(SketchPlugin_Arc::ID());
-  return ArcPtr(new SketchAPI_Arc(aFeature, theTangentPoint, theEndX, theEndY, theInversed));
+    compositeFeature()->addFeature(SketchPlugin_MacroArc::ID());
+  MacroArcPtr aMacroArc(new SketchAPI_MacroArc(aFeature));
+  if (theTransversal)
+    aMacroArc->setByTransversal(theTangentPoint, theEndX, theEndY, theInversed);
+  else
+    aMacroArc->setByTangent(theTangentPoint, theEndX, theEndY, theInversed);
+  return aMacroArc;
 }
 
-std::shared_ptr<SketchAPI_Arc> SketchAPI_Sketch::addArc(
+std::shared_ptr<SketchAPI_MacroArc> SketchAPI_Sketch::addArc(
                                               const ModelHighAPI_RefAttr& theTangentPoint,
                                               const std::shared_ptr<GeomAPI_Pnt2d>& theEnd,
-                                              bool theInversed)
+                                              bool theInversed,
+                                              bool theTransversal)
 {
   std::shared_ptr<ModelAPI_Feature> aFeature =
-    compositeFeature()->addFeature(SketchPlugin_Arc::ID());
-  return ArcPtr(new SketchAPI_Arc(aFeature, theTangentPoint, theEnd, theInversed));
+    compositeFeature()->addFeature(SketchPlugin_MacroArc::ID());
+  MacroArcPtr aMacroArc(new SketchAPI_MacroArc(aFeature));
+  if (theTransversal)
+    aMacroArc->setByTransversal(theTangentPoint, theEnd, theInversed);
+  else
+    aMacroArc->setByTangent(theTangentPoint, theEnd, theInversed);
+  return aMacroArc;
 }
 
 std::shared_ptr<SketchAPI_Arc> SketchAPI_Sketch::addArc(const ModelHighAPI_Selection & theExternal)
@@ -404,29 +630,290 @@ std::shared_ptr<SketchAPI_Arc> SketchAPI_Sketch::addArc(const ModelHighAPI_Selec
   return ArcPtr(new SketchAPI_Arc(aFeature, theExternal));
 }
 
-std::shared_ptr<SketchAPI_Arc> SketchAPI_Sketch::addArc(const std::string & theExternalName)
+std::shared_ptr<SketchAPI_Arc> SketchAPI_Sketch::addArc(const std::wstring & theExternalName)
 {
-  // TODO(spo): Add constraint SketchConstraintRigid like in PythonAPI. Is it necessary?
   std::shared_ptr<ModelAPI_Feature> aFeature =
     compositeFeature()->addFeature(SketchPlugin_Arc::ID());
   return ArcPtr(new SketchAPI_Arc(aFeature, theExternalName));
 }
 
 //--------------------------------------------------------------------------------------
-std::shared_ptr<SketchAPI_Projection> SketchAPI_Sketch::addProjection(
-    const ModelHighAPI_Selection & theExternalFeature)
+std::shared_ptr<SketchAPI_Ellipse> SketchAPI_Sketch::addEllipse(
+    double theCenterX, double theCenterY,
+    double theFocusX, double theFocusY,
+    double theMinorRadius)
 {
   std::shared_ptr<ModelAPI_Feature> aFeature =
-    compositeFeature()->addFeature(SketchPlugin_Projection::ID());
-  return ProjectionPtr(new SketchAPI_Projection(aFeature, theExternalFeature));
+      compositeFeature()->addFeature(SketchPlugin_Ellipse::ID());
+  return EllipsePtr(new SketchAPI_Ellipse(aFeature,
+      theCenterX, theCenterY, theFocusX, theFocusY, theMinorRadius));
+}
+
+std::shared_ptr<SketchAPI_Ellipse> SketchAPI_Sketch::addEllipse(
+    const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
+    const std::shared_ptr<GeomAPI_Pnt2d>& theFocus,
+    double theMinorRadius)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature =
+      compositeFeature()->addFeature(SketchPlugin_Ellipse::ID());
+  return EllipsePtr(new SketchAPI_Ellipse(aFeature, theCenter, theFocus, theMinorRadius));
+}
+
+std::shared_ptr<SketchAPI_MacroEllipse> SketchAPI_Sketch::addEllipse(
+    double thePoint1X, double thePoint1Y,
+    double thePoint2X, double thePoint2Y,
+    double thePassedX, double thePassedY,
+    bool isPoint1Center)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature =
+      compositeFeature()->addFeature(SketchPlugin_MacroEllipse::ID());
+  return MacroEllipsePtr(new SketchAPI_MacroEllipse(aFeature,
+      thePoint1X, thePoint1Y, thePoint2X, thePoint2Y, thePassedX, thePassedY, isPoint1Center));
+}
+
+std::shared_ptr<SketchAPI_MacroEllipse> SketchAPI_Sketch::addEllipse(
+    const PointOrReference& thePoint1,
+    const PointOrReference& thePoint2,
+    const PointOrReference& thePassedPoint,
+    bool isPoint1Center)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature =
+      compositeFeature()->addFeature(SketchPlugin_MacroEllipse::ID());
+  MacroEllipsePtr anEllipse;
+  if (thePoint1.second.isEmpty() &&
+      thePoint2.second.isEmpty() &&
+      thePassedPoint.second.isEmpty()) {
+    anEllipse.reset(new SketchAPI_MacroEllipse(aFeature,
+        thePoint1.first, thePoint2.first, thePassedPoint.first, isPoint1Center));
+  }
+  else {
+    anEllipse.reset(new SketchAPI_MacroEllipse(aFeature,
+        thePoint1.first, thePoint1.second,
+        thePoint2.first, thePoint2.second,
+        thePassedPoint.first, thePassedPoint.second,
+        isPoint1Center));
+  }
+  return anEllipse;
+}
+
+std::shared_ptr<SketchAPI_Ellipse> SketchAPI_Sketch::addEllipse(
+    const ModelHighAPI_Selection & theExternal)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature =
+      compositeFeature()->addFeature(SketchPlugin_Ellipse::ID());
+  return EllipsePtr(new SketchAPI_Ellipse(aFeature, theExternal));
+}
+
+std::shared_ptr<SketchAPI_Ellipse> SketchAPI_Sketch::addEllipse(
+    const std::wstring & theExternalName)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature =
+      compositeFeature()->addFeature(SketchPlugin_Ellipse::ID());
+  return EllipsePtr(new SketchAPI_Ellipse(aFeature, theExternalName));
+}
+
+//--------------------------------------------------------------------------------------
+std::shared_ptr<SketchAPI_EllipticArc> SketchAPI_Sketch::addEllipticArc(
+    double theCenterX, double theCenterY,
+    double theFocusX, double theFocusY,
+    double theStartX, double theStartY,
+    double theEndX, double theEndY,
+    bool theInversed)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature =
+      compositeFeature()->addFeature(SketchPlugin_EllipticArc::ID());
+  return EllipticArcPtr(new SketchAPI_EllipticArc(aFeature,
+      theCenterX, theCenterY,
+      theFocusX, theFocusY,
+      theStartX, theStartY,
+      theEndX, theEndY,
+      theInversed));
+}
+
+std::shared_ptr<SketchAPI_MacroEllipticArc> SketchAPI_Sketch::addEllipticArc(
+    const PointOrReference& theCenter,
+    const PointOrReference& theMajorAxisPoint,
+    const PointOrReference& theStartPoint,
+    const PointOrReference& theEndPoint,
+    bool theInversed)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature =
+      compositeFeature()->addFeature(SketchPlugin_MacroEllipticArc::ID());
+  return MacroEllipticArcPtr(new SketchAPI_MacroEllipticArc(aFeature,
+      theCenter.first, theCenter.second,
+      theMajorAxisPoint.first, theMajorAxisPoint.second,
+      theStartPoint.first, theStartPoint.second,
+      theEndPoint.first, theEndPoint.second,
+      theInversed));
 }
 
+std::shared_ptr<SketchAPI_EllipticArc> SketchAPI_Sketch::addEllipticArc(
+    const ModelHighAPI_Selection & theExternal)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature =
+      compositeFeature()->addFeature(SketchPlugin_EllipticArc::ID());
+  return EllipticArcPtr(new SketchAPI_EllipticArc(aFeature, theExternal));
+}
+
+std::shared_ptr<SketchAPI_EllipticArc> SketchAPI_Sketch::addEllipticArc(
+    const std::wstring & theExternalName)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature =
+      compositeFeature()->addFeature(SketchPlugin_EllipticArc::ID());
+  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<PointOrReference>& poles,
+    const std::list<ModelHighAPI_Double>& weights,
+    const std::list<ModelHighAPI_Double>& knots,
+    const std::list<ModelHighAPI_Integer>& multiplicities,
+    const bool periodic)
+{
+  // split poles and references to other shapes
+  bool hasReference = false;
+  std::list<GeomPnt2dPtr> aPoints;
+  std::list<ModelHighAPI_RefAttr> aReferences;
+  for (std::list<PointOrReference>::const_iterator it = poles.begin(); it != poles.end(); ++it) {
+    aPoints.push_back(it->first);
+    aReferences.push_back(it->second);
+    if (!it->second.isEmpty())
+      hasReference = true;
+  }
+
+  BSplinePtr aBSpline;
+  CompositeFeaturePtr aSketch = compositeFeature();
+  if (hasReference) {
+    // use macro-feature to create coincidences to referred features
+    FeaturePtr aMacroFeature = aSketch->addFeature(
+        periodic ? SketchPlugin_MacroBSplinePeriodic::ID() : SketchPlugin_MacroBSpline::ID());
+    AttributePoint2DArrayPtr aPolesAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(
+        aMacroFeature->attribute(SketchPlugin_MacroBSpline::POLES_ID()));
+    AttributeDoubleArrayPtr aWeightsAttr =
+        aMacroFeature->data()->realArray(SketchPlugin_MacroBSpline::WEIGHTS_ID());
+    AttributeRefAttrListPtr aPolesRefAttr =
+        aMacroFeature->data()->refattrlist(SketchPlugin_MacroBSpline::REF_POLES_ID());
+    // always generate a control polygon to apply coincidences correctly
+    aMacroFeature->boolean(SketchPlugin_MacroBSpline::CONTROL_POLYGON_ID())->setValue(true);
+    // initialize B-spline attributes
+    fillAttribute(aPoints, aPolesAttr);
+    if (weights.empty())
+      fillAttribute(std::list<ModelHighAPI_Double>(poles.size(), 1.0), aWeightsAttr);
+    else
+      fillAttribute(weights, aWeightsAttr);
+    fillAttribute(aReferences, aPolesRefAttr);
+    apply(); // to kill macro-feature
+
+    // find created B-spline feature
+    const std::string& aKindToFind =
+        periodic ? SketchPlugin_BSplinePeriodic::ID() : SketchPlugin_BSpline::ID();
+    int aNbSubs = aSketch->numberOfSubs();
+    for (int anIndex = aNbSubs - 1; anIndex >= 0; --anIndex) {
+      FeaturePtr aFeature = aSketch->subFeature(anIndex);
+      if (aFeature->getKind() == aKindToFind) {
+        aBSpline.reset(periodic ? new SketchAPI_BSplinePeriodic(aFeature)
+                                : new SketchAPI_BSpline(aFeature));
+        aBSpline->execute();
+        break;
+      }
+    }
+  }
+  else {
+    // compute B-spline by parameters
+    FeaturePtr aFeature = aSketch->addFeature(
+        periodic ? SketchPlugin_BSplinePeriodic::ID() : SketchPlugin_BSpline::ID());
+
+    aBSpline.reset(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, aPoints, weights);
+    else
+      aBSpline->setByParameters(degree, aPoints, weights, knots, multiplicities);
+  }
+  return aBSpline;
+}
+
+//--------------------------------------------------------------------------------------
+static std::shared_ptr<SketchAPI_BSpline> buildInterpolation(
+    const CompositeFeaturePtr& theSketch,
+    const FeaturePtr& theCurveFittingFeature,
+    const std::list<ModelHighAPI_RefAttr>& points,
+    const bool periodic,
+    const bool closed)
+{
+  AttributeBooleanPtr aPeriodicAttr =
+      theCurveFittingFeature->boolean(SketchPlugin_CurveFitting::PERIODIC_ID());
+  fillAttribute(periodic, aPeriodicAttr);
+  AttributeBooleanPtr aClosedAttr =
+      theCurveFittingFeature->boolean(SketchPlugin_CurveFitting::CLOSED_ID());
+  fillAttribute(closed, aClosedAttr);
+  AttributeRefAttrListPtr aPointsAttr =
+      theCurveFittingFeature->refattrlist(SketchPlugin_CurveFitting::POINTS_ID());
+  fillAttribute(points, aPointsAttr);
+  apply(); // to execute and kill the macro-feature
+
+  // find created B-spline feature
+  BSplinePtr aBSpline;
+  const std::string& aKindToFind =
+      periodic ? SketchPlugin_BSplinePeriodic::ID() : SketchPlugin_BSpline::ID();
+  int aNbSubs = theSketch->numberOfSubs();
+  for (int anIndex = aNbSubs - 1; anIndex >= 0; --anIndex) {
+    FeaturePtr aFeature = theSketch->subFeature(anIndex);
+    if (aFeature->getKind() == aKindToFind) {
+      aBSpline.reset(periodic ? new SketchAPI_BSplinePeriodic(aFeature)
+        : new SketchAPI_BSpline(aFeature));
+      aBSpline->execute();
+      break;
+    }
+  }
+  return aBSpline;
+}
+
+std::shared_ptr<SketchAPI_BSpline> SketchAPI_Sketch::addInterpolation(
+    const std::list<ModelHighAPI_RefAttr>& points,
+    const bool periodic,
+    const bool closed)
+{
+  CompositeFeaturePtr aSketch = compositeFeature();
+  FeaturePtr anInterpFeature = aSketch->addFeature(SketchPlugin_CurveFitting::ID());
+  anInterpFeature->string(SketchPlugin_CurveFitting::TYPE_ID())
+      ->setValue(SketchPlugin_CurveFitting::TYPE_INTERPOLATION_ID());
+  return buildInterpolation(aSketch, anInterpFeature, points, periodic, closed);
+}
+
+std::shared_ptr<SketchAPI_BSpline> SketchAPI_Sketch::addApproximation(
+    const std::list<ModelHighAPI_RefAttr>& points,
+    const ModelHighAPI_Double& precision,
+    const bool periodic,
+    const bool closed)
+{
+  CompositeFeaturePtr aSketch = compositeFeature();
+  FeaturePtr anInterpFeature = aSketch->addFeature(SketchPlugin_CurveFitting::ID());
+  anInterpFeature->string(SketchPlugin_CurveFitting::TYPE_ID())
+      ->setValue(SketchPlugin_CurveFitting::TYPE_APPROXIMATION_ID());
+  fillAttribute(precision, anInterpFeature->real(SketchPlugin_CurveFitting::PRECISION_ID()));
+  return buildInterpolation(aSketch, anInterpFeature, points, periodic, closed);
+}
+
+//--------------------------------------------------------------------------------------
 std::shared_ptr<SketchAPI_Projection> SketchAPI_Sketch::addProjection(
-    const std::string & theExternalName)
+    const ModelHighAPI_Selection & theExternalFeature,
+    bool keepResult,
+    bool keepRefToOriginal)
 {
   std::shared_ptr<ModelAPI_Feature> aFeature =
     compositeFeature()->addFeature(SketchPlugin_Projection::ID());
-  return ProjectionPtr(new SketchAPI_Projection(aFeature, theExternalName));
+  ProjectionPtr aProjection(new SketchAPI_Projection(aFeature));
+  aProjection->setIncludeToResult(keepResult);
+  aProjection->setKeepReferenceToOriginal(keepRefToOriginal);
+  aProjection->setExternalFeature(theExternalFeature);
+  return aProjection;
 }
 
 //--------------------------------------------------------------------------------------
@@ -439,6 +926,18 @@ std::shared_ptr<SketchAPI_Mirror> SketchAPI_Sketch::addMirror(
   return MirrorPtr(new SketchAPI_Mirror(aFeature, theMirrorLine, theObjects));
 }
 
+//--------------------------------------------------------------------------------------
+std::shared_ptr<SketchAPI_Offset> SketchAPI_Sketch::addOffset(
+    const std::list<std::shared_ptr<ModelAPI_Object> > & theObjects,
+    const ModelHighAPI_Double & theValue,
+    const bool theReversed,
+    const std::string & theJointType)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature =
+    compositeFeature()->addFeature(SketchPlugin_Offset::ID());
+  return OffsetPtr(new SketchAPI_Offset(aFeature, theObjects, theValue, theReversed, theJointType));
+}
+
 //--------------------------------------------------------------------------------------
 std::shared_ptr<SketchAPI_Translation> SketchAPI_Sketch::addTranslation(
     const std::list<std::shared_ptr<ModelAPI_Object> > & theObjects,
@@ -459,27 +958,31 @@ std::shared_ptr<SketchAPI_Rotation> SketchAPI_Sketch::addRotation(
     const ModelHighAPI_RefAttr & theCenter,
     const ModelHighAPI_Double & theAngle,
     const ModelHighAPI_Integer & theNumberOfObjects,
-    bool theFullValue)
+    bool theFullValue,
+    bool theReversed)
 {
   std::shared_ptr<ModelAPI_Feature> aFeature =
     compositeFeature()->addFeature(SketchPlugin_MultiRotation::ID());
   return RotationPtr(
     new SketchAPI_Rotation(aFeature, theObjects, theCenter,
-                           theAngle, theNumberOfObjects, theFullValue));
+                           theAngle, theNumberOfObjects, theFullValue, theReversed));
 }
 
 //--------------------------------------------------------------------------------------
 std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::addSplit(
-                                                    const ModelHighAPI_Reference& theFeature,
-                                                    const ModelHighAPI_RefAttr& thePoint1,
-                                                    const ModelHighAPI_RefAttr& thePoint2)
+                                          const ModelHighAPI_Reference& theFeature,
+                                          const std::shared_ptr<GeomAPI_Pnt2d>& thePositionPoint)
 {
   std::shared_ptr<ModelAPI_Feature> aFeature =
-    compositeFeature()->addFeature(SketchPlugin_ConstraintSplit::ID());
-  fillAttribute(theFeature, aFeature->reference(SketchPlugin_Constraint::VALUE()));
-  fillAttribute(thePoint1, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A()));
-  fillAttribute(thePoint2, aFeature->refattr(SketchPlugin_Constraint::ENTITY_B()));
-  //aFeature->execute();
+    compositeFeature()->addFeature(SketchPlugin_Split::ID());
+  fillAttribute(theFeature, aFeature->reference(SketchPlugin_Split::SELECTED_OBJECT()));
+
+  AttributePtr anAttribute = aFeature->attribute(SketchPlugin_Split::SELECTED_POINT());
+  if (anAttribute->attributeType() == GeomDataAPI_Point2D::typeId()) {
+    AttributePoint2DPtr aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttribute);
+    fillAttribute(thePositionPoint, aPointAttr);
+  }
+
   return InterfacePtr(new ModelHighAPI_Interface(aFeature));
 }
 
@@ -490,9 +993,9 @@ std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::addTrim(
 {
   std::shared_ptr<ModelAPI_Feature> aFeature =
     compositeFeature()->addFeature(SketchPlugin_Trim::ID());
-  fillAttribute(theFeature, aFeature->reference(SketchPlugin_Trim::BASE_OBJECT()));
+  fillAttribute(theFeature, aFeature->reference(SketchPlugin_Trim::SELECTED_OBJECT()));
 
-  AttributePtr anAttribute = aFeature->attribute(SketchPlugin_Trim::ENTITY_POINT());
+  AttributePtr anAttribute = aFeature->attribute(SketchPlugin_Trim::SELECTED_POINT());
   if (anAttribute->attributeType() == GeomDataAPI_Point2D::typeId()) {
     AttributePoint2DPtr aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttribute);
     fillAttribute(thePositionPoint, aPointAttr);
@@ -505,16 +1008,39 @@ 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
-  fillAttribute(theValue, aFeature->real(SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID()));
+
+  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()));
+
+  if (aVersion == SketchPlugin_ConstraintAngle::THE_VERSION_1) {
+    std::string aTypeLC = theType;
+    std::transform(aTypeLC.begin(), aTypeLC.end(), aTypeLC.begin(),
+                   [](char c) { return static_cast<char>(::tolower(c)); });
+    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));
 }
@@ -526,12 +1052,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_Constraint::VALUE()));
   aFeature->execute();
   return InterfacePtr(new ModelHighAPI_Interface(aFeature));
 }
@@ -543,12 +1070,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_Constraint::VALUE()));
   aFeature->execute();
   return InterfacePtr(new ModelHighAPI_Interface(aFeature));
 }
@@ -580,13 +1108,61 @@ std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setCollinear(
 std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setDistance(
     const ModelHighAPI_RefAttr & thePoint,
     const ModelHighAPI_RefAttr & thePointOrLine,
-    const ModelHighAPI_Double & theValue)
+    const ModelHighAPI_Double & theValue,
+    bool isSigned)
 {
   std::shared_ptr<ModelAPI_Feature> aFeature =
       compositeFeature()->addFeature(SketchPlugin_ConstraintDistance::ID());
   fillAttribute(thePoint, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A()));
   fillAttribute(thePointOrLine, aFeature->refattr(SketchPlugin_Constraint::ENTITY_B()));
   fillAttribute(theValue, aFeature->real(SketchPlugin_Constraint::VALUE()));
+  fillAttribute(isSigned, aFeature->boolean(SketchPlugin_ConstraintDistance::SIGNED()));
+  aFeature->execute();
+  return InterfacePtr(new ModelHighAPI_Interface(aFeature));
+}
+
+std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setSignedDistance(
+    const ModelHighAPI_RefAttr & thePoint,
+    const ModelHighAPI_RefAttr & thePointOrLine,
+    const ModelHighAPI_Double & theValue)
+{
+  return setDistance(thePoint, thePointOrLine, theValue, true);
+}
+
+std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setUnsignedDistance(
+    const ModelHighAPI_RefAttr & thePoint,
+    const ModelHighAPI_RefAttr & thePointOrLine,
+    const ModelHighAPI_Double & theValue)
+{
+  return setDistance(thePoint, thePointOrLine, theValue, false);
+}
+
+std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setHorizontalDistance(
+    const ModelHighAPI_RefAttr & thePoint1,
+    const ModelHighAPI_RefAttr & thePoint2,
+    const ModelHighAPI_Double & theValue)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature =
+      compositeFeature()->addFeature(SketchPlugin_ConstraintDistanceHorizontal::ID());
+  fillAttribute(thePoint1, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A()));
+  fillAttribute(thePoint2, aFeature->refattr(SketchPlugin_Constraint::ENTITY_B()));
+  fillAttribute(theValue,
+      aFeature->real(SketchPlugin_ConstraintDistanceAlongDir::DISTANCE_VALUE_ID()));
+  aFeature->execute();
+  return InterfacePtr(new ModelHighAPI_Interface(aFeature));
+}
+
+std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setVerticalDistance(
+    const ModelHighAPI_RefAttr & thePoint1,
+    const ModelHighAPI_RefAttr & thePoint2,
+    const ModelHighAPI_Double & theValue)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature =
+      compositeFeature()->addFeature(SketchPlugin_ConstraintDistanceVertical::ID());
+  fillAttribute(thePoint1, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A()));
+  fillAttribute(thePoint2, aFeature->refattr(SketchPlugin_Constraint::ENTITY_B()));
+  fillAttribute(theValue,
+      aFeature->real(SketchPlugin_ConstraintDistanceAlongDir::DISTANCE_VALUE_ID()));
   aFeature->execute();
   return InterfacePtr(new ModelHighAPI_Interface(aFeature));
 }
@@ -735,6 +1311,261 @@ std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setVertical(
 
 //--------------------------------------------------------------------------------------
 
+static std::shared_ptr<GeomAPI_Pnt2d> pointCoordinates(const AttributePtr& thePoint)
+{
+  AttributePoint2DPtr aPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(thePoint);
+  return aPnt ? aPnt->pnt() : std::shared_ptr<GeomAPI_Pnt2d>();
+}
+
+static std::shared_ptr<GeomAPI_Pnt2d> middlePointOnLine(const FeaturePtr& theFeature)
+{
+  AttributePoint2DPtr aStartAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+      theFeature->attribute(SketchPlugin_Line::START_ID()));
+  AttributePoint2DPtr aEndAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+      theFeature->attribute(SketchPlugin_Line::END_ID()));
+
+  if (!aStartAttr || !aEndAttr)
+    return std::shared_ptr<GeomAPI_Pnt2d>();
+
+  std::shared_ptr<GeomAPI_XY> aStartPoint = aStartAttr->pnt()->xy();
+  std::shared_ptr<GeomAPI_XY> aEndPoint = aEndAttr->pnt()->xy();
+  return std::shared_ptr<GeomAPI_Pnt2d>(
+      new GeomAPI_Pnt2d(aStartPoint->added(aEndPoint)->multiplied(0.5)));
+}
+
+static std::shared_ptr<GeomAPI_Pnt2d> pointOnCircle(const FeaturePtr& theFeature)
+{
+  AttributePoint2DPtr aCenter = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+      theFeature->attribute(SketchPlugin_Circle::CENTER_ID()));
+  AttributeDoublePtr aRadius = theFeature->real(SketchPlugin_Circle::RADIUS_ID());
+
+  if (!aCenter || !aRadius)
+    return std::shared_ptr<GeomAPI_Pnt2d>();
+
+  return std::shared_ptr<GeomAPI_Pnt2d>(
+      new GeomAPI_Pnt2d(aCenter->x() + aRadius->value(), aCenter->y()));
+}
+
+static std::shared_ptr<GeomAPI_Pnt2d> middlePointOnArc(const FeaturePtr& theFeature)
+{
+  static const double PI = 3.141592653589793238463;
+
+  AttributePoint2DPtr aCenterAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+      theFeature->attribute(SketchPlugin_Arc::CENTER_ID()));
+  AttributePoint2DPtr aStartAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+      theFeature->attribute(SketchPlugin_Arc::START_ID()));
+  AttributePoint2DPtr aEndAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+      theFeature->attribute(SketchPlugin_Arc::END_ID()));
+
+  if (!aCenterAttr || !aStartAttr || !aEndAttr)
+    return std::shared_ptr<GeomAPI_Pnt2d>();
+
+  std::shared_ptr<GeomAPI_Dir2d> aStartDir(new GeomAPI_Dir2d(
+      aStartAttr->x() - aCenterAttr->x(), aStartAttr->y() - aCenterAttr->y()));
+  std::shared_ptr<GeomAPI_Dir2d> aEndDir(new GeomAPI_Dir2d(
+      aEndAttr->x() - aCenterAttr->x(), aEndAttr->y() - aCenterAttr->y()));
+
+  double anAngle = aStartDir->angle(aEndDir);
+  bool isReversed = theFeature->boolean(SketchPlugin_Arc::REVERSED_ID())->value();
+  if (isReversed && anAngle > 0.)
+    anAngle -= 2.0 * PI;
+  else if (!isReversed && anAngle <= 0.)
+    anAngle += 2.0 * PI;
+
+  double cosA = cos(anAngle);
+  double sinA = sin(anAngle);
+
+  // rotate start dir to find middle point on arc
+  double aRadius = aStartAttr->pnt()->distance(aCenterAttr->pnt());
+  double x = aCenterAttr->x() + aRadius * (aStartDir->x() * cosA - aStartDir->y() * sinA);
+  double y = aCenterAttr->y() + aRadius * (aStartDir->x() * sinA + aStartDir->y() * cosA);
+
+  return std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(x, y));
+}
+
+static std::shared_ptr<GeomAPI_Pnt2d> pointOnEllipse(const FeaturePtr& theFeature,
+                                                     bool isEllipse = true)
+{
+  const std::string& anAttrName = isEllipse ? SketchPlugin_Ellipse::MAJOR_AXIS_END_ID() :
+                                  SketchPlugin_EllipticArc::MAJOR_AXIS_END_ID();
+  AttributePoint2DPtr aMajorAxisEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+      theFeature->attribute(anAttrName));
+  return aMajorAxisEnd ? aMajorAxisEnd->pnt() : std::shared_ptr<GeomAPI_Pnt2d>();
+}
+
+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);
+  if (aFeature) {
+    // move only features of the following types
+    const std::string& aFeatureKind = aFeature->getKind();
+    if (aFeatureKind == SketchPlugin_Point::ID())
+      aMiddlePoint = pointCoordinates(aFeature->attribute(SketchPlugin_Point::COORD_ID()));
+    else if (aFeatureKind == SketchPlugin_Line::ID())
+      aMiddlePoint = middlePointOnLine(aFeature);
+    else if (aFeatureKind == SketchPlugin_Circle::ID())
+      aMiddlePoint = pointOnCircle(aFeature);
+    else if (aFeatureKind == SketchPlugin_Arc::ID())
+      aMiddlePoint = middlePointOnArc(aFeature);
+    else if (aFeatureKind == SketchPlugin_Ellipse::ID())
+      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;
+}
+
+void SketchAPI_Sketch::move(const ModelHighAPI_RefAttr& theMovedEntity,
+                            const std::shared_ptr<GeomAPI_Pnt2d>& theTargetPoint)
+{
+  std::shared_ptr<ModelAPI_ObjectMovedMessage> aMessage(new ModelAPI_ObjectMovedMessage);
+  theMovedEntity.fillMessage(aMessage);
+
+  std::shared_ptr<GeomAPI_Pnt2d> anOriginalPosition;
+  if (aMessage->movedAttribute())
+    anOriginalPosition = pointCoordinates(aMessage->movedAttribute());
+  else
+    anOriginalPosition = middlePoint(aMessage->movedObject(), this);
+
+  if (!anOriginalPosition)
+    return; // something has gone wrong, do not process movement
+
+  aMessage->setOriginalPosition(anOriginalPosition);
+  aMessage->setCurrentPosition(theTargetPoint);
+  Events_Loop::loop()->send(aMessage);
+}
+
+void SketchAPI_Sketch::move(const ModelHighAPI_RefAttr& theMovedEntity,
+                            double theTargetX, double theTargetY)
+{
+  std::shared_ptr<GeomAPI_Pnt2d> aTargetPoint(new GeomAPI_Pnt2d(theTargetX, theTargetY));
+  move(theMovedEntity, aTargetPoint);
+}
+
+//--------------------------------------------------------------------------------------
+
+std::shared_ptr<GeomAPI_Pnt2d> SketchAPI_Sketch::to2D(const std::shared_ptr<GeomAPI_Pnt>& thePoint)
+{
+  FeaturePtr aBase = feature();
+  std::shared_ptr<GeomDataAPI_Point> aC = std::dynamic_pointer_cast<GeomDataAPI_Point>(
+      aBase->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
+  std::shared_ptr<GeomDataAPI_Dir> aNorm = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+      aBase->attribute(SketchPlugin_Sketch::NORM_ID()));
+  std::shared_ptr<GeomDataAPI_Dir> aX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+      aBase->attribute(SketchPlugin_Sketch::DIRX_ID()));
+  std::shared_ptr<GeomAPI_Dir> aY(new GeomAPI_Dir(aNorm->dir()->cross(aX->dir())));
+
+  return thePoint->to2D(aC->pnt(), aX->dir(), aY);
+}
+
+//--------------------------------------------------------------------------------------
+
+static bool isDifferent(GeomFacePtr theFace1, GeomFacePtr theFace2)
+{
+  // collect edges of the first face
+  std::list<GeomShapePtr> anEdges1;
+  for (GeomAPI_ShapeExplorer anExp(theFace1, GeomAPI_Shape::EDGE); anExp.more(); anExp.next())
+    anEdges1.push_back(anExp.current());
+  // compare edges of faces
+  for (GeomAPI_ShapeExplorer anExp(theFace2, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) {
+    GeomShapePtr aCurrent = anExp.current();
+    bool isFound = false;
+    std::list<GeomShapePtr>::iterator anIt1 = anEdges1.begin();
+    for (; anIt1 != anEdges1.end(); ++anIt1)
+      if (aCurrent->isSameGeometry(*anIt1)) {
+        isFound = true;
+        anEdges1.erase(anIt1);
+        break;
+      }
+    if (!isFound)
+      return true;
+  }
+  return !anEdges1.empty();
+}
+
+static bool isCustomFacesOrder(CompositeFeaturePtr theSketch)
+{
+  ResultConstructionPtr aSketchResult =
+      std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(theSketch->lastResult());
+  if (!aSketchResult)
+    return false;
+
+  std::shared_ptr<GeomAPI_PlanarEdges> aWires =
+      std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aSketchResult->shape());
+  if (!aWires)
+    return false;
+
+  // collect faces constructed by SketchBuilder algorithm
+  GeomAlgoAPI_SketchBuilder aSketchBuilder(aWires->origin(), aWires->dirX(),
+                                           aWires->norm(), aWires);
+  const ListOfShape& aFaces = aSketchBuilder.faces();
+
+  // compare faces stored in sketch with faces generated by SketchBuilder
+  int aNbSketchFaces = aSketchResult->facesNum();
+  int aFaceIndex = 0;
+  for (ListOfShape::const_iterator aFIt = aFaces.begin();
+       aFIt != aFaces.end() && aFaceIndex < aNbSketchFaces;
+       ++aFIt, ++aFaceIndex) {
+    GeomFacePtr aSketchFace = aSketchResult->face(aFaceIndex);
+    GeomFacePtr aCurFace = (*aFIt)->face();
+    if (isDifferent(aSketchFace, aCurFace))
+      return true;
+  }
+  return false;
+}
+
+static void edgesOfSketchFaces(CompositeFeaturePtr theSketch,
+                               std::list<std::list<ResultPtr> >& theEdges)
+{
+  ResultConstructionPtr aSketchResult =
+      std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(theSketch->lastResult());
+  if (!aSketchResult)
+    return;
+
+  // collect curves of the sketch
+  std::map<GeomCurvePtr, ResultPtr, GeomAPI_Curve::Comparator> aCurves;
+  int aSubNum = theSketch->numberOfSubs();
+  for (int a = 0; a < aSubNum; ++a) {
+    FeaturePtr aSub = theSketch->subFeature(a);
+    const std::list<ResultPtr>& aResults = aSub->results();
+    std::list<ResultPtr>::const_iterator aRes = aResults.cbegin();
+    for (; aRes != aResults.cend(); aRes++) {
+      GeomShapePtr aCurShape = (*aRes)->shape();
+      if (aCurShape && aCurShape->isEdge())
+        aCurves[untrimmedCurve(aCurShape)] = *aRes;
+    }
+  }
+
+  // convert each face to the list of results of its edges
+  int aFacesNum = aSketchResult->facesNum();
+  for (int a = 0; a < aFacesNum; ++a) {
+    theEdges.push_back(std::list<ResultPtr>());
+    std::list<ResultPtr>& aCurEdges = theEdges.back();
+
+    GeomFacePtr aFace = aSketchResult->face(a);
+    for (GeomAPI_ShapeExplorer anExp(aFace, GeomAPI_Shape::EDGE);
+         anExp.more(); anExp.next()) {
+      GeomCurvePtr aCurrent = untrimmedCurve(anExp.current());
+      aCurEdges.push_back(aCurves[aCurrent]);
+    }
+  }
+}
+
+//--------------------------------------------------------------------------------------
+
 void SketchAPI_Sketch::dump(ModelHighAPI_Dumper& theDumper) const
 {
   FeaturePtr aBase = feature();
@@ -754,7 +1585,7 @@ void SketchAPI_Sketch::dump(ModelHighAPI_Dumper& theDumper) const
         aBase->attribute(SketchPlugin_Sketch::DIRX_ID()))->dir();
 
     // Check the plane is coordinate plane
-    std::string aPlaneName = defaultPlane(anOrigin, aNormal, aDirX);
+    std::wstring aPlaneName = defaultPlane(anOrigin, aNormal, aDirX);
     if(anExternal->context()) { // checking for selected planes
       if (!aPlaneName.empty()
           && anExternal->context()->data()
@@ -794,4 +1625,26 @@ void SketchAPI_Sketch::dump(ModelHighAPI_Dumper& theDumper) const
   // dump sketch's subfeatures
   CompositeFeaturePtr aCompFeat = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aBase);
   theDumper.processSubs(aCompFeat, true);
+
+  // if face order differs to the order generated by SketchBuilder,
+  // dump the list of faces for correct execution of the script
+  if (isCustomFacesOrder(aCompFeat)) {
+    std::list<std::list<ResultPtr> > aFaces;
+    edgesOfSketchFaces(aCompFeat, aFaces);
+
+    const std::string& aSketchName = theDumper.name(aBase);
+    std::string aMethodName(".changeFacesOrder");
+    std::string aSpaceShift(aSketchName.size() + aMethodName.size(), ' ');
+
+    theDumper << aSketchName << aMethodName << "([";
+    for (std::list<std::list<ResultPtr> >::iterator aFIt = aFaces.begin();
+         aFIt != aFaces.end(); ++aFIt) {
+      if (aFIt != aFaces.begin())
+        theDumper << ",\n" << aSpaceShift << "  ";
+      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;
+  }
 }