1 # Copyright (C) 2019-2020 CEA/DEN, EDF R&D
3 # This library is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU Lesser General Public
5 # License as published by the Free Software Foundation; either
6 # version 2.1 of the License, or (at your option) any later version.
8 # This library is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 # Lesser General Public License for more details.
13 # You should have received a copy of the GNU Lesser General Public
14 # License along with this library; if not, write to the Free Software
15 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 Test constraint coincidence applied for ellipse and its sub-results
27 from salome.shaper import model
30 from SketchAPI import *
32 __updated__ = "2019-09-12"
34 class TestCoincidenceEllipse(unittest.TestCase):
36 axisStart = GeomAPI_Pnt2d(30., 60.)
37 axisEnd = GeomAPI_Pnt2d(80., 50.)
38 passedPoint = GeomAPI_Pnt2d(60., 60.)
41 self.myDocument = model.moduleDocument()
42 self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY"))
43 macroEllipse = self.mySketch.addEllipse(axisStart, axisEnd, passedPoint, False)
45 self.myOrigin = self.mySketch.addPoint("Origin")
46 self.myOX = self.mySketch.addLine("OX")
48 self.myEllipse = SketchAPI_Ellipse(model.lastSubFeature(self.mySketch, "SketchEllipse"))
49 self.myCenter = macroEllipse.center()
50 self.myFocus1 = macroEllipse.focus1()
51 self.myFocus2 = macroEllipse.focus2()
52 self.myMajorAxis = macroEllipse.majorAxis()
53 self.myMajorStart = macroEllipse.majorAxisStart()
54 self.myMajorEnd = macroEllipse.majorAxisEnd()
55 self.myMinorAxis = macroEllipse.minorAxis()
56 self.myMinorStart = macroEllipse.minorAxisStart()
57 self.myMinorEnd = macroEllipse.minorAxisEnd()
58 self.myExpectFailure = False
59 self.myNbCoindicences = 1
63 if self.myExpectFailure:
64 assert(self.mySketch.solverError() != ""), "PlaneGCS limitation: if you see this message, then PlaneGCS has solved the set of constraints correctly"
68 self.assertPoints(self.myCenter.coordinates(), self.myEllipse.center())
69 self.assertPoints(self.myFocus1.coordinates(), self.myEllipse.firstFocus())
70 self.assertPoints(self.myFocus2.coordinates(), self.myEllipse.secondFocus())
71 self.assertPoints(self.myMajorStart.coordinates(), self.myEllipse.majorAxisNegative())
72 self.assertPoints(self.myMajorEnd.coordinates(), self.myEllipse.majorAxisPositive())
73 self.assertPoints(self.myMajorAxis.startPoint(), self.myEllipse.majorAxisNegative())
74 self.assertPoints(self.myMajorAxis.endPoint(), self.myEllipse.majorAxisPositive())
75 self.assertPoints(self.myMinorStart.coordinates(), self.myEllipse.minorAxisNegative())
76 self.assertPoints(self.myMinorEnd.coordinates(), self.myEllipse.minorAxisPositive())
77 self.assertPoints(self.myMinorAxis.startPoint(), self.myEllipse.minorAxisNegative())
78 self.assertPoints(self.myMinorAxis.endPoint(), self.myEllipse.minorAxisPositive())
79 model.testNbSubFeatures(self.mySketch, "SketchPoint", 8)
80 model.testNbSubFeatures(self.mySketch, "SketchLine", 3)
81 model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1)
82 model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidenceInternal", 11)
83 model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", self.myNbCoindicences)
87 self.assertEqual(model.dof(self.mySketch), self.myDOF)
89 def checkPointFixing(self, thePoint):
90 self.mySketch.setCoincident(thePoint, self.myOrigin.coordinates())
93 if not self.myExpectFailure:
94 self.assertPoints(thePoint, self.myOrigin.coordinates())
95 self.assertGreater(self.myEllipse.majorRadius().value(), 0.0)
96 self.assertGreater(self.myEllipse.minorRadius().value(), 0.0)
98 def assertPoints(self, thePoint1, thePoint2):
99 self.assertAlmostEqual(thePoint1.x(), thePoint2.x(), delta = 1.e-6)
100 self.assertAlmostEqual(thePoint1.y(), thePoint2.y(), delta = 1.e-6)
102 def checkPointOnAxis(self, thePoint):
103 self.mySketch.setCoincident(thePoint, self.myOX.result())
106 if not self.myExpectFailure:
107 self.assertAlmostEqual(thePoint.y(), 0.0, delta = 1.e-6)
108 self.assertGreater(self.myEllipse.majorRadius().value(), 0.0)
109 self.assertGreater(self.myEllipse.minorRadius().value(), 0.0)
111 def checkPointOnLine(self, thePoint, theLineStart, theLineEnd):
112 vecP = [thePoint.x() - theLineStart.x(), thePoint.y() - theLineStart.y()]
113 vecL = [theLineEnd.x() - theLineStart.x(), theLineEnd.y() - theLineStart.y()]
114 dist = math.fabs(vecP[0] * vecL[1] - vecP[1] * vecL[0]) / math.hypot(vecL[0], vecL[1])
116 self.assertAlmostEqual(dist, 0.0, delta = 1.e-6)
117 self.assertGreater(self.myEllipse.majorRadius().value(), 0.0)
118 self.assertGreater(self.myEllipse.minorRadius().value(), 0.0)
120 def checkPointOnEllipse(self, thePoint, theEllipse):
121 firstFocus2d = GeomAPI_Pnt2d(theEllipse.firstFocus().x(), theEllipse.firstFocus().y())
122 distPF1 = model.distancePointPoint(firstFocus2d, thePoint)
123 secondFocus2d = GeomAPI_Pnt2d(theEllipse.secondFocus().x(), theEllipse.secondFocus().y())
124 distPF2 = model.distancePointPoint(secondFocus2d, thePoint)
125 self.assertAlmostEqual(distPF1 + distPF2, 2.0 * theEllipse.majorRadius().value(), 7)
128 def test_concident_center(self):
129 """ Test 1. Make center of ellipse coincident with the Origin
131 self.checkPointFixing(self.myCenter.coordinates())
133 def test_coincident_first_focus(self):
134 """ Test 2. Make first focus of ellipse coincident with the Origin
136 self.checkPointFixing(self.myFocus1.coordinates())
138 def test_coincident_second_focus(self):
139 """ Test 3. Make second focus of ellipse coincident with the Origin
141 self.checkPointFixing(self.myFocus2.coordinates())
143 def test_coincident_major_axis_start(self):
144 """ Test 4. Make start point on the major axis of ellipse coincident with the Origin
146 self.checkPointFixing(self.myMajorStart.coordinates())
148 def test_coincident_major_axis_end(self):
149 """ Test 5. Make end point on the major axis of ellipse coincident with the Origin
151 self.checkPointFixing(self.myMajorEnd.coordinates())
153 def test_coincident_minor_axis_start(self):
154 """ Test 6. Make start point on the minor axis of ellipse coincident with the Origin
156 self.checkPointFixing(self.myMinorStart.coordinates())
157 # workaround: kill the constraint to avoid instability on dump check
162 self.myNbCoindicences -= 1
164 def test_coincident_minor_axis_end(self):
165 """ Test 7. Make end point on the minor axis of ellipse coincident with the Origin.
166 Check solver is failed to compute the coincidence.
168 self.myExpectFailure = True
169 self.checkPointFixing(self.myMinorEnd.coordinates())
172 def test_center_on_line(self):
173 """ Test 8. Make center of ellipse coincident with the OX
175 self.checkPointOnAxis(self.myCenter.coordinates())
177 def test_first_focus_on_line(self):
178 """ Test 9. Make first focus of ellipse coincident with the OX
180 self.checkPointOnAxis(self.myFocus1.coordinates())
182 def test_second_focus_on_line(self):
183 """ Test 10. Make second focus of ellipse coincident with the OX
185 self.checkPointOnAxis(self.myFocus2.coordinates())
187 def test_major_axis_start_on_line(self):
188 """ Test 11. Make start point on the major axis of ellipse coincident with the OX
190 self.checkPointOnAxis(self.myMajorStart.coordinates())
192 def test_major_axis_end_on_line(self):
193 """ Test 12. Make end point on the major axis of ellipse coincident with the OX
195 self.checkPointOnAxis(self.myMajorEnd.coordinates())
197 def test_minor_axis_start_on_line(self):
198 """ Test 13. Make start point on the minor axis of ellipse coincident with the OX
200 self.checkPointOnAxis(self.myMinorStart.coordinates())
202 def test_minor_axis_end_on_line(self):
203 """ Test 14. Make end point on the minor axis of ellipse coincident with the OX
205 self.myExpectFailure = True
206 self.checkPointOnAxis(self.myMinorEnd.coordinates())
209 def test_origin_on_major_axis(self):
210 """ Test 15. Make origin coincident with the major axis of the ellipse
212 self.mySketch.setCoincident(self.myMajorAxis.result(), self.myOrigin.coordinates())
215 self.checkPointOnLine(self.myOrigin.coordinates(), self.myMajorStart.coordinates(), self.myMajorEnd.coordinates())
217 def test_origin_on_minor_axis(self):
218 """ Test 16. Make origin coincident with the minor axis of the ellipse
220 self.mySketch.setCoincident(self.myMinorAxis.result(), self.myOrigin.coordinates())
223 # solver shows wrong result
224 assert(self.mySketch.solverError() != ""), "PlaneGCS limitation: if you see this message, then PlaneGCS has solved the set of constraints correctly"
227 # move ellipse and set coincidence once again
229 self.mySketch.move(self.myMinorStart, 20, 10)
231 self.mySketch.setCoincident(self.myMinorAxis.results()[-1], self.myOrigin.coordinates())
233 self.checkPointOnLine(self.myOrigin.coordinates(), self.myMinorStart.coordinates(), self.myMinorEnd.coordinates())
236 def test_origin_on_ellipse(self):
237 """ Test 17. Make origin coincident with the ellipse
239 self.mySketch.setCoincident(self.myEllipse.results()[-1], self.myOrigin.coordinates())
242 self.checkPointOnEllipse(self.myOrigin.coordinates(), self.myEllipse)
245 if __name__ == "__main__":
246 test_program = unittest.main(exit=False)
247 assert test_program.result.wasSuccessful(), "Test failed"
248 assert model.checkPythonDump()