Salome HOME
Issue #2561: CEA 2018-1 Cut
[modules/shaper.git] / src / PythonAPI / model / tests / tests.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 from GeomAlgoAPI import *
22 from GeomAPI import *
23 from GeomDataAPI import *
24 from ModelAPI import ModelAPI_Feature
25 import math
26 from salome.shaper.model import sketcher
27
28 TOLERANCE = 1.e-7
29
30 aShapeTypes = {
31   GeomAPI_Shape.SOLID:  "GeomAPI_Shape.SOLID",
32   GeomAPI_Shape.FACE:   "GeomAPI_Shape.FACE",
33   GeomAPI_Shape.EDGE:   "GeomAPI_Shape.EDGE",
34   GeomAPI_Shape.VERTEX: "GeomAPI_Shape.VERTEX"}
35
36
37 def generateTests(theFeature, theFeatureName, theTestsList = []):
38   """ Generates tests for theFeature.
39   :param theFeature: feature to test. Should be ModelHighAPI_Interface.
40   :param theFeatureName: feature name to put in test commands.
41   :param theTestsList: list of test to be generated. If empty generates all tests.
42   """
43   if "testNbResults" in theTestsList or len(theTestsList) == 0:
44     aNbResults = len(theFeature.results())
45     print "model.testNbResults({}, {})".format(theFeatureName, aNbResults)
46
47   if "testNbSubResults" in theTestsList or len(theTestsList) == 0:
48     aNbResults = len(theFeature.results())
49     aNbSubResults = []
50     for anIndex in range(0, aNbResults):
51       aNbSubResults.append(theFeature.results()[anIndex].numberOfSubs())
52     print "model.testNbSubResults({}, {})".format(theFeatureName, aNbSubResults)
53
54   if "testNbSubShapes" in theTestsList or len(theTestsList) == 0:
55     aNbResults = len(theFeature.results())
56     for aShapeType in aShapeTypes:
57       aNbSubShapes = []
58       for anIndex in range(0, aNbResults):
59         aShape = theFeature.results()[anIndex].resultSubShapePair()[0].shape()
60         aNbResultSubShapes = 0
61         aShapeExplorer = GeomAPI_ShapeExplorer(aShape, aShapeType)
62         while aShapeExplorer.more():
63           aNbResultSubShapes += 1
64           aShapeExplorer.next();
65         aNbSubShapes.append(aNbResultSubShapes)
66       print "model.testNbSubShapes({}, {}, {})".format(theFeatureName, aShapeTypes[aShapeType], aNbSubShapes)
67
68   if "testResultsVolumes" in theTestsList or len(theTestsList) == 0:
69     aNbResults = len(theFeature.results())
70     aResultsVolumes = []
71     for anIndex in range(0, aNbResults):
72       aResultsVolumes.append(GeomAlgoAPI_ShapeTools_volume(theFeature.results()[anIndex].resultSubShapePair()[0].shape()))
73     print "model.testResultsVolumes({}, [{}])".format(theFeatureName, ", ".join("{:0.27f}".format(i) for i in aResultsVolumes))
74
75
76 def testNbResults(theFeature, theExpectedNbResults):
77   """ Tests number of feature results.
78   :param theFeature: feature to test.
79   :param theExpectedNbResults: expected number of results.
80   """
81   aNbResults = len(theFeature.results())
82   assert (aNbResults == theExpectedNbResults), "Number of results: {}. Expected: {}.".format(aNbResults, theExpectedNbResults)
83
84
85 def testNbSubResults(theFeature, theExpectedNbSubResults):
86   """ Tests number of feature sub-results for each result.
87   :param theFeature: feature to test.
88   :param theExpectedNbSubResults: list of sub-results numbers. Size of list should be equal to len(theFeature.results()).
89   """
90   aNbResults = len(theFeature.results())
91   aListSize = len(theExpectedNbSubResults)
92   assert (aNbResults == aListSize), "Number of results: {} not equal to list size: {}.".format(aNbResults, aListSize)
93   for anIndex in range(0, aNbResults):
94     aNbSubResults = theFeature.results()[anIndex].numberOfSubs()
95     anExpectedNbSubResults = theExpectedNbSubResults[anIndex]
96     assert (aNbSubResults == anExpectedNbSubResults), "Number of sub-results for result[{}]: {}. Expected: {}.".format(anIndex, aNbSubResults, anExpectedNbSubResults)
97
98
99 def testNbSubShapes(theFeature, theShapeType, theExpectedNbSubShapes):
100   """ Tests number of feature sub-shapes of passed type for each result.
101   :param theFeature: feature to test.
102   :param theShapeType: shape type of sub-shapes to test.
103   :param theExpectedNbSubShapes: list of sub-shapes numbers. Size of list should be equal to len(theFeature.results()).
104   """
105   aNbResults = len(theFeature.results())
106   aListSize = len(theExpectedNbSubShapes)
107   assert (aNbResults == aListSize), "Number of results: {} not equal to list size: {}.".format(aNbResults, aListSize)
108   for anIndex in range(0, aNbResults):
109     aNbResultSubShapes = 0
110     anExpectedNbSubShapes = theExpectedNbSubShapes[anIndex]
111     aShape = theFeature.results()[anIndex].resultSubShapePair()[0].shape()
112     aShapeExplorer = GeomAPI_ShapeExplorer(aShape, theShapeType)
113     while aShapeExplorer.more():
114       aNbResultSubShapes += 1
115       aShapeExplorer.next();
116     assert (aNbResultSubShapes == anExpectedNbSubShapes), "Number of sub-shapes of type {} for result[{}]: {}. Expected: {}.".format(aShapeTypes[theShapeType], anIndex, aNbResultSubShapes, anExpectedNbSubShapes)
117
118
119 def testResultsVolumes(theFeature, theExpectedResultsVolumes, theNbSignificantDigits = 7):
120   """ Tests results volumes.
121   :param theFeature: feature to test.
122   :param theExpectedResultsVolumes: list of results volumes. Size of list should be equal to len(theFeature.results()).
123   """
124   aTolerance = 10**(-theNbSignificantDigits)
125   aNbResults = len(theFeature.results())
126   aListSize = len(theExpectedResultsVolumes)
127   assert (aNbResults == aListSize), "Number of results: {} not equal to list size: {}.".format(aNbResults, aListSize)
128   for anIndex in range(0, aNbResults):
129     aResultVolume = GeomAlgoAPI_ShapeTools_volume(theFeature.results()[anIndex].resultSubShapePair()[0].shape())
130     aResultVolumeStr = "{:0.27f}".format(aResultVolume).lstrip("0").lstrip(".").lstrip("0")
131     anExpectedResultVolume = theExpectedResultsVolumes[anIndex]
132     anExpectedResultVolumeStr = "{:0.27f}".format(anExpectedResultVolume).lstrip("0").lstrip(".").lstrip("0")
133     assert math.fabs(aResultVolume - anExpectedResultVolume) < aTolerance * anExpectedResultVolume, "Volume of result[{}]: {:0.27f}. Expected: {:0.27f}. The first {} significant digits not equal.".format(anIndex, aResultVolume, anExpectedResultVolume, theNbSignificantDigits)
134
135 def testHaveNamingFaces(theFeature, theModel, thePartDoc) :
136   """ Tests if all faces of result have a name
137   :param theFeature: feature to test.
138   """
139   # open transaction since all the checking are performed in tests after model.end() call
140   theModel.begin()
141   # Get feature result/sub-result
142   aResult = theFeature.results()[0].resultSubShapePair()[0]
143   # Get result/sub-result shape
144   shape = aResult.shape()
145   # Create shape explorer with desired shape type
146   shapeExplorer = GeomAPI_ShapeExplorer(shape, GeomAPI_Shape.FACE)
147   # Create list, and store selections in it
148   selectionList = []
149   while shapeExplorer.more():
150     selection = theModel.selection(aResult, shapeExplorer.current()) # First argument should be result/sub-result, second is sub-shape on this result/sub-result
151     selectionList.append(selection)
152     shapeExplorer.next()
153   # Create group with this selection list
154   Group_1 = theModel.addGroup(thePartDoc, selectionList)
155   theModel.end()
156
157   # Now you can check that all selected shapes in group have right shape type and name.
158   groupFeature = Group_1.feature()
159   groupSelectionList = groupFeature.selectionList("group_list")
160   assert(groupSelectionList.size() == len(selectionList))
161   for index in range(0, groupSelectionList.size()):
162     attrSelection = groupSelectionList.value(index)
163     shape = attrSelection.value()
164     name = attrSelection.namingName()
165     assert(shape.isFace())
166     assert(name != ""), "String empty"
167
168 def testHaveNamingEdges(theFeature, theModel, thePartDoc) :
169   """ Tests if all edges of result have a name
170   :param theFeature: feature to test.
171   """
172   # Get feature result/sub-result
173   aResult = theFeature.results()[0].resultSubShapePair()[0]
174   # Get result/sub-result shape
175   shape = aResult.shape()
176   # Create shape explorer with desired shape type
177   shapeExplorer = GeomAPI_ShapeExplorer(shape, GeomAPI_Shape.EDGE)
178   # Create list, and store selections in it
179   selectionList = []
180   while shapeExplorer.more():
181     selection = theModel.selection(aResult, shapeExplorer.current()) # First argument should be result/sub-result, second is sub-shape on this result/sub-result
182     selectionList.append(selection)
183     shapeExplorer.next()
184   # Create group with this selection list
185   Group_1 = theModel.addGroup(thePartDoc, selectionList)
186   theModel.do()
187   theModel.end()
188
189   # Now you can check that all selected shapes in group have right shape type and name.
190   groupFeature = Group_1.feature()
191   groupSelectionList = groupFeature.selectionList("group_list")
192   theModel.end()
193   assert(groupSelectionList.size() == len(selectionList))
194   for index in range(0, groupSelectionList.size()):
195     attrSelection = groupSelectionList.value(index)
196     shape = attrSelection.value()
197     name = attrSelection.namingName()
198     assert(shape.isEdge())
199     assert(name != ""), "String empty"
200
201 def testHaveNamingByType(theFeature, theModel, thePartDoc, theSubshapeType) :
202   """ Tests if all sub-shapes of result have a unique name
203   :param theFeature: feature to test.
204   :param theSubshapeType: type of sub-shape
205   """
206   if not theFeature.results():
207     return
208   aFirstRes = theFeature.results()[0]
209   # Get number of sub-results
210   hasSubs = True
211   nbSubs = aFirstRes.numberOfSubs()
212   if nbSubs == 0:
213     # no sub-results => treat current result as a sub
214     hasSubs = False
215     nbSubs = 1
216
217   selectionList = []
218   shapesList = [] # to append only unique shapes (not isSame)
219   for sub in range(0, nbSubs):
220     # Get feature result/sub-result
221     if hasSubs:
222       aResult = aFirstRes.subResult(sub).resultSubShapePair()[0]
223     else:
224       aResult = aFirstRes.resultSubShapePair()[0]
225     # Get result/sub-result shape
226     shape = aResult.shape()
227     # Create shape explorer with desired shape type
228     shapeExplorer = GeomAPI_ShapeExplorer(shape, theSubshapeType)
229     # Create list, and store selections in it
230     while shapeExplorer.more():
231       current = shapeExplorer.current()
232       if current.isEdge() and GeomAPI.GeomAPI_Edge(current).isDegenerated(): # skip degenerative edges because they are not selected
233         shapeExplorer.next()
234         continue
235       aDuplicate = False
236       for alreadyThere in shapesList:
237         if alreadyThere.isSame(current):
238           aDuplicate = True
239       if aDuplicate:
240         shapeExplorer.next()
241         continue
242       shapesList.append(current)
243       selection = theModel.selection(aResult, current) # First argument should be result/sub-result, second is sub-shape on this result/sub-result
244       selectionList.append(selection)
245       shapeExplorer.next()
246   # Create group with this selection list
247   # (do not create group if nothing is selected)
248   if (len(selectionList) == 0):
249     return
250   Group_1 = theModel.addGroup(thePartDoc, selectionList)
251   theModel.do()
252
253   groupSelectionList = Group_1.feature().selectionList("group_list")
254   assert(groupSelectionList.size() == len(selectionList))
255
256   # Check that all selected shapes in group have right shape type and unique name.
257   checkGroup(Group_1, theSubshapeType)
258
259 def testHaveNamingSubshapes(theFeature, theModel, thePartDoc) :
260   """ Tests if all vertices/edges/faces of result have a unique name
261   :param theFeature: feature to test.
262   """
263   testHaveNamingByType(theFeature, theModel, thePartDoc, GeomAPI_Shape.VERTEX)
264   testHaveNamingByType(theFeature, theModel, thePartDoc, GeomAPI_Shape.EDGE)
265   testHaveNamingByType(theFeature, theModel, thePartDoc, GeomAPI_Shape.FACE)
266
267 def testNbSubFeatures(theComposite, theKindOfSub, theExpectedCount):
268   """ Tests number of sub-features of the given type
269   :param theComposite     composite feature to check its subs
270   :param theKindOfSub     kind of sub-feature to calculate count
271   :param theExpectedCount expected number of sub-features
272   """
273   count = 0
274   for aSub in theComposite.features().list():
275     aFeature = ModelAPI_Feature.feature(aSub)
276     if aFeature is not None and aFeature.getKind() == theKindOfSub:
277        count += 1
278   assert (count == theExpectedCount), "Number of sub-features of type {}: {}, expected {}".format(theKindOfSub, count, theExpectedCount)
279
280 def assertSketchArc(theArcFeature):
281   """ Tests whether the arc is correctly defined
282   """
283   aCenterPnt = geomDataAPI_Point2D(theArcFeature.attribute("center_point"))
284   aStartPnt = geomDataAPI_Point2D(theArcFeature.attribute("start_point"))
285   aEndPnt = geomDataAPI_Point2D(theArcFeature.attribute("end_point"))
286   aRadius = theArcFeature.real("radius")
287   aDistCS = sketcher.tools.distancePointPoint(aCenterPnt, aStartPnt)
288   aDistCE = sketcher.tools.distancePointPoint(aCenterPnt, aEndPnt)
289   assert math.fabs(aDistCS - aDistCE) < TOLERANCE, "Wrong arc: center-start distance {}, center-end distance {}".format(aDistCS, aDistCE)
290   assert math.fabs(aRadius.value() -aDistCS) < TOLERANCE, "Wrong arc: radius is {0}, expected {1}".format(aRadius.value(), aDistCS)
291
292 def checkResult(theFeature,theModel,NbRes,NbSubRes,NbSolid,NbFace,NbEdge,NbVertex):
293   """ Tests numbers of sub-shapes in results
294   """
295   theModel.testNbResults(theFeature, NbRes)
296   theModel.testNbSubResults(theFeature, NbSubRes)
297   theModel.testNbSubShapes(theFeature, GeomAPI_Shape.SOLID, NbSolid)
298   theModel.testNbSubShapes(theFeature, GeomAPI_Shape.FACE, NbFace)
299   theModel.testNbSubShapes(theFeature, GeomAPI_Shape.EDGE, NbEdge)
300   theModel.testNbSubShapes(theFeature, GeomAPI_Shape.VERTEX, NbVertex)
301
302 def checkSketch(theSketch, theDOF = -1):
303   """ Tests the sketch is valid and DoF is equal to the given
304   """
305   assert(theSketch.feature().error() == ""), "Sketch failed: {}".format(theSketch.feature().error())
306   assert(theSketch.solverError().value() == ""), "Sketch solver failed: {}".format(theSketch.solverError().value())
307   if theDOF != -1:
308     aDOF = sketcher.tools.dof(theSketch)
309     assert(aDOF == theDOF), "Sketch DoF {} is wrong. Expected {}".format(aDOF, theDOF)
310
311 def checkGroup(theGroup, theShapeType):
312   """ Check that all selected shapes in group have correct shape type and unique name
313   """
314   groupFeature = theGroup.feature()
315   groupSelectionList = groupFeature.selectionList("group_list")
316   presented_names = set()
317   for index in range(0, groupSelectionList.size()):
318     attrSelection = groupSelectionList.value(index)
319     shape = attrSelection.value()
320     name = attrSelection.namingName()
321     if theShapeType == GeomAPI_Shape.VERTEX:
322       assert(shape.isVertex())
323     elif theShapeType == GeomAPI_Shape.EDGE:
324       assert(shape.isEdge())
325     elif theShapeType == GeomAPI_Shape.FACE:
326       assert(shape.isFace())
327     assert(name != ""), "String empty"
328     presented_names.add(name)
329   assert(len(presented_names) == groupSelectionList.size()), "Some names are not unique"