Salome HOME
Copyright update 2020
[modules/shaper.git] / src / SketchPlugin / Test / TestConstraintCoincidenceEllipse.py
1 # Copyright (C) 2019-2020  CEA/DEN, EDF R&D
2 #
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.
7 #
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.
12 #
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
16 #
17 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 #
19
20 """
21     Test constraint coincidence applied for ellipse and its sub-results
22 """
23
24 import unittest
25 import math
26
27 from salome.shaper import model
28
29 from GeomAPI import *
30 from SketchAPI import *
31
32 __updated__ = "2019-09-12"
33
34 class TestCoincidenceEllipse(unittest.TestCase):
35   def setUp(self):
36     axisStart = GeomAPI_Pnt2d(30., 60.)
37     axisEnd = GeomAPI_Pnt2d(80., 50.)
38     passedPoint = GeomAPI_Pnt2d(60., 60.)
39
40     model.begin()
41     self.myDocument = model.moduleDocument()
42     self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY"))
43     macroEllipse = self.mySketch.addEllipse(axisStart, axisEnd, passedPoint, False)
44     self.myDOF = 5
45     self.myOrigin = self.mySketch.addPoint("Origin")
46     self.myOX = self.mySketch.addLine("OX")
47     model.do()
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
60   def tearDown(self):
61     model.end()
62     if self.myExpectFailure:
63       assert(self.mySketch.solverError() != ""), "PlaneGCS limitation: if you see this message, then PlaneGCS has solved the set of constraints correctly"
64       model.undo()
65     else:
66       self.checkDOF()
67       self.assertPoints(self.myCenter.coordinates(), self.myEllipse.center())
68       self.assertPoints(self.myFocus1.coordinates(), self.myEllipse.firstFocus())
69       self.assertPoints(self.myFocus2.coordinates(), self.myEllipse.secondFocus())
70       self.assertPoints(self.myMajorStart.coordinates(), self.myEllipse.majorAxisNegative())
71       self.assertPoints(self.myMajorEnd.coordinates(), self.myEllipse.majorAxisPositive())
72       self.assertPoints(self.myMajorAxis.startPoint(), self.myEllipse.majorAxisNegative())
73       self.assertPoints(self.myMajorAxis.endPoint(), self.myEllipse.majorAxisPositive())
74       self.assertPoints(self.myMinorStart.coordinates(), self.myEllipse.minorAxisNegative())
75       self.assertPoints(self.myMinorEnd.coordinates(), self.myEllipse.minorAxisPositive())
76       self.assertPoints(self.myMinorAxis.startPoint(), self.myEllipse.minorAxisNegative())
77       self.assertPoints(self.myMinorAxis.endPoint(), self.myEllipse.minorAxisPositive())
78       model.testNbSubFeatures(self.mySketch, "SketchPoint", 8)
79       model.testNbSubFeatures(self.mySketch, "SketchLine", 3)
80       model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1)
81       model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidenceInternal", 11)
82       model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1)
83
84
85   def checkDOF(self):
86     self.assertEqual(model.dof(self.mySketch), self.myDOF)
87
88   def checkPointFixing(self, thePoint):
89     self.mySketch.setCoincident(thePoint, self.myOrigin.coordinates())
90     self.myDOF -= 2
91     model.do()
92     if not self.myExpectFailure:
93       self.assertPoints(thePoint, self.myOrigin.coordinates())
94       self.assertGreater(self.myEllipse.majorRadius().value(), 0.0)
95       self.assertGreater(self.myEllipse.minorRadius().value(), 0.0)
96
97   def assertPoints(self, thePoint1, thePoint2):
98     self.assertAlmostEqual(thePoint1.x(), thePoint2.x())
99     self.assertAlmostEqual(thePoint1.y(), thePoint2.y())
100
101   def checkPointOnAxis(self, thePoint):
102     self.mySketch.setCoincident(thePoint, self.myOX.result())
103     self.myDOF -= 1
104     model.do()
105     if not self.myExpectFailure:
106       self.assertAlmostEqual(thePoint.y(), 0.0)
107       self.assertGreater(self.myEllipse.majorRadius().value(), 0.0)
108       self.assertGreater(self.myEllipse.minorRadius().value(), 0.0)
109
110   def checkPointOnLine(self, thePoint, theLineStart, theLineEnd):
111     vecP = [thePoint.x() - theLineStart.x(), thePoint.y() - theLineStart.y()]
112     vecL = [theLineEnd.x() - theLineStart.x(), theLineEnd.y() - theLineStart.y()]
113     dist = math.fabs(vecP[0] * vecL[1] - vecP[1] * vecL[0]) / math.hypot(vecL[0], vecL[1])
114
115     self.assertAlmostEqual(dist, 0.0)
116     self.assertGreater(self.myEllipse.majorRadius().value(), 0.0)
117     self.assertGreater(self.myEllipse.minorRadius().value(), 0.0)
118
119   def checkPointOnEllipse(self, thePoint, theEllipse):
120     firstFocus2d = GeomAPI_Pnt2d(theEllipse.firstFocus().x(), theEllipse.firstFocus().y())
121     distPF1 = model.distancePointPoint(firstFocus2d,  thePoint)
122     secondFocus2d = GeomAPI_Pnt2d(theEllipse.secondFocus().x(), theEllipse.secondFocus().y())
123     distPF2 = model.distancePointPoint(secondFocus2d,  thePoint)
124     self.assertAlmostEqual(distPF1 + distPF2, 2.0 * theEllipse.majorRadius().value(), 7)
125
126
127   def test_concident_center(self):
128     """ Test 1. Make center of ellipse coincident with the Origin
129     """
130     self.checkPointFixing(self.myCenter.coordinates())
131
132   def test_coincident_first_focus(self):
133     """ Test 2. Make first focus of ellipse coincident with the Origin
134     """
135     self.checkPointFixing(self.myFocus1.coordinates())
136
137   def test_coincident_second_focus(self):
138     """ Test 3. Make second focus of ellipse coincident with the Origin
139     """
140     self.checkPointFixing(self.myFocus2.coordinates())
141
142   def test_coincident_major_axis_start(self):
143     """ Test 4. Make start point on the major axis of ellipse coincident with the Origin
144     """
145     self.checkPointFixing(self.myMajorStart.coordinates())
146
147   def test_coincident_major_axis_end(self):
148     """ Test 5. Make end point on the major axis of ellipse coincident with the Origin
149     """
150     self.checkPointFixing(self.myMajorEnd.coordinates())
151
152   def test_coincident_minor_axis_start(self):
153     """ Test 6. Make start point on the minor axis of ellipse coincident with the Origin
154     """
155     self.checkPointFixing(self.myMinorStart.coordinates())
156
157   def test_coincident_minor_axis_end(self):
158     """ Test 7. Make end point on the minor axis of ellipse coincident with the Origin.
159                 Check solver is failed to compute the coincidence.
160     """
161     self.myExpectFailure = True
162     self.checkPointFixing(self.myMinorEnd.coordinates())
163
164
165   def test_center_on_line(self):
166     """ Test 8. Make center of ellipse coincident with the OX
167     """
168     self.checkPointOnAxis(self.myCenter.coordinates())
169
170   def test_first_focus_on_line(self):
171     """ Test 9. Make first focus of ellipse coincident with the OX
172     """
173     self.checkPointOnAxis(self.myFocus1.coordinates())
174
175   def test_second_focus_on_line(self):
176     """ Test 10. Make second focus of ellipse coincident with the OX
177     """
178     self.checkPointOnAxis(self.myFocus2.coordinates())
179
180   def test_major_axis_start_on_line(self):
181     """ Test 11. Make start point on the major axis of ellipse coincident with the OX
182     """
183     self.checkPointOnAxis(self.myMajorStart.coordinates())
184
185   def test_major_axis_end_on_line(self):
186     """ Test 12. Make end point on the major axis of ellipse coincident with the OX
187     """
188     self.checkPointOnAxis(self.myMajorEnd.coordinates())
189
190   def test_minor_axis_start_on_line(self):
191     """ Test 13. Make start point on the minor axis of ellipse coincident with the OX
192     """
193     self.checkPointOnAxis(self.myMinorStart.coordinates())
194
195   def test_minor_axis_end_on_line(self):
196     """ Test 14. Make end point on the minor axis of ellipse coincident with the OX
197     """
198     self.myExpectFailure = True
199     self.checkPointOnAxis(self.myMinorEnd.coordinates())
200
201
202   def test_origin_on_major_axis(self):
203     """ Test 15. Make origin coincident with the major axis of the ellipse
204     """
205     self.mySketch.setCoincident(self.myMajorAxis.result(), self.myOrigin.coordinates())
206     self.myDOF -= 1
207     model.do()
208     self.checkPointOnLine(self.myOrigin.coordinates(), self.myMajorStart.coordinates(), self.myMajorEnd.coordinates())
209
210   def test_origin_on_minor_axis(self):
211     """ Test 16. Make origin coincident with the minor axis of the ellipse
212     """
213     self.mySketch.setCoincident(self.myMinorAxis.result(), self.myOrigin.coordinates())
214     self.myDOF -= 1
215     model.end()
216     # solver shows wrong result
217     assert(self.mySketch.solverError() != ""), "PlaneGCS limitation: if you see this message, then PlaneGCS has solved the set of constraints correctly"
218     model.undo()
219
220     # move ellipse and set coincidence once again
221     model.begin()
222     self.mySketch.move(self.myMinorStart, 20, 10)
223     model.do()
224     self.mySketch.setCoincident(self.myMinorAxis.results()[-1], self.myOrigin.coordinates())
225     model.do()
226     self.checkPointOnLine(self.myOrigin.coordinates(), self.myMinorStart.coordinates(), self.myMinorEnd.coordinates())
227
228
229   def test_origin_on_ellipse(self):
230     """ Test 17. Make origin coincident with the ellipse
231     """
232     self.mySketch.setCoincident(self.myEllipse.results()[-1], self.myOrigin.coordinates())
233     self.myDOF -= 1
234     model.do()
235     self.checkPointOnEllipse(self.myOrigin.coordinates(), self.myEllipse)
236
237
238 if __name__ == "__main__":
239     test_program = unittest.main(exit=False)
240     assert test_program.result.wasSuccessful(), "Test failed"
241     assert model.checkPythonDump()