Salome HOME
Task 2.12. New entities: ellipses and arcs of ellipses (issue #3003)
authorazv <azv@opencascade.com>
Thu, 19 Sep 2019 08:53:30 +0000 (11:53 +0300)
committerazv <azv@opencascade.com>
Sun, 22 Sep 2019 13:14:08 +0000 (16:14 +0300)
Unit tests for constraints Angle, Coincidence, Collinear and Distance applied to ellipse.

src/ModelHighAPI/ModelHighAPI_Dumper.cpp
src/SketchAPI/SketchAPI_MacroEllipse.cpp
src/SketchAPI/SketchAPI_MacroEllipse.h
src/SketchPlugin/CMakeLists.txt
src/SketchPlugin/Test/TestConstraintAngleEllipse.py [new file with mode: 0644]
src/SketchPlugin/Test/TestConstraintCoincidenceEllipse.py [new file with mode: 0644]
src/SketchPlugin/Test/TestConstraintCollinearEllipse.py [new file with mode: 0644]
src/SketchPlugin/Test/TestConstraintDistanceEllipse.py [new file with mode: 0644]

index c8e37dc1c6598fbffb86604342bdce884a57119d..836f33c93016d29eb194e2f6e91a8e379842d9a6 100644 (file)
@@ -1227,7 +1227,8 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const AttributePtr& theAttr
   // Check the attribute belongs to copied (in multi-translation or multi-rotation) feature.
   // In this case we need to cast explicitly feature to appropriate type.
   AttributeBooleanPtr isCopy = anOwner->boolean("Copy");
-  if (isCopy.get() && isCopy->value()) {
+  AttributeReferencePtr hasParent = anOwner->reference("ParentFeature");
+  if ((isCopy.get() && isCopy->value()) || (hasParent && hasParent->value())) {
     aWrapperPrefix = featureWrapper(anOwner) + "(";
     aWrapperSuffix = ")";
     importModule("SketchAPI");
index ded0f75ba05b1014cfb03c0377fb69eccbbad5f2..c3ed48080d6f9d365379ccf597a359d7fc3aae32 100644 (file)
 //
 
 #include "SketchAPI_MacroEllipse.h"
+#include "SketchAPI_Line.h"
+#include "SketchAPI_Point.h"
 
 #include <GeomAPI_Pnt2d.h>
 
 #include <ModelHighAPI_RefAttr.h>
 #include <ModelHighAPI_Tools.h>
 
+#include <SketchPlugin_Sketch.h>
+
+#define MAJOR_AXIS_NEGATIVE (std::dynamic_pointer_cast<GeomDataAPI_Point2D>( \
+                             feature()->attribute(SketchPlugin_MacroEllipse::FIRST_POINT_ID())))
+#define MAJOR_AXIS_POSITIVE (std::dynamic_pointer_cast<GeomDataAPI_Point2D>( \
+                             feature()->attribute(SketchPlugin_MacroEllipse::SECOND_POINT_ID())))
+#define PASSED_POINT (std::dynamic_pointer_cast<GeomDataAPI_Point2D>( \
+                      feature()->attribute(SketchPlugin_MacroEllipse::PASSED_POINT_ID())))
+
+#define MAJOR_AXIS_NEGATIVE_REF (feature()->refattr( \
+                                 SketchPlugin_MacroEllipse::FIRST_POINT_REF_ID()))
+#define MAJOR_AXIS_POSITIVE_REF (feature()->refattr( \
+                                 SketchPlugin_MacroEllipse::SECOND_POINT_REF_ID()))
+#define PASSED_POINT_REF (feature()->refattr(SketchPlugin_MacroEllipse::PASSED_POINT_REF_ID()))
+
+
+// find a parent sketch
+static CompositeFeaturePtr sketch(FeaturePtr theFeature)
+{
+  CompositeFeaturePtr aSketch;
+  const std::set<AttributePtr>& aRefs = theFeature->data()->refsToMe();
+  for (std::set<AttributePtr>::const_iterator anIt = aRefs.begin(); anIt != aRefs.end(); ++anIt)
+    if ((*anIt)->id() == SketchPlugin_Sketch::FEATURES_ID()) {
+      aSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>((*anIt)->owner());
+      break;
+    }
+  return aSketch;
+}
+
+
 SketchAPI_MacroEllipse::SketchAPI_MacroEllipse(const std::shared_ptr<ModelAPI_Feature>& theFeature)
 : SketchAPI_SketchEntity(theFeature)
 {
@@ -102,10 +134,11 @@ void SketchAPI_MacroEllipse::initializePoints(double theX1, double theY1,
                                               double theX2, double theY2,
                                               double theX3, double theY3)
 {
-  fillAttribute(majorAxisNegativePoint(), theX1, theY1);
-  fillAttribute(majorAxisPositivePoint(), theX2, theY2);
-  fillAttribute(passedPoint(), theX3, theY3);
+  fillAttribute(MAJOR_AXIS_NEGATIVE, theX1, theY1);
+  fillAttribute(MAJOR_AXIS_POSITIVE, theX2, theY2);
+  fillAttribute(PASSED_POINT, theX3, theY3);
 
+  mySketch = sketch(feature());
   execute();
 }
 
@@ -113,10 +146,11 @@ void SketchAPI_MacroEllipse::initializePoints(const std::shared_ptr<GeomAPI_Pnt2
                                               const std::shared_ptr<GeomAPI_Pnt2d>& thePoint2,
                                               const std::shared_ptr<GeomAPI_Pnt2d>& thePoint3)
 {
-  fillAttribute(thePoint1, mymajorAxisNegativePoint);
-  fillAttribute(thePoint2, mymajorAxisPositivePoint);
-  fillAttribute(thePoint3, mypassedPoint);
+  fillAttribute(thePoint1, MAJOR_AXIS_NEGATIVE);
+  fillAttribute(thePoint2, MAJOR_AXIS_POSITIVE);
+  fillAttribute(thePoint3, PASSED_POINT);
 
+  mySketch = sketch(feature());
   execute();
 }
 
@@ -145,10 +179,94 @@ void SketchAPI_MacroEllipse::initializePoints(
     const ModelHighAPI_RefAttr&           thePassedPointRef)
 {
   fillAttribute(theMajorAxisPoint1, theMajorAxisPoint1Ref,
-                mymajorAxisNegativePoint, mymajorAxisNegativePointRef);
+                MAJOR_AXIS_NEGATIVE, MAJOR_AXIS_NEGATIVE_REF);
   fillAttribute(theMajorAxisPoint2, theMajorAxisPoint2Ref,
-                mymajorAxisPositivePoint, mymajorAxisPositivePointRef);
-  fillAttribute(thePassedPoint, thePassedPointRef, mypassedPoint, mypassedPointRef);
+                MAJOR_AXIS_POSITIVE, MAJOR_AXIS_POSITIVE_REF);
+  fillAttribute(thePassedPoint, thePassedPointRef,
+                PASSED_POINT, PASSED_POINT_REF);
 
