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