Salome HOME
321e37ab9d87c0addd56d7a5d52bbec0d165fcc7
[modules/shaper.git] / src / SketchPlugin / Test / TestCreateCircleByThreePoints.py
1 ## Copyright (C) 2014-2017  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
18 ## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
19 ##
20
21 """
22     TestCreateCircleByThreePoints.py
23
24     Test creation methods of a circle built by three points
25 """
26
27 #=========================================================================
28 # Initialization of the test
29 #=========================================================================
30 from GeomDataAPI import *
31 from GeomAPI import *
32 from ModelAPI import *
33 from SketchAPI import SketchAPI_Sketch
34 from salome.shaper import model
35 import math
36
37 __updated__ = "2017-03-22"
38
39
40 #=========================================================================
41 # Auxiliary functions
42 #=========================================================================
43 TOLERANCE = 1.e-7
44
45 def verifyLastCircle(theSketch, theX, theY, theR):
46     """
47     subroutine to verify position of last circle in the sketch
48     """
49     aLastCircle = model.lastSubFeature(theSketch, "SketchCircle")
50     aCenter = geomDataAPI_Point2D(aLastCircle.attribute("circle_center"))
51     verifyPointCoordinates(aCenter, theX, theY)
52     aRadius = aLastCircle.real("circle_radius")
53     assert aRadius.value() == theR, "Wrong radius {0}, expected {1}".format(aRadius.value(), theR)
54
55 def verifyPointCoordinates(thePoint, theX, theY):
56     assert thePoint.x() == theX and thePoint.y() == theY, "Wrong '{0}' point ({1}, {2}), expected ({3}, {4})".format(thePoint.attributeType(), thePoint.x(), thePoint.y(), theX, theY)
57
58 def verifyPointOnCircle(thePoint, theCircle):
59     aCircleCenter = geomDataAPI_Point2D(theCircle.attribute("circle_center"))
60     aDistCP = model.distancePointPoint(aCircleCenter, thePoint)
61     aCircleRadius = theCircle.real("circle_radius").value()
62     assert math.fabs(aDistCP - aCircleRadius) < TOLERANCE, "Point is not on circle, distance: {0}, radius of circle: {1}".format(aDistCP, aCircleRadius)
63
64 def verifyTangentCircles(theCircle1, theCircle2):
65     aCenter1 = geomDataAPI_Point2D(theCircle1.attribute("circle_center"))
66     aCenter2 = geomDataAPI_Point2D(theCircle2.attribute("circle_center"))
67     aDistCC = model.distancePointPoint(aCenter1, aCenter2)
68     aRadius1 = theCircle1.real("circle_radius").value()
69     aRadius2 = theCircle2.real("circle_radius").value()
70     verifyTangentCircular(aDistCC, aRadius1, aRadius2)
71
72 def verifyTangentCircleArc(theCircle, theArc):
73     aCircleCenter = geomDataAPI_Point2D(theCircle.attribute("circle_center"))
74     anArcCenter = geomDataAPI_Point2D(theArc.attribute("center_point"))
75     anArcStart = geomDataAPI_Point2D(theArc.attribute("start_point"))
76     aDistCC = model.distancePointPoint(aCircleCenter, anArcCenter)
77     aCircleRadius = theCircle.real("circle_radius").value()
78     anArcRadius = model.distancePointPoint(anArcCenter, anArcStart)
79     verifyTangentCircular(aDistCC, aCircleRadius, anArcRadius)
80
81 def verifyTangentCircular(theDistBetweenCenters, theRadius1, theRadius2):
82     aRSum = theRadius1 + theRadius2
83     aRDiff = math.fabs(theRadius1 - theRadius2)
84     assert math.fabs(aRSum - theDistBetweenCenters) < TOLERANCE or math.fabs(aRDiff - theDistBetweenCenters) < TOLERANCE, "Two circulars are not tangent"
85
86 def verifyTangentCircleLine(theCircle, theLine):
87     aCenter = geomDataAPI_Point2D(theCircle.attribute("circle_center"))
88     aRadius = theCircle.real("circle_radius").value()
89     aDistCL = distancePointLine(aCenter, theLine)
90     assert math.fabs(aDistCL - aRadius) < TOLERANCE, "Circle and line are not tangent"
91
92 def distancePointLine(thePoint, theLine):
93     aLineStart = geomDataAPI_Point2D(theLine.attribute("StartPoint")).pnt().xy()
94     aLineEnd = geomDataAPI_Point2D(theLine.attribute("EndPoint")).pnt().xy()
95     aLineDir = aLineEnd.decreased(aLineStart)
96     aLineLen = aLineEnd.distance(aLineStart)
97     aPntDir = thePoint.pnt().xy().decreased(aLineStart)
98     return math.fabs(aPntDir.cross(aLineDir) / aLineLen)
99
100
101 #=========================================================================
102 # Start of test
103 #=========================================================================
104
105 aSession = ModelAPI_Session.get()
106 aDocument = aSession.moduleDocument()
107 #=========================================================================
108 # Creation of a sketch
109 #=========================================================================
110 aSession.startOperation()
111 aSketchCommonFeature = aDocument.addFeature("Sketch")
112 aSketchFeature = featureToCompositeFeature(aSketchCommonFeature)
113 origin = geomDataAPI_Point(aSketchFeature.attribute("Origin"))
114 origin.setValue(0, 0, 0)
115 dirx = geomDataAPI_Dir(aSketchFeature.attribute("DirX"))
116 dirx.setValue(1, 0, 0)
117 norm = geomDataAPI_Dir(aSketchFeature.attribute("Norm"))
118 norm.setValue(0, 0, 1)
119 aSession.finishOperation()
120 aSketch = SketchAPI_Sketch(aSketchFeature)
121
122 #=========================================================================
123 # Test 1. Create a circle by three points
124 #=========================================================================
125 expectedCenter = [0., 0.]
126 expectedRadius = 10.
127 aSession.startOperation()
128 aCircle = aSketchFeature.addFeature("SketchMacroCircle")
129 assert (aCircle.getKind() == "SketchMacroCircle")
130 aCirclePnt1 = geomDataAPI_Point2D(aCircle.attribute("first_point"))
131 aCirclePnt2 = geomDataAPI_Point2D(aCircle.attribute("second_point"))
132 aCirclePnt3 = geomDataAPI_Point2D(aCircle.attribute("third_point"))
133 assert (not aCirclePnt1.isInitialized())
134 assert (not aCirclePnt2.isInitialized())
135 assert (not aCirclePnt3.isInitialized())
136 aCircleType = aCircle.string("circle_type")
137 assert (not aCircleType.isInitialized())
138 aCircleType.setValue("circle_type_by_three_points")
139 aCirclePnt1.setValue(expectedCenter[0] - expectedRadius, expectedCenter[1])
140 aCirclePnt2.setValue(expectedCenter[0] + expectedRadius, expectedCenter[1])
141 aCirclePnt3.setValue(expectedCenter[0], expectedCenter[1] + expectedRadius)
142 aSession.finishOperation()
143 assert (aSketchFeature.numberOfSubs() == 1)
144 verifyLastCircle(aSketchFeature, expectedCenter[0], expectedCenter[1], expectedRadius)
145
146 #=========================================================================
147 # Test 2. Create a circle by three points coincident to other points
148 #=========================================================================
149 # get previous circle
150 aPrevCircle = model.lastSubFeature(aSketchFeature, "SketchCircle")
151 aPrevCenter = geomDataAPI_Point2D(aPrevCircle.attribute("circle_center"))
152 aPrevCenterXY = [aPrevCenter.x(), aPrevCenter.y()]
153 aPrevCircleRadius = aPrevCircle.real("circle_radius").value()
154 # create additional point and line
155 aPointCoordinates = [5., 20.]
156 aLineStart = [10., 0.]
157 aLineEnd = [10., 50.]
158 aSession.startOperation()
159 aPoint = aSketchFeature.addFeature("SketchPoint")
160 aPointCoord = geomDataAPI_Point2D(aPoint.attribute("PointCoordinates"))
161 aPointCoord.setValue(aPointCoordinates[0], aPointCoordinates[1])
162 aLine = aSketchFeature.addFeature("SketchLine")
163 aStartPnt = geomDataAPI_Point2D(aLine.attribute("StartPoint"))
164 aStartPnt.setValue(aLineStart[0], aLineStart[1])
165 aEndPnt = geomDataAPI_Point2D(aLine.attribute("EndPoint"))
166 aEndPnt.setValue(aLineEnd[0], aLineEnd[1])
167 aSession.finishOperation()
168 # create new circle
169 aSession.startOperation()
170 aCircle = aSketchFeature.addFeature("SketchMacroCircle")
171 aCirclePnt1 = geomDataAPI_Point2D(aCircle.attribute("first_point"))
172 aCirclePnt2 = geomDataAPI_Point2D(aCircle.attribute("second_point"))
173 aCirclePnt3 = geomDataAPI_Point2D(aCircle.attribute("third_point"))
174 aCirclePnt1Ref = aCircle.refattr("first_point_ref")
175 aCirclePnt2Ref = aCircle.refattr("second_point_ref")
176 aCirclePnt3Ref = aCircle.refattr("third_point_ref")
177 aCircleType = aCircle.string("circle_type")
178 # initialize attributes
179 aCircleType.setValue("circle_type_by_three_points")
180 aCirclePnt1Ref.setAttr(aPrevCenter)
181 aCirclePnt1.setValue(aPrevCenter.pnt())
182 aCirclePnt2Ref.setObject(aPoint.lastResult())
183 aCirclePnt2.setValue(aPointCoord.pnt())
184 aCirclePnt3Ref.setAttr(aStartPnt)
185 aCirclePnt3.setValue(aLineStart[0], aLineStart[1])
186 aSession.finishOperation()
187 assert (aSketchFeature.numberOfSubs() == 7)
188 # check the points do not change their positions
189 verifyPointCoordinates(aPrevCenter, aPrevCenterXY[0], aPrevCenterXY[1])
190 verifyPointCoordinates(aPointCoord, aPointCoordinates[0], aPointCoordinates[1])
191 verifyPointCoordinates(aStartPnt, aLineStart[0], aLineStart[1])
192 # check newly created circle passes through the points
193 aCircle = model.lastSubFeature(aSketchFeature, "SketchCircle")
194 verifyPointOnCircle(aPrevCenter, aCircle)
195 verifyPointOnCircle(aPointCoord, aCircle)
196 verifyPointOnCircle(aStartPnt, aCircle)
197 model.testNbSubFeatures(aSketch, "SketchConstraintCoincidence", 3)
198 model.testNbSubFeatures(aSketch, "SketchConstraintTangent", 0)
199
200 #=========================================================================
201 # Test 3. Create a circle by three points and tangent to line, circle and arc
202 #=========================================================================
203 # create additional arc
204 anArcRadius = 5.
205 anArcCenter = [-10., 10.]
206 anArcStart = [anArcCenter[0], anArcCenter[1] - anArcRadius]
207 anArcEnd = [anArcCenter[0], anArcCenter[1] + anArcRadius]
208 aSession.startOperation()
209 anArc = aSketchFeature.addFeature("SketchArc")
210 anArcCenterPnt = geomDataAPI_Point2D(anArc.attribute("center_point"))
211 anArcCenterPnt.setValue(anArcCenter[0], anArcCenter[1])
212 anArcStartPnt = geomDataAPI_Point2D(anArc.attribute("start_point"))
213 anArcStartPnt.setValue(anArcStart[0], anArcStart[1])
214 anArcEndPnt = geomDataAPI_Point2D(anArc.attribute("end_point"))
215 anArcEndPnt.setValue(anArcEnd[0], anArcEnd[1])
216 aSession.finishOperation()
217 # create new circle
218 aSession.startOperation()
219 aCircle = aSketchFeature.addFeature("SketchMacroCircle")
220 aCirclePnt1 = geomDataAPI_Point2D(aCircle.attribute("first_point"))
221 aCirclePnt2 = geomDataAPI_Point2D(aCircle.attribute("second_point"))
222 aCirclePnt3 = geomDataAPI_Point2D(aCircle.attribute("third_point"))
223 aCirclePnt1Ref = aCircle.refattr("first_point_ref")
224 aCirclePnt2Ref = aCircle.refattr("second_point_ref")
225 aCirclePnt3Ref = aCircle.refattr("third_point_ref")
226 aCircleType = aCircle.string("circle_type")
227 # initialize attributes
228 aCircleType.setValue("circle_type_by_three_points")
229 aCirclePnt1Ref.setObject(aPrevCircle.lastResult())
230 aCirclePnt1.setValue(aPrevCenter.x(), aPrevCenter.y() + aPrevCircleRadius)
231 aCirclePnt2Ref.setObject(aLine.lastResult())
232 aCirclePnt2.setValue(aLineEnd[0], aLineEnd[1])
233 aCirclePnt3Ref.setObject(anArc.lastResult())
234 aCirclePnt3.setValue(anArcCenter[0] + anArcRadius, anArcCenter[1])
235 aSession.finishOperation()
236 assert (aSketchFeature.numberOfSubs() == 12)
237 # check the tangent entities do not change their positions
238 verifyPointCoordinates(aPrevCenter, aPrevCenterXY[0], aPrevCenterXY[1])
239 assert (aPrevCircle.real("circle_radius").value() == aPrevCircleRadius)
240 verifyPointCoordinates(aStartPnt, aLineStart[0], aLineStart[1])
241 verifyPointCoordinates(aEndPnt, aLineEnd[0], aLineEnd[1])
242 verifyPointCoordinates(anArcCenterPnt, anArcCenter[0], anArcCenter[1])
243 verifyPointCoordinates(anArcStartPnt, anArcStart[0], anArcStart[1])
244 verifyPointCoordinates(anArcEndPnt, anArcEnd[0], anArcEnd[1])
245 # check newly created circle passes through the points
246 aCircle = model.lastSubFeature(aSketchFeature, "SketchCircle")
247 verifyTangentCircles(aCircle, aPrevCircle)
248 verifyTangentCircleArc(aCircle, anArc)
249 verifyTangentCircleLine(aCircle, aLine)
250 model.testNbSubFeatures(aSketch, "SketchConstraintCoincidence", 3)
251 model.testNbSubFeatures(aSketch, "SketchConstraintTangent", 3)
252
253 #=========================================================================
254 # Test 4. Create a circle by three points:
255 #         a. first two points are coincident to extremities of the line
256 #         b. check that this line is not selectable by third point
257 #=========================================================================
258 aSession.startOperation()
259 aCircle = aSketchFeature.addFeature("SketchMacroCircle")
260 aCirclePnt1 = geomDataAPI_Point2D(aCircle.attribute("first_point"))
261 aCirclePnt2 = geomDataAPI_Point2D(aCircle.attribute("second_point"))
262 aCirclePnt3 = geomDataAPI_Point2D(aCircle.attribute("third_point"))
263 aCirclePnt1Ref = aCircle.refattr("first_point_ref")
264 aCirclePnt2Ref = aCircle.refattr("second_point_ref")
265 aCirclePnt3Ref = aCircle.refattr("third_point_ref")
266 aCircleType = aCircle.string("circle_type")
267 # initialize attributes
268 aCircleType.setValue("circle_type_by_three_points")
269 aCirclePnt1Ref.setAttr(aStartPnt)
270 aCirclePnt1.setValue(aStartPnt.pnt())
271 aCirclePnt2Ref.setAttr(aEndPnt)
272 aCirclePnt2.setValue(aEndPnt.pnt())
273 aCirclePnt3Ref.setObject(aLine.lastResult())
274 aCirclePnt3.setValue(aLineEnd[0], aLineEnd[1])
275 aSession.finishOperation()
276 aLastFeature = aSketchFeature.subFeature(aSketchFeature.numberOfSubs() - 1)
277 assert aLastFeature.getKind() == "SketchMacroCircle", "ERROR: SketchMacroCircle has NOT expected to be valid"
278 aDocument.removeFeature(aCircle)
279 assert (aSketchFeature.numberOfSubs() == 12)
280
281 #=========================================================================
282 # Test 5. Create a circle by three points:
283 #         a. first two points are placed on both sides from line
284 #         b. check that this line is not selectable by third point
285 #=========================================================================
286 aDistanceFromLine = 20.
287 aSession.startOperation()
288 aCircle = aSketchFeature.addFeature("SketchMacroCircle")
289 aCirclePnt1 = geomDataAPI_Point2D(aCircle.attribute("first_point"))
290 aCirclePnt2 = geomDataAPI_Point2D(aCircle.attribute("second_point"))
291 aCirclePnt3 = geomDataAPI_Point2D(aCircle.attribute("third_point"))
292 aCirclePnt1Ref = aCircle.refattr("first_point_ref")
293 aCirclePnt2Ref = aCircle.refattr("second_point_ref")
294 aCirclePnt3Ref = aCircle.refattr("third_point_ref")
295 aCircleType = aCircle.string("circle_type")
296 # initialize attributes
297 aCircleType.setValue("circle_type_by_three_points")
298 aCirclePnt1.setValue(aLineStart[0] + aDistanceFromLine, aLineStart[1])
299 aCirclePnt2.setValue(aLineStart[0] - aDistanceFromLine, aLineStart[1])
300 aCirclePnt3Ref.setObject(aLine.lastResult())
301 aCirclePnt3.setValue(aLineEnd[0], aLineEnd[1])
302 aSession.finishOperation()
303 aLastFeature = aSketchFeature.subFeature(aSketchFeature.numberOfSubs() - 1)
304 assert aLastFeature.getKind() == "SketchMacroCircle", "ERROR: SketchMacroCircle has NOT expected to be valid"
305 aDocument.removeFeature(aCircle)
306 assert (aSketchFeature.numberOfSubs() == 12)
307
308 #=========================================================================
309 # End of test
310 #=========================================================================
311
312 from salome.shaper import model
313 assert(model.checkPythonDump())