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