]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Task 2.4. Ability to modify the radius of circles and arcs of circle with the mouse Pre_2.8.0_development
authorazv <azv@opencascade.com>
Fri, 12 May 2017 12:52:14 +0000 (15:52 +0300)
committerazv <azv@opencascade.com>
Fri, 12 May 2017 12:52:14 +0000 (15:52 +0300)
Unit test for the new movement feature

src/PythonAPI/model/sketcher/tests.py
src/PythonAPI/model/sketcher/tools.py
src/SketchAPI/SketchAPI_Sketch.cpp
src/SketchAPI/SketchAPI_Sketch.h
src/SketchPlugin/CMakeLists.txt
src/SketchPlugin/Test/TestMoveArc.py [new file with mode: 0644]
src/SketchPlugin/Test/TestMoveCircle.py [new file with mode: 0644]
src/SketchPlugin/Test/TestMoveLine.py [new file with mode: 0644]
src/SketchPlugin/Test/TestMovePoint.py [new file with mode: 0644]
src/SketchPlugin/Test/TestMovementComplex.py [new file with mode: 0644]

index d59a5e21d83c2fd1035e1f018a1d9bcb0604349b..18984008cbba8833d06045b3bb6df72736db056b 100644 (file)
@@ -12,8 +12,8 @@ TOLERANCE = 1.e-7
 def assertPoint(thePoint, theCoords):
     """ Verifies coordinates of the point
     """
-    aPoint = tools.toPoint(thePoint)
-    assert aPoint.x() == theCoords[0] and aPoint.y() == theCoords[1], "Wrong '{}' point ({}, {}), expected ({}, {})".format(thePoint.id(), aPoint.x(), aPoint.y(), theCoords[0], theCoords[1])
+    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):
@@ -73,4 +73,4 @@ def assertArcValidity(theArc):
     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 {0}, expected {1}".format(aRadius.value(), aDistCS)
+    assert math.fabs(aRadius.value() - aDistCS) < TOLERANCE, "Wrong arc: radius is {}, expected {}".format(aRadius.value(), aDistCS)
index 57936dd8520d57f58d1f35f0a82c5c87a2f662ee..49a73bfbdeaac0b8183824abac7f1590db18aed7 100644 (file)
@@ -3,6 +3,7 @@
 
 import ModelHighAPI
 from GeomDataAPI import *
+from ModelAPI import *
 import math
 
 def addPolyline(sketch, *coords):
@@ -53,27 +54,28 @@ def dof(sketch):
     return int(filter(str.isdigit, aSketch.string("SolverDOF").value()))
 
 def distancePointPoint(thePoint1, thePoint2):
-    aGeomPnt1 = toPoint(thePoint1)
-    aGeomPnt2 = toPoint(thePoint2)
-    return aGeomPnt1.distance(aGeomPnt2)
+    aPnt1 = toList(thePoint1)
+    aPnt2 = toList(thePoint2)
+    return math.hypot(aPnt1[0] - aPnt2[0], aPnt1[1] - aPnt2[1])
 
 def distancePointLine(thePoint, theLine):
-    aPoint = toPoint(thePoint)
+    aPoint = toList(thePoint)
     aLine = toSketchFeature(theLine)
 
     aLineStart = geomDataAPI_Point2D(aLine.attribute("StartPoint")).pnt().xy()
     aLineEnd = geomDataAPI_Point2D(aLine.attribute("EndPoint")).pnt().xy()
     aLineDir = aLineEnd.decreased(aLineStart)
     aLineLen = aLineEnd.distance(aLineStart)
-    aPntDir = aPoint.xy().decreased(aLineStart)
-    return math.fabs(aPntDir.cross(aLineDir) / aLineLen)
+    aCross = (aPoint[0] - aLineStart.x()) * aLineDir.y() - (aPoint[1] - aLineStart.y()) * aLineDir.x()
+    return math.fabs(aCross / aLineLen)
 
 def lastSubFeature(theSketch, theKind):
     """
     obtains last feature of given kind from the sketch
     """
