Salome HOME
Allow smeshBuilder.New(salome.myStudy) but print a warning
[modules/smesh.git] / src / SMESH_SWIG / smeshBuilder.py
1 # Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
2 #
3 # This library is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU Lesser General Public
5 # License as published by the Free Software Foundation; either
6 # version 2.1 of the License, or (at your option) any later version.
7 #
8 # This library is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 # Lesser General Public License for more details.
12 #
13 # You should have received a copy of the GNU Lesser General Public
14 # License along with this library; if not, write to the Free Software
15 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 #
17 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 #
19 #  File   : smeshBuilder.py
20 #  Author : Francis KLOSS, OCC
21 #  Module : SMESH
22
23 import salome
24 from salome.geom import geomBuilder
25
26 import SMESH # This is necessary for back compatibility
27 import omniORB                                   # back compatibility
28 SMESH.MED_V2_1 = omniORB.EnumItem("MED_V2_1", 0) # back compatibility
29 SMESH.MED_V2_2 = omniORB.EnumItem("MED_V2_2", 1) # back compatibility
30
31 from   SMESH import *
32 from   salome.smesh.smesh_algorithm import Mesh_Algorithm
33
34 import SALOME
35 import SALOMEDS
36 import os
37 import inspect
38
39 # In case the omniORBpy EnumItem class does not fully support Python 3
40 # (for instance in version 4.2.1-2), the comparison ordering methods must be
41 # defined
42 #
43 try:
44     SMESH.Entity_Triangle < SMESH.Entity_Quadrangle
45 except TypeError:
46     def enumitem_eq(self, other):
47         try:
48             if isinstance(other, omniORB.EnumItem):
49                 if other._parent_id == self._parent_id:
50                     return self._v == other._v
51                 else:
52                     return self._parent_id == other._parent_id
53             else:
54                 return id(self) == id(other)
55         except:
56             return id(self) == id(other)
57
58     def enumitem_lt(self, other):
59         try:
60             if isinstance(other, omniORB.EnumItem):
61                 if other._parent_id == self._parent_id:
62                     return self._v < other._v
63                 else:
64                     return self._parent_id < other._parent_id
65             else:
66                 return id(self) < id(other)
67         except:
68             return id(self) < id(other)
69
70     def enumitem_le(self, other):
71         try:
72             if isinstance(other, omniORB.EnumItem):
73                 if other._parent_id == self._parent_id:
74                     return self._v <= other._v
75                 else:
76                     return self._parent_id <= other._parent_id
77             else:
78                 return id(self) <= id(other)
79         except:
80             return id(self) <= id(other)
81
82     def enumitem_gt(self, other):
83         try:
84             if isinstance(other, omniORB.EnumItem):
85                 if other._parent_id == self._parent_id:
86                     return self._v > other._v
87                 else:
88                     return self._parent_id > other._parent_id
89             else:
90                 return id(self) > id(other)
91         except:
92             return id(self) > id(other)
93
94     def enumitem_ge(self, other):
95         try:
96             if isinstance(other, omniORB.EnumItem):
97                 if other._parent_id == self._parent_id:
98                     return self._v >= other._v
99                 else:
100                     return self._parent_id >= other._parent_id
101             else:
102                 return id(self) >= id(other)
103         except:
104             return id(self) >= id(other)
105
106     omniORB.EnumItem.__eq__ = enumitem_eq
107     omniORB.EnumItem.__lt__ = enumitem_lt
108     omniORB.EnumItem.__le__ = enumitem_le
109     omniORB.EnumItem.__gt__ = enumitem_gt
110     omniORB.EnumItem.__ge__ = enumitem_ge
111
112
113 class MeshMeta(type):
114     """Private class used to workaround a problem that sometimes isinstance(m, Mesh) returns False
115     """
116     def __instancecheck__(cls, inst):
117         """Implement isinstance(inst, cls)."""
118         return any(cls.__subclasscheck__(c)
119                    for c in {type(inst), inst.__class__})
120
121     def __subclasscheck__(cls, sub):
122         """Implement issubclass(sub, cls)."""
123         return type.__subclasscheck__(cls, sub) or (cls.__name__ == sub.__name__ and cls.__module__ == sub.__module__)
124
125 def DegreesToRadians(AngleInDegrees):
126     """Convert an angle from degrees to radians
127     """
128     from math import pi
129     return AngleInDegrees * pi / 180.0
130
131 import salome_notebook
132 notebook = salome_notebook.notebook
133 # Salome notebook variable separator
134 var_separator = ":"
135
136 def ParseParameters(*args):
137     """
138     Return list of variable values from salome notebook.
139     The last argument, if is callable, is used to modify values got from notebook
140     """
141     Result = []
142     Parameters = ""
143     hasVariables = False
144     varModifFun=None
145     if args and callable(args[-1]):
146         args, varModifFun = args[:-1], args[-1]
147     for parameter in args:
148
149         Parameters += str(parameter) + var_separator
150
151         if isinstance(parameter,str):
152             # check if there is an inexistent variable name
153             if not notebook.isVariable(parameter):
154                 raise ValueError("Variable with name '" + parameter + "' doesn't exist!!!")
155             parameter = notebook.get(parameter)
156             hasVariables = True
157             if varModifFun:
158                 parameter = varModifFun(parameter)
159                 pass
160             pass
161         Result.append(parameter)
162
163         pass
164     Parameters = Parameters[:-1]
165     Result.append( Parameters )
166     Result.append( hasVariables )
167     return Result
168
169 def ParseAngles(*args):
170     """
171     Parse parameters while converting variables to radians
172     """
173     return ParseParameters( *( args + (DegreesToRadians, )))
174
175 def __initPointStruct(point,*args):
176     """
177     Substitute PointStruct.__init__() to create SMESH.PointStruct using notebook variables.
178     Parameters are stored in PointStruct.parameters attribute
179     """
180     point.x, point.y, point.z, point.parameters,hasVars = ParseParameters(*args)
181     pass
182 SMESH.PointStruct.__init__ = __initPointStruct
183
184 def __initAxisStruct(ax,*args):
185     """
186     Substitute AxisStruct.__init__() to create SMESH.AxisStruct using notebook variables.
187     Parameters are stored in AxisStruct.parameters attribute
188     """
189     if len( args ) != 6:
190         raise RuntimeError("Bad nb args (%s) passed in SMESH.AxisStruct(x,y,z,dx,dy,dz)"%(len( args )))
191     ax.x, ax.y, ax.z, ax.vx, ax.vy, ax.vz, ax.parameters,hasVars = ParseParameters(*args)
192     pass
193 SMESH.AxisStruct.__init__ = __initAxisStruct
194
195 smeshPrecisionConfusion = 1.e-07
196 def IsEqual(val1, val2, tol=smeshPrecisionConfusion):
197     """Compare real values using smeshPrecisionConfusion as tolerance
198     """
199     if abs(val1 - val2) < tol:
200         return True
201     return False
202
203 NO_NAME = "NoName"
204
205 def GetName(obj):
206     """
207     Return a name of an object
208     
209     Returns:
210         object name
211     """
212     if obj:
213         # object not null
214         if isinstance(obj, SALOMEDS._objref_SObject):
215             # study object
216             return obj.GetName()
217         try:
218             ior  = salome.orb.object_to_string(obj)
219         except:
220             ior = None
221         if ior:
222             sobj = salome.myStudy.FindObjectIOR(ior)
223             if sobj:
224                 return sobj.GetName()
225             if hasattr(obj, "GetName"):
226                 # unknown CORBA object, having GetName() method
227                 return obj.GetName()
228             else:
229                 # unknown CORBA object, no GetName() method
230                 return NO_NAME
231             pass
232         if hasattr(obj, "GetName"):
233             # unknown non-CORBA object, having GetName() method
234             return obj.GetName()
235         pass
236     raise RuntimeError("Null or invalid object")
237
238 def TreatHypoStatus(status, hypName, geomName, isAlgo, mesh):
239     """
240     Print error message if a hypothesis was not assigned.
241     """
242     if isAlgo:
243         hypType = "algorithm"
244     else:
245         hypType = "hypothesis"
246         pass
247     reason = ""
248     if hasattr( status, "__getitem__" ):
249         status, reason = status[0], status[1]
250     if status == HYP_UNKNOWN_FATAL:
251         reason = "for unknown reason"
252     elif status == HYP_INCOMPATIBLE:
253         reason = "this hypothesis mismatches the algorithm"
254     elif status == HYP_NOTCONFORM:
255         reason = "a non-conform mesh would be built"
256     elif status == HYP_ALREADY_EXIST:
257         if isAlgo: return # it does not influence anything
258         reason = hypType + " of the same dimension is already assigned to this shape"
259     elif status == HYP_BAD_DIM:
260         reason = hypType + " mismatches the shape"
261     elif status == HYP_CONCURRENT :
262         reason = "there are concurrent hypotheses on sub-shapes"
263     elif status == HYP_BAD_SUBSHAPE:
264         reason = "the shape is neither the main one, nor its sub-shape, nor a valid group"
265     elif status == HYP_BAD_GEOMETRY:
266         reason = "the algorithm is not applicable to this geometry"
267     elif status == HYP_HIDDEN_ALGO:
268         reason = "it is hidden by an algorithm of an upper dimension, which generates elements of all dimensions"
269     elif status == HYP_HIDING_ALGO:
270         reason = "it hides algorithms of lower dimensions by generating elements of all dimensions"
271     elif status == HYP_NEED_SHAPE:
272         reason = "algorithm can't work without shape"
273     elif status == HYP_INCOMPAT_HYPS:
274         pass
275     else:
276         return
277     where = geomName
278     if where:
279         where = '"%s"' % geomName
280         if mesh:
281             meshName = GetName( mesh )
282             if meshName and meshName != NO_NAME:
283                 where = '"%s" shape in "%s" mesh ' % ( geomName, meshName )
284     if status < HYP_UNKNOWN_FATAL and where:
285         print('"%s" was assigned to %s but %s' %( hypName, where, reason ))
286     elif where:
287         print('"%s" was not assigned to %s : %s' %( hypName, where, reason ))
288     else:
289         print('"%s" was not assigned : %s' %( hypName, reason ))
290         pass
291
292 def AssureGeomPublished(mesh, geom, name=''):
293     """
294     Private method. Add geom (sub-shape of the main shape) into the study if not yet there
295     """
296     if not isinstance( geom, geomBuilder.GEOM._objref_GEOM_Object ):
297         return
298     if not geom.GetStudyEntry():
299         ## get a name
300         if not name and geom.GetShapeType() != geomBuilder.GEOM.COMPOUND:
301             # for all groups SubShapeName() return "Compound_-1"
302             name = mesh.geompyD.SubShapeName(geom, mesh.geom)
303         if not name:
304             name = "%s_%s"%(geom.GetShapeType(), id(geom)%10000)
305         ## publish
306         mesh.geompyD.addToStudyInFather( mesh.geom, geom, name )
307     return
308
309 def FirstVertexOnCurve(mesh, edge):
310     """
311     Returns:
312         the first vertex of a geometrical edge by ignoring orientation
313     """
314     vv = mesh.geompyD.SubShapeAll( edge, geomBuilder.geomBuilder.ShapeType["VERTEX"])
315     if not vv:
316         raise TypeError("Given object has no vertices")
317     if len( vv ) == 1: return vv[0]
318     v0   = mesh.geompyD.MakeVertexOnCurve(edge,0.)
319     xyz  = mesh.geompyD.PointCoordinates( v0 ) # coords of the first vertex
320     xyz1 = mesh.geompyD.PointCoordinates( vv[0] )
321     xyz2 = mesh.geompyD.PointCoordinates( vv[1] )
322     dist1, dist2 = 0,0
323     for i in range(3):
324         dist1 += abs( xyz[i] - xyz1[i] )
325         dist2 += abs( xyz[i] - xyz2[i] )
326     if dist1 < dist2:
327         return vv[0]
328     else:
329         return vv[1]
330
331 smeshInst = None
332 """
333 Warning:
334     smeshInst is a singleton
335 """
336 engine = None
337 doLcc = False
338 created = False
339
340 class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
341     """
342     This class allows to create, load or manipulate meshes.
343     It has a set of methods to create, load or copy meshes, to combine several meshes, etc.
344     It also has methods to get infos and measure meshes.
345     """
346
347     # MirrorType enumeration
348     POINT = SMESH_MeshEditor.POINT
349     AXIS =  SMESH_MeshEditor.AXIS
350     PLANE = SMESH_MeshEditor.PLANE
351
352     # Smooth_Method enumeration
353     LAPLACIAN_SMOOTH = SMESH_MeshEditor.LAPLACIAN_SMOOTH
354     CENTROIDAL_SMOOTH = SMESH_MeshEditor.CENTROIDAL_SMOOTH
355
356     PrecisionConfusion = smeshPrecisionConfusion
357
358     # TopAbs_State enumeration
359     [TopAbs_IN, TopAbs_OUT, TopAbs_ON, TopAbs_UNKNOWN] = list(range(4))
360
361     # Methods of splitting a hexahedron into tetrahedra
362     Hex_5Tet, Hex_6Tet, Hex_24Tet, Hex_2Prisms, Hex_4Prisms = 1, 2, 3, 1, 2
363
364     def __new__(cls, *args):
365         global engine
366         global smeshInst
367         global doLcc
368         #print("==== __new__", engine, smeshInst, doLcc)
369
370         if smeshInst is None:
371             # smesh engine is either retrieved from engine, or created
372             smeshInst = engine
373             # Following test avoids a recursive loop
374             if doLcc:
375                 if smeshInst is not None:
376                     # smesh engine not created: existing engine found
377                     doLcc = False
378                 if doLcc:
379                     doLcc = False
380                     # FindOrLoadComponent called:
381                     # 1. CORBA resolution of server
382                     # 2. the __new__ method is called again
383                     #print("==== smeshInst = lcc.FindOrLoadComponent ", engine, smeshInst, doLcc)
384                     smeshInst = salome.lcc.FindOrLoadComponent( "FactoryServer", "SMESH" )
385             else:
386                 # FindOrLoadComponent not called
387                 if smeshInst is None:
388                     # smeshBuilder instance is created from lcc.FindOrLoadComponent
389                     #print("==== smeshInst = super(smeshBuilder,cls).__new__(cls) ", engine, smeshInst, doLcc)
390                     smeshInst = super(smeshBuilder,cls).__new__(cls)
391                 else:
392                     # smesh engine not created: existing engine found
393                     #print("==== existing ", engine, smeshInst, doLcc)
394                     pass
395             #print("====1 ", smeshInst)
396             return smeshInst
397
398         #print("====2 ", smeshInst)
399         return smeshInst
400
401     def __init__(self, *args):
402         global created
403         #print("--------------- smeshbuilder __init__ ---", created)
404         if not created:
405             created = True
406             SMESH._objref_SMESH_Gen.__init__(self, *args)
407
408
409     def DumpPython(self, theStudy, theIsPublished=True, theIsMultiFile=True):
410         """
411         Dump component to the Python script.
412         This method overrides IDL function to allow default values for the parameters.
413         """
414
415         return SMESH._objref_SMESH_Gen.DumpPython(self, theStudy, theIsPublished, theIsMultiFile)
416
417     def SetDumpPythonHistorical(self, isHistorical):
418         """
419         Set mode of DumpPython(), *historical* or *snapshot*.
420         In the *historical* mode, the Python Dump script includes all commands
421         performed by SMESH engine. In the *snapshot* mode, commands
422         relating to objects removed from the Study are excluded from the script
423         as well as commands not influencing the current state of meshes
424         """
425
426         if isHistorical: val = "true"
427         else:            val = "false"
428         SMESH._objref_SMESH_Gen.SetOption(self, "historical_python_dump", val)
429
430     def init_smesh(self,geompyD = None):
431         """
432         Set Geometry component
433         """    
434         #print("init_smesh")
435         self.UpdateStudy(geompyD)
436         notebook.myStudy = salome.myStudy
437
438     def Mesh(self, obj=0, name=0):
439         """
440         Create a mesh. This mesh can be either 
441
442         * an empty mesh not bound to geometry, if *obj* == 0
443         * an empty mesh bound to geometry, if *obj* is GEOM.GEOM_Object
444         * a mesh wrapping a :class:`CORBA mesh <SMESH.SMESH_Mesh>` given as *obj* parameter.
445
446         Parameters:
447             obj: either 
448
449                    1. a :class:`CORBA mesh <SMESH.SMESH_Mesh>` got by calling e.g.
450                       ::
451
452                         salome.myStudy.FindObjectID("0:1:2:3").GetObject() 
453
454                    2. a geometrical object for meshing
455                    3. none.
456             name: the name for the new mesh.
457
458         Returns:
459             an instance of class :class:`Mesh`.
460         """
461
462         if isinstance(obj,str):
463             obj,name = name,obj
464         return Mesh(self, self.geompyD, obj, name)
465
466     def EnumToLong(self,theItem):
467         """
468         Return a long value from enumeration
469         """
470
471         return theItem._v
472
473     def ColorToString(self,c):
474         """
475         Convert SALOMEDS.Color to string.
476         To be used with filters.
477
478         Parameters:
479             c: color value (SALOMEDS.Color)
480
481         Returns:
482             a string representation of the color.
483         """
484
485         val = ""
486         if isinstance(c, SALOMEDS.Color):
487             val = "%s;%s;%s" % (c.R, c.G, c.B)
488         elif isinstance(c, str):
489             val = c
490         else:
491             raise ValueError("Color value should be of string or SALOMEDS.Color type")
492         return val
493
494     def GetPointStruct(self,theVertex):
495         """
496         Get :class:`SMESH.PointStruct` from vertex
497
498         Parameters:
499                 theVertex (GEOM.GEOM_Object): vertex
500
501         Returns:
502                 :class:`SMESH.PointStruct`
503         """
504
505         [x, y, z] = self.geompyD.PointCoordinates(theVertex)
506         return PointStruct(x,y,z)
507
508     def GetDirStruct(self,theVector):
509         """
510         Get :class:`SMESH.DirStruct` from vector
511
512         Parameters:
513                 theVector (GEOM.GEOM_Object): vector
514
515         Returns:
516                 :class:`SMESH.DirStruct`
517         """
518
519         vertices = self.geompyD.SubShapeAll( theVector, geomBuilder.geomBuilder.ShapeType["VERTEX"] )
520         if(len(vertices) != 2):
521             print("Error: vector object is incorrect.")
522             return None
523         p1 = self.geompyD.PointCoordinates(vertices[0])
524         p2 = self.geompyD.PointCoordinates(vertices[1])
525         pnt = PointStruct(p2[0]-p1[0], p2[1]-p1[1], p2[2]-p1[2])
526         dirst = DirStruct(pnt)
527         return dirst
528
529     def MakeDirStruct(self,x,y,z):
530         """
531         Make :class:`SMESH.DirStruct` from a triplet of floats
532
533         Parameters:
534                 x,y,z (float): vector components
535
536         Returns:
537                 :class:`SMESH.DirStruct`
538         """
539
540         pnt = PointStruct(x,y,z)
541         return DirStruct(pnt)
542
543     def GetAxisStruct(self,theObj):
544         """
545         Get :class:`SMESH.AxisStruct` from a geometrical object
546
547         Parameters:
548             theObj (GEOM.GEOM_Object): line or plane
549
550         Returns:
551             :class:`SMESH.AxisStruct`
552         """
553         import GEOM
554         edges = self.geompyD.SubShapeAll( theObj, geomBuilder.geomBuilder.ShapeType["EDGE"] )
555         axis = None
556         if len(edges) > 1:
557             vertex1, vertex2 = self.geompyD.SubShapeAll( edges[0], geomBuilder.geomBuilder.ShapeType["VERTEX"] )
558             vertex3, vertex4 = self.geompyD.SubShapeAll( edges[1], geomBuilder.geomBuilder.ShapeType["VERTEX"] )
559             vertex1 = self.geompyD.PointCoordinates(vertex1)
560             vertex2 = self.geompyD.PointCoordinates(vertex2)
561             vertex3 = self.geompyD.PointCoordinates(vertex3)
562             vertex4 = self.geompyD.PointCoordinates(vertex4)
563             v1 = [vertex2[0]-vertex1[0], vertex2[1]-vertex1[1], vertex2[2]-vertex1[2]]
564             v2 = [vertex4[0]-vertex3[0], vertex4[1]-vertex3[1], vertex4[2]-vertex3[2]]
565             normal = [ v1[1]*v2[2]-v2[1]*v1[2], v1[2]*v2[0]-v2[2]*v1[0], v1[0]*v2[1]-v2[0]*v1[1] ]
566             axis = AxisStruct(vertex1[0], vertex1[1], vertex1[2], normal[0], normal[1], normal[2])
567             axis._mirrorType = SMESH.SMESH_MeshEditor.PLANE
568         elif len(edges) == 1:
569             vertex1, vertex2 = self.geompyD.SubShapeAll( edges[0], geomBuilder.geomBuilder.ShapeType["VERTEX"] )
570             p1 = self.geompyD.PointCoordinates( vertex1 )
571             p2 = self.geompyD.PointCoordinates( vertex2 )
572             axis = AxisStruct(p1[0], p1[1], p1[2], p2[0]-p1[0], p2[1]-p1[1], p2[2]-p1[2])
573             axis._mirrorType = SMESH.SMESH_MeshEditor.AXIS
574         elif theObj.GetShapeType() == GEOM.VERTEX:
575             x,y,z = self.geompyD.PointCoordinates( theObj )
576             axis = AxisStruct( x,y,z, 1,0,0,)
577             axis._mirrorType = SMESH.SMESH_MeshEditor.POINT
578         return axis
579
580     # From SMESH_Gen interface:
581     # ------------------------
582
583     def SetName(self, obj, name):
584         """
585         Set the given name to an object
586
587         Parameters:
588                 obj: the object to rename
589                 name: a new object name
590         """
591
592         if isinstance( obj, Mesh ):
593             obj = obj.GetMesh()
594         elif isinstance( obj, Mesh_Algorithm ):
595             obj = obj.GetAlgorithm()
596         ior  = salome.orb.object_to_string(obj)
597         SMESH._objref_SMESH_Gen.SetName(self, ior, name)
598
599     def SetEmbeddedMode( self,theMode ):
600         """
601         Set the current mode
602         """
603
604         SMESH._objref_SMESH_Gen.SetEmbeddedMode(self,theMode)
605
606     def IsEmbeddedMode(self):
607         """
608         Get the current mode
609         """
610
611         return SMESH._objref_SMESH_Gen.IsEmbeddedMode(self)
612
613     def UpdateStudy( self, geompyD = None  ):
614         """
615         Update the current study. Calling UpdateStudy() allows to
616         update meshes at switching GEOM->SMESH
617         """
618         #self.UpdateStudy()
619         if not geompyD:
620             from salome.geom import geomBuilder
621             geompyD = geomBuilder.geom
622             if not geompyD:
623                 geompyD = geomBuilder.New()
624             pass
625         self.geompyD=geompyD
626         self.SetGeomEngine(geompyD)
627         SMESH._objref_SMESH_Gen.UpdateStudy(self)
628         sb = salome.myStudy.NewBuilder()
629         sc = salome.myStudy.FindComponent("SMESH")
630         if sc:
631             sb.LoadWith(sc, self)
632         pass
633     
634     def SetEnablePublish( self, theIsEnablePublish ):
635         """
636         Set enable publishing in the study. Calling SetEnablePublish( False ) allows to
637         switch **off** publishing in the Study of mesh objects.
638         """
639        #self.SetEnablePublish(theIsEnablePublish)
640         SMESH._objref_SMESH_Gen.SetEnablePublish(self,theIsEnablePublish)
641         global notebook
642         notebook = salome_notebook.NoteBook( theIsEnablePublish )
643
644
645     def CreateMeshesFromUNV( self,theFileName ):
646         """
647         Create a Mesh object importing data from the given UNV file
648
649         Returns:
650                 an instance of class :class:`Mesh`
651         """
652
653         aSmeshMesh = SMESH._objref_SMESH_Gen.CreateMeshesFromUNV(self,theFileName)
654         aMesh = Mesh(self, self.geompyD, aSmeshMesh)
655         return aMesh
656
657     def CreateMeshesFromMED( self,theFileName ):
658         """
659         Create a Mesh object(s) importing data from the given MED file
660
661         Returns:
662                 a tuple ( list of class :class:`Mesh` instances, 
663                 :class:`SMESH.DriverMED_ReadStatus` )
664         """
665
666         aSmeshMeshes, aStatus = SMESH._objref_SMESH_Gen.CreateMeshesFromMED(self,theFileName)
667         aMeshes = [ Mesh(self, self.geompyD, m) for m in aSmeshMeshes ]
668         return aMeshes, aStatus
669
670     def CreateMeshesFromSAUV( self,theFileName ):
671         """
672         Create a Mesh object(s) importing data from the given SAUV file
673
674         Returns:
675                 a tuple ( list of class :class:`Mesh` instances, :class:`SMESH.DriverMED_ReadStatus` )
676         """
677
678         aSmeshMeshes, aStatus = SMESH._objref_SMESH_Gen.CreateMeshesFromSAUV(self,theFileName)
679         aMeshes = [ Mesh(self, self.geompyD, m) for m in aSmeshMeshes ]
680         return aMeshes, aStatus
681
682     def CreateMeshesFromSTL( self, theFileName ):
683         """
684         Create a Mesh object importing data from the given STL file
685
686         Returns:
687                 an instance of class :class:`Mesh`
688         """
689
690         aSmeshMesh = SMESH._objref_SMESH_Gen.CreateMeshesFromSTL(self,theFileName)
691         aMesh = Mesh(self, self.geompyD, aSmeshMesh)
692         return aMesh
693
694     def CreateMeshesFromCGNS( self, theFileName ):
695         """
696         Create Mesh objects importing data from the given CGNS file
697
698         Returns:
699                 a tuple ( list of class :class:`Mesh` instances, :class:`SMESH.DriverMED_ReadStatus` )
700         """
701
702         aSmeshMeshes, aStatus = SMESH._objref_SMESH_Gen.CreateMeshesFromCGNS(self,theFileName)
703         aMeshes = [ Mesh(self, self.geompyD, m) for m in aSmeshMeshes ]
704         return aMeshes, aStatus
705
706     def CreateMeshesFromGMF( self, theFileName ):
707         """
708         Create a Mesh object importing data from the given GMF file.
709         GMF files must have .mesh extension for the ASCII format and .meshb for
710         the binary format.
711
712         Returns:
713                 ( an instance of class :class:`Mesh`, :class:`SMESH.ComputeError` )
714         """
715
716         aSmeshMesh, error = SMESH._objref_SMESH_Gen.CreateMeshesFromGMF(self,
717                                                                         theFileName,
718                                                                         True)
719         if error.comment: print("*** CreateMeshesFromGMF() errors:\n", error.comment)
720         return Mesh(self, self.geompyD, aSmeshMesh), error
721
722     def Concatenate( self, meshes, uniteIdenticalGroups,
723                      mergeNodesAndElements = False, mergeTolerance = 1e-5, allGroups = False,
724                      name = ""):
725         """
726         Concatenate the given meshes into one mesh. All groups of input meshes will be
727         present in the new mesh.
728
729         Parameters:
730                 meshes: :class:`meshes, sub-meshes, groups or filters <SMESH.SMESH_IDSource>` to combine into one mesh
731                 uniteIdenticalGroups: if True, groups with same names are united, else they are renamed
732                 mergeNodesAndElements: if True, equal nodes and elements are merged
733                 mergeTolerance: tolerance for merging nodes
734                 allGroups: forces creation of groups corresponding to every input mesh
735                 name: name of a new mesh
736
737         Returns:
738                 an instance of class :class:`Mesh`
739         """
740
741         if not meshes: return None
742         for i,m in enumerate(meshes):
743             if isinstance(m, Mesh):
744                 meshes[i] = m.GetMesh()
745         mergeTolerance,Parameters,hasVars = ParseParameters(mergeTolerance)
746         meshes[0].SetParameters(Parameters)
747         if allGroups:
748             aSmeshMesh = SMESH._objref_SMESH_Gen.ConcatenateWithGroups(
749                 self,meshes,uniteIdenticalGroups,mergeNodesAndElements,mergeTolerance)
750         else:
751             aSmeshMesh = SMESH._objref_SMESH_Gen.Concatenate(
752                 self,meshes,uniteIdenticalGroups,mergeNodesAndElements,mergeTolerance)
753         aMesh = Mesh(self, self.geompyD, aSmeshMesh, name=name)
754         return aMesh
755
756     def CopyMesh( self, meshPart, meshName, toCopyGroups=False, toKeepIDs=False):
757         """
758         Create a mesh by copying a part of another mesh.
759
760         Parameters:
761                 meshPart: a part of mesh to copy, either 
762                         :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`.
763                         To copy nodes or elements not forming any mesh object,
764                         pass result of :meth:`Mesh.GetIDSource` as *meshPart*
765                 meshName: a name of the new mesh
766                 toCopyGroups: to create in the new mesh groups the copied elements belongs to
767                 toKeepIDs: to preserve order of the copied elements or not
768
769         Returns:
770                 an instance of class :class:`Mesh`
771         """
772
773         if (isinstance( meshPart, Mesh )):
774             meshPart = meshPart.GetMesh()
775         mesh = SMESH._objref_SMESH_Gen.CopyMesh( self,meshPart,meshName,toCopyGroups,toKeepIDs )
776         return Mesh(self, self.geompyD, mesh)
777
778     def GetSubShapesId( self, theMainObject, theListOfSubObjects ):
779         """
780         Return IDs of sub-shapes
781
782         Parameters:
783                 theMainObject (GEOM.GEOM_Object): a shape
784                 theListOfSubObjects: sub-shapes (list of GEOM.GEOM_Object)
785         Returns:
786                 the list of integer values
787         """
788
789         return SMESH._objref_SMESH_Gen.GetSubShapesId(self,theMainObject, theListOfSubObjects)
790
791     def GetPattern(self):
792         """
793         Create a pattern mapper.
794
795         Returns:
796                 an instance of :class:`SMESH.SMESH_Pattern`
797
798         :ref:`Example of Patterns usage <tui_pattern_mapping>`
799         """
800
801         return SMESH._objref_SMESH_Gen.GetPattern(self)
802
803     def SetBoundaryBoxSegmentation(self, nbSegments):
804         """
805         Set number of segments per diagonal of boundary box of geometry, by which
806         default segment length of appropriate 1D hypotheses is defined in GUI.
807         Default value is 10.
808         """
809
810         SMESH._objref_SMESH_Gen.SetBoundaryBoxSegmentation(self,nbSegments)
811
812     # Filtering. Auxiliary functions:
813     # ------------------------------
814
815     def GetEmptyCriterion(self):
816         """
817         Create an empty criterion
818
819         Returns:
820                 :class:`SMESH.Filter.Criterion`
821         """
822
823         Type = self.EnumToLong(FT_Undefined)
824         Compare = self.EnumToLong(FT_Undefined)
825         Threshold = 0
826         ThresholdStr = ""
827         ThresholdID = ""
828         UnaryOp = self.EnumToLong(FT_Undefined)
829         BinaryOp = self.EnumToLong(FT_Undefined)
830         Tolerance = 1e-07
831         TypeOfElement = ALL
832         Precision = -1 ##@1e-07
833         return Filter.Criterion(Type, Compare, Threshold, ThresholdStr, ThresholdID,
834                                 UnaryOp, BinaryOp, Tolerance, TypeOfElement, Precision)
835
836     def GetCriterion(self,elementType,
837                      CritType,
838                      Compare = FT_EqualTo,
839                      Threshold="",
840                      UnaryOp=FT_Undefined,
841                      BinaryOp=FT_Undefined,
842                      Tolerance=1e-07):
843         """
844         Create a criterion by the given parameters
845         Criterion structures allow to define complex filters by combining them with logical operations (AND / OR) (see example below)
846
847         Parameters:
848                 elementType: the :class:`type of elements <SMESH.ElementType>` (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME)
849                 CritType: the type of criterion :class:`SMESH.FunctorType` (SMESH.FT_Taper, SMESH.FT_Area, etc.).
850                         Note that the items starting from FT_LessThan are not suitable for *CritType*.
851                 Compare:  belongs to {SMESH.FT_LessThan, SMESH.FT_MoreThan, SMESH.FT_EqualTo}
852                 Threshold: the threshold value (range of ids as string, shape, numeric)
853                 UnaryOp:  SMESH.FT_LogicalNOT or SMESH.FT_Undefined
854                 BinaryOp: a binary logical operation SMESH.FT_LogicalAND, SMESH.FT_LogicalOR or
855                         SMESH.FT_Undefined
856                 Tolerance: the tolerance used by SMESH.FT_BelongToGeom, SMESH.FT_BelongToSurface,
857                         SMESH.FT_LyingOnGeom, SMESH.FT_CoplanarFaces criteria
858
859         Returns:
860                 :class:`SMESH.Filter.Criterion`
861
862         Example: :ref:`combining_filters`
863         """
864
865         if not CritType in SMESH.FunctorType._items:
866             raise TypeError("CritType should be of SMESH.FunctorType")
867         aCriterion               = self.GetEmptyCriterion()
868         aCriterion.TypeOfElement = elementType
869         aCriterion.Type          = self.EnumToLong(CritType)
870         aCriterion.Tolerance     = Tolerance
871
872         aThreshold = Threshold
873
874         if Compare in [FT_LessThan, FT_MoreThan, FT_EqualTo]:
875             aCriterion.Compare = self.EnumToLong(Compare)
876         elif Compare == "=" or Compare == "==":
877             aCriterion.Compare = self.EnumToLong(FT_EqualTo)
878         elif Compare == "<":
879             aCriterion.Compare = self.EnumToLong(FT_LessThan)
880         elif Compare == ">":
881             aCriterion.Compare = self.EnumToLong(FT_MoreThan)
882         elif Compare != FT_Undefined:
883             aCriterion.Compare = self.EnumToLong(FT_EqualTo)
884             aThreshold = Compare
885
886         if CritType in [FT_BelongToGeom,     FT_BelongToPlane, FT_BelongToGenSurface,
887                         FT_BelongToCylinder, FT_LyingOnGeom]:
888             # Check that Threshold is GEOM object
889             if isinstance(aThreshold, geomBuilder.GEOM._objref_GEOM_Object):
890                 aCriterion.ThresholdStr = GetName(aThreshold)
891                 aCriterion.ThresholdID  = aThreshold.GetStudyEntry()
892                 if not aCriterion.ThresholdID:
893                     name = aCriterion.ThresholdStr
894                     if not name:
895                         name = "%s_%s"%(aThreshold.GetShapeType(), id(aThreshold)%10000)
896                     aCriterion.ThresholdID = self.geompyD.addToStudy( aThreshold, name )
897             # or a name of GEOM object
898             elif isinstance( aThreshold, str ):
899                 aCriterion.ThresholdStr = aThreshold
900             else:
901                 raise TypeError("The Threshold should be a shape.")
902             if isinstance(UnaryOp,float):
903                 aCriterion.Tolerance = UnaryOp
904                 UnaryOp = FT_Undefined
905                 pass
906         elif CritType == FT_BelongToMeshGroup:
907             # Check that Threshold is a group
908             if isinstance(aThreshold, SMESH._objref_SMESH_GroupBase):
909                 if aThreshold.GetType() != elementType:
910                     raise ValueError("Group type mismatches Element type")
911                 aCriterion.ThresholdStr = aThreshold.GetName()
912                 aCriterion.ThresholdID  = salome.orb.object_to_string( aThreshold )
913                 study = salome.myStudy
914                 if study:
915                     so = study.FindObjectIOR( aCriterion.ThresholdID )
916                     if so:
917                         entry = so.GetID()
918                         if entry:
919                             aCriterion.ThresholdID = entry
920             else:
921                 raise TypeError("The Threshold should be a Mesh Group")
922         elif CritType == FT_RangeOfIds:
923             # Check that Threshold is string
924             if isinstance(aThreshold, str):
925                 aCriterion.ThresholdStr = aThreshold
926             else:
927                 raise TypeError("The Threshold should be a string.")
928         elif CritType == FT_CoplanarFaces:
929             # Check the Threshold
930             if isinstance(aThreshold, int):
931                 aCriterion.ThresholdID = str(aThreshold)
932             elif isinstance(aThreshold, str):
933                 ID = int(aThreshold)
934                 if ID < 1:
935                     raise ValueError("Invalid ID of mesh face: '%s'"%aThreshold)
936                 aCriterion.ThresholdID = aThreshold
937             else:
938                 raise TypeError("The Threshold should be an ID of mesh face and not '%s'"%aThreshold)
939         elif CritType == FT_ConnectedElements:
940             # Check the Threshold
941             if isinstance(aThreshold, geomBuilder.GEOM._objref_GEOM_Object): # shape
942                 aCriterion.ThresholdID = aThreshold.GetStudyEntry()
943                 if not aCriterion.ThresholdID:
944                     name = aThreshold.GetName()
945                     if not name:
946                         name = "%s_%s"%(aThreshold.GetShapeType(), id(aThreshold)%10000)
947                     aCriterion.ThresholdID = self.geompyD.addToStudy( aThreshold, name )
948             elif isinstance(aThreshold, int): # node id
949                 aCriterion.Threshold = aThreshold
950             elif isinstance(aThreshold, list): # 3 point coordinates
951                 if len( aThreshold ) < 3:
952                     raise ValueError("too few point coordinates, must be 3")
953                 aCriterion.ThresholdStr = " ".join( [str(c) for c in aThreshold[:3]] )
954             elif isinstance(aThreshold, str):
955                 if aThreshold.isdigit():
956                     aCriterion.Threshold = aThreshold # node id
957                 else:
958                     aCriterion.ThresholdStr = aThreshold # hope that it's point coordinates
959             else:
960                 raise TypeError("The Threshold should either a VERTEX, or a node ID, "\
961                       "or a list of point coordinates and not '%s'"%aThreshold)
962         elif CritType == FT_ElemGeomType:
963             # Check the Threshold
964             try:
965                 aCriterion.Threshold = self.EnumToLong(aThreshold)
966                 assert( aThreshold in SMESH.GeometryType._items )
967             except:
968                 if isinstance(aThreshold, int):
969                     aCriterion.Threshold = aThreshold
970                 else:
971                     raise TypeError("The Threshold should be an integer or SMESH.GeometryType.")
972                 pass
973             pass
974         elif CritType == FT_EntityType:
975             # Check the Threshold
976             try:
977                 aCriterion.Threshold = self.EnumToLong(aThreshold)
978                 assert( aThreshold in SMESH.EntityType._items )
979             except:
980                 if isinstance(aThreshold, int):
981                     aCriterion.Threshold = aThreshold
982                 else:
983                     raise TypeError("The Threshold should be an integer or SMESH.EntityType.")
984                 pass
985             pass
986
987         elif CritType == FT_GroupColor:
988             # Check the Threshold
989             try:
990                 aCriterion.ThresholdStr = self.ColorToString(aThreshold)
991             except:
992                 raise TypeError("The threshold value should be of SALOMEDS.Color type")
993             pass
994         elif CritType in [FT_FreeBorders, FT_FreeEdges, FT_FreeNodes, FT_FreeFaces,
995                           FT_LinearOrQuadratic, FT_BadOrientedVolume,
996                           FT_BareBorderFace, FT_BareBorderVolume,
997                           FT_OverConstrainedFace, FT_OverConstrainedVolume,
998                           FT_EqualNodes,FT_EqualEdges,FT_EqualFaces,FT_EqualVolumes ]:
999             # At this point the Threshold is unnecessary
1000             if aThreshold ==  FT_LogicalNOT:
1001                 aCriterion.UnaryOp = self.EnumToLong(FT_LogicalNOT)
1002             elif aThreshold in [FT_LogicalAND, FT_LogicalOR]:
1003                 aCriterion.BinaryOp = aThreshold
1004         else:
1005             # Check Threshold
1006             try:
1007                 aThreshold = float(aThreshold)
1008                 aCriterion.Threshold = aThreshold
1009             except:
1010                 raise TypeError("The Threshold should be a number.")
1011                 return None
1012
1013         if Threshold ==  FT_LogicalNOT or UnaryOp ==  FT_LogicalNOT:
1014             aCriterion.UnaryOp = self.EnumToLong(FT_LogicalNOT)
1015
1016         if Threshold in [FT_LogicalAND, FT_LogicalOR]:
1017             aCriterion.BinaryOp = self.EnumToLong(Threshold)
1018
1019         if UnaryOp in [FT_LogicalAND, FT_LogicalOR]:
1020             aCriterion.BinaryOp = self.EnumToLong(UnaryOp)
1021
1022         if BinaryOp in [FT_LogicalAND, FT_LogicalOR]:
1023             aCriterion.BinaryOp = self.EnumToLong(BinaryOp)
1024
1025         return aCriterion
1026
1027     def GetFilter(self,elementType,
1028                   CritType=FT_Undefined,
1029                   Compare=FT_EqualTo,
1030                   Threshold="",
1031                   UnaryOp=FT_Undefined,
1032                   Tolerance=1e-07,
1033                   mesh=None):
1034         """
1035         Create a filter with the given parameters
1036
1037         Parameters:
1038                 elementType: the :class:`type of elements <SMESH.ElementType>` (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME)
1039                 CritType: the :class:`type of criterion <SMESH.FunctorType>` (SMESH.FT_Taper, SMESH.FT_Area, etc.).
1040                         Note that the items starting from FT_LessThan are not suitable for CritType.
1041                 Compare: belongs to {SMESH.FT_LessThan, SMESH.FT_MoreThan, SMESH.FT_EqualTo}
1042                 Threshold: the threshold value (range of ids as string, shape, numeric)
1043                 UnaryOp:  SMESH.FT_LogicalNOT or SMESH.FT_Undefined
1044                 Tolerance: the tolerance used by SMESH.FT_BelongToGeom, SMESH.FT_BelongToSurface,
1045                         SMESH.FT_LyingOnGeom, SMESH.FT_CoplanarFaces and SMESH.FT_EqualNodes criteria
1046                 mesh: the mesh to initialize the filter with
1047
1048         Returns:
1049                 :class:`SMESH.Filter`
1050
1051         Examples:
1052                See :doc:`Filters usage examples <tui_filters>`
1053         """
1054
1055         aCriterion = self.GetCriterion(elementType, CritType, Compare, Threshold, UnaryOp, FT_Undefined,Tolerance)
1056         aFilterMgr = self.CreateFilterManager()
1057         aFilter = aFilterMgr.CreateFilter()
1058         aCriteria = []
1059         aCriteria.append(aCriterion)
1060         aFilter.SetCriteria(aCriteria)
1061         if mesh:
1062             if isinstance( mesh, Mesh ): aFilter.SetMesh( mesh.GetMesh() )
1063             else                       : aFilter.SetMesh( mesh )
1064         aFilterMgr.UnRegister()
1065         return aFilter
1066
1067     def GetFilterFromCriteria(self,criteria, binOp=SMESH.FT_LogicalAND):
1068         """
1069         Create a filter from criteria
1070
1071         Parameters:
1072                 criteria: a list of :class:`SMESH.Filter.Criterion`
1073                 binOp: binary operator used when binary operator of criteria is undefined
1074
1075         Returns:
1076                 :class:`SMESH.Filter`
1077
1078         Examples:
1079                See :doc:`Filters usage examples <tui_filters>`
1080         """
1081
1082         for i in range( len( criteria ) - 1 ):
1083             if criteria[i].BinaryOp == self.EnumToLong( SMESH.FT_Undefined ):
1084                 criteria[i].BinaryOp = self.EnumToLong( binOp )
1085         aFilterMgr = self.CreateFilterManager()
1086         aFilter = aFilterMgr.CreateFilter()
1087         aFilter.SetCriteria(criteria)
1088         aFilterMgr.UnRegister()
1089         return aFilter
1090
1091     def GetFunctor(self,theCriterion):
1092         """
1093         Create a numerical functor by its type
1094
1095         Parameters:
1096                 theCriterion (SMESH.FunctorType): functor type.
1097                         Note that not all items correspond to numerical functors.
1098
1099         Returns:
1100                 :class:`SMESH.NumericalFunctor`
1101         """
1102
1103         if isinstance( theCriterion, SMESH._objref_NumericalFunctor ):
1104             return theCriterion
1105         aFilterMgr = self.CreateFilterManager()
1106         functor = None
1107         if theCriterion == FT_AspectRatio:
1108             functor = aFilterMgr.CreateAspectRatio()
1109         elif theCriterion == FT_AspectRatio3D:
1110             functor = aFilterMgr.CreateAspectRatio3D()
1111         elif theCriterion == FT_Warping:
1112             functor = aFilterMgr.CreateWarping()
1113         elif theCriterion == FT_MinimumAngle:
1114             functor = aFilterMgr.CreateMinimumAngle()
1115         elif theCriterion == FT_Taper:
1116             functor = aFilterMgr.CreateTaper()
1117         elif theCriterion == FT_Skew:
1118             functor = aFilterMgr.CreateSkew()
1119         elif theCriterion == FT_Area:
1120             functor = aFilterMgr.CreateArea()
1121         elif theCriterion == FT_Volume3D:
1122             functor = aFilterMgr.CreateVolume3D()
1123         elif theCriterion == FT_MaxElementLength2D:
1124             functor = aFilterMgr.CreateMaxElementLength2D()
1125         elif theCriterion == FT_MaxElementLength3D:
1126             functor = aFilterMgr.CreateMaxElementLength3D()
1127         elif theCriterion == FT_MultiConnection:
1128             functor = aFilterMgr.CreateMultiConnection()
1129         elif theCriterion == FT_MultiConnection2D:
1130             functor = aFilterMgr.CreateMultiConnection2D()
1131         elif theCriterion == FT_Length:
1132             functor = aFilterMgr.CreateLength()
1133         elif theCriterion == FT_Length2D:
1134             functor = aFilterMgr.CreateLength2D()
1135         elif theCriterion == FT_Deflection2D:
1136             functor = aFilterMgr.CreateDeflection2D()
1137         elif theCriterion == FT_NodeConnectivityNumber:
1138             functor = aFilterMgr.CreateNodeConnectivityNumber()
1139         elif theCriterion == FT_BallDiameter:
1140             functor = aFilterMgr.CreateBallDiameter()
1141         else:
1142             print("Error: given parameter is not numerical functor type.")
1143         aFilterMgr.UnRegister()
1144         return functor
1145
1146     def CreateHypothesis(self, theHType, theLibName="libStdMeshersEngine.so"):
1147         """
1148         Create hypothesis
1149
1150         Parameters:
1151                 theHType (string): mesh hypothesis type
1152                 theLibName (string): mesh plug-in library name
1153
1154         Returns:
1155                 created hypothesis instance
1156         """
1157         hyp = SMESH._objref_SMESH_Gen.CreateHypothesis(self, theHType, theLibName )
1158
1159         if isinstance( hyp, SMESH._objref_SMESH_Algo ):
1160             return hyp
1161
1162         # wrap hypothesis methods
1163         for meth_name in dir( hyp.__class__ ):
1164             if not meth_name.startswith("Get") and \
1165                not meth_name in dir ( SMESH._objref_SMESH_Hypothesis ):
1166                 method = getattr ( hyp.__class__, meth_name )
1167                 if callable(method):
1168                     setattr( hyp, meth_name, hypMethodWrapper( hyp, method ))
1169
1170         return hyp
1171
1172     def GetMeshInfo(self, obj):
1173         """
1174         Get the mesh statistic.
1175         Use :meth:`smeshBuilder.EnumToLong` to get an integer from 
1176         an item of :class:`SMESH.EntityType`.
1177
1178         Returns:
1179                 dictionary { :class:`SMESH.EntityType` - "count of elements" }
1180         """
1181
1182         if isinstance( obj, Mesh ):
1183             obj = obj.GetMesh()
1184         d = {}
1185         if hasattr(obj, "GetMeshInfo"):
1186             values = obj.GetMeshInfo()
1187             for i in range(SMESH.Entity_Last._v):
1188                 if i < len(values): d[SMESH.EntityType._item(i)]=values[i]
1189             pass
1190         return d
1191
1192     def MinDistance(self, src1, src2=None, id1=0, id2=0, isElem1=False, isElem2=False):
1193         """
1194         Get minimum distance between two objects
1195
1196         * If *src2* is None, and *id2* = 0, distance from *src1* / *id1* to the origin is computed.
1197         * If *src2* is None, and *id2* != 0, it is assumed that both *id1* and *id2* belong to *src1*.
1198
1199         Parameters:
1200                 src1 (SMESH.SMESH_IDSource): first source object
1201                 src2 (SMESH.SMESH_IDSource): second source object
1202                 id1 (int): node/element id from the first source
1203                 id2 (int): node/element id from the second (or first) source
1204                 isElem1 (boolean): *True* if *id1* is element id, *False* if it is node id
1205                 isElem2 (boolean): *True* if *id2* is element id, *False* if it is node id
1206
1207         Returns:
1208                 minimum distance value
1209
1210         See also: 
1211                 :meth:`GetMinDistance`
1212         """
1213
1214         result = self.GetMinDistance(src1, src2, id1, id2, isElem1, isElem2)
1215         if result is None:
1216             result = 0.0
1217         else:
1218             result = result.value
1219         return result
1220
1221     def GetMinDistance(self, src1, src2=None, id1=0, id2=0, isElem1=False, isElem2=False):
1222         """
1223         Get :class:`SMESH.Measure` structure specifying minimum distance data between two objects
1224
1225         * If *src2* is None, and *id2*  = 0, distance from *src1* / *id1* to the origin is computed.
1226         * If *src2* is None, and *id2* != 0, it is assumed that both *id1* and *id2* belong to *src1*.
1227
1228         Parameters:
1229                 src1 (SMESH.SMESH_IDSource): first source object
1230                 src2 (SMESH.SMESH_IDSource): second source object
1231                 id1 (int): node/element id from the first source
1232                 id2 (int): node/element id from the second (or first) source
1233                 isElem1 (boolean): *True* if **id1** is element id, *False* if it is node id
1234                 isElem2 (boolean): *True* if **id2** is element id, *False* if it is node id
1235
1236         Returns:
1237                 :class:`SMESH.Measure` structure or None if input data is invalid
1238         See also: 
1239                 :meth:`MinDistance`
1240         """
1241
1242         if isinstance(src1, Mesh): src1 = src1.mesh
1243         if isinstance(src2, Mesh): src2 = src2.mesh
1244         if src2 is None and id2 != 0: src2 = src1
1245         if not hasattr(src1, "_narrow"): return None
1246         src1 = src1._narrow(SMESH.SMESH_IDSource)
1247         if not src1: return None
1248         unRegister = genObjUnRegister()
1249         if id1 != 0:
1250             m = src1.GetMesh()
1251             e = m.GetMeshEditor()
1252             if isElem1:
1253                 src1 = e.MakeIDSource([id1], SMESH.FACE)
1254             else:
1255                 src1 = e.MakeIDSource([id1], SMESH.NODE)
1256             unRegister.set( src1 )
1257             pass
1258         if hasattr(src2, "_narrow"):
1259             src2 = src2._narrow(SMESH.SMESH_IDSource)
1260             if src2 and id2 != 0:
1261                 m = src2.GetMesh()
1262                 e = m.GetMeshEditor()
1263                 if isElem2:
1264                     src2 = e.MakeIDSource([id2], SMESH.FACE)
1265                 else:
1266                     src2 = e.MakeIDSource([id2], SMESH.NODE)
1267                 unRegister.set( src2 )
1268                 pass
1269             pass
1270         aMeasurements = self.CreateMeasurements()
1271         unRegister.set( aMeasurements )
1272         result = aMeasurements.MinDistance(src1, src2)
1273         return result
1274
1275     def BoundingBox(self, objects):
1276         """
1277         Get bounding box of the specified object(s)
1278
1279         Parameters:
1280                 objects (SMESH.SMESH_IDSource): single source object or list of source objects
1281
1282         Returns:
1283                 tuple of six values (minX, minY, minZ, maxX, maxY, maxZ)
1284
1285         See also: 
1286                :meth:`GetBoundingBox`
1287         """
1288
1289         result = self.GetBoundingBox(objects)
1290         if result is None:
1291             result = (0.0,)*6
1292         else:
1293             result = (result.minX, result.minY, result.minZ, result.maxX, result.maxY, result.maxZ)
1294         return result
1295
1296     def GetBoundingBox(self, objects):
1297         """
1298         Get :class:`SMESH.Measure` structure specifying bounding box data of the specified object(s)
1299
1300         Parameters:
1301                 objects (SMESH.SMESH_IDSource): single source object or list of source objects
1302
1303         Returns:
1304                 :class:`SMESH.Measure` structure
1305
1306         See also: 
1307                 :meth:`BoundingBox`
1308         """
1309
1310         if isinstance(objects, tuple):
1311             objects = list(objects)
1312         if not isinstance(objects, list):
1313             objects = [objects]
1314         srclist = []
1315         for o in objects:
1316             if isinstance(o, Mesh):
1317                 srclist.append(o.mesh)
1318             elif hasattr(o, "_narrow"):
1319                 src = o._narrow(SMESH.SMESH_IDSource)
1320                 if src: srclist.append(src)
1321                 pass
1322             pass
1323         aMeasurements = self.CreateMeasurements()
1324         result = aMeasurements.BoundingBox(srclist)
1325         aMeasurements.UnRegister()
1326         return result
1327
1328     def GetLength(self, obj):
1329         """
1330         Get sum of lengths of all 1D elements in the mesh object.
1331
1332         Parameters:
1333                 obj: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
1334
1335         Returns:
1336                 sum of lengths of all 1D elements
1337         """
1338
1339         if isinstance(obj, Mesh): obj = obj.mesh
1340         if isinstance(obj, Mesh_Algorithm): obj = obj.GetSubMesh()
1341         aMeasurements = self.CreateMeasurements()
1342         value = aMeasurements.Length(obj)
1343         aMeasurements.UnRegister()
1344         return value
1345
1346     def GetArea(self, obj):
1347         """
1348         Get sum of areas of all 2D elements in the mesh object.
1349
1350         Parameters:
1351                 obj: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
1352
1353         Returns:
1354                 sum of areas of all 2D elements
1355         """
1356
1357         if isinstance(obj, Mesh): obj = obj.mesh
1358         if isinstance(obj, Mesh_Algorithm): obj = obj.GetSubMesh()
1359         aMeasurements = self.CreateMeasurements()
1360         value = aMeasurements.Area(obj)
1361         aMeasurements.UnRegister()
1362         return value
1363
1364     def GetVolume(self, obj):
1365         """
1366         Get sum of volumes of all 3D elements in the mesh object.
1367
1368         Parameters:
1369                 obj: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
1370
1371         Returns:
1372                 sum of volumes of all 3D elements
1373         """
1374
1375         if isinstance(obj, Mesh): obj = obj.mesh
1376         if isinstance(obj, Mesh_Algorithm): obj = obj.GetSubMesh()
1377         aMeasurements = self.CreateMeasurements()
1378         value = aMeasurements.Volume(obj)
1379         aMeasurements.UnRegister()
1380         return value
1381
1382     def GetGravityCenter(self, obj):
1383         """
1384         Get gravity center of all nodes of the mesh object.
1385         
1386         Parameters:            
1387                 obj: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
1388
1389         Returns:        
1390             Three components of the gravity center (x,y,z)
1391         """
1392         if isinstance(obj, Mesh): obj = obj.mesh
1393         if isinstance(obj, Mesh_Algorithm): obj = obj.GetSubMesh()
1394         aMeasurements = self.CreateMeasurements()
1395         pointStruct = aMeasurements.GravityCenter(obj)
1396         aMeasurements.UnRegister()
1397         return pointStruct.x, pointStruct.y, pointStruct.z
1398
1399     pass # end of class smeshBuilder
1400
1401 import omniORB
1402 omniORB.registerObjref(SMESH._objref_SMESH_Gen._NP_RepositoryId, smeshBuilder)
1403 """Registering the new proxy for SMESH.SMESH_Gen"""
1404
1405
1406 def New( instance=None, instanceGeom=None):
1407     """
1408     Create a new smeshBuilder instance. The smeshBuilder class provides the Python
1409     interface to create or load meshes.
1410
1411     Typical use is::
1412
1413         import salome
1414         salome.salome_init()
1415         from salome.smesh import smeshBuilder
1416         smesh = smeshBuilder.New()
1417
1418     Parameters:
1419         instance:      CORBA proxy of SMESH Engine. If None, the default Engine is used.
1420         instanceGeom:  CORBA proxy of GEOM  Engine. If None, the default Engine is used.
1421     Returns:
1422         :class:`smeshBuilder` instance
1423     """
1424     global engine
1425     global smeshInst
1426     global doLcc
1427     if instance and isinstance( instance, SALOMEDS._objref_Study ):
1428         import sys
1429         sys.stderr.write("Warning: 'study' argument is no more needed in smeshBuilder.New(). Consider updating your script!!!\n\n")
1430         instance = None
1431     engine = instance
1432     if engine is None:
1433         doLcc = True
1434     smeshInst = smeshBuilder()
1435     assert isinstance(smeshInst,smeshBuilder), "Smesh engine class is %s but should be smeshBuilder.smeshBuilder. Import salome.smesh.smeshBuilder before creating the instance."%smeshInst.__class__
1436     smeshInst.init_smesh(instanceGeom)
1437     return smeshInst
1438
1439
1440 # Public class: Mesh
1441 # ==================
1442
1443
1444 class Mesh(metaclass = MeshMeta):
1445     """
1446     This class allows defining and managing a mesh.
1447     It has a set of methods to build a mesh on the given geometry, including the definition of sub-meshes.
1448     It also has methods to define groups of mesh elements, to modify a mesh (by addition of
1449     new nodes and elements and by changing the existing entities), to get information
1450     about a mesh and to export a mesh in different formats.
1451     """    
1452
1453     geom = 0
1454     mesh = 0
1455     editor = 0
1456
1457     def __init__(self, smeshpyD, geompyD, obj=0, name=0):
1458
1459         """
1460         Constructor
1461
1462         Create a mesh on the shape *obj* (or an empty mesh if *obj* is equal to 0) and
1463         sets the GUI name of this mesh to *name*.
1464
1465         Parameters:
1466                 smeshpyD: an instance of smeshBuilder class
1467                 geompyD: an instance of geomBuilder class
1468                 obj: Shape to be meshed or :class:`SMESH.SMESH_Mesh` object
1469                 name: Study name of the mesh
1470         """
1471
1472         self.smeshpyD = smeshpyD
1473         self.geompyD = geompyD
1474         if obj is None:
1475             obj = 0
1476         objHasName = False
1477         if obj != 0:
1478             if isinstance(obj, geomBuilder.GEOM._objref_GEOM_Object):
1479                 self.geom = obj
1480                 objHasName = True
1481                 # publish geom of mesh (issue 0021122)
1482                 if not self.geom.GetStudyEntry():
1483                     objHasName = False
1484                     geompyD.init_geom()
1485                     if name:
1486                         geo_name = name + " shape"
1487                     else:
1488                         geo_name = "%s_%s to mesh"%(self.geom.GetShapeType(), id(self.geom)%100)
1489                     geompyD.addToStudy( self.geom, geo_name )
1490                 self.SetMesh( self.smeshpyD.CreateMesh(self.geom) )
1491
1492             elif isinstance(obj, SMESH._objref_SMESH_Mesh):
1493                 self.SetMesh(obj)
1494         else:
1495             self.SetMesh( self.smeshpyD.CreateEmptyMesh() )
1496         if name:
1497             self.smeshpyD.SetName(self.mesh, name)
1498         elif objHasName:
1499             self.smeshpyD.SetName(self.mesh, GetName(obj)) # + " mesh"
1500
1501         if not self.geom:
1502             self.geom = self.mesh.GetShapeToMesh()
1503
1504         self.editor   = self.mesh.GetMeshEditor()
1505         self.functors = [None] * SMESH.FT_Undefined._v
1506
1507         # set self to algoCreator's
1508         for attrName in dir(self):
1509             attr = getattr( self, attrName )
1510             if isinstance( attr, algoCreator ):
1511                 setattr( self, attrName, attr.copy( self ))
1512                 pass
1513             pass
1514         pass
1515
1516     def __del__(self):
1517         """
1518         Destructor. Clean-up resources
1519         """
1520         if self.mesh:
1521             #self.mesh.UnRegister()
1522             pass
1523         pass
1524
1525     def SetMesh(self, theMesh):
1526         """
1527         Initialize the Mesh object from an instance of :class:`SMESH.SMESH_Mesh` interface
1528
1529         Parameters:
1530                 theMesh: a :class:`SMESH.SMESH_Mesh` object
1531         """
1532
1533
1534         # do not call Register() as this prevents mesh servant deletion at closing study
1535         #if self.mesh: self.mesh.UnRegister()
1536         self.mesh = theMesh
1537         if self.mesh:
1538             #self.mesh.Register()
1539             self.geom = self.mesh.GetShapeToMesh()
1540         pass
1541
1542     def GetMesh(self):
1543         """
1544         Return the mesh, that is an encapsulated instance of :class:`SMESH.SMESH_Mesh` interface
1545
1546         Returns:
1547                 a :class:`SMESH.SMESH_Mesh` object
1548         """
1549
1550         return self.mesh
1551
1552     def GetName(self):
1553         """
1554         Get the name of the mesh
1555
1556         Returns:
1557                 the name of the mesh as a string
1558         """
1559
1560         name = GetName(self.GetMesh())
1561         return name
1562
1563     def SetName(self, name):
1564         """
1565         Set a name to the mesh
1566
1567         Parameters:
1568                 name: a new name of the mesh
1569         """
1570
1571         self.smeshpyD.SetName(self.GetMesh(), name)
1572
1573     def GetSubMesh(self, geom, name):
1574         """
1575         Get a sub-mesh object associated to a *geom* geometrical object.
1576
1577         Parameters:
1578                 geom: a geometrical object (shape)
1579                 name: a name for the sub-mesh in the Object Browser
1580
1581         Returns:
1582                 an object of type :class:`SMESH.SMESH_subMesh`, representing a part of mesh,
1583                 which lies on the given shape
1584
1585         Note:
1586                 A sub-mesh is implicitly created when a sub-shape is specified at
1587                 creating an algorithm, for example::
1588
1589                    algo1D = mesh.Segment(geom=Edge_1)
1590
1591                 creates a sub-mesh on *Edge_1* and assign Wire Discretization algorithm to it.
1592                 The created sub-mesh can be retrieved from the algorithm::
1593
1594                    submesh = algo1D.GetSubMesh()
1595         """
1596
1597         AssureGeomPublished( self, geom, name )
1598         submesh = self.mesh.GetSubMesh( geom, name )
1599         return submesh
1600
1601     def GetShape(self):
1602         """
1603         Return the shape associated to the mesh
1604
1605         Returns:
1606                 a GEOM_Object
1607         """
1608
1609         return self.geom
1610
1611     def SetShape(self, geom):
1612         """
1613         Associate the given shape to the mesh (entails the recreation of the mesh)
1614
1615         Parameters:
1616                 geom: the shape to be meshed (GEOM_Object)
1617         """
1618
1619         self.mesh = self.smeshpyD.CreateMesh(geom)
1620
1621     def Load(self):
1622         """
1623         Load mesh from the study after opening the study
1624         """
1625         self.mesh.Load()
1626
1627     def IsReadyToCompute(self, theSubObject):
1628         """
1629         Return true if the hypotheses are defined well
1630
1631         Parameters:
1632                 theSubObject: a sub-shape of a mesh shape
1633
1634         Returns:
1635                 True or False
1636         """
1637
1638         return self.smeshpyD.IsReadyToCompute(self.mesh, theSubObject)
1639
1640     def GetAlgoState(self, theSubObject):
1641         """
1642         Return errors of hypotheses definition.
1643         The list of errors is empty if everything is OK.
1644
1645         Parameters:
1646                 theSubObject: a sub-shape of a mesh shape
1647
1648         Returns:
1649                 a list of errors
1650         """
1651
1652         return self.smeshpyD.GetAlgoState(self.mesh, theSubObject)
1653
1654     def GetGeometryByMeshElement(self, theElementID, theGeomName):
1655         """
1656         Return a geometrical object on which the given element was built.
1657         The returned geometrical object, if not nil, is either found in the
1658         study or published by this method with the given name
1659
1660         Parameters:
1661             theElementID: the id of the mesh element
1662             theGeomName: the user-defined name of the geometrical object
1663
1664         Returns:
1665             GEOM.GEOM_Object instance
1666         """
1667
1668         return self.smeshpyD.GetGeometryByMeshElement( self.mesh, theElementID, theGeomName )
1669
1670     def MeshDimension(self):
1671         """
1672         Return the mesh dimension depending on the dimension of the underlying shape
1673         or, if the mesh is not based on any shape, basing on deimension of elements
1674
1675         Returns:
1676                 mesh dimension as an integer value [0,3]
1677         """
1678
1679         if self.mesh.HasShapeToMesh():
1680             shells = self.geompyD.SubShapeAllIDs( self.geom, self.geompyD.ShapeType["SOLID"] )
1681             if len( shells ) > 0 :
1682                 return 3
1683             elif self.geompyD.NumberOfFaces( self.geom ) > 0 :
1684                 return 2
1685             elif self.geompyD.NumberOfEdges( self.geom ) > 0 :
1686                 return 1
1687             else:
1688                 return 0;
1689         else:
1690             if self.NbVolumes() > 0: return 3
1691             if self.NbFaces()   > 0: return 2
1692             if self.NbEdges()   > 0: return 1
1693         return 0
1694
1695     def Evaluate(self, geom=0):
1696         """
1697         Evaluate size of prospective mesh on a shape
1698
1699         Returns:
1700                 a list where i-th element is a number of elements of i-th :class:`SMESH.EntityType`.
1701                 To know predicted number of e.g. edges, inquire it this way::
1702
1703                    Evaluate()[ smesh.EnumToLong( SMESH.Entity_Edge )]
1704         """
1705
1706         if geom == 0 or not isinstance(geom, geomBuilder.GEOM._objref_GEOM_Object):
1707             if self.geom == 0:
1708                 geom = self.mesh.GetShapeToMesh()
1709             else:
1710                 geom = self.geom
1711         return self.smeshpyD.Evaluate(self.mesh, geom)
1712
1713
1714     def Compute(self, geom=0, discardModifs=False, refresh=False):
1715         """
1716         Compute the mesh and return the status of the computation
1717
1718         Parameters:
1719                 geom: geomtrical shape on which mesh data should be computed
1720                 discardModifs: if True and the mesh has been edited since
1721                         a last total re-compute and that may prevent successful partial re-compute,
1722                         then the mesh is cleaned before Compute()
1723                 refresh: if *True*, Object Browser is automatically updated (when running in GUI)
1724
1725         Returns:
1726                 True or False
1727         """
1728
1729         if geom == 0 or not isinstance(geom, geomBuilder.GEOM._objref_GEOM_Object):
1730             if self.geom == 0:
1731                 geom = self.mesh.GetShapeToMesh()
1732             else:
1733                 geom = self.geom
1734         ok = False
1735         try:
1736             if discardModifs and self.mesh.HasModificationsToDiscard(): # issue 0020693
1737                 self.mesh.Clear()
1738             ok = self.smeshpyD.Compute(self.mesh, geom)
1739         except SALOME.SALOME_Exception as ex:
1740             print("Mesh computation failed, exception caught:")
1741             print("    ", ex.details.text)
1742         except:
1743             import traceback
1744             print("Mesh computation failed, exception caught:")
1745             traceback.print_exc()
1746         if True:#not ok:
1747             allReasons = ""
1748
1749             # Treat compute errors
1750             computeErrors = self.smeshpyD.GetComputeErrors( self.mesh, geom )
1751             shapeText = ""
1752             for err in computeErrors:
1753                 if self.mesh.HasShapeToMesh():
1754                     shapeText = " on %s" % self.GetSubShapeName( err.subShapeID )
1755                 errText = ""
1756                 stdErrors = ["OK",                   #COMPERR_OK
1757                              "Invalid input mesh",   #COMPERR_BAD_INPUT_MESH
1758                              "std::exception",       #COMPERR_STD_EXCEPTION
1759                              "OCC exception",        #COMPERR_OCC_EXCEPTION
1760                              "..",                   #COMPERR_SLM_EXCEPTION
1761                              "Unknown exception",    #COMPERR_EXCEPTION
1762                              "Memory allocation problem", #COMPERR_MEMORY_PB
1763                              "Algorithm failed",     #COMPERR_ALGO_FAILED
1764                              "Unexpected geometry",  #COMPERR_BAD_SHAPE
1765                              "Warning",              #COMPERR_WARNING
1766                              "Computation cancelled",#COMPERR_CANCELED
1767                              "No mesh on sub-shape"] #COMPERR_NO_MESH_ON_SHAPE
1768                 if err.code > 0:
1769                     if err.code < len(stdErrors): errText = stdErrors[err.code]
1770                 else:
1771                     errText = "code %s" % -err.code
1772                 if errText: errText += ". "
1773                 errText += err.comment
1774                 if allReasons: allReasons += "\n"
1775                 if ok:
1776                     allReasons += '-  "%s"%s - %s' %(err.algoName, shapeText, errText)
1777                 else:
1778                     allReasons += '-  "%s" failed%s. Error: %s' %(err.algoName, shapeText, errText)
1779                 pass
1780
1781             # Treat hyp errors
1782             errors = self.smeshpyD.GetAlgoState( self.mesh, geom )
1783             for err in errors:
1784                 if err.isGlobalAlgo:
1785                     glob = "global"
1786                 else:
1787                     glob = "local"
1788                     pass
1789                 dim = err.algoDim
1790                 name = err.algoName
1791                 if len(name) == 0:
1792                     reason = '%s %sD algorithm is missing' % (glob, dim)
1793                 elif err.state == HYP_MISSING:
1794                     reason = ('%s %sD algorithm "%s" misses %sD hypothesis'
1795                               % (glob, dim, name, dim))
1796                 elif err.state == HYP_NOTCONFORM:
1797                     reason = 'Global "Not Conform mesh allowed" hypothesis is missing'
1798                 elif err.state == HYP_BAD_PARAMETER:
1799                     reason = ('Hypothesis of %s %sD algorithm "%s" has a bad parameter value'
1800                               % ( glob, dim, name ))
1801                 elif err.state == HYP_BAD_GEOMETRY:
1802                     reason = ('%s %sD algorithm "%s" is assigned to mismatching'
1803                               'geometry' % ( glob, dim, name ))
1804                 elif err.state == HYP_HIDDEN_ALGO:
1805                     reason = ('%s %sD algorithm "%s" is ignored due to presence of a %s '
1806                               'algorithm of upper dimension generating %sD mesh'
1807                               % ( glob, dim, name, glob, dim ))
1808                 else:
1809                     reason = ("For unknown reason. "
1810                               "Developer, revise Mesh.Compute() implementation in smeshBuilder.py!")
1811                     pass
1812                 if allReasons: allReasons += "\n"
1813                 allReasons += "-  " + reason
1814                 pass
1815             if not ok or allReasons != "":
1816                 msg = '"' + GetName(self.mesh) + '"'
1817                 if ok: msg += " has been computed with warnings"
1818                 else:  msg += " has not been computed"
1819                 if allReasons != "": msg += ":"
1820                 else:                msg += "."
1821                 print(msg)
1822                 print(allReasons)
1823             pass
1824         if salome.sg.hasDesktop():
1825             if not isinstance( refresh, list): # not a call from subMesh.Compute()
1826                 smeshgui = salome.ImportComponentGUI("SMESH")
1827                 smeshgui.Init()
1828                 smeshgui.SetMeshIcon( salome.ObjectToID( self.mesh ), ok, (self.NbNodes()==0) )
1829                 if refresh: salome.sg.updateObjBrowser()
1830
1831         return ok
1832
1833     def GetComputeErrors(self, shape=0 ):
1834         """
1835         Return a list of error messages (:class:`SMESH.ComputeError`) of the last :meth:`Compute`
1836         """
1837
1838         if shape == 0:
1839             shape = self.mesh.GetShapeToMesh()
1840         return self.smeshpyD.GetComputeErrors( self.mesh, shape )
1841
1842     def GetSubShapeName(self, subShapeID ):
1843         """
1844         Return a name of a sub-shape by its ID.
1845         Possible variants (for *subShapeID* == 3):
1846
1847                 - **"Face_12"** - published sub-shape
1848                 - **FACE #3** - not published sub-shape
1849                 - **sub-shape #3** - invalid sub-shape ID
1850                 - **#3** - error in this function
1851
1852         Parameters:
1853                 subShapeID: a unique ID of a sub-shape
1854
1855         Returns:
1856                 a string describing the sub-shape
1857
1858         """
1859
1860         if not self.mesh.HasShapeToMesh():
1861             return ""
1862         try:
1863             shapeText = ""
1864             mainIOR  = salome.orb.object_to_string( self.GetShape() )
1865             s = salome.myStudy
1866             mainSO = s.FindObjectIOR(mainIOR)
1867             if mainSO:
1868                 if subShapeID == 1:
1869                     shapeText = '"%s"' % mainSO.GetName()
1870                 subIt = s.NewChildIterator(mainSO)
1871                 while subIt.More():
1872                     subSO = subIt.Value()
1873                     subIt.Next()
1874                     obj = subSO.GetObject()
1875                     if not obj: continue
1876                     go = obj._narrow( geomBuilder.GEOM._objref_GEOM_Object )
1877                     if not go: continue
1878                     try:
1879                         ids = self.geompyD.GetSubShapeID( self.GetShape(), go )
1880                     except:
1881                         continue
1882                     if ids == subShapeID:
1883                         shapeText = '"%s"' % subSO.GetName()
1884                         break
1885             if not shapeText:
1886                 shape = self.geompyD.GetSubShape( self.GetShape(), [subShapeID])
1887                 if shape:
1888                     shapeText = '%s #%s' % (shape.GetShapeType(), subShapeID)
1889                 else:
1890                     shapeText = 'sub-shape #%s' % (subShapeID)
1891         except:
1892             shapeText = "#%s" % (subShapeID)
1893         return shapeText
1894
1895     def GetFailedShapes(self, publish=False):
1896         """
1897         Return a list of sub-shapes meshing of which failed, grouped into GEOM groups by
1898         error of an algorithm
1899
1900         Parameters:
1901                 publish: if *True*, the returned groups will be published in the study
1902
1903         Returns:
1904                 a list of GEOM groups each named after a failed algorithm
1905         """
1906
1907
1908         algo2shapes = {}
1909         computeErrors = self.smeshpyD.GetComputeErrors( self.mesh, self.GetShape() )
1910         for err in computeErrors:
1911             shape = self.geompyD.GetSubShape( self.GetShape(), [err.subShapeID])
1912             if not shape: continue
1913             if err.algoName in algo2shapes:
1914                 algo2shapes[ err.algoName ].append( shape )
1915             else:
1916                 algo2shapes[ err.algoName ] = [ shape ]
1917             pass
1918
1919         groups = []
1920         for algoName, shapes in list(algo2shapes.items()):
1921             while shapes:
1922                 groupType = self.smeshpyD.EnumToLong( shapes[0].GetShapeType() )
1923                 otherTypeShapes = []
1924                 sameTypeShapes  = []
1925                 group = self.geompyD.CreateGroup( self.geom, groupType )
1926                 for shape in shapes:
1927                     if shape.GetShapeType() == shapes[0].GetShapeType():
1928                         sameTypeShapes.append( shape )
1929                     else:
1930                         otherTypeShapes.append( shape )
1931                 self.geompyD.UnionList( group, sameTypeShapes )
1932                 if otherTypeShapes:
1933                     group.SetName( "%s %s" % ( algoName, shapes[0].GetShapeType() ))
1934                 else:
1935                     group.SetName( algoName )
1936                 groups.append( group )
1937                 shapes = otherTypeShapes
1938             pass
1939         if publish:
1940             for group in groups:
1941                 self.geompyD.addToStudyInFather( self.geom, group, group.GetName() )
1942         return groups
1943
1944     def GetMeshOrder(self):
1945         """
1946         Return sub-mesh objects list in meshing order
1947
1948         Returns:
1949                 list of lists of :class:`sub-meshes <SMESH.SMESH_subMesh>`
1950         """
1951
1952         return self.mesh.GetMeshOrder()
1953
1954     def SetMeshOrder(self, submeshes):
1955         """
1956         Set order in which concurrent sub-meshes should be meshed
1957
1958         Parameters:
1959                 submeshes: list of lists of :class:`sub-meshes <SMESH.SMESH_subMesh>`
1960         """
1961
1962         return self.mesh.SetMeshOrder(submeshes)
1963
1964     def Clear(self, refresh=False):
1965         """
1966         Remove all nodes and elements generated on geometry. Imported elements remain.
1967
1968         Parameters:
1969                 refresh: if *True*, Object browser is automatically updated (when running in GUI)
1970         """
1971
1972         self.mesh.Clear()
1973         if ( salome.sg.hasDesktop() ):
1974             smeshgui = salome.ImportComponentGUI("SMESH")
1975             smeshgui.Init()
1976             smeshgui.SetMeshIcon( salome.ObjectToID( self.mesh ), False, True )
1977             if refresh: salome.sg.updateObjBrowser()
1978
1979     def ClearSubMesh(self, geomId, refresh=False):
1980         """
1981         Remove all nodes and elements of indicated shape
1982
1983         Parameters:
1984                 geomId: the ID of a sub-shape to remove elements on
1985                 refresh: if *True*, Object browser is automatically updated (when running in GUI)
1986         """
1987
1988         self.mesh.ClearSubMesh(geomId)
1989         if salome.sg.hasDesktop():
1990             smeshgui = salome.ImportComponentGUI("SMESH")
1991             smeshgui.Init()
1992             smeshgui.SetMeshIcon( salome.ObjectToID( self.mesh ), False, True )
1993             if refresh: salome.sg.updateObjBrowser()
1994
1995     def AutomaticTetrahedralization(self, fineness=0):
1996         """
1997         Compute a tetrahedral mesh using AutomaticLength + MEFISTO + Tetrahedron
1998
1999         Parameters:
2000                 fineness: [0.0,1.0] defines mesh fineness
2001
2002         Returns:
2003                 True or False
2004         """
2005
2006         dim = self.MeshDimension()
2007         # assign hypotheses
2008         self.RemoveGlobalHypotheses()
2009         self.Segment().AutomaticLength(fineness)
2010         if dim > 1 :
2011             self.Triangle().LengthFromEdges()
2012             pass
2013         if dim > 2 :
2014             self.Tetrahedron()
2015             pass
2016         return self.Compute()
2017
2018     def AutomaticHexahedralization(self, fineness=0):
2019         """
2020         Compute an hexahedral mesh using AutomaticLength + Quadrangle + Hexahedron
2021
2022         Parameters:
2023                 fineness: [0.0, 1.0] defines mesh fineness
2024
2025         Returns:
2026                 True or False
2027         """
2028
2029         dim = self.MeshDimension()
2030         # assign the hypotheses
2031         self.RemoveGlobalHypotheses()
2032         self.Segment().AutomaticLength(fineness)
2033         if dim > 1 :
2034             self.Quadrangle()
2035             pass
2036         if dim > 2 :
2037             self.Hexahedron()
2038             pass
2039         return self.Compute()
2040
2041     def AddHypothesis(self, hyp, geom=0):
2042         """
2043         Assign a hypothesis
2044
2045         Parameters:
2046                 hyp: a hypothesis to assign
2047                 geom: a subhape of mesh geometry
2048
2049         Returns:
2050                 :class:`SMESH.Hypothesis_Status`
2051         """
2052
2053         if isinstance( hyp, geomBuilder.GEOM._objref_GEOM_Object ):
2054             hyp, geom = geom, hyp
2055         if isinstance( hyp, Mesh_Algorithm ):
2056             hyp = hyp.GetAlgorithm()
2057             pass
2058         if not geom:
2059             geom = self.geom
2060             if not geom:
2061                 geom = self.mesh.GetShapeToMesh()
2062             pass
2063         isApplicable = True
2064         if self.mesh.HasShapeToMesh():
2065             hyp_type     = hyp.GetName()
2066             lib_name     = hyp.GetLibName()
2067             # checkAll    = ( not geom.IsSame( self.mesh.GetShapeToMesh() ))
2068             # if checkAll and geom:
2069             #     checkAll = geom.GetType() == 37
2070             checkAll     = False
2071             isApplicable = self.smeshpyD.IsApplicable(hyp_type, lib_name, geom, checkAll)
2072         if isApplicable:
2073             AssureGeomPublished( self, geom, "shape for %s" % hyp.GetName())
2074             status = self.mesh.AddHypothesis(geom, hyp)
2075         else:
2076             status = HYP_BAD_GEOMETRY, ""
2077         hyp_name = GetName( hyp )
2078         geom_name = ""
2079         if geom:
2080             geom_name = geom.GetName()
2081         isAlgo = hyp._narrow( SMESH_Algo )
2082         TreatHypoStatus( status, hyp_name, geom_name, isAlgo, self )
2083         return status
2084
2085     def IsUsedHypothesis(self, hyp, geom):
2086         """
2087         Return True if an algorithm or hypothesis is assigned to a given shape
2088
2089         Parameters:
2090                 hyp: an algorithm or hypothesis to check
2091                 geom: a subhape of mesh geometry
2092
2093         Returns:
2094                 True of False
2095         """
2096
2097         if not hyp: # or not geom
2098             return False
2099         if isinstance( hyp, Mesh_Algorithm ):
2100             hyp = hyp.GetAlgorithm()
2101             pass
2102         hyps = self.GetHypothesisList(geom)
2103         for h in hyps:
2104             if h.GetId() == hyp.GetId():
2105                 return True
2106         return False
2107
2108     def RemoveHypothesis(self, hyp, geom=0):
2109         """
2110         Unassign a hypothesis
2111
2112         Parameters:
2113                 hyp (SMESH.SMESH_Hypothesis): a hypothesis to unassign
2114                 geom (GEOM.GEOM_Object): a sub-shape of mesh geometry
2115
2116         Returns:
2117                 :class:`SMESH.Hypothesis_Status`
2118         """
2119
2120         if not hyp:
2121             return None
2122         if isinstance( hyp, Mesh_Algorithm ):
2123             hyp = hyp.GetAlgorithm()
2124             pass
2125         shape = geom
2126         if not shape:
2127             shape = self.geom
2128             pass
2129         if self.IsUsedHypothesis( hyp, shape ):
2130             return self.mesh.RemoveHypothesis( shape, hyp )
2131         hypName = GetName( hyp )
2132         geoName = GetName( shape )
2133         print("WARNING: RemoveHypothesis() failed as '%s' is not assigned to '%s' shape" % ( hypName, geoName ))
2134         return None
2135
2136     def GetHypothesisList(self, geom):
2137         """
2138         Get the list of hypotheses added on a geometry
2139
2140         Parameters:
2141                 geom (GEOM.GEOM_Object): a sub-shape of mesh geometry
2142
2143         Returns:
2144                 the sequence of :class:`SMESH.SMESH_Hypothesis`
2145         """
2146
2147         return self.mesh.GetHypothesisList( geom )
2148
2149     def RemoveGlobalHypotheses(self):
2150         """
2151         Remove all global hypotheses
2152         """
2153
2154         current_hyps = self.mesh.GetHypothesisList( self.geom )
2155         for hyp in current_hyps:
2156             self.mesh.RemoveHypothesis( self.geom, hyp )
2157             pass
2158         pass
2159     def ExportMED(self, *args, **kwargs):
2160         """
2161         Export the mesh in a file in MED format
2162         allowing to overwrite the file if it exists or add the exported data to its contents
2163
2164         Parameters:
2165                 fileName: is the file name
2166                 auto_groups (boolean): parameter for creating/not creating
2167                         the groups Group_On_All_Nodes, Group_On_All_Faces, ... ;
2168                         the typical use is auto_groups=False.
2169                 overwrite (boolean): parameter for overwriting/not overwriting the file
2170                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2171                 autoDimension: if *True* (default), a space dimension of a MED mesh can be either
2172
2173                         - 1D if all mesh nodes lie on OX coordinate axis, or
2174                         - 2D if all mesh nodes lie on XOY coordinate plane, or
2175                         - 3D in the rest cases.
2176
2177                         If *autoDimension* is *False*, the space dimension is always 3.
2178                 fields: list of GEOM fields defined on the shape to mesh.
2179                 geomAssocFields: each character of this string means a need to export a 
2180                         corresponding field; correspondence between fields and characters is following:
2181                         - 'v' stands for "_vertices _" field;
2182                         - 'e' stands for "_edges _" field;
2183                         - 'f' stands for "_faces _" field;
2184                         - 's' stands for "_solids _" field.
2185         """
2186         # process positional arguments
2187         args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]] # backward compatibility
2188         fileName        = args[0]
2189         auto_groups     = args[1] if len(args) > 1 else False
2190         overwrite       = args[2] if len(args) > 2 else True
2191         meshPart        = args[3] if len(args) > 3 else None
2192         autoDimension   = args[4] if len(args) > 4 else True
2193         fields          = args[5] if len(args) > 5 else []
2194         geomAssocFields = args[6] if len(args) > 6 else ''
2195         # process keywords arguments
2196         auto_groups     = kwargs.get("auto_groups", auto_groups)
2197         overwrite       = kwargs.get("overwrite", overwrite)
2198         meshPart        = kwargs.get("meshPart", meshPart)
2199         autoDimension   = kwargs.get("autoDimension", autoDimension)
2200         fields          = kwargs.get("fields", fields)
2201         geomAssocFields = kwargs.get("geomAssocFields", geomAssocFields)
2202         # invoke engine's function
2203         if meshPart or fields or geomAssocFields:
2204             unRegister = genObjUnRegister()
2205             if isinstance( meshPart, list ):
2206                 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2207                 unRegister.set( meshPart )
2208             self.mesh.ExportPartToMED( meshPart, fileName, auto_groups, overwrite, autoDimension,
2209                                        fields, geomAssocFields)
2210         else:
2211             self.mesh.ExportMED(fileName, auto_groups, overwrite, autoDimension)
2212
2213     def ExportSAUV(self, f, auto_groups=0):
2214         """
2215         Export the mesh in a file in SAUV format
2216
2217
2218         Parameters:
2219                 f: is the file name
2220                 auto_groups: boolean parameter for creating/not creating
2221                         the groups Group_On_All_Nodes, Group_On_All_Faces, ... ;
2222                         the typical use is auto_groups=False.
2223         """
2224
2225         self.mesh.ExportSAUV(f, auto_groups)
2226
2227     def ExportDAT(self, f, meshPart=None):
2228         """
2229         Export the mesh in a file in DAT format
2230
2231         Parameters:
2232                 f: the file name
2233                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2234         """
2235
2236         if meshPart:
2237             unRegister = genObjUnRegister()
2238             if isinstance( meshPart, list ):
2239                 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2240                 unRegister.set( meshPart )
2241             self.mesh.ExportPartToDAT( meshPart, f )
2242         else:
2243             self.mesh.ExportDAT(f)
2244
2245     def ExportUNV(self, f, meshPart=None):
2246         """
2247         Export the mesh in a file in UNV format
2248
2249         Parameters:
2250                 f: the file name
2251                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2252         """
2253
2254         if meshPart:
2255             unRegister = genObjUnRegister()
2256             if isinstance( meshPart, list ):
2257                 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2258                 unRegister.set( meshPart )
2259             self.mesh.ExportPartToUNV( meshPart, f )
2260         else:
2261             self.mesh.ExportUNV(f)
2262
2263     def ExportSTL(self, f, ascii=1, meshPart=None):
2264         """
2265         Export the mesh in a file in STL format
2266
2267         Parameters:
2268                 f: the file name
2269                 ascii: defines the file encoding
2270                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2271         """
2272
2273         if meshPart:
2274             unRegister = genObjUnRegister()
2275             if isinstance( meshPart, list ):
2276                 meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2277                 unRegister.set( meshPart )
2278             self.mesh.ExportPartToSTL( meshPart, f, ascii )
2279         else:
2280             self.mesh.ExportSTL(f, ascii)
2281
2282     def ExportCGNS(self, f, overwrite=1, meshPart=None, groupElemsByType=False):
2283         """
2284         Export the mesh in a file in CGNS format
2285
2286         Parameters:
2287                 f: is the file name
2288                 overwrite: boolean parameter for overwriting/not overwriting the file
2289                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2290                 groupElemsByType: if True all elements of same entity type are exported at ones,
2291                         else elements are exported in order of their IDs which can cause creation
2292                         of multiple cgns sections
2293         """
2294
2295         unRegister = genObjUnRegister()
2296         if isinstance( meshPart, list ):
2297             meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2298             unRegister.set( meshPart )
2299         if isinstance( meshPart, Mesh ):
2300             meshPart = meshPart.mesh
2301         elif not meshPart:
2302             meshPart = self.mesh
2303         self.mesh.ExportCGNS(meshPart, f, overwrite, groupElemsByType)
2304
2305     def ExportGMF(self, f, meshPart=None):
2306         """
2307         Export the mesh in a file in GMF format.
2308         GMF files must have .mesh extension for the ASCII format and .meshb for
2309         the bynary format. Other extensions are not allowed.
2310
2311         Parameters:
2312                 f: is the file name
2313                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
2314         """
2315
2316         unRegister = genObjUnRegister()
2317         if isinstance( meshPart, list ):
2318             meshPart = self.GetIDSource( meshPart, SMESH.ALL )
2319             unRegister.set( meshPart )
2320         if isinstance( meshPart, Mesh ):
2321             meshPart = meshPart.mesh
2322         elif not meshPart:
2323             meshPart = self.mesh
2324         self.mesh.ExportGMF(meshPart, f, True)
2325
2326     def ExportToMED(self, *args, **kwargs):
2327         """
2328         Deprecated, used only for compatibility! Please, use :meth:`ExportMED` method instead.
2329         Export the mesh in a file in MED format
2330         allowing to overwrite the file if it exists or add the exported data to its contents
2331
2332         Parameters:
2333                 fileName: the file name
2334                 opt (boolean): parameter for creating/not creating
2335                         the groups Group_On_All_Nodes, Group_On_All_Faces, ...
2336                 overwrite: boolean parameter for overwriting/not overwriting the file
2337                 autoDimension: if *True* (default), a space dimension of a MED mesh can be either
2338
2339                         - 1D if all mesh nodes lie on OX coordinate axis, or
2340                         - 2D if all mesh nodes lie on XOY coordinate plane, or
2341                         - 3D in the rest cases.
2342
2343                         If **autoDimension** is *False*, the space dimension is always 3.
2344         """
2345     
2346         print("WARNING: ExportToMED() is deprecated, use ExportMED() instead")
2347         # process positional arguments
2348         args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]] # backward compatibility
2349         fileName      = args[0]
2350         auto_groups   = args[1] if len(args) > 1 else False
2351         overwrite     = args[2] if len(args) > 2 else True
2352         autoDimension = args[3] if len(args) > 3 else True
2353         # process keywords arguments
2354         auto_groups   = kwargs.get("opt", auto_groups)         # old keyword name
2355         auto_groups   = kwargs.get("auto_groups", auto_groups) # new keyword name
2356         overwrite     = kwargs.get("overwrite", overwrite)
2357         autoDimension = kwargs.get("autoDimension", autoDimension)
2358         # invoke engine's function
2359         self.mesh.ExportMED(fileName, auto_groups, overwrite, autoDimension)
2360
2361     def ExportToMEDX(self, *args, **kwargs):
2362         """
2363         Deprecated, used only for compatibility! Please, use ExportMED() method instead.
2364         Export the mesh in a file in MED format
2365
2366         Parameters:
2367                 fileName: the file name
2368                 opt (boolean): parameter for creating/not creating
2369                         the groups Group_On_All_Nodes, Group_On_All_Faces, ...
2370                 overwrite: boolean parameter for overwriting/not overwriting the file
2371                 autoDimension: if *True* (default), a space dimension of a MED mesh can be either
2372
2373                         - 1D if all mesh nodes lie on OX coordinate axis, or
2374                         - 2D if all mesh nodes lie on XOY coordinate plane, or
2375                         - 3D in the rest cases.
2376
2377                         If **autoDimension** is *False*, the space dimension is always 3.
2378                 """
2379
2380         print("WARNING: ExportToMEDX() is deprecated, use ExportMED() instead")
2381         # process positional arguments
2382         args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]] # backward compatibility
2383         fileName      = args[0]
2384         auto_groups   = args[1] if len(args) > 1 else False
2385         overwrite     = args[2] if len(args) > 2 else True
2386         autoDimension = args[3] if len(args) > 3 else True
2387         # process keywords arguments
2388         auto_groups   = kwargs.get("auto_groups", auto_groups)
2389         overwrite     = kwargs.get("overwrite", overwrite)
2390         autoDimension = kwargs.get("autoDimension", autoDimension)
2391         # invoke engine's function
2392         self.mesh.ExportMED(fileName, auto_groups, overwrite, autoDimension)
2393
2394     # Operations with groups:
2395     # ----------------------
2396     def CreateEmptyGroup(self, elementType, name):
2397         """
2398         Create an empty mesh group
2399
2400         Parameters:
2401                 elementType: the :class:`type <SMESH.ElementType>` of elements in the group; 
2402                         either of (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME)
2403                 name: the name of the mesh group
2404
2405         Returns:
2406                 :class:`SMESH.SMESH_Group`
2407         """
2408
2409         return self.mesh.CreateGroup(elementType, name)
2410
2411     def Group(self, grp, name=""):
2412         """
2413         Create a mesh group based on the geometric object *grp*
2414         and give it a *name*.
2415         If *name* is not defined the name of the geometric group is used
2416
2417         Note:
2418                 Works like :meth:`GroupOnGeom`.
2419
2420         Parameters:
2421                 grp:  a geometric group, a vertex, an edge, a face or a solid
2422                 name: the name of the mesh group
2423
2424         Returns:
2425                 :class:`SMESH.SMESH_GroupOnGeom`
2426         """
2427
2428         return self.GroupOnGeom(grp, name)
2429
2430     def GroupOnGeom(self, grp, name="", typ=None):
2431         """
2432         Create a mesh group based on the geometrical object *grp*
2433         and gives a *name*.
2434         if *name* is not defined the name of the geometric group is used
2435
2436         Parameters:
2437                 grp:  a geometrical group, a vertex, an edge, a face or a solid
2438                 name: the name of the mesh group
2439                 typ:  the type of elements in the group; either of
2440                         (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME). If not set, it is
2441                         automatically detected by the type of the geometry
2442
2443         Returns:
2444                 :class:`SMESH.SMESH_GroupOnGeom`
2445         """
2446
2447         AssureGeomPublished( self, grp, name )
2448         if name == "":
2449             name = grp.GetName()
2450         if not typ:
2451             typ = self._groupTypeFromShape( grp )
2452         return self.mesh.CreateGroupFromGEOM(typ, name, grp)
2453
2454     def _groupTypeFromShape( self, shape ):
2455         """
2456         Pivate method to get a type of group on geometry
2457         """
2458         tgeo = str(shape.GetShapeType())
2459         if tgeo == "VERTEX":
2460             typ = NODE
2461         elif tgeo == "EDGE":
2462             typ = EDGE
2463         elif tgeo == "FACE" or tgeo == "SHELL":
2464             typ = FACE
2465         elif tgeo == "SOLID" or tgeo == "COMPSOLID":
2466             typ = VOLUME
2467         elif tgeo == "COMPOUND":
2468             sub = self.geompyD.SubShapeAll( shape, self.geompyD.ShapeType["SHAPE"])
2469             if not sub:
2470                 raise ValueError("_groupTypeFromShape(): empty geometric group or compound '%s'" % GetName(shape))
2471             return self._groupTypeFromShape( sub[0] )
2472         else:
2473             raise ValueError("_groupTypeFromShape(): invalid geometry '%s'" % GetName(shape))
2474         return typ
2475
2476     def GroupOnFilter(self, typ, name, filter):
2477         """
2478         Create a mesh group with given *name* based on the *filter* which
2479         is a special type of group dynamically updating it's contents during
2480         mesh modification
2481
2482         Parameters:
2483                 typ: the type of elements in the group; either of
2484                         (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME).
2485                 name: the name of the mesh group
2486                 filter (SMESH.Filter): the filter defining group contents
2487
2488         Returns:
2489                 :class:`SMESH.SMESH_GroupOnFilter`
2490         """
2491
2492         return self.mesh.CreateGroupFromFilter(typ, name, filter)
2493
2494     def MakeGroupByIds(self, groupName, elementType, elemIDs):
2495         """
2496         Create a mesh group by the given ids of elements
2497
2498         Parameters:
2499                 groupName: the name of the mesh group
2500                 elementType: the type of elements in the group; either of
2501                         (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME).
2502                 elemIDs: either the list of ids, :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
2503
2504         Returns:
2505                 :class:`SMESH.SMESH_Group`
2506         """
2507
2508         group = self.mesh.CreateGroup(elementType, groupName)
2509         if isinstance( elemIDs, Mesh ):
2510             elemIDs = elemIDs.GetMesh()
2511         if hasattr( elemIDs, "GetIDs" ):
2512             if hasattr( elemIDs, "SetMesh" ):
2513                 elemIDs.SetMesh( self.GetMesh() )
2514             group.AddFrom( elemIDs )
2515         else:
2516             group.Add(elemIDs)
2517         return group
2518
2519     def MakeGroup(self,
2520                   groupName,
2521                   elementType,
2522                   CritType=FT_Undefined,
2523                   Compare=FT_EqualTo,
2524                   Threshold="",
2525                   UnaryOp=FT_Undefined,
2526                   Tolerance=1e-07):
2527         """
2528         Create a mesh group by the given conditions
2529
2530         Parameters:
2531                 groupName: the name of the mesh group
2532                 elementType (SMESH.ElementType): the type of elements (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME)
2533                 CritType (SMESH.FunctorType): the type of criterion (SMESH.FT_Taper, SMESH.FT_Area, etc.).
2534                         Note that the items starting from FT_LessThan are not suitable for CritType.
2535                 Compare (SMESH.FunctorType): belongs to {SMESH.FT_LessThan, SMESH.FT_MoreThan, SMESH.FT_EqualTo}
2536                 Threshold: the threshold value (range of ids as string, shape, numeric, depending on *CritType*)
2537                 UnaryOp (SMESH.FunctorType):  SMESH.FT_LogicalNOT or SMESH.FT_Undefined
2538                 Tolerance (float): the tolerance used by SMESH.FT_BelongToGeom, SMESH.FT_BelongToSurface,
2539                         SMESH.FT_LyingOnGeom, SMESH.FT_CoplanarFaces criteria
2540
2541         Returns:
2542                 :class:`SMESH.SMESH_GroupOnFilter`
2543         """
2544
2545         aCriterion = self.smeshpyD.GetCriterion(elementType, CritType, Compare, Threshold, UnaryOp, FT_Undefined,Tolerance)
2546         group = self.MakeGroupByCriterion(groupName, aCriterion)
2547         return group
2548
2549     def MakeGroupByCriterion(self, groupName, Criterion):
2550         """
2551         Create a mesh group by the given criterion
2552
2553         Parameters:
2554                 groupName: the name of the mesh group
2555                 Criterion: the instance of :class:`SMESH.Filter.Criterion` class
2556
2557         Returns:
2558                 :class:`SMESH.SMESH_GroupOnFilter`
2559
2560         See Also:
2561                 :meth:`smeshBuilder.GetCriterion`
2562         """
2563
2564         return self.MakeGroupByCriteria( groupName, [Criterion] )
2565
2566     def MakeGroupByCriteria(self, groupName, theCriteria, binOp=SMESH.FT_LogicalAND):
2567         """
2568         Create a mesh group by the given criteria (list of :class:`SMESH.Filter.Criterion`)
2569
2570         Parameters:
2571                 groupName: the name of the mesh group
2572                 theCriteria: the list of :class:`SMESH.Filter.Criterion`
2573                 binOp: binary operator (SMESH.FT_LogicalAND or SMESH.FT_LogicalOR ) used when binary operator of criteria is undefined
2574
2575         Returns:
2576                 :class:`SMESH.SMESH_GroupOnFilter`
2577
2578         See Also:
2579                 :meth:`smeshBuilder.GetCriterion`
2580         """
2581
2582         aFilter = self.smeshpyD.GetFilterFromCriteria( theCriteria, binOp )
2583         group = self.MakeGroupByFilter(groupName, aFilter)
2584         return group
2585
2586     def MakeGroupByFilter(self, groupName, theFilter):
2587         """
2588         Create a mesh group by the given filter
2589
2590         Parameters:
2591                 groupName (string): the name of the mesh group
2592                 theFilter (SMESH.Filter): the filter
2593
2594         Returns:
2595                 :class:`SMESH.SMESH_GroupOnFilter`
2596
2597         See Also:
2598                 :meth:`smeshBuilder.GetFilter`
2599         """
2600
2601         #group = self.CreateEmptyGroup(theFilter.GetElementType(), groupName)
2602         #theFilter.SetMesh( self.mesh )
2603         #group.AddFrom( theFilter )
2604         group = self.GroupOnFilter( theFilter.GetElementType(), groupName, theFilter )
2605         return group
2606
2607     def RemoveGroup(self, group):
2608         """
2609         Remove a group
2610
2611         Parameters:
2612                 group (SMESH.SMESH_GroupBase): group to remove
2613         """
2614
2615         self.mesh.RemoveGroup(group)
2616
2617     def RemoveGroupWithContents(self, group):
2618         """
2619         Remove a group with its contents
2620
2621         Parameters:
2622                 group (SMESH.SMESH_GroupBase): group to remove
2623         """
2624
2625         self.mesh.RemoveGroupWithContents(group)
2626
2627     def GetGroups(self, elemType = SMESH.ALL):
2628         """
2629         Get the list of groups existing in the mesh in the order
2630         of creation (starting from the oldest one)
2631
2632         Parameters:
2633                 elemType (SMESH.ElementType): type of elements the groups contain;
2634                         by default groups of elements of all types are returned
2635
2636         Returns:
2637                 a sequence of :class:`SMESH.SMESH_GroupBase`
2638         """
2639
2640         groups = self.mesh.GetGroups()
2641         if elemType == SMESH.ALL:
2642             return groups
2643         typedGroups = []
2644         for g in groups:
2645             if g.GetType() == elemType:
2646                 typedGroups.append( g )
2647                 pass
2648             pass
2649         return typedGroups
2650
2651     def NbGroups(self):
2652         """
2653         Get the number of groups existing in the mesh
2654
2655         Returns:
2656                 the quantity of groups as an integer value
2657         """
2658
2659         return self.mesh.NbGroups()
2660
2661     def GetGroupNames(self):
2662         """
2663         Get the list of names of groups existing in the mesh
2664
2665         Returns:
2666                 list of strings
2667         """
2668
2669         groups = self.GetGroups()
2670         names = []
2671         for group in groups:
2672             names.append(group.GetName())
2673         return names
2674
2675     def GetGroupByName(self, name, elemType = None):
2676         """
2677         Find groups by name and type
2678
2679         Parameters:
2680                 name (string): name of the group of interest
2681                 elemType (SMESH.ElementType): type of elements the groups contain;
2682                         by default one group of any type is returned;
2683                         if elemType == SMESH.ALL then all groups of any type are returned
2684
2685         Returns:
2686                 a list of :class:`SMESH.SMESH_GroupBase`
2687         """
2688
2689         groups = []
2690         for group in self.GetGroups():
2691             if group.GetName() == name:
2692                 if elemType is None:
2693                     return [group]
2694                 if ( elemType == SMESH.ALL or
2695                      group.GetType() == elemType ):
2696                     groups.append( group )
2697         return groups
2698
2699     def UnionGroups(self, group1, group2, name):
2700         """
2701         Produce a union of two groups.
2702         A new group is created. All mesh elements that are
2703         present in the initial groups are added to the new one
2704
2705         Parameters:
2706            group1 (SMESH.SMESH_GroupBase): a group
2707            group2 (SMESH.SMESH_GroupBase): another group
2708
2709         Returns:
2710                 instance of :class:`SMESH.SMESH_Group`
2711         """
2712
2713         return self.mesh.UnionGroups(group1, group2, name)
2714
2715     def UnionListOfGroups(self, groups, name):
2716         """
2717         Produce a union list of groups.
2718         New group is created. All mesh elements that are present in
2719         initial groups are added to the new one
2720
2721         Parameters:
2722            groups: list of :class:`SMESH.SMESH_GroupBase`
2723
2724         Returns:
2725                 instance of :class:`SMESH.SMESH_Group`
2726         """
2727         return self.mesh.UnionListOfGroups(groups, name)
2728
2729     def IntersectGroups(self, group1, group2, name):
2730         """
2731         Prodice an intersection of two groups.
2732         A new group is created. All mesh elements that are common
2733         for the two initial groups are added to the new one.
2734
2735         Parameters:
2736            group1 (SMESH.SMESH_GroupBase): a group
2737            group2 (SMESH.SMESH_GroupBase): another group
2738
2739         Returns:
2740                 instance of :class:`SMESH.SMESH_Group`
2741         """
2742
2743         return self.mesh.IntersectGroups(group1, group2, name)
2744
2745     def IntersectListOfGroups(self, groups, name):
2746         """
2747         Produce an intersection of groups.
2748         New group is created. All mesh elements that are present in all
2749         initial groups simultaneously are added to the new one
2750
2751         Parameters:
2752            groups: a list of :class:`SMESH.SMESH_GroupBase`
2753
2754         Returns:
2755                 instance of :class:`SMESH.SMESH_Group`
2756         """
2757         return self.mesh.IntersectListOfGroups(groups, name)
2758
2759     def CutGroups(self, main_group, tool_group, name):
2760         """
2761         Produce a cut of two groups.
2762         A new group is created. All mesh elements that are present in
2763         the main group but are not present in the tool group are added to the new one
2764
2765         Parameters:
2766            main_group (SMESH.SMESH_GroupBase): a group to cut from
2767            tool_group (SMESH.SMESH_GroupBase): a group to cut by
2768
2769         Returns:
2770                 an instance of :class:`SMESH.SMESH_Group`
2771         """
2772
2773         return self.mesh.CutGroups(main_group, tool_group, name)
2774
2775     def CutListOfGroups(self, main_groups, tool_groups, name):
2776         """
2777         Produce a cut of groups.
2778         A new group is created. All mesh elements that are present in main groups
2779         but do not present in tool groups are added to the new one
2780
2781         Parameters:
2782            main_group: groups to cut from  (list of :class:`SMESH.SMESH_GroupBase`)
2783            tool_group: groups to cut by    (list of :class:`SMESH.SMESH_GroupBase`)
2784
2785         Returns:
2786                 an instance of :class:`SMESH.SMESH_Group`
2787         """
2788
2789         return self.mesh.CutListOfGroups(main_groups, tool_groups, name)
2790
2791     def CreateDimGroup(self, groups, elemType, name,
2792                        nbCommonNodes = SMESH.ALL_NODES, underlyingOnly = True):
2793         """
2794         Create a standalone group of entities basing on nodes of other groups.
2795
2796         Parameters:
2797                 groups: list of reference :class:`sub-meshes, groups or filters <SMESH.SMESH_IDSource>`, of any type.
2798                 elemType: a type of elements to include to the new group; either of
2799                         (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME).
2800                 name: a name of the new group.
2801                 nbCommonNodes: a criterion of inclusion of an element to the new group
2802                         basing on number of element nodes common with reference *groups*.
2803                         Meaning of possible values are:
2804
2805                                 - SMESH.ALL_NODES - include if all nodes are common,
2806                                 - SMESH.MAIN - include if all corner nodes are common (meaningful for a quadratic mesh),
2807                                 - SMESH.AT_LEAST_ONE - include if one or more node is common,
2808                                 - SMEHS.MAJORITY - include if half of nodes or more are common.
2809                 underlyingOnly: if *True* (default), an element is included to the
2810                         new group provided that it is based on nodes of an element of *groups*;
2811                         in this case the reference *groups* are supposed to be of higher dimension
2812                         than *elemType*, which can be useful for example to get all faces lying on
2813                         volumes of the reference *groups*.
2814
2815         Returns:
2816                 an instance of :class:`SMESH.SMESH_Group`
2817         """
2818
2819         if isinstance( groups, SMESH._objref_SMESH_IDSource ):
2820             groups = [groups]
2821         return self.mesh.CreateDimGroup(groups, elemType, name, nbCommonNodes, underlyingOnly)
2822
2823
2824     def ConvertToStandalone(self, group):
2825         """
2826         Convert group on geom into standalone group
2827         """
2828
2829         return self.mesh.ConvertToStandalone(group)
2830
2831     # Get some info about mesh:
2832     # ------------------------
2833
2834     def GetLog(self, clearAfterGet):
2835         """
2836         Return the log of nodes and elements added or removed
2837         since the previous clear of the log.
2838
2839         Parameters:
2840                 clearAfterGet: log is emptied after Get (safe if concurrents access)
2841
2842         Returns:
2843                 list of SMESH.log_block structures { commandType, number, coords, indexes }
2844         """
2845
2846         return self.mesh.GetLog(clearAfterGet)
2847
2848     def ClearLog(self):
2849         """
2850         Clear the log of nodes and elements added or removed since the previous
2851         clear. Must be used immediately after :meth:`GetLog` if clearAfterGet is false.
2852         """
2853
2854         self.mesh.ClearLog()
2855
2856     def SetAutoColor(self, theAutoColor):
2857         """
2858         Toggle auto color mode on the object.
2859         If switched on, a default color of a new group in Create Group dialog is chosen randomly.
2860
2861         Parameters:
2862                 theAutoColor (boolean): the flag which toggles auto color mode.
2863         """
2864
2865         self.mesh.SetAutoColor(theAutoColor)
2866
2867     def GetAutoColor(self):
2868         """
2869         Get flag of object auto color mode.
2870
2871         Returns:
2872                 True or False
2873         """
2874
2875         return self.mesh.GetAutoColor()
2876
2877     def GetId(self):
2878         """
2879         Get the internal ID
2880
2881         Returns:
2882             integer value, which is the internal Id of the mesh
2883         """
2884
2885         return self.mesh.GetId()
2886
2887     def HasDuplicatedGroupNamesMED(self):
2888         """
2889         Check the group names for duplications.
2890         Consider the maximum group name length stored in MED file.
2891
2892         Returns:
2893             True or False
2894         """
2895
2896         return self.mesh.HasDuplicatedGroupNamesMED()
2897
2898     def GetMeshEditor(self):
2899         """
2900         Obtain the mesh editor tool
2901
2902         Returns:
2903             an instance of :class:`SMESH.SMESH_MeshEditor`
2904         """
2905
2906         return self.editor
2907
2908     def GetIDSource(self, ids, elemType = SMESH.ALL):
2909         """
2910         Wrap a list of IDs of elements or nodes into :class:`SMESH.SMESH_IDSource` which
2911         can be passed as argument to a method accepting :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
2912
2913         Parameters:
2914                 ids: list of IDs
2915                 elemType: type of elements; this parameter is used to distinguish
2916                         IDs of nodes from IDs of elements; by default ids are treated as
2917                         IDs of elements; use SMESH.NODE if ids are IDs of nodes.
2918
2919         Returns:
2920             an instance of :class:`SMESH.SMESH_IDSource`
2921
2922         Warning:
2923                 call UnRegister() for the returned object as soon as it is no more useful::
2924
2925                         idSrc = mesh.GetIDSource( [1,3,5], SMESH.NODE )
2926                         mesh.DoSomething( idSrc )
2927                         idSrc.UnRegister()
2928         """
2929
2930         if isinstance( ids, int ):
2931             ids = [ids]
2932         return self.editor.MakeIDSource(ids, elemType)
2933
2934
2935     # Get information about mesh contents:
2936     # ------------------------------------
2937
2938     def GetMeshInfo(self, obj = None):
2939         """
2940         Get the mesh statistic.
2941         Use :meth:`smeshBuilder.EnumToLong` to get an integer from 
2942         an item of :class:`SMESH.EntityType`.
2943
2944         Returns:
2945                 dictionary { :class:`SMESH.EntityType` - "count of elements" }
2946         """
2947
2948         if not obj: obj = self.mesh
2949         return self.smeshpyD.GetMeshInfo(obj)
2950
2951     def NbNodes(self):
2952         """
2953         Return the number of nodes in the mesh
2954
2955         Returns:
2956             an integer value
2957         """
2958
2959         return self.mesh.NbNodes()
2960
2961     def NbElements(self):
2962         """
2963         Return the number of elements in the mesh
2964
2965         Returns:
2966             an integer value
2967         """
2968
2969         return self.mesh.NbElements()
2970
2971     def Nb0DElements(self):
2972         """
2973         Return the number of 0d elements in the mesh
2974
2975         Returns:
2976             an integer value
2977         """
2978
2979         return self.mesh.Nb0DElements()
2980
2981     def NbBalls(self):
2982         """
2983         Return the number of ball discrete elements in the mesh
2984
2985         Returns:
2986             an integer value
2987         """
2988
2989         return self.mesh.NbBalls()
2990
2991     def NbEdges(self):
2992         """
2993         Return the number of edges in the mesh
2994
2995         Returns:
2996             an integer value
2997         """
2998
2999         return self.mesh.NbEdges()
3000
3001     def NbEdgesOfOrder(self, elementOrder):
3002         """
3003         Return the number of edges with the given order in the mesh
3004
3005         Parameters:
3006                 elementOrder: the order of elements
3007                      (SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC)
3008
3009         Returns:
3010             an integer value
3011         """
3012
3013         return self.mesh.NbEdgesOfOrder(elementOrder)
3014
3015     def NbFaces(self):
3016         """
3017         Return the number of faces in the mesh
3018
3019         Returns:
3020             an integer value
3021         """
3022
3023         return self.mesh.NbFaces()
3024
3025     def NbFacesOfOrder(self, elementOrder):
3026         """
3027         Return the number of faces with the given order in the mesh
3028
3029         Parameters:
3030                 elementOrder: the order of elements
3031                         (SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC)
3032
3033         Returns:
3034             an integer value
3035         """
3036
3037         return self.mesh.NbFacesOfOrder(elementOrder)
3038
3039     def NbTriangles(self):
3040         """
3041         Return the number of triangles in the mesh
3042
3043         Returns:
3044             an integer value
3045         """
3046
3047         return self.mesh.NbTriangles()
3048
3049     def NbTrianglesOfOrder(self, elementOrder):
3050         """
3051         Return the number of triangles with the given order in the mesh
3052
3053         Parameters:
3054                 elementOrder: is the order of elements
3055                         (SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC)
3056
3057         Returns:
3058             an integer value
3059         """
3060
3061         return self.mesh.NbTrianglesOfOrder(elementOrder)
3062
3063     def NbBiQuadTriangles(self):
3064         """
3065         Return the number of biquadratic triangles in the mesh
3066
3067         Returns:
3068             an integer value
3069         """
3070
3071         return self.mesh.NbBiQuadTriangles()
3072
3073     def NbQuadrangles(self):
3074         """
3075         Return the number of quadrangles in the mesh
3076
3077         Returns:
3078             an integer value
3079         """
3080
3081         return self.mesh.NbQuadrangles()
3082
3083     def NbQuadranglesOfOrder(self, elementOrder):
3084         """
3085         Return the number of quadrangles with the given order in the mesh
3086
3087         Parameters:
3088                 elementOrder: the order of elements
3089                         (SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC)
3090
3091         Returns:
3092             an integer value
3093         """
3094
3095         return self.mesh.NbQuadranglesOfOrder(elementOrder)
3096
3097     def NbBiQuadQuadrangles(self):
3098         """
3099         Return the number of biquadratic quadrangles in the mesh
3100
3101         Returns:
3102             an integer value
3103         """
3104
3105         return self.mesh.NbBiQuadQuadrangles()
3106
3107     def NbPolygons(self, elementOrder = SMESH.ORDER_ANY):
3108         """
3109         Return the number of polygons of given order in the mesh
3110
3111         Parameters:
3112                 elementOrder: the order of elements
3113                         (SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC)
3114
3115         Returns:
3116             an integer value
3117         """
3118
3119         return self.mesh.NbPolygonsOfOrder(elementOrder)
3120
3121     def NbVolumes(self):
3122         """
3123         Return the number of volumes in the mesh
3124
3125         Returns:
3126             an integer value
3127         """
3128
3129         return self.mesh.NbVolumes()
3130
3131
3132     def NbVolumesOfOrder(self, elementOrder):
3133         """
3134         Return the number of volumes with the given order in the mesh
3135
3136         Parameters:
3137                 elementOrder:  the order of elements
3138                     (SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC)
3139
3140         Returns:
3141             an integer value
3142         """
3143
3144         return self.mesh.NbVolumesOfOrder(elementOrder)
3145
3146     def NbTetras(self):
3147         """
3148         Return the number of tetrahedrons in the mesh
3149
3150         Returns:
3151             an integer value
3152         """
3153
3154         return self.mesh.NbTetras()
3155
3156     def NbTetrasOfOrder(self, elementOrder):
3157         """
3158         Return the number of tetrahedrons with the given order in the mesh
3159
3160         Parameters:
3161                 elementOrder:  the order of elements
3162                         (SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC)
3163
3164         Returns:
3165             an integer value
3166         """
3167
3168         return self.mesh.NbTetrasOfOrder(elementOrder)
3169
3170     def NbHexas(self):
3171         """
3172         Return the number of hexahedrons in the mesh
3173
3174         Returns:
3175             an integer value
3176         """
3177
3178         return self.mesh.NbHexas()
3179
3180     def NbHexasOfOrder(self, elementOrder):
3181         """
3182         Return the number of hexahedrons with the given order in the mesh
3183
3184         Parameters:
3185                 elementOrder:  the order of elements
3186                         (SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC)
3187
3188         Returns:
3189             an integer value
3190         """
3191
3192         return self.mesh.NbHexasOfOrder(elementOrder)
3193
3194     def NbTriQuadraticHexas(self):
3195         """
3196         Return the number of triquadratic hexahedrons in the mesh
3197
3198         Returns:
3199             an integer value
3200         """
3201
3202         return self.mesh.NbTriQuadraticHexas()
3203
3204     def NbPyramids(self):
3205         """
3206         Return the number of pyramids in the mesh
3207
3208         Returns:
3209             an integer value
3210         """
3211
3212         return self.mesh.NbPyramids()
3213
3214     def NbPyramidsOfOrder(self, elementOrder):
3215         """
3216         Return the number of pyramids with the given order in the mesh
3217
3218         Parameters:
3219                 elementOrder:  the order of elements
3220                         (SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC)
3221
3222         Returns:
3223             an integer value
3224         """
3225
3226         return self.mesh.NbPyramidsOfOrder(elementOrder)
3227
3228     def NbPrisms(self):
3229         """
3230         Return the number of prisms in the mesh
3231
3232         Returns:
3233             an integer value
3234         """
3235
3236         return self.mesh.NbPrisms()
3237
3238     def NbPrismsOfOrder(self, elementOrder):
3239         """
3240         Return the number of prisms with the given order in the mesh
3241
3242         Parameters:
3243                 elementOrder:  the order of elements
3244                         (SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC)
3245
3246         Returns:
3247             an integer value
3248         """
3249
3250         return self.mesh.NbPrismsOfOrder(elementOrder)
3251
3252     def NbHexagonalPrisms(self):
3253         """
3254         Return the number of hexagonal prisms in the mesh
3255
3256         Returns:
3257             an integer value
3258         """
3259
3260         return self.mesh.NbHexagonalPrisms()
3261
3262     def NbPolyhedrons(self):
3263         """
3264         Return the number of polyhedrons in the mesh
3265
3266         Returns:
3267             an integer value
3268         """
3269
3270         return self.mesh.NbPolyhedrons()
3271
3272     def NbSubMesh(self):
3273         """
3274         Return the number of submeshes in the mesh
3275
3276         Returns:
3277             an integer value
3278         """
3279
3280         return self.mesh.NbSubMesh()
3281
3282     def GetElementsId(self):
3283         """
3284         Return the list of all mesh elements IDs
3285
3286         Returns:
3287             the list of integer values
3288
3289         See Also:
3290             :meth:`GetElementsByType`
3291         """
3292
3293         return self.mesh.GetElementsId()
3294
3295     def GetElementsByType(self, elementType):
3296         """
3297         Return the list of IDs of mesh elements with the given type
3298
3299         Parameters:
3300                 elementType (SMESH.ElementType):  the required type of elements
3301
3302         Returns:
3303             list of integer values
3304         """
3305
3306         return self.mesh.GetElementsByType(elementType)
3307
3308     def GetNodesId(self):
3309         """
3310         Return the list of mesh nodes IDs
3311
3312         Returns:
3313             the list of integer values
3314         """
3315
3316         return self.mesh.GetNodesId()
3317
3318     # Get the information about mesh elements:
3319     # ------------------------------------
3320
3321     def GetElementType(self, id, iselem=True):
3322         """
3323         Return the type of mesh element or node
3324
3325         Returns:
3326             the value from :class:`SMESH.ElementType` enumeration. 
3327             Return SMESH.ALL if element or node with the given ID does not exist
3328         """
3329
3330         return self.mesh.GetElementType(id, iselem)
3331
3332     def GetElementGeomType(self, id):
3333         """
3334         Return the geometric type of mesh element
3335
3336         Returns:
3337             the value from :class:`SMESH.EntityType` enumeration.
3338         """
3339
3340         return self.mesh.GetElementGeomType(id)
3341
3342     def GetElementShape(self, id):
3343         """
3344         Return the shape type of mesh element
3345
3346         Returns:
3347             the value from :class:`SMESH.GeometryType` enumeration.
3348         """
3349
3350         return self.mesh.GetElementShape(id)
3351
3352     def GetSubMeshElementsId(self, Shape):
3353         """
3354         Return the list of sub-mesh elements IDs
3355
3356         Parameters:
3357                 Shape (GEOM.GEOM_Object): a geom object (sub-shape).
3358                        *Shape* must be the sub-shape of the :meth:`main shape <GetShape>`
3359
3360         Returns:
3361             list of integer values
3362         """
3363
3364         if isinstance( Shape, geomBuilder.GEOM._objref_GEOM_Object):
3365             ShapeID = self.geompyD.GetSubShapeID( self.geom, Shape )
3366         else:
3367             ShapeID = Shape
3368         return self.mesh.GetSubMeshElementsId(ShapeID)
3369
3370     def GetSubMeshNodesId(self, Shape, all):
3371         """
3372         Return the list of sub-mesh nodes IDs
3373
3374         Parameters:
3375                 Shape: a geom object (sub-shape).
3376                        *Shape* must be the sub-shape of a :meth:`GetShape`
3377                 all: If True, gives all nodes of sub-mesh elements, otherwise gives only sub-mesh nodes
3378
3379         Returns:
3380             list of integer values
3381         """
3382
3383         if isinstance( Shape, geomBuilder.GEOM._objref_GEOM_Object):
3384             ShapeID = self.geompyD.GetSubShapeID( self.geom, Shape )
3385         else:
3386             ShapeID = Shape
3387         return self.mesh.GetSubMeshNodesId(ShapeID, all)
3388
3389     def GetSubMeshElementType(self, Shape):
3390         """
3391         Return type of elements on given shape
3392
3393         Parameters:
3394                 Shape: a geom object (sub-shape).
3395                        *Shape* must be a sub-shape of a ShapeToMesh()
3396
3397         Returns:
3398             :class:`SMESH.ElementType`
3399         """
3400
3401         if isinstance( Shape, geomBuilder.GEOM._objref_GEOM_Object):
3402             ShapeID = self.geompyD.GetSubShapeID( self.geom, Shape )
3403         else:
3404             ShapeID = Shape
3405         return self.mesh.GetSubMeshElementType(ShapeID)
3406
3407     def Dump(self):
3408         """
3409         Get the mesh description
3410
3411         Returns:
3412             string value
3413         """
3414
3415         return self.mesh.Dump()
3416
3417
3418     # Get the information about nodes and elements of a mesh by its IDs:
3419     # -----------------------------------------------------------
3420
3421     def GetNodeXYZ(self, id):
3422         """
3423         Get XYZ coordinates of a node.
3424         If there is no node for the given ID - return an empty list
3425
3426         Returns:
3427             list of float values
3428         """
3429
3430         return self.mesh.GetNodeXYZ(id)
3431
3432     def GetNodeInverseElements(self, id):
3433         """
3434         Return list of IDs of inverse elements for the given node.
3435         If there is no node for the given ID - return an empty list
3436
3437         Returns:
3438             list of integer values
3439         """
3440
3441         return self.mesh.GetNodeInverseElements(id)
3442
3443     def GetNodePosition(self,NodeID):
3444         """
3445         Return the position of a node on the shape
3446
3447         Returns:
3448             :class:`SMESH.NodePosition`
3449         """
3450
3451         return self.mesh.GetNodePosition(NodeID)
3452
3453     def GetElementPosition(self,ElemID):
3454         """
3455         Return the position of an element on the shape
3456
3457         Returns:
3458             :class:`SMESH.ElementPosition`
3459         """
3460
3461         return self.mesh.GetElementPosition(ElemID)
3462
3463     def GetShapeID(self, id):
3464         """
3465         Return the ID of the shape, on which the given node was generated.
3466
3467         Returns:
3468             an integer value > 0 or -1 if there is no node for the given
3469             ID or the node is not assigned to any geometry
3470         """
3471
3472         return self.mesh.GetShapeID(id)
3473
3474     def GetShapeIDForElem(self,id):
3475         """
3476         Return the ID of the shape, on which the given element was generated.
3477
3478         Returns:
3479             an integer value > 0 or -1 if there is no element for the given
3480             ID or the element is not assigned to any geometry
3481         """
3482
3483         return self.mesh.GetShapeIDForElem(id)
3484
3485     def GetElemNbNodes(self, id):
3486         """
3487         Return the number of nodes of the given element
3488
3489         Returns:
3490             an integer value > 0 or -1 if there is no element for the given ID
3491         """
3492
3493         return self.mesh.GetElemNbNodes(id)
3494
3495     def GetElemNode(self, id, index):
3496         """
3497         Return the node ID the given (zero based) index for the given element.
3498
3499         * If there is no element for the given ID - return -1.
3500         * If there is no node for the given index - return -2.
3501
3502         Parameters:
3503             id (int): element ID
3504             index (int): node index within the element
3505
3506         Returns:
3507             an integer value (ID)
3508
3509         See Also:
3510             :meth:`GetElemNodes`
3511         """
3512
3513         return self.mesh.GetElemNode(id, index)
3514
3515     def GetElemNodes(self, id):
3516         """
3517         Return the IDs of nodes of the given element
3518
3519         Returns:
3520             a list of integer values
3521         """
3522
3523         return self.mesh.GetElemNodes(id)
3524
3525     def IsMediumNode(self, elementID, nodeID):
3526         """
3527         Return true if the given node is the medium node in the given quadratic element
3528         """
3529
3530         return self.mesh.IsMediumNode(elementID, nodeID)
3531
3532     def IsMediumNodeOfAnyElem(self, nodeID, elementType = SMESH.ALL ):
3533         """
3534         Return true if the given node is the medium node in one of quadratic elements
3535
3536         Parameters:
3537                 nodeID: ID of the node
3538                 elementType:  the type of elements to check a state of the node, either of
3539                         (SMESH.ALL, SMESH.NODE, SMESH.EDGE, SMESH.FACE or SMESH.VOLUME)
3540         """
3541
3542         return self.mesh.IsMediumNodeOfAnyElem(nodeID, elementType)
3543
3544     def ElemNbEdges(self, id):
3545         """
3546         Return the number of edges for the given element
3547         """
3548
3549         return self.mesh.ElemNbEdges(id)
3550
3551     def ElemNbFaces(self, id):
3552         """
3553         Return the number of faces for the given element
3554         """
3555
3556         return self.mesh.ElemNbFaces(id)
3557
3558     def GetElemFaceNodes(self,elemId, faceIndex):
3559         """
3560         Return nodes of given face (counted from zero) for given volumic element.
3561         """
3562
3563         return self.mesh.GetElemFaceNodes(elemId, faceIndex)
3564
3565     def GetFaceNormal(self, faceId, normalized=False):
3566         """
3567         Return three components of normal of given mesh face
3568         (or an empty array in KO case)
3569         """
3570
3571         return self.mesh.GetFaceNormal(faceId,normalized)
3572
3573     def FindElementByNodes(self, nodes):
3574         """
3575         Return an element based on all given nodes.
3576         """
3577
3578         return self.mesh.FindElementByNodes(nodes)
3579
3580     def GetElementsByNodes(self, nodes, elemType=SMESH.ALL):
3581         """
3582         Return elements including all given nodes.
3583         """
3584
3585         return self.mesh.GetElementsByNodes( nodes, elemType )
3586
3587     def IsPoly(self, id):
3588         """
3589         Return true if the given element is a polygon
3590         """
3591
3592         return self.mesh.IsPoly(id)
3593
3594     def IsQuadratic(self, id):
3595         """
3596         Return true if the given element is quadratic
3597         """
3598
3599         return self.mesh.IsQuadratic(id)
3600
3601     def GetBallDiameter(self, id):
3602         """
3603         Return diameter of a ball discrete element or zero in case of an invalid *id*
3604         """
3605
3606         return self.mesh.GetBallDiameter(id)
3607
3608     def BaryCenter(self, id):
3609         """
3610         Return XYZ coordinates of the barycenter of the given element.
3611         If there is no element for the given ID - return an empty list
3612
3613         Returns:
3614             a list of three double values
3615         """
3616
3617         return self.mesh.BaryCenter(id)
3618
3619     def GetIdsFromFilter(self, theFilter):
3620         """
3621         Pass mesh elements through the given filter and return IDs of fitting elements
3622
3623         Parameters:
3624                 theFilter: :class:`SMESH.Filter`
3625
3626         Returns:
3627             a list of ids
3628
3629         See Also:
3630             :meth:`SMESH.Filter.GetIDs`
3631         """
3632
3633         theFilter.SetMesh( self.mesh )
3634         return theFilter.GetIDs()
3635
3636     # Get mesh measurements information:
3637     # ------------------------------------
3638
3639     def GetFreeBorders(self):
3640         """
3641         Verify whether a 2D mesh element has free edges (edges connected to one face only).
3642         Return a list of special structures (borders).
3643
3644         Returns:
3645             a list of :class:`SMESH.FreeEdges.Border`
3646         """
3647
3648         aFilterMgr = self.smeshpyD.CreateFilterManager()
3649         aPredicate = aFilterMgr.CreateFreeEdges()
3650         aPredicate.SetMesh(self.mesh)
3651         aBorders = aPredicate.GetBorders()
3652         aFilterMgr.UnRegister()
3653         return aBorders
3654
3655     def MinDistance(self, id1, id2=0, isElem1=False, isElem2=False):
3656         """
3657         Get minimum distance between two nodes, elements or distance to the origin
3658
3659         Parameters:
3660                 id1: first node/element id
3661                 id2: second node/element id (if 0, distance from *id1* to the origin is computed)
3662                 isElem1: *True* if *id1* is element id, *False* if it is node id
3663                 isElem2: *True* if *id2* is element id, *False* if it is node id
3664
3665         Returns:
3666             minimum distance value **GetMinDistance()**
3667         """
3668
3669         aMeasure = self.GetMinDistance(id1, id2, isElem1, isElem2)
3670         return aMeasure.value
3671
3672     def GetMinDistance(self, id1, id2=0, isElem1=False, isElem2=False):
3673         """
3674         Get :class:`SMESH.Measure` structure specifying minimum distance data between two objects
3675
3676         Parameters:
3677                 id1: first node/element id
3678                 id2: second node/element id (if 0, distance from *id1* to the origin is computed)
3679                 isElem1: *True* if *id1* is element id, *False* if it is node id
3680                 isElem2: *True* if *id2* is element id, *False* if it is node id
3681
3682         Returns:
3683             :class:`SMESH.Measure` structure
3684         See Also:
3685             :meth:`MinDistance`
3686         """
3687
3688         if isElem1:
3689             id1 = self.editor.MakeIDSource([id1], SMESH.FACE)
3690         else:
3691             id1 = self.editor.MakeIDSource([id1], SMESH.NODE)
3692         if id2 != 0:
3693             if isElem2:
3694                 id2 = self.editor.MakeIDSource([id2], SMESH.FACE)
3695             else:
3696                 id2 = self.editor.MakeIDSource([id2], SMESH.NODE)
3697             pass
3698         else:
3699             id2 = None
3700
3701         aMeasurements = self.smeshpyD.CreateMeasurements()
3702         aMeasure = aMeasurements.MinDistance(id1, id2)
3703         genObjUnRegister([aMeasurements,id1, id2])
3704         return aMeasure
3705
3706     def BoundingBox(self, objects=None, isElem=False):
3707         """
3708         Get bounding box of the specified object(s)
3709
3710         Parameters:
3711                 objects: single :class:`source object <SMESH.SMESH_IDSource>` or list of source objects or list of nodes/elements IDs
3712                 isElem: if *objects* is a list of IDs, *True* value in this parameters specifies that *objects* are elements,
3713                         *False* specifies that *objects* are nodes
3714
3715         Returns:
3716             tuple of six values (minX, minY, minZ, maxX, maxY, maxZ)
3717
3718         See Also: 
3719             :meth:`GetBoundingBox()`
3720         """
3721
3722         result = self.GetBoundingBox(objects, isElem)
3723         if result is None:
3724             result = (0.0,)*6
3725         else:
3726             result = (result.minX, result.minY, result.minZ, result.maxX, result.maxY, result.maxZ)
3727         return result
3728
3729     def GetBoundingBox(self, objects=None, isElem=False):
3730         """
3731         Get :class:`SMESH.Measure` structure specifying bounding box data of the specified object(s)
3732
3733         Parameters:
3734                 objects: single :class:`source object <SMESH.SMESH_IDSource>` or list of source objects or list of nodes/elements IDs
3735                 isElem: if *objects* is a list of IDs, True means that *objects* are elements,
3736                         False means that *objects* are nodes
3737
3738         Returns:
3739             :class:`SMESH.Measure` structure
3740
3741         See Also: 
3742             :meth:`BoundingBox()`
3743         """
3744
3745         if objects is None:
3746             objects = [self.mesh]
3747         elif isinstance(objects, tuple):
3748             objects = list(objects)
3749         if not isinstance(objects, list):
3750             objects = [objects]
3751         if len(objects) > 0 and isinstance(objects[0], int):
3752             objects = [objects]
3753         srclist = []
3754         unRegister = genObjUnRegister()
3755         for o in objects:
3756             if isinstance(o, Mesh):
3757                 srclist.append(o.mesh)
3758             elif hasattr(o, "_narrow"):
3759                 src = o._narrow(SMESH.SMESH_IDSource)
3760                 if src: srclist.append(src)
3761                 pass
3762             elif isinstance(o, list):
3763                 if isElem:
3764                     srclist.append(self.editor.MakeIDSource(o, SMESH.FACE))
3765                 else:
3766                     srclist.append(self.editor.MakeIDSource(o, SMESH.NODE))
3767                 unRegister.set( srclist[-1] )
3768                 pass
3769             pass
3770         aMeasurements = self.smeshpyD.CreateMeasurements()
3771         unRegister.set( aMeasurements )
3772         aMeasure = aMeasurements.BoundingBox(srclist)
3773         return aMeasure
3774
3775     # Mesh edition (SMESH_MeshEditor functionality):
3776     # ---------------------------------------------
3777
3778     def RemoveElements(self, IDsOfElements):
3779         """
3780         Remove the elements from the mesh by ids
3781
3782         Parameters:
3783                 IDsOfElements: is a list of ids of elements to remove
3784
3785         Returns:
3786             True or False
3787         """
3788
3789         return self.editor.RemoveElements(IDsOfElements)
3790
3791     def RemoveNodes(self, IDsOfNodes):
3792         """
3793         Remove nodes from mesh by ids
3794
3795         Parameters:
3796                 IDsOfNodes: is a list of ids of nodes to remove
3797
3798         Returns:
3799             True or False
3800         """
3801
3802         return self.editor.RemoveNodes(IDsOfNodes)
3803
3804     def RemoveOrphanNodes(self):
3805         """
3806         Remove all orphan (free) nodes from mesh
3807
3808         Returns:
3809             number of the removed nodes
3810         """
3811
3812         return self.editor.RemoveOrphanNodes()
3813
3814     def AddNode(self, x, y, z):
3815         """
3816         Add a node to the mesh by coordinates
3817
3818         Returns:
3819             ID of the new node
3820         """
3821
3822         x,y,z,Parameters,hasVars = ParseParameters(x,y,z)
3823         if hasVars: self.mesh.SetParameters(Parameters)
3824         return self.editor.AddNode( x, y, z)
3825
3826     def Add0DElement( self, IDOfNode, DuplicateElements=True ):
3827         """
3828         Create a 0D element on a node with given number.
3829
3830         Parameters:
3831                 IDOfNode: the ID of node for creation of the element.
3832                 DuplicateElements: to add one more 0D element to a node or not
3833
3834         Returns:
3835             ID of the new 0D element
3836         """
3837
3838         return self.editor.Add0DElement( IDOfNode, DuplicateElements )
3839
3840     def Add0DElementsToAllNodes(self, theObject, theGroupName="", DuplicateElements=False):
3841         """
3842         Create 0D elements on all nodes of the given elements except those
3843         nodes on which a 0D element already exists.
3844
3845         Parameters:
3846                 theObject: an object on whose nodes 0D elements will be created.
3847                         It can be list of element IDs, :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
3848                 theGroupName: optional name of a group to add 0D elements created
3849                         and/or found on nodes of *theObject*.
3850                 DuplicateElements: to add one more 0D element to a node or not
3851
3852         Returns:
3853             an object (a new group or a temporary :class:`SMESH.SMESH_IDSource`) holding
3854             IDs of new and/or found 0D elements. IDs of 0D elements
3855             can be retrieved from the returned object by 
3856             calling :meth:`GetIDs() <SMESH.SMESH_IDSource.GetIDs>`
3857         """
3858
3859         unRegister = genObjUnRegister()
3860         if isinstance( theObject, Mesh ):
3861             theObject = theObject.GetMesh()
3862         elif isinstance( theObject, list ):
3863             theObject = self.GetIDSource( theObject, SMESH.ALL )
3864             unRegister.set( theObject )
3865         return self.editor.Create0DElementsOnAllNodes( theObject, theGroupName, DuplicateElements )
3866
3867     def AddBall(self, IDOfNode, diameter):
3868         """
3869         Create a ball element on a node with given ID.
3870
3871         Parameters:
3872                 IDOfNode: the ID of node for creation of the element.
3873                 diameter: the bal diameter.
3874
3875         Returns:
3876             ID of the new ball element
3877         """
3878
3879         return self.editor.AddBall( IDOfNode, diameter )
3880
3881     def AddEdge(self, IDsOfNodes):
3882         """
3883         Create a linear or quadratic edge (this is determined
3884         by the number of given nodes).
3885
3886         Parameters:
3887                 IDsOfNodes: list of node IDs for creation of the element.
3888                         The order of nodes in this list should correspond to
3889                         the :ref:`connectivity convention <connectivity_page>`.
3890
3891         Returns:
3892             ID of the new edge
3893         """
3894
3895         return self.editor.AddEdge(IDsOfNodes)
3896
3897     def AddFace(self, IDsOfNodes):
3898         """
3899         Create a linear or quadratic face (this is determined
3900         by the number of given nodes).
3901
3902         Parameters:
3903                 IDsOfNodes: list of node IDs for creation of the element.
3904                         The order of nodes in this list should correspond to
3905                         the :ref:`connectivity convention <connectivity_page>`.
3906
3907         Returns:
3908             ID of the new face
3909         """
3910
3911         return self.editor.AddFace(IDsOfNodes)
3912
3913     def AddPolygonalFace(self, IdsOfNodes):
3914         """
3915         Add a polygonal face defined by a list of node IDs
3916
3917         Parameters:
3918                 IdsOfNodes: the list of node IDs for creation of the element.
3919
3920         Returns:
3921             ID of the new face
3922         """
3923
3924         return self.editor.AddPolygonalFace(IdsOfNodes)
3925
3926     def AddQuadPolygonalFace(self, IdsOfNodes):
3927         """
3928         Add a quadratic polygonal face defined by a list of node IDs
3929
3930         Parameters:
3931                 IdsOfNodes: the list of node IDs for creation of the element;
3932                         corner nodes follow first.
3933
3934         Returns:
3935             ID of the new face
3936         """
3937
3938         return self.editor.AddQuadPolygonalFace(IdsOfNodes)
3939
3940     def AddVolume(self, IDsOfNodes):
3941         """
3942         Create both simple and quadratic volume (this is determined
3943         by the number of given nodes).
3944
3945         Parameters:
3946                 IDsOfNodes: list of node IDs for creation of the element.
3947                         The order of nodes in this list should correspond to
3948                         the :ref:`connectivity convention <connectivity_page>`.
3949
3950         Returns:
3951             ID of the new volumic element
3952         """
3953
3954         return self.editor.AddVolume(IDsOfNodes)
3955
3956     def AddPolyhedralVolume (self, IdsOfNodes, Quantities):
3957         """
3958         Create a volume of many faces, giving nodes for each face.
3959
3960         Parameters:
3961                 IdsOfNodes: list of node IDs for volume creation, face by face.
3962                 Quantities: list of integer values, Quantities[i]
3963                         gives the quantity of nodes in face number i.
3964
3965         Returns:
3966             ID of the new volumic element
3967         """
3968
3969         return self.editor.AddPolyhedralVolume(IdsOfNodes, Quantities)
3970
3971     def AddPolyhedralVolumeByFaces (self, IdsOfFaces):
3972         """
3973         Create a volume of many faces, giving the IDs of the existing faces.
3974
3975         Note:
3976                 The created volume will refer only to the nodes
3977                 of the given faces, not to the faces themselves.
3978
3979         Parameters:
3980                 IdsOfFaces: the list of face IDs for volume creation.
3981
3982         Returns:
3983             ID of the new volumic element
3984         """
3985
3986         return self.editor.AddPolyhedralVolumeByFaces(IdsOfFaces)
3987
3988
3989     def SetNodeOnVertex(self, NodeID, Vertex):
3990         """
3991         Binds a node to a vertex
3992
3993         Parameters:
3994                 NodeID: a node ID
3995                 Vertex: a vertex (GEOM.GEOM_Object) or vertex ID
3996
3997         Returns:
3998             True if succeed else raises an exception
3999         """
4000
4001         if ( isinstance( Vertex, geomBuilder.GEOM._objref_GEOM_Object)):
4002             VertexID = self.geompyD.GetSubShapeID( self.geom, Vertex )
4003         else:
4004             VertexID = Vertex
4005         try:
4006             self.editor.SetNodeOnVertex(NodeID, VertexID)
4007         except SALOME.SALOME_Exception as inst:
4008             raise ValueError(inst.details.text)
4009         return True
4010
4011
4012     def SetNodeOnEdge(self, NodeID, Edge, paramOnEdge):
4013         """
4014         Stores the node position on an edge
4015
4016         Parameters:
4017                 NodeID: a node ID
4018                 Edge: an edge (GEOM.GEOM_Object) or edge ID
4019                 paramOnEdge: a parameter on the edge where the node is located
4020
4021         Returns:
4022             True if succeed else raises an exception
4023         """
4024
4025         if ( isinstance( Edge, geomBuilder.GEOM._objref_GEOM_Object)):
4026             EdgeID = self.geompyD.GetSubShapeID( self.geom, Edge )
4027         else:
4028             EdgeID = Edge
4029         try:
4030             self.editor.SetNodeOnEdge(NodeID, EdgeID, paramOnEdge)
4031         except SALOME.SALOME_Exception as inst:
4032             raise ValueError(inst.details.text)
4033         return True
4034
4035     def SetNodeOnFace(self, NodeID, Face, u, v):
4036         """
4037         Stores node position on a face
4038
4039         Parameters:
4040                 NodeID: a node ID
4041                 Face: a face (GEOM.GEOM_Object) or face ID
4042                 u: U parameter on the face where the node is located
4043                 v: V parameter on the face where the node is located
4044
4045         Returns:
4046             True if succeed else raises an exception
4047         """
4048
4049         if ( isinstance( Face, geomBuilder.GEOM._objref_GEOM_Object)):
4050             FaceID = self.geompyD.GetSubShapeID( self.geom, Face )
4051         else:
4052             FaceID = Face
4053         try:
4054             self.editor.SetNodeOnFace(NodeID, FaceID, u, v)
4055         except SALOME.SALOME_Exception as inst:
4056             raise ValueError(inst.details.text)
4057         return True
4058
4059     def SetNodeInVolume(self, NodeID, Solid):
4060         """
4061         Binds a node to a solid
4062
4063         Parameters:
4064                 NodeID: a node ID
4065                 Solid:  a solid (GEOM.GEOM_Object) or solid ID
4066
4067         Returns:
4068             True if succeed else raises an exception
4069         """
4070
4071         if ( isinstance( Solid, geomBuilder.GEOM._objref_GEOM_Object)):
4072             SolidID = self.geompyD.GetSubShapeID( self.geom, Solid )
4073         else:
4074             SolidID = Solid
4075         try:
4076             self.editor.SetNodeInVolume(NodeID, SolidID)
4077         except SALOME.SALOME_Exception as inst:
4078             raise ValueError(inst.details.text)
4079         return True
4080
4081     def SetMeshElementOnShape(self, ElementID, Shape):
4082         """
4083         Bind an element to a shape
4084
4085         Parameters:
4086                 ElementID: an element ID
4087                 Shape: a shape (GEOM.GEOM_Object) or shape ID
4088
4089         Returns:
4090             True if succeed else raises an exception
4091         """
4092
4093         if ( isinstance( Shape, geomBuilder.GEOM._objref_GEOM_Object)):
4094             ShapeID = self.geompyD.GetSubShapeID( self.geom, Shape )
4095         else:
4096             ShapeID = Shape
4097         try:
4098             self.editor.SetMeshElementOnShape(ElementID, ShapeID)
4099         except SALOME.SALOME_Exception as inst:
4100             raise ValueError(inst.details.text)
4101         return True
4102
4103
4104     def MoveNode(self, NodeID, x, y, z):
4105         """
4106         Move the node with the given id
4107
4108         Parameters:
4109                 NodeID: the id of the node
4110                 x:  a new X coordinate
4111                 y:  a new Y coordinate
4112                 z:  a new Z coordinate
4113
4114         Returns:
4115             True if succeed else False
4116         """
4117
4118         x,y,z,Parameters,hasVars = ParseParameters(x,y,z)
4119         if hasVars: self.mesh.SetParameters(Parameters)
4120         return self.editor.MoveNode(NodeID, x, y, z)
4121
4122     def MoveClosestNodeToPoint(self, x, y, z, NodeID):
4123         """
4124         Find the node closest to a point and moves it to a point location
4125
4126         Parameters:
4127                 x:  the X coordinate of a point
4128                 y:  the Y coordinate of a point
4129                 z:  the Z coordinate of a point
4130                 NodeID: if specified (>0), the node with this ID is moved,
4131                         otherwise, the node closest to point (*x*, *y*, *z*) is moved
4132
4133         Returns:
4134             the ID of a moved node
4135         """
4136
4137         x,y,z,Parameters,hasVars = ParseParameters(x,y,z)
4138         if hasVars: self.mesh.SetParameters(Parameters)
4139         return self.editor.MoveClosestNodeToPoint(x, y, z, NodeID)
4140
4141     def FindNodeClosestTo(self, x, y, z):
4142         """
4143         Find the node closest to a point
4144
4145         Parameters:
4146                 x:  the X coordinate of a point
4147                 y:  the Y coordinate of a point
4148                 z:  the Z coordinate of a point
4149
4150         Returns:
4151             the ID of a node
4152         """
4153
4154         #preview = self.mesh.GetMeshEditPreviewer()
4155         #return preview.MoveClosestNodeToPoint(x, y, z, -1)
4156         return self.editor.FindNodeClosestTo(x, y, z)
4157
4158     def FindElementsByPoint(self, x, y, z, elementType = SMESH.ALL, meshPart=None):
4159         """
4160         Find the elements where a point lays IN or ON
4161
4162         Parameters:
4163                 x,y,z (float): coordinates of the point
4164                 elementType (SMESH.ElementType): type of elements to find; SMESH.ALL type
4165                         means elements of any type excluding nodes, discrete and 0D elements.
4166                 meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to search within
4167
4168         Returns:
4169             list of IDs of found elements
4170         """
4171         if meshPart:
4172             return self.editor.FindAmongElementsByPoint( meshPart, x, y, z, elementType );
4173         else:
4174             return self.editor.FindElementsByPoint(x, y, z, elementType)
4175
4176     def GetPointState(self, x, y, z):
4177         """
4178         Return point state in a closed 2D mesh in terms of TopAbs_State enumeration:
4179         0-IN, 1-OUT, 2-ON, 3-UNKNOWN.
4180         UNKNOWN state means that either mesh is wrong or the analysis fails.
4181         """
4182
4183         return self.editor.GetPointState(x, y, z)
4184
4185     def IsManifold(self):
4186         """
4187         Check if a 2D mesh is manifold
4188         """
4189
4190         return self.editor.IsManifold()
4191
4192     def IsCoherentOrientation2D(self):
4193         """
4194         Check if orientation of 2D elements is coherent
4195         """
4196
4197         return self.editor.IsCoherentOrientation2D()
4198
4199     def MeshToPassThroughAPoint(self, x, y, z):
4200         """
4201         Find the node closest to a point and moves it to a point location
4202
4203         Parameters:
4204                 x:  the X coordinate of a point
4205                 y:  the Y coordinate of a point
4206                 z:  the Z coordinate of a point
4207
4208         Returns:
4209             the ID of a moved node
4210         """
4211
4212         return self.editor.MoveClosestNodeToPoint(x, y, z, -1)
4213
4214     def InverseDiag(self, NodeID1, NodeID2):
4215         """
4216         Replace two neighbour triangles sharing Node1-Node2 link
4217         with the triangles built on the same 4 nodes but having other common link.
4218
4219         Parameters:
4220                 NodeID1:  the ID of the first node
4221                 NodeID2:  the ID of the second node
4222
4223         Returns:
4224             False if proper faces were not found
4225         """
4226         return self.editor.InverseDiag(NodeID1, NodeID2)
4227
4228     def DeleteDiag(self, NodeID1, NodeID2):
4229         """
4230         Replace two neighbour triangles sharing *Node1-Node2* link
4231         with a quadrangle built on the same 4 nodes.
4232
4233         Parameters:
4234                 NodeID1: ID of the first node
4235                 NodeID2: ID of the second node
4236
4237         Returns:
4238             False if proper faces were not found
4239         """
4240
4241         return self.editor.DeleteDiag(NodeID1, NodeID2)
4242
4243     def Reorient(self, IDsOfElements=None):
4244         """
4245         Reorient elements by ids
4246
4247         Parameters:
4248                 IDsOfElements: if undefined reorients all mesh elements
4249
4250         Returns:
4251             True if succeed else False
4252         """
4253
4254         if IDsOfElements == None:
4255             IDsOfElements = self.GetElementsId()
4256         return self.editor.Reorient(IDsOfElements)
4257
4258     def ReorientObject(self, theObject):
4259         """
4260         Reorient all elements of the object
4261
4262         Parameters:
4263                 theObject: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
4264
4265         Returns:
4266             True if succeed else False
4267         """
4268
4269         if ( isinstance( theObject, Mesh )):
4270             theObject = theObject.GetMesh()
4271         return self.editor.ReorientObject(theObject)
4272
4273     def Reorient2D(self, the2DObject, theDirection, theFaceOrPoint ):
4274         """
4275         Reorient faces contained in *the2DObject*.
4276
4277         Parameters:
4278                 the2DObject: is a :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>` or list of IDs of 2D elements
4279                 theDirection: is a desired direction of normal of *theFace*.
4280                         It can be either a GEOM vector or a list of coordinates [x,y,z].
4281                 theFaceOrPoint: defines a face of *the2DObject* whose normal will be
4282                         compared with theDirection. It can be either ID of face or a point
4283                         by which the face will be found. The point can be given as either
4284                         a GEOM vertex or a list of point coordinates.
4285
4286         Returns:
4287             number of reoriented faces
4288         """
4289
4290         unRegister = genObjUnRegister()
4291         # check the2DObject
4292         if isinstance( the2DObject, Mesh ):
4293             the2DObject = the2DObject.GetMesh()
4294         if isinstance( the2DObject, list ):
4295             the2DObject = self.GetIDSource( the2DObject, SMESH.FACE )
4296             unRegister.set( the2DObject )
4297         # check theDirection
4298         if isinstance( theDirection, geomBuilder.GEOM._objref_GEOM_Object):
4299             theDirection = self.smeshpyD.GetDirStruct( theDirection )
4300         if isinstance( theDirection, list ):
4301             theDirection = self.smeshpyD.MakeDirStruct( *theDirection  )
4302         # prepare theFace and thePoint
4303         theFace = theFaceOrPoint
4304         thePoint = PointStruct(0,0,0)
4305         if isinstance( theFaceOrPoint, geomBuilder.GEOM._objref_GEOM_Object):
4306             thePoint = self.smeshpyD.GetPointStruct( theFaceOrPoint )
4307             theFace = -1
4308         if isinstance( theFaceOrPoint, list ):
4309             thePoint = PointStruct( *theFaceOrPoint )
4310             theFace = -1
4311         if isinstance( theFaceOrPoint, PointStruct ):
4312             thePoint = theFaceOrPoint
4313             theFace = -1
4314         return self.editor.Reorient2D( the2DObject, theDirection, theFace, thePoint )
4315
4316     def Reorient2DBy3D(self, the2DObject, the3DObject, theOutsideNormal=True ):
4317         """
4318         Reorient faces according to adjacent volumes.
4319
4320         Parameters:
4321                 the2DObject: is a :class:`mesh, sub-mesh, group, filter <SMESH.SMESH_IDSource>` or list of
4322                         either IDs of faces or face groups.
4323                 the3DObject: is a :class:`mesh, sub-mesh, group, filter <SMESH.SMESH_IDSource>` or list of IDs of volumes.
4324                 theOutsideNormal: to orient faces to have their normals
4325                         pointing either *outside* or *inside* the adjacent volumes.
4326
4327         Returns:
4328             number of reoriented faces.
4329         """
4330
4331         unRegister = genObjUnRegister()
4332         # check the2DObject
4333         if not isinstance( the2DObject, list ):
4334             the2DObject = [ the2DObject ]
4335         elif the2DObject and isinstance( the2DObject[0], int ):
4336             the2DObject = self.GetIDSource( the2DObject, SMESH.FACE )
4337             unRegister.set( the2DObject )
4338             the2DObject = [ the2DObject ]
4339         for i,obj2D in enumerate( the2DObject ):
4340             if isinstance( obj2D, Mesh ):
4341                 the2DObject[i] = obj2D.GetMesh()
4342             if isinstance( obj2D, list ):
4343                 the2DObject[i] = self.GetIDSource( obj2D, SMESH.FACE )
4344                 unRegister.set( the2DObject[i] )
4345         # check the3DObject
4346         if isinstance( the3DObject, Mesh ):
4347             the3DObject = the3DObject.GetMesh()
4348         if isinstance( the3DObject, list ):
4349             the3DObject = self.GetIDSource( the3DObject, SMESH.VOLUME )
4350             unRegister.set( the3DObject )
4351         return self.editor.Reorient2DBy3D( the2DObject, the3DObject, theOutsideNormal )
4352
4353     def TriToQuad(self, IDsOfElements, theCriterion, MaxAngle):
4354         """
4355         Fuse the neighbouring triangles into quadrangles.
4356
4357         Parameters:
4358                 IDsOfElements: The triangles to be fused.
4359                 theCriterion:  a numerical functor, in terms of enum :class:`SMESH.FunctorType`, used to
4360                         applied to possible quadrangles to choose a neighbour to fuse with.
4361                         Note that not all items of :class:`SMESH.FunctorType` corresponds
4362                         to numerical functors.
4363                 MaxAngle: is the maximum angle between element normals at which the fusion
4364                         is still performed; theMaxAngle is measured in radians.
4365                         Also it could be a name of variable which defines angle in degrees.
4366
4367         Returns:
4368             True in case of success, False otherwise.
4369         """
4370
4371         MaxAngle,Parameters,hasVars = ParseAngles(MaxAngle)
4372         self.mesh.SetParameters(Parameters)
4373         if not IDsOfElements:
4374             IDsOfElements = self.GetElementsId()
4375         Functor = self.smeshpyD.GetFunctor(theCriterion)
4376         return self.editor.TriToQuad(IDsOfElements, Functor, MaxAngle)
4377
4378     def TriToQuadObject (self, theObject, theCriterion, MaxAngle):
4379         """
4380         Fuse the neighbouring triangles of the object into quadrangles
4381
4382         Parameters:
4383                 theObject: is :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
4384                 theCriterion: is a numerical functor, in terms of enum :class:`SMESH.FunctorType`,
4385                         applied to possible quadrangles to choose a neighbour to fuse with.
4386                         Note that not all items of :class:`SMESH.FunctorType` corresponds
4387                         to numerical functors.
4388                 MaxAngle: a max angle between element normals at which the fusion
4389                         is still performed; theMaxAngle is measured in radians.
4390
4391         Returns:
4392             True in case of success, False otherwise.
4393         """
4394
4395         MaxAngle,Parameters,hasVars = ParseAngles(MaxAngle)
4396         self.mesh.SetParameters(Parameters)
4397         if isinstance( theObject, Mesh ):
4398             theObject = theObject.GetMesh()
4399         Functor = self.smeshpyD.GetFunctor(theCriterion)
4400         return self.editor.TriToQuadObject(theObject, Functor, MaxAngle)
4401
4402     def QuadToTri (self, IDsOfElements, theCriterion = None):
4403         """
4404         Split quadrangles into triangles.
4405
4406         Parameters:
4407                 IDsOfElements: the faces to be splitted.
4408                 theCriterion: is a numerical functor, in terms of enum :class:`SMESH.FunctorType`, used to
4409                         choose a diagonal for splitting. If *theCriterion* is None, which is a default
4410                         value, then quadrangles will be split by the smallest diagonal.
4411                         Note that not all items of :class:`SMESH.FunctorType` corresponds
4412                         to numerical functors.
4413
4414         Returns:
4415             True in case of success, False otherwise.
4416         """
4417         if IDsOfElements == []:
4418             IDsOfElements = self.GetElementsId()
4419         if theCriterion is None:
4420             theCriterion = FT_MaxElementLength2D
4421         Functor = self.smeshpyD.GetFunctor(theCriterion)
4422         return self.editor.QuadToTri(IDsOfElements, Functor)
4423
4424     def QuadToTriObject (self, theObject, theCriterion = None):
4425         """
4426         Split quadrangles into triangles.
4427
4428         Parameters:
4429                 theObject: the object from which the list of elements is taken,
4430                         this is :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
4431                 theCriterion: is a numerical functor, in terms of enum :class:`SMESH.FunctorType`, used to
4432                         choose a diagonal for splitting. If *theCriterion* is None, which is a default
4433                         value, then quadrangles will be split by the smallest diagonal.
4434                         Note that not all items of :class:`SMESH.FunctorType` corresponds
4435                         to numerical functors.
4436
4437         Returns:
4438             True in case of success, False otherwise.
4439         """
4440         if ( isinstance( theObject, Mesh )):
4441             theObject = theObject.GetMesh()
4442         if theCriterion is None:
4443             theCriterion = FT_MaxElementLength2D
4444         Functor = self.smeshpyD.GetFunctor(theCriterion)
4445         return self.editor.QuadToTriObject(theObject, Functor)
4446
4447     def QuadTo4Tri (self, theElements=[]):
4448         """
4449         Split each of given quadrangles into 4 triangles. A node is added at the center of
4450         a quadrangle.
4451
4452         Parameters:
4453                 theElements: the faces to be splitted. This can be either 
4454                         :class:`mesh, sub-mesh, group, filter <SMESH.SMESH_IDSource>`
4455                         or a list of face IDs. By default all quadrangles are split
4456         """
4457         unRegister = genObjUnRegister()
4458         if isinstance( theElements, Mesh ):
4459             theElements = theElements.mesh
4460         elif not theElements:
4461             theElements = self.mesh
4462         elif isinstance( theElements, list ):
4463             theElements = self.GetIDSource( theElements, SMESH.FACE )
4464             unRegister.set( theElements )
4465         return self.editor.QuadTo4Tri( theElements )
4466
4467     def SplitQuad (self, IDsOfElements, Diag13):
4468         """
4469         Split quadrangles into triangles.
4470
4471         Parameters:
4472                 IDsOfElements: the faces to be splitted
4473                 Diag13:        is used to choose a diagonal for splitting.
4474
4475         Returns:
4476             True in case of success, False otherwise.
4477         """
4478         if IDsOfElements == []:
4479             IDsOfElements = self.GetElementsId()
4480         return self.editor.SplitQuad(IDsOfElements, Diag13)
4481
4482     def SplitQuadObject (self, theObject, Diag13):
4483         """
4484         Split quadrangles into triangles.
4485
4486         Parameters:
4487                 theObject: the object from which the list of elements is taken,
4488                         this is :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
4489                 Diag13:    is used to choose a diagonal for splitting.
4490
4491         Returns:
4492             True in case of success, False otherwise.
4493         """
4494         if ( isinstance( theObject, Mesh )):
4495             theObject = theObject.GetMesh()
4496         return self.editor.SplitQuadObject(theObject, Diag13)
4497
4498     def BestSplit (self, IDOfQuad, theCriterion):
4499         """
4500         Find a better splitting of the given quadrangle.
4501
4502         Parameters:
4503                 IDOfQuad:   the ID of the quadrangle to be splitted.
4504                 theCriterion:  is a numerical functor, in terms of enum :class:`SMESH.FunctorType`, used to
4505                         choose a diagonal for splitting.
4506                         Note that not all items of :class:`SMESH.FunctorType` corresponds
4507                         to numerical functors.
4508
4509         Returns:
4510             * 1 if 1-3 diagonal is better, 
4511             * 2 if 2-4 diagonal is better, 
4512             * 0 if error occurs.
4513         """
4514         return self.editor.BestSplit(IDOfQuad, self.smeshpyD.GetFunctor(theCriterion))
4515
4516     def SplitVolumesIntoTetra(self, elems, method=smeshBuilder.Hex_5Tet ):
4517         """
4518         Split volumic elements into tetrahedrons
4519
4520         Parameters:
4521                 elems: either a list of elements or a :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
4522                 method:  flags passing splitting method:
4523                         smesh.Hex_5Tet, smesh.Hex_6Tet, smesh.Hex_24Tet.
4524                         smesh.Hex_5Tet - to split the hexahedron into 5 tetrahedrons, etc.
4525         """
4526         unRegister = genObjUnRegister()
4527         if isinstance( elems, Mesh ):
4528             elems = elems.GetMesh()
4529         if ( isinstance( elems, list )):
4530             elems = self.editor.MakeIDSource(elems, SMESH.VOLUME)
4531             unRegister.set( elems )
4532         self.editor.SplitVolumesIntoTetra(elems, method)
4533         return
4534
4535     def SplitBiQuadraticIntoLinear(self, elems=None):
4536         """
4537         Split bi-quadratic elements into linear ones without creation of additional nodes:
4538
4539             - bi-quadratic triangle will be split into 3 linear quadrangles;
4540             - bi-quadratic quadrangle will be split into 4 linear quadrangles;
4541             - tri-quadratic hexahedron will be split into 8 linear hexahedra.
4542
4543         Quadratic elements of lower dimension  adjacent to the split bi-quadratic element
4544         will be split in order to keep the mesh conformal.
4545
4546         Parameters:
4547             elems: elements to split\: :class:`mesh, sub-mesh, group, filter <SMESH.SMESH_IDSource>` or element IDs;
4548                 if None (default), all bi-quadratic elements will be split
4549         """
4550         unRegister = genObjUnRegister()
4551         if elems and isinstance( elems, list ) and isinstance( elems[0], int ):
4552             elems = self.editor.MakeIDSource(elems, SMESH.ALL)
4553             unRegister.set( elems )
4554         if elems is None:
4555             elems = [ self.GetMesh() ]
4556         if isinstance( elems, Mesh ):
4557             elems = [ elems.GetMesh() ]
4558         if not isinstance( elems, list ):
4559             elems = [elems]
4560         self.editor.SplitBiQuadraticIntoLinear( elems )
4561
4562     def SplitHexahedraIntoPrisms(self, elems, startHexPoint, facetNormal,
4563                                  method=smeshBuilder.Hex_2Prisms, allDomains=False ):
4564         """
4565         Split hexahedra into prisms
4566
4567         Parameters:
4568                 elems: either a list of elements or a :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
4569                 startHexPoint: a point used to find a hexahedron for which *facetNormal*
4570                         gives a normal vector defining facets to split into triangles.
4571                         *startHexPoint* can be either a triple of coordinates or a vertex.
4572                 facetNormal: a normal to a facet to split into triangles of a
4573                         hexahedron found by *startHexPoint*.
4574                         *facetNormal* can be either a triple of coordinates or an edge.
4575                 method:  flags passing splitting method: smesh.Hex_2Prisms, smesh.Hex_4Prisms.
4576                         smesh.Hex_2Prisms - to split the hexahedron into 2 prisms, etc.
4577                 allDomains: if :code:`False`, only hexahedra adjacent to one closest
4578                         to *startHexPoint* are split, else *startHexPoint*
4579                         is used to find the facet to split in all domains present in *elems*.
4580         """
4581         # IDSource
4582         unRegister = genObjUnRegister()
4583         if isinstance( elems, Mesh ):
4584             elems = elems.GetMesh()
4585         if ( isinstance( elems, list )):
4586             elems = self.editor.MakeIDSource(elems, SMESH.VOLUME)
4587             unRegister.set( elems )
4588             pass
4589         # axis
4590         if isinstance( startHexPoint, geomBuilder.GEOM._objref_GEOM_Object):
4591             startHexPoint = self.smeshpyD.GetPointStruct( startHexPoint )
4592         elif isinstance( startHexPoint, list ):
4593             startHexPoint = SMESH.PointStruct( startHexPoint[0],
4594                                                startHexPoint[1],
4595                                                startHexPoint[2])
4596         if isinstance( facetNormal, geomBuilder.GEOM._objref_GEOM_Object):
4597             facetNormal = self.smeshpyD.GetDirStruct( facetNormal )
4598         elif isinstance( facetNormal, list ):
4599             facetNormal = self.smeshpyD.MakeDirStruct( facetNormal[0],
4600                                                        facetNormal[1],
4601                                                        facetNormal[2])
4602         self.mesh.SetParameters( startHexPoint.parameters + facetNormal.PS.parameters )
4603
4604         self.editor.SplitHexahedraIntoPrisms(elems, startHexPoint, facetNormal, method, allDomains)
4605
4606     def SplitQuadsNearTriangularFacets(self):
4607         """
4608         Split quadrangle faces near triangular facets of volumes
4609         """
4610         faces_array = self.GetElementsByType(SMESH.FACE)
4611         for face_id in faces_array:
4612             if self.GetElemNbNodes(face_id) == 4: # quadrangle
4613                 quad_nodes = self.mesh.GetElemNodes(face_id)
4614                 node1_elems = self.GetNodeInverseElements(quad_nodes[1 -1])
4615                 isVolumeFound = False
4616                 for node1_elem in node1_elems:
4617                     if not isVolumeFound:
4618                         if self.GetElementType(node1_elem, True) == SMESH.VOLUME:
4619                             nb_nodes = self.GetElemNbNodes(node1_elem)
4620                             if 3 < nb_nodes and nb_nodes < 7: # tetra or penta, or prism
4621                                 volume_elem = node1_elem
4622                                 volume_nodes = self.mesh.GetElemNodes(volume_elem)
4623                                 if volume_nodes.count(quad_nodes[2 -1]) > 0: # 1,2
4624                                     if volume_nodes.count(quad_nodes[4 -1]) > 0: # 1,2,4
4625                                         isVolumeFound = True
4626                                         if volume_nodes.count(quad_nodes[3 -1]) == 0: # 1,2,4 & !3
4627                                             self.SplitQuad([face_id], False) # diagonal 2-4
4628                                     elif volume_nodes.count(quad_nodes[3 -1]) > 0: # 1,2,3 & !4
4629                                         isVolumeFound = True
4630                                         self.SplitQuad([face_id], True) # diagonal 1-3
4631                                 elif volume_nodes.count(quad_nodes[4 -1]) > 0: # 1,4 & !2
4632                                     if volume_nodes.count(quad_nodes[3 -1]) > 0: # 1,4,3 & !2
4633                                         isVolumeFound = True
4634                                         self.SplitQuad([face_id], True) # diagonal 1-3
4635
4636     def SplitHexaToTetras (self, theObject, theNode000, theNode001):
4637         """
4638         Split hexahedrons into tetrahedrons.
4639
4640         This operation uses :doc:`pattern_mapping` functionality for splitting.
4641
4642         Parameters:
4643                 theObject: the object from which the list of hexahedrons is taken; 
4644                         this is :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
4645                 theNode000,theNode001: within the range [0,7]; gives the orientation of the
4646                         pattern relatively each hexahedron: the (0,0,0) key-point of the pattern
4647                         will be mapped into *theNode000*-th node of each volume, the (0,0,1)
4648                         key-point will be mapped into *theNode001*-th node of each volume.
4649                         The (0,0,0) key-point of the used pattern corresponds to a non-split corner.
4650
4651         Returns:
4652             True in case of success, False otherwise.
4653         """
4654 #    Pattern:
4655 #                     5.---------.6
4656 #                    /|#*      /|
4657 #                   / | #*    / |
4658 #                  /  |  # * /  |
4659 #                 /   |   # /*  |
4660 #       (0,0,1) 4.---------.7 * |
4661 #                |#*  |1   | # *|
4662 #                | # *.----|---#.2
4663 #                |  #/ *   |   /
4664 #                |  /#  *  |  /
4665 #                | /   # * | /
4666 #                |/      #*|/
4667 #        (0,0,0) 0.---------.3
4668         pattern_tetra = "!!! Nb of points: \n 8 \n\
4669         !!! Points: \n\
4670         0 0 0  !- 0 \n\
4671         0 1 0  !- 1 \n\
4672         1 1 0  !- 2 \n\
4673         1 0 0  !- 3 \n\
4674         0 0 1  !- 4 \n\
4675         0 1 1  !- 5 \n\
4676         1 1 1  !- 6 \n\
4677         1 0 1  !- 7 \n\
4678         !!! Indices of points of 6 tetras: \n\
4679         0 3 4 1 \n\
4680         7 4 3 1 \n\
4681         4 7 5 1 \n\
4682         6 2 5 7 \n\
4683         1 5 2 7 \n\
4684         2 3 1 7 \n"
4685
4686         pattern = self.smeshpyD.GetPattern()
4687         isDone  = pattern.LoadFromFile(pattern_tetra)
4688         if not isDone:
4689             print('Pattern.LoadFromFile :', pattern.GetErrorCode())
4690             return isDone
4691
4692         pattern.ApplyToHexahedrons(self.mesh, theObject.GetIDs(), theNode000, theNode001)
4693         isDone = pattern.MakeMesh(self.mesh, False, False)
4694         if not isDone: print('Pattern.MakeMesh :', pattern.GetErrorCode())
4695
4696         # split quafrangle faces near triangular facets of volumes
4697         self.SplitQuadsNearTriangularFacets()
4698
4699         return isDone
4700
4701     def SplitHexaToPrisms (self, theObject, theNode000, theNode001):
4702         """
4703         Split hexahedrons into prisms.
4704
4705         Uses the :doc:`pattern_mapping` functionality for splitting.
4706
4707         Parameters:
4708                 theObject: the object (:class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`) from where the list of hexahedrons is taken;
4709                 theNode000,theNode001: (within the range [0,7]) gives the orientation of the
4710                         pattern relatively each hexahedron: keypoint (0,0,0) of the pattern
4711                         will be mapped into the *theNode000* -th node of each volume, keypoint (0,0,1)
4712                         will be mapped into the *theNode001* -th node of each volume.
4713                         Edge (0,0,0)-(0,0,1) of used pattern connects two not split corners.
4714
4715         Returns:
4716             True in case of success, False otherwise.
4717         """
4718 #        Pattern:     5.---------.6
4719 #                     /|#       /|
4720 #                    / | #     / |
4721 #                   /  |  #   /  |
4722 #                  /   |   # /   |
4723 #        (0,0,1) 4.---------.7   |
4724 #                 |    |    |    |
4725 #                 |   1.----|----.2
4726 #                 |   / *   |   /
4727 #                 |  /   *  |  /
4728 #                 | /     * | /
4729 #                 |/       *|/
4730 #        (0,0,0) 0.---------.3
4731         pattern_prism = "!!! Nb of points: \n 8 \n\
4732         !!! Points: \n\
4733         0 0 0  !- 0 \n\
4734         0 1 0  !- 1 \n\
4735         1 1 0  !- 2 \n\
4736         1 0 0  !- 3 \n\
4737         0 0 1  !- 4 \n\
4738         0 1 1  !- 5 \n\
4739         1 1 1  !- 6 \n\
4740         1 0 1  !- 7 \n\
4741         !!! Indices of points of 2 prisms: \n\
4742         0 1 3 4 5 7 \n\
4743         2 3 1 6 7 5 \n"
4744
4745         pattern = self.smeshpyD.GetPattern()
4746         isDone  = pattern.LoadFromFile(pattern_prism)
4747         if not isDone:
4748             print('Pattern.LoadFromFile :', pattern.GetErrorCode())
4749             return isDone
4750
4751         pattern.ApplyToHexahedrons(self.mesh, theObject.GetIDs(), theNode000, theNode001)
4752         isDone = pattern.MakeMesh(self.mesh, False, False)
4753         if not isDone: print('Pattern.MakeMesh :', pattern.GetErrorCode())
4754
4755         # Split quafrangle faces near triangular facets of volumes
4756         self.SplitQuadsNearTriangularFacets()
4757
4758         return isDone
4759
4760     def Smooth(self, IDsOfElements, IDsOfFixedNodes,
4761                MaxNbOfIterations, MaxAspectRatio, Method):
4762         """
4763         Smooth elements
4764
4765         Parameters:
4766                 IDsOfElements: the list if ids of elements to smooth
4767                 IDsOfFixedNodes: the list of ids of fixed nodes.
4768                         Note that nodes built on edges and boundary nodes are always fixed.
4769                 MaxNbOfIterations: the maximum number of iterations
4770                 MaxAspectRatio: varies in range [1.0, inf]
4771                 Method: is either Laplacian (smesh.LAPLACIAN_SMOOTH)
4772                         or Centroidal (smesh.CENTROIDAL_SMOOTH)
4773
4774         Returns:
4775             True in case of success, False otherwise.
4776         """
4777
4778         if IDsOfElements == []:
4779             IDsOfElements = self.GetElementsId()
4780         MaxNbOfIterations,MaxAspectRatio,Parameters,hasVars = ParseParameters(MaxNbOfIterations,MaxAspectRatio)
4781         self.mesh.SetParameters(Parameters)
4782         return self.editor.Smooth(IDsOfElements, IDsOfFixedNodes,
4783                                   MaxNbOfIterations, MaxAspectRatio, Method)
4784
4785     def SmoothObject(self, theObject, IDsOfFixedNodes,
4786                      MaxNbOfIterations, MaxAspectRatio, Method):
4787         """
4788         Smooth elements which belong to the given object
4789
4790         Parameters:
4791                 theObject: the object to smooth
4792                 IDsOfFixedNodes: the list of ids of fixed nodes.
4793                         Note that nodes built on edges and boundary nodes are always fixed.
4794                 MaxNbOfIterations: the maximum number of iterations
4795                 MaxAspectRatio: varies in range [1.0, inf]
4796                 Method: is either Laplacian (smesh.LAPLACIAN_SMOOTH)
4797                         or Centroidal (smesh.CENTROIDAL_SMOOTH)
4798
4799         Returns:
4800             True in case of success, False otherwise.
4801         """
4802
4803         if ( isinstance( theObject, Mesh )):
4804             theObject = theObject.GetMesh()
4805         return self.editor.SmoothObject(theObject, IDsOfFixedNodes,
4806                                         MaxNbOfIterations, MaxAspectRatio, Method)
4807
4808     def SmoothParametric(self, IDsOfElements, IDsOfFixedNodes,
4809                          MaxNbOfIterations, MaxAspectRatio, Method):
4810         """
4811         Parametrically smooth the given elements
4812
4813         Parameters:
4814                 IDsOfElements: the list if ids of elements to smooth
4815                 IDsOfFixedNodes: the list of ids of fixed nodes.
4816                         Note that nodes built on edges and boundary nodes are always fixed.
4817                 MaxNbOfIterations: the maximum number of iterations
4818                 MaxAspectRatio: varies in range [1.0, inf]
4819                 Method: is either Laplacian (smesh.LAPLACIAN_SMOOTH)
4820                         or Centroidal (smesh.CENTROIDAL_SMOOTH)
4821
4822         Returns:
4823             True in case of success, False otherwise.
4824         """
4825
4826         if IDsOfElements == []:
4827             IDsOfElements = self.GetElementsId()
4828         MaxNbOfIterations,MaxAspectRatio,Parameters,hasVars = ParseParameters(MaxNbOfIterations,MaxAspectRatio)
4829         self.mesh.SetParameters(Parameters)
4830         return self.editor.SmoothParametric(IDsOfElements, IDsOfFixedNodes,
4831                                             MaxNbOfIterations, MaxAspectRatio, Method)
4832
4833     def SmoothParametricObject(self, theObject, IDsOfFixedNodes,
4834                                MaxNbOfIterations, MaxAspectRatio, Method):
4835         """
4836         Parametrically smooth the elements which belong to the given object
4837
4838         Parameters:
4839                 theObject: the object to smooth
4840                 IDsOfFixedNodes: the list of ids of fixed nodes.
4841                         Note that nodes built on edges and boundary nodes are always fixed.
4842                 MaxNbOfIterations: the maximum number of iterations
4843                 MaxAspectRatio: varies in range [1.0, inf]
4844                 Method: is either Laplacian (smesh.LAPLACIAN_SMOOTH)
4845                         or Centroidal (smesh.CENTROIDAL_SMOOTH)
4846
4847         Returns:
4848             True in case of success, False otherwise.
4849         """
4850
4851         if ( isinstance( theObject, Mesh )):
4852             theObject = theObject.GetMesh()
4853         return self.editor.SmoothParametricObject(theObject, IDsOfFixedNodes,
4854                                                   MaxNbOfIterations, MaxAspectRatio, Method)
4855
4856     def ConvertToQuadratic(self, theForce3d=False, theSubMesh=None, theToBiQuad=False):
4857         """
4858         Convert the mesh to quadratic or bi-quadratic, deletes old elements, replacing
4859         them with quadratic with the same id.
4860
4861         Parameters:
4862                 theForce3d: method of new node creation:
4863
4864                   * False - the medium node lies at the geometrical entity from which the mesh element is built
4865                   * True - the medium node lies at the middle of the line segments connecting two nodes of a mesh element
4866                 theSubMesh: a :class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>` to convert
4867                 theToBiQuad: If True, converts the mesh to bi-quadratic
4868
4869         Returns:
4870             :class:`SMESH.ComputeError` which can hold a warning
4871
4872         Warning:
4873             If *theSubMesh* is provided, the mesh can become non-conformal
4874         """
4875
4876         if isinstance( theSubMesh, Mesh ):
4877             theSubMesh = theSubMesh.mesh
4878         if theToBiQuad:
4879             self.editor.ConvertToBiQuadratic(theForce3d,theSubMesh)
4880         else:
4881             if theSubMesh:
4882                 self.editor.ConvertToQuadraticObject(theForce3d,theSubMesh)
4883             else:
4884                 self.editor.ConvertToQuadratic(theForce3d)
4885         error = self.editor.GetLastError()
4886         if error and error.comment:
4887             print(error.comment)
4888         return error
4889
4890     def ConvertFromQuadratic(self, theSubMesh=None):
4891         """
4892         Convert the mesh from quadratic to ordinary,
4893         deletes old quadratic elements,
4894         replacing them with ordinary mesh elements with the same id.
4895
4896         Parameters:
4897             theSubMesh: a :class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>` to convert
4898
4899         Warning:
4900             If *theSubMesh* is provided, the mesh can become non-conformal
4901         """
4902
4903         if theSubMesh:
4904             self.editor.ConvertFromQuadraticObject(theSubMesh)
4905         else:
4906             return self.editor.ConvertFromQuadratic()
4907
4908     def Make2DMeshFrom3D(self):
4909         """
4910         Create 2D mesh as skin on boundary faces of a 3D mesh
4911
4912         Returns:
4913             True if operation has been completed successfully, False otherwise
4914         """
4915
4916         return self.editor.Make2DMeshFrom3D()
4917
4918     def MakeBoundaryMesh(self, elements, dimension=SMESH.BND_2DFROM3D, groupName="", meshName="",
4919                          toCopyElements=False, toCopyExistingBondary=False):
4920         """
4921         Create missing boundary elements
4922
4923         Parameters:
4924                 elements: elements whose boundary is to be checked:
4925                         :class:`mesh, sub-mesh, group, filter <SMESH.SMESH_IDSource>` or list of elements.
4926                         If *elements* is mesh, it must be the mesh whose MakeBoundaryMesh() is called
4927                 dimension: defines type of boundary elements to create, either of
4928                         { SMESH.BND_2DFROM3D, SMESH.BND_1DFROM3D, SMESH.BND_1DFROM2D }.
4929                         SMESH.BND_1DFROM3D create mesh edges on all borders of free facets of 3D cells
4930                 groupName: a name of group to store created boundary elements in,
4931                         "" means not to create the group
4932                 meshName: a name of new mesh to store created boundary elements in,
4933                         "" means not to create the new mesh
4934                 toCopyElements: if True, the checked elements will be copied into
4935                         the new mesh else only boundary elements will be copied into the new mesh
4936                 toCopyExistingBondary: if True, not only new but also pre-existing
4937                         boundary elements will be copied into the new mesh
4938
4939         Returns:
4940             tuple (:class:`Mesh`, :class:`group <SMESH.SMESH_Group>`) where boundary elements were added to
4941         """
4942
4943         unRegister = genObjUnRegister()
4944         if isinstance( elements, Mesh ):
4945             elements = elements.GetMesh()
4946         if ( isinstance( elements, list )):
4947             elemType = SMESH.ALL
4948             if elements: elemType = self.GetElementType( elements[0], iselem=True)
4949             elements = self.editor.MakeIDSource(elements, elemType)
4950             unRegister.set( elements )
4951         mesh, group = self.editor.MakeBoundaryMesh(elements,dimension,groupName,meshName,
4952                                                    toCopyElements,toCopyExistingBondary)
4953         if mesh: mesh = self.smeshpyD.Mesh(mesh)
4954         return mesh, group
4955
4956     def MakeBoundaryElements(self, dimension=SMESH.BND_2DFROM3D, groupName="", meshName="",
4957                              toCopyAll=False, groups=[]):
4958         """
4959         Create missing boundary elements around either the whole mesh or
4960         groups of elements
4961
4962         Parameters:
4963                 dimension: defines type of boundary elements to create, either of
4964                         { SMESH.BND_2DFROM3D, SMESH.BND_1DFROM3D, SMESH.BND_1DFROM2D }
4965                 groupName: a name of group to store all boundary elements in,
4966                         "" means not to create the group
4967                 meshName: a name of a new mesh, which is a copy of the initial
4968                         mesh + created boundary elements; "" means not to create the new mesh
4969                 toCopyAll: if True, the whole initial mesh will be copied into
4970                         the new mesh else only boundary elements will be copied into the new mesh
4971                 groups: list of :class:`sub-meshes, groups or filters <SMESH.SMESH_IDSource>` of elements to make boundary around
4972
4973         Returns:
4974                 tuple( long, mesh, groups )
4975                        - long - number of added boundary elements
4976                        - mesh - the :class:`Mesh` where elements were added to
4977                        - group - the :class:`group <SMESH.SMESH_Group>` of boundary elements or None
4978         """
4979
4980         nb, mesh, group = self.editor.MakeBoundaryElements(dimension,groupName,meshName,
4981                                                            toCopyAll,groups)
4982         if mesh: mesh = self.smeshpyD.Mesh(mesh)
4983         return nb, mesh, group
4984
4985     def RenumberNodes(self):
4986         """
4987         Renumber mesh nodes to remove unused node IDs
4988         """
4989         self.editor.RenumberNodes()
4990
4991     def RenumberElements(self):
4992         """
4993         Renumber mesh elements to remove unused element IDs
4994         """
4995         self.editor.RenumberElements()
4996
4997     def _getIdSourceList(self, arg, idType, unRegister):
4998         """
4999         Private method converting *arg* into a list of :class:`SMESH.SMESH_IDSource`
5000         """
5001         if arg and isinstance( arg, list ):
5002             if isinstance( arg[0], int ):
5003                 arg = self.GetIDSource( arg, idType )
5004                 unRegister.set( arg )
5005             elif isinstance( arg[0], Mesh ):
5006                 arg[0] = arg[0].GetMesh()
5007         elif isinstance( arg, Mesh ):
5008             arg = arg.GetMesh()
5009         if arg and isinstance( arg, SMESH._objref_SMESH_IDSource ):
5010             arg = [arg]
5011         return arg
5012
5013     def RotationSweepObjects(self, nodes, edges, faces, Axis, AngleInRadians, NbOfSteps, Tolerance,
5014                              MakeGroups=False, TotalAngle=False):
5015         """
5016         Generate new elements by rotation of the given elements and nodes around the axis
5017
5018         Parameters:
5019                 nodes: nodes to revolve: a list including ids, :class:`a mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>`
5020                 edges: edges to revolve: a list including ids, :class:`a mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>`
5021                 faces: faces to revolve: a list including ids, :class:`a mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>`
5022                 Axis: the axis of rotation: :class:`SMESH.AxisStruct`, line (geom object) or [x,y,z,dx,dy,dz]
5023                 AngleInRadians: the angle of Rotation (in radians) or a name of variable
5024                         which defines angle in degrees
5025                 NbOfSteps: the number of steps
5026                 Tolerance: tolerance
5027                 MakeGroups: forces the generation of new groups from existing ones
5028                 TotalAngle: gives meaning of AngleInRadians: if True then it is an angular size
5029                         of all steps, else - size of each step
5030
5031         Returns:
5032             the list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
5033         """
5034
5035         unRegister = genObjUnRegister()
5036         nodes = self._getIdSourceList( nodes, SMESH.NODE, unRegister )
5037         edges = self._getIdSourceList( edges, SMESH.EDGE, unRegister )
5038         faces = self._getIdSourceList( faces, SMESH.FACE, unRegister )
5039
5040         if isinstance( Axis, geomBuilder.GEOM._objref_GEOM_Object):
5041             Axis = self.smeshpyD.GetAxisStruct( Axis )
5042         if isinstance( Axis, list ):
5043             Axis = SMESH.AxisStruct( *Axis )
5044
5045         AngleInRadians,AngleParameters,hasVars = ParseAngles(AngleInRadians)
5046         NbOfSteps,Tolerance,Parameters,hasVars = ParseParameters(NbOfSteps,Tolerance)
5047         Parameters = Axis.parameters + var_separator + AngleParameters + var_separator + Parameters
5048         self.mesh.SetParameters(Parameters)
5049         if TotalAngle and NbOfSteps:
5050             AngleInRadians /= NbOfSteps
5051         return self.editor.RotationSweepObjects( nodes, edges, faces,
5052                                                  Axis, AngleInRadians,
5053                                                  NbOfSteps, Tolerance, MakeGroups)
5054
5055     def RotationSweep(self, IDsOfElements, Axis, AngleInRadians, NbOfSteps, Tolerance,
5056                       MakeGroups=False, TotalAngle=False):
5057         """
5058         Generate new elements by rotation of the elements around the axis
5059
5060         Parameters:
5061             IDsOfElements: the list of ids of elements to sweep
5062             Axis: the axis of rotation, :class:`SMESH.AxisStruct` or line(geom object)
5063             AngleInRadians: the angle of Rotation (in radians) or a name of variable which defines angle in degrees
5064             NbOfSteps: the number of steps
5065             Tolerance: tolerance
5066             MakeGroups: forces the generation of new groups from existing ones
5067             TotalAngle: gives meaning of AngleInRadians: if True then it is an angular size
5068                 of all steps, else - size of each step
5069
5070         Returns:
5071             the list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
5072         """
5073
5074         return self.RotationSweepObjects([], IDsOfElements, IDsOfElements, Axis,
5075                                          AngleInRadians, NbOfSteps, Tolerance,
5076                                          MakeGroups, TotalAngle)
5077
5078     def RotationSweepObject(self, theObject, Axis, AngleInRadians, NbOfSteps, Tolerance,
5079                             MakeGroups=False, TotalAngle=False):
5080         """
5081         Generate new elements by rotation of the elements of object around the axis
5082         theObject object which elements should be sweeped.
5083         It can be a mesh, a sub mesh or a group.
5084
5085         Parameters:
5086             Axis: the axis of rotation, :class:`SMESH.AxisStruct` or line(geom object)
5087             AngleInRadians: the angle of Rotation
5088             NbOfSteps: number of steps
5089             Tolerance: tolerance
5090             MakeGroups: forces the generation of new groups from existing ones
5091             TotalAngle: gives meaning of AngleInRadians: if True then it is an angular size
5092                 of all steps, else - size of each step
5093
5094         Returns:
5095             the list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
5096         """
5097
5098         return self.RotationSweepObjects( [], theObject, theObject, Axis,
5099                                           AngleInRadians, NbOfSteps, Tolerance,
5100                                           MakeGroups, TotalAngle )
5101
5102     def RotationSweepObject1D(self, theObject, Axis, AngleInRadians, NbOfSteps, Tolerance,
5103                               MakeGroups=False, TotalAngle=False):
5104         """
5105         Generate new elements by rotation of the elements of object around the axis
5106         theObject object which elements should be sweeped.
5107         It can be a mesh, a sub mesh or a group.
5108
5109         Parameters:
5110             Axis: the axis of rotation, :class:`SMESH.AxisStruct` or line(geom object)
5111             AngleInRadians: the angle of Rotation
5112             NbOfSteps: number of steps
5113             Tolerance: tolerance
5114             MakeGroups: forces the generation of new groups from existing ones
5115             TotalAngle: gives meaning of AngleInRadians: if True then it is an angular size
5116                 of all steps, else - size of each step
5117
5118         Returns:
5119             the list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, 
5120             empty list otherwise
5121         """
5122
5123         return self.RotationSweepObjects([],theObject,[], Axis,
5124                                          AngleInRadians, NbOfSteps, Tolerance,
5125                                          MakeGroups, TotalAngle)
5126
5127     def RotationSweepObject2D(self, theObject, Axis, AngleInRadians, NbOfSteps, Tolerance,
5128                               MakeGroups=False, TotalAngle=False):
5129         """
5130         Generate new elements by rotation of the elements of object around the axis
5131         theObject object which elements should be sweeped.
5132         It can be a mesh, a sub mesh or a group.
5133
5134         Parameters:
5135             Axis: the axis of rotation, :class:`SMESH.AxisStruct` or line(geom object)
5136             AngleInRadians: the angle of Rotation
5137             NbOfSteps: number of steps
5138             Tolerance: tolerance
5139             MakeGroups: forces the generation of new groups from existing ones
5140             TotalAngle: gives meaning of AngleInRadians: if True then it is an angular size
5141                 of all steps, else - size of each step
5142
5143         Returns:
5144             the list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
5145         """
5146
5147         return self.RotationSweepObjects([],[],theObject, Axis, AngleInRadians,
5148                                          NbOfSteps, Tolerance, MakeGroups, TotalAngle)
5149
5150     def ExtrusionSweepObjects(self, nodes, edges, faces, StepVector, NbOfSteps, MakeGroups=False,
5151                               scaleFactors=[], linearVariation=False, basePoint=[] ):
5152         """
5153         Generate new elements by extrusion of the given elements and nodes
5154
5155         Parameters:
5156             nodes: nodes to extrude: a list including ids, :class:`a mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>`
5157             edges: edges to extrude: a list including ids, :class:`a mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>`
5158             faces: faces to extrude: a list including ids, :class:`a mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>`
5159             StepVector: vector or :class:`SMESH.DirStruct` or 3 vector components, defining
5160                 the direction and value of extrusion for one step (the total extrusion
5161                 length will be NbOfSteps * ||StepVector||)
5162             NbOfSteps: the number of steps
5163             MakeGroups: forces the generation of new groups from existing ones
5164             scaleFactors: optional scale factors to apply during extrusion
5165             linearVariation: if *True*, scaleFactors are spread over all *scaleFactors*,
5166                 else scaleFactors[i] is applied to nodes at the i-th extrusion step
5167             basePoint: optional scaling center; if not provided, a gravity center of
5168                 nodes and elements being extruded is used as the scaling center.
5169                 It can be either
5170
5171                         - a list of tree components of the point or
5172                         - a node ID or
5173                         - a GEOM point
5174         Returns:
5175             the list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
5176
5177         Example: :ref:`tui_extrusion`
5178         """
5179         unRegister = genObjUnRegister()
5180         nodes = self._getIdSourceList( nodes, SMESH.NODE, unRegister )
5181         edges = self._getIdSourceList( edges, SMESH.EDGE, unRegister )
5182         faces = self._getIdSourceList( faces, SMESH.FACE, unRegister )
5183
5184         if isinstance( StepVector, geomBuilder.GEOM._objref_GEOM_Object):
5185             StepVector = self.smeshpyD.GetDirStruct(StepVector)
5186         if isinstance( StepVector, list ):
5187             StepVector = self.smeshpyD.MakeDirStruct(*StepVector)
5188
5189         if isinstance( basePoint, int):
5190             xyz = self.GetNodeXYZ( basePoint )
5191             if not xyz:
5192                 raise RuntimeError("Invalid node ID: %s" % basePoint)
5193             basePoint = xyz
5194         if isinstance( basePoint, geomBuilder.GEOM._objref_GEOM_Object ):
5195             basePoint = self.geompyD.PointCoordinates( basePoint )
5196
5197         NbOfSteps,Parameters,hasVars = ParseParameters(NbOfSteps)
5198         Parameters = StepVector.PS.parameters + var_separator + Parameters
5199         self.mesh.SetParameters(Parameters)
5200
5201         return self.editor.ExtrusionSweepObjects( nodes, edges, faces,
5202                                                   StepVector, NbOfSteps,
5203                                                   scaleFactors, linearVariation, basePoint,
5204                                                   MakeGroups)
5205
5206
5207     def ExtrusionSweep(self, IDsOfElements, StepVector, NbOfSteps, MakeGroups=False, IsNodes = False):
5208         """
5209         Generate new elements by extrusion of the elements with given ids
5210
5211         Parameters:
5212             IDsOfElements: the list of ids of elements or nodes for extrusion
5213             StepVector: vector or :class:`SMESH.DirStruct` or 3 vector components, defining
5214                 the direction and value of extrusion for one step (the total extrusion
5215                 length will be NbOfSteps * ||StepVector||)
5216             NbOfSteps: the number of steps
5217             MakeGroups: forces the generation of new groups from existing ones
5218             IsNodes: is True if elements with given ids are nodes
5219
5220         Returns:
5221             the list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
5222
5223         Example: :ref:`tui_extrusion`
5224         """
5225         n,e,f = [],[],[]
5226         if IsNodes: n = IDsOfElements
5227         else      : e,f, = IDsOfElements,IDsOfElements
5228         return self.ExtrusionSweepObjects(n,e,f, StepVector, NbOfSteps, MakeGroups)
5229
5230     def ExtrusionByNormal(self, Elements, StepSize, NbOfSteps,
5231                           ByAverageNormal=False, UseInputElemsOnly=True, MakeGroups=False, Dim = 2):
5232         """
5233         Generate new elements by extrusion along the normal to a discretized surface or wire
5234
5235         Parameters:
5236             Elements: elements to extrude - a list including ids, :class:`a mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>`.
5237                 Only faces can be extruded so far. A sub-mesh should be a sub-mesh on geom faces.
5238             StepSize: length of one extrusion step (the total extrusion
5239                 length will be *NbOfSteps* *StepSize*).
5240             NbOfSteps: number of extrusion steps.
5241             ByAverageNormal: if True each node is translated by *StepSize*
5242                 along the average of the normal vectors to the faces sharing the node;
5243                 else each node is translated along the same average normal till
5244                 intersection with the plane got by translation of the face sharing
5245                 the node along its own normal by *StepSize*.
5246             UseInputElemsOnly: to use only *Elements* when computing extrusion direction
5247                 for every node of *Elements*.
5248             MakeGroups: forces generation of new groups from existing ones.
5249             Dim: dimension of elements to extrude: 2 - faces or 1 - edges. Extrusion of edges
5250                 is not yet implemented. This parameter is used if *Elements* contains
5251                 both faces and edges, i.e. *Elements* is a Mesh.
5252
5253         Returns:
5254             the list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True,
5255             empty list otherwise.
5256         Example: :ref:`tui_extrusion`
5257         """
5258
5259         unRegister = genObjUnRegister()
5260         if isinstance( Elements, Mesh ):
5261             Elements = [ Elements.GetMesh() ]
5262         if isinstance( Elements, list ):
5263             if not Elements:
5264                 raise RuntimeError("Elements empty!")
5265             if isinstance( Elements[0], int ):
5266                 Elements = self.GetIDSource( Elements, SMESH.ALL )
5267                 unRegister.set( Elements )
5268         if not isinstance( Elements, list ):
5269             Elements = [ Elements ]
5270         StepSize,NbOfSteps,Parameters,hasVars = ParseParameters(StepSize,NbOfSteps)
5271         self.mesh.SetParameters(Parameters)
5272         return self.editor.ExtrusionByNormal(Elements, StepSize, NbOfSteps,
5273                                              ByAverageNormal, UseInputElemsOnly, MakeGroups, Dim)
5274
5275     def ExtrusionSweepObject(self, theObject, StepVector, NbOfSteps, MakeGroups=False, IsNodes=False):
5276         """
5277         Generate new elements by extrusion of the elements or nodes which belong to the object
5278
5279         Parameters:
5280             theObject: the object whose elements or nodes should be processed.
5281                 It can be a :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`.
5282             StepVector: vector or :class:`SMESH.DirStruct` or 3 vector components, defining
5283                 the direction and value of extrusion for one step (the total extrusion
5284                 length will be NbOfSteps * ||StepVector||)
5285             NbOfSteps: the number of steps
5286             MakeGroups: forces the generation of new groups from existing ones
5287             IsNodes: is True if elements to extrude are nodes
5288
5289         Returns:
5290             list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
5291         Example: :ref:`tui_extrusion`
5292         """
5293
5294         n,e,f = [],[],[]
5295         if IsNodes: n    = theObject
5296         else      : e,f, = theObject,theObject
5297         return self.ExtrusionSweepObjects(n,e,f, StepVector, NbOfSteps, MakeGroups)
5298
5299     def ExtrusionSweepObject1D(self, theObject, StepVector, NbOfSteps, MakeGroups=False):
5300         """
5301         Generate new elements by extrusion of edges which belong to the object
5302
5303         Parameters:
5304             theObject: object whose 1D elements should be processed.
5305                 It can be a :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`.
5306             StepVector: vector or :class:`SMESH.DirStruct` or 3 vector components, defining
5307                 the direction and value of extrusion for one step (the total extrusion
5308                 length will be NbOfSteps * ||StepVector||)
5309             NbOfSteps: the number of steps
5310             MakeGroups: to generate new groups from existing ones
5311
5312         Returns:
5313             list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
5314         Example: :ref:`tui_extrusion`
5315         """
5316
5317         return self.ExtrusionSweepObjects([],theObject,[], StepVector, NbOfSteps, MakeGroups)
5318
5319     def ExtrusionSweepObject2D(self, theObject, StepVector, NbOfSteps, MakeGroups=False):
5320         """
5321         Generate new elements by extrusion of faces which belong to the object
5322
5323         Parameters:
5324             theObject: object whose 2D elements should be processed.
5325                 It can be a :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`.
5326             StepVector: vector or :class:`SMESH.DirStruct` or 3 vector components, defining
5327                 the direction and value of extrusion for one step (the total extrusion
5328                 length will be NbOfSteps * ||StepVector||)
5329             NbOfSteps: the number of steps
5330             MakeGroups: forces the generation of new groups from existing ones
5331
5332         Returns:
5333             list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
5334         Example: :ref:`tui_extrusion`
5335         """
5336
5337         return self.ExtrusionSweepObjects([],[],theObject, StepVector, NbOfSteps, MakeGroups)
5338
5339     def AdvancedExtrusion(self, IDsOfElements, StepVector, NbOfSteps,
5340                           ExtrFlags, SewTolerance, MakeGroups=False):
5341         """
5342         Generate new elements by extrusion of the elements with given ids
5343
5344         Parameters:
5345             IDsOfElements: is ids of elements
5346             StepVector: vector or :class:`SMESH.DirStruct` or 3 vector components, defining
5347                 the direction and value of extrusion for one step (the total extrusion
5348                 length will be NbOfSteps * ||StepVector||)
5349             NbOfSteps: the number of steps
5350             ExtrFlags: sets flags for extrusion
5351             SewTolerance: uses for comparing locations of nodes if flag
5352                 EXTRUSION_FLAG_SEW is set
5353             MakeGroups: forces the generation of new groups from existing ones
5354
5355         Returns:
5356             list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
5357         """
5358
5359         if isinstance( StepVector, geomBuilder.GEOM._objref_GEOM_Object):
5360             StepVector = self.smeshpyD.GetDirStruct(StepVector)
5361         if isinstance( StepVector, list ):
5362             StepVector = self.smeshpyD.MakeDirStruct(*StepVector)
5363         return self.editor.AdvancedExtrusion(IDsOfElements, StepVector, NbOfSteps,
5364                                              ExtrFlags, SewTolerance, MakeGroups)
5365
5366     def ExtrusionAlongPathObjects(self, Nodes, Edges, Faces, PathMesh, PathShape=None,
5367                                   NodeStart=1, HasAngles=False, Angles=[], LinearVariation=False,
5368                                   HasRefPoint=False, RefPoint=[0,0,0], MakeGroups=False):
5369         """
5370         Generate new elements by extrusion of the given elements and nodes along the path.
5371         The path of extrusion must be a meshed edge.
5372
5373         Parameters:
5374             Nodes: nodes to extrude: a list including ids, :class:`a mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>`
5375             Edges: edges to extrude: a list including ids, :class:`a mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>`
5376             Faces: faces to extrude: a list including ids, :class:`a mesh, sub-meshes, groups or filters <SMESH.SMESH_IDSource>`
5377             PathMesh: 1D mesh or 1D sub-mesh, along which proceeds the extrusion
5378             PathShape: shape (edge) defines the sub-mesh of PathMesh if PathMesh
5379                 contains not only path segments, else it can be None
5380             NodeStart: the first or the last node on the path. Defines the direction of extrusion
5381             HasAngles: allows the shape to be rotated around the path
5382                 to get the resulting mesh in a helical fashion
5383             Angles: list of angles
5384             LinearVariation: forces the computation of rotation angles as linear
5385                 variation of the given Angles along path steps
5386             HasRefPoint: allows using the reference point
5387             RefPoint: the reference point around which the shape is rotated (the mass center of the
5388                 shape by default). The User can specify any point as the Reference Point. 
5389                 *RefPoint* can be either GEOM Vertex, [x,y,z] or :class:`SMESH.PointStruct`
5390             MakeGroups: forces the generation of new groups from existing ones
5391
5392         Returns:
5393             list of created :class:`groups <SMESH.SMESH_GroupBase>` and 
5394             :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>`
5395         Example: :ref:`tui_extrusion_along_path`
5396         """
5397
5398         unRegister = genObjUnRegister()
5399         Nodes = self._getIdSourceList( Nodes, SMESH.NODE, unRegister )
5400         Edges = self._getIdSourceList( Edges, SMESH.EDGE, unRegister )
5401         Faces = self._getIdSourceList( Faces, SMESH.FACE, unRegister )
5402
5403         if isinstance( RefPoint, geomBuilder.GEOM._objref_GEOM_Object):
5404             RefPoint = self.smeshpyD.GetPointStruct(RefPoint)
5405         if isinstance( RefPoint, list ):
5406             if not RefPoint: RefPoint = [0,0,0]
5407             RefPoint = SMESH.PointStruct( *RefPoint )
5408         if isinstance( PathMesh, Mesh ):
5409             PathMesh = PathMesh.GetMesh()
5410         Angles,AnglesParameters,hasVars = ParseAngles(Angles)
5411         Parameters = AnglesParameters + var_separator + RefPoint.parameters
5412         self.mesh.SetParameters(Parameters)
5413         return self.editor.ExtrusionAlongPathObjects(Nodes, Edges, Faces,
5414                                                      PathMesh, PathShape, NodeStart,
5415                                                      HasAngles, Angles, LinearVariation,
5416                                                      HasRefPoint, RefPoint, MakeGroups)
5417
5418     def ExtrusionAlongPathX(self, Base, Path, NodeStart,
5419                             HasAngles=False, Angles=[], LinearVariation=False,
5420                             HasRefPoint=False, RefPoint=[0,0,0], MakeGroups=False,
5421                             ElemType=SMESH.FACE):
5422         """
5423         Generate new elements by extrusion of the given elements.
5424         The path of extrusion must be a meshed edge.
5425
5426         Parameters:
5427             Base: :class:`mesh, sub-mesh, group, filter <SMESH.SMESH_IDSource>`, or list of ids of elements for extrusion
5428             Path: 1D mesh or 1D sub-mesh, along which proceeds the extrusion
5429             NodeStart: the start node from Path. Defines the direction of extrusion
5430             HasAngles: allows the shape to be rotated around the path
5431                 to get the resulting mesh in a helical fashion
5432             Angles: list of angles in radians
5433             LinearVariation: forces the computation of rotation angles as linear
5434                 variation of the given Angles along path steps
5435             HasRefPoint: allows using the reference point
5436             RefPoint: the reference point around which the elements are rotated (the mass
5437                 center of the elements by default).
5438                 The User can specify any point as the Reference Point.
5439                 *RefPoint* can be either GEOM Vertex, [x,y,z] or :class:`SMESH.PointStruct`
5440             MakeGroups: forces the generation of new groups from existing ones
5441             ElemType: type of elements for extrusion (if param Base is a mesh)
5442
5443         Returns:
5444             list of created :class:`groups <SMESH.SMESH_GroupBase>` and
5445             :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>`
5446             if *MakeGroups* == True, only :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>`
5447             otherwise
5448         Example: :ref:`tui_extrusion_along_path`
5449         """
5450
5451         n,e,f = [],[],[]
5452         if ElemType == SMESH.NODE: n = Base
5453         if ElemType == SMESH.EDGE: e = Base
5454         if ElemType == SMESH.FACE: f = Base
5455         gr,er = self.ExtrusionAlongPathObjects(n,e,f, Path, None, NodeStart,
5456                                                HasAngles, Angles, LinearVariation,
5457                                                HasRefPoint, RefPoint, MakeGroups)
5458         if MakeGroups: return gr,er
5459         return er
5460
5461     def ExtrusionAlongPath(self, IDsOfElements, PathMesh, PathShape, NodeStart,
5462                            HasAngles=False, Angles=[], HasRefPoint=False, RefPoint=[],
5463                            MakeGroups=False, LinearVariation=False):
5464         """
5465         Generate new elements by extrusion of the given elements.
5466         The path of extrusion must be a meshed edge.
5467
5468         Parameters:
5469             IDsOfElements: ids of elements
5470             PathMesh: mesh containing a 1D sub-mesh on the edge, along which proceeds the extrusion
5471             PathShape: shape (edge) defines the sub-mesh for the path
5472             NodeStart: the first or the last node on the edge. Defines the direction of extrusion
5473             HasAngles: allows the shape to be rotated around the path
5474                 to get the resulting mesh in a helical fashion
5475             Angles: list of angles in radians
5476             HasRefPoint: allows using the reference point
5477             RefPoint: the reference point around which the shape is rotated (the mass center of the shape by default).
5478                 The User can specify any point as the Reference Point.
5479                 *RefPoint* can be either GEOM Vertex, [x,y,z] or :class:`SMESH.PointStruct`
5480             MakeGroups: forces the generation of new groups from existing ones
5481             LinearVariation: forces the computation of rotation angles as linear
5482                 variation of the given Angles along path steps
5483
5484         Returns:
5485             list of created :class:`groups <SMESH.SMESH_GroupBase>` and
5486             :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>`
5487             if *MakeGroups* == True, only :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>` otherwise
5488         Example: :ref:`tui_extrusion_along_path`
5489         """
5490
5491         n,e,f = [],IDsOfElements,IDsOfElements
5492         gr,er = self.ExtrusionAlongPathObjects(n,e,f, PathMesh, PathShape,
5493                                                NodeStart, HasAngles, Angles,
5494                                                LinearVariation,
5495                                                HasRefPoint, RefPoint, MakeGroups)
5496         if MakeGroups: return gr,er
5497         return er
5498
5499     def ExtrusionAlongPathObject(self, theObject, PathMesh, PathShape, NodeStart,
5500                                  HasAngles=False, Angles=[], HasRefPoint=False, RefPoint=[],
5501                                  MakeGroups=False, LinearVariation=False):
5502         """
5503         Generate new elements by extrusion of the elements which belong to the object.
5504         The path of extrusion must be a meshed edge.
5505
5506         Parameters:
5507             theObject: the object whose elements should be processed.
5508                 It can be a :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`.
5509             PathMesh: mesh containing a 1D sub-mesh on the edge, along which the extrusion proceeds
5510             PathShape: shape (edge) defines the sub-mesh for the path
5511             NodeStart: the first or the last node on the edge. Defines the direction of extrusion
5512             HasAngles: allows the shape to be rotated around the path
5513                 to get the resulting mesh in a helical fashion
5514             Angles: list of angles
5515             HasRefPoint: allows using the reference point
5516             RefPoint: the reference point around which the shape is rotated (the mass center of the shape by default).
5517                 The User can specify any point as the Reference Point.
5518                 *RefPoint* can be either GEOM Vertex, [x,y,z] or :class:`SMESH.PointStruct`
5519             MakeGroups: forces the generation of new groups from existing ones
5520             LinearVariation: forces the computation of rotation angles as linear
5521                 variation of the given Angles along path steps
5522
5523         Returns:
5524             list of created :class:`groups <SMESH.SMESH_GroupBase>` and 
5525             :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>` if *MakeGroups* == True,
5526             only :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>` otherwise
5527         Example: :ref:`tui_extrusion_along_path`
5528         """
5529
5530         n,e,f = [],theObject,theObject
5531         gr,er = self.ExtrusionAlongPathObjects(n,e,f, PathMesh, PathShape, NodeStart,
5532                                                HasAngles, Angles, LinearVariation,
5533                                                HasRefPoint, RefPoint, MakeGroups)
5534         if MakeGroups: return gr,er
5535         return er
5536
5537     def ExtrusionAlongPathObject1D(self, theObject, PathMesh, PathShape, NodeStart,
5538                                    HasAngles=False, Angles=[], HasRefPoint=False, RefPoint=[],
5539                                    MakeGroups=False, LinearVariation=False):
5540         """
5541         Generate new elements by extrusion of mesh segments which belong to the object.
5542         The path of extrusion must be a meshed edge.
5543
5544         Parameters:
5545             theObject: the object whose 1D elements should be processed.
5546                 It can be a :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`.
5547             PathMesh: mesh containing a 1D sub-mesh on the edge, along which the extrusion proceeds
5548             PathShape: shape (edge) defines the sub-mesh for the path
5549             NodeStart: the first or the last node on the edge. Defines the direction of extrusion
5550             HasAngles: allows the shape to be rotated around the path
5551                 to get the resulting mesh in a helical fashion
5552             Angles: list of angles
5553             HasRefPoint: allows using the reference point
5554             RefPoint:  the reference point around which the shape is rotated (the mass center of the shape by default).
5555                 The User can specify any point as the Reference Point.
5556                 *RefPoint* can be either GEOM Vertex, [x,y,z] or :class:`SMESH.PointStruct`
5557             MakeGroups: forces the generation of new groups from existing ones
5558             LinearVariation: forces the computation of rotation angles as linear
5559                 variation of the given Angles along path steps
5560
5561         Returns:
5562             list of created :class:`groups <SMESH.SMESH_GroupBase>` and 
5563             :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>` if *MakeGroups* == True,
5564             only :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>` otherwise
5565         Example: :ref:`tui_extrusion_along_path`
5566         """
5567
5568         n,e,f = [],theObject,[]
5569         gr,er = self.ExtrusionAlongPathObjects(n,e,f, PathMesh, PathShape, NodeStart,
5570                                                HasAngles, Angles, LinearVariation,
5571                                                HasRefPoint, RefPoint, MakeGroups)
5572         if MakeGroups: return gr,er
5573         return er
5574
5575     def ExtrusionAlongPathObject2D(self, theObject, PathMesh, PathShape, NodeStart,
5576                                    HasAngles=False, Angles=[], HasRefPoint=False, RefPoint=[],
5577                                    MakeGroups=False, LinearVariation=False):
5578         """
5579         Generate new elements by extrusion of faces which belong to the object.
5580         The path of extrusion must be a meshed edge.
5581
5582         Parameters:
5583             theObject: the object whose 2D elements should be processed.
5584                 It can be a :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`.
5585             PathMesh: mesh containing a 1D sub-mesh on the edge, along which the extrusion proceeds
5586             PathShape: shape (edge) defines the sub-mesh for the path
5587             NodeStart: the first or the last node on the edge. Defines the direction of extrusion
5588             HasAngles: allows the shape to be rotated around the path
5589                 to get the resulting mesh in a helical fashion
5590             Angles: list of angles
5591             HasRefPoint: allows using the reference point
5592             RefPoint: the reference point around which the shape is rotated (the mass center of the shape by default).
5593                 The User can specify any point as the Reference Point.
5594                 *RefPoint* can be either GEOM Vertex, [x,y,z] or :class:`SMESH.PointStruct`
5595             MakeGroups: forces the generation of new groups from existing ones
5596             LinearVariation: forces the computation of rotation angles as linear
5597                 variation of the given Angles along path steps
5598
5599         Returns:
5600             list of created :class:`groups <SMESH.SMESH_GroupBase>` and 
5601             :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>` if *MakeGroups* == True,
5602             only :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>` otherwise
5603         Example: :ref:`tui_extrusion_along_path`
5604         """
5605
5606         n,e,f = [],[],theObject
5607         gr,er = self.ExtrusionAlongPathObjects(n,e,f, PathMesh, PathShape, NodeStart,
5608                                                HasAngles, Angles, LinearVariation,
5609                                                HasRefPoint, RefPoint, MakeGroups)
5610         if MakeGroups: return gr,er
5611         return er
5612
5613     def Mirror(self, IDsOfElements, Mirror, theMirrorType=None, Copy=0, MakeGroups=False):
5614         """
5615         Create a symmetrical copy of mesh elements
5616
5617         Parameters:
5618             IDsOfElements: list of elements ids
5619             Mirror: is :class:`SMESH.AxisStruct` or geom object (point, line, plane)
5620             theMirrorType: smeshBuilder.POINT, smeshBuilder.AXIS or smeshBuilder.PLANE.
5621                 If the *Mirror* is a geom object this parameter is unnecessary
5622             Copy: allows to copy element (Copy is 1) or to replace with its mirroring (Copy is 0)
5623             MakeGroups: forces the generation of new groups from existing ones (if Copy)
5624
5625         Returns:
5626             list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
5627         """
5628
5629         if IDsOfElements == []:
5630             IDsOfElements = self.GetElementsId()
5631         if ( isinstance( Mirror, geomBuilder.GEOM._objref_GEOM_Object)):
5632             Mirror        = self.smeshpyD.GetAxisStruct(Mirror)
5633             theMirrorType = Mirror._mirrorType
5634         else:
5635             self.mesh.SetParameters(Mirror.parameters)
5636         if Copy and MakeGroups:
5637             return self.editor.MirrorMakeGroups(IDsOfElements, Mirror, theMirrorType)
5638         self.editor.Mirror(IDsOfElements, Mirror, theMirrorType, Copy)
5639         return []
5640
5641     def MirrorMakeMesh(self, IDsOfElements, Mirror, theMirrorType=0, MakeGroups=0, NewMeshName=""):
5642         """
5643         Create a new mesh by a symmetrical copy of mesh elements
5644
5645         Parameters:
5646             IDsOfElements: the list of elements ids
5647             Mirror: is :class:`SMESH.AxisStruct` or geom object (point, line, plane)
5648             theMirrorType: smeshBuilder.POINT, smeshBuilder.AXIS or smeshBuilder.PLANE.
5649                 If the *Mirror* is a geom object this parameter is unnecessary
5650             MakeGroups: to generate new groups from existing ones
5651             NewMeshName: a name of the new mesh to create
5652
5653         Returns:
5654             instance of class :class:`Mesh`
5655         """
5656
5657         if IDsOfElements == []:
5658             IDsOfElements = self.GetElementsId()
5659         if ( isinstance( Mirror, geomBuilder.GEOM._objref_GEOM_Object)):
5660             Mirror        = self.smeshpyD.GetAxisStruct(Mirror)
5661             theMirrorType = Mirror._mirrorType
5662         else:
5663             self.mesh.SetParameters(Mirror.parameters)
5664         mesh = self.editor.MirrorMakeMesh(IDsOfElements, Mirror, theMirrorType,
5665                                           MakeGroups, NewMeshName)
5666         return Mesh(self.smeshpyD,self.geompyD,mesh)
5667
5668     def MirrorObject (self, theObject, Mirror, theMirrorType=None, Copy=0, MakeGroups=False):
5669         """
5670         Create a symmetrical copy of the object
5671
5672         Parameters:
5673             theObject: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
5674             Mirror: :class:`SMESH.AxisStruct` or geom object (point, line, plane)
5675             theMirrorType: smeshBuilder.POINT, smeshBuilder.AXIS or smeshBuilder.PLANE.
5676                 If the *Mirror* is a geom object this parameter is unnecessary
5677             Copy: allows copying the element (Copy==True) or replacing it with its mirror (Copy==False)
5678             MakeGroups: forces the generation of new groups from existing ones (if Copy)
5679
5680         Returns:
5681             list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
5682         """
5683
5684         if ( isinstance( theObject, Mesh )):
5685             theObject = theObject.GetMesh()
5686         if ( isinstance( Mirror, geomBuilder.GEOM._objref_GEOM_Object)):
5687             Mirror        = self.smeshpyD.GetAxisStruct(Mirror)
5688             theMirrorType = Mirror._mirrorType
5689         else:
5690             self.mesh.SetParameters(Mirror.parameters)
5691         if Copy and MakeGroups:
5692             return self.editor.MirrorObjectMakeGroups(theObject, Mirror, theMirrorType)
5693         self.editor.MirrorObject(theObject, Mirror, theMirrorType, Copy)
5694         return []
5695
5696     def MirrorObjectMakeMesh (self, theObject, Mirror, theMirrorType=0,MakeGroups=0,NewMeshName=""):
5697         """
5698         Create a new mesh by a symmetrical copy of the object
5699
5700         Parameters:
5701             theObject: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
5702             Mirror: :class:`SMESH.AxisStruct` or geom object (point, line, plane)
5703             theMirrorType: smeshBuilder.POINT, smeshBuilder.AXIS or smeshBuilder.PLANE.
5704                 If the *Mirror* is a geom object this parameter is unnecessary
5705             MakeGroups: forces the generation of new groups from existing ones
5706             NewMeshName: the name of the new mesh to create
5707
5708         Returns:
5709             instance of class :class:`Mesh`
5710         """
5711
5712         if ( isinstance( theObject, Mesh )):
5713             theObject = theObject.GetMesh()
5714         if ( isinstance( Mirror, geomBuilder.GEOM._objref_GEOM_Object)):
5715             Mirror        = self.smeshpyD.GetAxisStruct(Mirror)
5716             theMirrorType = Mirror._mirrorType
5717         else:
5718             self.mesh.SetParameters(Mirror.parameters)
5719         mesh = self.editor.MirrorObjectMakeMesh(theObject, Mirror, theMirrorType,
5720                                                 MakeGroups, NewMeshName)
5721         return Mesh( self.smeshpyD,self.geompyD,mesh )
5722
5723     def Translate(self, IDsOfElements, Vector, Copy, MakeGroups=False):
5724         """
5725         Translate the elements
5726
5727         Parameters:
5728             IDsOfElements: list of elements ids
5729             Vector: the direction of translation (:class:`SMESH.DirStruct` or vector or 3 vector components)
5730             Copy: allows copying the translated elements
5731             MakeGroups: forces the generation of new groups from existing ones (if Copy)
5732
5733         Returns:
5734             list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
5735         """
5736
5737         if IDsOfElements == []:
5738             IDsOfElements = self.GetElementsId()
5739         if ( isinstance( Vector, geomBuilder.GEOM._objref_GEOM_Object)):
5740             Vector = self.smeshpyD.GetDirStruct(Vector)
5741         if isinstance( Vector, list ):
5742             Vector = self.smeshpyD.MakeDirStruct(*Vector)
5743         self.mesh.SetParameters(Vector.PS.parameters)
5744         if Copy and MakeGroups:
5745             return self.editor.TranslateMakeGroups(IDsOfElements, Vector)
5746         self.editor.Translate(IDsOfElements, Vector, Copy)
5747         return []
5748
5749     def TranslateMakeMesh(self, IDsOfElements, Vector, MakeGroups=False, NewMeshName=""):
5750         """
5751         Create a new mesh of translated elements
5752
5753         Parameters:
5754             IDsOfElements: list of elements ids
5755             Vector: the direction of translation (:class:`SMESH.DirStruct` or vector or 3 vector components)
5756             MakeGroups: forces the generation of new groups from existing ones
5757             NewMeshName: the name of the newly created mesh
5758
5759         Returns:
5760             instance of class :class:`Mesh`
5761         """
5762
5763         if IDsOfElements == []:
5764             IDsOfElements = self.GetElementsId()
5765         if ( isinstance( Vector, geomBuilder.GEOM._objref_GEOM_Object)):
5766             Vector = self.smeshpyD.GetDirStruct(Vector)
5767         if isinstance( Vector, list ):
5768             Vector = self.smeshpyD.MakeDirStruct(*Vector)
5769         self.mesh.SetParameters(Vector.PS.parameters)
5770         mesh = self.editor.TranslateMakeMesh(IDsOfElements, Vector, MakeGroups, NewMeshName)
5771         return Mesh ( self.smeshpyD, self.geompyD, mesh )
5772
5773     def TranslateObject(self, theObject, Vector, Copy, MakeGroups=False):
5774         """
5775         Translate the object
5776
5777         Parameters:
5778             theObject: the object to translate (:class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`)
5779             Vector: direction of translation (:class:`SMESH.DirStruct` or geom vector or 3 vector components)
5780             Copy: allows copying the translated elements
5781             MakeGroups: forces the generation of new groups from existing ones (if Copy)
5782
5783         Returns:
5784             list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
5785         """
5786
5787         if ( isinstance( theObject, Mesh )):
5788             theObject = theObject.GetMesh()
5789         if ( isinstance( Vector, geomBuilder.GEOM._objref_GEOM_Object)):
5790             Vector = self.smeshpyD.GetDirStruct(Vector)
5791         if isinstance( Vector, list ):
5792             Vector = self.smeshpyD.MakeDirStruct(*Vector)
5793         self.mesh.SetParameters(Vector.PS.parameters)
5794         if Copy and MakeGroups:
5795             return self.editor.TranslateObjectMakeGroups(theObject, Vector)
5796         self.editor.TranslateObject(theObject, Vector, Copy)
5797         return []
5798
5799     def TranslateObjectMakeMesh(self, theObject, Vector, MakeGroups=False, NewMeshName=""):
5800         """
5801         Create a new mesh from the translated object
5802
5803         Parameters:
5804             theObject: the object to translate (:class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`)
5805             Vector: the direction of translation (:class:`SMESH.DirStruct` or geom vector or 3 vector components)
5806             MakeGroups: forces the generation of new groups from existing ones
5807             NewMeshName: the name of the newly created mesh
5808
5809         Returns:
5810             instance of class :class:`Mesh`
5811         """
5812
5813         if isinstance( theObject, Mesh ):
5814             theObject = theObject.GetMesh()
5815         if isinstance( Vector, geomBuilder.GEOM._objref_GEOM_Object ):
5816             Vector = self.smeshpyD.GetDirStruct(Vector)
5817         if isinstance( Vector, list ):
5818             Vector = self.smeshpyD.MakeDirStruct(*Vector)
5819         self.mesh.SetParameters(Vector.PS.parameters)
5820         mesh = self.editor.TranslateObjectMakeMesh(theObject, Vector, MakeGroups, NewMeshName)
5821         return Mesh( self.smeshpyD, self.geompyD, mesh )
5822
5823
5824
5825     def Scale(self, theObject, thePoint, theScaleFact, Copy, MakeGroups=False):
5826         """
5827         Scale the object
5828
5829         Parameters:
5830             theObject: the object to translate (:class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`)
5831             thePoint: base point for scale (:class:`SMESH.PointStruct` or list of 3 coordinates)
5832             theScaleFact: list of 1-3 scale factors for axises
5833             Copy: allows copying the translated elements
5834             MakeGroups: forces the generation of new groups from existing
5835                 ones (if Copy)
5836
5837         Returns:
5838             list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True,
5839             empty list otherwise
5840         """
5841         unRegister = genObjUnRegister()
5842         if ( isinstance( theObject, Mesh )):
5843             theObject = theObject.GetMesh()
5844         if ( isinstance( theObject, list )):
5845             theObject = self.GetIDSource(theObject, SMESH.ALL)
5846             unRegister.set( theObject )
5847         if ( isinstance( thePoint, list )):
5848             thePoint = PointStruct( thePoint[0], thePoint[1], thePoint[2] )
5849         if ( isinstance( theScaleFact, float )):
5850             theScaleFact = [theScaleFact]
5851         if ( isinstance( theScaleFact, int )):
5852             theScaleFact = [ float(theScaleFact)]
5853
5854         self.mesh.SetParameters(thePoint.parameters)
5855
5856         if Copy and MakeGroups:
5857             return self.editor.ScaleMakeGroups(theObject, thePoint, theScaleFact)
5858         self.editor.Scale(theObject, thePoint, theScaleFact, Copy)
5859         return []
5860
5861     def ScaleMakeMesh(self, theObject, thePoint, theScaleFact, MakeGroups=False, NewMeshName=""):
5862         """
5863         Create a new mesh from the translated object
5864
5865         Parameters:
5866             theObject: the object to translate (:class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`)
5867             thePoint: base point for scale (:class:`SMESH.PointStruct` or list of 3 coordinates)
5868             theScaleFact: list of 1-3 scale factors for axises
5869             MakeGroups: forces the generation of new groups from existing ones
5870             NewMeshName: the name of the newly created mesh
5871
5872         Returns:
5873             instance of class :class:`Mesh`
5874         """
5875         unRegister = genObjUnRegister()
5876         if (isinstance(theObject, Mesh)):
5877             theObject = theObject.GetMesh()
5878         if ( isinstance( theObject, list )):
5879             theObject = self.GetIDSource(theObject,SMESH.ALL)
5880             unRegister.set( theObject )
5881         if ( isinstance( thePoint, list )):
5882             thePoint = PointStruct( thePoint[0], thePoint[1], thePoint[2] )
5883         if ( isinstance( theScaleFact, float )):
5884             theScaleFact = [theScaleFact]
5885         if ( isinstance( theScaleFact, int )):
5886             theScaleFact = [ float(theScaleFact)]
5887
5888         self.mesh.SetParameters(thePoint.parameters)
5889         mesh = self.editor.ScaleMakeMesh(theObject, thePoint, theScaleFact,
5890                                          MakeGroups, NewMeshName)
5891         return Mesh( self.smeshpyD, self.geompyD, mesh )
5892
5893
5894
5895     def Rotate (self, IDsOfElements, Axis, AngleInRadians, Copy, MakeGroups=False):
5896         """
5897         Rotate the elements
5898
5899         Parameters:
5900             IDsOfElements: list of elements ids
5901             Axis: the axis of rotation (:class:`SMESH.AxisStruct` or geom line)
5902             AngleInRadians: the angle of rotation (in radians) or a name of variable which defines angle in degrees
5903             Copy: allows copying the rotated elements
5904             MakeGroups: forces the generation of new groups from existing ones (if Copy)
5905
5906         Returns:
5907             list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True, empty list otherwise
5908         """
5909
5910
5911         if IDsOfElements == []:
5912             IDsOfElements = self.GetElementsId()
5913         if ( isinstance( Axis, geomBuilder.GEOM._objref_GEOM_Object)):
5914             Axis = self.smeshpyD.GetAxisStruct(Axis)
5915         AngleInRadians,Parameters,hasVars = ParseAngles(AngleInRadians)
5916         Parameters = Axis.parameters + var_separator + Parameters
5917         self.mesh.SetParameters(Parameters)
5918         if Copy and MakeGroups:
5919             return self.editor.RotateMakeGroups(IDsOfElements, Axis, AngleInRadians)
5920         self.editor.Rotate(IDsOfElements, Axis, AngleInRadians, Copy)
5921         return []
5922
5923     def RotateMakeMesh (self, IDsOfElements, Axis, AngleInRadians, MakeGroups=0, NewMeshName=""):
5924         """
5925         Create a new mesh of rotated elements
5926
5927         Parameters:
5928             IDsOfElements: list of element ids
5929             Axis: the axis of rotation (:class:`SMESH.AxisStruct` or geom line)
5930             AngleInRadians: the angle of rotation (in radians) or a name of variable which defines angle in degrees
5931             MakeGroups: forces the generation of new groups from existing ones
5932             NewMeshName: the name of the newly created mesh
5933
5934         Returns:
5935             instance of class :class:`Mesh`
5936         """
5937
5938         if IDsOfElements == []:
5939             IDsOfElements = self.GetElementsId()
5940         if ( isinstance( Axis, geomBuilder.GEOM._objref_GEOM_Object)):
5941             Axis = self.smeshpyD.GetAxisStruct(Axis)
5942         AngleInRadians,Parameters,hasVars = ParseAngles(AngleInRadians)
5943         Parameters = Axis.parameters + var_separator + Parameters
5944         self.mesh.SetParameters(Parameters)
5945         mesh = self.editor.RotateMakeMesh(IDsOfElements, Axis, AngleInRadians,
5946                                           MakeGroups, NewMeshName)
5947         return Mesh( self.smeshpyD, self.geompyD, mesh )
5948
5949     def RotateObject (self, theObject, Axis, AngleInRadians, Copy, MakeGroups=False):
5950         """
5951         Rotate the object
5952
5953         Parameters:
5954             theObject: the object to rotate (:class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`)
5955             Axis: the axis of rotation (:class:`SMESH.AxisStruct` or geom line)
5956             AngleInRadians: the angle of rotation (in radians) or a name of variable which defines angle in degrees
5957             Copy: allows copying the rotated elements
5958             MakeGroups: forces the generation of new groups from existing ones (if Copy)
5959
5960         Returns:
5961             list of created :class:`groups <SMESH.SMESH_GroupBase>` if MakeGroups==True, empty list otherwise
5962         """
5963
5964         if (isinstance(theObject, Mesh)):
5965             theObject = theObject.GetMesh()
5966         if (isinstance(Axis, geomBuilder.GEOM._objref_GEOM_Object)):
5967             Axis = self.smeshpyD.GetAxisStruct(Axis)
5968         AngleInRadians,Parameters,hasVars = ParseAngles(AngleInRadians)
5969         Parameters = Axis.parameters + ":" + Parameters
5970         self.mesh.SetParameters(Parameters)
5971         if Copy and MakeGroups:
5972             return self.editor.RotateObjectMakeGroups(theObject, Axis, AngleInRadians)
5973         self.editor.RotateObject(theObject, Axis, AngleInRadians, Copy)
5974         return []
5975
5976     def RotateObjectMakeMesh(self, theObject, Axis, AngleInRadians, MakeGroups=0,NewMeshName=""):
5977         """
5978         Create a new mesh from the rotated object
5979
5980         Parameters:
5981             theObject: the object to rotate (:class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`)
5982             Axis: the axis of rotation (:class:`SMESH.AxisStruct` or geom line)
5983             AngleInRadians: the angle of rotation (in radians)  or a name of variable which defines angle in degrees
5984             MakeGroups: forces the generation of new groups from existing ones
5985             NewMeshName: the name of the newly created mesh
5986
5987         Returns:
5988             instance of class :class:`Mesh`
5989         """
5990
5991         if (isinstance( theObject, Mesh )):
5992             theObject = theObject.GetMesh()
5993         if (isinstance(Axis, geomBuilder.GEOM._objref_GEOM_Object)):
5994             Axis = self.smeshpyD.GetAxisStruct(Axis)
5995         AngleInRadians,Parameters,hasVars = ParseAngles(AngleInRadians)
5996         Parameters = Axis.parameters + ":" + Parameters
5997         mesh = self.editor.RotateObjectMakeMesh(theObject, Axis, AngleInRadians,
5998                                                        MakeGroups, NewMeshName)
5999         self.mesh.SetParameters(Parameters)
6000         return Mesh( self.smeshpyD, self.geompyD, mesh )
6001
6002     def Offset(self, theObject, Value, MakeGroups=False, CopyElements=False, NewMeshName=''):
6003         """
6004         Create an offset mesh from the given 2D object
6005
6006         Parameters:
6007             theObject (SMESH.SMESH_IDSource): the source object (mesh, sub-mesh, group or filter)
6008             theValue (float): signed offset size
6009             MakeGroups (boolean): forces the generation of new groups from existing ones
6010             CopyElements (boolean): if *NewMeshName* is empty, True means to keep original elements, 
6011                           False means to remove original elements.
6012             NewMeshName (string): the name of a mesh to create. If empty, offset elements are added to this mesh
6013
6014         Returns:
6015             A tuple (:class:`Mesh`, list of :class:`groups <SMESH.SMESH_Group>`)
6016         """
6017
6018         if isinstance( theObject, Mesh ):
6019             theObject = theObject.GetMesh()
6020         theValue,Parameters,hasVars = ParseParameters(Value)
6021         mesh_groups = self.editor.Offset(theObject, Value, MakeGroups, CopyElements, NewMeshName)
6022         self.mesh.SetParameters(Parameters)
6023         # if mesh_groups[0]:
6024         #     return Mesh( self.smeshpyD, self.geompyD, mesh_groups[0] ), mesh_groups[1]
6025         return mesh_groups
6026
6027     def FindCoincidentNodes (self, Tolerance, SeparateCornerAndMediumNodes=False):
6028         """
6029         Find groups of adjacent nodes within Tolerance.
6030
6031         Parameters:
6032             Tolerance (float): the value of tolerance
6033             SeparateCornerAndMediumNodes (boolean): if *True*, in quadratic mesh puts
6034                 corner and medium nodes in separate groups thus preventing
6035                 their further merge.
6036
6037         Returns:
6038             the list of groups of nodes IDs (e.g. [[1,12,13],[4,25]])
6039         """
6040
6041         return self.editor.FindCoincidentNodes( Tolerance, SeparateCornerAndMediumNodes )
6042
6043     def FindCoincidentNodesOnPart (self, SubMeshOrGroup, Tolerance,
6044                                    exceptNodes=[], SeparateCornerAndMediumNodes=False):
6045         """
6046         Find groups of adjacent nodes within Tolerance.
6047
6048         Parameters:
6049             Tolerance: the value of tolerance
6050             SubMeshOrGroup: :class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`
6051             exceptNodes: list of either SubMeshes, Groups or node IDs to exclude from search
6052             SeparateCornerAndMediumNodes: if *True*, in quadratic mesh puts
6053                 corner and medium nodes in separate groups thus preventing
6054                 their further merge.
6055
6056         Returns:
6057             the list of groups of nodes IDs (e.g. [[1,12,13],[4,25]])
6058         """
6059
6060         unRegister = genObjUnRegister()
6061         if (isinstance( SubMeshOrGroup, Mesh )):
6062             SubMeshOrGroup = SubMeshOrGroup.GetMesh()
6063         if not isinstance( exceptNodes, list ):
6064             exceptNodes = [ exceptNodes ]
6065         if exceptNodes and isinstance( exceptNodes[0], int ):
6066             exceptNodes = [ self.GetIDSource( exceptNodes, SMESH.NODE )]
6067             unRegister.set( exceptNodes )
6068         return self.editor.FindCoincidentNodesOnPartBut(SubMeshOrGroup, Tolerance,
6069                                                         exceptNodes, SeparateCornerAndMediumNodes)
6070
6071     def MergeNodes (self, GroupsOfNodes, NodesToKeep=[], AvoidMakingHoles=False):
6072         """
6073         Merge nodes
6074
6075         Parameters:
6076             GroupsOfNodes: a list of groups of nodes IDs for merging.
6077                 E.g. [[1,12,13],[25,4]] means that nodes 12, 13 and 4 will be removed and replaced
6078                 in all elements and groups by nodes 1 and 25 correspondingly
6079             NodesToKeep: nodes to keep in the mesh: a list of groups, sub-meshes or node IDs.
6080                 If *NodesToKeep* does not include a node to keep for some group to merge,
6081                 then the first node in the group is kept.
6082             AvoidMakingHoles: prevent merging nodes which cause removal of elements becoming
6083                 invalid
6084         """
6085         # NodesToKeep are converted to SMESH.SMESH_IDSource in meshEditor.MergeNodes()
6086         self.editor.MergeNodes( GroupsOfNodes, NodesToKeep, AvoidMakingHoles )
6087
6088     def FindEqualElements (self, MeshOrSubMeshOrGroup=None):
6089         """
6090         Find the elements built on the same nodes.
6091
6092         Parameters:
6093             MeshOrSubMeshOrGroup: :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
6094
6095         Returns:
6096             the list of groups of equal elements IDs (e.g. [[1,12,13],[4,25]])
6097         """
6098
6099         if not MeshOrSubMeshOrGroup:
6100             MeshOrSubMeshOrGroup=self.mesh
6101         elif isinstance( MeshOrSubMeshOrGroup, Mesh ):
6102             MeshOrSubMeshOrGroup = MeshOrSubMeshOrGroup.GetMesh()
6103         return self.editor.FindEqualElements( MeshOrSubMeshOrGroup )
6104
6105     def MergeElements(self, GroupsOfElementsID):
6106         """
6107         Merge elements in each given group.
6108
6109         Parameters:
6110             GroupsOfElementsID: a list of groups (lists) of elements IDs for merging
6111                 (e.g. [[1,12,13],[25,4]] means that elements 12, 13 and 4 will be removed and
6112                 replaced in all groups by elements 1 and 25)
6113         """
6114
6115         self.editor.MergeElements(GroupsOfElementsID)
6116
6117     def MergeEqualElements(self):
6118         """
6119         Leave one element and remove all other elements built on the same nodes.
6120         """
6121
6122         self.editor.MergeEqualElements()
6123
6124     def FindFreeBorders(self, ClosedOnly=True):
6125         """
6126         Returns all or only closed free borders
6127
6128         Returns:
6129             list of SMESH.FreeBorder's
6130         """
6131
6132         return self.editor.FindFreeBorders( ClosedOnly )
6133
6134     def FillHole(self, holeNodes):
6135         """
6136         Fill with 2D elements a hole defined by a SMESH.FreeBorder.
6137
6138         Parameters:
6139             FreeBorder: either a SMESH.FreeBorder or a list on node IDs. These nodes
6140                 must describe all sequential nodes of the hole border. The first and the last
6141                 nodes must be the same. Use :meth:`FindFreeBorders` to get nodes of holes.
6142         """
6143
6144
6145         if holeNodes and isinstance( holeNodes, list ) and isinstance( holeNodes[0], int ):
6146             holeNodes = SMESH.FreeBorder(nodeIDs=holeNodes)
6147         if not isinstance( holeNodes, SMESH.FreeBorder ):
6148             raise TypeError("holeNodes must be either SMESH.FreeBorder or list of integer and not %s" % holeNodes)
6149         self.editor.FillHole( holeNodes )
6150
6151     def FindCoincidentFreeBorders (self, tolerance=0.):
6152         """
6153         Return groups of FreeBorder's coincident within the given tolerance.
6154
6155         Parameters:
6156             tolerance: the tolerance. If the tolerance <= 0.0 then one tenth of an average
6157                 size of elements adjacent to free borders being compared is used.
6158
6159         Returns:
6160             SMESH.CoincidentFreeBorders structure
6161         """
6162
6163         return self.editor.FindCoincidentFreeBorders( tolerance )
6164
6165     def SewCoincidentFreeBorders (self, freeBorders, createPolygons=False, createPolyhedra=False):
6166         """
6167         Sew FreeBorder's of each group
6168
6169         Parameters:
6170             freeBorders: either a SMESH.CoincidentFreeBorders structure or a list of lists
6171                 where each enclosed list contains node IDs of a group of coincident free
6172                 borders such that each consequent triple of IDs within a group describes
6173                 a free border in a usual way: n1, n2, nLast - i.e. 1st node, 2nd node and
6174                 last node of a border.
6175                 For example [[1, 2, 10, 20, 21, 40], [11, 12, 15, 55, 54, 41]] describes two
6176                 groups of coincident free borders, each group including two borders.
6177             createPolygons: if :code:`True` faces adjacent to free borders are converted to
6178                 polygons if a node of opposite border falls on a face edge, else such
6179                 faces are split into several ones.
6180             createPolyhedra: if :code:`True` volumes adjacent to free borders are converted to
6181                 polyhedra if a node of opposite border falls on a volume edge, else such
6182                 volumes, if any, remain intact and the mesh becomes non-conformal.
6183
6184         Returns:
6185             a number of successfully sewed groups
6186         """
6187
6188         if freeBorders and isinstance( freeBorders, list ):
6189             # construct SMESH.CoincidentFreeBorders
6190             if isinstance( freeBorders[0], int ):
6191                 freeBorders = [freeBorders]
6192             borders = []
6193             coincidentGroups = []
6194             for nodeList in freeBorders:
6195                 if not nodeList or len( nodeList ) % 3:
6196                     raise ValueError("Wrong number of nodes in this group: %s" % nodeList)
6197                 group = []
6198                 while nodeList:
6199                     group.append  ( SMESH.FreeBorderPart( len(borders), 0, 1, 2 ))
6200                     borders.append( SMESH.FreeBorder( nodeList[:3] ))
6201                     nodeList = nodeList[3:]
6202                     pass
6203                 coincidentGroups.append( group )
6204                 pass
6205             freeBorders = SMESH.CoincidentFreeBorders( borders, coincidentGroups )
6206
6207         return self.editor.SewCoincidentFreeBorders( freeBorders, createPolygons, createPolyhedra )
6208
6209     def SewFreeBorders (self, FirstNodeID1, SecondNodeID1, LastNodeID1,
6210                         FirstNodeID2, SecondNodeID2, LastNodeID2,
6211                         CreatePolygons, CreatePolyedrs):
6212         """
6213         Sew free borders
6214
6215         Returns:
6216             :class:`error code <SMESH.SMESH_MeshEditor.Sew_Error>`
6217         """
6218
6219         return self.editor.SewFreeBorders(FirstNodeID1, SecondNodeID1, LastNodeID1,
6220                                           FirstNodeID2, SecondNodeID2, LastNodeID2,
6221                                           CreatePolygons, CreatePolyedrs)
6222
6223     def SewConformFreeBorders (self, FirstNodeID1, SecondNodeID1, LastNodeID1,
6224                                FirstNodeID2, SecondNodeID2):
6225         """
6226         Sew conform free borders
6227
6228         Returns:
6229             :class:`error code <SMESH.SMESH_MeshEditor.Sew_Error>`
6230         """
6231
6232         return self.editor.SewConformFreeBorders(FirstNodeID1, SecondNodeID1, LastNodeID1,
6233                                                  FirstNodeID2, SecondNodeID2)
6234
6235     def SewBorderToSide (self, FirstNodeIDOnFreeBorder, SecondNodeIDOnFreeBorder, LastNodeIDOnFreeBorder,
6236                          FirstNodeIDOnSide, LastNodeIDOnSide, CreatePolygons, CreatePolyedrs):
6237         """
6238         Sew border to side
6239
6240         Returns:
6241             :class:`error code <SMESH.SMESH_MeshEditor.Sew_Error>`
6242         """
6243
6244         return self.editor.SewBorderToSide(FirstNodeIDOnFreeBorder, SecondNodeIDOnFreeBorder, LastNodeIDOnFreeBorder,
6245                                            FirstNodeIDOnSide, LastNodeIDOnSide, CreatePolygons, CreatePolyedrs)
6246
6247     def SewSideElements (self, IDsOfSide1Elements, IDsOfSide2Elements,
6248                          NodeID1OfSide1ToMerge, NodeID1OfSide2ToMerge,
6249                          NodeID2OfSide1ToMerge, NodeID2OfSide2ToMerge):
6250         """
6251         Sew two sides of a mesh. The nodes belonging to Side1 are
6252         merged with the nodes of elements of Side2.
6253         The number of elements in theSide1 and in theSide2 must be
6254         equal and they should have similar nodal connectivity.
6255         The nodes to merge should belong to side borders and
6256         the first node should be linked to the second.
6257
6258         Returns:
6259             :class:`error code <SMESH.SMESH_MeshEditor.Sew_Error>`
6260         """
6261
6262         return self.editor.SewSideElements(IDsOfSide1Elements, IDsOfSide2Elements,
6263                                            NodeID1OfSide1ToMerge, NodeID1OfSide2ToMerge,
6264                                            NodeID2OfSide1ToMerge, NodeID2OfSide2ToMerge)
6265
6266     def ChangeElemNodes(self, ide, newIDs):
6267         """
6268         Set new nodes for the given element.
6269
6270         Parameters:
6271             ide: the element ID
6272             newIDs: nodes IDs
6273
6274         Returns:
6275             False if the number of nodes does not correspond to the type of element
6276         """
6277
6278         return self.editor.ChangeElemNodes(ide, newIDs)
6279
6280     def GetLastCreatedNodes(self):
6281         """
6282         If during the last operation of :class:`SMESH.SMESH_MeshEditor` some nodes were
6283         created, this method return the list of their IDs.
6284         If new nodes were not created - return empty list
6285
6286         Returns:
6287             the list of integer values (can be empty)
6288         """
6289
6290         return self.editor.GetLastCreatedNodes()
6291
6292     def GetLastCreatedElems(self):
6293         """
6294         If during the last operation of :class:`SMESH.SMESH_MeshEditor` some elements were
6295         created this method return the list of their IDs.
6296         If new elements were not created - return empty list
6297
6298         Returns:
6299             the list of integer values (can be empty)
6300         """
6301
6302         return self.editor.GetLastCreatedElems()
6303
6304     def ClearLastCreated(self):
6305         """
6306         Forget what nodes and elements were created by the last mesh edition operation
6307         """
6308
6309         self.editor.ClearLastCreated()
6310
6311     def DoubleElements(self, theElements, theGroupName=""):
6312         """
6313         Create duplicates of given elements, i.e. create new elements based on the
6314         same nodes as the given ones.
6315
6316         Parameters:
6317             theElements: container of elements to duplicate. It can be a
6318                 :class:`mesh, sub-mesh, group, filter <SMESH.SMESH_IDSource>` 
6319                 or a list of element IDs. If *theElements* is
6320                 a :class:`Mesh`, elements of highest dimension are duplicated
6321             theGroupName: a name of group to contain the generated elements.
6322                 If a group with such a name already exists, the new elements
6323                 are added to the existing group, else a new group is created.
6324                 If *theGroupName* is empty, new elements are not added
6325                 in any group.
6326
6327         Returns:
6328                 a :class:`group <SMESH.SMESH_Group>` where the new elements are added. 
6329                 None if *theGroupName* == "".
6330         """
6331
6332         unRegister = genObjUnRegister()
6333         if isinstance( theElements, Mesh ):
6334             theElements = theElements.mesh
6335         elif isinstance( theElements, list ):
6336             theElements = self.GetIDSource( theElements, SMESH.ALL )
6337             unRegister.set( theElements )
6338         return self.editor.DoubleElements(theElements, theGroupName)
6339
6340     def DoubleNodes(self, theNodes, theModifiedElems):
6341         """
6342         Create a hole in a mesh by doubling the nodes of some particular elements
6343
6344         Parameters:
6345             theNodes: IDs of nodes to be doubled
6346             theModifiedElems: IDs of elements to be updated by the new (doubled)
6347                 nodes. If list of element identifiers is empty then nodes are doubled but
6348                 they not assigned to elements
6349
6350         Returns:
6351             True if operation has been completed successfully, False otherwise
6352         """
6353
6354         return self.editor.DoubleNodes(theNodes, theModifiedElems)
6355
6356     def DoubleNode(self, theNodeId, theModifiedElems):
6357         """
6358         Create a hole in a mesh by doubling the nodes of some particular elements.
6359         This method provided for convenience works as :meth:`DoubleNodes`.
6360
6361         Parameters:
6362             theNodeId: IDs of node to double
6363             theModifiedElems: IDs of elements to update
6364
6365         Returns:
6366             True if operation has been completed successfully, False otherwise
6367         """
6368
6369         return self.editor.DoubleNode(theNodeId, theModifiedElems)
6370
6371     def DoubleNodeGroup(self, theNodes, theModifiedElems, theMakeGroup=False):
6372         """
6373         Create a hole in a mesh by doubling the nodes of some particular elements.
6374         This method provided for convenience works as :meth:`DoubleNodes`.
6375
6376         Parameters:
6377             theNodes: group of nodes to double.
6378             theModifiedElems: group of elements to update.
6379             theMakeGroup: forces the generation of a group containing new nodes.
6380
6381         Returns:
6382             True or a created group if operation has been completed successfully,
6383             False or None otherwise
6384         """
6385
6386         if theMakeGroup:
6387             return self.editor.DoubleNodeGroupNew(theNodes, theModifiedElems)
6388         return self.editor.DoubleNodeGroup(theNodes, theModifiedElems)
6389
6390     def DoubleNodeGroups(self, theNodes, theModifiedElems, theMakeGroup=False):
6391         """
6392         Create a hole in a mesh by doubling the nodes of some particular elements.
6393         This method provided for convenience works as :meth:`DoubleNodes`.
6394
6395         Parameters:
6396             theNodes: list of groups of nodes to double.
6397             theModifiedElems: list of groups of elements to update.
6398             theMakeGroup: forces the generation of a group containing new nodes.
6399
6400         Returns:
6401             True if operation has been completed successfully, False otherwise
6402         """
6403
6404         if theMakeGroup:
6405             return self.editor.DoubleNodeGroupsNew(theNodes, theModifiedElems)
6406         return self.editor.DoubleNodeGroups(theNodes, theModifiedElems)
6407
6408     def DoubleNodeElem(self, theElems, theNodesNot, theAffectedElems):
6409         """
6410         Create a hole in a mesh by doubling the nodes of some particular elements
6411
6412         Parameters:
6413             theElems: the list of elements (edges or faces) to replicate.
6414                 The nodes for duplication could be found from these elements
6415             theNodesNot: list of nodes NOT to replicate
6416             theAffectedElems: the list of elements (cells and edges) to which the
6417                 replicated nodes should be associated to
6418
6419         Returns:
6420             True if operation has been completed successfully, False otherwise
6421         """
6422
6423         return self.editor.DoubleNodeElem(theElems, theNodesNot, theAffectedElems)
6424
6425     def DoubleNodeElemInRegion(self, theElems, theNodesNot, theShape):
6426         """
6427         Create a hole in a mesh by doubling the nodes of some particular elements
6428
6429         Parameters:
6430             theElems: the list of elements (edges or faces) to replicate.
6431                 The nodes for duplication could be found from these elements
6432             theNodesNot: list of nodes NOT to replicate
6433             theShape: shape to detect affected elements (element which geometric center
6434                 located on or inside shape).
6435                 The replicated nodes should be associated to affected elements.
6436
6437         Returns:
6438             True if operation has been completed successfully, False otherwise
6439         """
6440
6441         return self.editor.DoubleNodeElemInRegion(theElems, theNodesNot, theShape)
6442
6443     def DoubleNodeElemGroup(self, theElems, theNodesNot, theAffectedElems,
6444                              theMakeGroup=False, theMakeNodeGroup=False):
6445         """
6446         Create a hole in a mesh by doubling the nodes of some particular elements.
6447         This method provided for convenience works as :meth:`DoubleNodes`.
6448
6449         Parameters:
6450             theElems: group of of elements (edges or faces) to replicate.
6451             theNodesNot: group of nodes NOT to replicate.
6452             theAffectedElems: group of elements to which the replicated nodes
6453                 should be associated to.
6454             theMakeGroup: forces the generation of a group containing new elements.
6455             theMakeNodeGroup: forces the generation of a group containing new nodes.
6456
6457         Returns:
6458             True or created groups (one or two) if operation has been completed successfully,
6459             False or None otherwise
6460         """
6461
6462         if theMakeGroup or theMakeNodeGroup:
6463             twoGroups = self.editor.DoubleNodeElemGroup2New(theElems, theNodesNot,
6464                                                             theAffectedElems,
6465                                                             theMakeGroup, theMakeNodeGroup)
6466             if theMakeGroup and theMakeNodeGroup:
6467                 return twoGroups
6468             else:
6469                 return twoGroups[ int(theMakeNodeGroup) ]
6470         return self.editor.DoubleNodeElemGroup(theElems, theNodesNot, theAffectedElems)
6471
6472     def DoubleNodeElemGroupInRegion(self, theElems, theNodesNot, theShape):
6473         """
6474         Create a hole in a mesh by doubling the nodes of some particular elements.
6475         This method provided for convenience works as :meth:`DoubleNodes`.
6476
6477         Parameters:
6478             theElems: group of of elements (edges or faces) to replicate
6479             theNodesNot: group of nodes not to replicate
6480             theShape: shape to detect affected elements (element which geometric center
6481                 located on or inside shape).
6482                 The replicated nodes should be associated to affected elements
6483         """
6484
6485         return self.editor.DoubleNodeElemGroupInRegion(theElems, theNodesNot, theShape)
6486
6487     def DoubleNodeElemGroups(self, theElems, theNodesNot, theAffectedElems,
6488                              theMakeGroup=False, theMakeNodeGroup=False):
6489         """
6490         Create a hole in a mesh by doubling the nodes of some particular elements.
6491         This method provided for convenience works as :meth:`DoubleNodes`.
6492
6493         Parameters:
6494             theElems: list of groups of elements (edges or faces) to replicate
6495             theNodesNot: list of groups of nodes NOT to replicate
6496             theAffectedElems: group of elements to which the replicated nodes
6497                 should be associated to
6498             theMakeGroup: forces generation of a group containing new elements.
6499             theMakeNodeGroup: forces generation of a group containing new nodes
6500
6501         Returns:
6502             True or created groups (one or two) if operation has been completed successfully,
6503             False or None otherwise
6504         """
6505
6506         if theMakeGroup or theMakeNodeGroup:
6507             twoGroups = self.editor.DoubleNodeElemGroups2New(theElems, theNodesNot,
6508                                                              theAffectedElems,
6509                                                              theMakeGroup, theMakeNodeGroup)
6510             if theMakeGroup and theMakeNodeGroup:
6511                 return twoGroups
6512             else:
6513                 return twoGroups[ int(theMakeNodeGroup) ]
6514         return self.editor.DoubleNodeElemGroups(theElems, theNodesNot, theAffectedElems)
6515
6516     def DoubleNodeElemGroupsInRegion(self, theElems, theNodesNot, theShape):
6517         """
6518         Create a hole in a mesh by doubling the nodes of some particular elements.
6519         This method provided for convenience works as :meth:`DoubleNodes`.
6520
6521         Parameters:
6522             theElems: list of groups of elements (edges or faces) to replicate
6523             theNodesNot: list of groups of nodes NOT to replicate
6524             theShape: shape to detect affected elements (element which geometric center
6525                 located on or inside shape).
6526                 The replicated nodes should be associated to affected elements
6527
6528         Returns:
6529             True if operation has been completed successfully, False otherwise
6530         """
6531
6532         return self.editor.DoubleNodeElemGroupsInRegion(theElems, theNodesNot, theShape)
6533
6534     def AffectedElemGroupsInRegion(self, theElems, theNodesNot, theShape):
6535         """
6536         Identify the elements that will be affected by node duplication (actual duplication is not performed).
6537         This method is the first step of :meth:`DoubleNodeElemGroupsInRegion`.
6538
6539         Parameters:
6540             theElems: list of groups of nodes or elements (edges or faces) to replicate
6541             theNodesNot: list of groups of nodes NOT to replicate
6542             theShape: shape to detect affected elements (element which geometric center
6543                 located on or inside shape).
6544                 The replicated nodes should be associated to affected elements
6545
6546         Returns:
6547             groups of affected elements in order: volumes, faces, edges
6548         """
6549
6550         return self.editor.AffectedElemGroupsInRegion(theElems, theNodesNot, theShape)
6551
6552     def DoubleNodesOnGroupBoundaries(self, theDomains, createJointElems, onAllBoundaries=False ):
6553
6554         """
6555         Double nodes on shared faces between groups of volumes and create flat elements on demand.
6556         The list of groups must describe a partition of the mesh volumes.
6557         The nodes of the internal faces at the boundaries of the groups are doubled.
6558         In option, the internal faces are replaced by flat elements.
6559         Triangles are transformed to prisms, and quadrangles to hexahedrons.
6560
6561         Parameters:
6562             theDomains: list of groups of volumes
6563             createJointElems: if True, create the elements
6564             onAllBoundaries: if True, the nodes and elements are also created on
6565                 the boundary between *theDomains* and the rest mesh
6566
6567         Returns:
6568             True if operation has been completed successfully, False otherwise
6569         """
6570
6571         return self.editor.DoubleNodesOnGroupBoundaries( theDomains, createJointElems, onAllBoundaries )
6572
6573     def CreateFlatElementsOnFacesGroups(self, theGroupsOfFaces ):
6574         """
6575         Double nodes on some external faces and create flat elements.
6576         Flat elements are mainly used by some types of mechanic calculations.
6577
6578         Each group of the list must be constituted of faces.
6579         Triangles are transformed in prisms, and quadrangles in hexahedrons.
6580
6581         Parameters:
6582             theGroupsOfFaces: list of groups of faces
6583
6584         Returns:
6585             True if operation has been completed successfully, False otherwise
6586         """
6587
6588         return self.editor.CreateFlatElementsOnFacesGroups( theGroupsOfFaces )
6589
6590     def CreateHoleSkin(self, radius, theShape, groupName, theNodesCoords):
6591         """
6592         Identify all the elements around a geom shape, get the faces delimiting the hole
6593         """
6594         return self.editor.CreateHoleSkin( radius, theShape, groupName, theNodesCoords )
6595
6596     def MakePolyLine(self, segments, groupName='', isPreview=False ):
6597         """    
6598         Create a polyline consisting of 1D mesh elements each lying on a 2D element of
6599         the initial mesh. Positions of new nodes are found by cutting the mesh by the
6600         plane passing through pairs of points specified by each :class:`SMESH.PolySegment` structure.
6601         If there are several paths connecting a pair of points, the shortest path is
6602         selected by the module. Position of the cutting plane is defined by the two
6603         points and an optional vector lying on the plane specified by a PolySegment.
6604         By default the vector is defined by Mesh module as following. A middle point
6605         of the two given points is computed. The middle point is projected to the mesh.
6606         The vector goes from the middle point to the projection point. In case of planar
6607         mesh, the vector is normal to the mesh.
6608
6609         *segments* [i].vector returns the used vector which goes from the middle point to its projection.
6610
6611         Parameters:        
6612             segments: list of :class:`SMESH.PolySegment` defining positions of cutting planes.
6613             groupName: optional name of a group where created mesh segments will be added.
6614             
6615         """    
6616         editor = self.editor
6617         if isPreview:
6618             editor = self.mesh.GetMeshEditPreviewer()
6619         segmentsRes = editor.MakePolyLine( segments, groupName )
6620         for i, seg in enumerate( segmentsRes ):
6621             segments[i].vector = seg.vector
6622         if isPreview:
6623             return editor.GetPreviewData()
6624         return None        
6625
6626     def GetFunctor(self, funcType ):
6627         """
6628         Return a cached numerical functor by its type.
6629
6630         Parameters:
6631             funcType: functor type: an item of :class:`SMESH.FunctorType` enumeration.
6632                 Note that not all items correspond to numerical functors.
6633
6634         Returns:
6635             :class:`SMESH.NumericalFunctor`. The functor is already initialized with a mesh
6636         """
6637
6638         fn = self.functors[ funcType._v ]
6639         if not fn:
6640             fn = self.smeshpyD.GetFunctor(funcType)
6641             fn.SetMesh(self.mesh)
6642             self.functors[ funcType._v ] = fn
6643         return fn
6644
6645     def FunctorValue(self, funcType, elemId, isElem=True):
6646         """
6647         Return value of a functor for a given element
6648
6649         Parameters:
6650             funcType: an item of :class:`SMESH.FunctorType` enum.
6651             elemId: element or node ID
6652             isElem: *elemId* is ID of element or node
6653
6654         Returns:
6655             the functor value or zero in case of invalid arguments
6656         """
6657
6658         fn = self.GetFunctor( funcType )
6659         if fn.GetElementType() == self.GetElementType(elemId, isElem):
6660             val = fn.GetValue(elemId)
6661         else:
6662             val = 0
6663         return val
6664
6665     def GetLength(self, elemId=None):
6666         """
6667         Get length of 1D element or sum of lengths of all 1D mesh elements
6668
6669         Parameters:
6670             elemId: mesh element ID (if not defined - sum of length of all 1D elements will be calculated)
6671
6672         Returns:
6673             element's length value if *elemId* is specified or sum of all 1D mesh elements' lengths otherwise
6674         """
6675
6676         length = 0
6677         if elemId == None:
6678             length = self.smeshpyD.GetLength(self)
6679         else:
6680             length = self.FunctorValue(SMESH.FT_Length, elemId)
6681         return length
6682
6683     def GetArea(self, elemId=None):
6684         """
6685         Get area of 2D element or sum of areas of all 2D mesh elements
6686         elemId mesh element ID (if not defined - sum of areas of all 2D elements will be calculated)
6687
6688         Returns:
6689             element's area value if *elemId* is specified or sum of all 2D mesh elements' areas otherwise
6690         """
6691
6692         area = 0
6693         if elemId == None:
6694             area = self.smeshpyD.GetArea(self)
6695         else:
6696             area = self.FunctorValue(SMESH.FT_Area, elemId)
6697         return area
6698
6699     def GetVolume(self, elemId=None):
6700         """
6701         Get volume of 3D element or sum of volumes of all 3D mesh elements
6702
6703         Parameters:
6704             elemId: mesh element ID (if not defined - sum of volumes of all 3D elements will be calculated)
6705
6706         Returns:
6707             element's volume value if *elemId* is specified or sum of all 3D mesh elements' volumes otherwise
6708         """
6709
6710         volume = 0
6711         if elemId == None:
6712             volume = self.smeshpyD.GetVolume(self)
6713         else:
6714             volume = self.FunctorValue(SMESH.FT_Volume3D, elemId)
6715         return volume
6716
6717     def GetMaxElementLength(self, elemId):
6718         """
6719         Get maximum element length.
6720
6721         Parameters:
6722             elemId: mesh element ID
6723
6724         Returns:
6725             element's maximum length value
6726         """
6727
6728         if self.GetElementType(elemId, True) == SMESH.VOLUME:
6729             ftype = SMESH.FT_MaxElementLength3D
6730         else:
6731             ftype = SMESH.FT_MaxElementLength2D
6732         return self.FunctorValue(ftype, elemId)
6733
6734     def GetAspectRatio(self, elemId):
6735         """
6736         Get aspect ratio of 2D or 3D element.
6737
6738         Parameters:
6739             elemId: mesh element ID
6740
6741         Returns:
6742             element's aspect ratio value
6743         """
6744
6745         if self.GetElementType(elemId, True) == SMESH.VOLUME:
6746             ftype = SMESH.FT_AspectRatio3D
6747         else:
6748             ftype = SMESH.FT_AspectRatio
6749         return self.FunctorValue(ftype, elemId)
6750
6751     def GetWarping(self, elemId):
6752         """
6753         Get warping angle of 2D element.
6754
6755         Parameters:
6756             elemId: mesh element ID
6757
6758         Returns:
6759             element's warping angle value
6760         """
6761
6762         return self.FunctorValue(SMESH.FT_Warping, elemId)
6763
6764     def GetMinimumAngle(self, elemId):
6765         """
6766         Get minimum angle of 2D element.
6767
6768         Parameters:
6769             elemId: mesh element ID
6770
6771         Returns:
6772             element's minimum angle value
6773         """
6774
6775         return self.FunctorValue(SMESH.FT_MinimumAngle, elemId)
6776
6777     def GetTaper(self, elemId):
6778         """
6779         Get taper of 2D element.
6780
6781         Parameters:
6782             elemId: mesh element ID
6783
6784         Returns:
6785             element's taper value
6786         """
6787
6788         return self.FunctorValue(SMESH.FT_Taper, elemId)
6789
6790     def GetSkew(self, elemId):
6791         """
6792         Get skew of 2D element.
6793
6794         Parameters:
6795             elemId: mesh element ID
6796
6797         Returns:
6798             element's skew value
6799         """
6800
6801         return self.FunctorValue(SMESH.FT_Skew, elemId)
6802
6803     def GetMinMax(self, funType, meshPart=None):
6804         """
6805         Return minimal and maximal value of a given functor.
6806
6807         Parameters:
6808             funType (SMESH.FunctorType): a functor type.
6809                   Note that not all items of :class:`SMESH.FunctorType` corresponds
6810                   to numerical functors.
6811             meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to treat
6812
6813         Returns:
6814             tuple (min,max)
6815         """
6816
6817         unRegister = genObjUnRegister()
6818         if isinstance( meshPart, list ):
6819             meshPart = self.GetIDSource( meshPart, SMESH.ALL )
6820             unRegister.set( meshPart )
6821         if isinstance( meshPart, Mesh ):
6822             meshPart = meshPart.mesh
6823         fun = self.GetFunctor( funType )
6824         if fun:
6825             if meshPart:
6826                 if hasattr( meshPart, "SetMesh" ):
6827                     meshPart.SetMesh( self.mesh ) # set mesh to filter
6828                 hist = fun.GetLocalHistogram( 1, False, meshPart )
6829             else:
6830                 hist = fun.GetHistogram( 1, False )
6831             if hist:
6832                 return hist[0].min, hist[0].max
6833         return None
6834
6835     pass # end of Mesh class
6836
6837
6838 class meshProxy(SMESH._objref_SMESH_Mesh):
6839     """
6840     Private class used to compensate change of CORBA API of SMESH_Mesh for backward compatibility
6841     with old dump scripts which call SMESH_Mesh directly and not via smeshBuilder.Mesh
6842     """
6843     def __init__(self,*args):
6844         SMESH._objref_SMESH_Mesh.__init__(self,*args)
6845     def __deepcopy__(self, memo=None):
6846         new = self.__class__(self)
6847         return new
6848     def CreateDimGroup(self,*args): # 2 args added: nbCommonNodes, underlyingOnly
6849         if len( args ) == 3:
6850             args += SMESH.ALL_NODES, True
6851         return SMESH._objref_SMESH_Mesh.CreateDimGroup(self, *args)
6852     def ExportToMEDX(self, *args): # function removed
6853         print("WARNING: ExportToMEDX() is deprecated, use ExportMED() instead")
6854         args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]]
6855         SMESH._objref_SMESH_Mesh.ExportMED(self, *args)
6856     def ExportToMED(self, *args): # function removed
6857         print("WARNING: ExportToMED() is deprecated, use ExportMED() instead")
6858         args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]]
6859         while len(args) < 4:  # !!!! nb of parameters for ExportToMED IDL's method
6860             args.append(True)
6861         SMESH._objref_SMESH_Mesh.ExportMED(self, *args)
6862     def ExportPartToMED(self, *args): # 'version' parameter removed
6863         args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]]
6864         SMESH._objref_SMESH_Mesh.ExportPartToMED(self, *args)
6865     def ExportMED(self, *args): # signature of method changed
6866         args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]]
6867         while len(args) < 4:  # !!!! nb of parameters for ExportToMED IDL's method
6868             args.append(True)
6869         SMESH._objref_SMESH_Mesh.ExportMED(self, *args)
6870     pass
6871 omniORB.registerObjref(SMESH._objref_SMESH_Mesh._NP_RepositoryId, meshProxy)
6872
6873
6874 class submeshProxy(SMESH._objref_SMESH_subMesh):
6875
6876     """
6877     Private class wrapping SMESH.SMESH_SubMesh in order to add Compute()
6878     """
6879     def __init__(self,*args):
6880         SMESH._objref_SMESH_subMesh.__init__(self,*args)
6881         self.mesh = None
6882     def __deepcopy__(self, memo=None):
6883         new = self.__class__(self)
6884         return new
6885
6886     def Compute(self,refresh=False):
6887         """
6888         Compute the sub-mesh and return the status of the computation
6889
6890         Parameters:
6891             refresh: if *True*, Object Browser is automatically updated (when running in GUI)
6892
6893         Returns:
6894             True or False
6895
6896         This is a method of SMESH.SMESH_submesh that can be obtained via Mesh.GetSubMesh() or
6897         :meth:`smeshBuilder.Mesh.GetSubMesh`.
6898         """
6899
6900         if not self.mesh:
6901             self.mesh = Mesh( smeshBuilder(), None, self.GetMesh())
6902
6903         ok = self.mesh.Compute( self.GetSubShape(),refresh=[] )
6904
6905         if salome.sg.hasDesktop():
6906             smeshgui = salome.ImportComponentGUI("SMESH")
6907             smeshgui.Init()
6908             smeshgui.SetMeshIcon( salome.ObjectToID( self ), ok, (self.GetNumberOfElements()==0) )
6909             if refresh: salome.sg.updateObjBrowser()
6910             pass
6911
6912         return ok
6913     pass
6914 omniORB.registerObjref(SMESH._objref_SMESH_subMesh._NP_RepositoryId, submeshProxy)
6915
6916
6917 class meshEditor(SMESH._objref_SMESH_MeshEditor):
6918     """
6919     Private class used to compensate change of CORBA API of SMESH_MeshEditor for backward
6920     compatibility with old dump scripts which call SMESH_MeshEditor directly and not via
6921     smeshBuilder.Mesh
6922     """
6923     def __init__(self,*args):
6924         SMESH._objref_SMESH_MeshEditor.__init__( self, *args)
6925         self.mesh = None
6926     def __getattr__(self, name ): # method called if an attribute not found
6927         if not self.mesh:         # look for name() method in Mesh class
6928             self.mesh = Mesh( None, None, SMESH._objref_SMESH_MeshEditor.GetMesh(self))
6929         if hasattr( self.mesh, name ):
6930             return getattr( self.mesh, name )
6931         if name == "ExtrusionAlongPathObjX":
6932             return getattr( self.mesh, "ExtrusionAlongPathX" ) # other method name
6933         print("meshEditor: attribute '%s' NOT FOUND" % name)
6934         return None
6935     def __deepcopy__(self, memo=None):
6936         new = self.__class__(self)
6937         return new
6938     def FindCoincidentNodes(self,*args): # a 2nd arg added (SeparateCornerAndMediumNodes)
6939         if len( args ) == 1: args += False,
6940         return SMESH._objref_SMESH_MeshEditor.FindCoincidentNodes( self, *args )
6941     def FindCoincidentNodesOnPart(self,*args): # a 3d arg added (SeparateCornerAndMediumNodes)
6942         if len( args ) == 2: args += False,
6943         return SMESH._objref_SMESH_MeshEditor.FindCoincidentNodesOnPart( self, *args )
6944     def MergeNodes(self,*args): # 2 args added (NodesToKeep,AvoidMakingHoles)
6945         if len( args ) == 1:
6946             return SMESH._objref_SMESH_MeshEditor.MergeNodes( self, args[0], [], False )
6947         NodesToKeep = args[1]
6948         AvoidMakingHoles = args[2] if len( args ) == 3 else False
6949         unRegister  = genObjUnRegister()
6950         if NodesToKeep:
6951             if isinstance( NodesToKeep, list ) and isinstance( NodesToKeep[0], int ):
6952                 NodesToKeep = self.MakeIDSource( NodesToKeep, SMESH.NODE )
6953             if not isinstance( NodesToKeep, list ):
6954                 NodesToKeep = [ NodesToKeep ]
6955         return SMESH._objref_SMESH_MeshEditor.MergeNodes( self, args[0], NodesToKeep, AvoidMakingHoles )
6956     pass
6957 omniORB.registerObjref(SMESH._objref_SMESH_MeshEditor._NP_RepositoryId, meshEditor)
6958
6959 class Pattern(SMESH._objref_SMESH_Pattern):
6960     """
6961     Private class wrapping SMESH.SMESH_Pattern CORBA class in order to treat Notebook
6962     variables in some methods
6963     """
6964
6965     def LoadFromFile(self, patternTextOrFile ):
6966         text = patternTextOrFile
6967         if os.path.exists( text ):
6968             text = open( patternTextOrFile ).read()
6969             pass
6970         return SMESH._objref_SMESH_Pattern.LoadFromFile( self, text )
6971
6972     def ApplyToMeshFaces(self, theMesh, theFacesIDs, theNodeIndexOnKeyPoint1, theReverse):
6973         decrFun = lambda i: i-1
6974         theNodeIndexOnKeyPoint1,Parameters,hasVars = ParseParameters(theNodeIndexOnKeyPoint1, decrFun)
6975         theMesh.SetParameters(Parameters)
6976         return SMESH._objref_SMESH_Pattern.ApplyToMeshFaces( self, theMesh, theFacesIDs, theNodeIndexOnKeyPoint1, theReverse )
6977
6978     def ApplyToHexahedrons(self, theMesh, theVolumesIDs, theNode000Index, theNode001Index):
6979         decrFun = lambda i: i-1
6980         theNode000Index,theNode001Index,Parameters,hasVars = ParseParameters(theNode000Index,theNode001Index, decrFun)
6981         theMesh.SetParameters(Parameters)
6982         return SMESH._objref_SMESH_Pattern.ApplyToHexahedrons( self, theMesh, theVolumesIDs, theNode000Index, theNode001Index )
6983
6984     def MakeMesh(self, mesh, CreatePolygons=False, CreatePolyhedra=False):
6985         if isinstance( mesh, Mesh ):
6986             mesh = mesh.GetMesh()
6987         return SMESH._objref_SMESH_Pattern.MakeMesh( self, mesh, CreatePolygons, CreatePolyhedra )
6988
6989 omniORB.registerObjref(SMESH._objref_SMESH_Pattern._NP_RepositoryId, Pattern)
6990 """
6991 Registering the new proxy for Pattern
6992 """
6993
6994 class algoCreator:
6995     """
6996     Private class used to bind methods creating algorithms to the class Mesh
6997     """
6998
6999     def __init__(self, method):
7000         self.mesh = None
7001         self.defaultAlgoType = ""
7002         self.algoTypeToClass = {}
7003         self.method = method
7004
7005     def add(self, algoClass):
7006         """
7007         Store a python class of algorithm
7008         """
7009         if inspect.isclass(algoClass) and \
7010            hasattr( algoClass, "algoType"):
7011             self.algoTypeToClass[ algoClass.algoType ] = algoClass
7012             if not self.defaultAlgoType and \
7013                hasattr( algoClass, "isDefault") and algoClass.isDefault:
7014                 self.defaultAlgoType = algoClass.algoType
7015             #print("Add",algoClass.algoType, "dflt",self.defaultAlgoType)
7016
7017     def copy(self, mesh):
7018         """
7019         Create a copy of self and assign mesh to the copy
7020         """
7021
7022         other = algoCreator( self.method )
7023         other.defaultAlgoType = self.defaultAlgoType
7024         other.algoTypeToClass = self.algoTypeToClass
7025         other.mesh = mesh
7026         return other
7027
7028     def __call__(self,algo="",geom=0,*args):
7029         """
7030         Create an instance of algorithm
7031         """
7032         algoType = ""
7033         shape = 0
7034         if isinstance( algo, str ):
7035             algoType = algo
7036         elif ( isinstance( algo, geomBuilder.GEOM._objref_GEOM_Object ) and \
7037                not isinstance( geom, geomBuilder.GEOM._objref_GEOM_Object )):
7038             shape = algo
7039         elif algo:
7040             args += (algo,)
7041
7042         if isinstance( geom, geomBuilder.GEOM._objref_GEOM_Object ):
7043             shape = geom
7044         elif not algoType and isinstance( geom, str ):
7045             algoType = geom
7046         elif geom:
7047             args += (geom,)
7048         for arg in args:
7049             if isinstance( arg, geomBuilder.GEOM._objref_GEOM_Object ) and not shape:
7050                 shape = arg
7051             elif isinstance( arg, str ) and not algoType:
7052                 algoType = arg
7053             else:
7054                 import traceback, sys
7055                 msg = "Warning. Unexpected argument in mesh.%s() --->  %s" % ( self.method, arg )
7056                 sys.stderr.write( msg + '\n' )
7057                 tb = traceback.extract_stack(None,2)
7058                 traceback.print_list( [tb[0]] )
7059         if not algoType:
7060             algoType = self.defaultAlgoType
7061         if not algoType and self.algoTypeToClass:
7062             algoType = sorted( self.algoTypeToClass.keys() )[0]
7063         if algoType in self.algoTypeToClass:
7064             #print("Create algo",algoType)
7065             return self.algoTypeToClass[ algoType ]( self.mesh, shape )
7066         raise RuntimeError( "No class found for algo type %s" % algoType)
7067         return None
7068
7069 class hypMethodWrapper:
7070     """
7071     Private class used to substitute and store variable parameters of hypotheses.
7072     """
7073
7074     def __init__(self, hyp, method):
7075         self.hyp    = hyp
7076         self.method = method
7077         #print("REBIND:", method.__name__)
7078         return
7079
7080     def __call__(self,*args):
7081         """
7082         call a method of hypothesis with calling SetVarParameter() before
7083         """
7084
7085         if not args:
7086             return self.method( self.hyp, *args ) # hypothesis method with no args
7087
7088         #print("MethWrapper.__call__", self.method.__name__, args)
7089         try:
7090             parsed = ParseParameters(*args)     # replace variables with their values
7091             self.hyp.SetVarParameter( parsed[-2], self.method.__name__ )
7092             result = self.method( self.hyp, *parsed[:-2] ) # call hypothesis method
7093         except omniORB.CORBA.BAD_PARAM: # raised by hypothesis method call
7094             # maybe there is a replaced string arg which is not variable
7095             result = self.method( self.hyp, *args )
7096         except ValueError as detail: # raised by ParseParameters()
7097             try:
7098                 result = self.method( self.hyp, *args )
7099             except omniORB.CORBA.BAD_PARAM:
7100                 raise ValueError(detail) # wrong variable name
7101
7102         return result
7103     pass
7104
7105 class genObjUnRegister:
7106     """
7107     A helper class that calls UnRegister() of SALOME.GenericObj'es stored in it
7108     """
7109
7110     def __init__(self, genObj=None):
7111         self.genObjList = []
7112         self.set( genObj )
7113         return
7114
7115     def set(self, genObj):
7116         "Store one or a list of of SALOME.GenericObj'es"
7117         if isinstance( genObj, list ):
7118             self.genObjList.extend( genObj )
7119         else:
7120             self.genObjList.append( genObj )
7121         return
7122
7123     def __del__(self):
7124         for genObj in self.genObjList:
7125             if genObj and hasattr( genObj, "UnRegister" ):
7126                 genObj.UnRegister()
7127
7128 for pluginName in os.environ[ "SMESH_MeshersList" ].split( ":" ):
7129     """
7130     Bind methods creating mesher plug-ins to the Mesh class
7131     """
7132
7133     # print("pluginName: ", pluginName)
7134     pluginBuilderName = pluginName + "Builder"
7135     try:
7136         exec( "from salome.%s.%s import *" % (pluginName, pluginBuilderName))
7137     except Exception as e:
7138         from salome_utils import verbose
7139         if verbose(): print("Exception while loading %s: %s" % ( pluginBuilderName, e ))
7140         continue
7141     exec( "from salome.%s import %s" % (pluginName, pluginBuilderName))
7142     plugin = eval( pluginBuilderName )
7143     # print("  plugin:" , str(plugin))
7144
7145     # add methods creating algorithms to Mesh
7146     for k in dir( plugin ):
7147         if k[0] == '_': continue
7148         algo = getattr( plugin, k )
7149         #print("             algo:", str(algo))
7150         if inspect.isclass(algo) and hasattr(algo, "meshMethod"):
7151             #print("                     meshMethod:" , str(algo.meshMethod))
7152             if not hasattr( Mesh, algo.meshMethod ):
7153                 setattr( Mesh, algo.meshMethod, algoCreator( algo.meshMethod ))
7154                 pass
7155             _mmethod = getattr( Mesh, algo.meshMethod )
7156             if hasattr(  _mmethod, "add" ):
7157                 _mmethod.add(algo)
7158             pass
7159         pass
7160     pass
7161 del pluginName