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