-    for anIndex in range(theSketch.numberOfSubs() - 1, -1, -1):
-        aSub = theSketch.subFeature(anIndex)
+    aSketch = featureToCompositeFeature(toSketchFeature(theSketch))
+    for anIndex in range(aSketch.numberOfSubs() - 1, -1, -1):
+        aSub = aSketch.subFeature(anIndex)
         if (aSub.getKind() == theKind):
             return aSub
 
@@ -85,9 +87,12 @@ def toSketchFeature(theEntity):
     else:
         return theEntity
 
-def toPoint(thePoint):
-    if issubclass(type(thePoint), GeomDataAPI_Point2D):
-        return thePoint.pnt()
+def toList(thePoint):
+    if issubclass(type(thePoint), list):
+        return thePoint
+    elif issubclass(type(thePoint), GeomDataAPI_Point2D):
+        return [thePoint.x(), thePoint.y()]
     else:
-        aPoint = toSketchFeature(thePoint)
-        return geomDataAPI_Point2D(aPoint.attribute("PointCoordinates")).pnt()
+        aFeature = toSketchFeature(thePoint)
+        aPoint = geomDataAPI_Point2D(aFeature.attribute("PointCoordinates"))
+        return [aPoint.x(), aPoint.y()]
index 57704a14647999ee7998473b1a84e24daf653dc1..2af8499870ea1142e74d4fd4b7429b30e6190f56 100644 (file)
@@ -31,6 +31,7 @@
 #include <SketchPlugin_ConstraintVertical.h>
 #include <SketcherPrs_Tools.h>
 //--------------------------------------------------------------------------------------
+#include <ModelAPI_Events.h>
 #include <ModelAPI_CompositeFeature.h>
 #include <ModelAPI_ResultConstruction.h>
 #include <ModelHighAPI_Double.h>
 #include "SketchAPI_Rotation.h"
 #include "SketchAPI_Translation.h"
 //--------------------------------------------------------------------------------------
+#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_XY.h>
+#include <cmath>
+//--------------------------------------------------------------------------------------
 SketchAPI_Sketch::SketchAPI_Sketch(
     const std::shared_ptr<ModelAPI_Feature> & theFeature)
 : ModelHighAPI_Interface(theFeature)