+  mySketch = sketch(feature());
   execute();
 }
+
+std::shared_ptr<SketchAPI_Point> SketchAPI_MacroEllipse::center()
+{
+  if (!myCenter)
+    collectAuxiliary();
+  return myCenter;
+}
+
+std::shared_ptr<SketchAPI_Point> SketchAPI_MacroEllipse::focus1()
+{
+  if (!myFocus1)
+    collectAuxiliary();
+  return myFocus1;
+}
+
+std::shared_ptr<SketchAPI_Point> SketchAPI_MacroEllipse::focus2()
+{
+  if (!myFocus2)
+    collectAuxiliary();
+  return myFocus2;
+}
+
+std::shared_ptr<SketchAPI_Point> SketchAPI_MacroEllipse::majorAxisStart()
+{
+  if (!myMajorAxisStart)
+    collectAuxiliary();
+  return myMajorAxisStart;
+}
+
+std::shared_ptr<SketchAPI_Point> SketchAPI_MacroEllipse::majorAxisEnd()
+{
+  if (!myMajorAxisEnd)
+    collectAuxiliary();
+  return myMajorAxisEnd;
+}
+
+std::shared_ptr<SketchAPI_Point> SketchAPI_MacroEllipse::minorAxisStart()
+{
+  if (!myMinorAxisStart)
+    collectAuxiliary();
+  return myMinorAxisStart;
+}
+
+std::shared_ptr<SketchAPI_Point> SketchAPI_MacroEllipse::minorAxisEnd()
+{
+  if (!myMinorAxisEnd)
+    collectAuxiliary();
+  return myMinorAxisEnd;
+}
+
+std::shared_ptr<SketchAPI_Line> SketchAPI_MacroEllipse::majorAxis()
+{
+  if (!myMajorAxis)
+    collectAuxiliary();
+  return myMajorAxis;
+}
+
+std::shared_ptr<SketchAPI_Line> SketchAPI_MacroEllipse::minorAxis()
+{
+  if (!myMinorAxis)
+    collectAuxiliary();
+  return myMinorAxis;
+}
+
+void SketchAPI_MacroEllipse::collectAuxiliary()
+{
+  // collect auxiliary features
+  int aNbSubs = mySketch->numberOfSubs();
+  std::shared_ptr<SketchAPI_Point>* anAuxPoint[] = {
+    &myCenter, &myFocus1, &myFocus2,
+    &myMajorAxisStart, &myMajorAxisEnd,
+    &myMinorAxisStart, &myMinorAxisEnd
+  };
+  std::shared_ptr<SketchAPI_Line>* anAuxLine[] = {&myMajorAxis, &myMinorAxis};
+  for (int aPtInd = 7, aLinInd = 2; (aPtInd > 0 || aLinInd > 0) && aNbSubs >= 0; ) {
+    FeaturePtr aCurFeature = mySketch->subFeature(--aNbSubs);
+    if (aPtInd > 0 && aCurFeature->getKind() == SketchPlugin_Point::ID())
+      anAuxPoint[--aPtInd]->reset(new SketchAPI_Point(aCurFeature));
+    else if (aLinInd > 0 && aCurFeature->getKind() == SketchPlugin_Line::ID())
+      anAuxLine[--aLinInd]->reset(new SketchAPI_Line(aCurFeature));
+  }
+}
index 6f74bbc98437ac6ff86cd002151ffa40c612e1d3..596a417e6801682a5479a8e84354f355541d62f8 100644 (file)
@@ -26,6 +26,8 @@
 #include <SketchPlugin_MacroEllipse.h>
 
 class ModelHighAPI_RefAttr;
+class SketchAPI_Point;
+class SketchAPI_Line;
 
 /// \class SketchAPI_MacroEllipse
 /// \ingroup CPPHighAPI
@@ -68,25 +70,28 @@ public:
   SKETCHAPI_EXPORT
   virtual ~SketchAPI_MacroEllipse();
 
