Unit tests for constraints Angle, Coincidence, Collinear and Distance applied to ellipse.
// 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");
//
#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)
{
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();
}
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();
}
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));
+ }
+}
#include <SketchPlugin_MacroEllipse.h>
class ModelHighAPI_RefAttr;
+class SketchAPI_Point;
+class SketchAPI_Line;
/// \class SketchAPI_MacroEllipse
/// \ingroup CPPHighAPI
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.
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.
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
--- /dev/null
+# 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()
--- /dev/null
+# 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()
--- /dev/null
+# 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()
--- /dev/null
+# 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()