@@ -790,6 +795,127 @@ std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setVertical(
 
 //--------------------------------------------------------------------------------------
 
+static std::shared_ptr<GeomAPI_Pnt2d> pointCoordinates(const AttributePtr& thePoint)
+{
+  AttributePoint2DPtr aPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(thePoint);
+  if (aPnt)
+    return aPnt->pnt();
+  return std::shared_ptr<GeomAPI_Pnt2d>();
+}
+
+static std::shared_ptr<GeomAPI_Pnt2d> middlePointOnLine(const FeaturePtr& theFeature)
+{
+  AttributePoint2DPtr aStartAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+      theFeature->attribute(SketchPlugin_Line::START_ID()));
+  AttributePoint2DPtr aEndAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+      theFeature->attribute(SketchPlugin_Line::END_ID()));
+
+  if (!aStartAttr || !aEndAttr)
+    return std::shared_ptr<GeomAPI_Pnt2d>();
+
+  std::shared_ptr<GeomAPI_XY> aStartPoint = aStartAttr->pnt()->xy();
+  std::shared_ptr<GeomAPI_XY> aEndPoint = aEndAttr->pnt()->xy();
+  return std::shared_ptr<GeomAPI_Pnt2d>(
+      new GeomAPI_Pnt2d(aStartPoint->added(aEndPoint)->multiplied(0.5)));
+}
+
+static std::shared_ptr<GeomAPI_Pnt2d> pointOnCircle(const FeaturePtr& theFeature)
+{
+  AttributePoint2DPtr aCenter = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+      theFeature->attribute(SketchPlugin_Circle::CENTER_ID()));
+  AttributeDoublePtr aRadius = theFeature->real(SketchPlugin_Circle::RADIUS_ID());
+
+  if (!aCenter || !aRadius)
+    return std::shared_ptr<GeomAPI_Pnt2d>();
+
+  return std::shared_ptr<GeomAPI_Pnt2d>(
+      new GeomAPI_Pnt2d(aCenter->x() + aRadius->value(), aCenter->y()));
+}
+
+static std::shared_ptr<GeomAPI_Pnt2d> middlePointOnArc(const FeaturePtr& theFeature)
+{
+  static const double PI = 3.141592653589793238463;
+
+  AttributePoint2DPtr aCenterAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+      theFeature->attribute(SketchPlugin_Arc::CENTER_ID()));
+  AttributePoint2DPtr aStartAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+      theFeature->attribute(SketchPlugin_Arc::START_ID()));
+  AttributePoint2DPtr aEndAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+      theFeature->attribute(SketchPlugin_Arc::END_ID()));
+
+  if (!aCenterAttr || !aStartAttr || !aEndAttr)
+    return std::shared_ptr<GeomAPI_Pnt2d>();
+
+  std::shared_ptr<GeomAPI_Dir2d> aStartDir(new GeomAPI_Dir2d(
+      aStartAttr->x() - aCenterAttr->x(), aStartAttr->y() - aCenterAttr->y()));
+  std::shared_ptr<GeomAPI_Dir2d> aEndDir(new GeomAPI_Dir2d(
+      aEndAttr->x() - aCenterAttr->x(), aEndAttr->y() - aCenterAttr->y()));
+
+  double anAngle = aStartDir->angle(aEndDir);
+  bool isReversed = theFeature->boolean(SketchPlugin_Arc::REVERSED_ID())->value();
+  if (isReversed && anAngle > 0.)
+    anAngle -= 2.0 * PI;
+  else if (!isReversed && anAngle <= 0.)
+    anAngle += 2.0 * PI;
+
+  double cosA = cos(anAngle);
+  double sinA = sin(anAngle);
+
+  // rotate start dir to find middle point on arc
+  double aRadius = aStartAttr->pnt()->distance(aCenterAttr->pnt());
+  double x = aCenterAttr->x() + aRadius * (aStartDir->x() * cosA - aStartDir->y() * sinA);
+  double y = aCenterAttr->y() + aRadius * (aStartDir->x() * sinA + aStartDir->y() * cosA);
+
+  return std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(x, y));
+}
+
+static std::shared_ptr<GeomAPI_Pnt2d> middlePoint(const ObjectPtr& theObject)
+{
+  FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
+  if (aFeature) {
+    const std::string& aFeatureKind = aFeature->getKind();
+    if (aFeatureKind == SketchPlugin_Point::ID())
+      return pointCoordinates(aFeature->attribute(SketchPlugin_Point::COORD_ID()));
+    else if (aFeatureKind == SketchPlugin_Line::ID())
+      return middlePointOnLine(aFeature);
+    else if (aFeatureKind == SketchPlugin_Circle::ID())
+      return pointOnCircle(aFeature);
+    else if (aFeatureKind == SketchPlugin_Arc::ID())
+      return middlePointOnArc(aFeature);
+  }
+  // do not move other types of features
+  return std::shared_ptr<GeomAPI_Pnt2d>();
+}
+
+void SketchAPI_Sketch::move(const ModelHighAPI_RefAttr& theMovedEntity,
+                            const std::shared_ptr<GeomAPI_Pnt2d>& theTargetPoint)
+{
+  std::shared_ptr<ModelAPI_ObjectMovedMessage> aMessage(new ModelAPI_ObjectMovedMessage);
+  theMovedEntity.fillMessage(aMessage);
+
+  std::shared_ptr<GeomAPI_Pnt2d> anOriginalPosition;
+  if (aMessage->movedAttribute())
+    anOriginalPosition = pointCoordinates(aMessage->movedAttribute());
+  else
+    anOriginalPosition = middlePoint(aMessage->movedObject());
+
+  if (!anOriginalPosition)
+    return; // something has gone wrong, do not process movement
+
+  aMessage->setOriginalPosition(anOriginalPosition);
+  aMessage->setCurrentPosition(theTargetPoint);
+  Events_Loop::loop()->send(aMessage);
+}
+
+void SketchAPI_Sketch::move(const ModelHighAPI_RefAttr& theMovedEntity,
+                            double theTargetX, double theTargetY)
+{
+  std::shared_ptr<GeomAPI_Pnt2d> aTargetPoint(new GeomAPI_Pnt2d(theTargetX, theTargetY));
+  move(theMovedEntity, aTargetPoint);
+}
+
+//--------------------------------------------------------------------------------------
+
 std::shared_ptr<GeomAPI_Pnt2d> SketchAPI_Sketch::to2D(const std::shared_ptr<GeomAPI_Pnt>& thePoint)
 {
   FeaturePtr aBase = feature();
index e7282dea2300a235616f2adf53518fbfb6f545b5..6f03285b498b2e8a115f0e2a431d11e1dc94f720 100644 (file)
@@ -409,6 +409,16 @@ public:
       const std::shared_ptr<ModelHighAPI_Interface> & theConstraint,
       const ModelHighAPI_Double & theValue);
 
