Salome HOME
23080: [CEA 1497] Do not merge a middle node in quadratic with the extreme nodes...
[modules/smesh.git] / src / SMESH_SWIG / smeshBuilder.py
index 74dddbd464b7979f2b3a790ea9bfd9f3cafc1728..c6e1eabb45b8766ef572d75d31cc4f269217b336 100644 (file)
@@ -732,7 +732,7 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
 
         if CritType in [FT_BelongToGeom,     FT_BelongToPlane, FT_BelongToGenSurface,
                         FT_BelongToCylinder, FT_LyingOnGeom]:
-            # Checks that Threshold is GEOM object
+            # Check that Threshold is GEOM object
             if isinstance(aThreshold, geomBuilder.GEOM._objref_GEOM_Object):
                 aCriterion.ThresholdStr = GetName(aThreshold)
                 aCriterion.ThresholdID  = aThreshold.GetStudyEntry()
@@ -745,21 +745,35 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
             elif isinstance( aThreshold, str ):
                 aCriterion.ThresholdStr = aThreshold
             else:
-                print "Error: The Threshold should be a shape."
-                return None
+                raise TypeError, "The Threshold should be a shape."
             if isinstance(UnaryOp,float):
                 aCriterion.Tolerance = UnaryOp
                 UnaryOp = FT_Undefined
                 pass
+        elif CritType == FT_BelongToMeshGroup:
+            # Check that Threshold is a group
+            if isinstance(aThreshold, SMESH._objref_SMESH_GroupBase):
+                if aThreshold.GetType() != elementType:
+                    raise ValueError, "Group type mismatches Element type"
+                aCriterion.ThresholdStr = aThreshold.GetName()
+                aCriterion.ThresholdID  = salome.orb.object_to_string( aThreshold )
+                study = self.GetCurrentStudy()
+                if study:
+                    so = study.FindObjectIOR( aCriterion.ThresholdID )
+                    if so:
+                        entry = so.GetID()
+                        if entry:
+                            aCriterion.ThresholdID = entry
+            else:
+                raise TypeError, "The Threshold should be a Mesh Group"
         elif CritType == FT_RangeOfIds:
-            # Checks that Threshold is string
+            # Check that Threshold is string
             if isinstance(aThreshold, str):
                 aCriterion.ThresholdStr = aThreshold
             else:
-                print "Error: The Threshold should be a string."
-                return None
+                raise TypeError, "The Threshold should be a string."
         elif CritType == FT_CoplanarFaces:
-            # Checks the Threshold
+            # Check the Threshold
             if isinstance(aThreshold, int):
                 aCriterion.ThresholdID = str(aThreshold)
             elif isinstance(aThreshold, str):
@@ -768,10 +782,10 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
                     raise ValueError, "Invalid ID of mesh face: '%s'"%aThreshold
                 aCriterion.ThresholdID = aThreshold
             else:
-                raise ValueError,\
+                raise TypeError,\
                       "The Threshold should be an ID of mesh face and not '%s'"%aThreshold
         elif CritType == FT_ConnectedElements:
-            # Checks the Threshold
+            # Check the Threshold
             if isinstance(aThreshold, geomBuilder.GEOM._objref_GEOM_Object): # shape
                 aCriterion.ThresholdID = aThreshold.GetStudyEntry()
                 if not aCriterion.ThresholdID:
@@ -791,11 +805,11 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
                 else:
                     aCriterion.ThresholdStr = aThreshold # hope that it's point coordinates
             else:
-                raise ValueError,\
+                raise TypeError,\
                       "The Threshold should either a VERTEX, or a node ID, "\
                       "or a list of point coordinates and not '%s'"%aThreshold
         elif CritType == FT_ElemGeomType:
-            # Checks the Threshold
+            # Check the Threshold
             try:
                 aCriterion.Threshold = self.EnumToLong(aThreshold)
                 assert( aThreshold in SMESH.GeometryType._items )
@@ -803,12 +817,11 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
                 if isinstance(aThreshold, int):
                     aCriterion.Threshold = aThreshold
                 else:
-                    print "Error: The Threshold should be an integer or SMESH.GeometryType."
-                    return None
+                    raise TypeError, "The Threshold should be an integer or SMESH.GeometryType."
                 pass
             pass
         elif CritType == FT_EntityType:
-            # Checks the Threshold
+            # Check the Threshold
             try:
                 aCriterion.Threshold = self.EnumToLong(aThreshold)
                 assert( aThreshold in SMESH.EntityType._items )
