]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Merge branch 'Pre_2.8.0_development'
authorazv <azv@opencascade.com>
Thu, 22 Jun 2017 05:08:46 +0000 (08:08 +0300)
committerazv <azv@opencascade.com>
Thu, 22 Jun 2017 05:08:46 +0000 (08:08 +0300)
# Conflicts:
# src/PartSet/CMakeLists.txt
# src/SketchSolver/SketchSolver_ConstraintFixed.cpp
# src/SketchSolver/SketchSolver_Group.cpp

112 files changed:
1  2 
src/GeomAPI/CMakeLists.txt
src/GeomAPI/GeomAPI_Ax2.h
src/GeomAPI/GeomAPI_Circ.h
src/GeomAPI/GeomAPI_Dir.h
src/GeomAPI/GeomAPI_Edge.cpp
src/GeomAPI/GeomAPI_Edge.h
src/GeomAPI/GeomAPI_Ellipse.cpp
src/GeomAPI/GeomAPI_Ellipse.h
src/GeomAPI/GeomAPI_Ellipse2d.cpp
src/GeomAPI/GeomAPI_Ellipse2d.h
src/GeomAPI/GeomAPI_Pln.h
src/GeomAPI/GeomAPI_Pnt.h
src/GeomAPI/GeomAPI_Vertex.h
src/GeomAlgoAPI/GeomAlgoAPI_EdgeBuilder.cpp
src/GeomAlgoAPI/GeomAlgoAPI_EdgeBuilder.h
src/Model/Model_AttributeSelection.cpp
src/Model/Model_AttributeSelection.h
src/ModelAPI/CMakeLists.txt
src/ModelAPI/ModelAPI_AttributeSelection.h
src/ModelAPI/ModelAPI_Events.cpp
src/ModelAPI/ModelAPI_Events.h
src/ModelHighAPI/ModelHighAPI_RefAttr.cpp
src/ModelHighAPI/ModelHighAPI_RefAttr.h
src/ModuleBase/ModuleBase_ModelWidget.cpp
src/ModuleBase/ModuleBase_ResultPrs.cpp
src/ModuleBase/ModuleBase_ResultPrs.h
src/PartSet/CMakeLists.txt
src/PartSet/PartSet_CenterPrs.cpp
src/PartSet/PartSet_CenterPrs.h
src/PartSet/PartSet_ExternalPointsMgr.cpp
src/PartSet/PartSet_ExternalPointsMgr.h
src/PartSet/PartSet_SketcherMgr.cpp
src/PartSet/PartSet_SketcherMgr.h
src/PartSet/PartSet_Tools.cpp
src/PartSet/PartSet_Tools.h
src/PartSet/PartSet_WidgetPoint2d.cpp
src/PartSet/PartSet_WidgetSketchLabel.cpp
src/PartSet/PartSet_WidgetSketchLabel.h
src/PythonAPI/model/sketcher/tests.py
src/PythonAPI/model/sketcher/tools.py
src/PythonAPI/model/tests/tests.py
src/SketchAPI/SketchAPI_Constraint.cpp
src/SketchAPI/SketchAPI_Rectangle.cpp
src/SketchAPI/SketchAPI_Rectangle.h
src/SketchAPI/SketchAPI_Sketch.cpp
src/SketchAPI/SketchAPI_Sketch.h
src/SketchPlugin/CMakeLists.txt
src/SketchPlugin/SketchPlugin_ConstraintDistance.cpp
src/SketchPlugin/SketchPlugin_ConstraintDistance.h
src/SketchPlugin/SketchPlugin_ConstraintDistanceHorizontal.cpp
src/SketchPlugin/SketchPlugin_ConstraintDistanceHorizontal.h
src/SketchPlugin/SketchPlugin_ConstraintDistanceVertical.cpp
src/SketchPlugin/SketchPlugin_ConstraintDistanceVertical.h
src/SketchPlugin/SketchPlugin_Ellipse.cpp
src/SketchPlugin/SketchPlugin_Ellipse.h
src/SketchPlugin/SketchPlugin_MacroCircle.cpp
src/SketchPlugin/SketchPlugin_MacroEllipse.cpp
src/SketchPlugin/SketchPlugin_MacroEllipse.h
src/SketchPlugin/SketchPlugin_Plugin.cpp
src/SketchPlugin/SketchPlugin_Validators.cpp
src/SketchPlugin/SketchPlugin_Validators.h
src/SketchPlugin/Test/TestArcBehavior.py
src/SketchPlugin/Test/TestConstraintDistance.py
src/SketchPlugin/Test/TestConstraintDistanceBehavior.py
src/SketchPlugin/Test/TestConstraintDistanceHorizontal.py
src/SketchPlugin/Test/TestConstraintDistanceVertical.py
src/SketchPlugin/Test/TestConstraintFixed.py
src/SketchPlugin/Test/TestConstraintHorizontalValidator.py
src/SketchPlugin/Test/TestConstraintTangent.py
src/SketchPlugin/Test/TestCreateArcByCenterStartEnd.py
src/SketchPlugin/Test/TestCreateArcByTangentEdge.py
src/SketchPlugin/Test/TestCreateArcByThreePoints.py
src/SketchPlugin/Test/TestCreateArcChangeType.py
src/SketchPlugin/Test/TestCreateCircleByCenterAndPassed.py
src/SketchPlugin/Test/TestCreateCircleByThreePoints.py
src/SketchPlugin/Test/TestCreateCircleChangeType.py
src/SketchPlugin/Test/TestFillet.py
src/SketchPlugin/Test/TestFilletInteracting.py
src/SketchPlugin/Test/TestMoveArc.py
src/SketchPlugin/Test/TestMoveCircle.py
src/SketchPlugin/Test/TestMoveLine.py
src/SketchPlugin/Test/TestMovePoint.py
src/SketchPlugin/Test/TestMovementComplex.py
src/SketchPlugin/plugin-Sketch.xml
src/SketchSolver/CMakeLists.txt
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Defs.h
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.cpp
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.h
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.h
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.h
src/SketchSolver/SketchSolver_Constraint.cpp
src/SketchSolver/SketchSolver_ConstraintDistance.cpp
src/SketchSolver/SketchSolver_ConstraintFixed.cpp
src/SketchSolver/SketchSolver_ConstraintFixed.h
src/SketchSolver/SketchSolver_ConstraintMovement.cpp
src/SketchSolver/SketchSolver_ConstraintMovement.h
src/SketchSolver/SketchSolver_Error.h
src/SketchSolver/SketchSolver_Group.cpp
src/SketchSolver/SketchSolver_Group.h
src/SketchSolver/SketchSolver_Manager.cpp
src/SketchSolver/SketchSolver_Manager.h
src/SketchSolver/SketchSolver_Storage.h
src/SketcherPrs/SketcherPrs_LengthDimension.cpp
src/XGUI/XGUI_ContextMenuMgr.cpp
src/XGUI/XGUI_MenuMgr.cpp
src/XGUI/XGUI_OperationMgr.cpp
src/XGUI/XGUI_OperationMgr.h
src/XGUI/XGUI_Tools.cpp
src/XGUI/XGUI_Workshop.cpp
src/XGUI/XGUI_Workshop.h

Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 0000000000000000000000000000000000000000,2d47a5a6f7a9612d68505f303b05821b8a69bdb3..9c0926a13e940c36e8ceb6183a9f45d431098dc4
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,47 +1,65 @@@
 -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
++// Copyright (C) 2017  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<mailto:webmaster.salome@opencascade.com>
++//
+ // File:        GeomAPI_Ellipse.cpp
+ // Created:     25 April 2017
+ // Author:      Vitaly Smetannikov
+ #include "GeomAPI_Ellipse.h"
+ #include "GeomAPI_Ax2.h"
+ #include "GeomAPI_Pnt.h"
+ #include <gp_Elips.hxx>
+ #define MY_ELIPS implPtr<gp_Elips>()
+ GeomAPI_Ellipse::GeomAPI_Ellipse(const std::shared_ptr<GeomAPI_Ax2>& theAx2,
+                                  double theMajorRadius, double theMinorRadius)
+ : GeomAPI_Interface(new gp_Elips(theAx2->impl<gp_Ax2>(), theMajorRadius, theMinorRadius))
+ {
+ }
+ std::shared_ptr<GeomAPI_Pnt> GeomAPI_Ellipse::center() const
+ {
+   const gp_Pnt& aCenter = MY_ELIPS->Location();
+   return std::shared_ptr<GeomAPI_Pnt>(new GeomAPI_Pnt(aCenter.X(), aCenter.Y(), aCenter.Z()));
+ }
+ GeomPointPtr GeomAPI_Ellipse::firstFocus() const
+ {
+   const gp_Pnt& aFirst = MY_ELIPS->Focus1();
+   return std::shared_ptr<GeomAPI_Pnt>(new GeomAPI_Pnt(aFirst.X(), aFirst.Y(), aFirst.Z()));
+ }
+ GeomPointPtr GeomAPI_Ellipse::secondFocus() const
+ {
+   const gp_Pnt& aSecond = MY_ELIPS->Focus2();
+   return std::shared_ptr<GeomAPI_Pnt>(new GeomAPI_Pnt(aSecond.X(), aSecond.Y(), aSecond.Z()));
+ }
+ double GeomAPI_Ellipse::minorRadius() const
+ {
+   return MY_ELIPS->MinorRadius();
+ }
+ double GeomAPI_Ellipse::majorRadius() const
+ {
+   return MY_ELIPS->MajorRadius();
+ }
index 0000000000000000000000000000000000000000,d201d127ac22b2204e879b97be66ccab31035b4a..02536b240499447ce4b2598815eef0965af482ee
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,58 +1,76 @@@
 -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
++// Copyright (C) 2017  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<mailto:webmaster.salome@opencascade.com>
++//
+ // File:        GeomAPI_Ellipse.h
+ // Created:     25 April 2017
+ // Author:      Vitaly Smetannikov
+ #ifndef GeomAPI_Ellipse_H_
+ #define GeomAPI_Ellipse_H_
+ #include <GeomAPI_Interface.h>
+ #include <memory>
+ class GeomAPI_Pnt;
+ class GeomAPI_Ax2;
+ /**\class GeomAPI_Ellipse
+  * \ingroup DataModel
+  * \brief Ellipse in 3D
+  */
+ class GeomAPI_Ellipse : public GeomAPI_Interface
+ {
+ public:
+   /// \brief Constructs an epty ellipse
+   GEOMAPI_EXPORT GeomAPI_Ellipse() : GeomAPI_Interface() {}
+   /** \brief Constructs an ellipse with major and minor radiuses,
+    *  where theAx2 locates the ellipse and defines its orientation in 3D space such that:\n
+    *  - the center of the circle is the origin of theAx2;\n
+    *  - the origin, "X Direction" and "Y Direction" of theAx2 define the plane of the circle;\n
+    *  - theAx2 is the local coordinate system of the circle.\n
+    *    Note: It is possible to create a circle where Radius is equal to 0.0. raised if Radius < 0.
+    */
+   GEOMAPI_EXPORT GeomAPI_Ellipse(const std::shared_ptr<GeomAPI_Ax2>& theAx2,
+                                  double theMajorRadius, double theMinorRadius);
+   /// Returns center of the ellipse
+   GEOMAPI_EXPORT std::shared_ptr<GeomAPI_Pnt> center() const;
+   /// Returns first focus of the ellipse
+   GEOMAPI_EXPORT std::shared_ptr<GeomAPI_Pnt> firstFocus() const;
+   /// Returns second focus of the ellipse
+   GEOMAPI_EXPORT std::shared_ptr<GeomAPI_Pnt> secondFocus() const;
+   /// Returns minor radius of the ellipse
+   GEOMAPI_EXPORT double minorRadius() const;
+   /// Returns major radius of the ellipse
+   GEOMAPI_EXPORT double majorRadius() const;
+ };
+ //! Pointer on the object
+ typedef std::shared_ptr<GeomAPI_Ellipse> GeomEllipsePtr;
+ #endif
index 0000000000000000000000000000000000000000,eca8f4a8ee3fd377cf894ab38cb1bfa732c1fa4c..d789f717fe3c9c78f45393d9168964c6ac754e60
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,97 +1,115 @@@
 -// Copyright (C) 2017-20xx CEA/DEN, EDF R&D
++// Copyright (C) 2017  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<mailto:webmaster.salome@opencascade.com>
++//
+ // File:        GeomAPI_Ellipse2d.cpp
+ // Created:     26 April 2017
+ // Author:      Artem ZHIDKOV
+ #include <GeomAPI_Ellipse2d.h>
+ #include <GeomAPI_Dir2d.h>
+ #include <GeomAPI_Pnt2d.h>
+ #include <gp_Ax22d.hxx>
+ #include <gp_Elips2d.hxx>
+ #include <Precision.hxx>
+ #define MY_ELLIPSE implPtr<gp_Elips2d>()
+ static gp_Elips2d* newEllipse(const gp_Pnt2d& theCenter,
+                               const gp_Dir2d& theXAxis,
+                               const double theMajorRadius,
+                               const double theMinorRadius)
+ {
+   if (theMajorRadius < theMinorRadius - Precision::Confusion()) {
+     return newEllipse(theCenter, gp_Dir2d(-theXAxis.Y(), theXAxis.X()),
+                       theMinorRadius, theMajorRadius);
+   }
+   gp_Ax22d anAxis(theCenter, theXAxis);
+   return new gp_Elips2d(anAxis, theMajorRadius, theMinorRadius);
+ }
+ static gp_Elips2d* newEllipse(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
+                               const std::shared_ptr<GeomAPI_Pnt2d>& theAxisPoint,
+                               const std::shared_ptr<GeomAPI_Pnt2d>& thePassingPoint)
+ {
+   const gp_Pnt2d& aCenter = theCenter->impl<gp_Pnt2d>();
+   const gp_Pnt2d& anAxisPnt = theAxisPoint->impl<gp_Pnt2d>();
+   const gp_Pnt2d& aPassedPnt = thePassingPoint->impl<gp_Pnt2d>();
+   gp_Dir2d aXAxis(anAxisPnt.XY() - aCenter.XY());
+   double aMajorRadius = anAxisPnt.Distance(aCenter);
+   gp_XY aPassedDir = aPassedPnt.XY() - aCenter.XY();
+   double X = aPassedDir.Dot(aXAxis.XY()) / aMajorRadius;
+   if (Abs(X) > 1.0 - Precision::Confusion())
+     return 0; // ellipse cannot be created for such parameters
+   double Y = aPassedDir.CrossMagnitude(aXAxis.XY());
+   double aMinorRadius = Y / Sqrt(1. - X * X);
+   return newEllipse(aCenter, aXAxis, aMajorRadius, aMinorRadius);
+ }
+ GeomAPI_Ellipse2d::GeomAPI_Ellipse2d(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
+                                      const std::shared_ptr<GeomAPI_Dir2d>& theXAxis,
+                                      const double theMajorRadius,
+                                      const double theMinorRadius)
+   : GeomAPI_Interface(newEllipse(theCenter->impl<gp_Pnt2d>(), theXAxis->impl<gp_Dir2d>(),
+                                  theMajorRadius, theMinorRadius))
+ {
+ }
+ GeomAPI_Ellipse2d::GeomAPI_Ellipse2d(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
+                                      const std::shared_ptr<GeomAPI_Pnt2d>& theAxisPoint,
+                                      const std::shared_ptr<GeomAPI_Pnt2d>& thePassingPoint)
+   : GeomAPI_Interface(newEllipse(theCenter, theAxisPoint, thePassingPoint))
+ {
+ }
+ std::shared_ptr<GeomAPI_Pnt2d> GeomAPI_Ellipse2d::center() const
+ {
+   const gp_Pnt2d& aCenter = MY_ELLIPSE->Location();
+   return std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(aCenter.X(), aCenter.Y()));
+ }
+ std::shared_ptr<GeomAPI_Pnt2d> GeomAPI_Ellipse2d::firstFocus() const
+ {
+   const gp_Pnt2d& aFirst = MY_ELLIPSE->Focus1();
+   return std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(aFirst.X(), aFirst.Y()));
+ }
+ std::shared_ptr<GeomAPI_Pnt2d> GeomAPI_Ellipse2d::secondFocus() const
+ {
+   const gp_Pnt2d& aSecond = MY_ELLIPSE->Focus2();
+   return std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(aSecond.X(), aSecond.Y()));
+ }
+ double GeomAPI_Ellipse2d::minorRadius() const
+ {
+   return MY_ELLIPSE->MinorRadius();
+ }
+ double GeomAPI_Ellipse2d::majorRadius() const
+ {
+   return MY_ELLIPSE->MajorRadius();
+ }
index 0000000000000000000000000000000000000000,293c956494a593d46eba58085b4d005a1a5f7be7..ef8840d4a59bf894d4302cb346a1382814bce9cd
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,51 +1,69 @@@
 -// Copyright (C) 2017-20xx CEA/DEN, EDF R&D
++// Copyright (C) 2017  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<mailto:webmaster.salome@opencascade.com>
++//
+ // File:        GeomAPI_Ellipse2d.h
+ // Created:     26 April 2017
+ // Author:      Artem ZHIDKOV
+ #ifndef GeomAPI_Ellipse2d_H_
+ #define GeomAPI_Ellipse2d_H_
+ #include <GeomAPI_Interface.h>
+ class GeomAPI_Pnt2d;
+ class GeomAPI_Dir2d;
+ /**\class GeomAPI_Ellipse2d
+  * \ingroup DataModel
+  * \brief Ellipse in 2D
+  */
+ class GeomAPI_Ellipse2d : public GeomAPI_Interface
+ {
+ public:
+   /// \brief Constructs ellipse by center, X-axis and given radii
+   GEOMAPI_EXPORT GeomAPI_Ellipse2d(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
+                                    const std::shared_ptr<GeomAPI_Dir2d>& theXAxis,
+                                    const double theMajorRadius,
+                                    const double theMinorRadius);
+   /// \brief Constructs ellipse by center and two points lying on the ellipse:
+   ///        first of them defines an axis of the ellipse
+   ///        and another is just placed on the ellipse.
+   GEOMAPI_EXPORT GeomAPI_Ellipse2d(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
+                                    const std::shared_ptr<GeomAPI_Pnt2d>& theAxisPoint,
+                                    const std::shared_ptr<GeomAPI_Pnt2d>& thePassingPoint);
+   /// Returns center of the ellipse
+   GEOMAPI_EXPORT std::shared_ptr<GeomAPI_Pnt2d> center() const;
+   /// Returns first focus of the ellipse
+   GEOMAPI_EXPORT std::shared_ptr<GeomAPI_Pnt2d> firstFocus() const;
+   /// Returns second focus of the ellipse
+   GEOMAPI_EXPORT std::shared_ptr<GeomAPI_Pnt2d> secondFocus() const;
+   /// Returns minor radius of the ellipse
+   GEOMAPI_EXPORT double minorRadius() const;
+   /// Returns major radius of the ellipse
+   GEOMAPI_EXPORT double majorRadius() const;
+ };
+ #endif
Simple merge
Simple merge
Simple merge
index c292ee4824f55409256af51df5fa1eff68a28024,b10bbf736a8e883130d7752aa305c3a9e99f8558..2e9c9c18ea45bb286d617a6fe91391e09babce54
@@@ -1,38 -1,25 +1,39 @@@
 -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
 -
 -// File:        GeomAlgoAPI_EdgeBuilder.cpp
 -// Created:     23 Apr 2014
 -// Author:      Mikhail PONIKAROV
 +// Copyright (C) 2014-2017  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<mailto:webmaster.salome@opencascade.com>
 +//
  
  #include <GeomAlgoAPI_EdgeBuilder.h>
- #include <gp_Pln.hxx>
- #include <BRepBuilderAPI_MakeEdge.hxx>
- #include <TopoDS_Edge.hxx>
- #include <TopoDS_Face.hxx>
- #include <TopoDS.hxx>
- #include <BRep_Tool.hxx>
- #include <Geom_Plane.hxx>
- #include <Geom_CylindricalSurface.hxx>
- #include <Geom_RectangularTrimmedSurface.hxx>
  
- #include <gp_Ax2.hxx>
- #include <gp_Circ.hxx>
  #include <Bnd_Box.hxx>
+ #include <BRep_Tool.hxx>
  #include <BRepBndLib.hxx>
