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