@@ -816,18 +829,16 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
                 if isinstance(aThreshold, int):
                     aCriterion.Threshold = aThreshold
                 else:
-                    print "Error: The Threshold should be an integer or SMESH.EntityType."
-                    return None
+                    raise TypeError, "The Threshold should be an integer or SMESH.EntityType."
                 pass
             pass
         
         elif CritType == FT_GroupColor:
-            # Checks the Threshold
+            # Check the Threshold
             try:
                 aCriterion.ThresholdStr = self.ColorToString(aThreshold)
             except:
-                print "Error: The threshold value should be of SALOMEDS.Color type"
-                return None
+                raise TypeError, "The threshold value should be of SALOMEDS.Color type"
             pass
         elif CritType in [FT_FreeBorders, FT_FreeEdges, FT_FreeNodes, FT_FreeFaces,
                           FT_LinearOrQuadratic, FT_BadOrientedVolume,
@@ -845,7 +856,7 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
                 aThreshold = float(aThreshold)
                 aCriterion.Threshold = aThreshold
             except:
-                print "Error: The Threshold should be a number."
+                raise TypeError, "The Threshold should be a number."
                 return None
 
         if Threshold ==  FT_LogicalNOT or UnaryOp ==  FT_LogicalNOT:
@@ -2231,11 +2242,11 @@ class Mesh:
     def NbBiQuadQuadrangles(self):
         return self.mesh.NbBiQuadQuadrangles()
 
-    ## Returns the number of polygons in the mesh
+    ## Returns the number of polygons of given order in the mesh
     #  @return an integer value
     #  @ingroup l1_meshinfo
-    def NbPolygons(self):
-        return self.mesh.NbPolygons()
+    def NbPolygons(self, elementOrder = SMESH.ORDER_ANY):
+        return self.mesh.NbPolygons(elementOrder)
 
     ## Returns the number of volumes in the mesh
     #  @return an integer value
@@ -2356,7 +2367,7 @@ class Mesh:
     ## Returns the type of mesh element
     #  @return the value from SMESH::ElementType enumeration
     #  @ingroup l1_meshinfo
-    def GetElementType(self, id, iselem):
+    def GetElementType(self, id, iselem=True):
         return self.mesh.GetElementType(id, iselem)
 
     ## Returns the geometric type of mesh element
@@ -2444,24 +2455,22 @@ class Mesh:
     def GetElementPosition(self,ElemID):
         return self.mesh.GetElementPosition(ElemID)
 
-    ## If the given element is a node, returns the ID of shape
-    #  \n If there is no node for the given ID - returns -1
-    #  @return an integer value
+    ## Returns the ID of the shape, on which the given node was generated.
+    #  @return an integer value > 0 or -1 if there is no node for the given
+    #          ID or the node is not assigned to any geometry
     #  @ingroup l1_meshinfo
     def GetShapeID(self, id):
         return self.mesh.GetShapeID(id)
 
-    ## Returns the ID of the result shape after
-    #  FindShape() from SMESH_MeshEditor for the given element
-    #  \n If there is no element for the given ID - returns -1
-    #  @return an integer value
+    ## Returns the ID of the shape, on which the given element was generated.
+    #  @return an integer value > 0 or -1 if there is no element for the given
+    #          ID or the element is not assigned to any geometry
     #  @ingroup l1_meshinfo
     def GetShapeIDForElem(self,id):
         return self.mesh.GetShapeIDForElem(id)
 
-    ## Returns the number of nodes for the given element
-    #  \n If there is no element for the given ID - returns -1
-    #  @return an integer value
+    ## Returns the number of nodes of the given element
+    #  @return an integer value > 0 or -1 if there is no element for the given ID
     #  @ingroup l1_meshinfo
     def GetElemNbNodes(self, id):
         return self.mesh.GetElemNbNodes(id)
@@ -2487,7 +2496,7 @@ class Mesh:
 
     ## Returns true if the given node is the medium node in one of quadratic elements
     #  @ingroup l1_meshinfo
-    def IsMediumNodeOfAnyElem(self, nodeID, elementType):
+    def IsMediumNodeOfAnyElem(self, nodeID, elementType = SMESH.ALL ):
         return self.mesh.IsMediumNodeOfAnyElem(nodeID, elementType)
 
     ## Returns the number of edges for the given element
@@ -2745,6 +2754,14 @@ class Mesh:
     def AddPolygonalFace(self, IdsOfNodes):
         return self.editor.AddPolygonalFace(IdsOfNodes)
 
+    ## Adds a quadratic polygonal face to the mesh by the list of node IDs
+    #  @param IdsOfNodes the list of node IDs for creation of the element;
+    #         corner nodes follow first.
+    #  @return the Id of the new face
+    #  @ingroup l2_modif_add
+    def AddQuadPolygonalFace(self, IdsOfNodes):
+        return self.editor.AddQuadPolygonalFace(IdsOfNodes)
+
     ## Creates both simple and quadratic volume (this is determined
     #  by the number of given nodes).
     #  @param IDsOfNodes the list of node IDs for creation of the element.
@@ -3979,8 +3996,8 @@ class Mesh:
     ## Creates a symmetrical copy of mesh elements
     #  @param IDsOfElements list of elements ids
     #  @param Mirror is AxisStruct or geom object(point, line, plane)
-    #  @param theMirrorType is  POINT, AXIS or PLANE
-    #  If the Mirror is a geom object this parameter is unnecessary
+    #  @param theMirrorType smeshBuilder.POINT, smeshBuilder.AXIS or smeshBuilder.PLANE
+    #         If the Mirror is a geom object this parameter is unnecessary
     #  @param Copy allows to copy element (Copy is 1) or to replace with its mirroring (Copy is 0)
     #  @param MakeGroups forces the generation of new groups from existing ones (if Copy)
     #  @return list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise
@@ -4001,8 +4018,8 @@ class Mesh:
     ## Creates a new mesh by a symmetrical copy of mesh elements
     #  @param IDsOfElements the list of elements ids
     #  @param Mirror is AxisStruct or geom object (point, line, plane)
-    #  @param theMirrorType is  POINT, AXIS or PLANE
-    #  If the Mirror is a geom object this parameter is unnecessary
+    #  @param theMirrorType smeshBuilder.POINT, smeshBuilder.AXIS or smeshBuilder.PLANE
+    #         If the Mirror is a geom object this parameter is unnecessary
     #  @param MakeGroups to generate new groups from existing ones
     #  @param NewMeshName a name of the new mesh to create
     #  @return instance of Mesh class
@@ -4022,8 +4039,8 @@ class Mesh:
     ## Creates a symmetrical copy of the object
     #  @param theObject mesh, submesh or group
     #  @param Mirror AxisStruct or geom object (point, line, plane)
-    #  @param theMirrorType is  POINT, AXIS or PLANE
-    #  If the Mirror is a geom object this parameter is unnecessary
+    #  @param theMirrorType smeshBuilder.POINT, smeshBuilder.AXIS or smeshBuilder.PLANE
+    #         If the Mirror is a geom object this parameter is unnecessary
     #  @param Copy allows copying the element (Copy is 1) or replacing it with its mirror (Copy is 0)
     #  @param MakeGroups forces the generation of new groups from existing ones (if Copy)
     #  @return list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise
@@ -4044,8 +4061,8 @@ class Mesh:
     ## Creates a new mesh by a symmetrical copy of the object
     #  @param theObject mesh, submesh or group
     #  @param Mirror AxisStruct or geom object (point, line, plane)
-    #  @param theMirrorType POINT, AXIS or PLANE
-    #  If the Mirror is a geom object this parameter is unnecessary
+    #  @param theMirrorType smeshBuilder.POINT, smeshBuilder.AXIS or smeshBuilder.PLANE
+    #         If the Mirror is a geom object this parameter is unnecessary
     #  @param MakeGroups forces the generation of new groups from existing ones
     #  @param NewMeshName the name of the new mesh to create
     #  @return instance of Mesh class
@@ -4282,31 +4299,39 @@ class Mesh:
 
     ## Finds groups of adjacent nodes within Tolerance.
     #  @param Tolerance the value of tolerance
-    #  @return the list of pairs of nodes IDs (e.g. [[1,12],[25,4]])
+    #  @param SeparateCornerAndMediumNodes if @c True, in quadratic mesh puts
+    #         corner and medium nodes in separate groups thus preventing
+    #         their further merge.
+    #  @return the list of groups of nodes IDs (e.g. [[1,12,13],[4,25]])
     #  @ingroup l2_modif_trsf
-    def FindCoincidentNodes (self, Tolerance):
-        return self.editor.FindCoincidentNodes(Tolerance)
+    def FindCoincidentNodes (self, Tolerance, SeparateCornerAndMediumNodes=False):
+        return self.editor.FindCoincidentNodes( Tolerance, SeparateCornerAndMediumNodes )
 
     ## Finds groups of ajacent nodes within Tolerance.
     #  @param Tolerance the value of tolerance
     #  @param SubMeshOrGroup SubMesh or Group
     #  @param exceptNodes list of either SubMeshes, Groups or node IDs to exclude from search
-    #  @return the list of pairs of nodes IDs (e.g. [[1,12],[25,4]])
+    #  @param SeparateCornerAndMediumNodes if @c True, in quadratic mesh puts
+    #         corner and medium nodes in separate groups thus preventing
+    #         their further merge.
+    #  @return the list of groups of nodes IDs (e.g. [[1,12,13],[4,25]])
     #  @ingroup l2_modif_trsf
-    def FindCoincidentNodesOnPart (self, SubMeshOrGroup, Tolerance, exceptNodes=[]):
+    def FindCoincidentNodesOnPart (self, SubMeshOrGroup, Tolerance,
+                                   exceptNodes=[], SeparateCornerAndMediumNodes=False):
         unRegister = genObjUnRegister()
         if (isinstance( SubMeshOrGroup, Mesh )):
             SubMeshOrGroup = SubMeshOrGroup.GetMesh()
-        if not isinstance( exceptNodes, list):
+        if not isinstance( exceptNodes, list ):
             exceptNodes = [ exceptNodes ]
-        if exceptNodes and isinstance( exceptNodes[0], int):
-            exceptNodes = [ self.GetIDSource( exceptNodes, SMESH.NODE)]
+        if exceptNodes and isinstance( exceptNodes[0], int ):
+            exceptNodes = [ self.GetIDSource( exceptNodes, SMESH.NODE )]
             unRegister.set( exceptNodes )
-        return self.editor.FindCoincidentNodesOnPartBut(SubMeshOrGroup, Tolerance,exceptNodes)
+        return self.editor.FindCoincidentNodesOnPartBut(SubMeshOrGroup, Tolerance,
+                                                        exceptNodes, SeparateCornerAndMediumNodes)
 
     ## Merges nodes
-    #  @param GroupsOfNodes a list of pairs of nodes IDs for merging
-    #         (e.g. [[1,12],[25,4]], then nodes 12 and 4 will be removed and replaced
+    #  @param GroupsOfNodes a list of groups of nodes IDs for merging
+    #         (e.g. [[1,12,13],[25,4]], then nodes 12, 13 and 4 will be removed and replaced
     #         by nodes 1 and 25 correspondingly in all elements and groups
     #  @ingroup l2_modif_trsf
     def MergeNodes (self, GroupsOfNodes):
@@ -4314,7 +4339,7 @@ class Mesh:
 
     ## Finds the elements built on the same nodes.
     #  @param MeshOrSubMeshOrGroup Mesh or SubMesh, or Group of elements for searching
-    #  @return the list of pairs of equal elements IDs (e.g. [[1,12],[25,4]])
+    #  @return the list of groups of equal elements IDs (e.g. [[1,12,13],[4,25]])
     #  @ingroup l2_modif_trsf
     def FindEqualElements (self, MeshOrSubMeshOrGroup=None):
         if not MeshOrSubMeshOrGroup:
@@ -4324,8 +4349,8 @@ class Mesh:
         return self.editor.FindEqualElements( MeshOrSubMeshOrGroup )
 
     ## Merges elements in each given group.
-    #  @param GroupsOfElementsID a list of pairs of elements IDs for merging
-    #        (e.g. [[1,12],[25,4]], then elements 12 and 4 will be removed and
+    #  @param GroupsOfElementsID a list of groups of elements IDs for merging
+    #        (e.g. [[1,12,13],[25,4]], then elements 12, 13 and 4 will be removed and
     #        replaced by elements 1 and 25 in all groups)
     #  @ingroup l2_modif_trsf
     def MergeElements(self, GroupsOfElementsID):
@@ -4409,8 +4434,9 @@ class Mesh:
     ## Creates Duplicates given elements, i.e. creates new elements based on the 
     #  same nodes as the given ones.
     #  @param theElements - container of elements to duplicate. It can be a Mesh,
-    #         sub-mesh, group, filter or a list of element IDs.
-    # @param theGroupName - a name of group to contain the generated elements.
+    #         sub-mesh, group, filter or a list of element IDs. If \a theElements is
+    #         a Mesh, elements of highest dimension are duplicated
+    #  @param theGroupName - a name of group to contain the generated elements.
     #                    If a group with such a name already exists, the new elements
     #                    are added to the existng group, else a new group is created.
     #                    If \a theGroupName is empty, new elements are not added