+ #include <BRepBuilderAPI_MakeEdge.hxx>
+ #include <gp_Ax2.hxx>
+ #include <gp_Circ.hxx>
+ #include <gp_Elips.hxx>
+ #include <gp_Pln.hxx>
+ #include <Geom_CylindricalSurface.hxx>
+ #include <Geom_Plane.hxx>
+ #include <Geom_RectangularTrimmedSurface.hxx>
+ #include <TopoDS.hxx>
+ #include <TopoDS_Edge.hxx>
+ #include <TopoDS_Face.hxx>
  
  std::shared_ptr<GeomAPI_Edge> GeomAlgoAPI_EdgeBuilder::line(
      std::shared_ptr<GeomAPI_Pnt> theStart, std::shared_ptr<GeomAPI_Pnt> theEnd)
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index b04c3171684c106de5865e2d6be2b853e735bf8b,3ab77b28b093bee450c4889796c4d396d75f56b9..37575cf725c28525a1f7541c0224ba880c0130a6
@@@ -56,6 -38,9 +56,8 @@@ SET(PROJECT_HEADER
      PartSet_WidgetShapeSelector.h
      PartSet_WidgetSketchCreator.h
      PartSet_WidgetSketchLabel.h
 -    PartSet_WidgetSubShapeSelector.h
 -      PartSet_CenterPrs.h
 -      PartSet_ExternalPointsMgr.h
++    PartSet_CenterPrs.h
++    PartSet_ExternalPointsMgr.h
  )
  
  SET(PROJECT_MOC_HEADERS
@@@ -74,6 -59,8 +76,7 @@@
      PartSet_WidgetShapeSelector.h
      PartSet_WidgetSketchCreator.h
      PartSet_WidgetSketchLabel.h
 -    PartSet_WidgetSubShapeSelector.h
 -      PartSet_ExternalPointsMgr.h
++    PartSet_ExternalPointsMgr.h
  )
  
  SET(PROJECT_SOURCES
      PartSet_WidgetShapeSelector.cpp
      PartSet_WidgetSketchCreator.cpp
      PartSet_WidgetSketchLabel.cpp
 -    PartSet_WidgetSubShapeSelector.cpp
 -      PartSet_CenterPrs.cpp
 -      PartSet_ExternalPointsMgr.cpp
++    PartSet_CenterPrs.cpp
++    PartSet_ExternalPointsMgr.cpp
  )
  
  SET(PROJECT_RESOURCES
index 0000000000000000000000000000000000000000,9f7f66249df19e88fe6590e20ad3d078cae99d96..065c7971cae650daa565e2e0bfa78f772cec1d26
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,23 +1,41 @@@
 -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
++// Copyright (C) 2017  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<mailto:webmaster.salome@opencascade.com>
++//
+ // File:        PartSet_CenterPrs.cpp
+ // Created:     25 April 2017
+ // Author:      Vitaly SMETANNIKOV
+ #include "PartSet_CenterPrs.h"
+ #include <Geom_CartesianPoint.hxx>
+ IMPLEMENT_STANDARD_RTTIEXT(PartSet_CenterPrs, AIS_Point)
+ PartSet_CenterPrs::PartSet_CenterPrs(const ObjectPtr& theObject,
+                                      const GeomEdgePtr& theEdge,
+                                      const gp_Pnt& theCenter,
+                                      ModelAPI_AttributeSelection::CenterType theType)
+   : AIS_Point(new Geom_CartesianPoint(theCenter)),
+   myObject(theObject),
+   myEdge(theEdge),
+   myCenterType(theType)
+ {
+ }
index 0000000000000000000000000000000000000000,f9cf9232fb5a91052ca2172a0393d5b73c16f584..86e54b24f345f62e11fd06baa0f12a7c41760d06
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,54 +1,72 @@@
 -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
++// Copyright (C) 2017  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<mailto:webmaster.salome@opencascade.com>
++//
+ // File:        PartSet_CenterPrs.h
+ // Created:     25 April 2017
+ // Author:      Vitaly SMETANNIKOV
+ #ifndef PartSet_CenterPrs_H
+ #define PartSet_CenterPrs_H
+ #include <ModelAPI_Object.h>
+ #include <ModelAPI_AttributeSelection.h>
+ #include <GeomAPI_Edge.h>
+ #include <AIS_Point.hxx>
+ #include <Standard_DefineHandle.hxx>
+ #include <gp_Pnt.hxx>
+ DEFINE_STANDARD_HANDLE(PartSet_CenterPrs, AIS_Point)
+ /**
+ * \ingroup GUI
+ * A presentation class for displaying of centers of external curcular objects in a sketch
+ */
+ class PartSet_CenterPrs: public AIS_Point
+ {
+ public:
+   /// Constructor
+   /// \param theObject an object with circular edge
+   /// \param theEdge a circular edge
+   /// \param theCenter a center point of the circular edge
+   /// \param theType a type of the center
+   Standard_EXPORT PartSet_CenterPrs(const ObjectPtr& theObject,
+                                     const GeomEdgePtr& theEdge,
+                                     const gp_Pnt& theCenter,
+                                     ModelAPI_AttributeSelection::CenterType theType);
+   /// Returns an Object which contains the circular edge
+   ObjectPtr object() const { return myObject; }
+   /// Returns a circular edge shape
+   GeomEdgePtr edge() const { return myEdge; }
+   /// Returns type of the center
+   ModelAPI_AttributeSelection::CenterType centerType() const { return myCenterType; }
+   DEFINE_STANDARD_RTTIEXT(PartSet_CenterPrs, AIS_Point)
+ private:
+   ObjectPtr myObject;
+   GeomEdgePtr myEdge;
+   ModelAPI_AttributeSelection::CenterType myCenterType;
+ };
+ #endif
index 0000000000000000000000000000000000000000,b0faeb447c5a70281709d893de68da71e8a32547..0f9babdae75ef5377962558fc8b69dc8076b16a0
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,211 +1,229 @@@
 -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
++// Copyright (C) 2017  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<mailto:webmaster.salome@opencascade.com>
++//
+ // File:        PartSet_ExternalPointsMgr.cpp
+ // Created:     26 April 2017
+ // Author:      Vitaly SMETANNIKOV
+ #include "PartSet_ExternalPointsMgr.h"
+ #include "PartSet_CenterPrs.h"
+ #include "PartSet_Tools.h"
+ #include <ModelAPI_Tools.h>
+ #include <ModuleBase_IWorkshop.h>
+ #include <ModuleBase_ViewerPrs.h>
+ #include <GeomAPI_Circ.h>
+ #include <GeomAPI_Edge.h>
+ #include <GeomAPI_Ellipse.h>
+ #include <GeomAPI_Pnt.h>
+ #include <GeomAPI_ShapeExplorer.h>
+ #include <XGUI_Tools.h>
+ #include <XGUI_Displayer.h>
+ #include <XGUI_Workshop.h>
+ #include <XGUI_SelectionMgr.h>
+ PartSet_ExternalPointsMgr::PartSet_ExternalPointsMgr(ModuleBase_IWorkshop* theWorkshop,
+                                                      const CompositeFeaturePtr& theSketch)
+   : QObject(theWorkshop), myWorkshop(theWorkshop), mySketch(theSketch)
+ {
+   XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop);
+   XGUI_Displayer* aDisplayer = aWorkshop->displayer();
+   connect(aDisplayer, SIGNAL(objectDisplayed(ObjectPtr, AISObjectPtr)),
+                       SLOT(onDisplayObject(ObjectPtr, AISObjectPtr)));
+   connect(aDisplayer, SIGNAL(beforeObjectErase(ObjectPtr, AISObjectPtr)),
+                       SLOT(onEraseObject(ObjectPtr, AISObjectPtr)));
+   updateCenterPresentations();
+ }
+ PartSet_ExternalPointsMgr::~PartSet_ExternalPointsMgr()
+ {
+   if (myPresentations.isEmpty())
+     return;
+   XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop);
+   if (!aWorkshop)
+     return;
+   XGUI_Displayer* aDisplayer = aWorkshop->displayer();
+   QMapIterator<ObjectPtr, ListOfAIS> aIt(myPresentations);
+   while (aIt.hasNext()) {
+     aIt.next();
+     ListOfAIS aAISList = aIt.value();
+     foreach (AISObjectPtr aAIS, aAISList) {
+       aDisplayer->eraseAIS(aAIS, false);
+     }
+   }
+ }
+ //******************************************************
+ QList<std::shared_ptr<ModuleBase_ViewerPrs>> PartSet_ExternalPointsMgr::findCircularEdgesInPlane()
+ {
+   QList<std::shared_ptr<ModuleBase_ViewerPrs>> aResult;
+   XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop);
+   XGUI_Displayer* aDisplayer = aWorkshop->displayer();
+   QObjectPtrList aDispObjects = aDisplayer->displayedObjects();
+   std::shared_ptr<GeomAPI_Pln> aPlane = plane();
+   foreach(ObjectPtr aObj, aDispObjects) {
+     if (myPresentations.contains(aObj))
+       continue;
+     // Do not process objects of the current sketch
+     if (isSketchObject(aObj))
+       continue;
+     ResultPtr aResObj = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
+     if (aResObj.get()) {
+       GeomShapePtr aShape = aResObj->shape();
+       if (aShape.get()) {
+         GeomAPI_ShapeExplorer aExplorer(aShape, GeomAPI_Shape::EDGE);
+         for(; aExplorer.more(); aExplorer.next()) {
+           GeomShapePtr aEdgeShape = aExplorer.current();
+           GeomAPI_Edge anEdge(aEdgeShape);
+           if ((anEdge.isCircle() || anEdge.isArc() || anEdge.isEllipse()) &&
+                anEdge.isInPlane(aPlane)) {
+             bool isContains = false;
+             // Check that edge is not already used.
+             // It is possible that the same edge will be taken from different faces
+             foreach(std::shared_ptr<ModuleBase_ViewerPrs> aPrs, aResult) {
+               GeomAPI_Edge aUsedEdge(aPrs->shape());
+               if (aUsedEdge.isEqual(aEdgeShape)) {
+                 isContains = true;
+                 break;
+               }
+             }
+             if (!isContains) {
+               std::shared_ptr<ModuleBase_ViewerPrs>
+                 aPrs(new ModuleBase_ViewerPrs(aResObj, aEdgeShape));
+               aResult.append(aPrs);
+             }
+           }
+         }
+       }
+     }
+   }
+   return aResult;
+ }
+ void PartSet_ExternalPointsMgr::updateCenterPresentations()
+ {
+   XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop);
+   // Return if there is no plane defined
+   if (!plane().get()) {
+     connect(aWorkshop->selector(), SIGNAL(selectionChanged()),
+                                    SLOT(onSelectionChanged()));
+     return;
+   }
+   XGUI_Displayer* aDisplayer = aWorkshop->displayer();
+   QList<std::shared_ptr<ModuleBase_ViewerPrs>> aEdgesPrs = findCircularEdgesInPlane();
+   foreach(std::shared_ptr<ModuleBase_ViewerPrs> aPrs, aEdgesPrs) {
+     GeomEdgePtr aEdge(new GeomAPI_Edge(aPrs->shape()));
+     ListOfAIS aList;
+     if (aEdge->isArc() || aEdge->isCircle()) {
+       GeomCirclePtr aCircle = aEdge->circle();
+       GeomPointPtr aCenter = aCircle->center();
+       Handle(PartSet_CenterPrs) aCentPrs =
+         new PartSet_CenterPrs(aPrs->object(), aEdge, aCenter->impl<gp_Pnt>(),
+                               ModelAPI_AttributeSelection::CIRCLE_CENTER);
+       AISObjectPtr anAIS(new GeomAPI_AISObject());
+       anAIS->setImpl(new Handle(AIS_InteractiveObject)(aCentPrs));
+       aList.append(anAIS);
+     } else if (aEdge->isEllipse()) {
+       GeomEllipsePtr aEllipse = aEdge->ellipse();
+       GeomPointPtr aF1 = aEllipse->firstFocus();
+       GeomPointPtr aF2 = aEllipse->secondFocus();
+       Handle(PartSet_CenterPrs) aF1Prs =
+         new PartSet_CenterPrs(aPrs->object(), aEdge, aF1->impl<gp_Pnt>(),
+                               ModelAPI_AttributeSelection::ELLIPSE_FIRST_FOCUS);
+       Handle(PartSet_CenterPrs) aF2Prs =
+         new PartSet_CenterPrs(aPrs->object(), aEdge, aF2->impl<gp_Pnt>(),
+                               ModelAPI_AttributeSelection::ELLIPSE_SECOND_FOCUS);
+       AISObjectPtr anAIS1(new GeomAPI_AISObject());
+       anAIS1->setImpl(new Handle(AIS_InteractiveObject)(aF1Prs));
+       aList.append(anAIS1);
+       AISObjectPtr anAIS2(new GeomAPI_AISObject());
+       anAIS2->setImpl(new Handle(AIS_InteractiveObject)(aF2Prs));
+       aList.append(anAIS2);
+     }
+     if (myPresentations.contains(aPrs->object()))
+       myPresentations[aPrs->object()].append(aList);
+     else
+       myPresentations[aPrs->object()] = aList;
+     foreach(AISObjectPtr anAIS, aList) {
+       aDisplayer->displayAIS(anAIS, false);
+       aDisplayer->activateAIS(anAIS->impl<Handle(AIS_InteractiveObject)>(), TopAbs_VERTEX, false);
+     }
+   }
+ }
+ std::shared_ptr<GeomAPI_Pln> PartSet_ExternalPointsMgr::plane() const
+ {
+   return PartSet_Tools::sketchPlane(mySketch);
+ }
+ void PartSet_ExternalPointsMgr::onDisplayObject(ObjectPtr theObj, AISObjectPtr theAIS)
+ {
+   updateCenterPresentations();
+ }
+ void PartSet_ExternalPointsMgr::onEraseObject(ObjectPtr theObj, AISObjectPtr theAIS)
+ {
+   if (myPresentations.contains(theObj)) {
+     XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop);
+     XGUI_Displayer* aDisplayer = aWorkshop->displayer();
+     ListOfAIS aList = myPresentations[theObj];
+     foreach(AISObjectPtr aAIS, aList) {
+       aDisplayer->eraseAIS(aAIS, false);
+     }
+     myPresentations.remove(theObj);
+     aDisplayer->updateViewer();
+   }
+ }
+ bool PartSet_ExternalPointsMgr::isSketchObject(const ObjectPtr& theRes) const
+ {
+   FeaturePtr aFeature = ModelAPI_Feature::feature(theRes);
+   if (!aFeature.get())
+     return false;
+   CompositeFeaturePtr aComp = ModelAPI_Tools::compositeOwner(aFeature);
+   return aComp == mySketch;
+ }
+ void PartSet_ExternalPointsMgr::onSelectionChanged()
+ {
+   if (plane().get()) {
+     XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop);
+     disconnect(aWorkshop->selector(), SIGNAL(selectionChanged()),
+                this, SLOT(onSelectionChanged()));
+     updateCenterPresentations();
+   }
+ }
index 0000000000000000000000000000000000000000,a053bcd1a4224715881d9ee77692b0ee5313eee6..4f13f09e81b4d19d141099efe420178c5d827081
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,90 +1,108 @@@
 -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
++// Copyright (C) 2017  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<mailto:webmaster.salome@opencascade.com>
++//
+ // File:        PartSet_ExternalPointsMgr.h
+ // Created:     26 April 2017
+ // Author:      Vitaly SMETANNIKOV
+ #ifndef PartSet_ExternalPointsMgr_H
+ #define PartSet_ExternalPointsMgr_H
+ #include <ModelAPI_CompositeFeature.h>
+ #include <ModelAPI_Result.h>
+ #include <GeomAPI_Pln.h>
+ #include <GeomAPI_AISObject.h>
+ #include <QObject>
+ #include <QMap>
+ class ModuleBase_ViewerPrs;
+ class ModuleBase_IWorkshop;
+ /**
+ * \ingroup Modules
+ * A class to manage display of presentations of center points of circular
+ * edges outside of a current sketcher
+ */
+ class PartSet_ExternalPointsMgr: public QObject
+ {
+   Q_OBJECT
+ public:
+   PartSet_ExternalPointsMgr(ModuleBase_IWorkshop* theWorkshop,
+                             const CompositeFeaturePtr& theSketch);
+   virtual ~PartSet_ExternalPointsMgr();
+ public slots:
+   /**
+   * A slot which processes display of object
+   * \param theObj the displayed object
+   * \param theAIS its presentation
+   */
+   void onDisplayObject(ObjectPtr theObj, AISObjectPtr theAIS);
+   /**
+   * A slot which processes erase of object
+   * \param theObj the displayed object
+   * \param theAIS its presentation
+   */
+   void onEraseObject(ObjectPtr theObj, AISObjectPtr theAIS);
+   // Called on selection changed
+   void onSelectionChanged();
+ private:
+   /**
+   * Returns list of presentations which have displayed shapes with circular edges
+   * (circles, arcs) which are in pane of of the given sketch
+   * \param theSketch - the sketch
+   */
+   QList<std::shared_ptr<ModuleBase_ViewerPrs>> findCircularEdgesInPlane();
+   /// Creates presentations of centers
+   void updateCenterPresentations();
+   /// Returns plane of the current sketch
+   GeomPlanePtr plane() const;
+   /**
+   * Checks that the given object is an object of the current sketch
+   * \param theRes an object to check
+   * \return True if the given object is a sub-object of the current sketch
+   */
+   bool isSketchObject(const ObjectPtr& theRes) const;
+ private:
+   /// Workshop
+   ModuleBase_IWorkshop* myWorkshop;
+   /// Current sketch
+   CompositeFeaturePtr mySketch;
+   /// Type for list of created AIS objects
+   typedef QList<AISObjectPtr> ListOfAIS;
+   /// Map of created AIS objects
+   QMap<ObjectPtr, ListOfAIS> myPresentations;
+ };
+ #endif
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 0000000000000000000000000000000000000000,18984008cbba8833d06045b3bb6df72736db056b..ea690813d4eefae9eb724940779b376ad8e6c869
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,76 +1,93 @@@
 -# Author: Artem Zhidkov
 -# Copyright (C) 2017-20xx CEA/DEN, EDF R&D
++## Copyright (C) 2017  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<mailto:webmaster.salome@opencascade.com>
++##
+ from ModelAPI import *
+ from GeomDataAPI import *
+ import ModelHighAPI
+ import math
+ from salome.shaper.model.sketcher import tools
+ TOLERANCE = 1.e-7
+ def assertPoint(thePoint, theCoords):
+     """ Verifies coordinates of the point
+     """
+     aPoint = tools.toList(thePoint)
+     assert aPoint[0] == theCoords[0] and aPoint[1] == theCoords[1], "Wrong '{}' point {}, expected {}".format(thePoint.id(), aPoint, theCoords)
+ def assertLine(theLine, theStart, theEnd):
+     """ Verifies coordinates of line extremities
+     """
+     aLine = tools.toSketchFeature(theLine)
+     aStartPnt = geomDataAPI_Point2D(aLine.attribute("StartPoint"))
+     aEndPnt = geomDataAPI_Point2D(aLine.attribute("EndPoint"))
+     if len(theStart):
+         assertPoint(aStartPnt, theStart)
+     if len(theEnd):
+         assertPoint(aEndPnt, theEnd)
+ def assertCircle(theCircle, theCenter, theRadius):
+     """ Verifies attributes of circle
+     """
+     aCircle = tools.toSketchFeature(theCircle)
+     aCenter = geomDataAPI_Point2D(aCircle.attribute("circle_center"))
+     if len(theCenter):
+         assertPoint(aCenter, theCenter)
+     aRadius = aCircle.real("circle_radius")
+     assert aRadius.value() == theRadius, "Wrong circle radius {}, expected {}".format(aRadius.value(), theRadius)
+ def assertArc(theArc, theCenter, theStart, theEnd):
+     """ Verifies coordinates of arc points and the consistency of the arc.
+         Some of points may be empty lists.
+     """
+     anArc = tools.toSketchFeature(theArc)
+     aCenterPnt = geomDataAPI_Point2D(anArc.attribute("center_point"))
+     aStartPnt = geomDataAPI_Point2D(anArc.attribute("start_point"))
+     aEndPnt = geomDataAPI_Point2D(anArc.attribute("end_point"))
+     if len(theCenter):
+         assertPoint(aCenterPnt, theCenter)
+     if len(theStart):
+         assertPoint(aStartPnt, theStart)
+     if len(theEnd):
+         assertPoint(aEndPnt, theEnd)
+     assertArcValidity(anArc)
+ def assertArcValidity(theArc):
+     """ Tests whether the arc is correctly defined
+     """
+     anArc = tools.toSketchFeature(theArc)
+     aCenterPnt = geomDataAPI_Point2D(anArc.attribute("center_point"))
+     aStartPnt = geomDataAPI_Point2D(anArc.attribute("start_point"))
+     aEndPnt = geomDataAPI_Point2D(anArc.attribute("end_point"))
+     aRadius = anArc.real("radius")
+     aDistCS = tools.distancePointPoint(aCenterPnt, aStartPnt)
+     aDistCE = tools.distancePointPoint(aCenterPnt, aEndPnt)
+     assert math.fabs(aDistCS - aDistCE) < TOLERANCE, "Wrong arc: center-start distance {}, center-end distance {}".format(aDistCS, aDistCE)
+     assert math.fabs(aRadius.value() - aDistCS) < TOLERANCE, "Wrong arc: radius is {}, expected {}".format(aRadius.value(), aDistCS)
index de3032f54d16bae221e821bfa78cb0d68c397e36,49a73bfbdeaac0b8183824abac7f1590db18aed7..e93fec49cda0fe4247cce01accb5155b426f2e16
@@@ -1,25 -1,10 +1,27 @@@
 -# Author: Sergey Pokhodenko
 -# Copyright (C) 2014-20xx CEA/DEN, EDF R&D
 +## Copyright (C) 2014-2017  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<mailto:webmaster.salome@opencascade.com>
 +##
  
  import ModelHighAPI
