Salome HOME
224c0be4d2288a8e0c0a4cb31cd8e25c594b7baf
[modules/shaper.git] / src / SketchPlugin / Test / TestConstraintMiddlePointOnEllipticArc.py
1 # Copyright (C) 2019-2021  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 middle point on an elliptic arc
22 """
23
24 import unittest
25 import math
26
27 from salome.shaper import model
28 from GeomAPI import *
29 from SketchAPI import *
30
31 __updated__ = "2019-10-02"
32
33 class TestMiddlePointOnEllipticArc(unittest.TestCase):
34   def setUp(self):
35     model.begin()
36     self.myTestPassed = True
37     self.myDocument = model.moduleDocument()
38     self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY"))
39     self.myArc = self.mySketch.addEllipticArc(30, 20, 50, 30, 45, 40, 5, 6.11485435, False)
40     self.myLine = self.mySketch.addLine(10, 40, 40, 80)
41     self.myDOF = 11
42     model.do()
43     self.checkDOF()
44
45   def tearDown(self):
46     if self.myTestPassed:
47       self.assertArc(self.myArc)
48       self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
49       self.checkDOF()
50     model.end()
51
52   def checkDOF(self):
53     self.assertEqual(model.dof(self.mySketch), self.myDOF)
54
55   def toPeriod(self, theValue):
56     while theValue < -math.pi:
57       theValue += 2.0 * math.pi
58     while theValue >= math.pi:
59       theValue -= 2.0 * math.pi
60     return theValue
61
62   def checkMiddlePoint(self, thePoint, theArc):
63     self.myTestPassed = False
64     anEllipse = theArc.defaultResult().shape().edge().ellipse()
65     # check point on ellipse
66     self.checkPointOnEllipse(thePoint, anEllipse)
67     # check angles
68     TOLERANCE = 1.e-5
69     startPoint = GeomAPI_Pnt(theArc.startPoint().x(), theArc.startPoint().y(), 0)
70     isCalculated, startAngle = anEllipse.parameter(startPoint, TOLERANCE)
71     endPoint = GeomAPI_Pnt(theArc.endPoint().x(), theArc.endPoint().y(), 0)
72     isCalculated, endAngle = anEllipse.parameter(endPoint, TOLERANCE)
73     midPoint = GeomAPI_Pnt(thePoint.x(), thePoint.y(), 0)
74     isCalculated, midAngle = anEllipse.parameter(midPoint, TOLERANCE)
75     diffMS = self.toPeriod(midAngle - startAngle)
76     diffEM = self.toPeriod(endAngle - midAngle)
77     self.assertAlmostEqual(diffMS, diffEM)
78     self.assertEqual(diffMS < 0, theArc.reversed().value())
79     self.myTestPassed = True
80
81   def checkPointOnEllipse(self, theCoordinates, theEllipse):
82     point = GeomAPI_Pnt2d(theCoordinates.x(), theCoordinates.y())
83     firstFocus2d = GeomAPI_Pnt2d(theEllipse.firstFocus().x(), theEllipse.firstFocus().y())
84     distPF1 = model.distancePointPoint(firstFocus2d,  point)
85     secondFocus2d = GeomAPI_Pnt2d(theEllipse.secondFocus().x(), theEllipse.secondFocus().y())
86     distPF2 = model.distancePointPoint(secondFocus2d,  point)
87     if issubclass(type(theEllipse), SketchAPI_Ellipse):
88       majorRad = theEllipse.majorRadius().value()
89     else:
90       majorRad = theEllipse.majorRadius()
91     NB_DIGITS = 7 - math.floor(math.log10(majorRad))
92     self.assertAlmostEqual(distPF1 + distPF2, 2.0 * majorRad, NB_DIGITS)
93
94   def assertArc(self, theArc):
95     anEllipse = theArc.defaultResult().shape().edge().ellipse()
96     self.checkPointOnEllipse(theArc.startPoint(), anEllipse)
97     self.checkPointOnEllipse(theArc.endPoint(), anEllipse)
98
99   def rotatePoint(self, thePoint, theCenter, theAngle):
100     dirX = thePoint.x() - theCenter.x()
101     dirY = thePoint.y() - theCenter.y()
102     newX = theCenter.x() + dirX * math.cos(theAngle) - dirY * math.sin(theAngle)
103     newY = theCenter.y() + dirX * math.sin(theAngle) + dirY * math.cos(theAngle)
104     self.mySketch.move(thePoint, newX, newY)
105
106   def moveArc(self):
107     ANGLE_STEP = math.pi * 5.0 / 180.0
108     ANGLE_THRESHOLD = math.pi / 2.0
109     # move start point of the arc clockwise
110     fullAngle = 0.0
111     while fullAngle < ANGLE_THRESHOLD:
112       self.rotatePoint(self.myArc.startPoint(), self.myArc.center(), -ANGLE_STEP)
113       model.do()
114       self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
115       fullAngle += ANGLE_STEP
116     # move start point of the arc conterclockwise
117     fullAngle = 0.0
118     while fullAngle < ANGLE_THRESHOLD:
119       self.rotatePoint(self.myArc.startPoint(), self.myArc.center(), ANGLE_STEP)
120       model.do()
121       self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
122       fullAngle += ANGLE_STEP
123
124     # move end point of the arc clockwise
125     fullAngle = 0.0
126     while fullAngle < ANGLE_THRESHOLD:
127       self.rotatePoint(self.myArc.endPoint(), self.myArc.center(), -ANGLE_STEP)
128       model.do()
129       self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
130       fullAngle += ANGLE_STEP
131     # move end point of the arc conterclockwise
132     fullAngle = 0.0
133     while fullAngle < ANGLE_THRESHOLD:
134       self.rotatePoint(self.myArc.endPoint(), self.myArc.center(), ANGLE_STEP)
135       model.do()
136       self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
137       fullAngle += ANGLE_STEP
138
139     # move center of the arc
140     DELTA = [0.1, 0.1]
141     for i in range(0, 40):
142       if i == 10 or i == 30:
143         DELTA = [-DELTA[0], -DELTA[1]]
144       self.mySketch.move(self.myArc.center(), self.myArc.center().x() + DELTA[0], self.myArc.center().y() + DELTA[1])
145       model.do()
146       self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
147     DELTA = [-0.1, 0.1]
148     for i in range(0, 40):
149       if i == 10 or i == 30:
150         DELTA = [-DELTA[0], -DELTA[1]]
151       self.mySketch.move(self.myArc.center(), self.myArc.center().x() + DELTA[0], self.myArc.center().y() + DELTA[1])
152       model.do()
153       self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
154
155   def moveLine(self):
156     DELTA = [0.1, 0.0]
157     for i in range(0, 40):
158       if i == 10 or i == 30:
159         DELTA = [-DELTA[0], -DELTA[1]]
160       self.mySketch.move(self.myLine.startPoint(), self.myLine.startPoint().x() + DELTA[0], self.myLine.startPoint().y() + DELTA[1])
161       model.do()
162       self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
163     DELTA = [0.0, 0.1]
164     for i in range(0, 40):
165       if i == 10 or i == 30:
166         DELTA = [-DELTA[0], -DELTA[1]]
167       self.mySketch.move(self.myLine.startPoint(), self.myLine.startPoint().x() + DELTA[0], self.myLine.startPoint().y() + DELTA[1])
168       model.do()
169       self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
170
171
172   def test_middle_point_PA(self):
173     """ Test 1. Set middle point constraint (point is the first argument)
174     """
175     self.mySketch.setMiddlePoint(self.myLine.startPoint(), self.myArc.results()[-1])
176     self.myDOF -= 2
177     model.do()
178
179   def test_middle_point_AP(self):
180     """ Test 2. Set middle point constraint (point is the second argument)
181     """
182     self.mySketch.setMiddlePoint(self.myArc.results()[-1], self.myLine.startPoint())
183     self.myDOF -= 2
184     model.do()
185
186   def test_coincident_middle_point(self):
187     """ Test 3. Set middle point constraint for the point already coincident with the arc
188     """
189     self.mySketch.setCoincident(self.myLine.startPoint(), self.myArc.results()[-1])
190     model.do()
191     self.mySketch.setMiddlePoint(self.myLine.startPoint(), self.myArc.results()[-1])
192     self.myDOF -= 2
193     model.do()
194
195   def test_middle_point_coincident(self):
196     """ Test 4. Set concidence of the point and the arc which are already constrained with middle point
197     """
198     self.mySketch.setMiddlePoint(self.myLine.startPoint(), self.myArc.results()[-1])
199     model.do()
200     self.mySketch.setCoincident(self.myLine.startPoint(), self.myArc.results()[-1])
201     self.myDOF -= 2
202     model.do()
203
204   @unittest.expectedFailure
205   def test_middle_point_limitation(self):
206     """ Test 5. Check middle point fails if the point's coordinates are equal to the arc start point
207     """
208     self.myLine.startPoint().setValue(self.myArc.startPoint().pnt())
209     model.do()
210     coincidence = self.mySketch.setCoincident(self.myLine.startPoint(), self.myArc.results()[-1])
211     self.mySketch.setMiddlePoint(self.myLine.startPoint(), self.myArc.results()[-1])
212     self.myDOF -= 2
213     model.do()
214     # this check will fail due to the limitation of PlanGCS
215     self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
216
217   def test_middle_point_equal_start(self):
218     """ Test 6. Check middle point does not fail if the point's coordinates are equal to the arc end point
219     """
220     self.myLine.startPoint().setValue(self.myArc.endPoint().pnt())
221     model.do()
222     coincidence = self.mySketch.setCoincident(self.myLine.startPoint(), self.myArc.results()[-1])
223     self.mySketch.setMiddlePoint(self.myLine.startPoint(), self.myArc.results()[-1])
224     self.myDOF -= 2
225     model.do()
226
227   def test_middle_point_move_arc(self):
228     """ Test 7. Set middle point constraint and move arc
229     """
230     self.mySketch.setMiddlePoint(self.myLine.startPoint(), self.myArc.results()[-1])
231     self.myDOF -= 2
232     model.do()
233     self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
234     self.moveArc()
235
236   def test_middle_point_coincidence_move_arc(self):
237     """ Test 8. Set coincidence and middle point constraint and move arc
238     """
239     self.mySketch.setCoincident(self.myLine.startPoint(), self.myArc.results()[-1])
240     model.do()
241     self.mySketch.setMiddlePoint(self.myLine.startPoint(), self.myArc.results()[-1])
242     self.myDOF -= 2
243     model.do()
244     self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
245     self.moveArc()
246
247   def test_middle_point_move_line(self):
248     """ Test 9. Set middle point constraint and move line
249     """
250     self.mySketch.setMiddlePoint(self.myLine.startPoint(), self.myArc.results()[-1])
251     self.myDOF -= 2
252     model.do()
253     self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
254     self.moveLine()
255
256   def test_middle_point_coincidence_move_line(self):
257     """ Test 10. Set coincidence and middle point constraint and move line
258     """
259     self.mySketch.setCoincident(self.myLine.startPoint(), self.myArc.results()[-1])
260     model.do()
261     self.mySketch.setMiddlePoint(self.myLine.startPoint(), self.myArc.results()[-1])
262     self.myDOF -= 2
263     model.do()
264     self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
265     self.moveLine()
266
267   def test_remove_middle_point(self):
268     """ Test 11. Set and then remove middle point constraint
269     """
270     mp = self.mySketch.setMiddlePoint(self.myLine.startPoint(), self.myArc.results()[-1])
271     self.myDOF -= 2
272     model.do()
273     self.assertArc(self.myArc)
274     self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
275     self.checkDOF()
276     # remove middle point
277     self.myDocument.removeFeature(mp.feature())
278     self.myDOF += 2
279     model.do()
280     self.checkDOF()
281     # set flag False to avoid checking middle point constraint in tearDown() method
282     self.myTestPassed = False
283
284
285 if __name__ == "__main__":
286     test_program = unittest.main(exit=False)
287     assert test_program.result.wasSuccessful(), "Test failed"
288     assert(model.checkPythonDump())