Salome HOME
Allow creating smeshBuilder before geomBuilder
[modules/smesh.git] / src / SMESH_SWIG / smeshBuilder.py
1 # Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
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 #  File   : smeshBuilder.py
20 #  Author : Francis KLOSS, OCC
21 #  Module : SMESH
22
23 import salome
24 from salome.geom import geomBuilder
25
26 import SMESH # This is necessary for back compatibility
27 import omniORB                                   # back compatibility
28 SMESH.MED_V2_1 = omniORB.EnumItem("MED_V2_1", 0) # back compatibility
29 SMESH.MED_V2_2 = omniORB.EnumItem("MED_V2_2", 1) # back compatibility
30
31 from   SMESH import *
32 from   salome.smesh.smesh_algorithm import Mesh_Algorithm
33
34 import SALOME
35 import SALOMEDS
36 import os
37 import inspect
38
39 # In case the omniORBpy EnumItem class does not fully support Python 3
40 # (for instance in version 4.2.1-2), the comparison ordering methods must be
41 # defined
42 #
43 try:
44     SMESH.Entity_Triangle < SMESH.Entity_Quadrangle
45 except TypeError:
46     def enumitem_eq(self, other):
47         try:
48             if isinstance(other, omniORB.EnumItem):
49                 if other._parent_id == self._parent_id:
50                     return self._v == other._v
51                 else:
52                     return self._parent_id == other._parent_id
53             else:
54                 return id(self) == id(other)
55         except:
56             return id(self) == id(other)
57
58     def enumitem_lt(self, other):
59         try:
60             if isinstance(other, omniORB.EnumItem):
61                 if other._parent_id == self._parent_id:
62                     return self._v < other._v
63                 else:
64                     return self._parent_id < other._parent_id
65             else:
66                 return id(self) < id(other)
67         except:
68             return id(self) < id(other)
69
70     def enumitem_le(self, other):
71         try:
72             if isinstance(other, omniORB.EnumItem):
73                 if other._parent_id == self._parent_id:
74                     return self._v <= other._v
75                 else:
76                     return self._parent_id <= other._parent_id
77             else:
78                 return id(self) <= id(other)
79         except:
80             return id(self) <= id(other)
81
82     def enumitem_gt(self, other):
83         try:
84             if isinstance(other, omniORB.EnumItem):
85                 if other._parent_id == self._parent_id:
86                     return self._v > other._v
87                 else:
88                     return self._parent_id > other._parent_id
89             else:
90                 return id(self) > id(other)
91         except:
92             return id(self) > id(other)
93
94     def enumitem_ge(self, other):
95         try:
96             if isinstance(other, omniORB.EnumItem):
97                 if other._parent_id == self._parent_id:
98                     return self._v >= other._v
99                 else:
100                     return self._parent_id >= other._parent_id
101             else:
102                 return id(self) >= id(other)
103         except:
104             return id(self) >= id(other)
105
106     omniORB.EnumItem.__eq__ = enumitem_eq
107     omniORB.EnumItem.__lt__ = enumitem_lt
108     omniORB.EnumItem.__le__ = enumitem_le
109     omniORB.EnumItem.__gt__ = enumitem_gt
110     omniORB.EnumItem.__ge__ = enumitem_ge
111
112
113 class MeshMeta(type):
114     """Private class used to workaround a problem that sometimes isinstance(m, Mesh) returns False
115     """
116     def __instancecheck__(cls, inst):
117         """Implement isinstance(inst, cls)."""
118         return any(cls.__subclasscheck__(c)
119                    for c in {type(inst), inst.__class__})
120
121     def __subclasscheck__(cls, sub):
122         """Implement issubclass(sub, cls)."""
123         return type.__subclasscheck__(cls, sub) or (cls.__name__ == sub.__name__ and cls.__module__ == sub.__module__)
124
125 def DegreesToRadians(AngleInDegrees):
126     """Convert an angle from degrees to radians
127     """
128     from math import pi
129     return AngleInDegrees * pi / 180.0
130
131 import salome_notebook
132 notebook = salome_notebook.notebook
133 # Salome notebook variable separator
134 var_separator = ":"
135
136 def ParseParameters(*args):
137     """
138     Return list of variable values from salome notebook.
139     The last argument, if is callable, is used to modify values got from notebook
140     """
141     Result = []
142     Parameters = ""
143     hasVariables = False
144     varModifFun=None
145     if args and callable(args[-1]):
146         args, varModifFun = args[:-1], args[-1]
147     for parameter in args:
148
149         Parameters += str(parameter) + var_separator
150
151         if isinstance(parameter,str):
152             # check if there is an inexistent variable name
153             if not notebook.isVariable(parameter):
154                 raise ValueError("Variable with name '" + parameter + "' doesn't exist!!!")
155             parameter = notebook.get(parameter)
156             hasVariables = True
157             if varModifFun:
158                 parameter = varModifFun(parameter)
159                 pass
160             pass
161         Result.append(parameter)
162
163         pass
164     Parameters = Parameters[:-1]
165     Result.append( Parameters )
166     Result.append( hasVariables )
167     return Result
168
169 def ParseAngles(*args):
170     """
171     Parse parameters while converting variables to radians
172     """
173     return ParseParameters( *( args + (DegreesToRadians, )))
174
175 def __initPointStruct(point,*args):
176     """
177     Substitute PointStruct.__init__() to create SMESH.PointStruct using notebook variables.
178     Parameters are stored in PointStruct.parameters attribute
179     """
180     point.x, point.y, point.z, point.parameters,hasVars = ParseParameters(*args)
181     pass
182 SMESH.PointStruct.__init__ = __initPointStruct
183
184 def __initAxisStruct(ax,*args):
185     """
186     Substitute AxisStruct.__init__() to create SMESH.AxisStruct using notebook variables.
187     Parameters are stored in AxisStruct.parameters attribute
188     """
189     if len( args ) != 6:
190         raise RuntimeError("Bad nb args (%s) passed in SMESH.AxisStruct(x,y,z,dx,dy,dz)"%(len( args )))
191     ax.x, ax.y, ax.z, ax.vx, ax.vy, ax.vz, ax.parameters,hasVars = ParseParameters(*args)
192     pass
193 SMESH.AxisStruct.__init__ = __initAxisStruct
194
195 smeshPrecisionConfusion = 1.e-07
196 def IsEqual(val1, val2, tol=smeshPrecisionConfusion):
197     """Compare real values using smeshPrecisionConfusion as tolerance
198     """
199     if abs(val1 - val2) < tol:
200         return True
201     return False
202
203 NO_NAME = "NoName"
204
205 def GetName(obj):
206     """
207     Return a name of an object
208     
209     Returns:
210         object name
211     """
212     if obj:
213         # object not null
214         if isinstance(obj, SALOMEDS._objref_SObject):
215             # study object
216             return obj.GetName()
217         try:
218             ior  = salome.orb.object_to_string(obj)
219         except:
220             ior = None
221         if ior:
222             sobj = salome.myStudy.FindObjectIOR(ior)
223             if sobj:
224                 return sobj.GetName()
225             if hasattr(obj, "GetName"):
226                 # unknown CORBA object, having GetName() method
227                 return obj.GetName()
228             else:
229                 # unknown CORBA object, no GetName() method
230                 return NO_NAME
231             pass
232         if hasattr(obj, "GetName"):
233             # unknown non-CORBA object, having GetName() method
234             return obj.GetName()
235         pass
236     raise RuntimeError("Null or invalid object")
237
238 def TreatHypoStatus(status, hypName, geomName, isAlgo, mesh):
239     """
240     Print error message if a hypothesis was not assigned.
241     """
242     if isAlgo:
243         hypType = "algorithm"
244     else:
245         hypType = "hypothesis"
246         pass
247     reason = ""
248     if hasattr( status, "__getitem__" ):
249         status, reason = status[0], status[1]
250     if status == HYP_UNKNOWN_FATAL:
251         reason = "for unknown reason"
252     elif status == HYP_INCOMPATIBLE:
253         reason = "this hypothesis mismatches the algorithm"
254     elif status == HYP_NOTCONFORM:
255         reason = "a non-conform mesh would be built"
256     elif status == HYP_ALREADY_EXIST:
257         if isAlgo: return # it does not influence anything
258         reason = hypType + " of the same dimension is already assigned to this shape"
259     elif status == HYP_BAD_DIM:
260         reason = hypType + " mismatches the shape"
261     elif status == HYP_CONCURRENT :
262         reason = "there are concurrent hypotheses on sub-shapes"
263     elif status == HYP_BAD_SUBSHAPE:
264         reason = "the shape is neither the main one, nor its sub-shape, nor a valid group"
265     elif status == HYP_BAD_GEOMETRY:
266         reason = "the algorithm is not applicable to this geometry"
267     elif status == HYP_HIDDEN_ALGO:
268         reason = "it is hidden by an algorithm of an upper dimension, which generates elements of all dimensions"
269     elif status == HYP_HIDING_ALGO:
270         reason = "it hides algorithms of lower dimensions by generating elements of all dimensions"
271     elif status == HYP_NEED_SHAPE:
272         reason = "algorithm can't work without shape"
273     elif status == HYP_INCOMPAT_HYPS:
274         pass
275     else:
276         return
277     where = geomName
278     if where:
279         where = '"%s"' % geomName
280         if mesh:
281             meshName = GetName( mesh )
282             if meshName and meshName != NO_NAME:
283                 where = '"%s" shape in "%s" mesh ' % ( geomName, meshName )
284     if status < HYP_UNKNOWN_FATAL and where:
285         print('"%s" was assigned to %s but %s' %( hypName, where, reason ))
286     elif where:
287         print('"%s" was not assigned to %s : %s' %( hypName, where, reason ))
288     else:
289         print('"%s" was not assigned : %s' %( hypName, reason ))
290         pass
291
292 def AssureGeomPublished(mesh, geom, name=''):
293     """
294     Private method. Add geom (sub-shape of the main shape) into the study if not yet there
295     """
296     if not isinstance( geom, geomBuilder.GEOM._objref_GEOM_Object ):
297         return
298     if not geom.GetStudyEntry():
299         ## get a name
300         if not name and geom.GetShapeType() != geomBuilder.GEOM.COMPOUND:
301             # for all groups SubShapeName() return "Compound_-1"
302             name = mesh.geompyD.SubShapeName(geom, mesh.geom)
303         if not name:
304             name = "%s_%s"%(geom.GetShapeType(), id(geom)%10000)
305         ## publish
306         mesh.geompyD.addToStudyInFather( mesh.geom, geom, name )
307     return
308
309 def FirstVertexOnCurve(mesh, edge):
310     """
311     Returns:
312         the first vertex of a geometrical edge by ignoring orientation
313     """
314     vv = mesh.geompyD.SubShapeAll( edge, geomBuilder.geomBuilder.ShapeType["VERTEX"])
315     if not vv:
316         raise TypeError("Given object has no vertices")
317     if len( vv ) == 1: return vv[0]
318     v0   = mesh.geompyD.MakeVertexOnCurve(edge,0.)
319     xyz  = mesh.geompyD.PointCoordinates( v0 ) # coords of the first vertex
320     xyz1 = mesh.geompyD.PointCoordinates( vv[0] )
321     xyz2 = mesh.geompyD.PointCoordinates( vv[1] )
322     dist1, dist2 = 0,0
323     for i in range(3):
324         dist1 += abs( xyz[i] - xyz1[i] )
325         dist2 += abs( xyz[i] - xyz2[i] )
326     if dist1 < dist2:
327         return vv[0]
328     else:
329         return vv[1]
330
331 smeshInst = None
332 """
333 Warning:
334     smeshInst is a singleton
335 """
336 engine = None
337 doLcc = False
338 created = False
339
340 class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
341     """
342     This class allows to create, load or manipulate meshes.
343     It has a set of methods to create, load or copy meshes, to combine several meshes, etc.
344     It also has methods to get infos and measure meshes.
345     """
346
347     # MirrorType enumeration
348     POINT = SMESH_MeshEditor.POINT
349     AXIS =  SMESH_MeshEditor.AXIS
350     PLANE = SMESH_MeshEditor.PLANE
351
352     # Smooth_Method enumeration
353     LAPLACIAN_SMOOTH = SMESH_MeshEditor.LAPLACIAN_SMOOTH
354     CENTROIDAL_SMOOTH = SMESH_MeshEditor.CENTROIDAL_SMOOTH
355
356     PrecisionConfusion = smeshPrecisionConfusion
357
358     # TopAbs_State enumeration
359     [TopAbs_IN, TopAbs_OUT, TopAbs_ON, TopAbs_UNKNOWN] = list(range(4))
360
361     # Methods of splitting a hexahedron into tetrahedra
362     Hex_5Tet, Hex_6Tet, Hex_24Tet, Hex_2Prisms, Hex_4Prisms = 1, 2, 3, 1, 2
363
364     def __new__(cls, *args):
365         global engine
366         global smeshInst
367         global doLcc
368         #print("==== __new__", engine, smeshInst, doLcc)
369
370         if smeshInst is None:
371             # smesh engine is either retrieved from engine, or created
372             smeshInst = engine
373             # Following test avoids a recursive loop
374             if doLcc:
375                 if smeshInst is not None:
376                     # smesh engine not created: existing engine found
377                     doLcc = False
378                 if doLcc:
379                     doLcc = False
380                     # FindOrLoadComponent called:
381                     # 1. CORBA resolution of server
382                     # 2. the __new__ method is called again
383                     #print("==== smeshInst = lcc.FindOrLoadComponent ", engine, smeshInst, doLcc)
384                     smeshInst = salome.lcc.FindOrLoadComponent( "FactoryServer", "SMESH" )
385             else:
386                 # FindOrLoadComponent not called
387                 if smeshInst is None:
388                     # smeshBuilder instance is created from lcc.FindOrLoadComponent
389                     #print("==== smeshInst = super(smeshBuilder,cls).__new__(cls) ", engine, smeshInst, doLcc)
390                     smeshInst = super(smeshBuilder,cls).__new__(cls)
391                 else:
392                     # smesh engine not created: existing engine found
393                     #print("==== existing ", engine, smeshInst, doLcc)
394                     pass
395             #print("====1 ", smeshInst)
396             return smeshInst
397
398         #print("====2 ", smeshInst)
399         return smeshInst
400
401     def __init__(self, *args):
402         global created
403         #print("--------------- smeshbuilder __init__ ---", created)
404         if not created:
405             created = True
406             SMESH._objref_SMESH_Gen.__init__(self, *args)
407
408
409     def DumpPython(self, theStudy, theIsPublished=True, theIsMultiFile=True):
410         """
411         Dump component to the Python script.
412         This method overrides IDL function to allow default values for the parameters.
413         """
414
415         return SMESH._objref_SMESH_Gen.DumpPython(self, theStudy, theIsPublished, theIsMultiFile)
416
417     def SetDumpPythonHistorical(self, isHistorical):
418         """
419         Set mode of DumpPython(), *historical* or *snapshot*.
420         In the *historical* mode, the Python Dump script includes all commands
421         performed by SMESH engine. In the *snapshot* mode, commands
422         relating to objects removed from the Study are excluded from the script
423         as well as commands not influencing the current state of meshes
424         """
425
426         if isHistorical: val = "true"
427         else:            val = "false"
428         SMESH._objref_SMESH_Gen.SetOption(self, "historical_python_dump", val)
429
430     def init_smesh(self,geompyD = None):
431         """
432         Set Geometry component
433         """    
434         #print("init_smesh")
435         self.UpdateStudy(geompyD)
436         notebook.myStudy = salome.myStudy
437
438     def Mesh(self, obj=0, name=0):
439         """
440         Create a mesh. This mesh can be either 
441
442         * an empty mesh not bound to geometry, if *obj* == 0
443         * an empty mesh bound to geometry, if *obj* is GEOM.GEOM_Object
444         * a mesh wrapping a :class:`CORBA mesh <SMESH.SMESH_Mesh>` given as *obj* parameter.
445
446         Parameters:
447             obj: either 
448
449                    1. a :class:`CORBA mesh <SMESH.SMESH_Mesh>` got by calling e.g.
450                       ::
451
452                         salome.myStudy.FindObjectID("0:1:2:3").GetObject() 
453
454                    2. a geometrical object for meshing
455                    3. none.
456             name: the name for the new mesh.
457
458         Returns:
459             an instance of class :class:`Mesh`.
460         """
461
462         if isinstance(obj,str):
463             obj,name = name,obj
464         return Mesh(self, self.geompyD, obj, name)
465
466     def EnumToLong(self,theItem):
467         """
468         Return a long value from enumeration
469         """
470
471         return theItem._v
472
473     def ColorToString(self,c):
474         """
475         Convert SALOMEDS.Color to string.
476         To be used with filters.
477
478         Parameters:
479             c: color value (SALOMEDS.Color)
480
481         Returns:
482             a string representation of the color.
483         """
484
485         val = ""
486         if isinstance(c, SALOMEDS.Color):
487             val = "%s;%s;%s" % (c.R, c.G, c.B)
488         elif isinstance(c, str):
489             val = c
490         else:
491             raise ValueError("Color value should be of string or SALOMEDS.Color type")
492         return val
493
494     def GetPointStruct(self,theVertex):
495         """
496         Get :class:`SMESH.PointStruct` from vertex
497
498         Parameters:
499                 theVertex (GEOM.GEOM_Object): vertex
500
501         Returns:
502                 :class:`SMESH.PointStruct`
503         """
504
505         [x, y, z] = self.geompyD.PointCoordinates(theVertex)
506         return PointStruct(x,y,z)
507
508     def GetDirStruct(self,theVector):
509         """
510         Get :class:`SMESH.DirStruct` from vector
511
512         Parameters:
513                 theVector (GEOM.GEOM_Object): vector
514
515         Returns:
516                 :class:`SMESH.DirStruct`
517         """
518
519         vertices = self.geompyD.SubShapeAll( theVector, geomBuilder.geomBuilder.ShapeType["VERTEX"] )
520         if(len(vertices) != 2):
521             print("Error: vector object is incorrect.")
522             return None
523         p1 = self.geompyD.PointCoordinates(vertices[0])
524         p2 = self.geompyD.PointCoordinates(vertices[1])
525         pnt = PointStruct(p2[0]-p1[0], p2[1]-p1[1], p2[2]-p1[2])
526         dirst = DirStruct(pnt)
527         return dirst
528
529     def MakeDirStruct(self,x,y,z):
530         """
531         Make :class:`SMESH.DirStruct` from a triplet of floats
532
533         Parameters:
534                 x,y,z (float): vector components
535
536         Returns:
537                 :class:`SMESH.DirStruct`
538         """
539
540         pnt = PointStruct(x,y,z)
541         return DirStruct(pnt)
542
543     def GetAxisStruct(self,theObj):
544         """
545         Get :class:`SMESH.AxisStruct` from a geometrical object
546
547         Parameters:
548             theObj (GEOM.GEOM_Object): line or plane
549
550         Returns:
551             :class:`SMESH.AxisStruct`
552         """
553         import GEOM
554         edges = self.geompyD.SubShapeAll( theObj, geomBuilder.geomBuilder.ShapeType["EDGE"] )
555         axis = None
556         if len(edges) > 1:
557             vertex1, vertex2 = self.geompyD.SubShapeAll( edges[0], geomBuilder.geomBuilder.ShapeType["VERTEX"] )
558             vertex3, vertex4 = self.geompyD.SubShapeAll( edges[1], geomBuilder.geomBuilder.ShapeType["VERTEX"] )
559             vertex1 = self.geompyD.PointCoordinates(vertex1)
560             vertex2 = self.geompyD.PointCoordinates(vertex2)
561             vertex3 = self.geompyD.PointCoordinates(vertex3)
562             vertex4 = self.geompyD.PointCoordinates(vertex4)
563             v1 = [vertex2[0]-vertex1[0], vertex2[1]-vertex1[1], vertex2[2]-vertex1[2]]
564             v2 = [vertex4[0]-vertex3[0], vertex4[1]-vertex3[1], vertex4[2]-vertex3[2]]
565             normal = [ v1[1]*v2[2]-v2[1]*v1[2], v1[2]*v2[0]-v2[2]*v1[0], v1[0]*v2[1]-v2[0]*v1[1] ]
566             axis = AxisStruct(vertex1[0], vertex1[1], vertex1[2], normal[0], normal[1], normal[2])
567             axis._mirrorType = SMESH.SMESH_MeshEditor.PLANE
568         elif len(edges) == 1:
569             vertex1, vertex2 = self.geompyD.SubShapeAll( edges[0], geomBuilder.geomBuilder.ShapeType["VERTEX"] )
570             p1 = self.geompyD.PointCoordinates( vertex1 )
571             p2 = self.geompyD.PointCoordinates( vertex2 )
572             axis = AxisStruct(p1[0], p1[1], p1[2], p2[0]-p1[0], p2[1]-p1[1], p2[2]-p1[2])
573             axis._mirrorType = SMESH.SMESH_MeshEditor.AXIS
574         elif theObj.GetShapeType() == GEOM.VERTEX:
575             x,y,z = self.geompyD.PointCoordinates( theObj )
576             axis = AxisStruct( x,y,z, 1,0,0,)
577             axis._mirrorType = SMESH.SMESH_MeshEditor.POINT
578         return axis
579
580     # From SMESH_Gen interface:
581     # ------------------------
582
583     def SetName(self, obj, name):
584         """
585         Set the given name to an object
586
587         Parameters:
588                 obj: the object to rename
589                 name: a new object name
590         """
591
592         if isinstance( obj, Mesh ):
593             obj = obj.GetMesh()
594         elif isinstance( obj, Mesh_Algorithm ):
595             obj = obj.GetAlgorithm()
596         ior  = salome.orb.object_to_string(obj)
597         SMESH._objref_SMESH_Gen.SetName(self, ior, name)
598
599     def SetEmbeddedMode( self,theMode ):
600         """
601         Set the current mode
602         """
603
604         SMESH._objref_SMESH_Gen.SetEmbeddedMode(self,theMode)
605
606     def IsEmbeddedMode(self):
607         """
608         Get the current mode
609         """
610
611         return SMESH._objref_SMESH_Gen.IsEmbeddedMode(self)
612
613     def UpdateStudy( self, geompyD = None  ):
614         """
615         Update the current study. Calling UpdateStudy() allows to
616         update meshes at switching GEOM->SMESH
617         """
618         #self.UpdateStudy()
619         if not geompyD:
620             from salome.geom import geomBuilder
621             geompyD = geomBuilder.geom
622             if not geompyD:
623                 geompyD = geomBuilder.New()
624             pass
625         self.geompyD=geompyD
626         self.SetGeomEngine(geompyD)
627         SMESH._objref_SMESH_Gen.UpdateStudy(self)
628         sb = salome.myStudy.NewBuilder()
629         sc = salome.myStudy.FindComponent("SMESH")
630         if sc:
631             sb.LoadWith(sc, self)
632         pass
633     
634     def SetEnablePublish( self, theIsEnablePublish ):
635         """
636         Set enable publishing in the study. Calling SetEnablePublish( False ) allows to
637         switch **off** publishing in the Study of mesh objects.
638         """
639        #self.SetEnablePublish(theIsEnablePublish)
640         SMESH._objref_SMESH_Gen.SetEnablePublish(self,theIsEnablePublish)
641         global notebook
642         notebook = salome_notebook.NoteBook( theIsEnablePublish )
643
644
645     def CreateMeshesFromUNV( self,theFileName ):
646         """
647         Create a Mesh object importing data from the given UNV file
648
649         Returns:
650                 an instance of class :class:`Mesh`
651         """
652
653         aSmeshMesh = SMESH._objref_SMESH_Gen.CreateMeshesFromUNV(self,theFileName)
654         aMesh = Mesh(self, self.geompyD, aSmeshMesh)
655         return aMesh
656
657     def CreateMeshesFromMED( self,theFileName ):
658         """
659         Create a Mesh object(s) importing data from the given MED file
660
661         Returns:
662                 a tuple ( list of class :class:`Mesh` instances, 
663                 :class:`SMESH.DriverMED_ReadStatus` )
664         """
665
666         aSmeshMeshes, aStatus = SMESH._objref_SMESH_Gen.CreateMeshesFromMED(self,theFileName)
667         aMeshes = [ Mesh(self, self.geompyD, m) for m in aSmeshMeshes ]
668         return aMeshes, aStatus
669
670     def CreateMeshesFromSAUV( self,theFileName ):
671         """
672         Create a Mesh object(s) importing data from the given SAUV file
673
674         Returns:
675                 a tuple ( list of class :class:`Mesh` instances, :class:`SMESH.DriverMED_ReadStatus` )
676         """
677
678         aSmeshMeshes, aStatus = SMESH._objref_SMESH_Gen.CreateMeshesFromSAUV(self,theFileName)
679         aMeshes = [ Mesh(self, self.geompyD, m) for m in aSmeshMeshes ]
680         return aMeshes, aStatus
681
682     def CreateMeshesFromSTL( self, theFileName ):
683         """
684         Create a Mesh object importing data from the given STL file
685
686         Returns:
687                 an instance of class :class:`Mesh`
688         """
689
690         aSmeshMesh = SMESH._objref_SMESH_Gen.CreateMeshesFromSTL(self,theFileName)
691         aMesh = Mesh(self, self.geompyD, aSmeshMesh)
692         return aMesh
693
694     def CreateMeshesFromCGNS( self, theFileName ):
695         """
696         Create Mesh objects importing data from the given CGNS file
697
698         Returns:
699                 a tuple ( list of class :class:`Mesh` instances, :class:`SMESH.DriverMED_ReadStatus` )
700         """
701
702         aSmeshMeshes, aStatus = SMESH._objref_SMESH_Gen.CreateMeshesFromCGNS(self,theFileName)
703         aMeshes = [ Mesh(self, self.geompyD, m) for m in aSmeshMeshes ]
704         return aMeshes, aStatus
705
706     def CreateMeshesFromGMF( self, theFileName ):
707         """
708         Create a Mesh object importing data from the given GMF file.
709         GMF files must have .mesh extension for the ASCII format and .meshb for
710         the binary format.
711
712         Returns:
713                 ( an instance of class :class:`Mesh`, :class:`SMESH.ComputeError` )
714         """
715
716         aSmeshMesh, error = SMESH._objref_SMESH_Gen.CreateMeshesFromGMF(self,
717                                                                         theFileName,
718                                                                         True)
719         if error.comment: print("*** CreateMeshesFromGMF() errors:\n", error.comment)
720         return Mesh(self, self.geompyD, aSmeshMesh), error
721
722     def Concatenate( self, meshes, uniteIdenticalGroups,
723                      mergeNodesAndElements = False, mergeTolerance = 1e-5, allGroups = False,
724                      name = ""):
725         """
726         Concatenate the given meshes into one mesh. All groups of input meshes will be
727         present in the new mesh.
728
729         Parameters:
730                 meshes: :class:`meshes, sub-meshes, groups or filters <SMESH.SMESH_IDSource>` to combine into one mesh
731                 uniteIdenticalGroups: if True, groups with same names are united, else they are renamed
732                 mergeNodesAndElements: if True, equal nodes and elements are merged
733                 mergeTolerance: tolerance for merging nodes
734                 allGroups: forces creation of groups corresponding to every input mesh
735                 name: name of a new mesh
736
737         Returns:
738                 an instance of class :class:`Mesh`
739         """
740
741         if not meshes: return None
742         for i,m in enumerate(meshes):
743             if isinstance(m, Mesh):
744                 meshes[i] = m.GetMesh()
745         mergeTolerance,Parameters,hasVars = ParseParameters(mergeTolerance)
746         meshes[0].SetParameters(Parameters)
747         if allGroups:
748             aSmeshMesh = SMESH._objref_SMESH_Gen.ConcatenateWithGroups(
749                 self,meshes,uniteIdenticalGroups,mergeNodesAndElements,mergeTolerance)
750         else:
751             aSmeshMesh = SMESH._objref_SMESH_Gen.Concatenate(
752                 self,meshes,uniteIdenticalGroups,mergeNodesAndElements,mergeTolerance)
753         aMesh = Mesh(self, self.geompyD, aSmeshMesh, name=name)
754         return aMesh
755
756     def CopyMesh( self, meshPart, meshName, toCopyGroups=False, toKeepIDs=False):
757         """
758         Create a mesh by copying a part of another mesh.
759
760         Parameters:
761                 meshPart: a part of mesh to copy, either 
762                         :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`.
763                         To copy nodes or elements not forming any mesh object,
764                         pass result of :meth:`Mesh.GetIDSource` as *meshPart*
765                 meshName: a name of the new mesh
766                 toCopyGroups: to create in the new mesh groups the copied elements belongs to
767                 toKeepIDs: to preserve order of the copied elements or not
768
769         Returns:
770                 an instance of class :class:`Mesh`
771         """
772
773         if (isinstance( meshPart, Mesh )):
774             meshPart = meshPart.GetMesh()
775         mesh = SMESH._objref_SMESH_Gen.CopyMesh( self,meshPart,meshName,toCopyGroups,toKeepIDs )
776         return Mesh(self, self.geompyD, mesh)
777
778     def GetSubShapesId( self, theMainObject, theListOfSubObjects ):
779         """
780         Return IDs of sub-shapes
781
782         Parameters:
783                 theMainObject (GEOM.GEOM_Object): a shape
784                 theListOfSubObjects: sub-shapes (list of GEOM.GEOM_Object)
785         Returns:
786                 the list of integer values
787         """
788
789         return SMESH._objref_SMESH_Gen.GetSubShapesId(self,theMainObject, theListOfSubObjects)
790
791     def GetPattern(self):
792         """
793         Create a pattern mapper.
794
795         Returns:
796                 an instance of :class:`SMESH.SMESH_Pattern`
797
798         :ref:`Example of Patterns usage <tui_pattern_mapping>`
799         """
800
801         return SMESH._objref_SMESH_Gen.GetPattern(self)
802
803     def SetBoundaryBoxSegmentation(self, nbSegments):
804         """
805         Set number of segments per diagonal of boundary box of geometry, by which
806         default segment length of appropriate 1D hypotheses is defined in GUI.
807         Default value is 10.
808         """
809
810         SMESH._objref_SMESH_Gen.SetBoundaryBoxSegmentation(self,nbSegments)
811
812     # Filtering. Auxiliary functions:
813     # ------------------------------
814
815     def GetEmptyCriterion(self):
816         """
817         Create an empty criterion
818
819         Returns:
820                 :class:`SMESH.Filter.Criterion`
821         """
822
823         Type = self.EnumToLong(FT_Undefined)
824         Compare = self.EnumToLong(FT_Undefined)
825         Threshold = 0
826         ThresholdStr = ""
827         ThresholdID = ""
828         UnaryOp = self.EnumToLong(FT_Undefined)
829         BinaryOp = self.EnumToLong(FT_Undefined)
830         Tolerance = 1e-07
831         TypeOfElement = ALL
832         Precision = -1 ##@1e-07
833         return Filter.Criterion(Type, Compare, Threshold, ThresholdStr, ThresholdID,
834                                 UnaryOp, BinaryOp, Tolerance, TypeOfElement, Precision)
835
836     def GetCriterion(self,elementType,
837                      CritType,
838                      Compare = FT_EqualTo,
839                      Threshold="",
840                      UnaryOp=FT_Undefined,
841                      BinaryOp=FT_Undefined,
842                      Tolerance=1e-07):
843         """
844         Create a criterion by the given parameters
845         Criterion structures allow to define complex filters by combining them with logical operations (AND / OR) (see example below)
846
847         Parameters:
848                 elementType: the :class:`type of elements <SMESH.ElementType>` (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME)
849                 CritType: the type of criterion :class:`SMESH.FunctorType` (SMESH.FT_Taper, SMESH.FT_Area, etc.).
850                         Note that the items starting from FT_LessThan are not suitable for *CritType*.
851                 Compare:  belongs to {SMESH.FT_LessThan, SMESH.FT_MoreThan, SMESH.FT_EqualTo}
852                 Threshold: the threshold value (range of ids as string, shape, numeric)
853                 UnaryOp:  SMESH.FT_LogicalNOT or SMESH.FT_Undefined
854                 BinaryOp: a binary logical operation SMESH.FT_LogicalAND, SMESH.FT_LogicalOR or
855                         SMESH.FT_Undefined
856                 Tolerance: the tolerance used by SMESH.FT_BelongToGeom, SMESH.FT_BelongToSurface,
857                         SMESH.FT_LyingOnGeom, SMESH.FT_CoplanarFaces criteria
858
859         Returns:
860                 :class:`SMESH.Filter.Criterion`
861
862         Example: :ref:`combining_filters`
863         """
864
865         if not CritType in SMESH.FunctorType._items:
866             raise TypeError("CritType should be of SMESH.FunctorType")
867         aCriterion               = self.GetEmptyCriterion()
868         aCriterion.TypeOfElement = elementType
869         aCriterion.Type          = self.EnumToLong(CritType)
870         aCriterion.Tolerance     = Tolerance
871
872         aThreshold = Threshold
873
874         if Compare in [FT_LessThan, FT_MoreThan, FT_EqualTo]:
875             aCriterion.Compare = self.EnumToLong(Compare)
876         elif Compare == "=" or Compare == "==":
877             aCriterion.Compare = self.EnumToLong(FT_EqualTo)
878         elif Compare == "<":
879             aCriterion.Compare = self.EnumToLong(FT_LessThan)
880         elif Compare == ">":
881             aCriterion.Compare = self.EnumToLong(FT_MoreThan)
882         elif Compare != FT_Undefined:
883             aCriterion.Compare = self.EnumToLong(FT_EqualTo)
884             aThreshold = Compare
885
886         if CritType in [FT_BelongToGeom,     FT_BelongToPlane, FT_BelongToGenSurface,
887                         FT_BelongToCylinder, FT_LyingOnGeom]:
888             # Check that Threshold is GEOM object
889             if isinstance(aThreshold, geomBuilder.GEOM._objref_GEOM_Object):
890                 aCriterion.ThresholdStr = GetName(aThreshold)
891                 aCriterion.ThresholdID  = aThreshold.GetStudyEntry()
892                 if not aCriterion.ThresholdID:
893                     name = aCriterion.ThresholdStr
894                     if not name:
895                         name = "%s_%s"%(aThreshold.GetShapeType(), id(aThreshold)%10000)
896                     aCriterion.ThresholdID = self.geompyD.addToStudy( aThreshold, name )
897             # or a name of GEOM object
898             elif isinstance( aThreshold, str ):
899                 aCriterion.ThresholdStr = aThreshold
900             else:
901                 raise TypeError("The Threshold should be a shape.")
902             if isinstance(UnaryOp,float):
903                 aCriterion.Tolerance = UnaryOp
904                 UnaryOp = FT_Undefined
905                 pass
906         elif CritType == FT_BelongToMeshGroup:
907             # Check that Threshold is a group
908             if isinstance(aThreshold, SMESH._objref_SMESH_GroupBase):
909                 if aThreshold.GetType() != elementType:
910                     raise ValueError("Group type mismatches Element type")
911                 aCriterion.ThresholdStr = aThreshold.GetName()
912                 aCriterion.ThresholdID  = salome.orb.object_to_string( aThreshold )
913                 study = salome.myStudy
914                 if study:
915                     so = study.FindObjectIOR( aCriterion.ThresholdID )
916                     if so:
917                         entry = so.GetID()
918                         if entry:
919                             aCriterion.ThresholdID = entry
920             else:
921                 raise TypeError("The Threshold should be a Mesh Group")
922         elif CritType == FT_RangeOfIds:
923             # Check that Threshold is string
924             if isinstance(aThreshold, str):
925                 aCriterion.ThresholdStr = aThreshold
926             else:
927                 raise TypeError("The Threshold should be a string.")
928         elif CritType == FT_CoplanarFaces:
929             # Check the Threshold
930             if isinstance(aThreshold, int):
931                 aCriterion.ThresholdID = str(aThreshold)
932             elif isinstance(aThreshold, str):
933                 ID = int(aThreshold)
934                 if ID < 1:
935                     raise ValueError("Invalid ID of mesh face: '%s'"%aThreshold)
936                 aCriterion.ThresholdID = aThreshold
937             else:
938                 raise TypeError("The Threshold should be an ID of mesh face and not '%s'"%aThreshold)
939         elif CritType == FT_ConnectedElements:
940             # Check the Threshold
941             if isinstance(aThreshold, geomBuilder.GEOM._objref_GEOM_Object): # shape
942                 aCriterion.ThresholdID = aThreshold.GetStudyEntry()
943                 if not aCriterion.ThresholdID:
944                     name = aThreshold.GetName()
945                     if not name:
946                         name = "%s_%s"%(aThreshold.GetShapeType(), id(aThreshold)%10000)
947                     aCriterion.ThresholdID = self.geompyD.addToStudy( aThreshold, name )
948             elif isinstance(aThreshold, int): # node id
949                 aCriterion.Threshold = aThreshold
950             elif isinstance(aThreshold, list): # 3 point coordinates
951                 if len( aThreshold ) < 3:
952                     raise ValueError("too few point coordinates, must be 3")
953                 aCriterion.ThresholdStr = " ".join( [str(c) for c in aThreshold[:3]] )
954             elif isinstance(aThreshold, str):
955                 if aThreshold.isdigit():
956                     aCriterion.Threshold = aThreshold # node id
957                 else:
958                     aCriterion.ThresholdStr = aThreshold # hope that it's point coordinates
959             else:
960                 raise TypeError("The Threshold should either a VERTEX, or a node ID, "\
961                       "or a list of point coordinates and not '%s'"%aThreshold)
962         elif CritType == FT_ElemGeomType:
963             # Check the Threshold
964             try:
965                 aCriterion.Threshold = self.EnumToLong(aThreshold)
966                 assert( aThreshold in SMESH.GeometryType._items )
967             except:
968                 if isinstance(aThreshold, int):
969                     aCriterion.Threshold = aThreshold
970                 else:
971                     raise TypeError("The Threshold should be an integer or SMESH.GeometryType.")
972                 pass
973             pass
974         elif CritType == FT_EntityType:
975             # Check the Threshold
976             try:
977                 aCriterion.Threshold = self.EnumToLong(aThreshold)
978                 assert( aThreshold in SMESH.EntityType._items )
979             except:
980                 if isinstance(aThreshold, int):
981                     aCriterion.Threshold = aThreshold
982                 else:
983                     raise TypeError("The Threshold should be an integer or SMESH.EntityType.")
984                 pass
985             pass
986
987         elif CritType == FT_GroupColor:
988             # Check the Threshold
989             try:
990                 aCriterion.ThresholdStr = self.ColorToString(aThreshold)
991             except:
992                 raise TypeError("The threshold value should be of SALOMEDS.Color type")
993             pass
994         elif CritType in [FT_FreeBorders, FT_FreeEdges, FT_FreeNodes, FT_FreeFaces,
995                           FT_LinearOrQuadratic, FT_BadOrientedVolume,
996                           FT_BareBorderFace, FT_BareBorderVolume,
997                           FT_OverConstrainedFace, FT_OverConstrainedVolume,
998                           FT_EqualNodes,FT_EqualEdges,FT_EqualFaces,FT_EqualVolumes ]:
999             # At this point the Threshold is unnecessary
1000             if aThreshold ==  FT_LogicalNOT:
1001                 aCriterion.UnaryOp = self.EnumToLong(FT_LogicalNOT)
1002             elif aThreshold in [FT_LogicalAND, FT_LogicalOR]:
1003                 aCriterion.BinaryOp = aThreshold
1004         else:
1005             # Check Threshold
1006             try:
1007                 aThreshold = float(aThreshold)
1008                 aCriterion.Threshold = aThreshold
1009             except:
1010                 raise TypeError("The Threshold should be a number.")
1011                 return None
1012
1013         if Threshold ==  FT_LogicalNOT or UnaryOp ==  FT_LogicalNOT:
1014             aCriterion.UnaryOp = self.EnumToLong(FT_LogicalNOT)
1015
1016         if Threshold in [FT_LogicalAND, FT_LogicalOR]:
1017             aCriterion.BinaryOp = self.EnumToLong(Threshold)
1018
1019         if UnaryOp in [FT_LogicalAND, FT_LogicalOR]:
1020             aCriterion.BinaryOp = self.EnumToLong(UnaryOp)
1021
1022         if BinaryOp in [FT_LogicalAND, FT_LogicalOR]:
1023             aCriterion.BinaryOp = self.EnumToLong(BinaryOp)
1024
1025         return aCriterion
1026
1027     def GetFilter(self,elementType,
1028                   CritType=FT_Undefined,
1029                   Compare=FT_EqualTo,
1030                   Threshold="",
1031                   UnaryOp=FT_Undefined,
1032                   Tolerance=1e-07,
1033                   mesh=None):
1034         """
1035         Create a filter with the given parameters
1036
1037         Parameters:
1038                 elementType: the :class:`type of elements <SMESH.ElementType>` (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME)
1039                 CritType: the :class:`type of criterion <SMESH.FunctorType>` (SMESH.FT_Taper, SMESH.FT_Area, etc.).
1040                         Note that the items starting from FT_LessThan are not suitable for CritType.
1041                 Compare: belongs to {SMESH.FT_LessThan, SMESH.FT_MoreThan, SMESH.FT_EqualTo}
1042                 Threshold: the threshold value (range of ids as string, shape, numeric)
1043                 UnaryOp:  SMESH.FT_LogicalNOT or SMESH.FT_Undefined
1044                 Tolerance: the tolerance used by SMESH.FT_BelongToGeom, SMESH.FT_BelongToSurface,
1045                         SMESH.FT_LyingOnGeom, SMESH.FT_CoplanarFaces and SMESH.FT_EqualNodes criteria
1046                 mesh: the mesh to initialize the filter with
1047
1048         Returns:
1049                 :class:`SMESH.Filter`
1050
1051         Examples:
1052                See :doc:`Filters usage examples <tui_filters>`
1053         """
1054
1055         aCriterion = self.GetCriterion(elementType, CritType, Compare, Threshold, UnaryOp, FT_Undefined,Tolerance)
1056         aFilterMgr = self.CreateFilterManager()
1057         aFilter = aFilterMgr.CreateFilter()
1058         aCriteria = []
1059         aCriteria.append(aCriterion)
1060         aFilter.SetCriteria(aCriteria)
1061         if mesh:
1062             if isinstance( mesh, Mesh ): aFilter.SetMesh( mesh.GetMesh() )
1063             else                       : aFilter.SetMesh( mesh )
1064         aFilterMgr.UnRegister()
1065         return aFilter
1066
1067     def GetFilterFromCriteria(self,criteria, binOp=SMESH.FT_LogicalAND):
1068         """
1069         Create a filter from criteria
1070
1071         Parameters:
1072                 criteria: a list of :class:`SMESH.Filter.Criterion`
1073                 binOp: binary operator used when binary operator of criteria is undefined
1074
1075         Returns:
1076                 :class:`SMESH.Filter`
1077
1078         Examples:
1079                See :doc:`Filters usage examples <tui_filters>`
1080         """
1081
1082         for i in range( len( criteria ) - 1 ):
1083             if criteria[i].BinaryOp == self.EnumToLong( SMESH.FT_Undefined ):
1084                 criteria[i].BinaryOp = self.EnumToLong( binOp )
1085         aFilterMgr = self.CreateFilterManager()
1086         aFilter = aFilterMgr.CreateFilter()
1087         aFilter.SetCriteria(criteria)
1088         aFilterMgr.UnRegister()
1089         return aFilter
1090
1091     def GetFunctor(self,theCriterion):
1092         """
1093         Create a numerical functor by its type
1094
1095         Parameters:
1096                 theCriterion (SMESH.FunctorType): functor type.
1097                         Note that not all items correspond to numerical functors.
1098
1099         Returns:
1100                 :class:`SMESH.NumericalFunctor`
1101         """
1102
1103         if isinstance( theCriterion, SMESH._objref_NumericalFunctor ):
1104             return theCriterion
1105         aFilterMgr = self.CreateFilterManager()
1106         functor = None
1107         if theCriterion == FT_AspectRatio:
1108             functor = aFilterMgr.CreateAspectRatio()
1109         elif theCriterion == FT_AspectRatio3D:
1110             functor = aFilterMgr.CreateAspectRatio3D()
1111         elif theCriterion == FT_Warping:
1112             functor = aFilterMgr.CreateWarping()
1113         elif theCriterion == FT_MinimumAngle:
1114             functor = aFilterMgr.CreateMinimumAngle()
1115         elif theCriterion == FT_Taper:
1116             functor = aFilterMgr.CreateTaper()
1117         elif theCriterion == FT_Skew:
1118             functor = aFilterMgr.CreateSkew()
1119         elif theCriterion == FT_Area:
1120             functor = aFilterMgr.CreateArea()
1121         elif theCriterion == FT_Volume3D:
1122             functor = aFilterMgr.CreateVolume3D()
1123         elif theCriterion == FT_MaxElementLength2D:
1124             functor = aFilterMgr.CreateMaxElementLength2D()
1125         elif theCriterion == FT_MaxElementLength3D:
1126             functor = aFilterMgr.CreateMaxElementLength3D()
1127         elif theCriterion == FT_MultiConnection:
1128             functor = aFilterMgr.CreateMultiConnection()
1129         elif theCriterion == FT_MultiConnection2D:
1130             functor = aFilterMgr.CreateMultiConnection2D()
1131         elif theCriterion == FT_Length:
1132             functor = aFilterMgr.CreateLength()
1133         elif theCriterion == FT_Length2D:
1134             functor = aFilterMgr.CreateLength2D()
1135         elif theCriterion == FT_Deflection2D:
1136             functor = aFilterMgr.CreateDeflection2D()
1137         elif theCriterion == FT_NodeConnectivityNumber:
1138             functor = aFilterMgr.CreateNodeConnectivityNumber()
1139         elif theCriterion == FT_BallDiameter:
1140             functor = aFilterMgr.CreateBallDiameter()
1141         else:
1142             print("Error: given parameter is not numerical functor type.")
1143         aFilterMgr.UnRegister()
1144         return functor
1145
1146     def CreateHypothesis(self, theHType, theLibName="libStdMeshersEngine.so"):
1147         """
1148         Create hypothesis
1149
1150         Parameters:
1151                 theHType (string): mesh hypothesis type
1152                 theLibName (string): mesh plug-in library name
1153
1154         Returns:
1155                 created hypothesis instance
1156         """
1157         hyp = SMESH._objref_SMESH_Gen.CreateHypothesis(self, theHType, theLibName )
1158
1159         if isinstance( hyp, SMESH._objref_SMESH_Algo ):
1160             return hyp
1161
1162         # wrap hypothesis methods
1163         for meth_name in dir( hyp.__class__ ):
1164             if not meth_name.startswith("Get") and \
1165                not meth_name in dir ( SMESH._objref_SMESH_Hypothesis ):
1166                 method = getattr ( hyp.__class__, meth_name )
1167                 if callable(method):
1168                     setattr( hyp, meth_name, hypMethodWrapper( hyp, method ))
1169
1170         return hyp
1171
1172     def GetMeshInfo(self, obj):
1173         """
1174         Get the mesh statistic.
1175         Use :meth:`smeshBuilder.EnumToLong` to get an integer from 
1176         an item of :class:`SMESH.EntityType`.
1177
1178         Returns:
1179                 dictionary { :class:`SMESH.EntityType` - "count of elements" }
1180         """
1181
1182         if isinstance( obj, Mesh ):
1183             obj = obj.GetMesh()
1184         d = {}
1185         if hasattr(obj, "GetMeshInfo"):
1186             values = obj.GetMeshInfo()
1187             for i in range(SMESH.Entity_Last._v):
1188                 if i < len(values): d[SMESH.EntityType._item(i)]=values[i]
1189             pass
1190         return d
1191
1192     def MinDistance(self, src1, src2=None, id1=0, id2=0, isElem1=False, isElem2=False):
1193         """
1194         Get minimum distance between two objects
1195
1196         * If *src2* is None, and *id2* = 0, distance from *src1* / *id1* to the origin is computed.
1197         * If *src2* is None, and *id2* != 0, it is assumed that both *id1* and *id2* belong to *src1*.
1198
1199         Parameters:
1200                 src1 (SMESH.SMESH_IDSource): first source object
1201                 src2 (SMESH.SMESH_IDSource): second source object
1202                 id1 (int): node/element id from the first source
1203                 id2 (int): node/element id from the second (or first) source
1204                 isElem1 (boolean): *True* if *id1* is element id, *False* if it is node id
1205                 isElem2 (boolean): *True* if *id2* is element id, *False* if it is node id
1206
1207         Returns:
1208                 minimum distance value
1209
1210         See also: 
1211                 :meth:`GetMinDistance`
1212         """
1213
1214         result = self.GetMinDistance(src1, src2, id1, id2, isElem1, isElem2)
1215         if result is None:
1216             result = 0.0
1217         else:
1218             result = result.value
1219         return result
1220
1221     def GetMinDistance(self, src1, src2=None, id1=0, id2=0, isElem1=False, isElem2=False):
1222         """
1223         Get :class:`SMESH.Measure` structure specifying minimum distance data between two objects
1224
1225         * If *src2* is None, and *id2*  = 0, distance from *src1* / *id1* to the origin is computed.
1226         * If *src2* is None, and *id2* != 0, it is assumed that both *id1* and *id2* belong to *src1*.
1227
1228         Parameters:
1229                 src1 (SMESH.SMESH_IDSource): first source object
1230                 src2 (SMESH.SMESH_IDSource): second source object
1231                 id1 (int): node/element id from the first source
1232                 id2 (int): node/element id from the second (or first) source
1233                 isElem1 (boolean): *True* if **id1** is element id, *False* if it is node id
1234                 isElem2 (boolean): *True* if **id2** is element id, *False* if it is node id
1235
1236         Returns:
1237                 :class:`SMESH.Measure` structure or None if input data is invalid
1238         See also: 
1239                 :meth:`MinDistance`
1240         """
1241
1242         if isinstance(src1, Mesh): src1 = src1.mesh
1243         if isinstance(src2, Mesh): src2 = src2.mesh
1244         if src2 is None and id2 != 0: src2 = src1
1245         if not hasattr(src1, "_narrow"): return None
1246         src1 = src1._narrow(SMESH.SMESH_IDSource)
1247         if not src1: return None
1248         unRegister = genObjUnRegister()
1249         if id1 != 0:
1250             m = src1.GetMesh()
1251             e = m.GetMeshEditor()
1252             if isElem1:
1253                 src1 = e.MakeIDSource([id1], SMESH.FACE)
1254             else:
1255                 src1 = e.MakeIDSource([id1], SMESH.NODE)
1256             unRegister.set( src1 )
1257             pass
1258         if hasattr(src2, "_narrow"):
1259             src2 = src2._narrow(SMESH.SMESH_IDSource)
1260             if src2 and id2 != 0:
1261                 m = src2.GetMesh()
1262                 e = m.GetMeshEditor()
1263                 if isElem2:
1264                     src2 = e.MakeIDSource([id2], SMESH.FACE)
1265                 else:
1266                     src2 = e.MakeIDSource([id2], SMESH.NODE)
1267                 unRegister.set( src2 )
1268                 pass
1269             pass
1270         aMeasurements = self.CreateMeasurements()
1271         unRegister.set( aMeasurements )
1272         result = aMeasurements.MinDistance(src1, src2)
1273         return result
1274
1275     def BoundingBox(self, objects):
1276         """
1277         Get bounding box of the specified object(s)
1278
1279         Parameters:
1280                 objects (SMESH.SMESH_IDSource): single source object or list of source objects
1281
1282         Returns:
1283                 tuple of six values (minX, minY, minZ, maxX, maxY, maxZ)
1284
1285         See also: 
1286                :meth:`GetBoundingBox`
1287         """
1288
1289         result = self.GetBoundingBox(objects)
1290         if result is None:
1291             result = (0.0,)*6
1292         else:
1293             result = (result.minX, result.minY, result.minZ, result.maxX, result.maxY, result.maxZ)
1294         return result
1295
1296     def GetBoundingBox(self, objects):
1297         """
1298         Get :class:`SMESH.Measure` structure specifying bounding box data of the specified object(s)
1299
1300         Parameters:
1301                 objects (SMESH.SMESH_IDSource): single source object or list of source objects
1302
1303         Returns:
1304                 :class:`SMESH.Measure` structure
1305
1306         See also: 
1307                 :meth:`BoundingBox`
1308         """
1309
1310         if isinstance(objects, tuple):
1311             objects = list(objects)
1312         if not isinstance(objects, list):
1313             objects = [objects]
1314         srclist = []
1315         for o in objects:
1316             if isinstance(o, Mesh):
1317                 srclist.append(o.mesh)
1318             elif hasattr(o, "_narrow"):
1319                 src = o._narrow(SMESH.SMESH_IDSource)
1320                 if src: srclist.append(src)
1321                 pass
1322             pass
1323         aMeasurements = self.CreateMeasurements()
1324         result = aMeasurements.BoundingBox(srclist)
1325         aMeasurements.UnRegister()
1326         return result
1327
1328     def GetLength(self, obj):
1329         """
1330         Get sum of lengths of all 1D elements in the mesh object.
1331
1332         Parameters:
1333                 obj: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
1334
1335         Returns:
1336                 sum of lengths of all 1D elements
1337         """
1338
1339         if isinstance(obj, Mesh): obj = obj.mesh
1340         if isinstance(obj, Mesh_Algorithm): obj = obj.GetSubMesh()
1341         aMeasurements = self.CreateMeasurements()
1342         value = aMeasurements.Length(obj)
1343         aMeasurements.UnRegister()
1344         return value
1345
1346     def GetArea(self, obj):
1347         """
1348         Get sum of areas of all 2D elements in the mesh object.
1349
1350         Parameters:
1351                 obj: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
1352
1353         Returns:
1354                 sum of areas of all 2D elements
1355         """
1356
1357         if isinstance(obj, Mesh): obj = obj.mesh
1358         if isinstance(obj, Mesh_Algorithm): obj = obj.GetSubMesh()
1359         aMeasurements = self.CreateMeasurements()
1360         value = aMeasurements.Area(obj)
1361         aMeasurements.UnRegister()
1362         return value
1363
1364     def GetVolume(self, obj):
1365         """
1366         Get sum of volumes of all 3D elements in the mesh object.
1367
1368         Parameters:
1369                 obj: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
1370
1371         Returns:
1372                 sum of volumes of all 3D elements
1373         """
1374
1375         if isinstance(obj, Mesh): obj = obj.mesh
1376         if isinstance(obj, Mesh_Algorithm): obj = obj.GetSubMesh()
1377         aMeasurements = self.CreateMeasurements()
1378         value = aMeasurements.Volume(obj)
1379         aMeasurements.UnRegister()
1380         return value
1381
1382     def GetGravityCenter(self, obj):
1383         """
1384         Get gravity center of all nodes of the mesh object.
1385         
1386         Parameters:            
1387                 obj: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
1388
1389         Returns:        
1390             Three components of the gravity center (x,y,z)
1391         """
1392         if isinstance(obj, Mesh): obj = obj.mesh
1393         if isinstance(obj, Mesh_Algorithm): obj = obj.GetSubMesh()
1394         aMeasurements = self.CreateMeasurements()
1395         pointStruct = aMeasurements.GravityCenter(obj)
1396         aMeasurements.UnRegister()
1397         return pointStruct.x, pointStruct.y, pointStruct.z
1398
1399     pass # end of class smeshBuilder
1400
1401 import omniORB
1402 omniORB.registerObjref(SMESH._objref_SMESH_Gen._NP_RepositoryId, smeshBuilder)
1403 """Registering the new proxy for SMESH.SMESH_Gen"""
1404
1405
1406 def New( instance=None, instanceGeom=None):
1407     """
1408     Create a new smeshBuilder instance. The smeshBuilder class provides the Python
1409     interface to create or load meshes.
1410
1411     Typical use is::
1412
1413         import salome
1414         salome.salome_init()
1415         from salome.smesh import smeshBuilder
1416         smesh = smeshBuilder.New()
1417
1418     Parameters:
1419         study:         SALOME study, generally obtained by salome.myStudy.
1420         instance:      CORBA proxy of SMESH Engine. If None, the default Engine is used.
1421         instanceGeom:  CORBA proxy of GEOM  Engine. If None, the default Engine is used.
1422     Returns:
1423         :class:`smeshBuilder` instance
1424     """
1425     global engine
1426     global smeshInst
1427     global doLcc
1428     engine = instance
1429     if engine is None:
1430         doLcc = True
1431     smeshInst = smeshBuilder()
1432     assert isinstance(smeshInst,smeshBuilder), "Smesh engine class is %s but should be smeshBuilder.smeshBuilder. Import salome.smesh.smeshBuilder before creating the instance."%smeshInst.__class__
1433     smeshInst.init_smesh(instanceGeom)
1434     return smeshInst
1435
1436
1437 # Public class: Mesh
1438 # ==================
1439
1440
1441 class Mesh(metaclass = MeshMeta):
1442     """
1443     This class allows defining and managing a mesh.
1444     It has a set of methods to build a mesh on the given geometry, including the definition of sub-meshes.
1445     It also has methods to define groups of mesh elements, to modify a mesh (by addition of
1446     new nodes and elements and by changing the existing entities), to get information
1447     about a mesh and to export a mesh in different formats.
1448     """    
1449
1450     geom = 0
1451     mesh = 0
1452     editor = 0
1453
1454     def __init__(self, smeshpyD, geompyD, obj=0, name=0):
1455
1456         """
1457         Constructor
1458
1459         Create a mesh on the shape *obj* (or an empty mesh if *obj* is equal to 0) and
1460         sets the GUI name of this mesh to *name*.
1461
1462         Parameters:
1463                 smeshpyD: an instance of smeshBuilder class
1464                 geompyD: an instance of geomBuilder class
1465                 obj: Shape to be meshed or :class:`SMESH.SMESH_Mesh` object
1466                 name: Study name of the mesh
1467         """
1468
1469         self.smeshpyD = smeshpyD
1470         self.geompyD = geompyD
1471         if obj is None:
1472             obj = 0
1473         objHasName = False
1474         if obj != 0:
1475             if isinstance(obj, geomBuilder.GEOM._objref_GEOM_Object):
1476                 self.geom = obj
1477                 objHasName = True
1478                 # publish geom of mesh (issue 0021122)
1479                 if not self.geom.GetStudyEntry():
1480                     objHasName = False
1481                     geompyD.init_geom()
1482                     if name:
1483                         geo_name = name + " shape"
1484                     else:
1485                         geo_name = "%s_%s to mesh"%(self.geom.GetShapeType(), id(self.geom)%100)
1486                     geompyD.addToStudy( self.geom, geo_name )
1487                 self.SetMesh( self.smeshpyD.CreateMesh(self.geom) )
1488
1489             elif isinstance(obj, SMESH._objref_SMESH_Mesh):
1490                 self.SetMesh(obj)
1491         else:
1492             self.SetMesh( self.smeshpyD.CreateEmptyMesh() )
1493         if name:
1494             self.smeshpyD.SetName(self.mesh, name)
1495         elif objHasName:
1496             self.smeshpyD.SetName(self.mesh, GetName(obj)) # + " mesh"
1497
1498         if not self.geom:
1499             self.geom = self.mesh.GetShapeToMesh()
1500
1501         self.editor   = self.mesh.GetMeshEditor()
1502         self.functors = [None] * SMESH.FT_Undefined._v
1503
1504         # set self to algoCreator's
1505         for attrName in dir(self):
1506             attr = getattr( self, attrName )
1507             if isinstance( attr, algoCreator ):
1508                 setattr( self, attrName, attr.copy( self ))
1509                 pass
1510             pass
1511         pass
1512
1513     def __del__(self):
1514         """
1515         Destructor. Clean-up resources
1516         """
1517         if self.mesh:
1518             #self.mesh.UnRegister()
1519             pass
1520         pass
1521
1522     def SetMesh(self, theMesh):
1523         """
1524         Initialize the Mesh object from an instance of :class:`SMESH.SMESH_Mesh` interface
1525
1526         Parameters:
1527                 theMesh: a :class:`SMESH.SMESH_Mesh` object
1528         """
1529
1530
1531         # do not call Register() as this prevents mesh servant deletion at closing study
1532         #if self.mesh: self.mesh.UnRegister()
1533         self.mesh = theMesh
1534         if self.mesh:
1535             #self.mesh.Register()
1536             self.geom = self.mesh.GetShapeToMesh()
1537         pass
1538
1539     def GetMesh(self):
1540         """
1541         Return the mesh, that is an encapsulated instance of :class:`SMESH.SMESH_Mesh` interface
1542
1543         Returns:
1544                 a :class:`SMESH.SMESH_Mesh` object
1545         """
1546
1547         return self.mesh
1548
1549     def GetName(self):
1550         """
1551         Get the name of the mesh
1552
1553         Returns:
1554                 the name of the mesh as a string
1555         """
1556
1557         name = GetName(self.GetMesh())
1558         return name
1559
1560     def SetName(self, name):
1561         """
1562         Set a name to the mesh
1563
1564         Parameters:
1565                 name: a new name of the mesh
1566         """
1567
1568         self.smeshpyD.SetName(self.GetMesh(), name)
1569
1570     def GetSubMesh(self, geom, name):
1571         """
1572         Get a sub-mesh object associated to a *geom* geometrical object.
1573
1574         Parameters:
1575                 geom: a geometrical object (shape)
1576                 name: a name for the sub-mesh in the Object Browser
1577
1578         Returns:
1579                 an object of type :class:`SMESH.SMESH_subMesh`, representing a part of mesh,
1580                 which lies on the given shape
1581
1582         Note:
1583                 A sub-mesh is implicitly created when a sub-shape is specified at
1584                 creating an algorithm, for example::
1585
1586                    algo1D = mesh.Segment(geom=Edge_1)
1587
1588                 creates a sub-mesh on *Edge_1* and assign Wire Discretization algorithm to it.
1589                 The created sub-mesh can be retrieved from the algorithm::
1590
1591                    submesh = algo1D.GetSubMesh()
1592         """
1593
1594         AssureGeomPublished( self, geom, name )
1595         submesh = self.mesh.GetSubMesh( geom, name )
1596         return submesh
1597
1598     def GetShape(self):
1599         """
1600         Return the shape associated to the mesh
1601
1602         Returns:
1603                 a GEOM_Object
1604         """
1605
1606         return self.geom
1607
1608     def SetShape(self, geom):
1609         """
1610         Associate the given shape to the mesh (entails the recreation of the mesh)
1611
1612         Parameters:
1613                 geom: the shape to be meshed (GEOM_Object)
1614         """
1615
1616         self.mesh = self.smeshpyD.CreateMesh(geom)
1617
1618     def Load(self):
1619         """
1620         Load mesh from the study after opening the study
1621         """
1622         self.mesh.Load()
1623
1624     def IsReadyToCompute(self, theSubObject):
1625         """
1626         Return true if the hypotheses are defined well
1627
1628         Parameters:
1629                 theSubObject: a sub-shape of a mesh shape
1630
1631         Returns:
1632                 True or False
1633         """
1634
1635         return self.smeshpyD.IsReadyToCompute(self.mesh, theSubObject)
1636
1637     def GetAlgoState(self, theSubObject):
1638         """
1639         Return errors of hypotheses definition.
1640         The list of errors is empty if everything is OK.
1641
1642         Parameters:
1643                 theSubObject: a sub-shape of a mesh shape
1644
1645         Returns:
1646                 a list of errors
1647         """
1648
1649         return self.smeshpyD.GetAlgoState(self.mesh, theSubObject)
1650
1651     def GetGeometryByMeshElement(self, theElementID, theGeomName):
1652         """
1653         Return a geometrical object on which the given element was built.
1654         The returned geometrical object, if not nil, is either found in the
1655         study or published by this method with the given name
1656
1657         Parameters:
1658             theElementID: the id of the mesh element
1659             theGeomName: the user-defined name of the geometrical object
1660
1661         Returns:
1662             GEOM.GEOM_Object instance
1663         """
1664
1665         return self.smeshpyD.GetGeometryByMeshElement( self.mesh, theElementID, theGeomName )
1666
1667     def MeshDimension(self):
1668         """
1669         Return the mesh dimension depending on the dimension of the underlying shape
1670         or, if the mesh is not based on any shape, basing on deimension of elements
1671
1672         Returns:
1673                 mesh dimension as an integer value [0,3]
1674         """
1675
1676         if self.mesh.HasShapeToMesh():
1677             shells = self.geompyD.SubShapeAllIDs( self.geom, self.geompyD.ShapeType["SOLID"] )
1678             if len( shells ) > 0 :
1679                 return 3
1680             elif self.geompyD.NumberOfFaces( self.geom ) > 0 :
1681                 return 2
1682             elif self.geompyD.NumberOfEdges( self.geom ) > 0 :
1683                 return 1
1684             else:
1685                 return 0;
1686         else:
1687             if self.NbVolumes() > 0: return 3
1688             if self.NbFaces()   > 0: return 2
1689             if self.NbEdges()   > 0: return 1
1690         return 0
1691
1692     def Evaluate(self, geom=0):
1693         """
1694         Evaluate size of prospective mesh on a shape
1695
1696         Returns:
1697                 a list where i-th element is a number of elements of i-th :class:`SMESH.EntityType`.
1698                 To know predicted number of e.g. edges, inquire it this way::
1699
1700                    Evaluate()[ smesh.EnumToLong( SMESH.Entity_Edge )]
1701         """
1702
1703         if geom == 0 or not isinstance(geom, geomBuilder.GEOM._objref_GEOM_Object):
1704             if self.geom == 0:
1705                 geom = self.mesh.GetShapeToMesh()
1706             else:
1707                 geom = self.geom
1708         return self.smeshpyD.Evaluate(self.mesh, geom)
1709
1710
1711     def Compute(self, geom=0, discardModifs=False, refresh=False):
1712         """
1713         Compute the mesh and return the status of the computation
1714
1715         Parameters:
1716                 geom: geomtrical shape on which mesh data should be computed
1717                 discardModifs: if True and the mesh has been edited since
1718                         a last total re-compute and that may prevent successful partial re-compute,
1719                         then the mesh is cleaned before Compute()
1720                 refresh: if *True*, Object Browser is automatically updated (when running in GUI)
1721
1722         Returns:
1723                 True or False
1724         """
1725
1726         if geom == 0 or not isinstance(geom, geomBuilder.GEOM._objref_GEOM_Object):
1727             if self.geom == 0:
1728                 geom = self.mesh.GetShapeToMesh()
1729             else:
1730                 geom = self.geom
1731         ok = False
1732         try:
1733             if discardModifs and self.mesh.HasModificationsToDiscard(): # issue 0020693
1734                 self.mesh.Clear()
1735             ok = self.smeshpyD.Compute(self.mesh, geom)
1736         except SALOME.SALOME_Exception as ex:
1737             print("Mesh computation failed, exception caught:")
1738             print("    ", ex.details.text)
1739         except:
1740             import traceback
1741             print("Mesh computation failed, exception caught:")
1742             traceback.print_exc()
1743         if True:#not ok:
1744             allReasons = ""
1745
1746             # Treat compute errors
1747             computeErrors = self.smeshpyD.GetComputeErrors( self.mesh, geom )
1748             shapeText = ""
1749             for err in computeErrors:
1750                 if self.mesh.HasShapeToMesh():
1751                     shapeText = " on %s" % self.GetSubShapeName( err.subShapeID )
1752                 errText = ""
1753                 stdErrors = ["OK",                   #COMPERR_OK
1754                              "Invalid input mesh",   #COMPERR_BAD_INPUT_MESH
1755                              "std::exception",       #COMPERR_STD_EXCEPTION
1756                              "OCC exception",        #COMPERR_OCC_EXCEPTION
1757                              "..",                   #COMPERR_SLM_EXCEPTION
1758                              "Unknown exception",    #COMPERR_EXCEPTION
1759                              "Memory allocation problem", #COMPERR_MEMORY_PB
1760                              "Algorithm failed",     #COMPERR_ALGO_FAILED
1761                              "Unexpected geometry",  #COMPERR_BAD_SHAPE
1762                              "Warning",              #COMPERR_WARNING
1763                              "Computation cancelled",#COMPERR_CANCELED
1764                              "No mesh on sub-shape"] #COMPERR_NO_MESH_ON_SHAPE
1765                 if err.code > 0:
1766                     if err.code < len(stdErrors): errText = stdErrors[err.code]
1767                 else:
1768                     errText = "code %s" % -err.code
1769                 if errText: errText += ". "
1770                 errText += err.comment
1771                 if allReasons: allReasons += "\n"
1772                 if ok:
1773                     allReasons += '-  "%s"%s - %s' %(err.algoName, shapeText, errText)
1774                 else:
1775                     allReasons += '-  "%s" failed%s. Error: %s' %(err.algoName, shapeText, errText)
1776                 pass
1777
1778             # Treat hyp errors
1779             errors = self.smeshpyD.GetAlgoState( self.mesh, geom )
1780             for err in errors:
1781                 if err.isGlobalAlgo:
1782                     glob = "global"
1783                 else:
1784                     glob = "local"
1785                     pass
1786                 dim = err.algoDim
1787                 name = err.algoName
1788                 if len(name) == 0:
1789                     reason = '%s %sD algorithm is missing' % (glob, dim)
1790                 elif err.state == HYP_MISSING:
1791                     reason = ('%s %sD algorithm "%s" misses %sD hypothesis'
1792                               % (glob, dim, name, dim))
1793                 elif err.state == HYP_NOTCONFORM:
1794                     reason = 'Global "Not Conform mesh allowed" hypothesis is missing'
1795                 elif err.state == HYP_BAD_PARAMETER:
1796                     reason = ('Hypothesis of %s %sD algorithm "%s" has a bad parameter value'
1797                               % ( glob, dim, name ))
1798                 elif err.state == HYP_BAD_GEOMETRY:
1799                     reason = ('%s %sD algorithm "%s" is assigned to mismatching'
1800                               'geometry' % ( glob, dim, name ))
1801                 elif err.state == HYP_HIDDEN_ALGO:
1802                     reason = ('%s %sD algorithm "%s" is ignored due to presence of a %s '
1803                               'algorithm of upper dimension generating %sD mesh'
1804                               % ( glob, dim, name, glob, dim ))
1805                 else:
1806                     reason = ("For unknown reason. "
1807                               "Developer, revise Mesh.Compute() implementation in smeshBuilder.py!")
1808                     pass
1809                 if allReasons: allReasons += "\n"
1810                 allReasons += "-  " + reason
1811                 pass
1812             if not ok or allReasons != "":
1813                 msg = '"' + GetName(self.mesh) + '"'
1814                 if ok: msg += " has been computed with warnings"
1815                 else:  msg += " has not been computed"
1816                 if allReasons != "": msg += ":"
1817                 else:                msg += "."
1818                 print(msg)
1819                 print(allReasons)
1820             pass
1821         if salome.sg.hasDesktop():
1822             if not isinstance( refresh, list): # not a call from subMesh.Compute()
1823                 smeshgui = salome.ImportComponentGUI("SMESH")
1824                 smeshgui.Init()
1825                 smeshgui.SetMeshIcon( salome.ObjectToID( self.mesh ), ok, (self.NbNodes()==0) )
1826                 if refresh: salome.sg.updateObjBrowser()
1827
1828         return ok
1829
1830     def GetComputeErrors(self, shape=0 ):
1831         """
1832         Return a list of error messages (:class:`SMESH.ComputeError`) of the last :meth:`Compute`
1833         """
1834
1835         if shape == 0:
1836             shape = self.mesh.GetShapeToMesh()
1837         return self.smeshpyD.GetComputeErrors( self.mesh, shape )
1838
1839     def GetSubShapeName(self, subShapeID ):
1840         """
1841         Return a name of a sub-shape by its ID.
1842         Possible variants (for *subShapeID* == 3):
1843
1844                 - **"Face_12"** - published sub-shape
1845                 - **FACE #3** - not published sub-shape
1846                 - **sub-shape #3** - invalid sub-shape ID
1847                 - **#3** - error in this function
1848
1849         Parameters:
1850                 subShapeID: a unique ID of a sub-shape
1851
1852         Returns:
1853                 a string describing the sub-shape
1854
1855         """
1856
1857         if not self.mesh.HasShapeToMesh():
1858             return ""
1859         try:
1860             shapeText = ""
1861             mainIOR  = salome.orb.object_to_string( self.GetShape() )
1862             s = salome.myStudy
1863             mainSO = s.FindObjectIOR(mainIOR)
1864             if mainSO:
1865                 if subShapeID == 1:
1866                     shapeText = '"%s"' % mainSO.GetName()
1867                 subIt = s.NewChildIterator(mainSO)
1868                 while subIt.More():
1869                     subSO = subIt.Value()
1870                     subIt.Next()
1871                     obj = subSO.GetObject()
1872                     if not obj: continue
1873                     go = obj._narrow( geomBuilder.GEOM._objref_GEOM_Object )
1874                     if not go: continue
1875                     try:
1876                         ids = self.geompyD.GetSubShapeID( self.GetShape(), go )
1877                     except:
1878                         continue
1879                     if ids == subShapeID:
1880                         shapeText = '"%s"' % subSO.GetName()
1881                         break
1882             if not shapeText:
1883                 shape = self.geompyD.GetSubShape( self.GetShape(), [subShapeID])
1884                 if shape:
1885                     shapeText = '%s #%s' % (shape.GetShapeType(), subShapeID)
1886                 else:
1887                     shapeText = 'sub-shape #%s' % (subShapeID)
1888         except:
1889             shapeText = "#%s" % (subShapeID)
1890         return shapeText
1891
1892     def GetFailedShapes(self, publish=False):
1893         """
1894         Return a list of sub-shapes meshing of which failed, grouped into GEOM groups by
1895         error of an algorithm
1896
1897         Parameters:
1898                 publish: if *True*, the returned groups will be published in the study
1899
1900         Returns:
1901                 a list of GEOM groups each named after a failed algorithm
1902         """
1903
1904
1905         algo2shapes = {}
1906         computeErrors = self.smeshpyD.GetComputeErrors( self.mesh, self.GetShape() )
1907         for err in computeErrors:
1908             shape = self.geompyD.GetSubShape( self.GetShape(), [err.subShapeID])
1909             if not shape: continue
1910             if err.algoName in algo2shapes:
1911                 algo2shapes[ err.algoName ].append( shape )
1912             else:
1913                 algo2shapes[ err.algoName ] = [ shape ]
1914             pass
1915
1916         groups = []
1917         for algoName, shapes in list(algo2shapes.items()):
1918             while shapes:
1919                 groupType = self.smeshpyD.EnumToLong( shapes[0].GetShapeType() )
1920                 otherTypeShapes = []
1921                 sameTypeShapes  = []
1922                 group = self.geompyD.CreateGroup( self.geom, groupType )
1923                 for shape in shapes:
1924                     if shape.GetShapeType() == shapes[0].GetShapeType():
1925                         sameTypeShapes.append( shape )
1926                     else:
1927                         otherTypeShapes.append( shape )
1928                 self.geompyD.UnionList( group, sameTypeShapes )
1929                 if otherTypeShapes:
1930                     group.SetName( "%s %s" % ( algoName, shapes[0].GetShapeType() ))
1931                 else:
1932                     group.SetName( algoName )
1933                 groups.append( group )
1934                 shapes = otherTypeShapes
1935             pass
1936         if publish:
1937             for group in groups:
1938                 self.geompyD.addToStudyInFather( self.geom, group, group.GetName() )
1939         return groups
1940
1941     def GetMeshOrder(self):
1942         """
1943         Return sub-mesh objects list in meshing order
1944
1945         Returns:
1946                 list of lists of :class:`sub-meshes <SMESH.SMESH_subMesh>`
1947         """
1948
1949         return self.mesh.GetMeshOrder()
1950
1951     def SetMeshOrder(self, submeshes):
1952         """
1953         Set order in which concurrent sub-meshes should be meshed
1954
1955         Parameters:
1956                 submeshes: list of lists of :class:`sub-meshes <SMESH.SMESH_subMesh>`
1957         """
1958
1959         return self.mesh.SetMeshOrder(submeshes)
1960
1961     def Clear(self, refresh=False):
1962         """
1963         Remove all nodes and elements generated on geometry. Imported elements remain.
1964
1965         Parameters:
1966                 refresh: if *True*, Object browser is automatically updated (when running in GUI)
1967         """
1968
1969         self.mesh.Clear()
1970         if ( salome.sg.hasDesktop() ):
1971             smeshgui = salome.ImportComponentGUI("SMESH")
1972             smeshgui.Init()
1973             smeshgui.SetMeshIcon( salome.ObjectToID( self.mesh ), False, True )
1974             if refresh: salome.sg.updateObjBrowser()
1975
1976     def ClearSubMesh(self, geomId, refresh=False):
1977         """
1978         Remove all nodes and elements of indicated shape
1979
1980         Parameters:
1981                 geomId: the ID of a sub-shape to remove elements on
1982                 refresh: if *True*, Object browser is automatically updated (when running in GUI)
1983         """
1984
1985         self.mesh.ClearSubMesh(geomId)
1986         if salome.sg.hasDesktop():
1987             smeshgui = salome.ImportComponentGUI("SMESH")
1988             smeshgui.Init()
1989             smeshgui.SetMeshIcon( salome.ObjectToID( self.mesh ), False, True )
1990             if refresh: salome.sg.updateObjBrowser()
1991
1992     def AutomaticTetrahedralization(self, fineness=0):
1993         """
1994         Compute a tetrahedral mesh using AutomaticLength + MEFISTO + Tetrahedron
1995
1996         Parameters:
1997                 fineness: [0.0,1.0] defines mesh fineness
1998
1999         Returns:
2000                 True or False
2001         """
2002
2003         dim = self.MeshDimension()
2004         # assign hypotheses
2005         self.RemoveGlobalHypotheses()
2006         self.Segment().AutomaticLength(fineness)
2007         if dim > 1 :
2008             self.Triangle().LengthFromEdges()
2009             pass
2010         if dim > 2 :
2011             self.Tetrahedron()
2012             pass
2013         return self.Compute()
2014
2015     def AutomaticHexahedralization(self, fineness=0):
2016         """
2017         Compute an hexahedral mesh using AutomaticLength + Quadrangle + Hexahedron
2018
2019         Parameters:
2020                 fineness: [0.0, 1.0] defines mesh fineness
2021
2022         Returns:
2023                 True or False
2024         """
2025
2026         dim = self.MeshDimension()
2027         # assign the hypotheses
2028         self.RemoveGlobalHypotheses()
2029         self.Segment().AutomaticLength(fineness)
2030         if dim > 1 :
2031             self.Quadrangle()
2032             pass
2033         if dim > 2 :
2034             self.Hexahedron()
2035             pass
2036         return self.Compute()
2037
2038     def AddHypothesis(self, hyp, geom=0):
2039         """
2040         Assign a hypothesis
2041
2042         Parameters:
2043                 hyp: a hypothesis to assign
2044                 geom: a subhape of mesh geometry
2045
2046         Returns:
2047                 :class:`SMESH.Hypothesis_Status`
2048         """
2049
2050         if isinstance( hyp, geomBuilder.GEOM._objref_GEOM_Object ):
2051             hyp, geom = geom, hyp
2052         if isinstance( hyp, Mesh_Algorithm ):
2053             hyp = hyp.GetAlgorithm()
2054             pass
2055         if not geom:
2056             geom = self.geom
2057             if not geom:
2058                 geom = self.mesh.GetShapeToMesh()
2059             pass
2060         isApplicable = True
2061         if self.mesh.HasShapeToMesh():
2062             hyp_type     = hyp.GetName()
2063             lib_name     = hyp.GetLibName()
2064             # checkAll    = ( not geom.IsSame( self.mesh.GetShapeToMesh() ))
2065             # if checkAll and geom:
2066             #     checkAll = geom.GetType() == 37
2067             checkAll     = False
2068             isApplicable = self.smeshpyD.IsApplicable(hyp_type, lib_name, geom, checkAll)
2069         if isApplicable:
2070             AssureGeomPublished( self, geom, "shape for %s" % hyp.GetName())
2071             status = self.mesh.AddHypothesis(geom, hyp)
2072         else:
2073             status = HYP_BAD_GEOMETRY, ""
2074         hyp_name = GetName( hyp )
2075         geom_name = ""
2076         if geom:
2077             geom_name = geom.GetName()
2078         isAlgo = hyp._narrow( SMESH_Algo )
2079         TreatHypoStatus( status, hyp_name, geom_name, isAlgo, self )
2080         return status
2081
2082     def IsUsedHypothesis(self, hyp, geom):
2083         """
2084         Return True if an algorithm or hypothesis is assigned to a given shape
2085
2086         Parameters:
2087                 hyp: an algorithm or hypothesis to check
2088                 geom: a subhape of mesh geometry
2089
2090         Returns:
2091                 True of False
2092         """
2093
2094         if not hyp: # or not geom
2095             return False
2096         if isinstance( hyp, Mesh_Algorithm ):
2097             hyp = hyp.GetAlgorithm()
2098             pass
2099         hyps = self.GetHypothesisList(geom)
2100         for h in hyps:
2101             if h.GetId() == hyp.GetId():
2102                 return True
2103         return False
2104
2105     def RemoveHypothesis(self, hyp, geom=0):
2106         """
2107         Unassign a hypothesis
2108
2109         Parameters:
2110                 hyp (SMESH.SMESH_Hypothesis): a hypothesis to unassign
2111                 geom (GEOM.GEOM_Object): a sub-shape of mesh geometry
2112
2113         Returns:
2114                 :class:`SMESH.Hypothesis_Status`
2115         """
2116
2117         if not hyp:
2118             return None
2119         if isinstance( hyp, Mesh_Algorithm ):
2120             hyp = hyp.GetAlgorithm()
2121             pass
2122         shape = geom
2123         if not shape:
2124             shape = self.geom
2125             pass
2126         if self.IsUsedHypothesis( hyp, shape ):
2127             return self.mesh.RemoveHypothesis( shape, hyp )
2128         hypName = GetName( hyp )
2129         geoName = GetName( shape )
2130         print("WARNING: RemoveHypothesis() failed as '%s' is not assigned to '%s' shape" % ( hypName, geoName ))
2131         return None
2132
2133     def GetHypothesisList(self, geom):
2134         """
2135         Get the list of hypotheses added on a geometry
2136
2137         Parameters:
2138                 geom (GEOM.GEOM_Object): a sub-shape of mesh geometry
2139
2140         Returns:
2141                 the sequence of :class:`SMESH.SMESH_Hypothesis`
2142         """
2143
2144         return self.mesh.GetHypothesisList( geom )
2145
2146     def RemoveGlobalHypotheses(self):
2147         """
2148         Remove all global hypotheses
2149         """
2150
2151         current_hyps = self.mesh.GetHypothesisList( self.geom )
2152         for hyp in current_hyps:
2153             self.mesh.RemoveHypothesis( self.geom, hyp )
2154             pass
2155         pass
2156     def ExportMED(self, *args, **kwargs):
2157         """
2158         Export the mesh in a file in MED format
2159         allowing to overwrite the file if it exists or add the exported data to its contents
2160
2161         Parameters:
2162                 fileName: is the file name
2163                 auto_groups (boolean): parameter for creating/not creating
2164                         the groups Group_On_All_Nodes, Group_On_All_Faces, ... ;
2165                         the typical use is auto_groups=False.
2166                 overwrite (boolean): parameter for overwriting/not overwriting the file
2167                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2168                 autoDimension: if *True* (default), a space dimension of a MED mesh can be either
2169
2170                         - 1D if all mesh nodes lie on OX coordinate axis, or
2171                         - 2D if all mesh nodes lie on XOY coordinate plane, or
2172                         - 3D in the rest cases.
2173
2174                         If *autoDimension* is *False*, the space dimension is always 3.
2175                 fields: list of GEOM fields defined on the shape to mesh.
2176                 geomAssocFields: each character of this string means a need to export a 
2177                         corresponding field; correspondence between fields and characters is following:
2178                         - 'v' stands for "_vertices _" field;
2179                         - 'e' stands for "_edges _" field;
2180                         - 'f' stands for "_faces _" field;
2181                         - 's' stands for "_solids _" field.
2182         """
2183         # process positional arguments
2184         args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]] # backward compatibility
2185         fileName        = args[0]
2186         auto_groups     = args[1] if len(args) > 1 else False
2187         overwrite       = args[2] if len(args) > 2 else True
2188         meshPart        = args[3] if len(args) > 3 else None
2189         autoDimension   = args[4] if len(args) > 4 else True
2190         fields          = args[5] if len(args) > 5 else []
2191         geomAssocFields = args[6] if len(args) > 6 else ''
2192         # process keywords arguments
2193         auto_groups     = kwargs.get("auto_groups", auto_groups)
2194         overwrite       = kwargs.get("overwrite", overwrite)
2195         meshPart        = kwargs.get("meshPart", meshPart)
2196         autoDimension   = kwargs.get("autoDimension", autoDimension)
2197         fields          = kwargs.get("fields", fields)
2198         geomAssocFields = kwargs.get("geomAssocFields", geomAssocFields)
2199         # invoke engine's function
2200         if meshPart or fields or geomAssocFields:
2201             unRegister = genObjUnRegister()
2202             if isinstance( meshPart, list ):
2203                 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2204                 unRegister.set( meshPart )
2205             self.mesh.ExportPartToMED( meshPart, fileName, auto_groups, overwrite, autoDimension,
2206                                        fields, geomAssocFields)
2207         else:
2208             self.mesh.ExportMED(fileName, auto_groups, overwrite, autoDimension)
2209
2210     def ExportSAUV(self, f, auto_groups=0):
2211         """
2212         Export the mesh in a file in SAUV format
2213
2214
2215         Parameters:
2216                 f: is the file name
2217                 auto_groups: boolean parameter for creating/not creating
2218                         the groups Group_On_All_Nodes, Group_On_All_Faces, ... ;
2219                         the typical use is auto_groups=False.
2220         """
2221
2222         self.mesh.ExportSAUV(f, auto_groups)
2223
2224     def ExportDAT(self, f, meshPart=None):
2225         """
2226         Export the mesh in a file in DAT format
2227
2228         Parameters:
2229                 f: the file name
2230                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2231         """
2232
2233         if meshPart:
2234             unRegister = genObjUnRegister()
2235             if isinstance( meshPart, list ):
2236                 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2237                 unRegister.set( meshPart )
2238             self.mesh.ExportPartToDAT( meshPart, f )
2239         else:
2240             self.mesh.ExportDAT(f)
2241
2242     def ExportUNV(self, f, meshPart=None):
2243         """
2244         Export the mesh in a file in UNV format
2245
2246         Parameters:
2247                 f: the file name
2248                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2249         """
2250
2251         if meshPart:
2252             unRegister = genObjUnRegister()
2253             if isinstance( meshPart, list ):
2254                 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2255                 unRegister.set( meshPart )
2256             self.mesh.ExportPartToUNV( meshPart, f )
2257         else:
2258             self.mesh.ExportUNV(f)
2259
2260     def ExportSTL(self, f, ascii=1, meshPart=None):
2261         """
2262         Export the mesh in a file in STL format
2263
2264         Parameters:
2265                 f: the file name
2266                 ascii: defines the file encoding
2267                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2268         """
2269
2270         if meshPart:
2271             unRegister = genObjUnRegister()
2272             if isinstance( meshPart, list ):
2273                 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2274                 unRegister.set( meshPart )
2275             self.mesh.ExportPartToSTL( meshPart, f, ascii )
2276         else:
2277             self.mesh.ExportSTL(f, ascii)
2278
2279     def ExportCGNS(self, f, overwrite=1, meshPart=None, groupElemsByType=False):
2280         """
2281         Export the mesh in a file in CGNS format
2282
2283         Parameters:
2284                 f: is the file name
2285                 overwrite: boolean parameter for overwriting/not overwriting the file
2286                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2287                 groupElemsByType: if True all elements of same entity type are exported at ones,
2288                         else elements are exported in order of their IDs which can cause creation
2289                         of multiple cgns sections
2290         """
2291
2292         unRegister = genObjUnRegister()
2293         if isinstance( meshPart, list ):
2294             meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2295             unRegister.set( meshPart )
2296         if isinstance( meshPart, Mesh ):
2297             meshPart = meshPart.mesh
2298         elif not meshPart:
2299             meshPart = self.mesh
2300         self.mesh.ExportCGNS(meshPart, f, overwrite, groupElemsByType)
2301
2302     def ExportGMF(self, f, meshPart=None):
2303         """
2304         Export the mesh in a file in GMF format.
2305         GMF files must have .mesh extension for the ASCII format and .meshb for
2306         the bynary format. Other extensions are not allowed.
2307
2308         Parameters:
2309                 f: is the file name
2310                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2311         """
2312
2313         unRegister = genObjUnRegister()
2314         if isinstance( meshPart, list ):
2315             meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2316             unRegister.set( meshPart )
2317         if isinstance( meshPart, Mesh ):
2318             meshPart = meshPart.mesh
2319         elif not meshPart:
2320             meshPart = self.mesh
2321         self.mesh.ExportGMF(meshPart, f, True)
2322
2323     def ExportToMED(self, *args, **kwargs):
2324         """
2325         Deprecated, used only for compatibility! Please, use :meth:`ExportMED` method instead.
2326         Export the mesh in a file in MED format
2327         allowing to overwrite the file if it exists or add the exported data to its contents
2328
2329         Parameters:
2330                 fileName: the file name
2331                 opt (boolean): parameter for creating/not creating
2332                         the groups Group_On_All_Nodes, Group_On_All_Faces, ...
2333                 overwrite: boolean parameter for overwriting/not overwriting the file
2334                 autoDimension: if *True* (default), a space dimension of a MED mesh can be either
2335
2336                         - 1D if all mesh nodes lie on OX coordinate axis, or
2337                         - 2D if all mesh nodes lie on XOY coordinate plane, or
2338                         - 3D in the rest cases.
2339
2340                         If **autoDimension** is *False*, the space dimension is always 3.
2341         """
2342     
2343         print("WARNING: ExportToMED() is deprecated, use ExportMED() instead")
2344         # process positional arguments
2345         args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]] # backward compatibility
2346         fileName      = args[0]
2347         auto_groups   = args[1] if len(args) > 1 else False
2348         overwrite     = args[2] if len(args) > 2 else True
2349         autoDimension = args[3] if len(args) > 3 else True
2350         # process keywords arguments
2351         auto_groups   = kwargs.get("opt", auto_groups)         # old keyword name
2352         auto_groups   = kwargs.get("auto_groups", auto_groups) # new keyword name
2353         overwrite     = kwargs.get("overwrite", overwrite)
2354         autoDimension = kwargs.get("autoDimension", autoDimension)
2355         # invoke engine's function
2356         self.mesh.ExportMED(fileName, auto_groups, overwrite, autoDimension)
2357
2358     def ExportToMEDX(self, *args, **kwargs):
2359         """
2360         Deprecated, used only for compatibility! Please, use ExportMED() method instead.
2361         Export the mesh in a file in MED format
2362
2363         Parameters:
2364                 fileName: the file name
2365                 opt (boolean): parameter for creating/not creating
2366                         the groups Group_On_All_Nodes, Group_On_All_Faces, ...
2367                 overwrite: boolean parameter for overwriting/not overwriting the file
2368                 autoDimension: if *True* (default), a space dimension of a MED mesh can be either
2369
2370                         - 1D if all mesh nodes lie on OX coordinate axis, or
2371                         - 2D if all mesh nodes lie on XOY coordinate plane, or
2372                         - 3D in the rest cases.
2373
2374                         If **autoDimension** is *False*, the space dimension is always 3.
2375                 """
2376
2377         print("WARNING: ExportToMEDX() is deprecated, use ExportMED() instead")
2378         # process positional arguments
2379         args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]] # backward compatibility
2380         fileName      = args[0]
2381         auto_groups   = args[1] if len(args) > 1 else False
2382         overwrite     = args[2] if len(args) > 2 else True
2383         autoDimension = args[3] if len(args) > 3 else True
2384         # process keywords arguments
2385         auto_groups   = kwargs.get("auto_groups", auto_groups)
2386         overwrite     = kwargs.get("overwrite", overwrite)
2387         autoDimension = kwargs.get("autoDimension", autoDimension)
2388         # invoke engine's function
2389         self.mesh.ExportMED(fileName, auto_groups, overwrite, autoDimension)
2390
2391     # Operations with groups:
2392     # ----------------------
2393     def CreateEmptyGroup(self, elementType, name):
2394         """
2395         Create an empty mesh group
2396
2397         Parameters:
2398                 elementType: the :class:`type <SMESH.ElementType>` of elements in the group; 
2399                         either of (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME)
2400                 name: the name of the mesh group
2401
2402         Returns:
2403                 :class:`SMESH.SMESH_Group`
2404         """
2405
2406         return self.mesh.CreateGroup(elementType, name)
2407
2408     def Group(self, grp, name=""):
2409         """
2410         Create a mesh group based on the geometric object *grp*
2411         and give it a *name*.
2412         If *name* is not defined the name of the geometric group is used
2413
2414         Note:
2415                 Works like :meth:`GroupOnGeom`.
2416
2417         Parameters:
2418                 grp:  a geometric group, a vertex, an edge, a face or a solid
2419                 name: the name of the mesh group
2420
2421         Returns:
2422                 :class:`SMESH.SMESH_GroupOnGeom`
2423         """
2424
2425         return self.GroupOnGeom(grp, name)
2426
2427     def GroupOnGeom(self, grp, name="", typ=None):
2428         """
2429         Create a mesh group based on the geometrical object *grp*
2430         and gives a *name*.
2431         if *name* is not defined the name of the geometric group is used
2432
2433         Parameters:
2434                 grp:  a geometrical group, a vertex, an edge, a face or a solid
2435                 name: the name of the mesh group
2436                 typ:  the type of elements in the group; either of
2437                         (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME). If not set, it is
2438                         automatically detected by the type of the geometry
2439
2440         Returns:
2441                 :class:`SMESH.SMESH_GroupOnGeom`
2442         """
2443
2444         AssureGeomPublished( self, grp, name )
2445         if name == "":
2446             name = grp.GetName()
2447         if not typ:
2448             typ = self._groupTypeFromShape( grp )
2449         return self.mesh.CreateGroupFromGEOM(typ, name, grp)
2450
2451     def _groupTypeFromShape( self, shape ):
2452         """
2453         Pivate method to get a type of group on geometry
2454         """
2455         tgeo = str(shape.GetShapeType())
2456         if tgeo == "VERTEX":
2457             typ = NODE
2458         elif tgeo == "EDGE":
2459             typ = EDGE
2460         elif tgeo == "FACE" or tgeo == "SHELL":
2461             typ = FACE
2462         elif tgeo == "SOLID" or tgeo == "COMPSOLID":
2463             typ = VOLUME
2464         elif tgeo == "COMPOUND":
2465             sub = self.geompyD.SubShapeAll( shape, self.geompyD.ShapeType["SHAPE"])
2466             if not sub:
2467                 raise ValueError("_groupTypeFromShape(): empty geometric group or compound '%s'" % GetName(shape))
2468             return self._groupTypeFromShape( sub[0] )
2469         else:
2470             raise ValueError("_groupTypeFromShape(): invalid geometry '%s'" % GetName(shape))
2471         return typ
2472
2473     def GroupOnFilter(self, typ, name, filter):
2474         """
2475         Create a mesh group with given *name* based on the *filter* which
2476         is a special type of group dynamically updating it's contents during
2477         mesh modification
2478
2479         Parameters:
2480                 typ: the type of elements in the group; either of
2481                         (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME).
2482                 name: the name of the mesh group
2483                 filter (SMESH.Filter): the filter defining group contents
2484
2485         Returns:
2486                 :class:`SMESH.SMESH_GroupOnFilter`
2487         """
2488
2489         return self.mesh.CreateGroupFromFilter(typ, name, filter)
2490
2491     def MakeGroupByIds(self, groupName, elementType, elemIDs):
2492         """
2493         Create a mesh group by the given ids of elements
2494
2495         Parameters:
2496                 groupName: the name of the mesh group
2497                 elementType: the type of elements in the group; either of
2498                         (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME).
2499                 elemIDs: either the list of ids, :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
2500
2501         Returns:
2502                 :class:`SMESH.SMESH_Group`
2503         """
2504
2505         group = self.mesh.CreateGroup(elementType, groupName)
2506         if isinstance( elemIDs, Mesh ):
2507             elemIDs = elemIDs.GetMesh()
2508         if hasattr( elemIDs, "GetIDs" ):
2509             if hasattr( elemIDs, "SetMesh" ):
2510                 elemIDs.SetMesh( self.GetMesh() )
2511             group.AddFrom( elemIDs )
2512         else:
2513             group.Add(elemIDs)
2514         return group
2515
2516     def MakeGroup(self,
2517                   groupName,
2518                   elementType,
2519                   CritType=FT_Undefined,
2520                   Compare=FT_EqualTo,
2521                   Threshold="",
2522                   UnaryOp=FT_Undefined,
2523                   Tolerance=1e-07):
2524         """
2525         Create a mesh group by the given conditions
2526
2527         Parameters:
2528                 groupName: the name of the mesh group
2529                 elementType (SMESH.ElementType): the type of elements (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME)
2530                 CritType (SMESH.FunctorType): the type of criterion (SMESH.FT_Taper, SMESH.FT_Area, etc.).
2531                         Note that the items starting from FT_LessThan are not suitable for CritType.
2532                 Compare (SMESH.FunctorType): belongs to {SMESH.FT_LessThan, SMESH.FT_MoreThan, SMESH.FT_EqualTo}
2533                 Threshold: the threshold value (range of ids as string, shape, numeric, depending on *CritType*)
2534                 UnaryOp (SMESH.FunctorType):  SMESH.FT_LogicalNOT or SMESH.FT_Undefined
2535                 Tolerance (float): the tolerance used by SMESH.FT_BelongToGeom, SMESH.FT_BelongToSurface,
2536                         SMESH.FT_LyingOnGeom, SMESH.FT_CoplanarFaces criteria
2537
2538         Returns:
2539                 :class:`SMESH.SMESH_GroupOnFilter`
2540         """
2541
2542         aCriterion = self.smeshpyD.GetCriterion(elementType, CritType, Compare, Threshold, UnaryOp, FT_Undefined,Tolerance)
2543         group = self.MakeGroupByCriterion(groupName, aCriterion)
2544         return group
2545
2546     def MakeGroupByCriterion(self, groupName, Criterion):
2547         """
2548         Create a mesh group by the given criterion
2549
2550         Parameters:
2551                 groupName: the name of the mesh group
2552                 Criterion: the instance of :class:`SMESH.Filter.Criterion` class
2553
2554         Returns:
2555                 :class:`SMESH.SMESH_GroupOnFilter`
2556
2557         See Also:
2558                 :meth:`smeshBuilder.GetCriterion`
2559         """
2560
2561         return self.MakeGroupByCriteria( groupName, [Criterion] )
2562
2563     def MakeGroupByCriteria(self, groupName, theCriteria, binOp=SMESH.FT_LogicalAND):
2564         """
2565         Create a mesh group by the given criteria (list of :class:`SMESH.Filter.Criterion`)
2566
2567         Parameters:
2568                 groupName: the name of the mesh group
2569                 theCriteria: the list of :class:`SMESH.Filter.Criterion`
2570                 binOp: binary operator (SMESH.FT_LogicalAND or SMESH.FT_LogicalOR ) used when binary operator of criteria is undefined
2571
2572         Returns:
2573                 :class:`SMESH.SMESH_GroupOnFilter`
2574
2575         See Also:
2576                 :meth:`smeshBuilder.GetCriterion`
2577         """
2578
2579         aFilter = self.smeshpyD.GetFilterFromCriteria( theCriteria, binOp )
2580         group = self.MakeGroupByFilter(groupName, aFilter)
2581         return group
2582
2583     def MakeGroupByFilter(self, groupName, theFilter):
2584         """
2585         Create a mesh group by the given filter
2586
2587         Parameters:
2588                 groupName (string): the name of the mesh group
2589                 theFilter (SMESH.Filter): the filter
2590
2591         Returns:
2592                 :class:`SMESH.SMESH_GroupOnFilter`
2593
2594         See Also:
2595                 :meth:`smeshBuilder.GetFilter`
2596         """
2597
2598         #group = self.CreateEmptyGroup(theFilter.GetElementType(), groupName)
2599         #theFilter.SetMesh( self.mesh )
2600         #group.AddFrom( theFilter )
2601         group = self.GroupOnFilter( theFilter.GetElementType(), groupName, theFilter )
2602         return group
2603
2604     def RemoveGroup(self, group):
2605         """
2606         Remove a group
2607
2608         Parameters:
2609                 group (SMESH.SMESH_GroupBase): group to remove
2610         """
2611
2612         self.mesh.RemoveGroup(group)
2613
2614     def RemoveGroupWithContents(self, group):
2615         """
2616         Remove a group with its contents
2617
2618         Parameters:
2619                 group (SMESH.SMESH_GroupBase): group to remove
2620         """
2621
2622         self.mesh.RemoveGroupWithContents(group)
2623
2624     def GetGroups(self, elemType = SMESH.ALL):
2625         """
2626         Get the list of groups existing in the mesh in the order
2627         of creation (starting from the oldest one)
2628
2629         Parameters:
2630                 elemType (SMESH.ElementType): type of elements the groups contain;
2631                         by default groups of elements of all types are returned
2632
2633         Returns:
2634                 a sequence of :class:`SMESH.SMESH_GroupBase`
2635         """
2636
2637         groups = self.mesh.GetGroups()
2638         if elemType == SMESH.ALL:
2639             return groups
2640         typedGroups = []
2641         for g in groups:
2642             if g.GetType() == elemType:
2643                 typedGroups.append( g )
2644                 pass
2645             pass
2646         return typedGroups
2647
2648     def NbGroups(self):
2649         """
2650         Get the number of groups existing in the mesh
2651
2652         Returns:
2653                 the quantity of groups as an integer value
2654         """
2655
2656         return self.mesh.NbGroups()
2657
2658     def GetGroupNames(self):
2659         """
2660         Get the list of names of groups existing in the mesh
2661
2662         Returns:
2663                 list of strings
2664         """
2665
2666         groups = self.GetGroups()
2667         names = []
2668         for group in groups:
2669             names.append(group.GetName())
2670         return names
2671
2672     def GetGroupByName(self, name, elemType = None):
2673         """
2674         Find groups by name and type
2675
2676         Parameters:
2677                 name (string): name of the group of interest
2678                 elemType (SMESH.ElementType): type of elements the groups contain;
2679                         by default one group of any type is returned;
2680                         if elemType == SMESH.ALL then all groups of any type are returned
2681
2682         Returns:
2683                 a list of :class:`SMESH.SMESH_GroupBase`
2684         """
2685
2686         groups = []
2687         for group in self.GetGroups():
2688             if group.GetName() == name:
2689                 if elemType is None:
2690                     return [group]
2691                 if ( elemType == SMESH.ALL or
2692                      group.GetType() == elemType ):
2693                     groups.append( group )
2694         return groups
2695
2696     def UnionGroups(self, group1, group2, name):
2697         """
2698         Produce a union of two groups.
2699         A new group is created. All mesh elements that are
2700         present in the initial groups are added to the new one
2701
2702         Parameters:
2703            group1 (SMESH.SMESH_GroupBase): a group
2704            group2 (SMESH.SMESH_GroupBase): another group
2705
2706         Returns:
2707                 instance of :class:`SMESH.SMESH_Group`
2708         """
2709
2710         return self.mesh.UnionGroups(group1, group2, name)
2711
2712     def UnionListOfGroups(self, groups, name):
2713         """
2714         Produce a union list of groups.
2715         New group is created. All mesh elements that are present in
2716         initial groups are added to the new one
2717
2718         Parameters:
2719            groups: list of :class:`SMESH.SMESH_GroupBase`
2720
2721         Returns:
2722                 instance of :class:`SMESH.SMESH_Group`
2723         """
2724         return self.mesh.UnionListOfGroups(groups, name)
2725
2726     def IntersectGroups(self, group1, group2, name):
2727         """
2728         Prodice an intersection of two groups.
2729         A new group is created. All mesh elements that are common
2730         for the two initial groups are added to the new one.
2731
2732         Parameters:
2733            group1 (SMESH.SMESH_GroupBase): a group
2734            group2 (SMESH.SMESH_GroupBase): another group
2735
2736         Returns:
2737                 instance of :class:`SMESH.SMESH_Group`
2738         """
2739
2740         return self.mesh.IntersectGroups(group1, group2, name)
2741
2742     def IntersectListOfGroups(self, groups, name):
2743         """
2744         Produce an intersection of groups.
2745         New group is created. All mesh elements that are present in all
2746         initial groups simultaneously are added to the new one
2747
2748         Parameters:
2749            groups: a list of :class:`SMESH.SMESH_GroupBase`
2750
2751         Returns:
2752                 instance of :class:`SMESH.SMESH_Group`
2753         """
2754         return self.mesh.IntersectListOfGroups(groups, name)
2755
2756     def CutGroups(self, main_group, tool_group, name):
2757         """
2758         Produce a cut of two groups.
2759         A new group is created. All mesh elements that are present in
2760         the main group but are not present in the tool group are added to the new one
2761
2762         Parameters:
2763            main_group (SMESH.SMESH_GroupBase): a group to cut from
2764            tool_group (SMESH.SMESH_GroupBase): a group to cut by
2765
2766         Returns:
2767                 an instance of :class:`SMESH.SMESH_Group`
2768         """
2769
2770         return self.mesh.CutGroups(main_group, tool_group, name)
2771
2772     def CutListOfGroups(self, main_groups, tool_groups, name):
2773         """
2774         Produce a cut of groups.
2775         A new group is created. All mesh elements that are present in main groups
2776         but do not present in tool groups are added to the new one
2777
2778         Parameters:
2779            main_group: groups to cut from  (list of :class:`SMESH.SMESH_GroupBase`)
2780            tool_group: groups to cut by    (list of :class:`SMESH.SMESH_GroupBase`)
2781
2782         Returns:
2783                 an instance of :class:`SMESH.SMESH_Group`
2784         """
2785
2786         return self.mesh.CutListOfGroups(main_groups, tool_groups, name)
2787
2788     def CreateDimGroup(self, groups, elemType, name,
2789                        nbCommonNodes = SMESH.ALL_NODES, underlyingOnly = True):
2790         """
2791         Create a standalone group of entities basing on nodes of other groups.
2792
2793         Parameters:
2794                 groups: list of reference :class:`sub-meshes, groups or filters <SMESH.SMESH_IDSource>`, of any type.
2795                 elemType: a type of elements to include to the new group; either of
2796                         (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME).
2797                 name: a name of the new group.
2798                 nbCommonNodes: a criterion of inclusion of an element to the new group
2799                         basing on number of element nodes common with reference *groups*.
2800                         Meaning of possible values are:
2801
2802                                 - SMESH.ALL_NODES - include if all nodes are common,
2803                                 - SMESH.MAIN - include if all corner nodes are common (meaningful for a quadratic mesh),
2804                                 - SMESH.AT_LEAST_ONE - include if one or more node is common,
2805                                 - SMEHS.MAJORITY - include if half of nodes or more are common.
2806                 underlyingOnly: if *True* (default), an element is included to the
2807                         new group provided that it is based on nodes of an element of *groups*;
2808                         in this case the reference *groups* are supposed to be of higher dimension
2809                         than *elemType*, which can be useful for example to get all faces lying on
2810                         volumes of the reference *groups*.
2811
2812         Returns:
2813                 an instance of :class:`SMESH.SMESH_Group`
2814         """
2815
2816         if isinstance( groups, SMESH._objref_SMESH_IDSource ):
2817             groups = [groups]
2818         return self.mesh.CreateDimGroup(groups, elemType, name, nbCommonNodes, underlyingOnly)
2819
2820
2821     def ConvertToStandalone(self, group):
2822         """
2823         Convert group on geom into standalone group
2824         """
2825
2826         return self.mesh.ConvertToStandalone(group)
2827
2828     # Get some info about mesh:
2829     # ------------------------
2830
2831     def GetLog(self, clearAfterGet):
2832         """
2833         Return the log of nodes and elements added or removed
2834         since the previous clear of the log.
2835
2836         Parameters:
2837                 clearAfterGet: log is emptied after Get (safe if concurrents access)
2838
2839         Returns:
2840                 list of SMESH.log_block structures { commandType, number, coords, indexes }
2841         """
2842
2843         return self.mesh.GetLog(clearAfterGet)
2844
2845     def ClearLog(self):
2846         """
2847         Clear the log of nodes and elements added or removed since the previous
2848         clear. Must be used immediately after :meth:`GetLog` if clearAfterGet is false.
2849         """
2850
2851         self.mesh.ClearLog()
2852
2853     def SetAutoColor(self, theAutoColor):
2854         """
2855         Toggle auto color mode on the object.
2856         If switched on, a default color of a new group in Create Group dialog is chosen randomly.
2857
2858         Parameters:
2859                 theAutoColor (boolean): the flag which toggles auto color mode.
2860         """
2861
2862         self.mesh.SetAutoColor(theAutoColor)
2863
2864     def GetAutoColor(self):
2865         """
2866         Get flag of object auto color mode.
2867
2868         Returns:
2869                 True or False
2870         """
2871
2872         return self.mesh.GetAutoColor()
2873
2874     def GetId(self):
2875         """
2876         Get the internal ID
2877
2878         Returns:
2879             integer value, which is the internal Id of the mesh
2880         """
2881
2882         return self.mesh.GetId()
2883
2884     def HasDuplicatedGroupNamesMED(self):
2885         """
2886         Check the group names for duplications.
2887         Consider the maximum group name length stored in MED file.
2888
2889         Returns:
2890             True or False
2891         """
2892
2893         return self.mesh.HasDuplicatedGroupNamesMED()
2894
2895     def GetMeshEditor(self):
2896         """
2897         Obtain the mesh editor tool
2898
2899         Returns:
2900             an instance of :class:`SMESH.SMESH_MeshEditor`
2901         """
2902
2903         return self.editor
2904
2905     def GetIDSource(self, ids, elemType = SMESH.ALL):
2906         """
2907         Wrap a list of IDs of elements or nodes into :class:`SMESH.SMESH_IDSource` which
2908         can be passed as argument to a method accepting :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
2909
2910         Parameters:
2911                 ids: list of IDs
2912                 elemType: type of elements; this parameter is used to distinguish