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