Salome HOME
Allow smeshBuilder.New(salome.myStudy) but print a warning
[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         instance:      CORBA proxy of SMESH Engine. If None, the default Engine is used.
1420         instanceGeom:  CORBA proxy of GEOM  Engine. If None, the default Engine is used.
1421     Returns:
1422         :class:`smeshBuilder` instance
1423     """
1424     global engine
1425     global smeshInst
1426     global doLcc
1427     if instance and isinstance( instance, SALOMEDS._objref_Study ):
1428         import sys
1429         sys.stderr.write("Warning: 'study' argument is no more needed in smeshBuilder.New(). Consider updating your script!!!\n\n")
1430         instance = None
1431     engine = instance
1432     if engine is None:
1433         doLcc = True
1434     smeshInst = smeshBuilder()
1435     assert isinstance(smeshInst,smeshBuilder), "Smesh engine class is %s but should be smeshBuilder.smeshBuilder. Import salome.smesh.smeshBuilder before creating the instance."%smeshInst.__class__
1436     smeshInst.init_smesh(instanceGeom)
1437     return smeshInst
1438
1439
1440 # Public class: Mesh
1441 # ==================
1442
1443
1444 class Mesh(metaclass = MeshMeta):
1445     """
1446     This class allows defining and managing a mesh.
1447     It has a set of methods to build a mesh on the given geometry, including the definition of sub-meshes.
1448     It also has methods to define groups of mesh elements, to modify a mesh (by addition of
1449     new nodes and elements and by changing the existing entities), to get information
1450     about a mesh and to export a mesh in different formats.
1451     """    
1452
1453     geom = 0
1454     mesh = 0
1455     editor = 0
1456
1457     def __init__(self, smeshpyD, geompyD, obj=0, name=0):
1458
1459         """
1460         Constructor
1461
1462         Create a mesh on the shape *obj* (or an empty mesh if *obj* is equal to 0) and
1463         sets the GUI name of this mesh to *name*.
1464
1465         Parameters:
1466                 smeshpyD: an instance of smeshBuilder class
1467                 geompyD: an instance of geomBuilder class
1468                 obj: Shape to be meshed or :class:`SMESH.SMESH_Mesh` object
1469                 name: Study name of the mesh
1470         """
1471
1472         self.smeshpyD = smeshpyD
1473         self.geompyD = geompyD
1474         if obj is None:
1475             obj = 0
1476         objHasName = False
1477         if obj != 0:
1478             if isinstance(obj, geomBuilder.GEOM._objref_GEOM_Object):
1479                 self.geom = obj
1480                 objHasName = True
1481                 # publish geom of mesh (issue 0021122)
1482                 if not self.geom.GetStudyEntry():
1483                     objHasName = False
1484                     geompyD.init_geom()
1485                     if name:
1486                         geo_name = name + " shape"
1487                     else:
1488                         geo_name = "%s_%s to mesh"%(self.geom.GetShapeType(), id(self.geom)%100)
1489                     geompyD.addToStudy( self.geom, geo_name )
1490                 self.SetMesh( self.smeshpyD.CreateMesh(self.geom) )
1491
1492             elif isinstance(obj, SMESH._objref_SMESH_Mesh):
1493                 self.SetMesh(obj)
1494         else:
1495             self.SetMesh( self.smeshpyD.CreateEmptyMesh() )
1496         if name:
1497             self.smeshpyD.SetName(self.mesh, name)
1498         elif objHasName:
1499             self.smeshpyD.SetName(self.mesh, GetName(obj)) # + " mesh"
1500
1501         if not self.geom:
1502             self.geom = self.mesh.GetShapeToMesh()
1503
1504         self.editor   = self.mesh.GetMeshEditor()
1505         self.functors = [None] * SMESH.FT_Undefined._v
1506
1507         # set self to algoCreator's
1508         for attrName in dir(self):
1509             attr = getattr( self, attrName )
1510             if isinstance( attr, algoCreator ):
1511                 setattr( self, attrName, attr.copy( self ))
1512                 pass
1513             pass
1514         pass
1515
1516     def __del__(self):
1517         """
1518         Destructor. Clean-up resources
1519         """
1520         if self.mesh:
1521             #self.mesh.UnRegister()
1522             pass
1523         pass
1524
1525     def SetMesh(self, theMesh):
1526         """
1527         Initialize the Mesh object from an instance of :class:`SMESH.SMESH_Mesh` interface
1528
1529         Parameters:
1530                 theMesh: a :class:`SMESH.SMESH_Mesh` object
1531         """
1532
1533
1534         # do not call Register() as this prevents mesh servant deletion at closing study
1535         #if self.mesh: self.mesh.UnRegister()
1536         self.mesh = theMesh
1537         if self.mesh:
1538             #self.mesh.Register()
1539             self.geom = self.mesh.GetShapeToMesh()
1540         pass
1541
1542     def GetMesh(self):
1543         """
1544         Return the mesh, that is an encapsulated instance of :class:`SMESH.SMESH_Mesh` interface
1545
1546         Returns:
1547                 a :class:`SMESH.SMESH_Mesh` object
1548         """
1549
1550         return self.mesh
1551
1552     def GetName(self):
1553         """
1554         Get the name of the mesh
1555
1556         Returns:
1557                 the name of the mesh as a string
1558         """
1559
1560         name = GetName(self.GetMesh())
1561         return name
1562
1563     def SetName(self, name):
1564         """
1565         Set a name to the mesh
1566
1567         Parameters:
1568                 name: a new name of the mesh
1569         """
1570
1571         self.smeshpyD.SetName(self.GetMesh(), name)
1572
1573     def GetSubMesh(self, geom, name):
1574         """
1575         Get a sub-mesh object associated to a *geom* geometrical object.
1576
1577         Parameters:
1578                 geom: a geometrical object (shape)
1579                 name: a name for the sub-mesh in the Object Browser
1580
1581         Returns:
1582                 an object of type :class:`SMESH.SMESH_subMesh`, representing a part of mesh,
1583                 which lies on the given shape
1584
1585         Note:
1586                 A sub-mesh is implicitly created when a sub-shape is specified at
1587                 creating an algorithm, for example::
1588
1589                    algo1D = mesh.Segment(geom=Edge_1)
1590
1591                 creates a sub-mesh on *Edge_1* and assign Wire Discretization algorithm to it.
1592                 The created sub-mesh can be retrieved from the algorithm::
1593
1594                    submesh = algo1D.GetSubMesh()
1595         """
1596
1597         AssureGeomPublished( self, geom, name )
1598         submesh = self.mesh.GetSubMesh( geom, name )
1599         return submesh
1600
1601     def GetShape(self):
1602         """
1603         Return the shape associated to the mesh
1604
1605         Returns:
1606                 a GEOM_Object
1607         """
1608
1609         return self.geom
1610
1611     def SetShape(self, geom):
1612         """
1613         Associate the given shape to the mesh (entails the recreation of the mesh)
1614
1615         Parameters:
1616                 geom: the shape to be meshed (GEOM_Object)
1617         """
1618
1619         self.mesh = self.smeshpyD.CreateMesh(geom)
1620
1621     def Load(self):
1622         """
1623         Load mesh from the study after opening the study
1624         """
1625         self.mesh.Load()
1626
1627     def IsReadyToCompute(self, theSubObject):
1628         """
1629         Return true if the hypotheses are defined well
1630
1631         Parameters:
1632                 theSubObject: a sub-shape of a mesh shape
1633
1634         Returns:
1635                 True or False
1636         """
1637
1638         return self.smeshpyD.IsReadyToCompute(self.mesh, theSubObject)
1639
1640     def GetAlgoState(self, theSubObject):
1641         """
1642         Return errors of hypotheses definition.
1643         The list of errors is empty if everything is OK.
1644
1645         Parameters:
1646                 theSubObject: a sub-shape of a mesh shape
1647
1648         Returns:
1649                 a list of errors
1650         """
1651
1652         return self.smeshpyD.GetAlgoState(self.mesh, theSubObject)
1653
1654     def GetGeometryByMeshElement(self, theElementID, theGeomName):
1655         """
1656         Return a geometrical object on which the given element was built.
1657         The returned geometrical object, if not nil, is either found in the
1658         study or published by this method with the given name
1659
1660         Parameters:
1661             theElementID: the id of the mesh element
1662             theGeomName: the user-defined name of the geometrical object
1663
1664         Returns:
1665             GEOM.GEOM_Object instance
1666         """
1667
1668         return self.smeshpyD.GetGeometryByMeshElement( self.mesh, theElementID, theGeomName )
1669
1670     def MeshDimension(self):
1671         """
1672         Return the mesh dimension depending on the dimension of the underlying shape
1673         or, if the mesh is not based on any shape, basing on deimension of elements
1674
1675         Returns:
1676                 mesh dimension as an integer value [0,3]
1677         """
1678
1679         if self.mesh.HasShapeToMesh():
1680             shells = self.geompyD.SubShapeAllIDs( self.geom, self.geompyD.ShapeType["SOLID"] )
1681             if len( shells ) > 0 :
1682                 return 3
1683             elif self.geompyD.NumberOfFaces( self.geom ) > 0 :
1684                 return 2
1685             elif self.geompyD.NumberOfEdges( self.geom ) > 0 :
1686                 return 1
1687             else:
1688                 return 0;
1689         else:
1690             if self.NbVolumes() > 0: return 3
1691             if self.NbFaces()   > 0: return 2
1692             if self.NbEdges()   > 0: return 1
1693         return 0
1694
1695     def Evaluate(self, geom=0):
1696         """
1697         Evaluate size of prospective mesh on a shape
1698
1699         Returns:
1700                 a list where i-th element is a number of elements of i-th :class:`SMESH.EntityType`.
1701                 To know predicted number of e.g. edges, inquire it this way::
1702
1703                    Evaluate()[ smesh.EnumToLong( SMESH.Entity_Edge )]
1704         """
1705
1706         if geom == 0 or not isinstance(geom, geomBuilder.GEOM._objref_GEOM_Object):
1707             if self.geom == 0:
1708                 geom = self.mesh.GetShapeToMesh()
1709             else:
1710                 geom = self.geom
1711         return self.smeshpyD.Evaluate(self.mesh, geom)
1712
1713
1714     def Compute(self, geom=0, discardModifs=False, refresh=False):
1715         """
1716         Compute the mesh and return the status of the computation
1717
1718         Parameters:
1719                 geom: geomtrical shape on which mesh data should be computed
1720                 discardModifs: if True and the mesh has been edited since
1721                         a last total re-compute and that may prevent successful partial re-compute,
1722                         then the mesh is cleaned before Compute()
1723                 refresh: if *True*, Object Browser is automatically updated (when running in GUI)
1724
1725         Returns:
1726                 True or False
1727         """
1728
1729         if geom == 0 or not isinstance(geom, geomBuilder.GEOM._objref_GEOM_Object):
1730             if self.geom == 0:
1731                 geom = self.mesh.GetShapeToMesh()
1732             else:
1733                 geom = self.geom
1734         ok = False
1735         try:
1736             if discardModifs and self.mesh.HasModificationsToDiscard(): # issue 0020693
1737                 self.mesh.Clear()
1738             ok = self.smeshpyD.Compute(self.mesh, geom)
1739         except SALOME.SALOME_Exception as ex:
1740             print("Mesh computation failed, exception caught:")
1741             print("    ", ex.details.text)
1742         except:
1743             import traceback
1744             print("Mesh computation failed, exception caught:")
1745             traceback.print_exc()
1746         if True:#not ok:
1747             allReasons = ""
1748
1749             # Treat compute errors
1750             computeErrors = self.smeshpyD.GetComputeErrors( self.mesh, geom )
1751             shapeText = ""
1752             for err in computeErrors:
1753                 if self.mesh.HasShapeToMesh():
1754                     shapeText = " on %s" % self.GetSubShapeName( err.subShapeID )
1755                 errText = ""
1756                 stdErrors = ["OK",                   #COMPERR_OK
1757                              "Invalid input mesh",   #COMPERR_BAD_INPUT_MESH
1758                              "std::exception",       #COMPERR_STD_EXCEPTION
1759                              "OCC exception",        #COMPERR_OCC_EXCEPTION
1760                              "..",                   #COMPERR_SLM_EXCEPTION
1761                              "Unknown exception",    #COMPERR_EXCEPTION
1762                              "Memory allocation problem", #COMPERR_MEMORY_PB
1763                              "Algorithm failed",     #COMPERR_ALGO_FAILED
1764                              "Unexpected geometry",  #COMPERR_BAD_SHAPE
1765                              "Warning",              #COMPERR_WARNING
1766                              "Computation cancelled",#COMPERR_CANCELED
1767                              "No mesh on sub-shape"] #COMPERR_NO_MESH_ON_SHAPE
1768                 if err.code > 0:
1769                     if err.code < len(stdErrors): errText = stdErrors[err.code]
1770                 else:
1771                     errText = "code %s" % -err.code
1772                 if errText: errText += ". "
1773                 errText += err.comment
1774                 if allReasons: allReasons += "\n"
1775                 if ok:
1776                     allReasons += '-  "%s"%s - %s' %(err.algoName, shapeText, errText)
1777                 else:
1778                     allReasons += '-  "%s" failed%s. Error: %s' %(err.algoName, shapeText, errText)
1779                 pass
1780
1781             # Treat hyp errors
1782             errors = self.smeshpyD.GetAlgoState( self.mesh, geom )
1783             for err in errors:
1784                 if err.isGlobalAlgo:
1785                     glob = "global"
1786                 else:
1787                     glob = "local"
1788                     pass
1789                 dim = err.algoDim
1790                 name = err.algoName
1791                 if len(name) == 0:
1792                     reason = '%s %sD algorithm is missing' % (glob, dim)
1793                 elif err.state == HYP_MISSING:
1794                     reason = ('%s %sD algorithm "%s" misses %sD hypothesis'
1795                               % (glob, dim, name, dim))
1796                 elif err.state == HYP_NOTCONFORM:
1797                     reason = 'Global "Not Conform mesh allowed" hypothesis is missing'
1798                 elif err.state == HYP_BAD_PARAMETER:
1799                     reason = ('Hypothesis of %s %sD algorithm "%s" has a bad parameter value'
1800                               % ( glob, dim, name ))
1801                 elif err.state == HYP_BAD_GEOMETRY:
1802                     reason = ('%s %sD algorithm "%s" is assigned to mismatching'
1803                               'geometry' % ( glob, dim, name ))
1804                 elif err.state == HYP_HIDDEN_ALGO:
1805                     reason = ('%s %sD algorithm "%s" is ignored due to presence of a %s '
1806                               'algorithm of upper dimension generating %sD mesh'
1807                               % ( glob, dim, name, glob, dim ))
1808                 else:
1809                     reason = ("For unknown reason. "
1810                               "Developer, revise Mesh.Compute() implementation in smeshBuilder.py!")
1811                     pass
1812                 if allReasons: allReasons += "\n"
1813                 allReasons += "-  " + reason
1814                 pass
1815             if not ok or allReasons != "":
1816                 msg = '"' + GetName(self.mesh) + '"'
1817                 if ok: msg += " has been computed with warnings"
1818                 else:  msg += " has not been computed"
1819                 if allReasons != "": msg += ":"
1820                 else:                msg += "."
1821                 print(msg)
1822                 print(allReasons)
1823             pass
1824         if salome.sg.hasDesktop():
1825             if not isinstance( refresh, list): # not a call from subMesh.Compute()
1826                 smeshgui = salome.ImportComponentGUI("SMESH")
1827                 smeshgui.Init()
1828                 smeshgui.SetMeshIcon( salome.ObjectToID( self.mesh ), ok, (self.NbNodes()==0) )
1829                 if refresh: salome.sg.updateObjBrowser()
1830
1831         return ok
1832
1833     def GetComputeErrors(self, shape=0 ):
1834         """
1835         Return a list of error messages (:class:`SMESH.ComputeError`) of the last :meth:`Compute`
1836         """
1837
1838         if shape == 0:
1839             shape = self.mesh.GetShapeToMesh()
1840         return self.smeshpyD.GetComputeErrors( self.mesh, shape )
1841
1842     def GetSubShapeName(self, subShapeID ):
1843         """
1844         Return a name of a sub-shape by its ID.
1845         Possible variants (for *subShapeID* == 3):
1846
1847                 - **"Face_12"** - published sub-shape
1848                 - **FACE #3** - not published sub-shape
1849                 - **sub-shape #3** - invalid sub-shape ID
1850                 - **#3** - error in this function
1851
1852         Parameters:
1853                 subShapeID: a unique ID of a sub-shape
1854
1855         Returns:
1856                 a string describing the sub-shape
1857
1858         """
1859
1860         if not self.mesh.HasShapeToMesh():
1861             return ""
1862         try:
1863             shapeText = ""
1864             mainIOR  = salome.orb.object_to_string( self.GetShape() )
1865             s = salome.myStudy
1866             mainSO = s.FindObjectIOR(mainIOR)
1867             if mainSO:
1868                 if subShapeID == 1:
1869                     shapeText = '"%s"' % mainSO.GetName()
1870                 subIt = s.NewChildIterator(mainSO)
1871                 while subIt.More():
1872                     subSO = subIt.Value()
1873                     subIt.Next()
1874                     obj = subSO.GetObject()
1875                     if not obj: continue
1876                     go = obj._narrow( geomBuilder.GEOM._objref_GEOM_Object )
1877                     if not go: continue
1878                     try:
1879                         ids = self.geompyD.GetSubShapeID( self.GetShape(), go )
1880                     except:
1881                         continue
1882                     if ids == subShapeID:
1883                         shapeText = '"%s"' % subSO.GetName()
1884                         break
1885             if not shapeText:
1886                 shape = self.geompyD.GetSubShape( self.GetShape(), [subShapeID])
1887                 if shape:
1888                     shapeText = '%s #%s' % (shape.GetShapeType(), subShapeID)
1889                 else:
1890                     shapeText = 'sub-shape #%s' % (subShapeID)
1891         except:
1892             shapeText = "#%s" % (subShapeID)
1893         return shapeText
1894
1895     def GetFailedShapes(self, publish=False):
1896         """
1897         Return a list of sub-shapes meshing of which failed, grouped into GEOM groups by
1898         error of an algorithm
1899
1900         Parameters:
1901                 publish: if *True*, the returned groups will be published in the study
1902
1903         Returns:
1904                 a list of GEOM groups each named after a failed algorithm
1905         """
1906
1907
1908         algo2shapes = {}
1909         computeErrors = self.smeshpyD.GetComputeErrors( self.mesh, self.GetShape() )
1910         for err in computeErrors:
1911             shape = self.geompyD.GetSubShape( self.GetShape(), [err.subShapeID])
1912             if not shape: continue
1913             if err.algoName in algo2shapes:
1914                 algo2shapes[ err.algoName ].append( shape )
1915             else:
1916                 algo2shapes[ err.algoName ] = [ shape ]
1917             pass
1918
1919         groups = []
1920         for algoName, shapes in list(algo2shapes.items()):
1921             while shapes:
1922                 groupType = self.smeshpyD.EnumToLong( shapes[0].GetShapeType() )
1923                 otherTypeShapes = []
1924                 sameTypeShapes  = []
1925                 group = self.geompyD.CreateGroup( self.geom, groupType )
1926                 for shape in shapes:
1927                     if shape.GetShapeType() == shapes[0].GetShapeType():
1928                         sameTypeShapes.append( shape )
1929                     else:
1930                         otherTypeShapes.append( shape )
1931                 self.geompyD.UnionList( group, sameTypeShapes )
1932                 if otherTypeShapes:
1933                     group.SetName( "%s %s" % ( algoName, shapes[0].GetShapeType() ))
1934                 else:
1935                     group.SetName( algoName )
1936                 groups.append( group )
1937                 shapes = otherTypeShapes
1938             pass
1939         if publish:
1940             for group in groups:
1941                 self.geompyD.addToStudyInFather( self.geom, group, group.GetName() )
1942         return groups
1943
1944     def GetMeshOrder(self):
1945         """
1946         Return sub-mesh objects list in meshing order
1947
1948         Returns:
1949                 list of lists of :class:`sub-meshes <SMESH.SMESH_subMesh>`
1950         """
1951
1952         return self.mesh.GetMeshOrder()
1953
1954     def SetMeshOrder(self, submeshes):
1955         """
1956         Set order in which concurrent sub-meshes should be meshed
1957
1958         Parameters:
1959                 submeshes: list of lists of :class:`sub-meshes <SMESH.SMESH_subMesh>`
1960         """
1961
1962         return self.mesh.SetMeshOrder(submeshes)
1963
1964     def Clear(self, refresh=False):
1965         """
1966         Remove all nodes and elements generated on geometry. Imported elements remain.
1967
1968         Parameters:
1969                 refresh: if *True*, Object browser is automatically updated (when running in GUI)
1970         """
1971
1972         self.mesh.Clear()
1973         if ( salome.sg.hasDesktop() ):
1974             smeshgui = salome.ImportComponentGUI("SMESH")
1975             smeshgui.Init()
1976             smeshgui.SetMeshIcon( salome.ObjectToID( self.mesh ), False, True )
1977             if refresh: salome.sg.updateObjBrowser()
1978
1979     def ClearSubMesh(self, geomId, refresh=False):
1980         """
1981         Remove all nodes and elements of indicated shape
1982
1983         Parameters:
1984                 geomId: the ID of a sub-shape to remove elements on
1985                 refresh: if *True*, Object browser is automatically updated (when running in GUI)
1986         """
1987
1988         self.mesh.ClearSubMesh(geomId)
1989         if salome.sg.hasDesktop():
1990             smeshgui = salome.ImportComponentGUI("SMESH")
1991             smeshgui.Init()
1992             smeshgui.SetMeshIcon( salome.ObjectToID( self.mesh ), False, True )
1993             if refresh: salome.sg.updateObjBrowser()
1994
1995     def AutomaticTetrahedralization(self, fineness=0):
1996         """
1997         Compute a tetrahedral mesh using AutomaticLength + MEFISTO + Tetrahedron
1998
1999         Parameters:
2000                 fineness: [0.0,1.0] defines mesh fineness
2001
2002         Returns:
2003                 True or False
2004         """
2005
2006         dim = self.MeshDimension()
2007         # assign hypotheses
2008         self.RemoveGlobalHypotheses()
2009         self.Segment().AutomaticLength(fineness)
2010         if dim > 1 :
2011             self.Triangle().LengthFromEdges()
2012             pass
2013         if dim > 2 :
2014             self.Tetrahedron()
2015             pass
2016         return self.Compute()
2017
2018     def AutomaticHexahedralization(self, fineness=0):
2019         """
2020         Compute an hexahedral mesh using AutomaticLength + Quadrangle + Hexahedron
2021
2022         Parameters:
2023                 fineness: [0.0, 1.0] defines mesh fineness
2024
2025         Returns:
2026                 True or False
2027         """
2028
2029         dim = self.MeshDimension()
2030         # assign the hypotheses
2031         self.RemoveGlobalHypotheses()
2032         self.Segment().AutomaticLength(fineness)
2033         if dim > 1 :
2034             self.Quadrangle()
2035             pass
2036         if dim > 2 :
2037             self.Hexahedron()
2038             pass
2039         return self.Compute()
2040
2041     def AddHypothesis(self, hyp, geom=0):
2042         """
2043         Assign a hypothesis
2044
2045         Parameters:
2046                 hyp: a hypothesis to assign
2047                 geom: a subhape of mesh geometry
2048
2049         Returns:
2050                 :class:`SMESH.Hypothesis_Status`
2051         """
2052
2053         if isinstance( hyp, geomBuilder.GEOM._objref_GEOM_Object ):
2054             hyp, geom = geom, hyp
2055         if isinstance( hyp, Mesh_Algorithm ):
2056             hyp = hyp.GetAlgorithm()
2057             pass
2058         if not geom:
2059             geom = self.geom
2060             if not geom:
2061                 geom = self.mesh.GetShapeToMesh()
2062             pass
2063         isApplicable = True
2064         if self.mesh.HasShapeToMesh():
2065             hyp_type     = hyp.GetName()
2066             lib_name     = hyp.GetLibName()
2067             # checkAll    = ( not geom.IsSame( self.mesh.GetShapeToMesh() ))
2068             # if checkAll and geom:
2069             #     checkAll = geom.GetType() == 37
2070             checkAll     = False
2071             isApplicable = self.smeshpyD.IsApplicable(hyp_type, lib_name, geom, checkAll)
2072         if isApplicable:
2073             AssureGeomPublished( self, geom, "shape for %s" % hyp.GetName())
2074             status = self.mesh.AddHypothesis(geom, hyp)
2075         else:
2076             status = HYP_BAD_GEOMETRY, ""
2077         hyp_name = GetName( hyp )
2078         geom_name = ""
2079         if geom:
2080             geom_name = geom.GetName()
2081         isAlgo = hyp._narrow( SMESH_Algo )
2082         TreatHypoStatus( status, hyp_name, geom_name, isAlgo, self )
2083         return status
2084
2085     def IsUsedHypothesis(self, hyp, geom):
2086         """
2087         Return True if an algorithm or hypothesis is assigned to a given shape
2088
2089         Parameters:
2090                 hyp: an algorithm or hypothesis to check
2091                 geom: a subhape of mesh geometry
2092
2093         Returns:
2094                 True of False
2095         """
2096
2097         if not hyp: # or not geom
2098             return False
2099         if isinstance( hyp, Mesh_Algorithm ):
2100             hyp = hyp.GetAlgorithm()
2101             pass
2102         hyps = self.GetHypothesisList(geom)
2103         for h in hyps:
2104             if h.GetId() == hyp.GetId():
2105                 return True
2106         return False
2107
2108     def RemoveHypothesis(self, hyp, geom=0):
2109         """
2110         Unassign a hypothesis
2111
2112         Parameters:
2113                 hyp (SMESH.SMESH_Hypothesis): a hypothesis to unassign
2114                 geom (GEOM.GEOM_Object): a sub-shape of mesh geometry
2115
2116         Returns:
2117                 :class:`SMESH.Hypothesis_Status`
2118         """
2119
2120         if not hyp:
2121             return None
2122         if isinstance( hyp, Mesh_Algorithm ):
2123             hyp = hyp.GetAlgorithm()
2124             pass
2125         shape = geom
2126         if not shape:
2127             shape = self.geom
2128             pass
2129         if self.IsUsedHypothesis( hyp, shape ):
2130             return self.mesh.RemoveHypothesis( shape, hyp )
2131         hypName = GetName( hyp )
2132         geoName = GetName( shape )
2133         print("WARNING: RemoveHypothesis() failed as '%s' is not assigned to '%s' shape" % ( hypName, geoName ))
2134         return None
2135
2136     def GetHypothesisList(self, geom):
2137         """
2138         Get the list of hypotheses added on a geometry
2139
2140         Parameters:
2141                 geom (GEOM.GEOM_Object): a sub-shape of mesh geometry
2142
2143         Returns:
2144                 the sequence of :class:`SMESH.SMESH_Hypothesis`
2145         """
2146
2147         return self.mesh.GetHypothesisList( geom )
2148
2149     def RemoveGlobalHypotheses(self):
2150         """
2151         Remove all global hypotheses
2152         """
2153
2154         current_hyps = self.mesh.GetHypothesisList( self.geom )
2155         for hyp in current_hyps:
2156             self.mesh.RemoveHypothesis( self.geom, hyp )
2157             pass
2158         pass
2159     def ExportMED(self, *args, **kwargs):
2160         """
2161         Export the mesh in a file in MED format
2162         allowing to overwrite the file if it exists or add the exported data to its contents
2163
2164         Parameters:
2165                 fileName: is the file name
2166                 auto_groups (boolean): parameter for creating/not creating
2167                         the groups Group_On_All_Nodes, Group_On_All_Faces, ... ;
2168                         the typical use is auto_groups=False.
2169                 overwrite (boolean): parameter for overwriting/not overwriting the file
2170                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2171                 autoDimension: if *True* (default), a space dimension of a MED mesh can be either
2172
2173                         - 1D if all mesh nodes lie on OX coordinate axis, or
2174                         - 2D if all mesh nodes lie on XOY coordinate plane, or
2175                         - 3D in the rest cases.
2176
2177                         If *autoDimension* is *False*, the space dimension is always 3.
2178                 fields: list of GEOM fields defined on the shape to mesh.
2179                 geomAssocFields: each character of this string means a need to export a 
2180                         corresponding field; correspondence between fields and characters is following:
2181                         - 'v' stands for "_vertices _" field;
2182                         - 'e' stands for "_edges _" field;
2183                         - 'f' stands for "_faces _" field;
2184                         - 's' stands for "_solids _" field.
2185         """
2186         # process positional arguments
2187         args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]] # backward compatibility
2188         fileName        = args[0]
2189         auto_groups     = args[1] if len(args) > 1 else False
2190         overwrite       = args[2] if len(args) > 2 else True
2191         meshPart        = args[3] if len(args) > 3 else None
2192         autoDimension   = args[4] if len(args) > 4 else True
2193         fields          = args[5] if len(args) > 5 else []
2194         geomAssocFields = args[6] if len(args) > 6 else ''
2195         # process keywords arguments
2196         auto_groups     = kwargs.get("auto_groups", auto_groups)
2197         overwrite       = kwargs.get("overwrite", overwrite)
2198         meshPart        = kwargs.get("meshPart", meshPart)
2199         autoDimension   = kwargs.get("autoDimension", autoDimension)
2200         fields          = kwargs.get("fields", fields)
2201         geomAssocFields = kwargs.get("geomAssocFields", geomAssocFields)
2202         # invoke engine's function
2203         if meshPart or fields or geomAssocFields:
2204             unRegister = genObjUnRegister()
2205             if isinstance( meshPart, list ):
2206                 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2207                 unRegister.set( meshPart )
2208             self.mesh.ExportPartToMED( meshPart, fileName, auto_groups, overwrite, autoDimension,
2209                                        fields, geomAssocFields)
2210         else:
2211             self.mesh.ExportMED(fileName, auto_groups, overwrite, autoDimension)
2212
2213     def ExportSAUV(self, f, auto_groups=0):
2214         """
2215         Export the mesh in a file in SAUV format
2216
2217
2218         Parameters:
2219                 f: is the file name
2220                 auto_groups: boolean parameter for creating/not creating
2221                         the groups Group_On_All_Nodes, Group_On_All_Faces, ... ;
2222                         the typical use is auto_groups=False.
2223         """
2224
2225         self.mesh.ExportSAUV(f, auto_groups)
2226
2227     def ExportDAT(self, f, meshPart=None):
2228         """
2229         Export the mesh in a file in DAT format
2230
2231         Parameters:
2232                 f: the file name
2233                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2234         """
2235
2236         if meshPart:
2237             unRegister = genObjUnRegister()
2238             if isinstance( meshPart, list ):
2239                 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2240                 unRegister.set( meshPart )
2241             self.mesh.ExportPartToDAT( meshPart, f )
2242         else:
2243             self.mesh.ExportDAT(f)
2244
2245     def ExportUNV(self, f, meshPart=None):
2246         """
2247         Export the mesh in a file in UNV format
2248
2249         Parameters:
2250                 f: the file name
2251                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2252         """
2253
2254         if meshPart:
2255             unRegister = genObjUnRegister()
2256             if isinstance( meshPart, list ):
2257                 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2258                 unRegister.set( meshPart )
2259             self.mesh.ExportPartToUNV( meshPart, f )
2260         else:
2261             self.mesh.ExportUNV(f)
2262
2263     def ExportSTL(self, f, ascii=1, meshPart=None):
2264         """
2265         Export the mesh in a file in STL format
2266
2267         Parameters:
2268                 f: the file name
2269                 ascii: defines the file encoding
2270                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2271         """
2272
2273         if meshPart:
2274             unRegister = genObjUnRegister()
2275             if isinstance( meshPart, list ):
2276                 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2277                 unRegister.set( meshPart )
2278             self.mesh.ExportPartToSTL( meshPart, f, ascii )
2279         else:
2280             self.mesh.ExportSTL(f, ascii)
2281
2282     def ExportCGNS(self, f, overwrite=1, meshPart=None, groupElemsByType=False):
2283         """
2284         Export the mesh in a file in CGNS format
2285
2286         Parameters:
2287                 f: is the file name
2288                 overwrite: boolean parameter for overwriting/not overwriting the file
2289                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2290                 groupElemsByType: if True all elements of same entity type are exported at ones,
2291                         else elements are exported in order of their IDs which can cause creation
2292                         of multiple cgns sections
2293         """
2294
2295         unRegister = genObjUnRegister()
2296         if isinstance( meshPart, list ):
2297             meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2298             unRegister.set( meshPart )
2299         if isinstance( meshPart, Mesh ):
2300             meshPart = meshPart.mesh
2301         elif not meshPart:
2302             meshPart = self.mesh
2303         self.mesh.ExportCGNS(meshPart, f, overwrite, groupElemsByType)
2304
2305     def ExportGMF(self, f, meshPart=None):
2306         """
2307         Export the mesh in a file in GMF format.
2308         GMF files must have .mesh extension for the ASCII format and .meshb for
2309         the bynary format. Other extensions are not allowed.
2310
2311         Parameters:
2312                 f: is the file name
2313                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2314         """
2315
2316         unRegister = genObjUnRegister()
2317         if isinstance( meshPart, list ):
2318             meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2319             unRegister.set( meshPart )
2320         if isinstance( meshPart, Mesh ):
2321             meshPart = meshPart.mesh
2322         elif not meshPart:
2323             meshPart = self.mesh
2324         self.mesh.ExportGMF(meshPart, f, True)
2325
2326     def ExportToMED(self, *args, **kwargs):
2327         """
2328         Deprecated, used only for compatibility! Please, use :meth:`ExportMED` method instead.
2329         Export the mesh in a file in MED format
2330         allowing to overwrite the file if it exists or add the exported data to its contents
2331
2332         Parameters:
2333                 fileName: the file name
2334                 opt (boolean): parameter for creating/not creating
2335                         the groups Group_On_All_Nodes, Group_On_All_Faces, ...
2336                 overwrite: boolean parameter for overwriting/not overwriting the file
2337                 autoDimension: if *True* (default), a space dimension of a MED mesh can be either
2338
2339                         - 1D if all mesh nodes lie on OX coordinate axis, or
2340                         - 2D if all mesh nodes lie on XOY coordinate plane, or
2341                         - 3D in the rest cases.
2342
2343                         If **autoDimension** is *False*, the space dimension is always 3.
2344         """
2345     
2346         print("WARNING: ExportToMED() is deprecated, use ExportMED() instead")
2347         # process positional arguments
2348         args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]] # backward compatibility
2349         fileName      = args[0]
2350         auto_groups   = args[1] if len(args) > 1 else False
2351         overwrite     = args[2] if len(args) > 2 else True
2352         autoDimension = args[3] if len(args) > 3 else True
2353         # process keywords arguments
2354         auto_groups   = kwargs.get("opt", auto_groups)         # old keyword name
2355         auto_groups   = kwargs.get("auto_groups", auto_groups) # new keyword name
2356         overwrite     = kwargs.get("overwrite", overwrite)
2357         autoDimension = kwargs.get("autoDimension", autoDimension)
2358         # invoke engine's function
2359         self.mesh.ExportMED(fileName, auto_groups, overwrite, autoDimension)
2360
2361     def ExportToMEDX(self, *args, **kwargs):
2362         """
2363         Deprecated, used only for compatibility! Please, use ExportMED() method instead.
2364         Export the mesh in a file in MED format
2365
2366         Parameters:
2367                 fileName: the file name
2368                 opt (boolean): parameter for creating/not creating
2369                         the groups Group_On_All_Nodes, Group_On_All_Faces, ...
2370                 overwrite: boolean parameter for overwriting/not overwriting the file
2371                 autoDimension: if *True* (default), a space dimension of a MED mesh can be either
2372
2373                         - 1D if all mesh nodes lie on OX coordinate axis, or
2374                         - 2D if all mesh nodes lie on XOY coordinate plane, or
2375                         - 3D in the rest cases.
2376
2377                         If **autoDimension** is *False*, the space dimension is always 3.
2378                 """
2379
2380         print("WARNING: ExportToMEDX() is deprecated, use ExportMED() instead")
2381         # process positional arguments
2382         args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]] # backward compatibility
2383         fileName      = args[0]
2384         auto_groups   = args[1] if len(args) > 1 else False
2385         overwrite     = args[2] if len(args) > 2 else True
2386         autoDimension = args[3] if len(args) > 3 else True
2387         # process keywords arguments
2388         auto_groups   = kwargs.get("auto_groups", auto_groups)
2389         overwrite     = kwargs.get("overwrite", overwrite)
2390         autoDimension = kwargs.get("autoDimension", autoDimension)
2391         # invoke engine's function
2392         self.mesh.ExportMED(fileName, auto_groups, overwrite, autoDimension)
2393
2394     # Operations with groups:
2395     # ----------------------
2396     def CreateEmptyGroup(self, elementType, name):
2397         """
2398         Create an empty mesh group
2399
2400         Parameters:
2401                 elementType: the :class:`type <SMESH.ElementType>` of elements in the group; 
2402                         either of (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME)
2403                 name: the name of the mesh group
2404
2405         Returns:
2406                 :class:`SMESH.SMESH_Group`
2407         """
2408
2409         return self.mesh.CreateGroup(elementType, name)
2410
2411     def Group(self, grp, name=""):
2412         """
2413         Create a mesh group based on the geometric object *grp*
2414         and give it a *name*.
2415         If *name* is not defined the name of the geometric group is used
2416
2417         Note:
2418                 Works like :meth:`GroupOnGeom`.
2419
2420         Parameters:
2421                 grp:  a geometric group, a vertex, an edge, a face or a solid
2422                 name: the name of the mesh group
2423
2424         Returns:
2425                 :class:`SMESH.SMESH_GroupOnGeom`
2426         """
2427
2428         return self.GroupOnGeom(grp, name)
2429
2430     def GroupOnGeom(self, grp, name="", typ=None):
2431         """
2432         Create a mesh group based on the geometrical object *grp*
2433         and gives a *name*.
2434         if *name* is not defined the name of the geometric group is used
2435
2436         Parameters:
2437                 grp:  a geometrical group, a vertex, an edge, a face or a solid
2438                 name: the name of the mesh group
2439                 typ:  the type of elements in the group; either of
2440                         (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME). If not set, it is
2441                         automatically detected by the type of the geometry
2442
2443         Returns:
2444                 :class:`SMESH.SMESH_GroupOnGeom`
2445         """
2446
2447         AssureGeomPublished( self, grp, name )
2448         if name == "":
2449             name = grp.GetName()
2450         if not typ:
2451             typ = self._groupTypeFromShape( grp )
2452         return self.mesh.CreateGroupFromGEOM(typ, name, grp)
2453
2454     def _groupTypeFromShape( self, shape ):
2455         """
2456         Pivate method to get a type of group on geometry
2457         """
2458         tgeo = str(shape.GetShapeType())
2459         if tgeo == "VERTEX":
2460             typ = NODE
2461         elif tgeo == "EDGE":
2462             typ = EDGE
2463         elif tgeo == "FACE" or tgeo == "SHELL":
2464             typ = FACE
2465         elif tgeo == "SOLID" or tgeo == "COMPSOLID":
2466             typ = VOLUME
2467         elif tgeo == "COMPOUND":
2468             sub = self.geompyD.SubShapeAll( shape, self.geompyD.ShapeType["SHAPE"])
2469             if not sub:
2470                 raise ValueError("_groupTypeFromShape(): empty geometric group or compound '%s'" % GetName(shape))
2471             return self._groupTypeFromShape( sub[0] )
2472         else:
2473             raise ValueError("_groupTypeFromShape(): invalid geometry '%s'" % GetName(shape))
2474         return typ
2475
2476     def GroupOnFilter(self, typ, name, filter):
2477         """
2478         Create a mesh group with given *name* based on the *filter* which
2479         is a special type of group dynamically updating it's contents during
2480         mesh modification
2481
2482         Parameters:
2483                 typ: the type of elements in the group; either of
2484                         (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME).
2485                 name: the name of the mesh group
2486                 filter (SMESH.Filter): the filter defining group contents
2487
2488         Returns:
2489                 :class:`SMESH.SMESH_GroupOnFilter`
2490         """
2491
2492         return self.mesh.CreateGroupFromFilter(typ, name, filter)
2493
2494     def MakeGroupByIds(self, groupName, elementType, elemIDs):
2495         """
2496         Create a mesh group by the given ids of elements
2497
2498         Parameters:
2499                 groupName: the name of the mesh group
2500                 elementType: the type of elements in the group; either of
2501                         (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME).
2502                 elemIDs: either the list of ids, :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
2503
2504         Returns:
2505                 :class:`SMESH.SMESH_Group`
2506         """
2507
2508         group = self.mesh.CreateGroup(elementType, groupName)
2509         if isinstance( elemIDs, Mesh ):
2510             elemIDs = elemIDs.GetMesh()
2511         if hasattr( elemIDs, "GetIDs" ):
2512             if hasattr( elemIDs, "SetMesh" ):
2513                 elemIDs.SetMesh( self.GetMesh() )
2514             group.AddFrom( elemIDs )
2515         else:
2516             group.Add(elemIDs)
2517         return group
2518
2519     def MakeGroup(self,
2520                   groupName,
2521                   elementType,
2522                   CritType=FT_Undefined,
2523                   Compare=FT_EqualTo,
2524                   Threshold="",
2525                   UnaryOp=FT_Undefined,
2526                   Tolerance=1e-07):
2527         """
2528         Create a mesh group by the given conditions
2529
2530         Parameters:
2531                 groupName: the name of the mesh group
2532                 elementType (SMESH.ElementType): the type of elements (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME)
2533                 CritType (SMESH.FunctorType): the type of criterion (SMESH.FT_Taper, SMESH.FT_Area, etc.).
2534                         Note that the items starting from FT_LessThan are not suitable for CritType.
2535                 Compare (SMESH.FunctorType): belongs to {SMESH.FT_LessThan, SMESH.FT_MoreThan, SMESH.FT_EqualTo}
2536                 Threshold: the threshold value (range of ids as string, shape, numeric, depending on *CritType*)
2537                 UnaryOp (SMESH.FunctorType):  SMESH.FT_LogicalNOT or SMESH.FT_Undefined
2538                 Tolerance (float): the tolerance used by SMESH.FT_BelongToGeom, SMESH.FT_BelongToSurface,
2539                         SMESH.FT_LyingOnGeom, SMESH.FT_CoplanarFaces criteria
2540
2541         Returns:
2542                 :class:`SMESH.SMESH_GroupOnFilter`
2543         """
2544
2545         aCriterion = self.smeshpyD.GetCriterion(elementType, CritType, Compare, Threshold, UnaryOp, FT_Undefined,Tolerance)
2546         group = self.MakeGroupByCriterion(groupName, aCriterion)
2547         return group
2548
2549     def MakeGroupByCriterion(self, groupName, Criterion):
2550         """
2551         Create a mesh group by the given criterion
2552
2553         Parameters:
2554                 groupName: the name of the mesh group
2555                 Criterion: the instance of :class:`SMESH.Filter.Criterion` class
2556
2557         Returns:
2558                 :class:`SMESH.SMESH_GroupOnFilter`
2559
2560         See Also:
2561                 :meth:`smeshBuilder.GetCriterion`
2562         """
2563
2564         return self.MakeGroupByCriteria( groupName, [Criterion] )
2565
2566     def MakeGroupByCriteria(self, groupName, theCriteria, binOp=SMESH.FT_LogicalAND):
2567         """
2568         Create a mesh group by the given criteria (list of :class:`SMESH.Filter.Criterion`)
2569
2570         Parameters:
2571                 groupName: the name of the mesh group
2572                 theCriteria: the list of :class:`SMESH.Filter.Criterion`
2573                 binOp: binary operator (SMESH.FT_LogicalAND or SMESH.FT_LogicalOR ) used when binary operator of criteria is undefined
2574
2575         Returns:
2576                 :class:`SMESH.SMESH_GroupOnFilter`
2577
2578         See Also:
2579                 :meth:`smeshBuilder.GetCriterion`
2580         """
2581
2582         aFilter = self.smeshpyD.GetFilterFromCriteria( theCriteria, binOp )
2583         group = self.MakeGroupByFilter(groupName, aFilter)
2584         return group
2585
2586     def MakeGroupByFilter(self, groupName, theFilter):
2587         """
2588         Create a mesh group by the given filter
2589
2590         Parameters:
2591                 groupName (string): the name of the mesh group
2592                 theFilter (SMESH.Filter): the filter
2593
2594         Returns:
2595                 :class:`SMESH.SMESH_GroupOnFilter`
2596
2597         See Also:
2598                 :meth:`smeshBuilder.GetFilter`
2599         """
2600
2601         #group = self.CreateEmptyGroup(theFilter.GetElementType(), groupName)
2602         #theFilter.SetMesh( self.mesh )
2603         #group.AddFrom( theFilter )
2604         group = self.GroupOnFilter( theFilter.GetElementType(), groupName, theFilter )
2605         return group
2606
2607     def RemoveGroup(self, group):
2608         """
2609         Remove a group
2610
2611         Parameters:
2612                 group (SMESH.SMESH_GroupBase): group to remove
2613         """
2614
2615         self.mesh.RemoveGroup(group)
2616
2617     def RemoveGroupWithContents(self, group):
2618         """
2619         Remove a group with its contents
2620
2621         Parameters:
2622                 group (SMESH.SMESH_GroupBase): group to remove
2623         """
2624
2625         self.mesh.RemoveGroupWithContents(group)
2626
2627     def GetGroups(self, elemType = SMESH.ALL):
2628         """
2629         Get the list of groups existing in the mesh in the order
2630         of creation (starting from the oldest one)
2631
2632         Parameters:
2633                 elemType (SMESH.ElementType): type of elements the groups contain;
2634                         by default groups of elements of all types are returned
2635
2636         Returns:
2637                 a sequence of :class:`SMESH.SMESH_GroupBase`
2638         """
2639
2640         groups = self.mesh.GetGroups()
2641         if elemType == SMESH.ALL:
2642             return groups
2643         typedGroups = []
2644         for g in groups:
2645             if g.GetType() == elemType:
2646                 typedGroups.append( g )
2647                 pass
2648             pass
2649         return typedGroups
2650
2651     def NbGroups(self):
2652         """
2653         Get the number of groups existing in the mesh
2654
2655         Returns:
2656                 the quantity of groups as an integer value
2657         """
2658
2659         return self.mesh.NbGroups()
2660
2661     def GetGroupNames(self):
2662         """
2663         Get the list of names of groups existing in the mesh
2664
2665         Returns:
2666                 list of strings
2667         """
2668
2669         groups = self.GetGroups()
2670         names = []
2671         for group in groups:
2672             names.append(group.GetName())
2673         return names
2674
2675     def GetGroupByName(self, name, elemType = None):
2676         """
2677         Find groups by name and type
2678
2679         Parameters:
2680                 name (string): name of the group of interest
2681                 elemType (SMESH.ElementType): type of elements the groups contain;
2682                         by default one group of any type is returned;
2683                         if elemType == SMESH.ALL then all groups of any type are returned
2684
2685         Returns:
2686                 a list of :class:`SMESH.SMESH_GroupBase`
2687         """
2688
2689         groups = []
2690         for group in self.GetGroups():
2691             if group.GetName() == name:
2692                 if elemType is None:
2693                     return [group]
2694                 if ( elemType == SMESH.ALL or
2695                      group.GetType() == elemType ):
2696                     groups.append( group )
2697         return groups
2698
2699     def UnionGroups(self, group1, group2, name):
2700         """
2701         Produce a union of two groups.
2702         A new group is created. All mesh elements that are
2703         present in the initial groups are added to the new one
2704
2705         Parameters:
2706            group1 (SMESH.SMESH_GroupBase): a group
2707            group2 (SMESH.SMESH_GroupBase): another group
2708
2709         Returns:
2710                 instance of :class:`SMESH.SMESH_Group`
2711         """
2712
2713         return self.mesh.UnionGroups(group1, group2, name)
2714
2715     def UnionListOfGroups(self, groups, name):
2716         """
2717         Produce a union list of groups.
2718         New group is created. All mesh elements that are present in
2719         initial groups are added to the new one
2720
2721         Parameters:
2722            groups: list of :class:`SMESH.SMESH_GroupBase`
2723
2724         Returns:
2725                 instance of :class:`SMESH.SMESH_Group`
2726         """
2727         return self.mesh.UnionListOfGroups(groups, name)
2728
2729     def IntersectGroups(self, group1, group2, name):
2730         """
2731         Prodice an intersection of two groups.
2732         A new group is created. All mesh elements that are common
2733         for the two initial groups are added to the new one.
2734
2735         Parameters:
2736            group1 (SMESH.SMESH_GroupBase): a group
2737            group2 (SMESH.SMESH_GroupBase): another group
2738
2739         Returns:
2740                 instance of :class:`SMESH.SMESH_Group`
2741         """
2742
2743         return self.mesh.IntersectGroups(group1, group2, name)
2744
2745     def IntersectListOfGroups(self, groups, name):
2746         """
2747         Produce an intersection of groups.
2748         New group is created. All mesh elements that are present in all
2749         initial groups simultaneously are added to the new one
2750
2751         Parameters:
2752            groups: a list of :class:`SMESH.SMESH_GroupBase`
2753
2754         Returns:
2755                 instance of :class:`SMESH.SMESH_Group`
2756         """
2757         return self.mesh.IntersectListOfGroups(groups, name)
2758
2759     def CutGroups(self, main_group, tool_group, name):
2760         """
2761         Produce a cut of two groups.
2762         A new group is created. All mesh elements that are present in
2763         the main group but are not present in the tool group are added to the new one
2764
2765         Parameters:
2766            main_group (SMESH.SMESH_GroupBase): a group to cut from
2767            tool_group (SMESH.SMESH_GroupBase): a group to cut by
2768
2769         Returns:
2770                 an instance of :class:`SMESH.SMESH_Group`
2771         """
2772
2773         return self.mesh.CutGroups(main_group, tool_group, name)
2774
2775     def CutListOfGroups(self, main_groups, tool_groups, name):
2776         """
2777         Produce a cut of groups.
2778         A new group is created. All mesh elements that are present in main groups
2779         but do not present in tool groups are added to the new one
2780
2781         Parameters:
2782            main_group: groups to cut from  (list of :class:`SMESH.SMESH_GroupBase`)
2783            tool_group: groups to cut by    (list of :class:`SMESH.SMESH_GroupBase`)
2784
2785         Returns:
2786                 an instance of :class:`SMESH.SMESH_Group`
2787         """
2788
2789         return self.mesh.CutListOfGroups(main_groups, tool_groups, name)
2790
2791     def CreateDimGroup(self, groups, elemType, name,
2792                        nbCommonNodes = SMESH.ALL_NODES, underlyingOnly = True):
2793         """
2794         Create a standalone group of entities basing on nodes of other groups.
2795
2796         Parameters:
2797                 groups: list of reference :class:`sub-meshes, groups or filters <SMESH.SMESH_IDSource>`, of any type.
2798                 elemType: a type of elements to include to the new group; either of
2799                         (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME).
2800                 name: a name of the new group.
2801                 nbCommonNodes: a criterion of inclusion of an element to the new group
2802                         basing on number of element nodes common with reference *groups*.
2803                         Meaning of possible values are:
2804
2805                                 - SMESH.ALL_NODES - include if all nodes are common,
2806                                 - SMESH.MAIN - include if all corner nodes are common (meaningful for a quadratic mesh),
2807                                 - SMESH.AT_LEAST_ONE - include if one or more node is common,
2808                                 - SMEHS.MAJORITY - include if half of nodes or more are common.
2809                 underlyingOnly: if *True* (default), an element is included to the
2810                         new group provided that it is based on nodes of an element of *groups*;
2811                         in this case the reference *groups* are supposed to be of higher dimension
2812                         than *elemType*, which can be useful for example to get all faces lying on
2813                         volumes of the reference *groups*.
2814
2815         Returns:
2816                 an instance of :class:`SMESH.SMESH_Group`
2817         """
2818
2819         if isinstance( groups, SMESH._objref_SMESH_IDSource ):
2820             groups = [groups]
2821         return self.mesh.CreateDimGroup(groups, elemType, name, nbCommonNodes, underlyingOnly)
2822
2823
2824     def ConvertToStandalone(self, group):
2825         """
2826         Convert group on geom into standalone group
2827         """
2828
2829         return self.mesh.ConvertToStandalone(group)
2830
2831     # Get some info about mesh:
2832     # ------------------------
2833
2834     def GetLog(self, clearAfterGet):
2835         """
2836         Return the log of nodes and elements added or removed
2837         since the previous clear of the log.
2838
2839         Parameters:
2840                 clearAfterGet: log is emptied after Get (safe if concurrents access)
2841
2842         Returns:
2843                 list of SMESH.log_block structures { commandType, number, coords, indexes }
2844         """
2845
2846         return self.mesh.GetLog(clearAfterGet)
2847
2848     def ClearLog(self):
2849         """
2850         Clear the log of nodes and elements added or removed since the previous
2851         clear. Must be used immediately after :meth:`GetLog` if clearAfterGet is false.
2852         """
2853
2854         self.mesh.ClearLog()
2855
2856     def SetAutoColor(self, theAutoColor):
2857         """
2858         Toggle auto color mode on the object.
2859         If switched on, a default color of a new group in Create Group dialog is chosen randomly.
2860
2861         Parameters:
2862                 theAutoColor (boolean): the flag which toggles auto color mode.
2863         """
2864
2865         self.mesh.SetAutoColor(theAutoColor)
2866
2867     def GetAutoColor(self):
2868         """
2869         Get flag of object auto color mode.
2870
2871         Returns:
2872                 True or False
2873         """
2874
2875         return self.mesh.GetAutoColor()
2876
2877     def GetId(self):
2878         """
2879         Get the internal ID
2880
2881         Returns:
2882             integer value, which is the internal Id of the mesh
2883         """
2884
2885         return self.mesh.GetId()
2886
2887     def HasDuplicatedGroupNamesMED(self):
2888         """
2889         Check the group names for duplications.
2890         Consider the maximum group name length stored in MED file.
2891
2892         Returns:
2893             True or False
2894         """
2895
2896         return self.mesh.HasDuplicatedGroupNamesMED()
2897
2898     def GetMeshEditor(self):
2899         """
2900         Obtain the mesh editor tool
2901
2902         Returns:
2903             an instance of :class:`SMESH.SMESH_MeshEditor`
2904         """
2905
2906         return self.editor
2907
2908     def GetIDSource(self, ids, elemType = SMESH.ALL):
2909         """
2910         Wrap a list of IDs of elements or nodes into :class:`SMESH.SMESH_IDSource` which
2911         can be passed as argument to a method accepting :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
2912