- import GeomDataAPI
+ from GeomDataAPI import *
+ from ModelAPI import *
+ import math
  
  def addPolyline(sketch, *coords):
      """Add a poly-line to sketch.
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 82e27cd77e41a9efeee2f3899f5003402c08016a,6f4b3a09cfd9f987fc1b27460c18a69e7cc37807..bacf4249a679c2940aae88099ebad870875e9464
@@@ -41,10 -24,13 +42,12 @@@ SET(PROJECT_HEADER
      SketchPlugin_ConstraintPerpendicular.h
      SketchPlugin_ConstraintRadius.h
      SketchPlugin_ConstraintRigid.h
 -    SketchPlugin_ConstraintSplit.h
      SketchPlugin_ConstraintTangent.h
      SketchPlugin_ConstraintVertical.h
+     SketchPlugin_Ellipse.h
      SketchPlugin_ExternalValidator.h
      SketchPlugin_Feature.h
+     SketchPlugin_Fillet.h
      SketchPlugin_IntersectionPoint.h
      SketchPlugin_Line.h
      SketchPlugin_MacroArc.h
@@@ -82,10 -69,13 +87,12 @@@ SET(PROJECT_SOURCE
      SketchPlugin_ConstraintPerpendicular.cpp
      SketchPlugin_ConstraintRadius.cpp
      SketchPlugin_ConstraintRigid.cpp
 -    SketchPlugin_ConstraintSplit.cpp
      SketchPlugin_ConstraintTangent.cpp
      SketchPlugin_ConstraintVertical.cpp
+     SketchPlugin_Ellipse.cpp
      SketchPlugin_ExternalValidator.cpp
      SketchPlugin_Feature.cpp
+     SketchPlugin_Fillet.cpp
      SketchPlugin_IntersectionPoint.cpp
      SketchPlugin_Line.cpp
      SketchPlugin_MacroArc.cpp
index 0000000000000000000000000000000000000000,29c8ce222ef997ee99d489fbe56241198543619b..4d9216477b7d60643dc048609f2d50e98a9caf0a
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,149 +1,167 @@@
 -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
++// Copyright (C) 2017  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<mailto:webmaster.salome@opencascade.com>
++//
+ // File:    SketchPlugin_ConstraintDistanceHorizontal.cpp
+ // Created: 2 May 2017
+ // Author:  Artem ZHIDKOV
+ #include <SketchPlugin_ConstraintDistanceHorizontal.h>
+ #include <SketcherPrs_Tools.h>
+ #include <SketcherPrs_Factory.h>
+ #include <GeomAPI_Dir2d.h>
+ #include <GeomAPI_XY.h>
+ #include <GeomDataAPI_Point2D.h>
+ #include <ModelAPI_AttributeDouble.h>
+ const double tolerance = 1e-7;
+ SketchPlugin_ConstraintDistanceHorizontal::SketchPlugin_ConstraintDistanceHorizontal()
+   : SketchPlugin_ConstraintDistance()
+ {
+ }
+ //*************************************************************************************
+ void SketchPlugin_ConstraintDistanceHorizontal::initAttributes()
+ {
+   data()->addAttribute(SketchPlugin_Constraint::VALUE(), ModelAPI_AttributeDouble::typeId());
+   data()->addAttribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT(), GeomDataAPI_Point2D::typeId());
+   data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId());
+   data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::typeId());
+ }
+ //*************************************************************************************
+ void SketchPlugin_ConstraintDistanceHorizontal::execute()
+ {
+   AttributeDoublePtr anAttrValue = real(SketchPlugin_Constraint::VALUE());
+   if (anAttrValue->isInitialized() || !areAttributesInitialized())
+     return;
+   double aDistance = calculateCurrentDistance();
+   anAttrValue->setValue(aDistance);
+ }
+ //*************************************************************************************
+ AISObjectPtr SketchPlugin_ConstraintDistanceHorizontal::getAISObject(AISObjectPtr thePrevious)
+ {
+   if (!sketch())
+     return thePrevious;
+   AISObjectPtr anAIS = SketcherPrs_Factory::lengthDimensionConstraint(this,
+                                                                       sketch()->coordinatePlane(),
+                                                                       thePrevious);
+   return anAIS;
+ }
+ //*************************************************************************************
+ void SketchPlugin_ConstraintDistanceHorizontal::move(double theDeltaX, double theDeltaY)
+ {
+   std::shared_ptr<ModelAPI_Data> aData = data();
+   if (!aData->isValid())
+     return;
+   // Recalculate a shift of flyout point in terms of local coordinates
+   std::shared_ptr<GeomAPI_XY> aDir(new GeomAPI_XY(theDeltaX, theDeltaY));
+   std::shared_ptr<GeomAPI_Ax3> aPlane = SketchPlugin_Sketch::plane(sketch());
+   std::shared_ptr<GeomDataAPI_Point2D> aPointA = SketcherPrs_Tools::getFeaturePoint(
+       data(), SketchPlugin_Constraint::ENTITY_A(), aPlane);
+   std::shared_ptr<GeomDataAPI_Point2D> aPointB = SketcherPrs_Tools::getFeaturePoint(
+       data(), SketchPlugin_Constraint::ENTITY_B(), aPlane);
+   if (!aPointA || !aPointB)
+     return;
+   std::shared_ptr<GeomAPI_XY> aStartPnt = aPointA->pnt()->xy();
+   std::shared_ptr<GeomAPI_XY> aEndPnt = aPointB->pnt()->xy();
+   std::shared_ptr<GeomAPI_Dir2d> aLineDir(new GeomAPI_Dir2d(aEndPnt->decreased(aStartPnt)));
+   double dX = aDir->dot(aLineDir->xy());
+   double dY = -aDir->cross(aLineDir->xy());
+   std::shared_ptr<GeomDataAPI_Point2D> aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+       aData->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
+   myFlyoutUpdate = true;
+   if (aPoint->isInitialized()) {
+     aPoint->setValue(aPoint->x() + dX, aPoint->y() + dY);
+   } else {
+     aPoint->setValue(dX, dY);
+   }
+   myFlyoutUpdate = false;
+ }
+ double SketchPlugin_ConstraintDistanceHorizontal::calculateCurrentDistance()
+ {
+   std::shared_ptr<ModelAPI_Data> aData = data();
+   std::shared_ptr<GeomAPI_Ax3> aPlane = SketchPlugin_Sketch::plane(sketch());
+   std::shared_ptr<GeomDataAPI_Point2D> aPointA =
+     SketcherPrs_Tools::getFeaturePoint(aData, SketchPlugin_Constraint::ENTITY_A(), aPlane);
+   std::shared_ptr<GeomDataAPI_Point2D> aPointB =
+       SketcherPrs_Tools::getFeaturePoint(aData, SketchPlugin_Constraint::ENTITY_B(), aPlane);
+   return aPointB->x() - aPointA->x();
+ }
+ void SketchPlugin_ConstraintDistanceHorizontal::attributeChanged(const std::string& theID)
+ {
+   if (theID == SketchPlugin_Constraint::ENTITY_A() ||
+       theID == SketchPlugin_Constraint::ENTITY_B())
+   {
+     AttributeDoublePtr aValueAttr = real(SketchPlugin_Constraint::VALUE());
+     if (!aValueAttr->isInitialized() && areAttributesInitialized()) {
+       // only if it is not initialized, try to compute the current value
+       double aDistance = calculateCurrentDistance();
+       aValueAttr->setValue(aDistance);
+     }
+   } else if (theID == SketchPlugin_Constraint::FLYOUT_VALUE_PNT() && !myFlyoutUpdate) {
+     myFlyoutUpdate = true;
+     // Recalculate flyout point in local coordinates of the distance constraint:
+     // the X coordinate is a length of projection of the flyout point on the
+     //                  line binding two distanced points
+     //                  or a line of projection of the distanced point onto the distanced segment
+     // the Y coordinate is a distance from the flyout point to the line
+     std::shared_ptr<GeomDataAPI_Point2D> aFlyoutAttr =
+         std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+         attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
+     std::shared_ptr<GeomAPI_Pnt2d> aFlyoutPnt = aFlyoutAttr->pnt();
+     std::shared_ptr<GeomAPI_Ax3> aPlane = SketchPlugin_Sketch::plane(sketch());
+     std::shared_ptr<GeomDataAPI_Point2D> aPointA = SketcherPrs_Tools::getFeaturePoint(
+         data(), SketchPlugin_Constraint::ENTITY_A(), aPlane);
+     std::shared_ptr<GeomDataAPI_Point2D> aPointB = SketcherPrs_Tools::getFeaturePoint(
+         data(), SketchPlugin_Constraint::ENTITY_B(), aPlane);
+     std::shared_ptr<GeomAPI_XY> aStartPnt = aPointA->pnt()->xy();
+     std::shared_ptr<GeomAPI_XY> aEndPnt = aPointB->pnt()->xy();
+     if (aEndPnt->distance(aStartPnt) < tolerance)
+       return;
+     std::shared_ptr<GeomAPI_Dir2d> aLineDir(new GeomAPI_Dir2d(aEndPnt->decreased(aStartPnt)));
+     std::shared_ptr<GeomAPI_XY> aFlyoutDir = aFlyoutPnt->xy()->decreased(aStartPnt);
+     double X = aFlyoutDir->dot(aLineDir->xy());
+     double Y = -aFlyoutDir->cross(aLineDir->xy());
+     aFlyoutAttr->setValue(X, Y);
+     myFlyoutUpdate = false;
+   }
+ }
index 0000000000000000000000000000000000000000,948fe13e201cda16bc4633b5ce8f82c8dccd071b..98ef11796a6f1b9fc3772252ac1a8c19d4f613ee
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,66 +1,84 @@@
 -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
++// Copyright (C) 2017  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<mailto:webmaster.salome@opencascade.com>
++//
+ // File:    SketchPlugin_ConstraintDistanceHorizontal.h
+ // Created: 2 May 2017
+ // Author:  Artem ZHIDKOV
+ #ifndef SketchPlugin_ConstraintDistanceHorizontal_H_
+ #define SketchPlugin_ConstraintDistanceHorizontal_H_
+ #include <SketchPlugin.h>
+ #include <SketchPlugin_ConstraintDistance.h>
+ /** \class SketchPlugin_ConstraintDistanceHorizontal
+  *  \ingroup Plugins
+  *  \brief Feature for creation of a new constraint which defines a horizontal distance between two points.
+  *
+  *  This constraint has three attributes:
+  *  SketchPlugin_Constraint::VALUE(), SketchPlugin_Constraint::ENTITY_A() and SketchPlugin_Constraint::ENTITY_B()
+  */
+ class SketchPlugin_ConstraintDistanceHorizontal : public SketchPlugin_ConstraintDistance
+ {
+ public:
+   /// Distance constraint kind
+   inline static const std::string& ID()
+   {
+     static const std::string MY_CONSTRAINT_DISTANCE_ID("SketchConstraintDistanceHorizontal");
+     return MY_CONSTRAINT_DISTANCE_ID;
+   }
+   /// \brief Returns the kind of a feature
+   SKETCHPLUGIN_EXPORT virtual const std::string& getKind()
+   {
+     static std::string MY_KIND = SketchPlugin_ConstraintDistanceHorizontal::ID();
+     return MY_KIND;
+   }
+   /// \brief Creates a new part document if needed
+   SKETCHPLUGIN_EXPORT virtual void execute();
+   /// \brief Request for initialization of data model of the feature: adding all attributes
+   SKETCHPLUGIN_EXPORT virtual void initAttributes();
+   /// Returns the AIS preview
+   SKETCHPLUGIN_EXPORT virtual AISObjectPtr getAISObject(AISObjectPtr thePrevious);
+   /// Moves the feature
+   /// \param theDeltaX the delta for X coordinate is moved
+   /// \param theDeltaY the delta for Y coordinate is moved
+   SKETCHPLUGIN_EXPORT virtual void move(const double theDeltaX, const double theDeltaY);
+   /// Called on change of any argument-attribute of this object
+   /// \param theID identifier of changed attribute
+   SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID);
+   /// \brief Use plugin manager for features creation
+   SketchPlugin_ConstraintDistanceHorizontal();
+ protected:
+   /// Returns the current distance between the feature attributes
+   virtual double calculateCurrentDistance();
+ private:
+   bool myFlyoutUpdate; ///< to avoid cyclic dependencies on automatic updates of flyout point
+ };
+ #endif
index 0000000000000000000000000000000000000000,49db91f59f913211f0dd2c0110874763e766da31..6691ee51bba8ad4a231d9cf4953c9e4d5ce363ec
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,149 +1,167 @@@
 -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
++// Copyright (C) 2017  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<mailto:webmaster.salome@opencascade.com>
++//
+ // File:    SketchPlugin_ConstraintDistanceVertical.cpp
+ // Created: 10 May 2017
+ // Author:  Artem ZHIDKOV
+ #include <SketchPlugin_ConstraintDistanceVertical.h>
+ #include <SketcherPrs_Tools.h>
+ #include <SketcherPrs_Factory.h>
+ #include <GeomAPI_Dir2d.h>
+ #include <GeomAPI_XY.h>
+ #include <GeomDataAPI_Point2D.h>
+ #include <ModelAPI_AttributeDouble.h>
+ const double tolerance = 1e-7;
+ SketchPlugin_ConstraintDistanceVertical::SketchPlugin_ConstraintDistanceVertical()
+   : SketchPlugin_ConstraintDistance()
+ {
+ }
+ //*************************************************************************************
+ void SketchPlugin_ConstraintDistanceVertical::initAttributes()
+ {
+   data()->addAttribute(SketchPlugin_Constraint::VALUE(), ModelAPI_AttributeDouble::typeId());
+   data()->addAttribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT(), GeomDataAPI_Point2D::typeId());
+   data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId());
+   data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::typeId());
+ }
+ //*************************************************************************************
+ void SketchPlugin_ConstraintDistanceVertical::execute()
+ {
+   AttributeDoublePtr anAttrValue = real(SketchPlugin_Constraint::VALUE());
+   if (anAttrValue->isInitialized() || !areAttributesInitialized())
+     return;
+   double aDistance = calculateCurrentDistance();
+   anAttrValue->setValue(aDistance);
+ }
+ //*************************************************************************************
+ AISObjectPtr SketchPlugin_ConstraintDistanceVertical::getAISObject(AISObjectPtr thePrevious)
+ {
+   if (!sketch())
+     return thePrevious;
+   AISObjectPtr anAIS = SketcherPrs_Factory::lengthDimensionConstraint(this,
+                                                                       sketch()->coordinatePlane(),
+                                                                       thePrevious);
+   return anAIS;
+ }
+ //*************************************************************************************
+ void SketchPlugin_ConstraintDistanceVertical::move(double theDeltaX, double theDeltaY)
+ {
+   std::shared_ptr<ModelAPI_Data> aData = data();
+   if (!aData->isValid())
+     return;
+   // Recalculate a shift of flyout point in terms of local coordinates
+   std::shared_ptr<GeomAPI_XY> aDir(new GeomAPI_XY(theDeltaX, theDeltaY));
+   std::shared_ptr<GeomAPI_Ax3> aPlane = SketchPlugin_Sketch::plane(sketch());
+   std::shared_ptr<GeomDataAPI_Point2D> aPointA = SketcherPrs_Tools::getFeaturePoint(
+       data(), SketchPlugin_Constraint::ENTITY_A(), aPlane);
+   std::shared_ptr<GeomDataAPI_Point2D> aPointB = SketcherPrs_Tools::getFeaturePoint(
+       data(), SketchPlugin_Constraint::ENTITY_B(), aPlane);
+   if (!aPointA || !aPointB)
+     return;
+   std::shared_ptr<GeomAPI_XY> aStartPnt = aPointA->pnt()->xy();
+   std::shared_ptr<GeomAPI_XY> aEndPnt = aPointB->pnt()->xy();
+   std::shared_ptr<GeomAPI_Dir2d> aLineDir(new GeomAPI_Dir2d(aEndPnt->decreased(aStartPnt)));
+   double dX = aDir->dot(aLineDir->xy());
+   double dY = -aDir->cross(aLineDir->xy());
+   std::shared_ptr<GeomDataAPI_Point2D> aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+       aData->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
+   myFlyoutUpdate = true;
+   if (aPoint->isInitialized()) {
+     aPoint->setValue(aPoint->x() + dX, aPoint->y() + dY);
+   } else {
+     aPoint->setValue(dX, dY);
+   }
+   myFlyoutUpdate = false;
+ }
+ double SketchPlugin_ConstraintDistanceVertical::calculateCurrentDistance()
+ {
+   std::shared_ptr<ModelAPI_Data> aData = data();
+   std::shared_ptr<GeomAPI_Ax3> aPlane = SketchPlugin_Sketch::plane(sketch());
+   std::shared_ptr<GeomDataAPI_Point2D> aPointA =
+     SketcherPrs_Tools::getFeaturePoint(aData, SketchPlugin_Constraint::ENTITY_A(), aPlane);
+   std::shared_ptr<GeomDataAPI_Point2D> aPointB =
+       SketcherPrs_Tools::getFeaturePoint(aData, SketchPlugin_Constraint::ENTITY_B(), aPlane);
+   return aPointB->y() - aPointA->y();
+ }
+ void SketchPlugin_ConstraintDistanceVertical::attributeChanged(const std::string& theID)
+ {
+   if (theID == SketchPlugin_Constraint::ENTITY_A() ||
+       theID == SketchPlugin_Constraint::ENTITY_B())
+   {
+     AttributeDoublePtr aValueAttr = real(SketchPlugin_Constraint::VALUE());
+     if (!aValueAttr->isInitialized() && areAttributesInitialized()) {
+       // only if it is not initialized, try to compute the current value
+       double aDistance = calculateCurrentDistance();
+       aValueAttr->setValue(aDistance);
+     }
+   } else if (theID == SketchPlugin_Constraint::FLYOUT_VALUE_PNT() && !myFlyoutUpdate) {
+     myFlyoutUpdate = true;
+     // Recalculate flyout point in local coordinates of the distance constraint:
+     // the X coordinate is a length of projection of the flyout point on the
+     //                  line binding two distanced points
+     //                  or a line of projection of the distanced point onto the distanced segment
+     // the Y coordinate is a distance from the flyout point to the line
+     std::shared_ptr<GeomDataAPI_Point2D> aFlyoutAttr =
+         std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+         attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
+     std::shared_ptr<GeomAPI_Pnt2d> aFlyoutPnt = aFlyoutAttr->pnt();
+     std::shared_ptr<GeomAPI_Ax3> aPlane = SketchPlugin_Sketch::plane(sketch());
+     std::shared_ptr<GeomDataAPI_Point2D> aPointA = SketcherPrs_Tools::getFeaturePoint(
+         data(), SketchPlugin_Constraint::ENTITY_A(), aPlane);
+     std::shared_ptr<GeomDataAPI_Point2D> aPointB = SketcherPrs_Tools::getFeaturePoint(
+         data(), SketchPlugin_Constraint::ENTITY_B(), aPlane);
+     std::shared_ptr<GeomAPI_XY> aStartPnt = aPointA->pnt()->xy();
+     std::shared_ptr<GeomAPI_XY> aEndPnt = aPointB->pnt()->xy();
+     if (aEndPnt->distance(aStartPnt) < tolerance)
+       return;
+     std::shared_ptr<GeomAPI_Dir2d> aLineDir(new GeomAPI_Dir2d(aEndPnt->decreased(aStartPnt)));
+     std::shared_ptr<GeomAPI_XY> aFlyoutDir = aFlyoutPnt->xy()->decreased(aStartPnt);
+     double X = aFlyoutDir->dot(aLineDir->xy());
+     double Y = -aFlyoutDir->cross(aLineDir->xy());
+     aFlyoutAttr->setValue(X, Y);
+     myFlyoutUpdate = false;
+   }
+ }
index 0000000000000000000000000000000000000000,e5f14d83ee99d1a0d987b2816a708698cdd20a57..7847700612850cc9633d0e03a4e1be318baaef87
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,66 +1,84 @@@
 -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
++// Copyright (C) 2017  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<mailto:webmaster.salome@opencascade.com>
++//
+ // File:    SketchPlugin_ConstraintDistanceVertical.h
+ // Created: 10 May 2017
+ // Author:  Artem ZHIDKOV
+ #ifndef SketchPlugin_ConstraintDistanceVertical_H_
+ #define SketchPlugin_ConstraintDistanceVertical_H_
+ #include <SketchPlugin.h>
+ #include <SketchPlugin_ConstraintDistance.h>
+ /** \class SketchPlugin_ConstraintDistanceVertical
+  *  \ingroup Plugins
+  *  \brief Feature for creation of a new constraint which defines a vertical distance between two points.
+  *
+  *  This constraint has three attributes:
+  *  SketchPlugin_Constraint::VALUE(), SketchPlugin_Constraint::ENTITY_A() and SketchPlugin_Constraint::ENTITY_B()
+  */
+ class SketchPlugin_ConstraintDistanceVertical : public SketchPlugin_ConstraintDistance
+ {
+ public:
+   /// Distance constraint kind
+   inline static const std::string& ID()
+   {
+     static const std::string MY_CONSTRAINT_DISTANCE_ID("SketchConstraintDistanceVertical");
+     return MY_CONSTRAINT_DISTANCE_ID;
+   }
+   /// \brief Returns the kind of a feature
+   SKETCHPLUGIN_EXPORT virtual const std::string& getKind()
+   {
+     static std::string MY_KIND = SketchPlugin_ConstraintDistanceVertical::ID();
+     return MY_KIND;
+   }
+   /// \brief Creates a new part document if needed
+   SKETCHPLUGIN_EXPORT virtual void execute();
+   /// \brief Request for initialization of data model of the feature: adding all attributes
+   SKETCHPLUGIN_EXPORT virtual void initAttributes();
+   /// Returns the AIS preview
+   SKETCHPLUGIN_EXPORT virtual AISObjectPtr getAISObject(AISObjectPtr thePrevious);
+   /// Moves the feature
+   /// \param theDeltaX the delta for X coordinate is moved
+   /// \param theDeltaY the delta for Y coordinate is moved
+   SKETCHPLUGIN_EXPORT virtual void move(const double theDeltaX, const double theDeltaY);
+   /// Called on change of any argument-attribute of this object
+   /// \param theID identifier of changed attribute
+   SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID);
+   /// \brief Use plugin manager for features creation
+   SketchPlugin_ConstraintDistanceVertical();
+ protected:
+   /// Returns the current distance between the feature attributes
+   virtual double calculateCurrentDistance();
+ private:
+   bool myFlyoutUpdate; ///< to avoid cyclic dependencies on automatic updates of flyout point
+ };
+ #endif
index 0000000000000000000000000000000000000000,2317e05754db360268f4e71d413853f9a8d3b5dd..d9f61e165814e763df3099d4bfc6f439c149cacd
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,132 +1,150 @@@
 -// Copyright (C) 2017-20xx CEA/DEN, EDF R&D -->
++// Copyright (C) 2017  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<mailto:webmaster.salome@opencascade.com>
++//
+ // File:        SketchPlugin_Ellipse.cpp
+ // Created:     26 April 2017
+ // Author:      Artem ZHIDKOV
+ #include <SketchPlugin_Ellipse.h>
+ #include <SketchPlugin_Sketch.h>
+ #include <GeomAlgoAPI_EdgeBuilder.h>
+ #include <GeomAPI_Edge.h>
+ #include <GeomAPI_Ellipse.h>
+ #include <GeomDataAPI_Point2D.h>
+ #include <ModelAPI_AttributeDouble.h>
+ #include <ModelAPI_ResultConstruction.h>
+ #include <ModelAPI_Session.h>
+ #include <ModelAPI_Validator.h>
+ static const double tolerance = 1e-7;
+ SketchPlugin_Ellipse::SketchPlugin_Ellipse()
+ : SketchPlugin_SketchEntity()
+ {
+ }
+ void SketchPlugin_Ellipse::initDerivedClassAttributes()
+ {
+   data()->addAttribute(CENTER_ID(), GeomDataAPI_Point2D::typeId());
+   data()->addAttribute(FOCUS_ID(), GeomDataAPI_Point2D::typeId());
+   data()->addAttribute(MAJOR_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
+   data()->addAttribute(MINOR_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
+   data()->addAttribute(EXTERNAL_ID(), ModelAPI_AttributeSelection::typeId());
+   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EXTERNAL_ID());
+ }
+ void SketchPlugin_Ellipse::execute()
+ {
+   SketchPlugin_Sketch* aSketch = sketch();
+   if(!aSketch) {
+     return;
+   }
+   // Compute a ellipse in 3D view.
+   std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr =
+       std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
+   std::shared_ptr<GeomDataAPI_Point2D> aFocusAttr =
+       std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(FOCUS_ID()));
+   AttributeDoublePtr aMajorRadiusAttr = real(MAJOR_RADIUS_ID());
+   AttributeDoublePtr aMinorRadiusAttr = real(MINOR_RADIUS_ID());
+   if (!aCenterAttr->isInitialized() ||
+       !aFocusAttr->isInitialized() ||
+       !aMajorRadiusAttr->isInitialized() ||
+       !aMinorRadiusAttr->isInitialized()) {
+     return;
+   }
+   double aMajorRadius = aMajorRadiusAttr->value();
+   double aMinorRadius = aMinorRadiusAttr->value();
+   if(aMajorRadius < tolerance || aMinorRadius < tolerance) {
+     return;
+   }
+   // Make a visible point.
+   SketchPlugin_Sketch::createPoint2DResult(this, aSketch, CENTER_ID(), 0);
+   std::shared_ptr<GeomDataAPI_Dir> aNDir = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+       aSketch->attribute(SketchPlugin_Sketch::NORM_ID()));
+   // Make a visible ellipse.
+   std::shared_ptr<GeomAPI_Pnt> aCenter(aSketch->to3D(aCenterAttr->x(), aCenterAttr->y()));
+   std::shared_ptr<GeomAPI_Pnt> aFocus(aSketch->to3D(aFocusAttr->x(), aFocusAttr->y()));
+   std::shared_ptr<GeomAPI_Dir> aNormal = aNDir->dir();
+   std::shared_ptr<GeomAPI_Dir> aMajorAxis(new GeomAPI_Dir(aFocus->x() - aCenter->x(),
+       aFocus->y() - aCenter->y(), aFocus->z() - aCenter->z()));
+   std::shared_ptr<GeomAPI_Shape> anEllipseShape =
+       GeomAlgoAPI_EdgeBuilder::ellipse(aCenter, aNormal, aMajorAxis, aMajorRadius, aMinorRadius);
+   std::shared_ptr<ModelAPI_ResultConstruction> aResult = document()->createConstruction(data(), 1);
+   aResult->setShape(anEllipseShape);
+   aResult->setIsInHistory(false);
+   setResult(aResult, 1);
+ }
+ void SketchPlugin_Ellipse::move(double theDeltaX, double theDeltaY)
+ {
+   std::shared_ptr<ModelAPI_Data> aData = data();
+   if(!aData->isValid()) {
+     return;
+   }
+   std::shared_ptr<GeomDataAPI_Point2D> aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+       aData->attribute(CENTER_ID()));
+   if(aPoint->isInitialized()) {
+     aPoint->move(theDeltaX, theDeltaY);
+   }
+ }
+ bool SketchPlugin_Ellipse::isFixed() {
+   return data()->selection(EXTERNAL_ID())->context().get() != NULL;
+ }
+ void SketchPlugin_Ellipse::attributeChanged(const std::string& theID) {
+   // the second condition for unability to move external segments anywhere
+   if (theID == EXTERNAL_ID() || isFixed()) {
+     std::shared_ptr<GeomAPI_Shape> aSelection = data()->selection(EXTERNAL_ID())->value();
+     if (!aSelection) {
+       // empty shape in selection shows that the shape is equal to context
+       ResultPtr anExtRes = selection(EXTERNAL_ID())->context();
+       if (anExtRes)
+         aSelection = anExtRes->shape();
+     }
+     // update arguments due to the selection value
+     if (aSelection && !aSelection->isNull() && aSelection->isEdge()) {
+       std::shared_ptr<GeomAPI_Edge> anEdge( new GeomAPI_Edge(aSelection));
+       std::shared_ptr<GeomAPI_Ellipse> anEllipse = anEdge->ellipse();
+       std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr =
+           std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(CENTER_ID()));
+       aCenterAttr->setValue(sketch()->to2D(anEllipse->center()));
+       std::shared_ptr<GeomDataAPI_Point2D> aFocusAttr =
+           std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(FOCUS_ID()));
+       aFocusAttr->setValue(sketch()->to2D(anEllipse->firstFocus()));
+       real(MAJOR_RADIUS_ID())->setValue(anEllipse->majorRadius());
+       real(MINOR_RADIUS_ID())->setValue(anEllipse->minorRadius());
+     }
+   }
+ }
index 0000000000000000000000000000000000000000,287a1a54ade125851712f36056f816f8bb3f3575..fc4b77c64e48be137a9b04d00704664b86aac12c
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,84 +1,102 @@@
 -// Copyright (C) 2017-20xx CEA/DEN, EDF R&D -->
++// Copyright (C) 2017  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<mailto:webmaster.salome@opencascade.com>
++//
+ // File:        SketchPlugin_Ellipse.h
+ // Created:     26 April 2017
+ // Author:      Artem ZHIDKOV
+ #ifndef SketchPlugin_Ellipse_H_
+ #define SketchPlugin_Ellipse_H_
+ #include <SketchPlugin.h>
+ #include <SketchPlugin_SketchEntity.h>
+ /**\class SketchPlugin_Ellipse
+  * \ingroup Plugins
+  * \brief Feature for creation of the new ellipse in Sketch.
+  */
+ class SketchPlugin_Ellipse: public SketchPlugin_SketchEntity
+ {
+  public:
+   /// Ellipse feature kind
+   inline static const std::string& ID()
+   {
+     static const std::string ID("SketchEllipse");
+     return ID;
+   }
+   /// 2D point - center of the ellipse
+   inline static const std::string& CENTER_ID()
+   {
+     static const std::string ID("ellipse_center");
+     return ID;
+   }
+   /// 2D point - focus of the ellipse
+   inline static const std::string& FOCUS_ID()
+   {
+     static const std::string ID("ellipse_focus");
+     return ID;
+   }
+   /// Major radius of the ellipse
+   inline static const std::string& MAJOR_RADIUS_ID()
+   {
+     static const std::string ID("ellipse_major_radius");
+     return ID;
+   }
+   /// Minor radius of the ellipse
+   inline static const std::string& MINOR_RADIUS_ID()
+   {
+     static const std::string ID("ellipse_minor_radius");
+     return ID;
+   }
+   /// Returns the kind of a feature
+   SKETCHPLUGIN_EXPORT virtual const std::string& getKind()
+   {
+     static std::string MY_KIND = SketchPlugin_Ellipse::ID();
+     return MY_KIND;
+   }
+   /// Returns true is sketch element is under the rigid constraint
+   SKETCHPLUGIN_EXPORT virtual bool isFixed();
+   /// Called on change of any argument-attribute of this object
+   SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID);
+   /// Creates a new part document if needed
+   SKETCHPLUGIN_EXPORT virtual void execute();
+   /// Moves the feature
+   /// \param theDeltaX the delta for X coordinate is moved
+   /// \param theDeltaY the delta for Y coordinate is moved
+   SKETCHPLUGIN_EXPORT virtual void move(const double theDeltaX, const double theDeltaY);
+   /// Use plugin manager for features creation
+   SketchPlugin_Ellipse();
+ protected:
+   /// \brief Initializes attributes of derived class.
+   virtual void initDerivedClassAttributes();
+ };
+ #endif
index 0000000000000000000000000000000000000000,1376384eada33876a166d085d0a917db1508590d..37ea7aa31462cd88932a8b1d50a7e9eb7783b8e3
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,244 +1,262 @@@
 -// Copyright (C) 2017-20xx CEA/DEN, EDF R&D -->
++// Copyright (C) 2017  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<mailto:webmaster.salome@opencascade.com>
++//
+ // File:        SketchPlugin_MacroEllipse.cpp
+ // Created:     26 April 2017
+ // Author:      Artem ZHIDKOV
+ #include <SketchPlugin_MacroEllipse.h>
+ #include <SketchPlugin_Ellipse.h>
+ #include <SketchPlugin_Tools.h>
+ #include <SketchPlugin_Sketch.h>
+ #include <ModelAPI_AttributeDouble.h>
+ #include <ModelAPI_AttributeRefAttr.h>
+ #include <ModelAPI_EventReentrantMessage.h>
+ #include <ModelAPI_Session.h>
+ #include <ModelAPI_Validator.h>
+ #include <ModelAPI_Events.h>
+ #include <GeomDataAPI_Point2D.h>
+ #include <GeomAPI_Dir2d.h>
+ #include <GeomAPI_Pnt2d.h>
+ #include <GeomAPI_Ellipse2d.h>
+ #include <GeomAPI_Vertex.h>
+ #include <GeomAlgoAPI_CompoundBuilder.h>
+ #include <GeomAlgoAPI_EdgeBuilder.h>
+ #include <GeomAlgoAPI_PointBuilder.h>
+ SketchPlugin_MacroEllipse::SketchPlugin_MacroEllipse()
+ : SketchPlugin_SketchEntity(),
+   myMajorRadius(0.0),
+   myMinorRadius(0.0)
+ {
+ }
+ void SketchPlugin_MacroEllipse::initAttributes()
+ {
+   data()->addAttribute(CENTER_POINT_ID(), GeomDataAPI_Point2D::typeId());
+   data()->addAttribute(CENTER_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
+   data()->addAttribute(MAJOR_AXIS_POINT_ID(), GeomDataAPI_Point2D::typeId());
+   data()->addAttribute(MAJOR_AXIS_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
+   data()->addAttribute(PASSED_POINT_ID(), GeomDataAPI_Point2D::typeId());
+   data()->addAttribute(PASSED_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
+   data()->addAttribute(MAJOR_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
+   data()->addAttribute(MINOR_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
+   data()->addAttribute(AUXILIARY_ID(), ModelAPI_AttributeBoolean::typeId());
+   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CENTER_POINT_REF_ID());
+   ModelAPI_Session::get()->validators()->
+       registerNotObligatory(getKind(), MAJOR_AXIS_POINT_REF_ID());
+   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PASSED_POINT_REF_ID());
+ }
+ void SketchPlugin_MacroEllipse::execute()
+ {
+   FeaturePtr anEllipse = createEllipseFeature();
+   constraintsForEllipse(anEllipse);
+   // message to init reentrant operation
+   static Events_ID anId = ModelAPI_EventReentrantMessage::eventId();
+   ReentrantMessagePtr aMessage(new ModelAPI_EventReentrantMessage(anId, this));
+   aMessage->setCreatedFeature(anEllipse);
+   Events_Loop::loop()->send(aMessage);
+ }
+ void SketchPlugin_MacroEllipse::attributeChanged(const std::string& theID)
+ {
+   static const int NB_POINTS = 3;
+   std::string aPointAttrName[NB_POINTS] = { CENTER_POINT_ID(),
+                                             MAJOR_AXIS_POINT_ID(),
+                                             PASSED_POINT_ID() };
+   std::string aPointRefName[NB_POINTS] = { CENTER_POINT_REF_ID(),
+                                            MAJOR_AXIS_POINT_REF_ID(),
+                                            PASSED_POINT_REF_ID() };
+   int aNbInitialized = 0;
+   std::shared_ptr<GeomAPI_Pnt2d> anEllipsePoints[NB_POINTS];
+   for (int aPntIndex = 0; aPntIndex < NB_POINTS; ++aPntIndex) {
+     AttributePtr aPointAttr = attribute(aPointAttrName[aPntIndex]);
+     if (!aPointAttr->isInitialized())
+       continue;
+     AttributeRefAttrPtr aPointRef = refattr(aPointRefName[aPntIndex]);
+     // calculate ellipse parameters
+     std::shared_ptr<GeomAPI_Pnt2d> aPassedPoint;
+     std::shared_ptr<GeomAPI_Shape> aTangentCurve;
+     SketchPlugin_Tools::convertRefAttrToPointOrTangentCurve(
+         aPointRef, aPointAttr, aTangentCurve, aPassedPoint);
+     anEllipsePoints[aNbInitialized++] = aPassedPoint;
+   }
+   std::shared_ptr<GeomAPI_Ellipse2d> anEllipse;
+   if (aNbInitialized == 2) {
+     std::shared_ptr<GeomAPI_Dir2d> aXDir(new GeomAPI_Dir2d(
+         anEllipsePoints[1]->x() - anEllipsePoints[0]->x(),
+         anEllipsePoints[1]->y() - anEllipsePoints[0]->y()));
+     double aMajorRad = anEllipsePoints[1]->distance(anEllipsePoints[0]);
+     anEllipse = std::shared_ptr<GeomAPI_Ellipse2d>(
+         new GeomAPI_Ellipse2d(anEllipsePoints[0], aXDir, aMajorRad, 0.5 * aMajorRad));
+   } else if (aNbInitialized == 3) {
+     anEllipse = std::shared_ptr<GeomAPI_Ellipse2d>(
+         new GeomAPI_Ellipse2d(anEllipsePoints[0], anEllipsePoints[1], anEllipsePoints[2]));
+   }
+   if (!anEllipse || anEllipse->implPtr<void>() == 0)
+     return;
+   myCenter = anEllipse->center();
+   myFocus = anEllipse->firstFocus();
+   myMajorRadius = anEllipse->majorRadius();
+   myMinorRadius = anEllipse->minorRadius();
+   AttributeDoublePtr aMajorRadiusAttr = real(MAJOR_RADIUS_ID());
+   AttributeDoublePtr aMinorRadiusAttr = real(MINOR_RADIUS_ID());
+   bool aWasBlocked = data()->blockSendAttributeUpdated(true);
+   // center attribute is used in processEvent() to set reference to reentrant arc
+   std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(CENTER_POINT_ID()))->setValue(myCenter);
+   aMajorRadiusAttr->setValue(myMajorRadius);
+   aMinorRadiusAttr->setValue(myMinorRadius);
+   data()->blockSendAttributeUpdated(aWasBlocked, false);
+ }
+ std::string SketchPlugin_MacroEllipse::processEvent(
+                                               const std::shared_ptr<Events_Message>& theMessage)
+ {
+   std::string aFilledAttributeName;
+   ReentrantMessagePtr aReentrantMessage =
+         std::dynamic_pointer_cast<ModelAPI_EventReentrantMessage>(theMessage);
+   if (aReentrantMessage) {
+     FeaturePtr aCreatedFeature = aReentrantMessage->createdFeature();
+     ObjectPtr anObject = aReentrantMessage->selectedObject();
+     AttributePtr anAttribute = aReentrantMessage->selectedAttribute();
+     std::shared_ptr<GeomAPI_Pnt2d> aClickedPoint = aReentrantMessage->clickedPoint();
+     if (aClickedPoint && (anObject || anAttribute)) {
+       aFilledAttributeName = CENTER_POINT_ID();
+       std::string aReferenceAttributeName = CENTER_POINT_REF_ID();
+       // fill 2d point attribute
+       AttributePoint2DPtr aPointAttr =
+           std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(aFilledAttributeName));
+       aPointAttr->setValue(aClickedPoint);
+       // fill reference attribute
+       AttributeRefAttrPtr aRefAttr =
+           std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(attribute(aReferenceAttributeName));
+       if (anAttribute) {
+         if (!anAttribute->owner() || !anAttribute->owner()->data()->isValid()) {
+           if (aCreatedFeature && anAttribute->id() == CENTER_POINT_ID())
+             anAttribute = aCreatedFeature->attribute(SketchPlugin_Ellipse::CENTER_ID());
+         }
+         aRefAttr->setAttr(anAttribute);
+       }
+       else if (anObject.get()) {
+         // if presentation of previous reentrant macro arc is used, the object is invalid,
+         // we should use result of previous feature of the message(Arc)
+         if (!anObject->data()->isValid())
+           anObject = aCreatedFeature->lastResult();
+         aRefAttr->setObject(anObject);
+       }
+     }
+     Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
+   }
+   return aFilledAttributeName;
+ }
+ void SketchPlugin_MacroEllipse::constraintsForEllipse(FeaturePtr theEllipseFeature)
+ {
+   // Create constraints.
+   SketchPlugin_Tools::createConstraint(
+       this, CENTER_POINT_REF_ID(),
+       theEllipseFeature->attribute(SketchPlugin_Ellipse::CENTER_ID()),
+       ObjectPtr(), false);
+   SketchPlugin_Tools::createConstraint(
+       this, MAJOR_AXIS_POINT_REF_ID(), AttributePtr(),
+       theEllipseFeature->lastResult(), true);
+   SketchPlugin_Tools::createConstraint(
+       this, PASSED_POINT_REF_ID(), AttributePtr(),
+       theEllipseFeature->lastResult(), true);
+ }
+ FeaturePtr SketchPlugin_MacroEllipse::createEllipseFeature()
+ {
+   FeaturePtr aEllipseFeature = sketch()->addFeature(SketchPlugin_Ellipse::ID());
+   AttributePoint2DPtr aCenterAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+       aEllipseFeature->attribute(SketchPlugin_Ellipse::CENTER_ID()));
+   aCenterAttr->setValue(myCenter->x(), myCenter->y());
+   AttributePoint2DPtr aFocusAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+       aEllipseFeature->attribute(SketchPlugin_Ellipse::FOCUS_ID()));
+   aFocusAttr->setValue(myFocus->x(), myFocus->y());
+   aEllipseFeature->real(SketchPlugin_Ellipse::MAJOR_RADIUS_ID())->setValue(myMajorRadius);
+   aEllipseFeature->real(SketchPlugin_Ellipse::MINOR_RADIUS_ID())->setValue(myMinorRadius);
+   aEllipseFeature->boolean(SketchPlugin_Ellipse::AUXILIARY_ID())->setValue(
+       boolean(AUXILIARY_ID())->value());
+   aEllipseFeature->execute();
+   return aEllipseFeature;
+ }
+ AISObjectPtr SketchPlugin_MacroEllipse::getAISObject(AISObjectPtr thePrevious)
+ {
+   SketchPlugin_Sketch* aSketch = sketch();
+   if (!aSketch || !myCenter || myMajorRadius == 0)
+     return AISObjectPtr();
+   std::shared_ptr<GeomDataAPI_Dir> aNDir = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+       aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
+   // Compute a ellipse in 3D view.
+   std::shared_ptr<GeomAPI_Pnt> aCenter(aSketch->to3D(myCenter->x(), myCenter->y()));
+   std::shared_ptr<GeomAPI_Pnt> aFocus(aSketch->to3D(myFocus->x(), myFocus->y()));
+   std::shared_ptr<GeomAPI_Dir> aNormal = aNDir->dir();
+   std::shared_ptr<GeomAPI_Dir> aMajorAxis(new GeomAPI_Dir(aFocus->x() - aCenter->x(),
+       aFocus->y() - aCenter->y(), aFocus->z() - aCenter->z()));
+   std::shared_ptr<GeomAPI_Shape> anEllipseShape =
+       GeomAlgoAPI_EdgeBuilder::ellipse(aCenter, aNormal, aMajorAxis, myMajorRadius, myMinorRadius);
+   GeomShapePtr aCenterPointShape = GeomAlgoAPI_PointBuilder::vertex(aCenter);
+   if (!anEllipseShape.get() || !aCenterPointShape.get())
+     return AISObjectPtr();
+   std::list<std::shared_ptr<GeomAPI_Shape> > aShapes;
+   aShapes.push_back(anEllipseShape);
+   aShapes.push_back(aCenterPointShape);
+   std::shared_ptr<GeomAPI_Shape> aCompound = GeomAlgoAPI_CompoundBuilder::compound(aShapes);
+   AISObjectPtr anAIS = thePrevious;
+   if (!anAIS)
+     anAIS.reset(new GeomAPI_AISObject());
+   anAIS->createShape(aCompound);
+   return anAIS;
+ }
index 0000000000000000000000000000000000000000,29ae0897852929f3621e1375b5ecbb90be9bfc9e..d31d0d55f3fb3b83d5af430bb57e2aa6a2d7e97f
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,142 +1,160 @@@
 -// Copyright (C) 2017-20xx CEA/DEN, EDF R&D -->
++// Copyright (C) 2017  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<mailto:webmaster.salome@opencascade.com>
++//
+ // File:        SketchPlugin_MacroEllipse.h
+ // Created:     26 April 2017
+ // Author:      Artem ZHIDKOV
+ #ifndef SketchPlugin_MacroEllipse_H_
+ #define SketchPlugin_MacroEllipse_H_
+ #include <ModelAPI_IReentrant.h>
+ #include <SketchPlugin.h>
+ #include <SketchPlugin_SketchEntity.h>
+ #include <GeomAPI_IPresentable.h>
+ ////class GeomAPI_Circ2d;
+ class GeomAPI_Pnt2d;
+ /**\class SketchPlugin_MacroEllipse
+  * \ingroup Plugins
+  * \brief Feature for creation of the new ellipse in Sketch.
+  */
+ class SketchPlugin_MacroEllipse: public SketchPlugin_SketchEntity,
+                                  public GeomAPI_IPresentable,
+                                  public ModelAPI_IReentrant
+ {
+  public:
+   /// Ellipse feature kind
+   inline static const std::string& ID()
+   {
+     static const std::string ID("SketchMacroEllipse");
+     return ID;
+   }
+   /// 2D point - center of the ellipse.
+   inline static const std::string& CENTER_POINT_ID()
+   {
+     static const std::string ID("center_point");
+     return ID;
+   }
+   /// Reference for center point selection.
+   inline static const std::string& CENTER_POINT_REF_ID()
+   {
+     static const std::string ID("center_point_ref");
+     return ID;
+   }
+   /// 2D point - major axis point of the ellipse.
+   inline static const std::string& MAJOR_AXIS_POINT_ID()
+   {
+     static const std::string ID("major_axis_point");
+     return ID;
+   }
+   /// Reference for major axis point selection.
+   inline static const std::string& MAJOR_AXIS_POINT_REF_ID()
+   {
+     static const std::string ID("major_axis_point_ref");
+     return ID;
+   }
+   /// 2D point - passed point of the ellipse
+   inline static const std::string& PASSED_POINT_ID()
+   {
+     static const std::string ID("passed_point");
+     return ID;
+   }
+   /// Reference for passed point selection.
+   inline static const std::string& PASSED_POINT_REF_ID()
+   {
+     static const std::string ID("passed_point_ref");
+     return ID;
+   }
+   /// Major radius of the ellipse
+   inline static const std::string& MAJOR_RADIUS_ID()
+   {
+     static const std::string ID("ellipse_major_radius");
+     return ID;
+   }
+   /// Minor radius of the ellipse
+   inline static const std::string& MINOR_RADIUS_ID()
+   {
+     static const std::string ID("ellipse_minor_radius");
+     return ID;
+   }
+   /// Returns the kind of a feature
+   SKETCHPLUGIN_EXPORT virtual const std::string& getKind()
+   {
+     static std::string MY_KIND = SketchPlugin_MacroEllipse::ID();
+     return MY_KIND;
+   }
+   /// \brief Request for initialization of data model of the feature: adding all attributes.
+   SKETCHPLUGIN_EXPORT virtual void initAttributes();
+   /// Called on change of any argument-attribute of this object
+   SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID);
+   /// Returns the AIS preview
+   virtual AISObjectPtr getAISObject(AISObjectPtr thePrevious);
+   /// Creates a new part document if needed
+   SKETCHPLUGIN_EXPORT virtual void execute();
+   /// Moves the feature
+   /// \param theDeltaX the delta for X coordinate is moved
+   /// \param theDeltaY the delta for Y coordinate is moved
+   SKETCHPLUGIN_EXPORT virtual void move(const double theDeltaX, const double theDeltaY)
+   {}
+   /// Reimplemented from ModelAPI_Feature::isMacro().
+   /// \returns true
+   SKETCHPLUGIN_EXPORT virtual bool isMacro() const
+   {return true;}
+   SKETCHPLUGIN_EXPORT virtual bool isPreviewNeeded() const
+   {return false;}
+   /// Apply information of the message to current object. It fills reference object,
+   /// tangent type and tangent point refence in case of tangent arc
+   virtual std::string processEvent(const std::shared_ptr<Events_Message>& theMessage);
+   /// Use plugin manager for features creation
+   SketchPlugin_MacroEllipse();
+ private:
+   void constraintsForEllipse(FeaturePtr theEllipseFeature);
+   FeaturePtr createEllipseFeature();
+ private:
+   std::shared_ptr<GeomAPI_Pnt2d> myCenter;
+   std::shared_ptr<GeomAPI_Pnt2d> myFocus;
+   double                         myMajorRadius;
+   double                         myMinorRadius;
+ };
+ #endif
index 515cc685deb68622074d8105d937b7e6526623eb,4776e5e3a4ba3a39b146080ededa566871adec98..0a1c026780f159025a7b7ca0653c3a74ebde224a
  #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_ConstraintSplit.h>
  #include <SketchPlugin_ConstraintHorizontal.h>
  #include <SketchPlugin_ConstraintLength.h>
  #include <SketchPlugin_ConstraintMiddle.h>
  #include <SketchPlugin_MultiRotation.h>
  #include <SketchPlugin_MultiTranslation.h>
  #include <SketchPlugin_Trim.h>
 +#include <SketchPlugin_Split.h>
  #include <SketchPlugin_Validators.h>
  #include <SketchPlugin_ExternalValidator.h>
+ #include <SketchPlugin_Ellipse.h>
+ #include <SketchPlugin_MacroEllipse.h>
  
  #include <Events_Loop.h>
  #include <GeomDataAPI_Dir.h>
index 0000000000000000000000000000000000000000,37c0458e4706672c48cac5047f318a169a1cfde2..35ab1496c62a7d35459e590568951f54a7431421
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,82 +1,102 @@@
++## Copyright (C) 2017  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<mailto:webmaster.salome@opencascade.com>
++##
++
+ from salome.shaper import model
+ from SketchAPI import *
+ import math
+ TOLERANCE = 1.e-7
+ model.begin()
+ partSet = model.moduleDocument()
+ Part_1 = model.addPart(partSet)
+ Part_1_doc = Part_1.document()
+ DistanceParam = model.addParameter(Part_1_doc, "distance", "10.")
+ Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+ SketchRectangle_1 = Sketch_1.addRectangle(20., 20., 70., 50.)
+ [SketchLine_1, SketchLine_2, SketchLine_3, SketchLine_4] = SketchRectangle_1.lines()
+ firstPoint = SketchAPI_Line(SketchLine_2).startPoint()
+ secondPoint = SketchAPI_Line(SketchLine_3).endPoint()
+ model.do()
+ # =============================================================================
+ # Test 1.
+ # =============================================================================
+ # horizontal distance constraint
+ SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(firstPoint, secondPoint, "distance")
+ model.do()
+ # changing the parameter
+ for param in range(-30, 31, 2):
+     DistanceParam.setValue(param)
+     model.do()
+     dist = secondPoint.x() - firstPoint.x()
+     assert math.fabs(dist - param) < TOLERANCE, "Incorrect horizontal distance {}, expected {}".format(dist, param)
+ model.testNbSubFeatures(Sketch_1, "SketchLine", 4)
+ model.testNbSubFeatures(Sketch_1, "SketchConstraintDistanceHorizontal", 1)
+ # remove horizontal distance constraint
+ Part_1_doc.removeFeature(SketchConstraintDistanceHorizontal_1.feature())
+ model.do()
+ # =============================================================================
+ # Test 2.
+ # =============================================================================
+ # Vertical distance constraint
+ SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(firstPoint, secondPoint, "distance")
+ model.do()
+ # changing the parameter
+ for param in range(-30, 31, 2):
+     DistanceParam.setValue(param)
+     model.do()
+     dist = secondPoint.y() - firstPoint.y()
+     assert math.fabs(dist - param) < TOLERANCE, "Incorrect vertical distance {}, expected {}".format(dist, param)
+ model.testNbSubFeatures(Sketch_1, "SketchLine", 4)
+ model.testNbSubFeatures(Sketch_1, "SketchConstraintDistanceVertical", 1)
+ # remove verticel distance constraint
+ Part_1_doc.removeFeature(SketchConstraintDistanceVertical_1.feature())
+ model.do()
+ # =============================================================================
+ # Test 3.
+ # =============================================================================
+ # distance constraint
+ SketchConstraintDistance_1 = Sketch_1.setDistance(firstPoint, secondPoint, "distance")
+ model.do()
+ # changing the parameter
+ for param in range(-30, 31, 2):
+     DistanceParam.setValue(param)
+     model.do()
+     if param <= 0:
+         assert SketchConstraintDistance_1.feature().error() != '', "ERROR: Sketch should not be valid due to negative distance value"
+     else:
+         dist = model.distancePointPoint(firstPoint, secondPoint)
+         assert math.fabs(dist - math.fabs(param)) < TOLERANCE, "Incorrect distance {}, expected {}".format(dist, math.fabs(param))
+ model.testNbSubFeatures(Sketch_1, "SketchLine", 4)
+ model.testNbSubFeatures(Sketch_1, "SketchConstraintDistance", 1)
+ # leave distance constraint alive
+ model.end()
index 0000000000000000000000000000000000000000,dedb8d68510087f38f2e05b21a6bc2459d752450..24278747112d3c0b53efa128acf1c87452511983
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,208 +1,228 @@@
++## Copyright (C) 2017  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<mailto:webmaster.salome@opencascade.com>
++##
++
+ """
+     TestConstraintDistanceHorizontal.py
+     Unit test of SketchPlugin_ConstraintDistanceHorizontal class
+     SketchPlugin_ConstraintDistanceHorizontal
+         static const std::string MY_CONSTRAINT_DISTANCE_ID("SketchConstraintDistance");
+         data()->addAttribute(SketchPlugin_Constraint::VALUE(),    ModelAPI_AttributeDouble::typeId());
+         data()->addAttribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT(), GeomDataAPI_Point2D::typeId());
+         data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId());
+         data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::typeId());
+ """
+ from GeomDataAPI import *
+ from ModelAPI import *
+ import math
+ from salome.shaper import model
+ #=========================================================================
+ # Initialization of the test
+ #=========================================================================
+ __updated__ = "2017-05-10"
+ def horizontalDistance(point1, point2):
+     """
+     subroutine to calculate signed distance between two points
+     """
+     return point2.x() - point1.x()
+ aSession = ModelAPI_Session.get()
+ aDocument = aSession.moduleDocument()
+ #=========================================================================
+ # Creation of a sketch
+ #=========================================================================
+ aSession.startOperation()
+ aSketchCommonFeature = aDocument.addFeature("Sketch")
+ aSketchFeature = featureToCompositeFeature(aSketchCommonFeature)
+ origin = geomDataAPI_Point(aSketchFeature.attribute("Origin"))
+ origin.setValue(0, 0, 0)
+ dirx = geomDataAPI_Dir(aSketchFeature.attribute("DirX"))
+ dirx.setValue(1, 0, 0)
+ norm = geomDataAPI_Dir(aSketchFeature.attribute("Norm"))
+ norm.setValue(0, 0, 1)
+ aSession.finishOperation()
+ #=========================================================================
+ # Create two movable and one fixed point
+ #=========================================================================
+ aSession.startOperation()
+ aPoint1 = aSketchFeature.addFeature("SketchPoint")
+ aPoint1Coords = geomDataAPI_Point2D(aPoint1.attribute("PointCoordinates"))
+ aPoint1Coords.setValue(50., 50.)
+ aSession.finishOperation()
+ aSession.startOperation()
+ aPoint2 = aSketchFeature.addFeature("SketchPoint")
+ aPoint2Coords = geomDataAPI_Point2D(aPoint2.attribute("PointCoordinates"))
+ aPoint2Coords.setValue(70., 70.)
+ aSession.finishOperation()
+ aSession.startOperation()
+ anOriginResult = modelAPI_Result(aDocument.objectByName("Construction", "Origin"))
+ anOriginShape = anOriginResult.shape()
+ anExtPoint = aSketchFeature.addFeature("SketchPoint")
+ anExtCoords = geomDataAPI_Point2D(anExtPoint.attribute("PointCoordinates"))
+ anExtCoords.setValue(0., 0.)
+ anExtPoint.selection("External").setValue(anOriginResult, anOriginShape)
+ aSession.finishOperation()
+ assert (model.dof(aSketchFeature) == 4)
+ #=========================================================================
+ # Create a constraint to keep horizontal distance between movable points
+ #=========================================================================
+ DISTANCE1 = 25.
+ aSession.startOperation()
+ aHDist1 = aSketchFeature.addFeature("SketchConstraintDistanceHorizontal")
+ aDistance = aHDist1.real("ConstraintValue")
+ refattrA = aHDist1.refattr("ConstraintEntityA")
+ refattrB = aHDist1.refattr("ConstraintEntityB")
+ assert (not aDistance.isInitialized())
+ assert (not refattrA.isInitialized())
+ assert (not refattrB.isInitialized())
+ refattrA.setObject(aPoint1.lastResult())
+ refattrB.setObject(aPoint2.lastResult())
+ aSession.finishOperation()
+ assert (model.dof(aSketchFeature) == 3)
+ # set flyout point then abort operation, after that check the Distance is correct
+ aSession.startOperation()
+ aFlyoutPoint = geomDataAPI_Point2D(aHDist1.attribute("ConstraintFlyoutValuePnt"))
+ aFlyoutPoint.setValue(50.0, 100.0)
+ aSession.abortOperation()
+ assert (refattrA.isInitialized())
+ assert (refattrB.isInitialized())
+ assert (aDistance.isInitialized())
+ aSession.startOperation()
+ aDistance.setValue(DISTANCE1)
+ aSession.finishOperation()
+ assert math.fabs(horizontalDistance(aPoint1Coords, aPoint2Coords) - DISTANCE1) < 1.e-5, "Distance values are different: {0} != {1}".format(horizontalDistance(aPoint1Coords, aPoint2Coords), DISTANCE1)
+ assert (model.dof(aSketchFeature) == 3)
+ #=========================================================================
+ # Change a distance value
+ #=========================================================================
+ d = DISTANCE1 + 20.
+ dStep = -5.
+ while d >= -30.:
+     aSession.startOperation()
+     DISTANCE1 = d
+     aDistance.setValue(DISTANCE1)
+     aSession.finishOperation()
+     assert math.fabs(horizontalDistance(aPoint1Coords, aPoint2Coords) - DISTANCE1) < 1.e-5, "Distance values are different: {0} != {1}".format(horizontalDistance(aPoint1Coords, aPoint2Coords), DISTANCE1)
+     d += dStep
+ assert (model.dof(aSketchFeature) == 3)
+ #=========================================================================
+ # Create a constraint to keep horizontal distance between fixed and movable points
+ #=========================================================================
+ DISTANCE2 = 50.
+ aSession.startOperation()
+ aHDist2 = aSketchFeature.addFeature("SketchConstraintDistanceHorizontal")
+ aDistance = aHDist2.real("ConstraintValue")
+ refattrA = aHDist2.refattr("ConstraintEntityA")
+ refattrB = aHDist2.refattr("ConstraintEntityB")
+ assert (not aDistance.isInitialized())
+ assert (not refattrA.isInitialized())
+ assert (not refattrB.isInitialized())
+ refattrA.setObject(anExtPoint.lastResult())
+ refattrB.setAttr(aPoint1Coords)
+ aDistance.setValue(DISTANCE2)
+ aSession.finishOperation()
+ assert math.fabs(horizontalDistance(anExtCoords, aPoint1Coords) - DISTANCE2) < 1.e-5, "Distance values are different: {0} != {1}".format(horizontalDistance(anExtCoords, aPoint1Coords), DISTANCE2)
+ assert math.fabs(aPoint1Coords.x() - DISTANCE2) < 1.e-5, "Wrong point coordinates ({}, {}), expected x = {}".format(aPoint1Coords.x(), aPoint1Coords.y(), DISTANCE2)
+ assert (model.dof(aSketchFeature) == 2)
+ #=========================================================================
+ # Change a distance value (check previous constraint is applied too)
+ #=========================================================================
+ d = DISTANCE2
+ dStep = -5.
+ while d >= -50.:
+     aSession.startOperation()
+     DISTANCE2 = d
+     aDistance.setValue(DISTANCE2)
+     aSession.finishOperation()
+     assert math.fabs(horizontalDistance(anExtCoords, aPoint1Coords) - DISTANCE2) < 1.e-5, "Distance values are different: {0} != {1}".format(horizontalDistance(anExtCoords, aPoint1Coords), DISTANCE2)
+     assert math.fabs(aPoint1Coords.x() - DISTANCE2) < 1.e-5, "Wrong point coordinates ({}, {}), expected x = {}".format(aPoint1Coords.x(), aPoint1Coords.y(), DISTANCE2)
+     assert math.fabs(horizontalDistance(aPoint1Coords, aPoint2Coords) - DISTANCE1) < 1.e-5, "Distance values are different: {0} != {1}".format(horizontalDistance(aPoint1Coords, aPoint2Coords), DISTANCE1)
+     d += dStep
+ assert (model.dof(aSketchFeature) == 2)
+ #=========================================================================
+ # Remove first distance
+ #=========================================================================
+ aStoredCoords = [aPoint2Coords.x(), aPoint2Coords.y()]
+ aSession.startOperation()
+ aDocument.removeFeature(aHDist1)
+ aSession.finishOperation()
+ assert (model.dof(aSketchFeature) == 3)
+ aSession.startOperation()
+ DISTANCE2 = 20.
+ aDistance.setValue(DISTANCE2)
+ aSession.finishOperation()
+ assert math.fabs(horizontalDistance(anExtCoords, aPoint1Coords) - DISTANCE2) < 1.e-5, "Distance values are different: {0} != {1}".format(horizontalDistance(anExtCoords, aPoint1Coords), DISTANCE2)
+ assert math.fabs(aPoint1Coords.x() - DISTANCE2) < 1.e-5, "Wrong point coordinates ({}, {}), expected x = {}".format(aPoint1Coords.x(), aPoint1Coords.y(), DISTANCE2)
+ assert aPoint2Coords.x() == aStoredCoords[0] and aPoint2Coords.y() == aStoredCoords[1]
+ #=========================================================================
+ # Create line and set horizontal distance between line boundaries
+ #=========================================================================
+ aSession.startOperation()
+ aLine = aSketchFeature.addFeature("SketchLine")
+ aStartPoint = geomDataAPI_Point2D(aLine.attribute("StartPoint"))
+ aEndPoint = geomDataAPI_Point2D(aLine.attribute("EndPoint"))
+ aStartPoint.setValue(50., 0.)
+ aEndPoint.setValue(100., 20.)
+ aSession.finishOperation()
+ assert (model.dof(aSketchFeature) == 7)
+ DISTANCE3 = 50.
+ aSession.startOperation()
+ aHDist3 = aSketchFeature.addFeature("SketchConstraintDistanceHorizontal")
+ aDistance = aHDist3.real("ConstraintValue")
+ refattrA = aHDist3.refattr("ConstraintEntityA")
+ refattrB = aHDist3.refattr("ConstraintEntityB")
+ assert (not aDistance.isInitialized())
+ assert (not refattrA.isInitialized())
+ assert (not refattrB.isInitialized())
+ refattrA.setAttr(aStartPoint)
+ refattrB.setAttr(aEndPoint)
+ aDistance.setValue(DISTANCE3)
+ aSession.finishOperation()
+ assert math.fabs(horizontalDistance(aStartPoint, aEndPoint) - DISTANCE3) < 1.e-5, "Distance values are different: {0} != {1}".format(horizontalDistance(aStartPoint, aEndPoint), DISTANCE3)
+ assert (model.dof(aSketchFeature) == 6)
+ #=========================================================================
+ # Change a distance value
+ #=========================================================================
+ d = DISTANCE3
+ dStep = -5.
+ while d >= -50.:
+     aSession.startOperation()
+     DISTANCE3 = d
+     aDistance.setValue(DISTANCE3)
+     aSession.finishOperation()
+     assert math.fabs(horizontalDistance(aStartPoint, aEndPoint) - DISTANCE3) < 1.e-5, "Distance values are different: {0} != {1}".format(horizontalDistance(aStartPoint, aEndPoint), DISTANCE3)
+     d += dStep
+ assert (model.dof(aSketchFeature) == 6)
+ #=========================================================================
+ # End of test
+ #=========================================================================
+ assert(model.checkPythonDump())
index 0000000000000000000000000000000000000000,09ba211426e0a96ee499c3ef8c2737bd030703be..8910edcbfd5613e5da8b4e631d3d12ab6d63b393
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,208 +1,228 @@@
++## Copyright (C) 2017  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<mailto:webmaster.salome@opencascade.com>
++##
++
+ """
+     TestConstraintDistanceVertical.py
+     Unit test of SketchPlugin_ConstraintDistanceVertical class
+     SketchPlugin_ConstraintDistanceVertical
+         static const std::string MY_CONSTRAINT_DISTANCE_ID("SketchConstraintDistance");
+         data()->addAttribute(SketchPlugin_Constraint::VALUE(),    ModelAPI_AttributeDouble::typeId());
+         data()->addAttribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT(), GeomDataAPI_Point2D::typeId());
+         data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId());
+         data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::typeId());
+ """
+ from GeomDataAPI import *
+ from ModelAPI import *
+ import math
+ from salome.shaper import model
+ #=========================================================================
+ # Initialization of the test
+ #=========================================================================
+ __updated__ = "2017-05-10"
+ def verticalDistance(point1, point2):
+     """
+     subroutine to calculate signed distance between two points
+     """
+     return point2.y() - point1.y()
+ aSession = ModelAPI_Session.get()
+ aDocument = aSession.moduleDocument()
+ #=========================================================================
+ # Creation of a sketch
+ #=========================================================================
+ aSession.startOperation()
+ aSketchCommonFeature = aDocument.addFeature("Sketch")
+ aSketchFeature = featureToCompositeFeature(aSketchCommonFeature)
+ origin = geomDataAPI_Point(aSketchFeature.attribute("Origin"))
+ origin.setValue(0, 0, 0)
+ dirx = geomDataAPI_Dir(aSketchFeature.attribute("DirX"))
+ dirx.setValue(1, 0, 0)
+ norm = geomDataAPI_Dir(aSketchFeature.attribute("Norm"))
+ norm.setValue(0, 0, 1)
+ aSession.finishOperation()
+ #=========================================================================
+ # Create two movable and one fixed point
+ #=========================================================================
+ aSession.startOperation()
+ aPoint1 = aSketchFeature.addFeature("SketchPoint")
+ aPoint1Coords = geomDataAPI_Point2D(aPoint1.attribute("PointCoordinates"))
+ aPoint1Coords.setValue(50., 50.)
+ aSession.finishOperation()
+ aSession.startOperation()
+ aPoint2 = aSketchFeature.addFeature("SketchPoint")
+ aPoint2Coords = geomDataAPI_Point2D(aPoint2.attribute("PointCoordinates"))
+ aPoint2Coords.setValue(70., 70.)
+ aSession.finishOperation()
+ aSession.startOperation()
+ anOriginResult = modelAPI_Result(aDocument.objectByName("Construction", "Origin"))
+ anOriginShape = anOriginResult.shape()
+ anExtPoint = aSketchFeature.addFeature("SketchPoint")
+ anExtCoords = geomDataAPI_Point2D(anExtPoint.attribute("PointCoordinates"))
+ anExtCoords.setValue(0., 0.)
+ anExtPoint.selection("External").setValue(anOriginResult, anOriginShape)
+ aSession.finishOperation()
+ assert (model.dof(aSketchFeature) == 4)
+ #=========================================================================
+ # Create a constraint to keep vertical distance between movable points
+ #=========================================================================
+ DISTANCE1 = 25.
+ aSession.startOperation()
+ aVDist1 = aSketchFeature.addFeature("SketchConstraintDistanceVertical")
+ aDistance = aVDist1.real("ConstraintValue")
+ refattrA = aVDist1.refattr("ConstraintEntityA")
+ refattrB = aVDist1.refattr("ConstraintEntityB")
+ assert (not aDistance.isInitialized())
+ assert (not refattrA.isInitialized())
+ assert (not refattrB.isInitialized())
+ refattrA.setObject(aPoint1.lastResult())
+ refattrB.setObject(aPoint2.lastResult())
+ aSession.finishOperation()
+ assert (model.dof(aSketchFeature) == 3)
+ # set flyout point then abort operation, after that check the Distance is correct
+ aSession.startOperation()
+ aFlyoutPoint = geomDataAPI_Point2D(aVDist1.attribute("ConstraintFlyoutValuePnt"))
+ aFlyoutPoint.setValue(50.0, 100.0)
+ aSession.abortOperation()
+ assert (refattrA.isInitialized())
+ assert (refattrB.isInitialized())
+ assert (aDistance.isInitialized())
+ aSession.startOperation()
+ aDistance.setValue(DISTANCE1)
+ aSession.finishOperation()
+ assert math.fabs(verticalDistance(aPoint1Coords, aPoint2Coords) - DISTANCE1) < 1.e-5, "Distance values are different: {0} != {1}".format(verticalDistance(aPoint1Coords, aPoint2Coords), DISTANCE1)
+ assert (model.dof(aSketchFeature) == 3)
+ #=========================================================================
+ # Change a distance value
+ #=========================================================================
+ d = DISTANCE1 + 20.
+ dStep = -5.
+ while d >= -30.:
+     aSession.startOperation()
+     DISTANCE1 = d
+     aDistance.setValue(DISTANCE1)
+     aSession.finishOperation()
+     assert math.fabs(verticalDistance(aPoint1Coords, aPoint2Coords) - DISTANCE1) < 1.e-5, "Distance values are different: {0} != {1}".format(verticalDistance(aPoint1Coords, aPoint2Coords), DISTANCE1)
+     d += dStep
+ assert (model.dof(aSketchFeature) == 3)
+ #=========================================================================
+ # Create a constraint to keep vertical distance between fixed and movable points
+ #=========================================================================
+ DISTANCE2 = 50.
+ aSession.startOperation()
+ aVDist2 = aSketchFeature.addFeature("SketchConstraintDistanceVertical")
+ aDistance = aVDist2.real("ConstraintValue")
+ refattrA = aVDist2.refattr("ConstraintEntityA")
+ refattrB = aVDist2.refattr("ConstraintEntityB")
+ assert (not aDistance.isInitialized())
+ assert (not refattrA.isInitialized())
+ assert (not refattrB.isInitialized())
+ refattrA.setObject(anExtPoint.lastResult())
+ refattrB.setAttr(aPoint1Coords)
+ aDistance.setValue(DISTANCE2)
+ aSession.finishOperation()
+ assert math.fabs(verticalDistance(anExtCoords, aPoint1Coords) - DISTANCE2) < 1.e-5, "Distance values are different: {0} != {1}".format(verticalDistance(anExtCoords, aPoint1Coords), DISTANCE2)
+ assert math.fabs(aPoint1Coords.y() - DISTANCE2) < 1.e-5, "Wrong point coordinates ({}, {}), expected y = {}".format(aPoint1Coords.x(), aPoint1Coords.y(), DISTANCE2)
+ assert (model.dof(aSketchFeature) == 2)
+ #=========================================================================
+ # Change a distance value (check previous constraint is applied too)
+ #=========================================================================
+ d = DISTANCE2
+ dStep = -5.
+ while d >= -50.:
+     aSession.startOperation()
+     DISTANCE2 = d
+     aDistance.setValue(DISTANCE2)
+     aSession.finishOperation()
+     assert math.fabs(verticalDistance(anExtCoords, aPoint1Coords) - DISTANCE2) < 1.e-5, "Distance values are different: {0} != {1}".format(verticalDistance(anExtCoords, aPoint1Coords), DISTANCE2)
+     assert math.fabs(aPoint1Coords.y() - DISTANCE2) < 1.e-5, "Wrong point coordinates ({}, {}), expected y = {}".format(aPoint1Coords.x(), aPoint1Coords.y(), DISTANCE2)
+     assert math.fabs(verticalDistance(aPoint1Coords, aPoint2Coords) - DISTANCE1) < 1.e-5, "Distance values are different: {0} != {1}".format(verticalDistance(aPoint1Coords, aPoint2Coords), DISTANCE1)
+     d += dStep
+ assert (model.dof(aSketchFeature) == 2)
+ #=========================================================================
+ # Remove first distance
+ #=========================================================================
+ aStoredCoords = [aPoint2Coords.x(), aPoint2Coords.y()]
+ aSession.startOperation()
+ aDocument.removeFeature(aVDist1)
+ aSession.finishOperation()
+ assert (model.dof(aSketchFeature) == 3)
+ aSession.startOperation()
+ DISTANCE2 = 20.
+ aDistance.setValue(DISTANCE2)
+ aSession.finishOperation()
+ assert math.fabs(verticalDistance(anExtCoords, aPoint1Coords) - DISTANCE2) < 1.e-5, "Distance values are different: {0} != {1}".format(verticalDistance(anExtCoords, aPoint1Coords), DISTANCE2)
+ assert math.fabs(aPoint1Coords.y() - DISTANCE2) < 1.e-5, "Wrong point coordinates ({}, {}), expected y = {}".format(aPoint1Coords.x(), aPoint1Coords.y(), DISTANCE2)
+ assert aPoint2Coords.x() == aStoredCoords[0] and aPoint2Coords.y() == aStoredCoords[1]
+ #=========================================================================
+ # Create line and set vertical distance between line boundaries
+ #=========================================================================
+ aSession.startOperation()
+ aLine = aSketchFeature.addFeature("SketchLine")
+ aStartPoint = geomDataAPI_Point2D(aLine.attribute("StartPoint"))
+ aEndPoint = geomDataAPI_Point2D(aLine.attribute("EndPoint"))
+ aStartPoint.setValue(50., 0.)
+ aEndPoint.setValue(100., 20.)
+ aSession.finishOperation()
+ assert (model.dof(aSketchFeature) == 7)
+ DISTANCE3 = 50.
+ aSession.startOperation()
+ aVDist3 = aSketchFeature.addFeature("SketchConstraintDistanceVertical")
+ aDistance = aVDist3.real("ConstraintValue")
+ refattrA = aVDist3.refattr("ConstraintEntityA")
+ refattrB = aVDist3.refattr("ConstraintEntityB")
+ assert (not aDistance.isInitialized())
+ assert (not refattrA.isInitialized())
+ assert (not refattrB.isInitialized())
+ refattrA.setAttr(aStartPoint)
+ refattrB.setAttr(aEndPoint)
+ aDistance.setValue(DISTANCE3)
+ aSession.finishOperation()
+ assert math.fabs(verticalDistance(aStartPoint, aEndPoint) - DISTANCE3) < 1.e-5, "Distance values are different: {0} != {1}".format(verticalDistance(aStartPoint, aEndPoint), DISTANCE3)
+ assert (model.dof(aSketchFeature) == 6)
+ #=========================================================================
+ # Change a distance value
+ #=========================================================================
+ d = DISTANCE3
+ dStep = -5.
+ while d >= -50.:
+     aSession.startOperation()
+     DISTANCE3 = d
+     aDistance.setValue(DISTANCE3)
+     aSession.finishOperation()
+     assert math.fabs(verticalDistance(aStartPoint, aEndPoint) - DISTANCE3) < 1.e-5, "Distance values are different: {0} != {1}".format(verticalDistance(aStartPoint, aEndPoint), DISTANCE3)
+     d += dStep
+ assert (model.dof(aSketchFeature) == 6)
+ #=========================================================================
+ # End of test
+ #=========================================================================
+ assert(model.checkPythonDump())
index 0000000000000000000000000000000000000000,caf2f1a4932e59f25011d7280a057ea938ccf87f..103d7db80a1729ed03befdc89da41cf0eea0b176
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,50 +1,70 @@@
++## Copyright (C) 2017  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<mailto:webmaster.salome@opencascade.com>
++##
++
+ """
+     TestConstraintHorizontalValidator.py
+     It tests validation of horizontal and vertical segments in H and V constraints to avoid
+     selection segments that already have one of these constraint"
+ """
+ #=========================================================================
+ # of the test
+ #=========================================================================
+ from salome.shaper import model
+ from ModelAPI import *
+ import math
+ #=========================================================================
+ # Creation of a part
+ #=========================================================================
+ model.begin()
+ partSet = model.moduleDocument()
+ Part_1 = model.addPart(partSet)
+ Part_1_doc = Part_1.document()
+ #=========================================================================
+ # Creation of a sketch
+ #=========================================================================
+ Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ"))
+ SketchLine_1 = Sketch_1.addLine(20, 20, 40, 80)
+ SketchLine_2 = Sketch_1.addLine(40, 80, 60, 40)
+ SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+ SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+ SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_1.result())
+ model.do()
+ #=========================================================================
+ # Checking that sketch and constraints become invalid when to one line
+ # two horizontal/vertical constraints are applied in any combination
+ #=========================================================================
+ aFactory = ModelAPI_Session.get().validators()
+ assert(aFactory.validate(Sketch_1.feature()))
+ assert(Sketch_1.feature().error() != '')
+ #=========================================================================
+ # Remove duplicated Vertical constraints
+ #=========================================================================
+ Part_1_doc.removeFeature(SketchConstraintVertical_1.feature())
+ assert(aFactory.validate(Sketch_1.feature()))
+ model.do()
+ #=========================================================================
+ # Checking that after excess constraints are removed or undone,
+ # sketch becomes valid.
+ #=========================================================================
+ assert(aFactory.validate(Sketch_1.feature()))
+ assert(Sketch_1.feature().error() == '')
+ assert(model.checkPythonDump())
Simple merge
index 0000000000000000000000000000000000000000,10f4ec06a53de266e21c198b0ef15503681ec535..4419d85e1cf1fe72c4a950a2aef9d1c48474173e
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,329 +1,349 @@@
++## Copyright (C) 2017  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<mailto:webmaster.salome@opencascade.com>
++##
++
+ """
+     Test movement of the sketch arc of circle
+ """
+ import unittest
+ from GeomDataAPI import geomDataAPI_Point2D
+ from salome.shaper import model
+ __updated__ = "2017-05-11"
+ class TestMoveArc(unittest.TestCase):
+   def setUp(self):
+     model.begin()
+     self.myDocument = model.moduleDocument()
+     self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY"))
+     self.myCenter = [50., 50.]
+     self.myStart = [70., 50.]
+     self.myEnd = [50., 70.]
+     self.myArc = self.mySketch.addArc(self.myCenter[0], self.myCenter[1], self.myStart[0], self.myStart[1], self.myEnd[0], self.myEnd[1], False)
+     self.myDOF = 5
+     model.do()
+     self.checkDOF()
+   def tearDown(self):
+     model.assertArcValidity(self.myArc)
+     self.checkDOF()
+     model.end()
+     assert(model.checkPythonDump())
+   def checkDOF(self):
+     self.assertEqual(model.dof(self.mySketch), self.myDOF)
+   def checkPointCoordinates(self, thePoint, theCoordinates):
+     self.assertAlmostEqual(thePoint.x(), theCoordinates[0])
+     self.assertAlmostEqual(thePoint.y(), theCoordinates[1])
+   def checkPointOnArc(self, theCoordinates):
+     distPC = model.distancePointPoint(self.myArc.center(),  theCoordinates)
+     radius = model.distancePointPoint(self.myArc.center(), self.myArc.startPoint())
+     self.assertAlmostEqual(distPC, radius)
+   def checkArcRadius(self):
+     radius = model.distancePointPoint(self.myArc.center(), self.myArc.startPoint())
+     self.assertAlmostEqual(radius, self.myRadius)
+   def fixArcRadius(self):
+     self.myRadius = 20.
+     self.mySketch.setRadius(self.myArc.results()[1], self.myRadius)
+     self.myDOF -= 1
+     model.do()
+     self.checkDOF()
+   def fixPoint(self, thePoint):
+     self.mySketch.setFixed(thePoint)
+     self.myDOF -= 2
+     model.do()
+     self.checkDOF()
+   def fixArc(self):
+     self.mySketch.setFixed(self.myArc.results()[1])
+     self.myDOF -= 5
+     model.do()
+     self.checkDOF()
+   def test_move_center_of_free_arc(self):
+     """ Test 1. Movement of center of a free arc
+     """
+     newPosition = [self.myCenter[0] + 10., self.myCenter[1] - 15.]
+     self.mySketch.move(self.myArc.center(), newPosition[0], newPosition[1])
+     model.do()
+     self.checkPointCoordinates(self.myArc.center(), newPosition)
+   def test_move_start_of_free_arc(self):
+     """ Test 2. Movement of start point of a free arc
+     """
+     newPosition = [self.myStart[0] - 10., self.myStart[1] + 5.]
+     self.mySketch.move(self.myArc.startPoint(), newPosition[0], newPosition[1])
+     model.do()
+     self.checkPointCoordinates(self.myArc.center(), self.myCenter)
+     self.checkPointCoordinates(self.myArc.startPoint(), newPosition)
+   def test_move_end_of_free_arc(self):
+     """ Test 3. Movement of end point of a free arc
+     """
+     newPosition = [self.myEnd[0] + 10., self.myEnd[1] + 5.]
+     self.mySketch.move(self.myArc.endPoint(), newPosition[0], newPosition[1])
+     model.do()
+     self.checkPointCoordinates(self.myArc.center(), self.myCenter)
+     self.checkPointCoordinates(self.myArc.endPoint(), newPosition)
+   def test_move_free_arc(self):
+     """ Test 4. Movement of a free arc dragging the edge
+     """
+     newPosition = [100., 80.]
+     self.mySketch.move(self.myArc.defaultResult(), newPosition[0], newPosition[1])
+     model.do()
+     self.checkPointOnArc(newPosition)
+     self.checkPointCoordinates(self.myArc.center(), self.myCenter)
+   def test_move_center_of_arc_fixed_center(self):
+     """ Test 5. Movement of center of the arc with fixed center (nothing should be changed)
+     """
+     self.fixPoint(self.myArc.center())
+     newPosition = [self.myCenter[0] + 10., self.myCenter[1] - 15.]
+     self.mySketch.move(self.myArc.center(), newPosition[0], newPosition[1])
+     model.do()
+     self.checkPointCoordinates(self.myArc.center(), self.myCenter)
+   def test_move_start_of_arc_fixed_center(self):
+     """ Test 6. Movement of start point of the arc with fixed center
+     """
+     self.fixPoint(self.myArc.center())
+     newPosition = [self.myStart[0] - 10., self.myStart[1] + 5.]
+     self.mySketch.move(self.myArc.startPoint(), newPosition[0], newPosition[1])
+     model.do()
+     self.checkPointCoordinates(self.myArc.center(), self.myCenter)
+     self.checkPointCoordinates(self.myArc.startPoint(), newPosition)
+   def test_move_end_of_arc_fixed_center(self):
+     """ Test 7. Movement of end point of the arc with fixed center
+     """
+     self.fixPoint(self.myArc.center())
+     newPosition = [self.myEnd[0] + 10., self.myEnd[1] + 5.]
+     self.mySketch.move(self.myArc.endPoint(), newPosition[0], newPosition[1])
+     model.do()
+     self.checkPointCoordinates(self.myArc.center(), self.myCenter)
+     self.checkPointCoordinates(self.myArc.endPoint(), newPosition)
+   def test_move_arc_fixed_center(self):
+     """ Test 8. Movement of the arc with fixed center dragging the edge
+     """
+     self.fixPoint(self.myArc.center())
+     newPosition = [100., 80.]
+     self.mySketch.move(self.myArc.defaultResult(), newPosition[0], newPosition[1])
+     model.do()
+     self.checkPointOnArc(newPosition)
+     self.checkPointCoordinates(self.myArc.center(), self.myCenter)
+   def test_move_center_of_arc_fixed_start(self):
+     """ Test 9. Movement of center of the arc with fixed start point
+     """
+     self.fixPoint(self.myArc.startPoint())
+     newPosition = [self.myCenter[0] + 10., self.myCenter[1] - 15.]
+     self.mySketch.move(self.myArc.center(), newPosition[0], newPosition[1])
+     model.do()
+     self.checkPointCoordinates(self.myArc.center(), newPosition)
+     self.checkPointCoordinates(self.myArc.startPoint(), self.myStart)
+   def test_move_start_of_arc_fixed_start(self):
+     """ Test 10. Movement of start point of the arc with fixed start point (nothing should be changed)
+     """
+     self.fixPoint(self.myArc.startPoint())
+     newPosition = [self.myStart[0] - 10., self.myStart[1] + 5.]
+     self.mySketch.move(self.myArc.startPoint(), newPosition[0], newPosition[1])
+     model.do()
+     self.checkPointCoordinates(self.myArc.center(), self.myCenter)
+     self.checkPointCoordinates(self.myArc.startPoint(), self.myStart)
+     self.checkPointCoordinates(self.myArc.endPoint(), self.myEnd)
+   def test_move_end_of_arc_fixed_start(self):
+     """ Test 11. Movement of end point of the arc with fixed start point
+     """
+     self.fixPoint(self.myArc.startPoint())
+     newPosition = [self.myEnd[0] + 10., self.myEnd[1] + 5.]
+     self.mySketch.move(self.myArc.endPoint(), newPosition[0], newPosition[1])
+     model.do()
+     self.checkPointCoordinates(self.myArc.startPoint(), self.myStart)
+     self.assertNotEqual(self.myArc.center().x(), self.myCenter[0])
+     self.assertNotEqual(self.myArc.center().y(), self.myCenter[1])
+   def test_move_arc_fixed_start(self):
+     """ Test 12. Movement of the arc with fixed start point dragging the edge
+     """
+     self.fixPoint(self.myArc.startPoint())
+     newPosition = [100., 80.]
+     self.mySketch.move(self.myArc.defaultResult(), newPosition[0], newPosition[1])
+     model.do()
+     self.checkPointCoordinates(self.myArc.startPoint(), self.myStart)
+     self.assertNotEqual(self.myArc.center().x(), self.myCenter[0])
+     self.assertNotEqual(self.myArc.center().y(), self.myCenter[1])
+   def test_move_center_of_arc_fixed_end(self):
+     """ Test 13. Movement of center of the arc with fixed end point
+     """
+     self.fixPoint(self.myArc.endPoint())
+     newPosition = [self.myCenter[0] + 10., self.myCenter[1] - 15.]
+     self.mySketch.move(self.myArc.center(), newPosition[0], newPosition[1])
+     model.do()
+     self.checkPointCoordinates(self.myArc.center(), newPosition)
+     self.checkPointCoordinates(self.myArc.endPoint(), self.myEnd)
+   def test_move_start_of_arc_fixed_end(self):
+     """ Test 14. Movement of start point of the arc with fixed end point
+     """
+     self.fixPoint(self.myArc.endPoint())
+     newPosition = [self.myStart[0] - 10., self.myStart[1] + 5.]
+     self.mySketch.move(self.myArc.startPoint(), newPosition[0], newPosition[1])
+     model.do()
+     self.checkPointCoordinates(self.myArc.endPoint(), self.myEnd)
+     self.assertNotEqual(self.myArc.center().x(), self.myCenter[0])
+     self.assertNotEqual(self.myArc.center().y(), self.myCenter[1])
+   def test_move_end_of_arc_fixed_end(self):
+     """ Test 15. Movement of end point of the arc with fixed end point (nothing should be changed)
+     """
+     self.fixPoint(self.myArc.endPoint())
+     newPosition = [self.myEnd[0] + 10., self.myEnd[1] + 5.]
+     self.mySketch.move(self.myArc.endPoint(), newPosition[0], newPosition[1])
+     model.do()
+     self.checkPointCoordinates(self.myArc.center(), self.myCenter)
+     self.checkPointCoordinates(self.myArc.startPoint(), self.myStart)
+     self.checkPointCoordinates(self.myArc.endPoint(), self.myEnd)
+   def test_move_arc_fixed_end(self):
+     """ Test 16. Movement of the arc with fixed end point dragging the edge
+     """
+     self.fixPoint(self.myArc.endPoint())
+     newPosition = [100., 80.]
+     self.mySketch.move(self.myArc.defaultResult(), newPosition[0], newPosition[1])
+     model.do()
+     self.checkPointCoordinates(self.myArc.endPoint(), self.myEnd)
+     self.assertNotEqual(self.myArc.center().x(), self.myCenter[0])
+     self.assertNotEqual(self.myArc.center().y(), self.myCenter[1])
+   def test_move_center_of_arc_fixed_radius(self):
+     """ Test 17. Movement of center of the arc with fixed radius
+     """
+     self.fixArcRadius()
+     newPosition = [self.myCenter[0] + 10., self.myCenter[1] - 15.]
+     self.mySketch.move(self.myArc.center(), newPosition[0], newPosition[1])
+     model.do()
+     self.checkPointCoordinates(self.myArc.center(), newPosition)
+     self.checkArcRadius()
+   def test_move_start_of_arc_fixed_radius(self):
+     """ Test 18. Movement of start point of the arc with fixed radius
+     """
+     self.fixArcRadius()
+     newPosition = [self.myStart[0] - 10., self.myStart[1] + 5.]
+     self.mySketch.move(self.myArc.startPoint(), newPosition[0], newPosition[1])
+     model.do()
+     self.checkArcRadius()
+   def test_move_end_of_arc_fixed_radius(self):
+     """ Test 19. Movement of end point of the arc with fixed radius
+     """
+     self.fixArcRadius()
+     newPosition = [self.myEnd[0] + 10., self.myEnd[1] + 5.]
+     self.mySketch.move(self.myArc.endPoint(), newPosition[0], newPosition[1])
+     model.do()
+     self.checkArcRadius()
+   def test_move_arc_fixed_radius(self):
+     """ Test 20. Movement of the arc with fixed radius dragging the edge
+     """
+     self.fixArcRadius()
+     newPosition = [100., 80.]
+     self.mySketch.move(self.myArc.defaultResult(), newPosition[0], newPosition[1])
+     model.do()
+     self.checkArcRadius()
+   def test_move_center_of_fixed_arc(self):
+     """ Test 21. Movement of center of fully fixed arc (nothing should be changed)
+     """
+     self.fixArc()
+     newPosition = [self.myCenter[0] + 10., self.myCenter[1] - 15.]
+     self.mySketch.move(self.myArc.center(), newPosition[0], newPosition[1])
+     model.do()
+     self.checkPointCoordinates(self.myArc.center(), self.myCenter)
+     self.checkPointCoordinates(self.myArc.startPoint(), self.myStart)
+     self.checkPointCoordinates(self.myArc.endPoint(), self.myEnd)
+   def test_move_start_of_fixed_arc(self):
+     """ Test 22. Movement of start point of fully fixed arc (nothing should be changed)
+     """
+     self.fixArc()
+     newPosition = [self.myStart[0] - 10., self.myStart[1] + 5.]
+     self.mySketch.move(self.myArc.startPoint(), newPosition[0], newPosition[1])
+     model.do()
+     self.checkPointCoordinates(self.myArc.center(), self.myCenter)
+     self.checkPointCoordinates(self.myArc.startPoint(), self.myStart)
+     self.checkPointCoordinates(self.myArc.endPoint(), self.myEnd)
+   def test_move_end_of_fixed_arc(self):
+     """ Test 23. Movement of end point of fully fixed arc (nothing should be changed)
+     """
+     self.fixArc()
+     newPosition = [self.myEnd[0] + 10., self.myEnd[1] + 5.]
+     self.mySketch.move(self.myArc.endPoint(), newPosition[0], newPosition[1])
+     model.do()
+     self.checkPointCoordinates(self.myArc.center(), self.myCenter)
+     self.checkPointCoordinates(self.myArc.startPoint(), self.myStart)
+     self.checkPointCoordinates(self.myArc.endPoint(), self.myEnd)
+   def test_move_fixed_arc(self):
+     """ Test 24. Movement of fully fixed arc (nothing should be changed)
+     """
+     self.fixArc()
+     newPosition = [100., 80.]
+     self.mySketch.move(self.myArc.defaultResult(), newPosition[0], newPosition[1])
+     model.do()
+     self.checkPointCoordinates(self.myArc.center(), self.myCenter)
+     self.checkPointCoordinates(self.myArc.startPoint(), self.myStart)
+     self.checkPointCoordinates(self.myArc.endPoint(), self.myEnd)
+ if __name__ == '__main__':
+   unittest.main()
index 0000000000000000000000000000000000000000,fdccca617353510548e3d2955ea690a7e519d6db..54a9b580e5d6473e86aaeb53e791993c1e227205
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,129 +1,149 @@@
++## Copyright (C) 2017  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<mailto:webmaster.salome@opencascade.com>
++##
++
+ """
+     Test movement of the sketch circle
+ """
+ import unittest
+ from GeomDataAPI import geomDataAPI_Point2D
+ from salome.shaper import model
+ __updated__ = "2017-05-11"
+ class TestMoveCircle(unittest.TestCase):
+   def setUp(self):
+     model.begin()
+     self.myDocument = model.moduleDocument()
+     self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY"))
+     self.myCenter = [70., 50.]
+     self.myRadius = 20.
+     self.myCircle = self.mySketch.addCircle(self.myCenter[0], self.myCenter[1], self.myRadius)
+     self.myDOF = 3
+     model.do()
+     self.checkDOF()
+   def tearDown(self):
+     self.checkDOF()
+     model.end()
+     assert(model.checkPythonDump())
+   def checkDOF(self):
+     self.assertEqual(model.dof(self.mySketch), self.myDOF)
+   def checkPointCoordinates(self, thePoint, theCoordinates):
+     self.assertAlmostEqual(thePoint.x(), theCoordinates[0])
+     self.assertAlmostEqual(thePoint.y(), theCoordinates[1])
+   def checkPointOnCircle(self, theCoordinates):
+     self.assertAlmostEqual(model.distancePointPoint(self.myCircle.center(),  theCoordinates), self.myCircle.radius().value())
+   def fixCircleRadius(self):
+     self.mySketch.setRadius(self.myCircle.results()[1], self.myRadius)
+     self.myDOF -= 1
+     model.do()
+     self.checkDOF()
+   def fixCircleCenter(self):
+     self.mySketch.setFixed(self.myCircle.center())
+     self.myDOF -= 2
+     model.do()
+     self.checkDOF()
+   def test_move_center_free_circle(self):
+     """ Test 1. Movement of central point of a free circle
+     """
+     newPosition = [self.myCenter[0] + 20., self.myCenter[1] + 10.]
+     self.mySketch.move(self.myCircle.center(), newPosition[0], newPosition[1])
+     model.do()
+     self.checkPointCoordinates(self.myCircle.center(), newPosition)
+     self.assertAlmostEqual(self.myCircle.radius().value(), self.myRadius)
+   def test_move_free_circle(self):
+     """ Test 2. Movement of a free circle dragging the edge
+     """
+     newPosition = [120., 90.]
+     self.mySketch.move(self.myCircle.defaultResult(), newPosition[0], newPosition[1])
+     model.do()
+     self.checkPointCoordinates(self.myCircle.center(), self.myCenter)
+     self.checkPointOnCircle(newPosition)
+     self.assertNotEqual(self.myCircle.radius().value(), self.myRadius)
+   def test_move_center_circle_fixed_radius(self):
+     """ Test 3. Movement of central point of a circle with fixed radius
+     """
+     self.fixCircleRadius()
+     newPosition = [self.myCenter[0] + 20., self.myCenter[1] + 10.]
+     self.mySketch.move(self.myCircle.center(), newPosition[0], newPosition[1])
+     model.do()
+     self.checkPointCoordinates(self.myCircle.center(), newPosition)
+     self.assertAlmostEqual(self.myCircle.radius().value(), self.myRadius)
+   def test_move_circle_fixed_radius(self):
+     """ Test 4. Movement of a circle with fixed radius
+     """
+     self.fixCircleRadius()
+     newPosition = [120., 90.]
+     self.mySketch.move(self.myCircle.defaultResult(), newPosition[0], newPosition[1])
+     model.do()
+     self.assertAlmostEqual(self.myCircle.radius().value(), self.myRadius)
+     self.assertNotEqual(self.myCircle.center().x(), self.myCenter[0])
+     self.assertNotEqual(self.myCircle.center().y(), self.myCenter[1])
+   def test_move_center_circle_fixed_center(self):
+     """ Test 5. Movement of central point of a circle with fixed center (nothing should be changed)
+     """
+     self.fixCircleCenter()
+     newPosition = [self.myCenter[0] + 20., self.myCenter[1] + 10.]
+     self.mySketch.move(self.myCircle.center(), newPosition[0], newPosition[1])
+     model.do()
+     self.checkPointCoordinates(self.myCircle.center(), self.myCenter)
+     self.assertAlmostEqual(self.myCircle.radius().value(), self.myRadius)
+   def test_move_circle_fixed_center(self):
+     """ Test 6. Movement of a circle with fixed center
+     """
+     self.fixCircleCenter()
+     newPosition = [120., 90.]
+     self.mySketch.move(self.myCircle.defaultResult(), newPosition[0], newPosition[1])
+     model.do()
+     self.checkPointOnCircle(newPosition)
+     self.assertNotEqual(self.myCircle.radius().value(), self.myRadius)
+   def test_move_fixed_circle(self):
+     """ Test 7. Trying to move fully fixed circle
+     """
+     self.fixCircleCenter()
+     self.fixCircleRadius()
+     newPosition = [120., 90.]
+     self.mySketch.move(self.myCircle.defaultResult(), newPosition[0], newPosition[1])
+     model.do()
+     self.checkPointCoordinates(self.myCircle.center(), self.myCenter)
+     self.assertAlmostEqual(self.myCircle.radius().value(), self.myRadius)
+ if __name__ == '__main__':
+   unittest.main()
index 0000000000000000000000000000000000000000,89c6f7fecc9e16813741f9d289ab6efab9996324..3d4efa1dc5aba29f2aaf0a5e4b76d02553a405c9
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,116 +1,136 @@@
++## Copyright (C) 2017  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<mailto:webmaster.salome@opencascade.com>
++##
++
+ """
+     Test movement of the sketch line
+ """
+ import unittest
+ from GeomDataAPI import geomDataAPI_Point2D
+ from salome.shaper import model
+ __updated__ = "2017-05-11"
+ class TestMoveLine(unittest.TestCase):
+   def setUp(self):
+     model.begin()
+     self.myDocument = model.moduleDocument()
+     self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY"))
+     self.myStart = [70., 50.]
+     self.myEnd = [100., 20.]
+     self.myLine = self.mySketch.addLine(self.myStart[0], self.myStart[1], self.myEnd[0], self.myEnd[1])
+     self.myDOF = 4
+     model.do()
+     self.checkDOF()
+   def tearDown(self):
+     self.checkDOF()
+     model.end()
+     assert(model.checkPythonDump())
+   def checkDOF(self):
+     self.assertEqual(model.dof(self.mySketch), self.myDOF)
+   def checkPointCoordinates(self, thePoint, theCoordinates):
+     self.assertAlmostEqual(thePoint.x(), theCoordinates[0])
+     self.assertAlmostEqual(thePoint.y(), theCoordinates[1])
+   def checkPointOnLine(self, theCoordinates):
+     self.assertAlmostEqual(model.distancePointLine(theCoordinates, self.myLine), 0.)
+   def test_move_start_of_free_line(self):
+     """ Test 1. Movement of start point of a free line
+     """
+     newPosition = [self.myStart[0] + 20., self.myStart[1] + 10.]
+     self.mySketch.move(self.myLine.startPoint(), newPosition[0], newPosition[1])
+     model.do()
+     self.checkPointCoordinates(self.myLine.startPoint(), newPosition)
+     self.checkPointCoordinates(self.myLine.endPoint(), self.myEnd)
+   def test_move_end_of_free_line(self):
+     """ Test 2. Movement of end point of a free line
+     """
+     newPosition = [self.myEnd[0] + 20., self.myEnd[1] + 10.]
+     self.mySketch.move(self.myLine.endPoint(), newPosition[0], newPosition[1])
+     model.do()
+     self.checkPointCoordinates(self.myLine.startPoint(), self.myStart)
+     self.checkPointCoordinates(self.myLine.endPoint(), newPosition)
+   def test_move_free_line(self):
+     """ Test 3. Movement of free line
+     """
+     diff = [self.myEnd[0] - self.myStart[0], self.myEnd[1] - self.myStart[1]]
+     newPosition = [100., 100.]
+     self.mySketch.move(self.myLine.defaultResult(), newPosition[0], newPosition[1])
+     model.do()
+     self.checkPointOnLine(newPosition)
+     # additionally check the line keeps geometry (relative positions of extremities)
+     startPoint = self.myLine.startPoint()
+     endPoint = [startPoint.x() + diff[0], startPoint.y() + diff[1]]
+     self.checkPointCoordinates(self.myLine.endPoint(), endPoint)
+   def test_move_line_start_fixed(self):
+     """ Test 4. Movement of a line, which start point is fixed
+     """
+     fixed = self.mySketch.setFixed(self.myLine.startPoint())
+     self.myDOF -= 2
+     model.do()
+     self.checkDOF()
+     newPosition = [100., 100.]
+     self.mySketch.move(self.myLine.defaultResult(), newPosition[0], newPosition[1])
+     model.do()
+     self.checkPointCoordinates(self.myLine.startPoint(), self.myStart)
+     self.assertNotEqual(self.myLine.endPoint().x(), self.myEnd[0])
+     self.assertNotEqual(self.myLine.endPoint().y(), self.myEnd[1])
+   def test_move_line_end_fixed(self):
+     """ Test 5. Movement of a line, which end point is fixed
+     """
+     fixed = self.mySketch.setFixed(self.myLine.endPoint())
+     self.myDOF -= 2
+     model.do()
+     self.checkDOF()
+     newPosition = [100., 100.]
+     self.mySketch.move(self.myLine.defaultResult(), newPosition[0], newPosition[1])
+     model.do()
+     self.assertNotEqual(self.myLine.startPoint().x(), self.myStart[0])
+     self.assertNotEqual(self.myLine.startPoint().y(), self.myStart[1])
+     self.checkPointCoordinates(self.myLine.endPoint(), self.myEnd)
+   def test_move_line_fully_fixed(self):
+     """ Test 6. Movement of fully fixed line (should not change its coordinates)
+     """
+     fixed = self.mySketch.setFixed(self.myLine.defaultResult())
+     self.myDOF -= 4
+     model.do()
+     newPosition = [100., 100.]
+     self.mySketch.move(self.myLine.defaultResult(), newPosition[0], newPosition[1])
+     model.do()
+     self.checkPointCoordinates(self.myLine.startPoint(), self.myStart)
+     self.checkPointCoordinates(self.myLine.endPoint(), self.myEnd)
+ if __name__ == '__main__':
+   unittest.main()
index 0000000000000000000000000000000000000000,88a143a17a47162f82d5ce7e8dce49f88533fedb..60b0a43b640fd3fdedce506b4dbe4788465ec53d
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,88 +1,108 @@@
++## Copyright (C) 2017  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<mailto:webmaster.salome@opencascade.com>
++##
++
+ """
+     Test movement of the sketch point
+ """
+ import unittest
+ from GeomDataAPI import geomDataAPI_Point2D
+ from salome.shaper import model
+ __updated__ = "2017-05-11"
+ class TestMovePoint(unittest.TestCase):
+   def setUp(self):
+     model.begin()
+     self.myDocument = model.moduleDocument()
+     self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY"))
+     self.myOrigin = self.mySketch.addPoint(model.selection("VERTEX", "Origin"))
+     self.myPoint = self.mySketch.addPoint(70, 50)
+     self.myPointCoordinates = geomDataAPI_Point2D(self.myPoint.coordinates())
+     self.myDOF = 2
+     model.do()
+     self.checkDOF()
+   def tearDown(self):
+     self.checkDOF()
+     model.end()
+     assert(model.checkPythonDump())
+   def checkDOF(self):
+     self.assertEqual(model.dof(self.mySketch), self.myDOF)
+   def test_move_free_point(self):
+     """ Test 1. Movement of free point
+     """
+     newPosition = [100., 100.]
+     self.mySketch.move(self.myPoint, newPosition[0], newPosition[1])
+     model.do()
+     self.assertAlmostEqual(self.myPointCoordinates.x(), newPosition[0])
+     self.assertAlmostEqual(self.myPointCoordinates.y(), newPosition[1])
+   def test_move_fixed_x(self):
+     """ Test 2. Movement of partially fixed point (fixed x coordinate)
+     """
+     DISTANCE = 50.
+     horizDistance = self.mySketch.setHorizontalDistance(self.myOrigin.result(), self.myPoint.coordinates(), DISTANCE)
+     self.myDOF -= 1
+     model.do()
+     self.checkDOF()
+     newPosition = [100., 100.]
+     self.mySketch.move(self.myPoint, newPosition[0], newPosition[1])
+     model.do()
+     self.assertAlmostEqual(self.myPointCoordinates.x(), DISTANCE)
+     self.assertAlmostEqual(self.myPointCoordinates.y(), newPosition[1])
+   def test_move_fixed_y(self):
+     """ Test 3. Movement of partially fixed point (fixed y coordinate)
+     """
+     DISTANCE = 50.
+     vertDistance = self.mySketch.setVerticalDistance(self.myOrigin.result(), self.myPoint.coordinates(), DISTANCE)
+     self.myDOF -= 1
+     model.do()
+     self.checkDOF()
+     newPosition = [100., 100.]
+     self.mySketch.move(self.myPoint, newPosition[0], newPosition[1])
+     model.do()
+     self.assertAlmostEqual(self.myPointCoordinates.x(), newPosition[0])
+     self.assertAlmostEqual(self.myPointCoordinates.y(), DISTANCE)
+   def test_move_fully_fixed(self):
+     """ Test 4. Movement of fully fixed point (should not be changed)
+     """
+     coord = [self.myPointCoordinates.x(), self.myPointCoordinates.y()]
+     fixed = self.mySketch.setFixed(self.myPoint.result())
+     self.myDOF -= 2
+     model.do()
+     self.checkDOF()
+     newPosition = [100., 100.]
+     self.mySketch.move(self.myPoint, newPosition[0], newPosition[1])
+     model.do()
+     self.assertAlmostEqual(self.myPointCoordinates.x(), coord[0])
+     self.assertAlmostEqual(self.myPointCoordinates.y(), coord[1])
+ if __name__ == '__main__':
+   unittest.main()
index 0000000000000000000000000000000000000000,6b576fdccb68fd77e8652a8bb8ea92fda6231c65..6fe6afe903899dd5d1a69f4661d8fdda08515369
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,364 +1,384 @@@
++## Copyright (C) 2017  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<mailto:webmaster.salome@opencascade.com>
++##
++
+ """
+     Test moving the entities in the complex sketch by the example of a clamp
+ """
+ from salome.shaper import model
+ from SketchAPI import *
+ from GeomAPI import *
+ import math
+ TOLERANCE = 1.e-7
+ model.begin()
+ partSet = model.moduleDocument()
+ Part_1 = model.addPart(partSet)
+ Part_1_doc = Part_1.document()
+ # Create sketch representing main part of clamp
+ Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+ SketchLine_1 = Sketch_1.addLine(20, 165, 175, 165)
+ SketchLine_2 = Sketch_1.addLine(175, 165, 175, 120)
+ SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+ SketchLine_3 = Sketch_1.addLine(175, 120, 80, 20)
+ SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+ SketchLine_4 = Sketch_1.addLine(80, 20, 20, 20)
+ SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+ SketchLine_5 = Sketch_1.addLine(20, 20, 20, 165)
+ SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+ SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_5.endPoint())
+ SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), 155)
+ SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+ SketchConstraintPerpendicular_1 = Sketch_1.setPerpendicular(SketchLine_2.result(), SketchLine_1.result())
+ SketchConstraintParallel_1 = Sketch_1.setParallel(SketchLine_1.result(), SketchLine_4.result())
+ SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_5.result())
+ SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_2.result(), 45)
+ SketchConstraintDistance_1 = Sketch_1.setDistance(SketchLine_4.startPoint(), SketchLine_1.result(), 145)
+ SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchLine_4.startPoint(), SketchLine_3.startPoint(), 95)
+ SketchPoint_1 = Sketch_1.addPoint(model.selection("VERTEX", "PartSet/Origin"))
+ SketchConstraintDistanceHorizontal_2 = Sketch_1.setHorizontalDistance(SketchPoint_1.coordinates(), SketchLine_5.endPoint(), 20)
+ SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchPoint_1.coordinates(), SketchLine_5.endPoint(), 165)
+ model.do()
+ # =============================================================================
+ # Test 1. Create fillet and move fillet arc
+ # =============================================================================
+ Sketch_1.setFillet(SketchLine_5.startPoint())
+ SketchArc_1 = SketchAPI_Arc(model.lastSubFeature(Sketch_1, "SketchArc"))
+ model.do()
+ anArcCenter = [SketchArc_1.center().x(), SketchArc_1.center().y()]
+ anArcStart  = [SketchArc_1.startPoint().x(), SketchArc_1.startPoint().y()]
+ anArcEnd    = [SketchArc_1.endPoint().x(), SketchArc_1.endPoint().y()]
+ # move arc dragging center
+ delta = [1., 1.]
+ for i in range(1, 10):
+     anArcCenter = [anArcCenter[0] + delta[0], anArcCenter[1] + delta[1]]
+     Sketch_1.move(SketchArc_1.center(), anArcCenter[0], anArcCenter[1])
+     model.do()
+     model.assertArcValidity(SketchArc_1)
+     model.assertPoint(SketchArc_1.center(), anArcCenter)
+     assert(SketchArc_1.startPoint().x() == anArcStart[0])
+     assert(SketchArc_1.endPoint().y() == anArcEnd[1])
+     if i == 5:
+         delta = [-1., -1.]
+ # move arc dragging start point
+ delta = [1., 1.]
+ aPosition = anArcStart
+ for i in range(1, 10):
+     aPosition = [aPosition[0] + delta[0], aPosition[1] + delta[1]]
+     Sketch_1.move(SketchArc_1.startPoint(), aPosition[0], aPosition[1])
+     model.do()
+     model.assertArcValidity(SketchArc_1)
+     assert(SketchArc_1.startPoint().x() == anArcStart[0])
+     assert(SketchArc_1.endPoint().y() == anArcEnd[1])
+     if i == 5:
+         delta = [-1., -1.]
+ # move arc dragging end point
+ delta = [1., 1.]
+ aPosition = anArcEnd
+ for i in range(1, 10):
+     aPosition = [aPosition[0] + delta[0], aPosition[1] + delta[1]]
+     Sketch_1.move(SketchArc_1.endPoint(), aPosition[0], aPosition[1])
+     model.do()
+     model.assertArcValidity(SketchArc_1)
+     assert(SketchArc_1.startPoint().x() == anArcStart[0])
+     assert(SketchArc_1.endPoint().y() == anArcEnd[1])
+     if i == 5:
+         delta = [-1., -1.]
+ # =============================================================================
+ # Test 2. Create circle and move it near its potential position
+ # =============================================================================
+ aCircleCenter = [0, 0]
+ aCircleRadius = 5
+ SketchCircle_1 = Sketch_1.addCircle(aCircleCenter[0], aCircleCenter[1], aCircleRadius)
+ model.do()
+ # move center
+ delta = [3., 2.]
+ for i in range(1, 15):
+     aCircleCenter = [aCircleCenter[0] + delta[0], aCircleCenter[1] + delta[1]]
+     Sketch_1.move(SketchCircle_1.center(), aCircleCenter[0], aCircleCenter[1])
+     model.do()
+     model.assertPoint(SketchCircle_1.center(), aCircleCenter)
+     assert(SketchCircle_1.radius().value() == aCircleRadius)
+ # move circle by dragging edge
+ aPosition = [aCircleCenter[0] + aCircleRadius, aCircleCenter[1]]
+ delta = [1., 1.]
+ for i in range(1, 10):
+     aPosition = [aPosition[0] + delta[0], aPosition[1] + delta[1]]
+     Sketch_1.move(SketchCircle_1.defaultResult(), aPosition[0], aPosition[1])
+     model.do()
+     model.assertPoint(SketchCircle_1.center(), aCircleCenter)
+     assert(math.fabs(SketchCircle_1.radius().value() - model.distancePointPoint(aPosition, aCircleCenter)) < TOLERANCE)
+ # =============================================================================
+ # Test 3. Constrain center of circle and move it again
+ # =============================================================================
+ SketchConstraintDistanceHorizontal_3 = Sketch_1.setHorizontalDistance(SketchCircle_1.center(), SketchArc_1.startPoint(), -30)
+ model.do()
+ # move center
+ delta = [1., 1.]
+ aCircleCenter = [SketchCircle_1.center().x(), SketchCircle_1.center().y()]
+ aPosition = aCircleCenter
+ for i in range(1, 10):
+     aPosition = [aPosition[0] + delta[0], aPosition[1] + delta[1]]
+     Sketch_1.move(SketchCircle_1.center(), aPosition[0], aPosition[1])
+     model.do()
+     assert(SketchCircle_1.center().x() == aCircleCenter[0])
+     if i == 5:
+         delta = [-1., -1.]
+ # move circle by dragging edge
+ aCircleCenter = [SketchCircle_1.center().x(), SketchCircle_1.center().y()]
+ aPosition = [aCircleCenter[0] + aCircleRadius, aCircleCenter[1]]
+ delta = [1., 1.]
+ for i in range(1, 10):
+     aPosition = [aPosition[0] + delta[0], aPosition[1] + delta[1]]
+     Sketch_1.move(SketchCircle_1.defaultResult(), aPosition[0], aPosition[1])
+     model.do()
+     model.assertPoint(SketchCircle_1.center(), aCircleCenter)
+     assert(math.fabs(SketchCircle_1.radius().value() - model.distancePointPoint(aPosition, aCircleCenter)) < TOLERANCE)
+ # set radius of the circle
+ aCircleRadius = 17.5
+ SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], aCircleRadius)
+ model.do()
+ # move center
+ delta = [1., 1.]
+ aCircleCenter = [SketchCircle_1.center().x(), SketchCircle_1.center().y()]
+ aPosition = aCircleCenter
+ for i in range(1, 10):
+     aPosition = [aPosition[0] + delta[0], aPosition[1] + delta[1]]
+     Sketch_1.move(SketchCircle_1.center(), aPosition[0], aPosition[1])
+     model.do()
+     assert(SketchCircle_1.center().x() == aCircleCenter[0])
+     assert(SketchCircle_1.radius().value() == aCircleRadius)
+     if i == 5:
+         delta = [-1., -1.]
+ # move circle by dragging edge
+ aCircleCenter = [SketchCircle_1.center().x(), SketchCircle_1.center().y()]
+ aPosition = [aCircleCenter[0] + aCircleRadius, aCircleCenter[1]]
+ delta = [1., 1.]
+ for i in range(1, 10):
+     aPosition = [aPosition[0] + delta[0], aPosition[1] + delta[1]]
+     Sketch_1.move(SketchCircle_1.defaultResult(), aPosition[0], aPosition[1])
+     model.do()
+     assert(SketchCircle_1.center().x() == aCircleCenter[0])
+     assert(SketchCircle_1.radius().value() == aCircleRadius)
+ # =============================================================================
+ # Test 4. Set centers of circle and arc coincident and move circle
+ # =============================================================================
+ SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchCircle_1.center(), SketchArc_1.center())
+ model.do()
+ assert(model.dof(Sketch_1) == 0)
+ # move circle
+ aCircleCenter = [SketchCircle_1.center().x(), SketchCircle_1.center().y()]
+ aPosition = [aCircleCenter[0], aCircleCenter[1] + aCircleRadius]
+ delta = [0., 1.]
+ for i in range(1, 10):
+     aPosition = [aPosition[0] + delta[0], aPosition[1] + delta[1]]
+     Sketch_1.move(SketchCircle_1.defaultResult(), aPosition[0], aPosition[1])
+     model.do()
+     model.assertPoint(SketchCircle_1.center(), aCircleCenter)
+     assert(SketchCircle_1.radius().value() == aCircleRadius)
+ assert(model.dof(Sketch_1) == 0)
+ # Extrude main part of clamp
+ Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2r-SketchLine_3r-SketchLine_4r-SketchLine_5r-SketchArc_1_2f-SketchCircle_1_2r")], model.selection(), 10, 0)
+ model.do()
+ # Create sketch representing orthogonal part of clamp
+ Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ"))
+ SketchRectangle_1 = Sketch_2.addRectangle(20, 0, 100, 50)
+ [SketchLine_6, SketchLine_7, SketchLine_8, SketchLine_9] = SketchRectangle_1.lines()
+ SketchProjection_1 = Sketch_2.addProjection(model.selection("EDGE", "Sketch_1/Edge-SketchLine_1"))
+ SketchLine_10 = SketchProjection_1.createdFeature()
+ SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchAPI_Line(SketchLine_7).startPoint(), SketchAPI_Line(SketchLine_10).startPoint())
+ SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_8.result(), SketchLine_10.result())
+ SketchConstraintLength_3 = Sketch_2.setLength(SketchLine_7.result(), 80)
+ model.do()
+ assert(model.dof(Sketch_2) == 0)
+ # Create auxiliary lines for further holes
+ SketchLine_11 = Sketch_2.addLine(20, 10, 175, 10)
+ SketchLine_11.setAuxiliary(True)
+ SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchLine_11.startPoint(), SketchLine_7.result())
+ SketchConstraintCoincidence_9 = Sketch_2.setCoincident(SketchLine_11.endPoint(), SketchLine_9.result())
+ SketchConstraintParallel_2 = Sketch_2.setParallel(SketchLine_11.result(), SketchLine_8.result())
+ SketchLine_12 = Sketch_2.addLine(150, 0, 150, 80)
+ SketchLine_12.setAuxiliary(True)
+ SketchConstraintCoincidence_10 = Sketch_2.setCoincident(SketchLine_12.startPoint(), SketchLine_6.result())
+ SketchConstraintCoincidence_11 = Sketch_2.setCoincident(SketchLine_12.endPoint(), SketchLine_8.result())
+ SketchConstraintPerpendicular_2 = Sketch_2.setPerpendicular(SketchLine_11.result(), SketchLine_12.result())
+ model.do()
+ assert(model.dof(Sketch_2) == 2)
+ # =============================================================================
+ # Test 5. Create circular hole and move it
+ # =============================================================================
+ SketchCircle_2 = Sketch_2.addCircle(50, 10, 10)
+ SketchConstraintCoincidence_12 = Sketch_2.setCoincident(SketchCircle_2.center(), SketchLine_11.result())
+ model.do()
+ # move center
+ delta = [2., 1.]
+ aCircleCenter = [SketchCircle_2.center().x(), SketchCircle_2.center().y()]
+ aCircleRadius = SketchCircle_2.radius().value()
+ for i in range(1, 10):
+     aCircleCenter = [aCircleCenter[0] + delta[0], aCircleCenter[1] + delta[1]]
+     Sketch_2.move(SketchCircle_2.center(), aCircleCenter[0], aCircleCenter[1])
+     model.do()
+     model.assertPoint(SketchCircle_2.center(), aCircleCenter)
+     assert(aCircleRadius == SketchCircle_2.radius().value())
+ # move circle by dragging edge
+ aCircleCenter = [SketchCircle_2.center().x(), SketchCircle_2.center().y()]
+ aPosition = [aCircleCenter[0] + aCircleRadius, aCircleCenter[1]]
+ delta = [0., 1.]
+ for i in range(1, 10):
+     aPosition = [aPosition[0] + delta[0], aPosition[1] + delta[1]]
+     Sketch_1.move(SketchCircle_2.defaultResult(), aPosition[0], aPosition[1])
+     model.do()
+     model.assertPoint(SketchCircle_2.center(), aCircleCenter)
+     assert(math.fabs(SketchCircle_2.radius().value() - model.distancePointPoint(aPosition, aCircleCenter)) < TOLERANCE)
+ SketchConstraintDistanceHorizontal_4 = Sketch_2.setHorizontalDistance(SketchLine_11.startPoint(), SketchCircle_2.center(), 21.5)
+ model.do()
+ assert(model.dof(Sketch_2) == 3)
+ # =============================================================================
+ # Test 6. Create oval hole and move it
+ # =============================================================================
+ anArcRadius = 5
+ anArcCenter = [SketchLine_11.endPoint().x() + anArcRadius, SketchCircle_2.center().y()]
+ SketchArc_2 = Sketch_2.addArc(anArcCenter[0], anArcCenter[1], anArcCenter[0], anArcCenter[1] + anArcRadius, anArcCenter[0], anArcCenter[1] - anArcRadius, True)
+ SketchConstraintCoincidence_13 = Sketch_2.setCoincident(SketchArc_2.center(), SketchLine_11.result())
+ SketchLine_13 = Sketch_2.addLine(anArcCenter[0], anArcCenter[1] + anArcRadius, SketchLine_12.startPoint().x(), anArcCenter[1] + anArcRadius)
+ SketchConstraintCoincidence_14 = Sketch_2.setCoincident(SketchArc_2.startPoint(), SketchLine_13.startPoint())
+ SketchConstraintCoincidence_15 = Sketch_2.setCoincident(SketchLine_13.endPoint(), SketchLine_12.result())
+ SketchConstraintPerpendicular_3 = Sketch_2.setPerpendicular(SketchLine_13.result(), SketchLine_12.result())
+ SketchLine_14 = Sketch_2.addLine(anArcCenter[0], anArcCenter[1] - anArcRadius, SketchLine_12.startPoint().x(), anArcCenter[1] - anArcRadius)
+ SketchConstraintCoincidence_16 = Sketch_2.setCoincident(SketchArc_2.endPoint(), SketchLine_14.startPoint())
+ SketchConstraintCoincidence_17 = Sketch_2.setCoincident(SketchLine_14.endPoint(), SketchLine_12.result())
+ SketchConstraintPerpendicular_4 = Sketch_2.setPerpendicular(SketchLine_14.result(), SketchLine_12.result())
+ SketchConstraintTangent_1 = Sketch_2.setTangent(SketchArc_2.results()[1], SketchLine_13.result())
+ SketchConstraintTangent_2 = Sketch_2.setTangent(SketchArc_2.results()[1], SketchLine_14.result())
+ model.do()
+ assert(model.dof(Sketch_2) == 5)
+ # move center of arc
+ delta = [-2., 1.]
+ anArcCenter = [SketchArc_2.center().x(), SketchArc_2.center().y()]
+ for i in range(1, 10):
+     anArcCenter = [anArcCenter[0] + delta[0], anArcCenter[1] + delta[1]]
+     Sketch_2.move(SketchArc_2.center(), anArcCenter[0], anArcCenter[1])
+     model.do()
+     model.assertArc(SketchArc_2, anArcCenter, [], [])
+ # Complete the oval hole
+ SketchConstraintMirror_1_objects = [SketchLine_13.result(), SketchArc_2.results()[1], SketchLine_14.result()]
+ SketchConstraintMirror_1 = Sketch_2.addMirror(SketchLine_12.result(), SketchConstraintMirror_1_objects)
+ [SketchLine_15, SketchArc_3, SketchLine_16] = SketchConstraintMirror_1.mirrored()
+ model.do()
+ # =============================================================================
+ # Test 7. Set arc and circle equal radii and move arc
+ # =============================================================================
+ SketchConstraintEqual_2 = Sketch_2.setEqual(SketchCircle_2.results()[1], SketchArc_2.results()[1])
+ model.do()
+ # move center of arc
+ delta = [-1., -1.]
+ anArcCenter = [SketchArc_2.center().x(), SketchArc_2.center().y()]
+ aCircleCenter = [SketchCircle_2.center().x(), SketchCircle_2.center().y()]
+ for i in range(1, 10):
+     anArcCenter = [anArcCenter[0] + delta[0], anArcCenter[1] + delta[1]]
+     Sketch_2.move(SketchArc_2.center(), anArcCenter[0], anArcCenter[1])
+     model.do()
+     model.assertArc(SketchArc_2, anArcCenter, [], [])
+     model.assertPoint(SketchCircle_2.center(), [aCircleCenter[0], anArcCenter[1]])
+     anArcRadius = model.distancePointPoint(SketchArc_2.center(), SketchArc_2.startPoint())
+     assert(math.fabs(SketchCircle_2.radius().value() - anArcRadius) < TOLERANCE)
+ # move arc by dragging edge
+ aCircleCenter = [SketchCircle_2.center().x(), SketchCircle_2.center().y()]
+ anArcCenter = [SketchArc_2.center().x(), SketchArc_2.center().y()]
+ aPosition = [anArcCenter[0] + anArcRadius, anArcCenter[1]]
+ delta = [1., 1.]
+ for i in range(1, 10):
+     aPosition = [aPosition[0] + delta[0], aPosition[1] + delta[1]]
+     Sketch_2.move(SketchArc_2.defaultResult(), aPosition[0], aPosition[1])
+     model.do()
+     model.assertArc(SketchArc_2, anArcCenter, [], [])
+     model.assertPoint(SketchCircle_2.center(), aCircleCenter)
+     anArcRadius = model.distancePointPoint(SketchArc_2.center(), SketchArc_2.startPoint())
+     assert(math.fabs(SketchCircle_2.radius().value() - anArcRadius) < TOLERANCE)
+     if i == 5:
+         delta = [-1., -1.]
+ # Fix all DOF in Sketch_2
+ SketchConstraintDistance_2 = Sketch_2.setDistance(SketchArc_2.center(), SketchLine_9.result(), 21.5)
+ SketchConstraintLength_4 = Sketch_2.setLength(SketchLine_13.result(), 3.5)
+ SketchConstraintRadius_2 = Sketch_2.setRadius(SketchCircle_2.results()[1], 6.5)
+ SketchConstraintDistance_3 = Sketch_2.setDistance(SketchCircle_2.center(), SketchLine_8.result(), 30)
+ model.do()
+ Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_6r-SketchLine_7r-SketchLine_8r-SketchLine_9r-SketchCircle_2_2r-SketchArc_2_2r-SketchLine_13r-SketchLine_14f-SketchLine_15f-SketchArc_3_2r-SketchLine_16r")], model.selection(), -165, 155)
+ Boolean_1 = model.addFuse(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1")], [model.selection("SOLID", "Extrusion_2_1")])
+ Sketch_3 = model.addSketch(Part_1_doc, model.selection("FACE", "Boolean_1_1/Modified_8"))
+ SketchLine_17 = Sketch_3.addLine(145, 0, 165, 0)
+ SketchPoint_2 = Sketch_3.addPoint(model.selection("VERTEX", "Boolean_1_1/Modified_7&Boolean_1_1/Modified_6&Boolean_1_1/Modified_2"))
+ SketchConstraintCoincidence_23 = Sketch_3.setCoincident(SketchLine_17.endPoint(), SketchPoint_2.result())
+ SketchLine_18 = Sketch_3.addLine(165, 0, 165, -20)
+ SketchLine_19 = Sketch_3.addLine(165, -20, 145, -20)
+ SketchLine_20 = Sketch_3.addLine(145, -20, 145, 0)
+ SketchConstraintCoincidence_24 = Sketch_3.setCoincident(SketchLine_20.endPoint(), SketchLine_17.startPoint())
+ SketchConstraintCoincidence_25 = Sketch_3.setCoincident(SketchLine_17.endPoint(), SketchLine_18.startPoint())
+ SketchConstraintCoincidence_26 = Sketch_3.setCoincident(SketchLine_18.endPoint(), SketchLine_19.startPoint())
+ SketchConstraintCoincidence_27 = Sketch_3.setCoincident(SketchLine_19.endPoint(), SketchLine_20.startPoint())
+ SketchConstraintHorizontal_4 = Sketch_3.setHorizontal(SketchLine_17.result())
+ SketchConstraintVertical_4 = Sketch_3.setVertical(SketchLine_18.result())
+ SketchConstraintHorizontal_5 = Sketch_3.setHorizontal(SketchLine_19.result())
+ SketchConstraintVertical_5 = Sketch_3.setVertical(SketchLine_20.result())
+ SketchArc_4 = Sketch_3.addArc(145, -20, 165, -20, 145, 0, False)
+ SketchConstraintCoincidence_28 = Sketch_3.setCoincident(SketchLine_19.endPoint(), SketchArc_4.center())
+ SketchConstraintCoincidence_29 = Sketch_3.setCoincident(SketchLine_18.endPoint(), SketchArc_4.startPoint())
+ SketchConstraintCoincidence_30 = Sketch_3.setCoincident(SketchArc_4.endPoint(), SketchLine_20.endPoint())
+ SketchConstraintRadius_3 = Sketch_3.setRadius(SketchArc_4.results()[1], 20)
+ SketchArc_5 = Sketch_3.addArc(145, -20, 155, -20, 145, -10, False)
+ SketchConstraintCoincidence_31 = Sketch_3.setCoincident(SketchLine_19.endPoint(), SketchArc_5.center())
+ SketchConstraintCoincidence_32 = Sketch_3.setCoincident(SketchLine_20.result(), SketchArc_5.endPoint())
+ SketchConstraintCoincidence_33 = Sketch_3.setCoincident(SketchArc_5.startPoint(), SketchLine_19.result())
+ SketchLine_21 = Sketch_3.addLine(model.selection("EDGE", "Boolean_1_1/Modified_12&Boolean_1_1/Modified_11"))
+ SketchConstraintTangent_5 = Sketch_3.setTangent(SketchArc_5.results()[1], SketchLine_21.result())
+ model.do()
+ ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_3/Face-SketchLine_17r-SketchLine_18r-SketchArc_4_2r")], model.selection(), model.selection("FACE", "Boolean_1_1/Modified_5"), 0, model.selection(), 0, [model.selection("SOLID", "Boolean_1_1")])
+ ExtrusionFuse_1 = model.addExtrusionFuse(Part_1_doc, [model.selection("FACE", "Sketch_3/Face-SketchLine_19r-SketchLine_20r-SketchArc_4_2f-SketchArc_5_2r")], model.selection(), model.selection("FACE", "ExtrusionCut_1_1/Modfied_7"), 0, model.selection(), 0, [model.selection("SOLID", "ExtrusionCut_1_1")])
+ model.do()
+ model.end()
+ model.testNbResults(ExtrusionFuse_1, 1)
+ model.testNbSubShapes(ExtrusionFuse_1, GeomAPI_Shape.SOLID, [1])
+ model.testNbSubShapes(ExtrusionFuse_1, GeomAPI_Shape.FACE, [30])
+ model.testNbSubShapes(ExtrusionFuse_1, GeomAPI_Shape.EDGE, [140])
+ model.testNbSubShapes(ExtrusionFuse_1, GeomAPI_Shape.VERTEX, [280])
+ model.testResultsVolumes(ExtrusionFuse_1, [260653.824775497108930721879005432])
+ assert(model.checkPythonDump())
index d5b54374a8d3cf23466780e3e88683a88812ca6c,10673347829e1d5d7a97de5f17d4b3e3411fdb7a..6099d82b961f75f72c40d3e5913cadca79189fab
@@@ -26,9 -7,10 +26,10 @@@ email : webmaster.salome@opencascade.co
          id="Sketch"
          nested="SketchPoint SketchIntersectionPoint SketchLine
                  SketchCircle SketchMacroCircle SketchArc SketchMacroArc
 -                SketchEllipse SketchMacroEllipse
++<!--                SketchEllipse SketchMacroEllipse-->
                  SketchRectangle
                  SketchProjection
-                 SketchConstraintLength SketchConstraintRadius SketchConstraintDistance
+                 SketchConstraintLength SketchConstraintRadius SketchConstraintDistance SketchConstraintDistanceHorizontal SketchConstraintDistanceVertical
                  SketchConstraintParallel SketchConstraintPerpendicular
                  SketchConstraintRigid SketchConstraintHorizontal SketchConstraintVertical
                  SketchConstraintEqual SketchConstraintTangent
        </feature>
      </group>
  
++<!--
+     <group id="Elliptic geometry">
+       <!-- SketchEllipse is a hidden feature. It is created inside SketchMacroEllipse. -->
+       <feature id="SketchEllipse"
+                title="Ellipse"
+                tooltip="Create ellipse"
+                icon="icons/Sketch/ellipse.png"
+                internal="1">
+         <sketch-2dpoint_selector id="ellipse_center"
+                                  title="Center"
+                                  tooltip="Center coordinates"
+                                  accept_expressions="0"
+                                  enable_value="enable_by_preferences"/>
+         <sketch-2dpoint_selector id="ellipse_focus"
+                                  title="Focus"
+                                  tooltip="Focus coordinates"
+                                  accept_expressions="0"
+                                  enable_value="enable_by_preferences"/>
+         <labelvalue id="ellipse_major_radius"
+                     icon="icons/Sketch/radius.png"
+                     label="Major radius:"
+                     tooltip="Set major radius"
+                     default="computed"
+                     accept_expressions="0"
+                     enable_value="enable_by_preferences">
+         </labelvalue>
+         <labelvalue id="ellipse_minor_radius"
+                     icon="icons/Sketch/radius.png"
+                     label="Minor radius:"
+                     tooltip="Set minor radius"
+                     default="computed"
+                     accept_expressions="0"
+                     enable_value="enable_by_preferences">
+         </labelvalue>
+         <boolvalue id="Auxiliary" label="Auxiliary" default="false" tooltip="Construction element" obligatory="0"/>
+       </feature>
+       <!-- SketchMacroEllipse -->
+       <feature id="SketchMacroEllipse"
+                icon="icons/Sketch/ellipse.png"
+                title="Ellipse"
+                tooltip="Create ellipse">
+         <sketch-2dpoint_selector id="center_point"
+                                  reference_attribute="center_point_ref"
+                                  title="Center point"
+                                  tooltip="Center point coordinates"
+                                  accept_expressions="0"
+                                  enable_value="enable_by_preferences"/>
+         <sketch-2dpoint_selector id="major_axis_point"
+                                  reference_attribute="major_axis_point_ref"
+                                  title="Major axis point"
+                                  tooltip="Major axis point coordinates"
+                                  accept_expressions="0"
+                                  enable_value="enable_by_preferences"/>
+         <sketch-2dpoint_selector id="passed_point"
+                                  reference_attribute="passed_point_ref"
+                                  title="Passed point"
+                                  tooltip="Passed point coordinates"
+                                  accept_expressions="0"
+                                  enable_value="enable_by_preferences">
+ <!--          <validator id="SketchPlugin_CirclePassedPointValidator"/> -->
+         </sketch-2dpoint_selector>
+ <!--        <validator id="GeomValidators_Different" parameters="center_point_ref,passed_point_ref"/> -->
+         <labelvalue id="ellipse_major_radius"
+                     icon="icons/Sketch/radius.png"
+                     label="Major radius:"
+                     tooltip="Set major radius"
+                     default="computed"
+                     accept_expressions="0"
+                     obligatory="0"
+                     enable_value="enable_by_preferences">
+           <validator id="GeomValidators_Positive"/>
+         </labelvalue>
+         <labelvalue id="ellipse_minor_radius"
+                     icon="icons/Sketch/radius.png"
+                     label="Minor radius:"
+                     tooltip="Set minor radius"
+                     default="computed"
+                     accept_expressions="0"
+                     obligatory="0"
+                     enable_value="enable_by_preferences">
+           <validator id="GeomValidators_Positive"/>
+         </labelvalue>
+         <boolvalue id="Auxiliary"
+                    tooltip="Construction element"
+                    label="Auxiliary"
+                    default="false"
+                    obligatory="0"/>
+       </feature>
+     </group>
++-->
      <group id="Projection">
        <!-- Intersection Point -->
        <!-- feature
Simple merge
index 0000000000000000000000000000000000000000,bec111b871975cab56dc2e8f0aac9890400d1117..94c6d7af10066fa33f4489933acae9427abbdb76
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,201 +1,219 @@@
 -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
++// Copyright (C) 2017  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<mailto:webmaster.salome@opencascade.com>
++//
+ #include <SketchSolver_ConstraintMovement.h>
+ #include <SketchSolver_Error.h>
+ #include <SketchSolver_Manager.h>
+ #include <PlaneGCSSolver_EdgeWrapper.h>
+ #include <PlaneGCSSolver_PointWrapper.h>
+ #include <SketchPlugin_Arc.h>
+ #include <SketchPlugin_Circle.h>
+ #include <SketchPlugin_Line.h>
+ #include <SketchPlugin_Point.h>
+ #include <GeomDataAPI_Point2D.h>
+ #include <GeomAPI_Pnt2d.h>
+ SketchSolver_ConstraintMovement::SketchSolver_ConstraintMovement(FeaturePtr theFeature)
+   : SketchSolver_ConstraintFixed(ConstraintPtr()),
+     myMovedFeature(theFeature),
+     mySimpleMove(true)
+ {
+ }
+ SketchSolver_ConstraintMovement::SketchSolver_ConstraintMovement(AttributePtr thePoint)
+   : SketchSolver_ConstraintFixed(ConstraintPtr()),
+     myDraggedPoint(thePoint),
+     mySimpleMove(true)
+ {
+   myMovedFeature = ModelAPI_Feature::feature(thePoint->owner());
+ }
+ void SketchSolver_ConstraintMovement::blockEvents(bool isBlocked)
+ {
+   if (myMovedFeature)
+     myMovedFeature->data()->blockSendAttributeUpdated(isBlocked);
+ }
+ void SketchSolver_ConstraintMovement::process()
+ {
+   cleanErrorMsg();
+   if (!myMovedFeature || !myStorage) {
+     // Not enough parameters are initialized
+     return;
+   }
+   mySolverConstraint = initMovement();
+   if (!myErrorMsg.empty() || !mySolverConstraint) {
+     // Nothing to move, clear the feature to avoid changing its group
+     // after removing the Movement constraint.
+     myMovedFeature = FeaturePtr();
+     return;
+   }
+   myStorage->addMovementConstraint(mySolverConstraint);
+ }
+ static bool isSimpleMove(FeaturePtr theMovedFeature, AttributePtr theDraggedPoint)
+ {
+   bool isSimple = true;
+   if (theMovedFeature->getKind() == SketchPlugin_Circle::ID())
+     isSimple = (theDraggedPoint.get() != 0);
+   else if (theMovedFeature->getKind() == SketchPlugin_Arc::ID()) {
+     isSimple = (theDraggedPoint.get() != 0 &&
+                 theDraggedPoint->id() == SketchPlugin_Arc::CENTER_ID());
+   }
+   return isSimple;
+ }
+ ConstraintWrapperPtr SketchSolver_ConstraintMovement::initMovement()
+ {
+   ConstraintWrapperPtr aConstraint;
+   // if the feature is copy, do not move it
+   std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
+       std::dynamic_pointer_cast<SketchPlugin_Feature>(myMovedFeature);
+   if (!aSketchFeature || aSketchFeature->isCopy()) {
+     myStorage->setNeedToResolve(true);
+     return aConstraint;
+   }
+   EntityWrapperPtr anEntity =
+       myDraggedPoint ? myStorage->entity(myDraggedPoint) : myStorage->entity(myMovedFeature);
+   if (!anEntity) {
+     myStorage->update(myMovedFeature, true);
+     anEntity =
+         myDraggedPoint ? myStorage->entity(myDraggedPoint) : myStorage->entity(myMovedFeature);
+     if (!anEntity)
+       return aConstraint;
+   }
+   mySimpleMove = isSimpleMove(myMovedFeature, myDraggedPoint);
+   if (mySimpleMove)
+     aConstraint = fixFeature(anEntity);
+   else {
+     if (myDraggedPoint) // start or end point of arc has been moved
+       aConstraint = fixArcExtremity(anEntity);
+     else // arc or circle has been moved
+       aConstraint = fixPointOnCircle(anEntity);
+   }
+   return aConstraint;
+ }
+ ConstraintWrapperPtr SketchSolver_ConstraintMovement::fixArcExtremity(
+     const EntityWrapperPtr& theArcExtremity)
+ {
+   static const int nbParams = 4;
+   myFixedValues.reserve(nbParams); // moved point and center of arc
+   EdgeWrapperPtr aCircularEntity = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(
+       myStorage->entity(myMovedFeature));
+   std::shared_ptr<GCS::Arc> anArc =
+       std::dynamic_pointer_cast<GCS::Arc>(aCircularEntity->entity());
+   PointWrapperPtr aPoint =
+       std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theArcExtremity);
+   double* aParams[nbParams] = { aPoint->point()->x, aPoint->point()->y,
+                                 anArc->center.x, anArc->center.y };
+   std::list<GCSConstraintPtr> aConstraints;
+   for (int i = 0; i < nbParams; ++i) {
+     myFixedValues.push_back(*aParams[i]);
+     GCSConstraintPtr aNewConstraint(new GCS::ConstraintEqual(&myFixedValues[i], aParams[i]));
+     aNewConstraint->rescale(0.01);
+     aConstraints.push_back(aNewConstraint);
+   }
+   return ConstraintWrapperPtr(
+       new PlaneGCSSolver_ConstraintWrapper(aConstraints, getType()));
+ }
+ ConstraintWrapperPtr SketchSolver_ConstraintMovement::fixPointOnCircle(
+     const EntityWrapperPtr& theCircular)
+ {
+   static const double scale = 0.01;
+   static const int nbParams = 4;
+   myFixedValues.reserve(nbParams); // moved point and center of arc/circle
+   EdgeWrapperPtr aCircularEntity =
+       std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theCircular);
+   std::shared_ptr<GCS::Circle> aCircular =
+       std::dynamic_pointer_cast<GCS::Circle>(aCircularEntity->entity());
+   // initialize fixed values
+   myFixedValues.push_back(*aCircular->center.x + *aCircular->rad);
+   myFixedValues.push_back(*aCircular->center.y);
+   myFixedValues.push_back(*aCircular->center.x);
+   myFixedValues.push_back(*aCircular->center.y);
+   // create a moved point
+   GCS::Point aPointOnCircle;
+   aPointOnCircle.x = &myFixedValues[0];
+   aPointOnCircle.y = &myFixedValues[1];
+   std::list<GCSConstraintPtr> aConstraints;
+   // point-on-circle
+   GCSConstraintPtr aNewConstraint(
+       new GCS::ConstraintP2PDistance(aPointOnCircle, aCircular->center, aCircular->rad));
+   aNewConstraint->rescale(scale);
+   aConstraints.push_back(aNewConstraint);
+   // fixed center (x)
+   aNewConstraint = GCSConstraintPtr(
+       new GCS::ConstraintEqual(&myFixedValues[2], aCircular->center.x));
+   aNewConstraint->rescale(scale);
+   aConstraints.push_back(aNewConstraint);
+   // fixed center (y)
+   aNewConstraint = GCSConstraintPtr(
+       new GCS::ConstraintEqual(&myFixedValues[3], aCircular->center.y));
+   aNewConstraint->rescale(scale);
+   aConstraints.push_back(aNewConstraint);
+   return ConstraintWrapperPtr(
+       new PlaneGCSSolver_ConstraintWrapper(aConstraints, getType()));
+ }
+ void SketchSolver_ConstraintMovement::startPoint(
+     const std::shared_ptr<GeomAPI_Pnt2d>& theStartPoint)
+ {
+   myStartPoint = theStartPoint;
+   if (!mySimpleMove) {
+     myFixedValues[0] = myStartPoint->x();
+     myFixedValues[1] = myStartPoint->y();
+   }
+ }
+ void SketchSolver_ConstraintMovement::moveTo(
+     const std::shared_ptr<GeomAPI_Pnt2d>& theDestinationPoint)
+ {
+   double aDelta[2] = { theDestinationPoint->x() - myStartPoint->x(),
+                        theDestinationPoint->y() - myStartPoint->y() };
+   int aMaxSize = mySimpleMove ? (int)myFixedValues.size() : 2;
+   for (int i = 0; i < aMaxSize; ++i)
+     myFixedValues[i] += aDelta[i % 2];
+ }
index 0000000000000000000000000000000000000000,f25bbb0afff880325d2e95e1a5b29a7bc08fafa6..8614f309ac064177045d915bad8d86d234c199fb
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,63 +1,81 @@@
 -// Copyright (C) 2015-20xx CEA/DEN, EDF R&D
++// Copyright (C) 2017  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<mailto:webmaster.salome@opencascade.com>
++//
+ // File:    SketchSolver_ConstraintMovement.h
+ // Created: 15 Jun 2015
+ // Author:  Artem ZHIDKOV
+ #ifndef SketchSolver_ConstraintMovement_H_
+ #define SketchSolver_ConstraintMovement_H_
+ #include <SketchSolver_ConstraintFixed.h>
+ class GeomAPI_Pnt2d;
+ /** \class   SketchSolver_ConstraintMovement
+  *  \ingroup Plugins
+  *  \brief   Stores data to the Fixed constraint for the moved feature only
+  */
+ class SketchSolver_ConstraintMovement : public SketchSolver_ConstraintFixed
+ {
+ public:
+   /// Creates movement constraint based on feature
+   SketchSolver_ConstraintMovement(FeaturePtr theFeature);
+   /// Creates movement constraint based on point
+   SketchSolver_ConstraintMovement(AttributePtr thePoint);
+   /// \brief Set coordinates of the start point of the movement
+   void startPoint(const std::shared_ptr<GeomAPI_Pnt2d>& theStartPoint);
+   /// \brief Set coordinates of fixed feature to the values where it has been dragged.
+   ///        Useful when the feature is being moved.
+   void moveTo(const std::shared_ptr<GeomAPI_Pnt2d>& theDestinationPoint);
+   /// \brief Block or unblock events from this constraint
+   virtual void blockEvents(bool isBlocked);
+   /// \brief Returns moved feature
+   FeaturePtr movedFeature() const
+   { return myMovedFeature; }
+ protected:
+   /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
+   virtual void process();
+   /// \brief Create Fixed constraint for the feature basing on its type and moved point
+   /// \return Fixed constraint
+   ConstraintWrapperPtr initMovement();
+   /// \brief Create constraint to fix moved arc extremity
+   ConstraintWrapperPtr fixArcExtremity(const EntityWrapperPtr& theArcExtremity);
+   /// \brief Creat constraint to fix moved point on circle/arc
+   ConstraintWrapperPtr fixPointOnCircle(const EntityWrapperPtr& theCircular);
+ private:
+   FeaturePtr       myMovedFeature; ///< fixed feature (if set, myBaseConstraint should be NULL)
+   AttributePtr     myDraggedPoint; ///< one of the feature points which has been moved
+   std::shared_ptr<GeomAPI_Pnt2d> myStartPoint; ///< start point of the movement
+   bool mySimpleMove; ///< simple move, thus all parameters should be increased by movement delta
+ };
+ #endif
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge