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