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