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