-  INTERFACE_9(SketchPlugin_MacroEllipse::ID(),
+  INTERFACE_1(SketchPlugin_MacroEllipse::ID(),
               ellipseType, SketchPlugin_MacroEllipse::ELLIPSE_TYPE(),
-              ModelAPI_AttributeString, /** Ellipse type */,
-              centerPoint, SketchPlugin_MacroEllipse::FIRST_POINT_ID(),
-              GeomDataAPI_Point2D, /** Center point */,
-              centerPointRef, SketchPlugin_MacroEllipse::FIRST_POINT_REF_ID(),
-              ModelAPI_AttributeRefAttr, /** Reference to a center point */,
-              majorAxisNegativePoint, SketchPlugin_MacroEllipse::FIRST_POINT_ID(),
-              GeomDataAPI_Point2D, /** Major axis negative point point */,
-              majorAxisNegativePointRef, SketchPlugin_MacroEllipse::FIRST_POINT_REF_ID(),
-              ModelAPI_AttributeRefAttr, /** Reference to the negative point on a major axis */,
-              majorAxisPositivePoint, SketchPlugin_MacroEllipse::SECOND_POINT_ID(),
-              GeomDataAPI_Point2D, /** Major axis positive point point */,
-              majorAxisPositivePointRef, SketchPlugin_MacroEllipse::SECOND_POINT_REF_ID(),
-              ModelAPI_AttributeRefAttr, /** Reference to the positive point on a major axis */,
-              passedPoint, SketchPlugin_MacroEllipse::PASSED_POINT_ID(),
-              GeomDataAPI_Point2D, /** Passed point */,
-              passedPointRef, SketchPlugin_MacroEllipse::PASSED_POINT_REF_ID(),
-              ModelAPI_AttributeRefAttr, /** Reference to a passed point */)
+              ModelAPI_AttributeString, /** Ellipse type */)
+
+  /// Return created auxiliary center point
+  SKETCHAPI_EXPORT std::shared_ptr<SketchAPI_Point> center();
+  /// Return created auxiliary focus in the positive direction of major axis
+  SKETCHAPI_EXPORT std::shared_ptr<SketchAPI_Point> focus1();
+  /// Return created auxiliary focus in the negative direction of major axis
+  SKETCHAPI_EXPORT std::shared_ptr<SketchAPI_Point> focus2();
+  /// Return created auxiliary point - start of major axis
+  SKETCHAPI_EXPORT std::shared_ptr<SketchAPI_Point> majorAxisStart();
+  /// Return created auxiliary point - end of major axis
+  SKETCHAPI_EXPORT std::shared_ptr<SketchAPI_Point> majorAxisEnd();
+  /// Return created auxiliary point - start of minor axis
+  SKETCHAPI_EXPORT std::shared_ptr<SketchAPI_Point> minorAxisStart();
+  /// Return created auxiliary point - end of minor axis
+  SKETCHAPI_EXPORT std::shared_ptr<SketchAPI_Point> minorAxisEnd();
+  /// Return created auxiliary major axis
+  SKETCHAPI_EXPORT std::shared_ptr<SketchAPI_Line> majorAxis();
+  /// Return created auxiliary minor axis
+  SKETCHAPI_EXPORT std::shared_ptr<SketchAPI_Line> minorAxis();
 
 private:
   /// Set flag of creation by center, major semi-axis and passed point.
@@ -111,6 +116,21 @@ private:
                         const ModelHighAPI_RefAttr&           theMajorAxisPoint2Ref,
                         const std::shared_ptr<GeomAPI_Pnt2d>& thePassedPoint,
                         const ModelHighAPI_RefAttr&           thePassedPointRef);
+
+  /// Collect auxiliary features
+  void collectAuxiliary();
+
+private:
+  CompositeFeaturePtr mySketch;
+  std::shared_ptr<SketchAPI_Point> myCenter;
+  std::shared_ptr<SketchAPI_Point> myFocus1;
+  std::shared_ptr<SketchAPI_Point> myFocus2;
+  std::shared_ptr<SketchAPI_Point> myMajorAxisStart;
+  std::shared_ptr<SketchAPI_Point> myMajorAxisEnd;
+  std::shared_ptr<SketchAPI_Point> myMinorAxisStart;
+  std::shared_ptr<SketchAPI_Point> myMinorAxisEnd;
+  std::shared_ptr<SketchAPI_Line>  myMajorAxis;
+  std::shared_ptr<SketchAPI_Line>  myMinorAxis;
 };
 
 /// Pointer on Circle object.
