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