+  /// Move point or sketch feature
+  SKETCHAPI_EXPORT
+  void move(const ModelHighAPI_RefAttr& theMovedEntity,
+            const std::shared_ptr<GeomAPI_Pnt2d>& theTargetPoint);
+
+  /// Move point or sketch feature
+  SKETCHAPI_EXPORT
+  void move(const ModelHighAPI_RefAttr& theMovedEntity,
+            double theTargetX, double theTargetY);
+
   SKETCHAPI_EXPORT
   std::shared_ptr<GeomAPI_Pnt2d> to2D(const std::shared_ptr<GeomAPI_Pnt>& thePoint);
 
index e1358181263709732c16191b89122e111d12ba84..6f4b3a09cfd9f987fc1b27460c18a69e7cc37807 100644 (file)
@@ -192,4 +192,10 @@ ADD_UNIT_TESTS(TestSketchPointLine.py
                TestTrimCircle05.py
                TestTrimCircleAndArc01.py
                TestTrimLine01.py
-               TestTrimLine02.py)
+               TestTrimLine02.py
+               TestMovePoint.py
+               TestMoveLine.py
+               TestMoveCircle.py
+               TestMoveArc.py
+               TestMovementComplex.py
+)
diff --git a/src/SketchPlugin/Test/TestMoveArc.py b/src/SketchPlugin/Test/TestMoveArc.py
new file mode 100644 (file)
index 0000000..10f4ec0
--- /dev/null
@@ -0,0 +1,329 @@
+"""
+    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()
diff --git a/src/SketchPlugin/Test/TestMoveCircle.py b/src/SketchPlugin/Test/TestMoveCircle.py
new file mode 100644 (file)
index 0000000..fdccca6
--- /dev/null
@@ -0,0 +1,129 @@
+"""
+    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()
diff --git a/src/SketchPlugin/Test/TestMoveLine.py b/src/SketchPlugin/Test/TestMoveLine.py
new file mode 100644 (file)
index 0000000..89c6f7f
--- /dev/null
@@ -0,0 +1,116 @@
+"""
+    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()
diff --git a/src/SketchPlugin/Test/TestMovePoint.py b/src/SketchPlugin/Test/TestMovePoint.py
new file mode 100644 (file)
index 0000000..88a143a
--- /dev/null
@@ -0,0 +1,88 @@
+"""
+    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()
diff --git a/src/SketchPlugin/Test/TestMovementComplex.py b/src/SketchPlugin/Test/TestMovementComplex.py
new file mode 100644 (file)
index 0000000..6b576fd
--- /dev/null
@@ -0,0 +1,364 @@
+"""
+    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())