index 52370987810f73b50d0919ded27688215e053b38..3476cd275104a14e9d4d8063d4a97a7d34ea52ec 100644 (file)
@@ -203,9 +203,13 @@ ADD_UNIT_TESTS(
   TestChangeSketchPlane2.py
   TestChangeSketchPlane3.py
   TestConstraintAngle.py
+  TestConstraintAngleEllipse.py
   TestConstraintCoincidence.py
+  TestConstraintCoincidenceEllipse.py
   TestConstraintCollinear.py
+  TestConstraintCollinearEllipse.py
   TestConstraintDistance.py
+  TestConstraintDistanceEllipse.py
   TestConstraintDistanceBehavior.py
   TestConstraintDistanceHorizontal.py
   TestConstraintDistanceVertical.py
diff --git a/src/SketchPlugin/Test/TestConstraintAngleEllipse.py b/src/SketchPlugin/Test/TestConstraintAngleEllipse.py
new file mode 100644 (file)
index 0000000..f795677
--- /dev/null
@@ -0,0 +1,125 @@
+# Copyright (C) 2019  CEA/DEN, EDF R&D
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+"""
+    Test constraint "Angle" applied for ellipse's axes
+"""
+
+import unittest
+import math
+
+from salome.shaper import model
+
+from GeomAPI import *
+from SketchAPI import *
+
+__updated__ = "2019-09-12"
+
+class TestAngleEllipse(unittest.TestCase):
+  def setUp(self):
+    axisStart = GeomAPI_Pnt2d(30., 60.)
+    axisEnd = GeomAPI_Pnt2d(80., 50.)
+    passedPoint = GeomAPI_Pnt2d(60., 60.)
+    self.myAngle = 60
+
+    model.begin()
+    self.myDocument = model.moduleDocument()
+    self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY"))
+    macroEllipse = self.mySketch.addEllipse(axisStart, axisEnd, passedPoint, False)
+    self.myDOF = 5
+    self.myOX = self.mySketch.addLine("OX")
+    model.do()
+    self.myEllipse = SketchAPI_Ellipse(model.lastSubFeature(self.mySketch, "SketchEllipse"))
+    self.myCenter = macroEllipse.center()
+    self.myFocus1 = macroEllipse.focus1()
+    self.myFocus2 = macroEllipse.focus2()
+    self.myMajorAxis = macroEllipse.majorAxis()
+    self.myMajorStart = macroEllipse.majorAxisStart()
+    self.myMajorEnd = macroEllipse.majorAxisEnd()
+    self.myMinorAxis = macroEllipse.minorAxis()
+    self.myMinorStart = macroEllipse.minorAxisStart()
+    self.myMinorEnd = macroEllipse.minorAxisEnd()
+
+
+  def tearDown(self):
+    model.end()
+    self.checkDOF()
+    self.assertPoints(self.myCenter.coordinates(), self.myEllipse.center())
+    self.assertPoints(self.myFocus1.coordinates(), self.myEllipse.firstFocus())
+    self.assertPoints(self.myFocus2.coordinates(), self.myEllipse.secondFocus())
+    self.assertPoints(self.myMajorStart.coordinates(), self.myEllipse.majorAxisNegative())
+    self.assertPoints(self.myMajorEnd.coordinates(), self.myEllipse.majorAxisPositive())
+    self.assertPoints(self.myMajorAxis.startPoint(), self.myEllipse.majorAxisNegative())
+    self.assertPoints(self.myMajorAxis.endPoint(), self.myEllipse.majorAxisPositive())
+    self.assertPoints(self.myMinorStart.coordinates(), self.myEllipse.minorAxisNegative())
+    self.assertPoints(self.myMinorEnd.coordinates(), self.myEllipse.minorAxisPositive())
+    self.assertPoints(self.myMinorAxis.startPoint(), self.myEllipse.minorAxisNegative())
+    self.assertPoints(self.myMinorAxis.endPoint(), self.myEllipse.minorAxisPositive())
+    model.testNbSubFeatures(self.mySketch, "SketchPoint", 7)
+    model.testNbSubFeatures(self.mySketch, "SketchLine", 3)
+    model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1)
+    model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidenceInternal", 11)
+
+
+  def checkDOF(self):
+    self.assertEqual(model.dof(self.mySketch), self.myDOF)
+
+  def assertPoints(self, thePoint1, thePoint2):
+    self.assertAlmostEqual(thePoint1.x(), thePoint2.x())
+    self.assertAlmostEqual(thePoint1.y(), thePoint2.y())
+
+  def assertAngle(self, theStart, theEnd, theAngle):
+    dirX = (theEnd.x() - theStart.x()) / math.hypot(theEnd.x() - theStart.x(), theEnd.y() - theStart.y())
+    self.assertAlmostEqual(math.fabs(dirX), math.cos(theAngle * math.pi / 180))
+
+
+  def test_angle_major_axis(self):
+    """ Test 1. Make angle between major axis of ellipse and OX
+    """
+    self.mySketch.setAngle(self.myOX.result(), self.myMajorAxis.result(), self.myAngle)
+    self.myDOF -= 1
+    model.do()
+    self.assertAngle(self.myMajorAxis.startPoint(), self.myMajorAxis.endPoint(), self.myAngle)
+    self.assertAngle(self.myMajorStart.coordinates(), self.myMajorEnd.coordinates(), self.myAngle)
+    model.testNbSubFeatures(self.mySketch, "SketchConstraintAngle", 1)
+
+  def test_angle_minor_axis(self):
+    """ Test 2. Make angle between minor axis of ellipse and OX
+    """
+    self.mySketch.setAngle(self.myOX.result(), self.myMinorAxis.result(), self.myAngle)
+    self.myDOF -= 1
+    model.do()
+    self.assertAngle(self.myMinorAxis.startPoint(), self.myMinorAxis.endPoint(), self.myAngle)
+    self.assertAngle(self.myMinorStart.coordinates(), self.myMinorEnd.coordinates(), self.myAngle)
+    model.testNbSubFeatures(self.mySketch, "SketchConstraintAngle", 1)
+
+  def test_angle_ellipse_axes(self):
+    """ Test 3. Set angle between axes of an ellipse. Check conflicting constraints.
+    """
+    self.mySketch.setAngle(self.myMajorAxis.result(), self.myMinorAxis.result(), self.myAngle)
+    model.end()
+    self.assertNotEqual(self.mySketch.solverError(), "")
+    model.undo()
+    model.begin()
+
+
+if __name__ == "__main__":
+    test_program = unittest.main(exit=False)
+    assert test_program.result.wasSuccessful(), "Test failed"
+    assert model.checkPythonDump()
diff --git a/src/SketchPlugin/Test/TestConstraintCoincidenceEllipse.py b/src/SketchPlugin/Test/TestConstraintCoincidenceEllipse.py
new file mode 100644 (file)
index 0000000..1b5944d
--- /dev/null
@@ -0,0 +1,241 @@
+# Copyright (C) 2019  CEA/DEN, EDF R&D
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+"""
+    Test constraint coincidence applied for ellipse and its sub-results
+"""
+
+import unittest
+import math
+
+from salome.shaper import model
+
+from GeomAPI import *
+from SketchAPI import *
+
+__updated__ = "2019-09-12"
+
+class TestCoincidenceEllipse(unittest.TestCase):
+  def setUp(self):
+    axisStart = GeomAPI_Pnt2d(30., 60.)
+    axisEnd = GeomAPI_Pnt2d(80., 50.)
+    passedPoint = GeomAPI_Pnt2d(60., 60.)
+
+    model.begin()
+    self.myDocument = model.moduleDocument()
+    self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY"))
+    macroEllipse = self.mySketch.addEllipse(axisStart, axisEnd, passedPoint, False)
+    self.myDOF = 5
+    self.myOrigin = self.mySketch.addPoint("Origin")
+    self.myOX = self.mySketch.addLine("OX")
+    model.do()
+    self.myEllipse = SketchAPI_Ellipse(model.lastSubFeature(self.mySketch, "SketchEllipse"))
+    self.myCenter = macroEllipse.center()
+    self.myFocus1 = macroEllipse.focus1()
+    self.myFocus2 = macroEllipse.focus2()
+    self.myMajorAxis = macroEllipse.majorAxis()
+    self.myMajorStart = macroEllipse.majorAxisStart()
+    self.myMajorEnd = macroEllipse.majorAxisEnd()
+    self.myMinorAxis = macroEllipse.minorAxis()
+    self.myMinorStart = macroEllipse.minorAxisStart()
+    self.myMinorEnd = macroEllipse.minorAxisEnd()
+    self.myExpectFailure = False
+
+  def tearDown(self):
+    model.end()
+    if self.myExpectFailure:
+      assert(self.mySketch.solverError() != ""), "PlaneGCS limitation: if you see this message, then PlaneGCS has solved the set of constraints correctly"
+      model.undo()
+    else:
+      self.checkDOF()
+      self.assertPoints(self.myCenter.coordinates(), self.myEllipse.center())
+      self.assertPoints(self.myFocus1.coordinates(), self.myEllipse.firstFocus())
+      self.assertPoints(self.myFocus2.coordinates(), self.myEllipse.secondFocus())
+      self.assertPoints(self.myMajorStart.coordinates(), self.myEllipse.majorAxisNegative())
+      self.assertPoints(self.myMajorEnd.coordinates(), self.myEllipse.majorAxisPositive())
+      self.assertPoints(self.myMajorAxis.startPoint(), self.myEllipse.majorAxisNegative())
+      self.assertPoints(self.myMajorAxis.endPoint(), self.myEllipse.majorAxisPositive())
+      self.assertPoints(self.myMinorStart.coordinates(), self.myEllipse.minorAxisNegative())
+      self.assertPoints(self.myMinorEnd.coordinates(), self.myEllipse.minorAxisPositive())
+      self.assertPoints(self.myMinorAxis.startPoint(), self.myEllipse.minorAxisNegative())
+      self.assertPoints(self.myMinorAxis.endPoint(), self.myEllipse.minorAxisPositive())
+      model.testNbSubFeatures(self.mySketch, "SketchPoint", 8)
+      model.testNbSubFeatures(self.mySketch, "SketchLine", 3)
+      model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1)
+      model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidenceInternal", 11)
+      model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1)
+
+
+  def checkDOF(self):
+    self.assertEqual(model.dof(self.mySketch), self.myDOF)
+
+  def checkPointFixing(self, thePoint):
+    self.mySketch.setCoincident(thePoint, self.myOrigin.coordinates())
+    self.myDOF -= 2
+    model.do()
+    if not self.myExpectFailure:
+      self.assertPoints(thePoint, self.myOrigin.coordinates())
+      self.assertGreater(self.myEllipse.majorRadius().value(), 0.0)
+      self.assertGreater(self.myEllipse.minorRadius().value(), 0.0)
+
+  def assertPoints(self, thePoint1, thePoint2):
+    self.assertAlmostEqual(thePoint1.x(), thePoint2.x())
+    self.assertAlmostEqual(thePoint1.y(), thePoint2.y())
+
+  def checkPointOnAxis(self, thePoint):
+    self.mySketch.setCoincident(thePoint, self.myOX.result())
+    self.myDOF -= 1
+    model.do()
+    if not self.myExpectFailure:
+      self.assertAlmostEqual(thePoint.y(), 0.0)
+      self.assertGreater(self.myEllipse.majorRadius().value(), 0.0)
+      self.assertGreater(self.myEllipse.minorRadius().value(), 0.0)
+
+  def checkPointOnLine(self, thePoint, theLineStart, theLineEnd):
+    vecP = [thePoint.x() - theLineStart.x(), thePoint.y() - theLineStart.y()]
+    vecL = [theLineEnd.x() - theLineStart.x(), theLineEnd.y() - theLineStart.y()]
+    dist = math.fabs(vecP[0] * vecL[1] - vecP[1] * vecL[0]) / math.hypot(vecL[0], vecL[1])
+
+    self.assertAlmostEqual(dist, 0.0)
+    self.assertGreater(self.myEllipse.majorRadius().value(), 0.0)
+    self.assertGreater(self.myEllipse.minorRadius().value(), 0.0)
+
+  def checkPointOnEllipse(self, thePoint, theEllipse):
+    firstFocus2d = GeomAPI_Pnt2d(theEllipse.firstFocus().x(), theEllipse.firstFocus().y())
+    distPF1 = model.distancePointPoint(firstFocus2d,  thePoint)
+    secondFocus2d = GeomAPI_Pnt2d(theEllipse.secondFocus().x(), theEllipse.secondFocus().y())
+    distPF2 = model.distancePointPoint(secondFocus2d,  thePoint)
+    self.assertAlmostEqual(distPF1 + distPF2, 2.0 * theEllipse.majorRadius().value(), 7)
+
+
+  def test_concident_center(self):
+    """ Test 1. Make center of ellipse coincident with the Origin
+    """
+    self.checkPointFixing(self.myCenter.coordinates())
+
+  def test_coincident_first_focus(self):
+    """ Test 2. Make first focus of ellipse coincident with the Origin
+    """
+    self.checkPointFixing(self.myFocus1.coordinates())
+
+  def test_coincident_second_focus(self):
+    """ Test 3. Make second focus of ellipse coincident with the Origin
+    """
+    self.checkPointFixing(self.myFocus2.coordinates())
+
+  def test_coincident_major_axis_start(self):
+    """ Test 4. Make start point on the major axis of ellipse coincident with the Origin
+    """
+    self.checkPointFixing(self.myMajorStart.coordinates())
+
+  def test_coincident_major_axis_end(self):
+    """ Test 5. Make end point on the major axis of ellipse coincident with the Origin
+    """
+    self.checkPointFixing(self.myMajorEnd.coordinates())
+
+  def test_coincident_minor_axis_start(self):
+    """ Test 6. Make start point on the minor axis of ellipse coincident with the Origin
+    """
+    self.checkPointFixing(self.myMinorStart.coordinates())
+
+  def test_coincident_minor_axis_end(self):
+    """ Test 7. Make end point on the minor axis of ellipse coincident with the Origin.
+                Check solver is failed to compute the coincidence.
+    """
+    self.myExpectFailure = True
+    self.checkPointFixing(self.myMinorEnd.coordinates())
+
+
+  def test_center_on_line(self):
+    """ Test 8. Make center of ellipse coincident with the OX
+    """
+    self.checkPointOnAxis(self.myCenter.coordinates())
+
+  def test_first_focus_on_line(self):
+    """ Test 9. Make first focus of ellipse coincident with the OX
+    """
+    self.checkPointOnAxis(self.myFocus1.coordinates())
+
+  def test_second_focus_on_line(self):
+    """ Test 10. Make second focus of ellipse coincident with the OX
+    """
+    self.checkPointOnAxis(self.myFocus2.coordinates())
+
+  def test_major_axis_start_on_line(self):
+    """ Test 11. Make start point on the major axis of ellipse coincident with the OX
+    """
+    self.checkPointOnAxis(self.myMajorStart.coordinates())
+
+  def test_major_axis_end_on_line(self):
+    """ Test 12. Make end point on the major axis of ellipse coincident with the OX
+    """
+    self.checkPointOnAxis(self.myMajorEnd.coordinates())
+
+  def test_minor_axis_start_on_line(self):
+    """ Test 13. Make start point on the minor axis of ellipse coincident with the OX
+    """
+    self.checkPointOnAxis(self.myMinorStart.coordinates())
+
+  def test_minor_axis_end_on_line(self):
+    """ Test 14. Make end point on the minor axis of ellipse coincident with the OX
+    """
+    self.myExpectFailure = True
+    self.checkPointOnAxis(self.myMinorEnd.coordinates())
+
+
+  def test_origin_on_major_axis(self):
+    """ Test 15. Make origin coincident with the major axis of the ellipse
+    """
+    self.mySketch.setCoincident(self.myMajorAxis.result(), self.myOrigin.coordinates())
+    self.myDOF -= 1
+    model.do()
+    self.checkPointOnLine(self.myOrigin.coordinates(), self.myMajorStart.coordinates(), self.myMajorEnd.coordinates())
+
+  def test_origin_on_minor_axis(self):
+    """ Test 16. Make origin coincident with the minor axis of the ellipse
+    """
+    self.mySketch.setCoincident(self.myMinorAxis.result(), self.myOrigin.coordinates())
+    self.myDOF -= 1
+    model.end()
+    # solver shows wrong result
+    assert(self.mySketch.solverError() != ""), "PlaneGCS limitation: if you see this message, then PlaneGCS has solved the set of constraints correctly"
+    model.undo()
+
+    # move ellipse and set coincidence once again
+    model.begin()
+    self.mySketch.move(self.myCenter, 20, 10)
+    model.do()
+    self.mySketch.setCoincident(self.myMinorAxis.results()[-1], self.myOrigin.coordinates())
+    model.do()
+    self.checkPointOnLine(self.myOrigin.coordinates(), self.myMinorStart.coordinates(), self.myMinorEnd.coordinates())
+
+
+  def test_origin_on_ellipse(self):
+    """ Test 17. Make origin coincident with the ellipse
+    """
+    self.mySketch.setCoincident(self.myEllipse.results()[-1], self.myOrigin.coordinates())
+    self.myDOF -= 1
+    model.do()
+    self.checkPointOnEllipse(self.myOrigin.coordinates(), self.myEllipse)
+
+
+if __name__ == "__main__":
+    test_program = unittest.main(exit=False)
+    assert test_program.result.wasSuccessful(), "Test failed"
+    assert model.checkPythonDump()
diff --git a/src/SketchPlugin/Test/TestConstraintCollinearEllipse.py b/src/SketchPlugin/Test/TestConstraintCollinearEllipse.py
new file mode 100644 (file)
index 0000000..38fff89
--- /dev/null
@@ -0,0 +1,134 @@
+# Copyright (C) 2019  CEA/DEN, EDF R&D
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+"""
+    Test constraint "Collinear" applied for ellipse's axes
+"""
+
+import unittest
+import math
+
+from salome.shaper import model
+
+from GeomAPI import *
+from SketchAPI import *
+
+__updated__ = "2019-09-18"
+
+class TestCollinearEllipse(unittest.TestCase):
+  def setUp(self):
+    axisStart = GeomAPI_Pnt2d(30., 60.)
+    axisEnd = GeomAPI_Pnt2d(80., 50.)
+    passedPoint = GeomAPI_Pnt2d(60., 60.)
+
+    model.begin()
+    self.myDocument = model.moduleDocument()
+    self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY"))
+    macroEllipse = self.mySketch.addEllipse(axisStart, axisEnd, passedPoint, False)
+    self.myDOF = 5
+    self.myOX = self.mySketch.addLine("OX")
+    model.do()
+    self.myEllipse = SketchAPI_Ellipse(model.lastSubFeature(self.mySketch, "SketchEllipse"))
+    self.myCenter = macroEllipse.center()
+    self.myFocus1 = macroEllipse.focus1()
+    self.myFocus2 = macroEllipse.focus2()
+    self.myMajorAxis = macroEllipse.majorAxis()
+    self.myMajorStart = macroEllipse.majorAxisStart()
+    self.myMajorEnd = macroEllipse.majorAxisEnd()
+    self.myMinorAxis = macroEllipse.minorAxis()
+    self.myMinorStart = macroEllipse.minorAxisStart()
+    self.myMinorEnd = macroEllipse.minorAxisEnd()
+
+
+  def tearDown(self):
+    model.end()
+    self.checkDOF()
+    self.assertPoints(self.myCenter.coordinates(), self.myEllipse.center())
+    self.assertPoints(self.myFocus1.coordinates(), self.myEllipse.firstFocus())
+    self.assertPoints(self.myFocus2.coordinates(), self.myEllipse.secondFocus())
+    self.assertPoints(self.myMajorStart.coordinates(), self.myEllipse.majorAxisNegative())
+    self.assertPoints(self.myMajorEnd.coordinates(), self.myEllipse.majorAxisPositive())
+    self.assertPoints(self.myMajorAxis.startPoint(), self.myEllipse.majorAxisNegative())
+    self.assertPoints(self.myMajorAxis.endPoint(), self.myEllipse.majorAxisPositive())
+    self.assertPoints(self.myMinorStart.coordinates(), self.myEllipse.minorAxisNegative())
+    self.assertPoints(self.myMinorEnd.coordinates(), self.myEllipse.minorAxisPositive())
+    self.assertPoints(self.myMinorAxis.startPoint(), self.myEllipse.minorAxisNegative())
+    self.assertPoints(self.myMinorAxis.endPoint(), self.myEllipse.minorAxisPositive())
+    model.testNbSubFeatures(self.mySketch, "SketchPoint", 7)
+    model.testNbSubFeatures(self.mySketch, "SketchLine", 3)
+    model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1)
+    model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidenceInternal", 11)
+
+
+  def checkDOF(self):
+    self.assertEqual(model.dof(self.mySketch), self.myDOF)
+
+  def assertPoints(self, thePoint1, thePoint2):
+    self.assertAlmostEqual(thePoint1.x(), thePoint2.x())
+    self.assertAlmostEqual(thePoint1.y(), thePoint2.y())
+
+
+  def test_collinear_major_axis(self):
+    """ Test 1. Make major axis of ellipse collinear with OX
+    """
+    self.mySketch.setCollinear(self.myOX.result(), self.myMajorAxis.result())
+    self.myDOF -= 2
+    model.do()
+    self.assertAlmostEqual(self.myMajorAxis.startPoint().y(), 0)
+    self.assertAlmostEqual(self.myMajorAxis.endPoint().y(), 0)
+    self.assertAlmostEqual(self.myMajorStart.coordinates().y(), 0)
+    self.assertAlmostEqual(self.myMajorEnd.coordinates().y(), 0)
+    model.testNbSubFeatures(self.mySketch, "SketchConstraintCollinear", 1)
+
+  def test_collinear_minor_axis(self):
+    """ Test 2. Make minor axis of ellipse collinear with OX
+    """
+    self.mySketch.setCollinear(self.myOX.result(), self.myMinorAxis.result())
+    self.myDOF -= 2
+    model.end()
+    # solver shows wrong result
+    assert(self.mySketch.solverError() != ""), "PlaneGCS limitation: if you see this message, then PlaneGCS has solved the set of constraints correctly"
+    model.undo()
+
+    model.begin()
+    self.mySketch.move(self.myMinorStart.coordinates(), 0, 70)
+    self.mySketch.move(self.myMinorEnd.coordinates(), 50, 70)
+    model.do()
+    self.mySketch.setCollinear(self.myOX.result(), self.myMinorAxis.result())
+    model.do()
+    self.assertAlmostEqual(self.myMinorAxis.startPoint().y(), 0)
+    self.assertAlmostEqual(self.myMinorAxis.endPoint().y(), 0)
+    self.assertAlmostEqual(self.myMinorStart.coordinates().y(), 0)
+    self.assertAlmostEqual(self.myMinorEnd.coordinates().y(), 0)
+    model.testNbSubFeatures(self.mySketch, "SketchConstraintCollinear", 1)
+
+  def test_collinear_ellipse_axes(self):
+    """ Test 3. Set collinear axes of an ellipse. Check conflicting constraints.
+    """
+    self.mySketch.setCollinear(self.myEllipse.majorAxis(), self.myEllipse.minorAxis())
+    model.end()
+    self.assertNotEqual(self.mySketch.solverError(), "")
+    model.undo()
+    model.begin()
+
+
+if __name__ == "__main__":
+    test_program = unittest.main(exit=False)
+    assert test_program.result.wasSuccessful(), "Test failed"
+    assert model.checkPythonDump()
diff --git a/src/SketchPlugin/Test/TestConstraintDistanceEllipse.py b/src/SketchPlugin/Test/TestConstraintDistanceEllipse.py
new file mode 100644 (file)
index 0000000..6ec2980
--- /dev/null
@@ -0,0 +1,199 @@
+# Copyright (C) 2019  CEA/DEN, EDF R&D
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+"""
+    Test constraint "Distance" applied sub-elements of an ellipse
+"""
+
+import unittest
+import math
+
+from salome.shaper import model
+
+from GeomAPI import *
+from SketchAPI import *
+
+__updated__ = "2019-09-12"
+
+class TestDistanceEllipse(unittest.TestCase):
+  def setUp(self):
+    axisStart = GeomAPI_Pnt2d(20., 60.)
+    axisEnd = GeomAPI_Pnt2d(80., 50.)
+    passedPoint = GeomAPI_Pnt2d(60., 70.)
+
+    model.begin()
+    self.myDocument = model.moduleDocument()
+    self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY"))
+    macroEllipse = self.mySketch.addEllipse(axisStart, axisEnd, passedPoint, False)
+    self.myDOF = 5
+    self.myOrigin = self.mySketch.addPoint("Origin")
+    self.myOX = self.mySketch.addLine("OX")
+    model.do()
+    self.myEllipse = SketchAPI_Ellipse(model.lastSubFeature(self.mySketch, "SketchEllipse"))
+    self.myCenter = macroEllipse.center()
+    self.myFocus1 = macroEllipse.focus1()
+    self.myFocus2 = macroEllipse.focus2()
+    self.myMajorAxis = macroEllipse.majorAxis()
+    self.myMajorStart = macroEllipse.majorAxisStart()
+    self.myMajorEnd = macroEllipse.majorAxisEnd()
+    self.myMinorAxis = macroEllipse.minorAxis()
+    self.myMinorStart = macroEllipse.minorAxisStart()
+    self.myMinorEnd = macroEllipse.minorAxisEnd()
+    self.myExpectFailure = False
+    self.myDistance = 20
+
+  def tearDown(self):
+    model.end()
+    if self.myExpectFailure:
+      assert(self.mySketch.solverError() != ""), "PlaneGCS limitation: if you see this message, then PlaneGCS has solved the set of constraints correctly"
+      model.undo()
+    else:
+      self.checkDOF()
+      self.assertPoints(self.myCenter.coordinates(), self.myEllipse.center())
+      self.assertPoints(self.myFocus1.coordinates(), self.myEllipse.firstFocus())
+      self.assertPoints(self.myFocus2.coordinates(), self.myEllipse.secondFocus())
+      self.assertPoints(self.myMajorStart.coordinates(), self.myEllipse.majorAxisNegative())
+      self.assertPoints(self.myMajorEnd.coordinates(), self.myEllipse.majorAxisPositive())
+      self.assertPoints(self.myMajorAxis.startPoint(), self.myEllipse.majorAxisNegative())
+      self.assertPoints(self.myMajorAxis.endPoint(), self.myEllipse.majorAxisPositive())
+      self.assertPoints(self.myMinorStart.coordinates(), self.myEllipse.minorAxisNegative())
+      self.assertPoints(self.myMinorEnd.coordinates(), self.myEllipse.minorAxisPositive())
+      self.assertPoints(self.myMinorAxis.startPoint(), self.myEllipse.minorAxisNegative())
+      self.assertPoints(self.myMinorAxis.endPoint(), self.myEllipse.minorAxisPositive())
+      model.testNbSubFeatures(self.mySketch, "SketchPoint", 8)
+      model.testNbSubFeatures(self.mySketch, "SketchLine", 3)
+      model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1)
+      model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidenceInternal", 11)
+      model.testNbSubFeatures(self.mySketch, "SketchConstraintDistance", 1)
+
+
+  def checkDOF(self):
+    self.assertEqual(model.dof(self.mySketch), self.myDOF)
+
+  def checkPointPointDistance(self, thePoint1, thePoint2):
+    self.mySketch.setDistance(thePoint1, thePoint2, self.myDistance)
+    self.myDOF -= 1
+    model.do()
+    if not self.myExpectFailure:
+      self.assertAlmostEqual(model.distancePointPoint(thePoint1, thePoint2), self.myDistance)
+      self.assertGreater(self.myEllipse.majorRadius().value(), 0.0)
+      self.assertGreater(self.myEllipse.minorRadius().value(), 0.0)
+
+  def checkPointLineDistance(self, thePoint, theLine):
+    self.mySketch.setDistance(thePoint, theLine.result(), self.myDistance)
+    self.myDOF -= 1
+    model.do()
+    self.assertAlmostEqual(model.distancePointLine(thePoint, theLine), self.myDistance)
+    self.assertGreater(self.myEllipse.majorRadius().value(), 0.0)
+    self.assertGreater(self.myEllipse.minorRadius().value(), 0.0)
+
+  def assertPoints(self, thePoint1, thePoint2):
+    self.assertAlmostEqual(thePoint1.x(), thePoint2.x())
+    self.assertAlmostEqual(thePoint1.y(), thePoint2.y())
+
+
+  def test_distance_center(self):
+    """ Test 1. Set distance to the Origin from the center of ellipse
+    """
+    self.checkPointPointDistance(self.myCenter.coordinates(), self.myOrigin.coordinates())
+
+  def test_distance_first_focus(self):
+    """ Test 2. Set distance to the Origin from the first focus of ellipse
+    """
+    self.checkPointPointDistance(self.myFocus1.coordinates(), self.myOrigin.coordinates())
+
+  def test_distance_second_focus(self):
+    """ Test 3. Set distance to the Origin from the second focus of ellipse
+    """
+    self.checkPointPointDistance(self.myFocus2.coordinates(), self.myOrigin.coordinates())
+
+  def test_distance_major_axis_start(self):
+    """ Test 4. Set distance to the Origin from the start point on the major axis of ellipse
+    """
+    self.checkPointPointDistance(self.myMajorStart.coordinates(), self.myOrigin.coordinates())
+
+  def test_distance_major_axis_end(self):
+    """ Test 5. Set distance to the Origin from the end point on the major axis of ellipse
+    """
+    self.checkPointPointDistance(self.myMajorEnd.coordinates(), self.myOrigin.coordinates())
+
+  def test_distance_minor_axis_start(self):
+    """ Test 6. Set distance to the Origin from the start point on the minor axis of ellipse
+    """
+    self.checkPointPointDistance(self.myMinorStart.coordinates(), self.myOrigin.coordinates())
+
+  def test_distance_minor_axis_end(self):
+    """ Test 7. Set distance to the Origin from the end point on the minor axis of ellipse
+    """
+    self.myExpectFailure = True
+    self.checkPointPointDistance(self.myMinorEnd.coordinates(), self.myOrigin.coordinates())
+
+
+  def test_distance_center_to_line(self):
+    """ Test 8. Set distance from theOX to the center of ellipse
+    """
+    self.checkPointLineDistance(self.myCenter.coordinates(), self.myOX)
+
+  def test_distance_first_focus_to_line(self):
+    """ Test 9. Set distance from theOX to the first focus of ellipse
+    """
+    self.checkPointLineDistance(self.myFocus1.coordinates(), self.myOX)
+
+  def test_distance_second_focus_to_line(self):
+    """ Test 10. Set distance from theOX to the second focus of ellipse
+    """
+    self.checkPointLineDistance(self.myFocus2.coordinates(), self.myOX)
+
+  def test_distance_major_axis_start_to_line(self):
+    """ Test 11. Set distance from theOX to the start point on the major axis of ellipse
+    """
+    self.checkPointLineDistance(self.myMajorStart.coordinates(), self.myOX)
+
+  def test_distance_major_axis_end_to_line(self):
+    """ Test 12. Set distance from theOX to the end point on the major axis of ellipse
+    """
+    self.checkPointLineDistance(self.myMajorEnd.coordinates(), self.myOX)
+
+  def test_distance_minor_axis_start_to_line(self):
+    """ Test 13. Set distance from theOX to the start point on the minor axis of ellipse
+    """
+    self.checkPointLineDistance(self.myMinorStart.coordinates(), self.myOX)
+
+  def test_distance_minor_axis_end_to_line(self):
+    """ Test 14. Set distance from theOX to the end point on the minor axis of ellipse
+    """
+    self.myDistance = 150
+    self.checkPointLineDistance(self.myMinorEnd.coordinates(), self.myOX)
+
+
+  def test_distance_origin_to_major_axis(self):
+    """ Test 15. Set distance from the Origin to the major axis of the ellipse
+    """
+    self.checkPointLineDistance(self.myOrigin.coordinates(), self.myMajorAxis)
+
+  def test_distance_origin_to_minor_axis(self):
+    """ Test 16. Set distance from the Origin to the minor axis of the ellipse
+    """
+    self.checkPointLineDistance(self.myOrigin.coordinates(), self.myMinorAxis)
+
+
+if __name__ == "__main__":
+    test_program = unittest.main(exit=False)
+    assert test_program.result.wasSuccessful(), "Test failed"
+    assert model.checkPythonDump()