Back to index

salome-smesh  6.5.0
Public Types | Public Member Functions
SMESH::SMESH_MeshEditor Interface Reference

import "SMESH_MeshEditor.idl";

List of all members.

Public Types

enum  Smooth_Method { LAPLACIAN_SMOOTH, CENTROIDAL_SMOOTH }
enum  Extrusion_Error {
  EXTR_OK, EXTR_NO_ELEMENTS, EXTR_PATH_NOT_EDGE, EXTR_BAD_PATH_SHAPE,
  EXTR_BAD_STARTING_NODE, EXTR_BAD_ANGLES_NUMBER, EXTR_CANT_GET_TANGENT
}
enum  MirrorType { POINT, AXIS, PLANE }
enum  Sew_Error {
  SEW_OK, SEW_BORDER1_NOT_FOUND, SEW_BORDER2_NOT_FOUND, SEW_BOTH_BORDERS_NOT_FOUND,
  SEW_BAD_SIDE_NODES, SEW_VOLUMES_TO_SPLIT, SEW_DIFF_NB_OF_ELEMENTS, SEW_TOPO_DIFF_SETS_OF_ELEMENTS,
  SEW_BAD_SIDE1_NODES, SEW_BAD_SIDE2_NODES
}

Public Member Functions

SMESH_IDSource MakeIDSource (in long_array IDsOfElements, in ElementType type)
 Wrap a sequence of ids in a SMESH_IDSource.
boolean RemoveElements (in long_array IDsOfElements)
 Remove mesh elements specified by their identifiers.
boolean RemoveNodes (in long_array IDsOfNodes)
 Remove mesh nodes specified by their identifiers.
long RemoveOrphanNodes ()
 Remove all orphan nodes.
long AddNode (in double x, in double y, in double z)
 Add new node.
long Add0DElement (in long IDOfNode)
 Create 0D element on the given node.
long AddEdge (in long_array IDsOfNodes)
 Create edge, either linear and quadratic (this is determed by number of given nodes).
long AddFace (in long_array IDsOfNodes)
 Create face, either linear and quadratic (this is determed by number of given nodes).
long AddPolygonalFace (in long_array IdsOfNodes)
long AddVolume (in long_array IDsOfNodes)
 Create volume, either linear and quadratic (this is determed by number of given nodes).
long AddPolyhedralVolume (in long_array IdsOfNodes, in long_array Quantities)
 Create volume of many faces, giving nodes for each face.
long AddPolyhedralVolumeByFaces (in long_array IdsOfFaces)
 Create volume of many faces, giving IDs of existing faces.
void SetNodeOnVertex (in long NodeID, in long VertexID) raises (SALOME::SALOME_Exception)
 Bind a node to a vertex.
void SetNodeOnEdge (in long NodeID, in long EdgeID, in double paramOnEdge) raises (SALOME::SALOME_Exception)
 Store node position on an edge.
void SetNodeOnFace (in long NodeID, in long FaceID, in double u, in double v) raises (SALOME::SALOME_Exception)
 Store node position on a face.
void SetNodeInVolume (in long NodeID, in long SolidID) raises (SALOME::SALOME_Exception)
 Bind a node to a solid.
void SetMeshElementOnShape (in long ElementID, in long ShapeID) raises (SALOME::SALOME_Exception)
 Bind an element to a shape.
boolean MoveNode (in long NodeID, in double x, in double y, in double z)
boolean InverseDiag (in long NodeID1, in long NodeID2)
boolean DeleteDiag (in long NodeID1, in long NodeID2)
boolean Reorient (in long_array IDsOfElements)
boolean ReorientObject (in SMESH_IDSource theObject)
boolean TriToQuad (in long_array IDsOfElements, in NumericalFunctor Criterion, in double MaxAngle)
 Fuse neighbour triangles into quadrangles.
boolean TriToQuadObject (in SMESH_IDSource theObject, in NumericalFunctor Criterion, in double MaxAngle)
 Fuse neighbour triangles into quadrangles.
boolean QuadToTri (in long_array IDsOfElements, in NumericalFunctor Criterion)
 Split quadrangles into triangles.
boolean QuadToTriObject (in SMESH_IDSource theObject, in NumericalFunctor Criterion)
 Split quadrangles into triangles.
boolean SplitQuad (in long_array IDsOfElements, in boolean Diag13)
 Split quadrangles into triangles.
boolean SplitQuadObject (in SMESH_IDSource theObject, in boolean Diag13)
 Split quadrangles into triangles.
long BestSplit (in long IDOfQuad, in NumericalFunctor Criterion)
 Find better splitting of the given quadrangle.
void SplitVolumesIntoTetra (in SMESH_IDSource elems, in short methodFlags) raises (SALOME::SALOME_Exception)
 Split volumic elements into tetrahedrons.
boolean Smooth (in long_array IDsOfElements, in long_array IDsOfFixedNodes, in long MaxNbOfIterations, in double MaxAspectRatio, in Smooth_Method Method)
boolean SmoothObject (in SMESH_IDSource theObject, in long_array IDsOfFixedNodes, in long MaxNbOfIterations, in double MaxAspectRatio, in Smooth_Method Method)
boolean SmoothParametric (in long_array IDsOfElements, in long_array IDsOfFixedNodes, in long MaxNbOfIterations, in double MaxAspectRatio, in Smooth_Method Method)
boolean SmoothParametricObject (in SMESH_IDSource theObject, in long_array IDsOfFixedNodes, in long MaxNbOfIterations, in double MaxAspectRatio, in Smooth_Method Method)
void ConvertToQuadratic (in boolean theForce3d)
 Makes given elements quadratic.
boolean ConvertFromQuadratic ()
 Makes given elements linear.
void ConvertToQuadraticObject (in boolean theForce3d, in SMESH_IDSource theObject) raises (SALOME::SALOME_Exception)
void ConvertFromQuadraticObject (in SMESH_IDSource theObject) raises (SALOME::SALOME_Exception)
void RenumberNodes ()
void RenumberElements ()
void RotationSweep (in long_array IDsOfElements, in AxisStruct Axix, in double AngleInRadians, in long NbOfSteps, in double Tolerance)
 Genarate dim+1 elements by rotation of given elements around axis.
ListOfGroups RotationSweepMakeGroups (in long_array IDsOfElements, in AxisStruct Axix, in double AngleInRadians, in long NbOfSteps, in double Tolerance)
 Same as previous but additionally create groups of elements generated from elements belonging to preexisting groups.
void RotationSweepObject (in SMESH_IDSource theObject, in AxisStruct Axix, in double AngleInRadians, in long NbOfSteps, in double Tolerance)
 Genarate dim+1 elements by rotation of the object around axis.
ListOfGroups RotationSweepObjectMakeGroups (in SMESH_IDSource theObject, in AxisStruct Axix, in double AngleInRadians, in long NbOfSteps, in double Tolerance)
 Same as previous but additionally create groups of elements generated from elements belonging to preexisting groups.
void RotationSweepObject1D (in SMESH_IDSource theObject, in AxisStruct Axix, in double AngleInRadians, in long NbOfSteps, in double Tolerance)
 Genarate dim+1 elements by rotation of the object around axis.
ListOfGroups RotationSweepObject1DMakeGroups (in SMESH_IDSource theObject, in AxisStruct Axix, in double AngleInRadians, in long NbOfSteps, in double Tolerance)
 Same as previous but additionally create groups of elements generated from elements belonging to preexisting groups.
void RotationSweepObject2D (in SMESH_IDSource theObject, in AxisStruct Axix, in double AngleInRadians, in long NbOfSteps, in double Tolerance)
 Genarate dim+1 elements by rotation of the object around axis.
ListOfGroups RotationSweepObject2DMakeGroups (in SMESH_IDSource theObject, in AxisStruct Axix, in double AngleInRadians, in long NbOfSteps, in double Tolerance)
 Same as previous but additionally create groups of elements generated from elements belonging to preexisting groups.
void ExtrusionSweep (in long_array IDsOfElements, in DirStruct StepVector, in long NbOfSteps)
 Genarate dim+1 elements by extrusion of elements along vector.
void ExtrusionSweep0D (in long_array IDsOfElements, in DirStruct StepVector, in long NbOfSteps)
 Genarate dim+1 elements by extrusion of elements along vector.
ListOfGroups ExtrusionSweepMakeGroups (in long_array IDsOfElements, in DirStruct StepVector, in long NbOfSteps)
 Same as previous but additionally create groups of elements generated from elements belonging to preexisting groups.
ListOfGroups ExtrusionSweepMakeGroups0D (in long_array IDsOfElements, in DirStruct StepVector, in long NbOfSteps)
 Same as previous but elements are nodes.
void AdvancedExtrusion (in long_array IDsOfElements, in DirStruct StepVector, in long NbOfSteps, in long ExtrFlags, in double SewTolerance)
 Generate new elements by extrusion of theElements by StepVector by NbOfSteps param ExtrFlags set flags for performing extrusion param SewTolerance - uses for comparing locations of nodes if flag EXTRUSION_FLAG_SEW is set.
ListOfGroups AdvancedExtrusionMakeGroups (in long_array IDsOfElements, in DirStruct StepVector, in long NbOfSteps, in long ExtrFlags, in double SewTolerance)
 Same as previous but additionally create groups of elements generated from elements belonging to preexisting groups.
void ExtrusionSweepObject (in SMESH_IDSource theObject, in DirStruct StepVector, in long NbOfSteps)
ListOfGroups ExtrusionSweepObjectMakeGroups (in SMESH_IDSource theObject, in DirStruct StepVector, in long NbOfSteps)
void ExtrusionSweepObject0D (in SMESH_IDSource theObject, in DirStruct StepVector, in long NbOfSteps)
ListOfGroups ExtrusionSweepObject0DMakeGroups (in SMESH_IDSource theObject, in DirStruct StepVector, in long NbOfSteps)
void ExtrusionSweepObject1D (in SMESH_IDSource theObject, in DirStruct StepVector, in long NbOfSteps)
ListOfGroups ExtrusionSweepObject1DMakeGroups (in SMESH_IDSource theObject, in DirStruct StepVector, in long NbOfSteps)
void ExtrusionSweepObject2D (in SMESH_IDSource theObject, in DirStruct StepVector, in long NbOfSteps)
ListOfGroups ExtrusionSweepObject2DMakeGroups (in SMESH_IDSource theObject, in DirStruct StepVector, in long NbOfSteps)
ListOfGroups ExtrusionAlongPathX (in long_array IDsOfElements, in SMESH_IDSource Path, in long NodeStart, in boolean HasAngles, in double_array Angles, in boolean LinearVariation, in boolean HasRefPoint, in PointStruct RefPoint, in boolean MakeGroups, in ElementType ElemType, out Extrusion_Error Error)
ListOfGroups ExtrusionAlongPathObjX (in SMESH_IDSource theObject, in SMESH_IDSource Path, in long NodeStart, in boolean HasAngles, in double_array Angles, in boolean LinearVariation, in boolean HasRefPoint, in PointStruct RefPoint, in boolean MakeGroups, in ElementType ElemType, out Extrusion_Error Error)
Extrusion_Error ExtrusionAlongPath (in long_array IDsOfElements, in SMESH_Mesh PathMesh, in GEOM::GEOM_Object PathShape, in long NodeStart, in boolean HasAngles, in double_array Angles, in boolean HasRefPoint, in PointStruct RefPoint)
ListOfGroups ExtrusionAlongPathMakeGroups (in long_array IDsOfElements, in SMESH_Mesh PathMesh, in GEOM::GEOM_Object PathShape, in long NodeStart, in boolean HasAngles, in double_array Angles, in boolean HasRefPoint, in PointStruct RefPoint, out Extrusion_Error Error)
Extrusion_Error ExtrusionAlongPathObject (in SMESH_IDSource theObject, in SMESH_Mesh PathMesh, in GEOM::GEOM_Object PathShape, in long NodeStart, in boolean HasAngles, in double_array Angles, in boolean HasRefPoint, in PointStruct RefPoint)
ListOfGroups ExtrusionAlongPathObjectMakeGroups (in SMESH_IDSource theObject, in SMESH_Mesh PathMesh, in GEOM::GEOM_Object PathShape, in long NodeStart, in boolean HasAngles, in double_array Angles, in boolean HasRefPoint, in PointStruct RefPoint, out Extrusion_Error Error)
Extrusion_Error ExtrusionAlongPathObject1D (in SMESH_IDSource theObject, in SMESH_Mesh PathMesh, in GEOM::GEOM_Object PathShape, in long NodeStart, in boolean HasAngles, in double_array Angles, in boolean HasRefPoint, in PointStruct RefPoint)
ListOfGroups ExtrusionAlongPathObject1DMakeGroups (in SMESH_IDSource theObject, in SMESH_Mesh PathMesh, in GEOM::GEOM_Object PathShape, in long NodeStart, in boolean HasAngles, in double_array Angles, in boolean HasRefPoint, in PointStruct RefPoint, out Extrusion_Error Error)
Extrusion_Error ExtrusionAlongPathObject2D (in SMESH_IDSource theObject, in SMESH_Mesh PathMesh, in GEOM::GEOM_Object PathShape, in long NodeStart, in boolean HasAngles, in double_array Angles, in boolean HasRefPoint, in PointStruct RefPoint)
ListOfGroups ExtrusionAlongPathObject2DMakeGroups (in SMESH_IDSource theObject, in SMESH_Mesh PathMesh, in GEOM::GEOM_Object PathShape, in long NodeStart, in boolean HasAngles, in double_array Angles, in boolean HasRefPoint, in PointStruct RefPoint, out Extrusion_Error Error)
double_array LinearAnglesVariation (in SMESH_Mesh PathMesh, in GEOM::GEOM_Object PathShape, in double_array Angles)
 Compute rotation angles for ExtrusionAlongPath as linear variation of given angles along path steps param PathMesh mesh containing a 1D sub-mesh on the edge, along which proceeds the extrusion param PathShape is shape(edge); as the mesh can be complex, the edge is used to define the sub-mesh for the path.
void Mirror (in long_array IDsOfElements, in AxisStruct Mirror, in MirrorType Type, in boolean Copy)
ListOfGroups MirrorMakeGroups (in long_array IDsOfElements, in AxisStruct Mirror, in MirrorType Type)
SMESH_Mesh MirrorMakeMesh (in long_array IDsOfElements, in AxisStruct Mirror, in MirrorType Type, in boolean CopyGroups, in string MeshName)
void MirrorObject (in SMESH_IDSource theObject, in AxisStruct Mirror, in MirrorType Type, in boolean Copy)
ListOfGroups MirrorObjectMakeGroups (in SMESH_IDSource theObject, in AxisStruct Mirror, in MirrorType Type)
SMESH_Mesh MirrorObjectMakeMesh (in SMESH_IDSource theObject, in AxisStruct Mirror, in MirrorType Type, in boolean CopyGroups, in string MeshName)
void Translate (in long_array IDsOfElements, in DirStruct Vector, in boolean Copy)
ListOfGroups TranslateMakeGroups (in long_array IDsOfElements, in DirStruct Vector)
SMESH_Mesh TranslateMakeMesh (in long_array IDsOfElements, in DirStruct Vector, in boolean CopyGroups, in string MeshName)
void TranslateObject (in SMESH_IDSource theObject, in DirStruct Vector, in boolean Copy)
ListOfGroups TranslateObjectMakeGroups (in SMESH_IDSource theObject, in DirStruct Vector)
SMESH_Mesh TranslateObjectMakeMesh (in SMESH_IDSource theObject, in DirStruct Vector, in boolean CopyGroups, in string MeshName)
void Scale (in SMESH_IDSource theObject, in PointStruct thePoint, in double_array theScaleFact, in boolean Copy)
ListOfGroups ScaleMakeGroups (in SMESH_IDSource theObject, in PointStruct thePoint, in double_array theScaleFact)
SMESH_Mesh ScaleMakeMesh (in SMESH_IDSource theObject, in PointStruct thePoint, in double_array theScaleFact, in boolean CopyGroups, in string MeshName)
void Rotate (in long_array IDsOfElements, in AxisStruct Axis, in double AngleInRadians, in boolean Copy)
ListOfGroups RotateMakeGroups (in long_array IDsOfElements, in AxisStruct Axis, in double AngleInRadians)
SMESH_Mesh RotateMakeMesh (in long_array IDsOfElements, in AxisStruct Axis, in double AngleInRadians, in boolean CopyGroups, in string MeshName)
void RotateObject (in SMESH_IDSource theObject, in AxisStruct Axis, in double AngleInRadians, in boolean Copy)
ListOfGroups RotateObjectMakeGroups (in SMESH_IDSource theObject, in AxisStruct Axis, in double AngleInRadians)
SMESH_Mesh RotateObjectMakeMesh (in SMESH_IDSource theObject, in AxisStruct Axis, in double AngleInRadians, in boolean CopyGroups, in string MeshName)
void FindCoincidentNodes (in double Tolerance, out array_of_long_array GroupsOfNodes)
 Return list of group of nodes close to each other within theTolerance Search among theNodes or in the whole mesh if theNodes is empty using an Octree algorithm.
void FindCoincidentNodesOnPart (in SMESH_IDSource SubMeshOrGroup, in double Tolerance, out array_of_long_array GroupsOfNodes)
void FindCoincidentNodesOnPartBut (in SMESH_IDSource SubMeshOrGroup, in double Tolerance, out array_of_long_array GroupsOfNodes, in ListOfIDSources ExceptSubMeshOrGroups)
void MergeNodes (in array_of_long_array GroupsOfNodes)
void FindEqualElements (in SMESH_IDSource MeshOrSubMeshOrGroup, out array_of_long_array GroupsOfElementsID)
 Find elements built on the same nodes.
void MergeElements (in array_of_long_array GroupsOfElementsID)
 Merge elements in each given group.
void MergeEqualElements ()
 Merge equal elements in the whole mesh.
long MoveClosestNodeToPoint (in double x, in double y, in double z, in long nodeID)
 If the given ID is a valid node ID (nodeID > 0), just move this node, else move the node closest to the point to point's location and return ID of the node.
long FindNodeClosestTo (in double x, in double y, in double z)
 Return ID of node closest to a given point.
long_array FindElementsByPoint (in double x, in double y, in double z, in ElementType type)
 Return elements of given type where the given point is IN or ON.
long_array FindAmongElementsByPoint (in SMESH_IDSource elements, in double x, in double y, in double z, in ElementType type)
 Searching among the given elements, return elements of given type where the given point is IN or ON.
short GetPointState (in double x, in double y, in double z)
 Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
Sew_Error SewFreeBorders (in long FirstNodeID1, in long SecondNodeID1, in long LastNodeID1, in long FirstNodeID2, in long SecondNodeID2, in long LastNodeID2, in boolean CreatePolygons, in boolean CreatePolyedrs)
Sew_Error SewConformFreeBorders (in long FirstNodeID1, in long SecondNodeID1, in long LastNodeID1, in long FirstNodeID2, in long SecondNodeID2)
Sew_Error SewBorderToSide (in long FirstNodeIDOnFreeBorder, in long SecondNodeIDOnFreeBorder, in long LastNodeIDOnFreeBorder, in long FirstNodeIDOnSide, in long LastNodeIDOnSide, in boolean CreatePolygons, in boolean CreatePolyedrs)
Sew_Error SewSideElements (in long_array IDsOfSide1Elements, in long_array IDsOfSide2Elements, in long NodeID1OfSide1ToMerge, in long NodeID1OfSide2ToMerge, in long NodeID2OfSide1ToMerge, in long NodeID2OfSide2ToMerge)
boolean ChangeElemNodes (in long ide, in long_array newIDs)
 Set new nodes for given element.
MeshPreviewStruct GetPreviewData ()
 Return data of mesh edition preview which is computed provided that the editor was obtained trough SMESH_Mesh::GetMeshEditPreviewer()
long_array GetLastCreatedNodes ()
 If during last operation of MeshEditor some nodes were created this method returns list of it's IDs, if new nodes not creared - returns empty list.
long_array GetLastCreatedElems ()
 If during last operation of MeshEditor some elements were created this method returns list of it's IDs, if new elements not creared - returns empty list.
boolean DoubleNodes (in long_array theNodes, in long_array theModifiedElems)
 Creates a hole in a mesh by doubling the nodes of some particular elements.
boolean DoubleNode (in long theNodeId, in long_array theModifiedElems)
 Creates a hole in a mesh by doubling the nodes of some particular elements This method provided for convenience works as DoubleNodes() described above.
boolean DoubleNodeGroup (in SMESH_GroupBase theNodes, in SMESH_GroupBase theModifiedElems)
 Creates a hole in a mesh by doubling the nodes of some particular elements This method provided for convenience works as DoubleNodes() described above.
SMESH_Group DoubleNodeGroupNew (in SMESH_GroupBase theNodes, in SMESH_GroupBase theModifiedElems)
 Creates a hole in a mesh by doubling the nodes of some particular elements.
boolean DoubleNodeGroups (in ListOfGroups theNodes, in ListOfGroups theModifiedElems)
 Creates a hole in a mesh by doubling the nodes of some particular elements This method provided for convenience works as DoubleNodes() described above.
SMESH_Group DoubleNodeGroupsNew (in ListOfGroups theNodes, in ListOfGroups theModifiedElems)
 Creates a hole in a mesh by doubling the nodes of some particular elements Works as DoubleNodeGroups() described above, but returns a new group with newly created nodes.
boolean DoubleNodeElem (in long_array theElems, in long_array theNodesNot, in long_array theAffectedElems)
 Creates a hole in a mesh by doubling the nodes of some particular elements.
boolean DoubleNodeElemInRegion (in long_array theElems, in long_array theNodesNot, in GEOM::GEOM_Object theShape)
 Creates a hole in a mesh by doubling the nodes of some particular elements.
boolean DoubleNodeElemGroup (in SMESH_GroupBase theElems, in SMESH_GroupBase theNodesNot, in SMESH_GroupBase theAffectedElems)
 Creates a hole in a mesh by doubling the nodes of some particular elements This method provided for convenience works as DoubleNodes() described above.
SMESH_Group DoubleNodeElemGroupNew (in SMESH_GroupBase theElems, in SMESH_GroupBase theNodesNot, in SMESH_GroupBase theAffectedElems)
 Creates a hole in a mesh by doubling the nodes of some particular elements.
ListOfGroups DoubleNodeElemGroup2New (in SMESH_GroupBase theElems, in SMESH_GroupBase theNodesNot, in SMESH_GroupBase theAffectedElems, in boolean theElemGroupNeeded, in boolean theNodeGroupNeeded)
 Creates a hole in a mesh by doubling the nodes of some particular elements.
boolean DoubleNodeElemGroupInRegion (in SMESH_GroupBase theElems, in SMESH_GroupBase theNodesNot, in GEOM::GEOM_Object theShape)
 Creates a hole in a mesh by doubling the nodes of some particular elements This method provided for convenience works as DoubleNodes() described above.
boolean DoubleNodeElemGroups (in ListOfGroups theElems, in ListOfGroups theNodesNot, in ListOfGroups theAffectedElems)
 Creates a hole in a mesh by doubling the nodes of some particular elements This method provided for convenience works as DoubleNodes() described above.
SMESH_Group DoubleNodeElemGroupsNew (in ListOfGroups theElems, in ListOfGroups theNodesNot, in ListOfGroups theAffectedElems)
 Creates a hole in a mesh by doubling the nodes of some particular elements.
ListOfGroups DoubleNodeElemGroups2New (in ListOfGroups theElems, in ListOfGroups theNodesNot, in ListOfGroups theAffectedElems, in boolean theElemGroupNeeded, in boolean theNodeGroupNeeded)
 Creates a hole in a mesh by doubling the nodes of some particular elements.
boolean DoubleNodeElemGroupsInRegion (in ListOfGroups theElems, in ListOfGroups theNodesNot, in GEOM::GEOM_Object theShape)
 Creates a hole in a mesh by doubling the nodes of some particular elements This method provided for convenience works as DoubleNodes() described above.
boolean Make2DMeshFrom3D ()
 Generates skin mesh (containing 2D cells) from 3D mesh The created 2D mesh elements based on nodes of free faces of boundary volumes.
SMESH_Mesh MakeBoundaryMesh (in SMESH_IDSource elements, in Bnd_Dimension dimension, in string groupName, in string meshName, in boolean toCopyElements, in boolean toCopyExistingBondary, out SMESH_Group group)
 Creates missing boundary elements.
long MakeBoundaryElements (in Bnd_Dimension dimension, in string groupName, in string meshName, in boolean toCopyAll, in ListOfIDSources groups, out SMESH_Mesh mesh, out SMESH_Group group) raises (SALOME::SALOME_Exception)
 Creates missing boundary elements around either the whole mesh or groups of 2D elements.
boolean DoubleNodesOnGroupBoundaries (in ListOfGroups theDomains, in boolean createJointElems) raises (SALOME::SALOME_Exception)
 Double nodes on shared faces between groups of volumes and create flat elements on demand.
boolean CreateFlatElementsOnFacesGroups (in ListOfGroups theGroupsOfFaces)
 Double nodes on some external faces and create flat elements.

Detailed Description

Definition at line 37 of file SMESH_MeshEditor.idl.


Member Enumeration Documentation

Enumerator:
EXTR_OK 
EXTR_NO_ELEMENTS 
EXTR_PATH_NOT_EDGE 
EXTR_BAD_PATH_SHAPE 
EXTR_BAD_STARTING_NODE 
EXTR_BAD_ANGLES_NUMBER 
EXTR_CANT_GET_TANGENT 

Definition at line 463 of file SMESH_MeshEditor.idl.

Enumerator:
POINT 
AXIS 
PLANE 

Definition at line 581 of file SMESH_MeshEditor.idl.

{ POINT, AXIS, PLANE };
Enumerator:
SEW_OK 
SEW_BORDER1_NOT_FOUND 
SEW_BORDER2_NOT_FOUND 
SEW_BOTH_BORDERS_NOT_FOUND 
SEW_BAD_SIDE_NODES 
SEW_VOLUMES_TO_SPLIT 
SEW_DIFF_NB_OF_ELEMENTS 
SEW_TOPO_DIFF_SETS_OF_ELEMENTS 
SEW_BAD_SIDE1_NODES 
SEW_BAD_SIDE2_NODES 

Definition at line 735 of file SMESH_MeshEditor.idl.

Enumerator:
LAPLACIAN_SMOOTH 
CENTROIDAL_SMOOTH 

Definition at line 257 of file SMESH_MeshEditor.idl.


Member Function Documentation

long SMESH::SMESH_MeshEditor::Add0DElement ( in long  IDOfNode)

Create 0D element on the given node.

Parameters:
IdOfNodeNode IDs for creation of element.

Create edge, either linear and quadratic (this is determed by number of given nodes).

Parameters:
IdsOfNodesList of node IDs for creation of element. Needed order of nodes in this list corresponds to description of MED. This description is located by the following link: http://www.salome-platform.org/salome2/web_med_internet/logiciels/medV2.2.2_doc_html/html/modele_de_donnees.html#3.

Create face, either linear and quadratic (this is determed by number of given nodes).

Parameters:
IdsOfNodesList of node IDs for creation of element. Needed order of nodes in this list corresponds to description of MED. This description is located by the following link: http://www.salome-platform.org/salome2/web_med_internet/logiciels/medV2.2.2_doc_html/html/modele_de_donnees.html#3.
long SMESH::SMESH_MeshEditor::AddNode ( in double  x,
in double  y,
in double  z 
)

Add new node.

Parameters:
xX coordinate of new node
yY coordinate of new node
zZ coordinate of new node
Returns:
integer identifier of new node
long SMESH::SMESH_MeshEditor::AddPolyhedralVolume ( in long_array  IdsOfNodes,
in long_array  Quantities 
)

Create volume of many faces, giving nodes for each face.

Parameters:
IdsOfNodesList of node IDs for volume creation face by face.
QuantitiesList of integer values, Quantities[i] gives quantity of nodes in face number i.

Create volume of many faces, giving IDs of existing faces.

Parameters:
IdsOfFacesList of face IDs for volume creation.
Note:
The created volume will refer only to nodes of the given faces, not to the faces itself.

Create volume, either linear and quadratic (this is determed by number of given nodes).

Parameters:
IdsOfNodesList of node IDs for creation of element. Needed order of nodes in this list corresponds to description of MED. This description is located by the following link: http://www.salome-platform.org/salome2/web_med_internet/logiciels/medV2.2.2_doc_html/html/modele_de_donnees.html#3.
void SMESH::SMESH_MeshEditor::AdvancedExtrusion ( in long_array  IDsOfElements,
in DirStruct  StepVector,
in long  NbOfSteps,
in long  ExtrFlags,
in double  SewTolerance 
)

Generate new elements by extrusion of theElements by StepVector by NbOfSteps param ExtrFlags set flags for performing extrusion param SewTolerance - uses for comparing locations of nodes if flag EXTRUSION_FLAG_SEW is set.

ListOfGroups SMESH::SMESH_MeshEditor::AdvancedExtrusionMakeGroups ( in long_array  IDsOfElements,
in DirStruct  StepVector,
in long  NbOfSteps,
in long  ExtrFlags,
in double  SewTolerance 
)

Same as previous but additionally create groups of elements generated from elements belonging to preexisting groups.

int SMESH_MeshEditor::BestSplit ( in long  IDOfQuad,
in NumericalFunctor  Criterion 
)

Find better splitting of the given quadrangle.

Parameters:
IDOfQuadID of the quadrangle to be splitted.
CriterionA criterion to choose a diagonal for splitting.
Returns:
1 if 1-3 diagonal is better, 2 if 2-4 diagonal is better, 0 if error occurs.

Definition at line 1221 of file SMESH_MeshEditor.cxx.

{
  myLastCreatedElems.Clear();
  myLastCreatedNodes.Clear();

  if (!theCrit.get())
    return -1;

  if (!theQuad || theQuad->GetType() != SMDSAbs_Face )
    return -1;

  if( theQuad->NbNodes()==4 ||
      (theQuad->NbNodes()==8 && theQuad->IsQuadratic()) ) {

    // retrieve element nodes
    const SMDS_MeshNode* aNodes [4];
    SMDS_ElemIteratorPtr itN = theQuad->nodesIterator();
    int i = 0;
    //while (itN->more())
    while (i<4) {
      aNodes[ i++ ] = static_cast<const SMDS_MeshNode*>( itN->next() );
    }
    // compare two sets of possible triangles
    double aBadRate1, aBadRate2; // to what extent a set is bad
    SMDS_FaceOfNodes tr1 ( aNodes[0], aNodes[1], aNodes[2] );
    SMDS_FaceOfNodes tr2 ( aNodes[2], aNodes[3], aNodes[0] );
    aBadRate1 = getBadRate( &tr1, theCrit ) + getBadRate( &tr2, theCrit );

    SMDS_FaceOfNodes tr3 ( aNodes[1], aNodes[2], aNodes[3] );
    SMDS_FaceOfNodes tr4 ( aNodes[3], aNodes[0], aNodes[1] );
    aBadRate2 = getBadRate( &tr3, theCrit ) + getBadRate( &tr4, theCrit );

    if (aBadRate1 <= aBadRate2) // tr1 + tr2 is better
      return 1; // diagonal 1-3

    return 2; // diagonal 2-4
  }
  return -1;
}

Here is the call graph for this function:

boolean SMESH::SMESH_MeshEditor::ChangeElemNodes ( in long  ide,
in long_array  newIDs 
)

Set new nodes for given element.

If number of nodes is not corresponded to type of element - returns false

Makes given elements linear.

Definition at line 9424 of file SMESH_MeshEditor.cxx.

{
  int nbCheckedElems = 0;
  if ( myMesh->HasShapeToMesh() )
  {
    if ( SMESH_subMesh *aSubMesh = myMesh->GetSubMeshContaining(myMesh->GetShapeToMesh()))
    {
      SMESH_subMeshIteratorPtr smIt = aSubMesh->getDependsOnIterator(true,false);
      while ( smIt->more() ) {
        SMESH_subMesh* sm = smIt->next();
        if ( SMESHDS_SubMesh *smDS = sm->GetSubMeshDS() )
          nbCheckedElems += removeQuadElem( smDS, smDS->GetElements(), sm->GetId() );
      }
    }
  }

  int totalNbElems =
    GetMeshDS()->NbEdges() + GetMeshDS()->NbFaces() + GetMeshDS()->NbVolumes();
  if ( nbCheckedElems < totalNbElems ) // not all elements are in submeshes
  {
    SMESHDS_SubMesh *aSM = 0;
    removeQuadElem( aSM, GetMeshDS()->elementsIterator(), 0 );
  }

  return true;
}

Here is the call graph for this function:

void SMESH::SMESH_MeshEditor::ConvertFromQuadraticObject ( in SMESH_IDSource  theObject) raises (SALOME::SALOME_Exception)
void SMESH_MeshEditor::ConvertToQuadratic ( in boolean  theForce3d)

Makes given elements quadratic.

Parameters:
theForce3d- if true, the medium nodes will be placed in the middle of link
theElements- elements to make quadratic

Definition at line 9113 of file SMESH_MeshEditor.cxx.

{
  SMESHDS_Mesh* meshDS = GetMeshDS();

  SMESH_MesherHelper aHelper(*myMesh);
  aHelper.SetIsQuadratic( true );

  int nbCheckedElems = 0;
  if ( myMesh->HasShapeToMesh() )
  {
    if ( SMESH_subMesh *aSubMesh = myMesh->GetSubMeshContaining(myMesh->GetShapeToMesh()))
    {
      SMESH_subMeshIteratorPtr smIt = aSubMesh->getDependsOnIterator(true,false);
      while ( smIt->more() ) {
        SMESH_subMesh* sm = smIt->next();
        if ( SMESHDS_SubMesh *smDS = sm->GetSubMeshDS() ) {
          aHelper.SetSubShape( sm->GetSubShape() );
          nbCheckedElems += convertElemToQuadratic(smDS, aHelper, theForce3d);
        }
      }
    }
  }
  int totalNbElems = meshDS->NbEdges() + meshDS->NbFaces() + meshDS->NbVolumes();
  if ( nbCheckedElems < totalNbElems ) // not all elements are in submeshes
  {
    SMESHDS_SubMesh *smDS = 0;
    SMDS_EdgeIteratorPtr aEdgeItr = meshDS->edgesIterator();
    while(aEdgeItr->more())
    {
      const SMDS_MeshEdge* edge = aEdgeItr->next();
      if(edge && !edge->IsQuadratic())
      {
        int id = edge->GetID();
        //MESSAGE("edge->GetID() " << id);
        const SMDS_MeshNode* n1 = edge->GetNode(0);
        const SMDS_MeshNode* n2 = edge->GetNode(1);

        meshDS->RemoveFreeElement(edge, smDS, /*fromGroups=*/false);

        const SMDS_MeshEdge* NewEdge = aHelper.AddEdge(n1, n2, id, theForce3d);
        ReplaceElemInGroups( edge, NewEdge, GetMeshDS());
      }
    }
    SMDS_FaceIteratorPtr aFaceItr = meshDS->facesIterator();
    while(aFaceItr->more())
    {
      const SMDS_MeshFace* face = aFaceItr->next();
      if(!face || face->IsQuadratic() ) continue;

      const int id = face->GetID();
      const SMDSAbs_EntityType type = face->GetEntityType();
      vector<const SMDS_MeshNode *> nodes ( face->begin_nodes(), face->end_nodes());

      meshDS->RemoveFreeElement(face, smDS, /*fromGroups=*/false);

      SMDS_MeshFace * NewFace = 0;
      switch( type )
      {
      case SMDSEntity_Triangle:
        NewFace = aHelper.AddFace(nodes[0], nodes[1], nodes[2], id, theForce3d);
        break;
      case SMDSEntity_Quadrangle:
        NewFace = aHelper.AddFace(nodes[0], nodes[1], nodes[2], nodes[3], id, theForce3d);
        break;
      default:
        NewFace = aHelper.AddPolygonalFace(nodes, id, theForce3d);
      }
      ReplaceElemInGroups( face, NewFace, GetMeshDS());
    }
    vector<int> nbNodeInFaces;
    SMDS_VolumeIteratorPtr aVolumeItr = meshDS->volumesIterator();
    while(aVolumeItr->more())
    {
      const SMDS_MeshVolume* volume = aVolumeItr->next();
      if(!volume || volume->IsQuadratic() ) continue;

      const int id = volume->GetID();
      const SMDSAbs_EntityType type = volume->GetEntityType();
      vector<const SMDS_MeshNode *> nodes (volume->begin_nodes(), volume->end_nodes());
      if ( type == SMDSEntity_Polyhedra )
        nbNodeInFaces = static_cast<const SMDS_VtkVolume* >(volume)->GetQuantities();
      else if ( type == SMDSEntity_Hexagonal_Prism )
        volumeToPolyhedron( volume, nodes, nbNodeInFaces );

      meshDS->RemoveFreeElement(volume, smDS, /*fromGroups=*/false);

      SMDS_MeshVolume * NewVolume = 0;
      switch ( type )
      {
      case SMDSEntity_Tetra:
        NewVolume = aHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], id, theForce3d );
        break;
      case SMDSEntity_Hexa:
        NewVolume = aHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3],
                                      nodes[4], nodes[5], nodes[6], nodes[7], id, theForce3d);
        break;
      case SMDSEntity_Pyramid:
        NewVolume = aHelper.AddVolume(nodes[0], nodes[1], nodes[2],
                                      nodes[3], nodes[4], id, theForce3d);
        break;
      case SMDSEntity_Penta:
        NewVolume = aHelper.AddVolume(nodes[0], nodes[1], nodes[2],
                                      nodes[3], nodes[4], nodes[5], id, theForce3d);
        break;
      case SMDSEntity_Hexagonal_Prism:
      default:
        NewVolume = aHelper.AddPolyhedralVolume(nodes, nbNodeInFaces, id, theForce3d);
      }
      ReplaceElemInGroups(volume, NewVolume, meshDS);
    }
  }

  if ( !theForce3d )
  { // setenv NO_FixQuadraticElements to know if FixQuadraticElements() is guilty of bad conversion
    aHelper.SetSubShape(0); // apply FixQuadraticElements() to the whole mesh
    aHelper.FixQuadraticElements();
  }
}

Here is the call graph for this function:

void SMESH::SMESH_MeshEditor::ConvertToQuadraticObject ( in boolean  theForce3d,
in SMESH_IDSource  theObject 
) raises (SALOME::SALOME_Exception)

Double nodes on some external faces and create flat elements.

Flat elements are mainly used by some types of mechanic calculations.

Each group of the list must be constituted of faces. Triangles are transformed in prisms, and quadrangles in hexahedrons.

Parameters:
theGroupsOfFaces- list of groups of faces
Returns:
TRUE if operation has been completed successfully, FALSE otherwise

Flat elements are mainly used by some types of mechanic calculations.

Each group of the list must be constituted of faces. Triangles are transformed in prisms, and quadrangles in hexahedrons.

Parameters:
theElems- list of groups of faces, where a group of faces is a set of SMDS_MeshElements sorted by Id.
Returns:
TRUE if operation has been completed successfully, FALSE otherwise

Definition at line 11093 of file SMESH_MeshEditor.cxx.

{
  MESSAGE("-------------------------------------------------");
  MESSAGE("SMESH_MeshEditor::CreateFlatElementsOnFacesGroups");
  MESSAGE("-------------------------------------------------");

  SMESHDS_Mesh *meshDS = this->myMesh->GetMeshDS();

  // --- For each group of faces
  //     duplicate the nodes, create a flat element based on the face
  //     replace the nodes of the faces by their clones

  std::map<const SMDS_MeshNode*, const SMDS_MeshNode*> clonedNodes;
  std::map<const SMDS_MeshNode*, const SMDS_MeshNode*> intermediateNodes;
  clonedNodes.clear();
  intermediateNodes.clear();
  std::map<std::string, SMESH_Group*> mapOfJunctionGroups;
  mapOfJunctionGroups.clear();

  for (int idom = 0; idom < theElems.size(); idom++)
    {
      const TIDSortedElemSet& domain = theElems[idom];
      TIDSortedElemSet::const_iterator elemItr = domain.begin();
      for (; elemItr != domain.end(); ++elemItr)
        {
          SMDS_MeshElement* anElem = (SMDS_MeshElement*) *elemItr;
          SMDS_MeshFace* aFace = dynamic_cast<SMDS_MeshFace*> (anElem);
          if (!aFace)
            continue;
          // MESSAGE("aFace=" << aFace->GetID());
          bool isQuad = aFace->IsQuadratic();
          vector<const SMDS_MeshNode*> ln0, ln1, ln2, ln3, ln4;

          // --- clone the nodes, create intermediate nodes for non medium nodes of a quad face

          SMDS_ElemIteratorPtr nodeIt = aFace->nodesIterator();
          while (nodeIt->more())
            {
              const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*> (nodeIt->next());
              bool isMedium = isQuad && (aFace->IsMediumNode(node));
              if (isMedium)
                ln2.push_back(node);
              else
                ln0.push_back(node);

              const SMDS_MeshNode* clone = 0;
              if (!clonedNodes.count(node))
                {
                  clone = meshDS->AddNode(node->X(), node->Y(), node->Z());
                  clonedNodes[node] = clone;
                }
              else
                clone = clonedNodes[node];

              if (isMedium)
                ln3.push_back(clone);
              else
                ln1.push_back(clone);

              const SMDS_MeshNode* inter = 0;
              if (isQuad && (!isMedium))
                {
                  if (!intermediateNodes.count(node))
                    {
                      inter = meshDS->AddNode(node->X(), node->Y(), node->Z());
                      intermediateNodes[node] = inter;
                    }
                  else
                    inter = intermediateNodes[node];
                  ln4.push_back(inter);
                }
            }

          // --- extrude the face

          vector<const SMDS_MeshNode*> ln;
          SMDS_MeshVolume* vol = 0;
          vtkIdType aType = aFace->GetVtkType();
          switch (aType)
          {
            case VTK_TRIANGLE:
              vol = meshDS->AddVolume(ln0[2], ln0[1], ln0[0], ln1[2], ln1[1], ln1[0]);
              // MESSAGE("vol prism " << vol->GetID());
              ln.push_back(ln1[0]);
              ln.push_back(ln1[1]);
              ln.push_back(ln1[2]);
              break;
            case VTK_QUAD:
              vol = meshDS->AddVolume(ln0[3], ln0[2], ln0[1], ln0[0], ln1[3], ln1[2], ln1[1], ln1[0]);
              // MESSAGE("vol hexa " << vol->GetID());
              ln.push_back(ln1[0]);
              ln.push_back(ln1[1]);
              ln.push_back(ln1[2]);
              ln.push_back(ln1[3]);
              break;
            case VTK_QUADRATIC_TRIANGLE:
              vol = meshDS->AddVolume(ln1[0], ln1[1], ln1[2], ln0[0], ln0[1], ln0[2], ln3[0], ln3[1], ln3[2],
                                      ln2[0], ln2[1], ln2[2], ln4[0], ln4[1], ln4[2]);
              // MESSAGE("vol quad prism " << vol->GetID());
              ln.push_back(ln1[0]);
              ln.push_back(ln1[1]);
              ln.push_back(ln1[2]);
              ln.push_back(ln3[0]);
              ln.push_back(ln3[1]);
              ln.push_back(ln3[2]);
              break;
            case VTK_QUADRATIC_QUAD:
//              vol = meshDS->AddVolume(ln0[0], ln0[1], ln0[2], ln0[3], ln1[0], ln1[1], ln1[2], ln1[3],
//                                      ln2[0], ln2[1], ln2[2], ln2[3], ln3[0], ln3[1], ln3[2], ln3[3],
//                                      ln4[0], ln4[1], ln4[2], ln4[3]);
              vol = meshDS->AddVolume(ln1[0], ln1[1], ln1[2], ln1[3], ln0[0], ln0[1], ln0[2], ln0[3],
                                      ln3[0], ln3[1], ln3[2], ln3[3], ln2[0], ln2[1], ln2[2], ln2[3],
                                      ln4[0], ln4[1], ln4[2], ln4[3]);
              // MESSAGE("vol quad hexa " << vol->GetID());
              ln.push_back(ln1[0]);
              ln.push_back(ln1[1]);
              ln.push_back(ln1[2]);
              ln.push_back(ln1[3]);
              ln.push_back(ln3[0]);
              ln.push_back(ln3[1]);
              ln.push_back(ln3[2]);
              ln.push_back(ln3[3]);
              break;
            case VTK_POLYGON:
              break;
            default:
              break;
          }

          if (vol)
            {
              stringstream grpname;
              grpname << "jf_";
              grpname << idom;
              int idg;
              string namegrp = grpname.str();
              if (!mapOfJunctionGroups.count(namegrp))
                mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Volume, namegrp.c_str(), idg);
              SMESHDS_Group *sgrp = dynamic_cast<SMESHDS_Group*>(mapOfJunctionGroups[namegrp]->GetGroupDS());
              if (sgrp)
                sgrp->Add(vol->GetID());
            }

          // --- modify the face

          aFace->ChangeNodes(&ln[0], ln.size());
        }
    }
  return true;
}

Here is the call graph for this function:

bool SMESH_MeshEditor::DeleteDiag ( in long  NodeID1,
in long  NodeID2 
)

Definition at line 865 of file SMESH_MeshEditor.cxx.

{
  myLastCreatedElems.Clear();
  myLastCreatedNodes.Clear();

  MESSAGE( "::DeleteDiag()" );

  const SMDS_MeshElement *tr1, *tr2;
  if ( !findTriangles( theNode1, theNode2, tr1, tr2 ))
    return false;

  const SMDS_VtkFace* F1 = dynamic_cast<const SMDS_VtkFace*>( tr1 );
  if (!F1) return false;
  const SMDS_VtkFace* F2 = dynamic_cast<const SMDS_VtkFace*>( tr2 );
  if (!F2) return false;
  SMESHDS_Mesh * aMesh = GetMeshDS();

  if ((tr1->GetEntityType() == SMDSEntity_Triangle) &&
      (tr2->GetEntityType() == SMDSEntity_Triangle)) {

    const SMDS_MeshNode* aNodes [ 4 ];
    if ( ! getQuadrangleNodes( aNodes, theNode1, theNode2, tr1, tr2 ))
      return false;

    const SMDS_MeshElement* newElem = 0;
    newElem = aMesh->AddFace( aNodes[0], aNodes[1], aNodes[2], aNodes[3] );
    myLastCreatedElems.Append(newElem);
    AddToSameGroups( newElem, tr1, aMesh );
    int aShapeId = tr1->getshapeId();
    if ( aShapeId )
      {
        aMesh->SetMeshElementOnShape( newElem, aShapeId );
      }
    aMesh->RemoveElement( tr1 );
    aMesh->RemoveElement( tr2 );

    return true;
  }

  // check case of quadratic faces
  if (tr1->GetEntityType() != SMDSEntity_Quad_Triangle)
    return false;
  if (tr2->GetEntityType() != SMDSEntity_Quad_Triangle)
    return false;

  //       5
  //  1 +--+--+ 2  tr1: (1 2 4 5 9 7) or (2 4 1 9 7 5) or (4 1 2 7 5 9)
  //    |    /|    tr2: (2 3 4 6 8 9) or (3 4 2 8 9 6) or (4 2 3 9 6 8)
  //    |   / |
  //  7 +  +  + 6
  //    | /9  |
  //    |/    |
  //  4 +--+--+ 3
  //       8

  const SMDS_MeshNode* N1 [6];
  const SMDS_MeshNode* N2 [6];
  if(!GetNodesFromTwoTria(tr1,tr2,N1,N2))
    return false;
  // now we receive following N1 and N2 (using numeration as above image)
  // tria1 : (1 2 4 5 9 7)  and  tria2 : (3 4 2 8 9 6)
  // i.e. first nodes from both arrays determ new diagonal

  const SMDS_MeshNode* aNodes[8];
  aNodes[0] = N1[0];
  aNodes[1] = N1[1];
  aNodes[2] = N2[0];
  aNodes[3] = N2[1];
  aNodes[4] = N1[3];
  aNodes[5] = N2[5];
  aNodes[6] = N2[3];
  aNodes[7] = N1[5];

  const SMDS_MeshElement* newElem = 0;
  newElem = aMesh->AddFace( aNodes[0], aNodes[1], aNodes[2], aNodes[3],
                            aNodes[4], aNodes[5], aNodes[6], aNodes[7]);
  myLastCreatedElems.Append(newElem);
  AddToSameGroups( newElem, tr1, aMesh );
  int aShapeId = tr1->getshapeId();
  if ( aShapeId )
    {
      aMesh->SetMeshElementOnShape( newElem, aShapeId );
    }
  aMesh->RemoveElement( tr1 );
  aMesh->RemoveElement( tr2 );

  // remove middle node (9)
  GetMeshDS()->RemoveNode( N1[4] );

  return true;
}

Here is the call graph for this function:

boolean SMESH::SMESH_MeshEditor::DoubleNode ( in long  theNodeId,
in long_array  theModifiedElems 
)

Creates a hole in a mesh by doubling the nodes of some particular elements This method provided for convenience works as DoubleNodes() described above.

Parameters:
theNodeId- identifier of node to be doubled.
theModifiedElems- identifiers of elements to be updated.
Returns:
TRUE if operation has been completed successfully, FALSE otherwise
See also:
DoubleNodes(), DoubleNodeGroup(), DoubleNodeGroups()
boolean SMESH::SMESH_MeshEditor::DoubleNodeElem ( in long_array  theElems,
in long_array  theNodesNot,
in long_array  theAffectedElems 
)

Creates a hole in a mesh by doubling the nodes of some particular elements.

Parameters:
theElems- the list of elements (edges or faces) to be replicated The nodes for duplication could be found from these elements
theNodesNot- list of nodes to NOT replicate
theAffectedElems- the list of elements (cells and edges) to which the replicated nodes should be associated to.
Returns:
TRUE if operation has been completed successfully, FALSE otherwise
See also:
DoubleNodeGroup(), DoubleNodeGroups()
boolean SMESH::SMESH_MeshEditor::DoubleNodeElemGroup ( in SMESH_GroupBase  theElems,
in SMESH_GroupBase  theNodesNot,
in SMESH_GroupBase  theAffectedElems 
)

Creates a hole in a mesh by doubling the nodes of some particular elements This method provided for convenience works as DoubleNodes() described above.

Parameters:
theElems- group of of elements (edges or faces) to be replicated
theNodesNot- group of nodes not to replicated
theAffectedElems- group of elements to which the replicated nodes should be associated to.
Returns:
TRUE if operation has been completed successfully, FALSE otherwise
See also:
DoubleNodes(), DoubleNodeGroups(), DoubleNodeElemGroupNew()
ListOfGroups SMESH::SMESH_MeshEditor::DoubleNodeElemGroup2New ( in SMESH_GroupBase  theElems,
in SMESH_GroupBase  theNodesNot,
in SMESH_GroupBase  theAffectedElems,
in boolean  theElemGroupNeeded,
in boolean  theNodeGroupNeeded 
)

Creates a hole in a mesh by doubling the nodes of some particular elements.

Works as DoubleNodeElemGroup() described above, but returns two new groups: a group of newly created elements and a group of newly created nodes

Parameters:
theElems- group of of elements (edges or faces) to be replicated
theNodesNot- group of nodes not to replicated
theAffectedElems- group of elements to which the replicated nodes should be associated to.
theElemGroupNeeded- to create group of new elements or not
theNodeGroupNeeded- to create group of new nodes or not
Returns:
two new groups of newly created elements (1st) and nodes (2nd)
See also:
DoubleNodeElemGroup()
boolean SMESH::SMESH_MeshEditor::DoubleNodeElemGroupInRegion ( in SMESH_GroupBase  theElems,
in SMESH_GroupBase  theNodesNot,
in GEOM::GEOM_Object  theShape 
)

Creates a hole in a mesh by doubling the nodes of some particular elements This method provided for convenience works as DoubleNodes() described above.

Parameters:
theElems- group of elements (edges or faces) to be replicated
theNodesNot- group of nodes not to replicated
theShape- shape to detect affected elements (element which geometric center located on or inside shape). The replicated nodes should be associated to affected elements.
Returns:
TRUE if operation has been completed successfully, FALSE otherwise
See also:
DoubleNodesInRegion(), DoubleNodeGroupsInRegion()

Creates a hole in a mesh by doubling the nodes of some particular elements.

Works as DoubleNodeElemGroup() described above, but returns a new group with newly created elements.

Parameters:
theElems- group of of elements (edges or faces) to be replicated
theNodesNot- group of nodes not to replicated
theAffectedElems- group of elements to which the replicated nodes should be associated to.
Returns:
a new group with newly created elements
See also:
DoubleNodeElemGroup()
boolean SMESH::SMESH_MeshEditor::DoubleNodeElemGroups ( in ListOfGroups  theElems,
in ListOfGroups  theNodesNot,
in ListOfGroups  theAffectedElems 
)

Creates a hole in a mesh by doubling the nodes of some particular elements This method provided for convenience works as DoubleNodes() described above.

Parameters:
theElems- list of groups of elements (edges or faces) to be replicated
theNodesNot- list of groups of nodes not to replicated
theAffectedElems- group of elements to which the replicated nodes should be associated to.
Returns:
TRUE if operation has been completed successfully, FALSE otherwise
See also:
DoubleNodeGroup(), DoubleNodes(), DoubleNodeElemGroupsNew()
ListOfGroups SMESH::SMESH_MeshEditor::DoubleNodeElemGroups2New ( in ListOfGroups  theElems,
in ListOfGroups  theNodesNot,
in ListOfGroups  theAffectedElems,
in boolean  theElemGroupNeeded,
in boolean  theNodeGroupNeeded 
)

Creates a hole in a mesh by doubling the nodes of some particular elements.

Works as DoubleNodeElemGroups() described above, but returns two new groups: a group of newly created elements and a group of newly created nodes.

Parameters:
theElems- list of groups of elements (edges or faces) to be replicated
theNodesNot- list of groups of nodes not to replicated
theAffectedElems- group of elements to which the replicated nodes should be associated to.
theElemGroupNeeded- to create group of new elements or not
theNodeGroupNeeded- to create group of new nodes or not
Returns:
two new groups of newly created elements (1st) and nodes (2nd)
See also:
DoubleNodeElemGroups()
boolean SMESH::SMESH_MeshEditor::DoubleNodeElemGroupsInRegion ( in ListOfGroups  theElems,
in ListOfGroups  theNodesNot,
in GEOM::GEOM_Object  theShape 
)

Creates a hole in a mesh by doubling the nodes of some particular elements This method provided for convenience works as DoubleNodes() described above.

Parameters:
theElems- list of groups of elements (edges or faces) to be replicated
theNodesNot- list of groups of nodes not to replicated
theShape- shape to detect affected elements (element which geometric center located on or inside shape). The replicated nodes should be associated to affected elements.
Returns:
TRUE if operation has been completed successfully, FALSE otherwise
See also:
DoubleNodeGroupInRegion(), DoubleNodesInRegion()
SMESH_Group SMESH::SMESH_MeshEditor::DoubleNodeElemGroupsNew ( in ListOfGroups  theElems,
in ListOfGroups  theNodesNot,
in ListOfGroups  theAffectedElems 
)

Creates a hole in a mesh by doubling the nodes of some particular elements.

Works as DoubleNodeElemGroups() described above, but returns a new group with newly created elements.

Parameters:
theElems- list of groups of elements (edges or faces) to be replicated
theNodesNot- list of groups of nodes not to replicated
theAffectedElems- group of elements to which the replicated nodes should be associated to.
Returns:
a new group with newly created elements
See also:
DoubleNodeElemGroups()
boolean SMESH::SMESH_MeshEditor::DoubleNodeElemInRegion ( in long_array  theElems,
in long_array  theNodesNot,
in GEOM::GEOM_Object  theShape 
)

Creates a hole in a mesh by doubling the nodes of some particular elements.

Parameters:
theElems- the list of elements (edges or faces) to be replicated The nodes for duplication could be found from these elements
theNodesNot- list of nodes to NOT replicate
theShape- shape to detect affected elements (element which geometric center located on or inside shape). The replicated nodes should be associated to affected elements.
Returns:
TRUE if operation has been completed successfully, FALSE otherwise
See also:
DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
boolean SMESH::SMESH_MeshEditor::DoubleNodeGroup ( in SMESH_GroupBase  theNodes,
in SMESH_GroupBase  theModifiedElems 
)

Creates a hole in a mesh by doubling the nodes of some particular elements This method provided for convenience works as DoubleNodes() described above.

Parameters:
theNodes- group of nodes to be doubled.
theModifiedElems- group of elements to be updated.
Returns:
TRUE if operation has been completed successfully, FALSE otherwise
See also:
DoubleNode(), DoubleNodes(), DoubleNodeGroups(), DoubleNodeGroupNew()

Creates a hole in a mesh by doubling the nodes of some particular elements.

Works as DoubleNodeGroup() described above, but returns a new group with newly created nodes.

Parameters:
theNodes- group of nodes to be doubled.
theModifiedElems- group of elements to be updated.
Returns:
a new group with newly created nodes
See also:
DoubleNodeGroup()
boolean SMESH::SMESH_MeshEditor::DoubleNodeGroups ( in ListOfGroups  theNodes,
in ListOfGroups  theModifiedElems 
)

Creates a hole in a mesh by doubling the nodes of some particular elements This method provided for convenience works as DoubleNodes() described above.

Parameters:
theNodes- list of groups of nodes to be doubled
theModifiedElems- list of groups of elements to be updated.
Returns:
TRUE if operation has been completed successfully, FALSE otherwise
See also:
DoubleNode(), DoubleNodeGroup(), DoubleNodes()

Creates a hole in a mesh by doubling the nodes of some particular elements Works as DoubleNodeGroups() described above, but returns a new group with newly created nodes.

Parameters:
theNodes- list of groups of nodes to be doubled
theModifiedElems- list of groups of elements to be updated.
Returns:
a new group with newly created nodes
See also:
DoubleNodeGroups()
bool SMESH_MeshEditor::DoubleNodes ( in long_array  theNodes,
in long_array  theModifiedElems 
)

Creates a hole in a mesh by doubling the nodes of some particular elements.

Parameters:
theNodes- identifiers of nodes to be doubled
theModifiedElems- identifiers of elements to be updated by the new (doubled) nodes. If list of element identifiers is empty then nodes are doubled but they not assigned to elements
Returns:
TRUE if operation has been completed successfully, FALSE otherwise
See also:
DoubleNode(), DoubleNodeGroup(), DoubleNodeGroups()
Parameters:
theElems- the list of elements (edges or faces) to be replicated The nodes for duplication could be found from these elements
theNodesNot- list of nodes to NOT replicate
theAffectedElems- the list of elements (cells and edges) to which the replicated nodes should be associated to.
Returns:
TRUE if operation has been completed successfully, FALSE otherwise
Parameters:
theNodes- identifiers of nodes to be doubled
theModifiedElems- identifiers of elements to be updated by the new (doubled) nodes. If list of element identifiers is empty then nodes are doubled but they not assigned to elements
Returns:
TRUE if operation has been completed successfully, FALSE otherwise

Definition at line 10238 of file SMESH_MeshEditor.cxx.

{
  myLastCreatedElems.Clear();
  myLastCreatedNodes.Clear();

  if ( theElems.size() == 0 )
    return false;

  SMESHDS_Mesh* aMeshDS = GetMeshDS();
  if ( !aMeshDS )
    return false;

  bool res = false;
  std::map< const SMDS_MeshNode*, const SMDS_MeshNode* > anOldNodeToNewNode;
  // duplicate elements and nodes
  res = doubleNodes( aMeshDS, theElems, theNodesNot, anOldNodeToNewNode, true );
  // replce nodes by duplications
  res = doubleNodes( aMeshDS, theAffectedElems, theNodesNot, anOldNodeToNewNode, false );
  return res;
}
bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries ( in ListOfGroups  theDomains,
in boolean  createJointElems 
) raises (SALOME::SALOME_Exception)

Double nodes on shared faces between groups of volumes and create flat elements on demand.

Flat elements are mainly used by some types of mechanic calculations.

The list of groups must describe a partition of the mesh volumes. The nodes of the internal faces at the boundaries of the groups are doubled. In option, the internal faces are replaced by flat elements. Triangles are transformed in prisms, and quadrangles in hexahedrons.

Parameters:
theDomains- list of groups of volumes
createJointElems- if TRUE, create the elements
Returns:
TRUE if operation has been completed successfully, FALSE otherwise

The list of groups must describe a partition of the mesh volumes. The nodes of the internal faces at the boundaries of the groups are doubled. In option, the internal faces are replaced by flat elements. Triangles are transformed in prisms, and quadrangles in hexahedrons. The flat elements are stored in groups of volumes.

Parameters:
theElems- list of groups of volumes, where a group of volume is a set of SMDS_MeshElements sorted by Id.
createJointElems- if TRUE, create the elements
Returns:
TRUE if operation has been completed successfully, FALSE otherwise

Definition at line 10583 of file SMESH_MeshEditor.cxx.

{
  MESSAGE("----------------------------------------------");
  MESSAGE("SMESH_MeshEditor::doubleNodesOnGroupBoundaries");
  MESSAGE("----------------------------------------------");

  SMESHDS_Mesh *meshDS = this->myMesh->GetMeshDS();
  meshDS->BuildDownWardConnectivity(true);
  CHRONO(50);
  SMDS_UnstructuredGrid *grid = meshDS->getGrid();

  // --- build the list of faces shared by 2 domains (group of elements), with their domain and volume indexes
  //     build the list of cells with only a node or an edge on the border, with their domain and volume indexes
  //     build the list of nodes shared by 2 or more domains, with their domain indexes

  std::map<DownIdType, std::map<int,int>, DownIdCompare> faceDomains; // face --> (id domain --> id volume)
  std::map<int,int>celldom; // cell vtkId --> domain
  std::map<DownIdType, std::map<int,int>, DownIdCompare> cellDomains;  // oldNode --> (id domain --> id cell)
  std::map<int, std::map<int,int> > nodeDomains; // oldId -->  (domainId --> newId)
  faceDomains.clear();
  celldom.clear();
  cellDomains.clear();
  nodeDomains.clear();
  std::map<int,int> emptyMap;
  std::set<int> emptySet;
  emptyMap.clear();

  for (int idom = 0; idom < theElems.size(); idom++)
    {

      // --- build a map (face to duplicate --> volume to modify)
      //     with all the faces shared by 2 domains (group of elements)
      //     and corresponding volume of this domain, for each shared face.
      //     a volume has a face shared by 2 domains if it has a neighbor which is not in is domain.

      //MESSAGE("Domain " << idom);
      const TIDSortedElemSet& domain = theElems[idom];
      TIDSortedElemSet::const_iterator elemItr = domain.begin();
      for (; elemItr != domain.end(); ++elemItr)
        {
          SMDS_MeshElement* anElem = (SMDS_MeshElement*) *elemItr;
          if (!anElem)
            continue;
          int vtkId = anElem->getVtkId();
          //MESSAGE("  vtkId " << vtkId << " smdsId " << anElem->GetID());
          int neighborsVtkIds[NBMAXNEIGHBORS];
          int downIds[NBMAXNEIGHBORS];
          unsigned char downTypes[NBMAXNEIGHBORS];
          int nbNeighbors = grid->GetNeighbors(neighborsVtkIds, downIds, downTypes, vtkId);
          for (int n = 0; n < nbNeighbors; n++)
            {
              int smdsId = meshDS->fromVtkToSmds(neighborsVtkIds[n]);
              const SMDS_MeshElement* elem = meshDS->FindElement(smdsId);
              if (! domain.count(elem)) // neighbor is in another domain : face is shared
                {
                  DownIdType face(downIds[n], downTypes[n]);
                  if (!faceDomains.count(face))
                    faceDomains[face] = emptyMap; // create an empty entry for face
                  if (!faceDomains[face].count(idom))
                    {
                      faceDomains[face][idom] = vtkId; // volume associated to face in this domain
                      celldom[vtkId] = idom;
                      //MESSAGE("       cell with a border " << vtkId << " domain " << idom);
                    }
                }
            }
        }
    }

  //MESSAGE("Number of shared faces " << faceDomains.size());
  std::map<DownIdType, std::map<int, int>, DownIdCompare>::iterator itface;

  // --- explore the shared faces domain by domain,
  //     explore the nodes of the face and see if they belong to a cell in the domain,
  //     which has only a node or an edge on the border (not a shared face)

  for (int idomain = 0; idomain < theElems.size(); idomain++)
    {
      //MESSAGE("Domain " << idomain);
      const TIDSortedElemSet& domain = theElems[idomain];
      itface = faceDomains.begin();
      for (; itface != faceDomains.end(); ++itface)
        {
          std::map<int, int> domvol = itface->second;
          if (!domvol.count(idomain))
            continue;
          DownIdType face = itface->first;
          //MESSAGE(" --- face " << face.cellId);
          std::set<int> oldNodes;
          oldNodes.clear();
          grid->GetNodeIds(oldNodes, face.cellId, face.cellType);
          std::set<int>::iterator itn = oldNodes.begin();
          for (; itn != oldNodes.end(); ++itn)
            {
              int oldId = *itn;
              //MESSAGE("     node " << oldId);
              std::set<int> cells;
              cells.clear();
              vtkCellLinks::Link l = grid->GetCellLinks()->GetLink(oldId);
              for (int i=0; i<l.ncells; i++)
                {
                  int vtkId = l.cells[i];
                  const SMDS_MeshElement* anElem = GetMeshDS()->FindElement(GetMeshDS()->fromVtkToSmds(vtkId));
                  if (!domain.count(anElem))
                    continue;
                  int vtkType = grid->GetCellType(vtkId);
                  int downId = grid->CellIdToDownId(vtkId);
                  if (downId < 0)
                    {
                      MESSAGE("doubleNodesOnGroupBoundaries: internal algorithm problem");
                      continue; // not OK at this stage of the algorithm:
                                //no cells created after BuildDownWardConnectivity
                    }
                  DownIdType aCell(downId, vtkType);
                  if (celldom.count(vtkId))
                    continue;
                  cellDomains[aCell][idomain] = vtkId;
                  celldom[vtkId] = idomain;
                  //MESSAGE("       cell " << vtkId << " domain " << idomain);
                }
            }
        }
    }

  // --- explore the shared faces domain by domain, to duplicate the nodes in a coherent way
  //     for each shared face, get the nodes
  //     for each node, for each domain of the face, create a clone of the node

  // --- edges at the intersection of 3 or 4 domains, with the order of domains to build
  //     junction elements of type prism or hexa. the key is the pair of nodesId (lower first)
  //     the value is the ordered domain ids. (more than 4 domains not taken into account)

  std::map<std::vector<int>, std::vector<int> > edgesMultiDomains; // nodes of edge --> ordered domains
  std::map<int, std::vector<int> > mutipleNodes; // nodes multi domains with domain order
  std::map<int, std::vector<int> > mutipleNodesToFace; // nodes multi domains with domain order to transform in Face (junction between 3 or more 2D domains)

  for (int idomain = 0; idomain < theElems.size(); idomain++)
    {
      itface = faceDomains.begin();
      for (; itface != faceDomains.end(); ++itface)
        {
          std::map<int, int> domvol = itface->second;
          if (!domvol.count(idomain))
            continue;
          DownIdType face = itface->first;
          //MESSAGE(" --- face " << face.cellId);
          std::set<int> oldNodes;
          oldNodes.clear();
          grid->GetNodeIds(oldNodes, face.cellId, face.cellType);
          bool isMultipleDetected = false;
          std::set<int>::iterator itn = oldNodes.begin();
          for (; itn != oldNodes.end(); ++itn)
            {
              int oldId = *itn;
              //MESSAGE("     node " << oldId);
              if (!nodeDomains.count(oldId))
                nodeDomains[oldId] = emptyMap; // create an empty entry for node
              if (nodeDomains[oldId].empty())
                nodeDomains[oldId][idomain] = oldId; // keep the old node in the first domain
              std::map<int, int>::iterator itdom = domvol.begin();
              for (; itdom != domvol.end(); ++itdom)
                {
                  int idom = itdom->first;
                  //MESSAGE("         domain " << idom);
                  if (!nodeDomains[oldId].count(idom)) // --- node to clone
                    {
                      if (nodeDomains[oldId].size() >= 2) // a multiple node
                        {
                          vector<int> orderedDoms;
                          //MESSAGE("multiple node " << oldId);
                          isMultipleDetected =true;
                          if (mutipleNodes.count(oldId))
                            orderedDoms = mutipleNodes[oldId];
                          else
                            {
                              map<int,int>::iterator it = nodeDomains[oldId].begin();
                              for (; it != nodeDomains[oldId].end(); ++it)
                                orderedDoms.push_back(it->first);
                            }
                          orderedDoms.push_back(idom); // TODO order ==> push_front or back
                          //stringstream txt;
                          //for (int i=0; i<orderedDoms.size(); i++)
                          //  txt << orderedDoms[i] << " ";
                          //MESSAGE("orderedDoms " << txt.str());
                          mutipleNodes[oldId] = orderedDoms;
                        }
                      double *coords = grid->GetPoint(oldId);
                      SMDS_MeshNode *newNode = meshDS->AddNode(coords[0], coords[1], coords[2]);
                      int newId = newNode->getVtkId();
                      nodeDomains[oldId][idom] = newId; // cloned node for other domains
                      //MESSAGE("   newNode " << newId << " oldNode " << oldId << " size=" <<nodeDomains[oldId].size());
                    }
                  if (nodeDomains[oldId].size() >= 3)
                    {
                      //MESSAGE("confirm multiple node " << oldId);
                      isMultipleDetected =true;
                    }
                }
            }
          if (isMultipleDetected) // check if an edge of the face is shared between 3 or more domains
            {
              //MESSAGE("multiple Nodes detected on a shared face");
              int downId = itface->first.cellId;
              unsigned char cellType = itface->first.cellType;
              // --- shared edge or shared face ?
              if ((cellType == VTK_LINE) || (cellType == VTK_QUADRATIC_EDGE)) // shared edge (between two faces)
                {
                  int nodes[3];
                  int nbNodes = grid->getDownArray(cellType)->getNodes(downId, nodes);
                  for (int i=0; i< nbNodes; i=i+nbNodes-1) // i=0 , i=nbNodes-1
                    if (mutipleNodes.count(nodes[i]))
                      if (!mutipleNodesToFace.count(nodes[i]))
                        mutipleNodesToFace[nodes[i]] = mutipleNodes[nodes[i]];
               }
              else // shared face (between two volumes)
                {
                  int nbEdges = grid->getDownArray(cellType)->getNumberOfDownCells(downId);
                  const int* downEdgeIds = grid->getDownArray(cellType)->getDownCells(downId);
                  const unsigned char* edgeType = grid->getDownArray(cellType)->getDownTypes(downId);
                  for (int ie =0; ie < nbEdges; ie++)
                    {
                      int nodes[3];
                      int nbNodes = grid->getDownArray(edgeType[ie])->getNodes(downEdgeIds[ie], nodes);
                      if (mutipleNodes.count(nodes[0]) && mutipleNodes.count(nodes[nbNodes-1]))
                        {
                          vector<int> vn0 = mutipleNodes[nodes[0]];
                          vector<int> vn1 = mutipleNodes[nodes[nbNodes - 1]];
                          sort( vn0.begin(), vn0.end() );
                          sort( vn1.begin(), vn1.end() );
                          if (vn0 == vn1)
                            {
                              //MESSAGE(" detect edgesMultiDomains " << nodes[0] << " " << nodes[nbNodes - 1]);
                              double *coords = grid->GetPoint(nodes[0]);
                              gp_Pnt p0(coords[0], coords[1], coords[2]);
                              coords = grid->GetPoint(nodes[nbNodes - 1]);
                              gp_Pnt p1(coords[0], coords[1], coords[2]);
                              gp_Pnt gref;
                              int vtkVolIds[1000];  // an edge can belong to a lot of volumes
                              map<int, SMDS_VtkVolume*> domvol; // domain --> a volume with the edge
                              map<int, double> angleDom; // oriented angles between planes defined by edge and volume centers
                              int nbvol = grid->GetParentVolumes(vtkVolIds, downEdgeIds[ie], edgeType[ie]);
                              for (int id=0; id < vn0.size(); id++)
                                {
                                  int idom = vn0[id];
                                  for (int ivol=0; ivol<nbvol; ivol++)
                                    {
                                      int smdsId = meshDS->fromVtkToSmds(vtkVolIds[ivol]);
                                      SMDS_MeshElement* elem = (SMDS_MeshElement*)meshDS->FindElement(smdsId);
                                      if (theElems[idom].count(elem))
                                        {
                                          SMDS_VtkVolume* svol = dynamic_cast<SMDS_VtkVolume*>(elem);
                                          domvol[idom] = svol;
                                          //MESSAGE("  domain " << idom << " volume " << elem->GetID());
                                          double values[3];
                                          vtkIdType npts = 0;
                                          vtkIdType* pts = 0;
                                          grid->GetCellPoints(vtkVolIds[ivol], npts, pts);
                                          SMDS_VtkVolume::gravityCenter(grid, pts, npts, values);
                                          if (id ==0)
                                            {
                                              gref.SetXYZ(gp_XYZ(values[0], values[1], values[2]));
                                              angleDom[idom] = 0;
                                            }
                                          else
                                            {
                                              gp_Pnt g(values[0], values[1], values[2]);
                                              angleDom[idom] = OrientedAngle(p0, p1, gref, g); // -pi<angle<+pi
                                              //MESSAGE("  angle=" << angleDom[idom]);
                                            }
                                          break;
                                        }
                                    }
                                }
                              map<double, int> sortedDom; // sort domains by angle
                              for (map<int, double>::iterator ia = angleDom.begin(); ia != angleDom.end(); ++ia)
                                sortedDom[ia->second] = ia->first;
                              vector<int> vnodes;
                              vector<int> vdom;
                              for (map<double, int>::iterator ib = sortedDom.begin(); ib != sortedDom.end(); ++ib)
                                {
                                  vdom.push_back(ib->second);
                                  //MESSAGE("  ordered domain " << ib->second << "  angle " << ib->first);
                                }
                              for (int ino = 0; ino < nbNodes; ino++)
                                vnodes.push_back(nodes[ino]);
                              edgesMultiDomains[vnodes] = vdom; // nodes vector --> ordered domains
                            }
                        }
                    }
                }
            }
        }
    }

  // --- iterate on shared faces (volumes to modify, face to extrude)
  //     get node id's of the face (id SMDS = id VTK)
  //     create flat element with old and new nodes if requested

  // --- new quad nodes on flat quad elements: oldId --> ((domain1 X domain2) --> newId)
  //     (domain1 X domain2) = domain1 + MAXINT*domain2

  std::map<int, std::map<long,int> > nodeQuadDomains;
  std::map<std::string, SMESH_Group*> mapOfJunctionGroups;

  if (createJointElems)
    {
      itface = faceDomains.begin();
      for (; itface != faceDomains.end(); ++itface)
        {
          DownIdType face = itface->first;
          std::set<int> oldNodes;
          std::set<int>::iterator itn;
          oldNodes.clear();
          grid->GetNodeIds(oldNodes, face.cellId, face.cellType);

          std::map<int, int> domvol = itface->second;
          std::map<int, int>::iterator itdom = domvol.begin();
          int dom1 = itdom->first;
          int vtkVolId = itdom->second;
          itdom++;
          int dom2 = itdom->first;
          SMDS_MeshCell *vol = grid->extrudeVolumeFromFace(vtkVolId, dom1, dom2, oldNodes, nodeDomains,
                                                             nodeQuadDomains);
          stringstream grpname;
          grpname << "j_";
          if (dom1 < dom2)
            grpname << dom1 << "_" << dom2;
          else
            grpname << dom2 << "_" << dom1;
          int idg;
          string namegrp = grpname.str();
          if (!mapOfJunctionGroups.count(namegrp))
            mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(vol->GetType(), namegrp.c_str(), idg);
          SMESHDS_Group *sgrp = dynamic_cast<SMESHDS_Group*>(mapOfJunctionGroups[namegrp]->GetGroupDS());
          if (sgrp)
            sgrp->Add(vol->GetID());
        }
    }

  // --- create volumes on multiple domain intersection if requested
  //     iterate on mutipleNodesToFace
  //     iterate on edgesMultiDomains

  if (createJointElems)
    {
      // --- iterate on mutipleNodesToFace

      std::map<int, std::vector<int> >::iterator itn =  mutipleNodesToFace.begin();
      for (; itn != mutipleNodesToFace.end(); ++itn)
        {
          int node = itn->first;
          vector<int> orderDom = itn->second;
          vector<vtkIdType> orderedNodes;
          for (int idom = 0; idom <orderDom.size(); idom++)
            orderedNodes.push_back( nodeDomains[node][orderDom[idom]] );
            SMDS_MeshFace* face = this->GetMeshDS()->AddFaceFromVtkIds(orderedNodes);

            stringstream grpname;
            grpname << "m2j_";
            grpname << 0 << "_" << 0;
            int idg;
            string namegrp = grpname.str();
            if (!mapOfJunctionGroups.count(namegrp))
              mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Face, namegrp.c_str(), idg);
            SMESHDS_Group *sgrp = dynamic_cast<SMESHDS_Group*>(mapOfJunctionGroups[namegrp]->GetGroupDS());
            if (sgrp)
              sgrp->Add(face->GetID());
        }

      // --- iterate on edgesMultiDomains

      std::map<std::vector<int>, std::vector<int> >::iterator ite = edgesMultiDomains.begin();
      for (; ite != edgesMultiDomains.end(); ++ite)
        {
          vector<int> nodes = ite->first;
          vector<int> orderDom = ite->second;
          vector<vtkIdType> orderedNodes;
          if (nodes.size() == 2)
            {
              //MESSAGE(" use edgesMultiDomains " << nodes[0] << " " << nodes[1]);
              for (int ino=0; ino < nodes.size(); ino++)
                if (orderDom.size() == 3)
                  for (int idom = 0; idom <orderDom.size(); idom++)
                    orderedNodes.push_back( nodeDomains[nodes[ino]][orderDom[idom]] );
                else
                  for (int idom = orderDom.size()-1; idom >=0; idom--)
                    orderedNodes.push_back( nodeDomains[nodes[ino]][orderDom[idom]] );
              SMDS_MeshVolume* vol = this->GetMeshDS()->AddVolumeFromVtkIds(orderedNodes);

              stringstream grpname;
              grpname << "mj_";
              grpname << 0 << "_" << 0;
              int idg;
              string namegrp = grpname.str();
              if (!mapOfJunctionGroups.count(namegrp))
                mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Volume, namegrp.c_str(), idg);
              SMESHDS_Group *sgrp = dynamic_cast<SMESHDS_Group*>(mapOfJunctionGroups[namegrp]->GetGroupDS());
              if (sgrp)
                sgrp->Add(vol->GetID());
            }
          else
            {
              MESSAGE("Quadratic multiple joints not implemented");
              // TODO quadratic nodes
            }
        }
    }

  // --- list the explicit faces and edges of the mesh that need to be modified,
  //     i.e. faces and edges built with one or more duplicated nodes.
  //     associate these faces or edges to their corresponding domain.
  //     only the first domain found is kept when a face or edge is shared

  std::map<DownIdType, std::map<int,int>, DownIdCompare> faceOrEdgeDom; // cellToModify --> (id domain --> id cell)
  std::map<int,int> feDom; // vtk id of cell to modify --> id domain
  faceOrEdgeDom.clear();
  feDom.clear();

  for (int idomain = 0; idomain < theElems.size(); idomain++)
    {
      std::map<int, std::map<int, int> >::const_iterator itnod = nodeDomains.begin();
      for (; itnod != nodeDomains.end(); ++itnod)
        {
          int oldId = itnod->first;
          //MESSAGE("     node " << oldId);
          vtkCellLinks::Link l = grid->GetCellLinks()->GetLink(oldId);
          for (int i = 0; i < l.ncells; i++)
            {
              int vtkId = l.cells[i];
              int vtkType = grid->GetCellType(vtkId);
              int downId = grid->CellIdToDownId(vtkId);
              if (downId < 0)
                continue; // new cells: not to be modified
              DownIdType aCell(downId, vtkType);
              int volParents[1000];
              int nbvol = grid->GetParentVolumes(volParents, vtkId);
              for (int j = 0; j < nbvol; j++)
                if (celldom.count(volParents[j]) && (celldom[volParents[j]] == idomain))
                  if (!feDom.count(vtkId))
                    {
                      feDom[vtkId] = idomain;
                      faceOrEdgeDom[aCell] = emptyMap;
                      faceOrEdgeDom[aCell][idomain] = vtkId; // affect face or edge to the first domain only
                      //MESSAGE("affect cell " << this->GetMeshDS()->fromVtkToSmds(vtkId) << " domain " << idomain
                      //        << " type " << vtkType << " downId " << downId);
                    }
            }
        }
    }

  // --- iterate on shared faces (volumes to modify, face to extrude)
  //     get node id's of the face
  //     replace old nodes by new nodes in volumes, and update inverse connectivity

  std::map<DownIdType, std::map<int,int>, DownIdCompare>* maps[3] = {&faceDomains, &cellDomains, &faceOrEdgeDom};
  for (int m=0; m<3; m++)
    {
      std::map<DownIdType, std::map<int,int>, DownIdCompare>* amap = maps[m];
      itface = (*amap).begin();
      for (; itface != (*amap).end(); ++itface)
        {
          DownIdType face = itface->first;
          std::set<int> oldNodes;
          std::set<int>::iterator itn;
          oldNodes.clear();
          grid->GetNodeIds(oldNodes, face.cellId, face.cellType);
          //MESSAGE("examine cell, downId " << face.cellId << " type " << int(face.cellType));
          std::map<int, int> localClonedNodeIds;

          std::map<int, int> domvol = itface->second;
          std::map<int, int>::iterator itdom = domvol.begin();
          for (; itdom != domvol.end(); ++itdom)
            {
              int idom = itdom->first;
              int vtkVolId = itdom->second;
              //MESSAGE("modify nodes of cell " << this->GetMeshDS()->fromVtkToSmds(vtkVolId) << " domain " << idom);
              localClonedNodeIds.clear();
              for (itn = oldNodes.begin(); itn != oldNodes.end(); ++itn)
                {
                  int oldId = *itn;
                  if (nodeDomains[oldId].count(idom))
                    {
                      localClonedNodeIds[oldId] = nodeDomains[oldId][idom];
                      //MESSAGE("     node " << oldId << " --> " << localClonedNodeIds[oldId]);
                    }
                }
              meshDS->ModifyCellNodes(vtkVolId, localClonedNodeIds);
            }
        }
    }

  meshDS->CleanDownWardConnectivity(); // Mesh has been modified, downward connectivity is no more usable, free memory
  grid->BuildLinks();

  CHRONOSTOP(50);
  counters::stats();
  return true;
}
Extrusion_Error SMESH::SMESH_MeshEditor::ExtrusionAlongPath ( in long_array  IDsOfElements,
in SMESH_Mesh  PathMesh,
in GEOM::GEOM_Object  PathShape,
in long  NodeStart,
in boolean  HasAngles,
in double_array  Angles,
in boolean  HasRefPoint,
in PointStruct  RefPoint 
)
ListOfGroups SMESH::SMESH_MeshEditor::ExtrusionAlongPathMakeGroups ( in long_array  IDsOfElements,
in SMESH_Mesh  PathMesh,
in GEOM::GEOM_Object  PathShape,
in long  NodeStart,
in boolean  HasAngles,
in double_array  Angles,
in boolean  HasRefPoint,
in PointStruct  RefPoint,
out Extrusion_Error  Error 
)
Extrusion_Error SMESH::SMESH_MeshEditor::ExtrusionAlongPathObject ( in SMESH_IDSource  theObject,
in SMESH_Mesh  PathMesh,
in GEOM::GEOM_Object  PathShape,
in long  NodeStart,
in boolean  HasAngles,
in double_array  Angles,
in boolean  HasRefPoint,
in PointStruct  RefPoint 
)
Extrusion_Error SMESH::SMESH_MeshEditor::ExtrusionAlongPathObject1D ( in SMESH_IDSource  theObject,
in SMESH_Mesh  PathMesh,
in GEOM::GEOM_Object  PathShape,
in long  NodeStart,
in boolean  HasAngles,
in double_array  Angles,
in boolean  HasRefPoint,
in PointStruct  RefPoint 
)
ListOfGroups SMESH::SMESH_MeshEditor::ExtrusionAlongPathObject1DMakeGroups ( in SMESH_IDSource  theObject,
in SMESH_Mesh  PathMesh,
in GEOM::GEOM_Object  PathShape,
in long  NodeStart,
in boolean  HasAngles,
in double_array  Angles,
in boolean  HasRefPoint,
in PointStruct  RefPoint,
out Extrusion_Error  Error 
)
Extrusion_Error SMESH::SMESH_MeshEditor::ExtrusionAlongPathObject2D ( in SMESH_IDSource  theObject,
in SMESH_Mesh  PathMesh,
in GEOM::GEOM_Object  PathShape,
in long  NodeStart,
in boolean  HasAngles,
in double_array  Angles,
in boolean  HasRefPoint,
in PointStruct  RefPoint 
)
ListOfGroups SMESH::SMESH_MeshEditor::ExtrusionAlongPathObject2DMakeGroups ( in SMESH_IDSource  theObject,
in SMESH_Mesh  PathMesh,
in GEOM::GEOM_Object  PathShape,
in long  NodeStart,
in boolean  HasAngles,
in double_array  Angles,
in boolean  HasRefPoint,
in PointStruct  RefPoint,
out Extrusion_Error  Error 
)
ListOfGroups SMESH::SMESH_MeshEditor::ExtrusionAlongPathObjectMakeGroups ( in SMESH_IDSource  theObject,
in SMESH_Mesh  PathMesh,
in GEOM::GEOM_Object  PathShape,
in long  NodeStart,
in boolean  HasAngles,
in double_array  Angles,
in boolean  HasRefPoint,
in PointStruct  RefPoint,
out Extrusion_Error  Error 
)
ListOfGroups SMESH::SMESH_MeshEditor::ExtrusionAlongPathObjX ( in SMESH_IDSource  theObject,
in SMESH_IDSource  Path,
in long  NodeStart,
in boolean  HasAngles,
in double_array  Angles,
in boolean  LinearVariation,
in boolean  HasRefPoint,
in PointStruct  RefPoint,
in boolean  MakeGroups,
in ElementType  ElemType,
out Extrusion_Error  Error 
)
ListOfGroups SMESH::SMESH_MeshEditor::ExtrusionAlongPathX ( in long_array  IDsOfElements,
in SMESH_IDSource  Path,
in long  NodeStart,
in boolean  HasAngles,
in double_array  Angles,
in boolean  LinearVariation,
in boolean  HasRefPoint,
in PointStruct  RefPoint,
in boolean  MakeGroups,
in ElementType  ElemType,
out Extrusion_Error  Error 
)
SMESH_MeshEditor::PGroupIDs SMESH_MeshEditor::ExtrusionSweep ( in long_array  IDsOfElements,
in DirStruct  StepVector,
in long  NbOfSteps 
)

Genarate dim+1 elements by extrusion of elements along vector.

Parameters:
IDsOfElements- elements to sweep
StepVector- vector giving direction and distance of an extrusion step
NbOfSteps- number of elements to generate from one element

Definition at line 4485 of file SMESH_MeshEditor.cxx.

{
  ExtrusParam aParams;
  aParams.myDir = gp_Dir(theStep);
  aParams.myNodes.Clear();
  aParams.mySteps = new TColStd_HSequenceOfReal;
  int i;
  for(i=1; i<=theNbSteps; i++)
    aParams.mySteps->Append(theStep.Magnitude());

  return
    ExtrusionSweep(theElems,aParams,newElemsMap,theMakeGroups,theFlags,theTolerance);
}
void SMESH::SMESH_MeshEditor::ExtrusionSweep0D ( in long_array  IDsOfElements,
in DirStruct  StepVector,
in long  NbOfSteps 
)

Genarate dim+1 elements by extrusion of elements along vector.

Parameters:
IDsOfElements- elements to sweep
StepVector- vector giving direction and distance of an extrusion step
NbOfSteps- number of elements to generate from one element
ListOfGroups SMESH::SMESH_MeshEditor::ExtrusionSweepMakeGroups ( in long_array  IDsOfElements,
in DirStruct  StepVector,
in long  NbOfSteps 
)

Same as previous but additionally create groups of elements generated from elements belonging to preexisting groups.

ListOfGroups SMESH::SMESH_MeshEditor::ExtrusionSweepMakeGroups0D ( in long_array  IDsOfElements,
in DirStruct  StepVector,
in long  NbOfSteps 
)

Same as previous but elements are nodes.

void SMESH::SMESH_MeshEditor::ExtrusionSweepObject ( in SMESH_IDSource  theObject,
in DirStruct  StepVector,
in long  NbOfSteps 
)
void SMESH::SMESH_MeshEditor::ExtrusionSweepObject0D ( in SMESH_IDSource  theObject,
in DirStruct  StepVector,
in long  NbOfSteps 
)
ListOfGroups SMESH::SMESH_MeshEditor::ExtrusionSweepObject0DMakeGroups ( in SMESH_IDSource  theObject,
in DirStruct  StepVector,
in long  NbOfSteps 
)
void SMESH::SMESH_MeshEditor::ExtrusionSweepObject1D ( in SMESH_IDSource  theObject,
in DirStruct  StepVector,
in long  NbOfSteps 
)
ListOfGroups SMESH::SMESH_MeshEditor::ExtrusionSweepObject1DMakeGroups ( in SMESH_IDSource  theObject,
in DirStruct  StepVector,
in long  NbOfSteps 
)
void SMESH::SMESH_MeshEditor::ExtrusionSweepObject2D ( in SMESH_IDSource  theObject,
in DirStruct  StepVector,
in long  NbOfSteps 
)
ListOfGroups SMESH::SMESH_MeshEditor::ExtrusionSweepObject2DMakeGroups ( in SMESH_IDSource  theObject,
in DirStruct  StepVector,
in long  NbOfSteps 
)
ListOfGroups SMESH::SMESH_MeshEditor::ExtrusionSweepObjectMakeGroups ( in SMESH_IDSource  theObject,
in DirStruct  StepVector,
in long  NbOfSteps 
)
long_array SMESH::SMESH_MeshEditor::FindAmongElementsByPoint ( in SMESH_IDSource  elements,
in double  x,
in double  y,
in double  z,
in ElementType  type 
)

Searching among the given elements, return elements of given type where the given point is IN or ON.

'ALL' type means elements of any type excluding nodes and 0D elements

void SMESH_MeshEditor::FindCoincidentNodes ( in double  Tolerance,
out array_of_long_array  GroupsOfNodes 
)

Return list of group of nodes close to each other within theTolerance Search among theNodes or in the whole mesh if theNodes is empty using an Octree algorithm.

Definition at line 5884 of file SMESH_MeshEditor.cxx.

{
  myLastCreatedElems.Clear();
  myLastCreatedNodes.Clear();

  if ( theNodes.empty() )
  { // get all nodes in the mesh
    SMDS_NodeIteratorPtr nIt = GetMeshDS()->nodesIterator(/*idInceasingOrder=*/true);
    while ( nIt->more() )
      theNodes.insert( theNodes.end(),nIt->next());
  }

  SMESH_OctreeNode::FindCoincidentNodes ( theNodes, &theGroupsOfNodes, theTolerance);
}
void SMESH::SMESH_MeshEditor::FindCoincidentNodesOnPart ( in SMESH_IDSource  SubMeshOrGroup,
in double  Tolerance,
out array_of_long_array  GroupsOfNodes 
)
void SMESH::SMESH_MeshEditor::FindCoincidentNodesOnPartBut ( in SMESH_IDSource  SubMeshOrGroup,
in double  Tolerance,
out array_of_long_array  GroupsOfNodes,
in ListOfIDSources  ExceptSubMeshOrGroups 
)
long_array SMESH::SMESH_MeshEditor::FindElementsByPoint ( in double  x,
in double  y,
in double  z,
in ElementType  type 
)

Return elements of given type where the given point is IN or ON.

'ALL' type means elements of any type excluding nodes and 0D elements

void SMESH_MeshEditor::FindEqualElements ( in SMESH_IDSource  MeshOrSubMeshOrGroup,
out array_of_long_array  GroupsOfElementsID 
)

Find elements built on the same nodes.

Parameters:
MeshOrSubMeshOrGroupMesh or SubMesh, or Group of elements for searching.
Returns:
List of groups of equal elements.

Definition at line 7749 of file SMESH_MeshEditor.cxx.

{
  myLastCreatedElems.Clear();
  myLastCreatedNodes.Clear();

  typedef set<const SMDS_MeshElement*> TElemsSet;
  typedef map< SortableElement, int > TMapOfNodeSet;
  typedef list<int> TGroupOfElems;

  TElemsSet elems;
  if ( theElements.empty() )
  { // get all elements in the mesh
    SMDS_ElemIteratorPtr eIt = GetMeshDS()->elementsIterator();
    while ( eIt->more() )
      elems.insert( elems.end(), eIt->next());
  }
  else
    elems = theElements;

  vector< TGroupOfElems > arrayOfGroups;
  TGroupOfElems groupOfElems;
  TMapOfNodeSet mapOfNodeSet;

  TElemsSet::iterator elemIt = elems.begin();
  for ( int i = 0, j=0; elemIt != elems.end(); ++elemIt, ++j ) {
    const SMDS_MeshElement* curElem = *elemIt;
    SortableElement SE(curElem);
    int ind = -1;
    // check uniqueness
    pair< TMapOfNodeSet::iterator, bool> pp = mapOfNodeSet.insert(make_pair(SE, i));
    if( !(pp.second) ) {
      TMapOfNodeSet::iterator& itSE = pp.first;
      ind = (*itSE).second;
      arrayOfGroups[ind].push_back(curElem->GetID());
    }
    else {
      groupOfElems.clear();
      groupOfElems.push_back(curElem->GetID());
      arrayOfGroups.push_back(groupOfElems);
      i++;
    }
  }

  vector< TGroupOfElems >::iterator groupIt = arrayOfGroups.begin();
  for ( ; groupIt != arrayOfGroups.end(); ++groupIt ) {
    groupOfElems = *groupIt;
    if ( groupOfElems.size() > 1 ) {
      groupOfElems.sort();
      theGroupsOfElementsID.push_back(groupOfElems);
    }
  }
}
long SMESH::SMESH_MeshEditor::FindNodeClosestTo ( in double  x,
in double  y,
in double  z 
)

Return ID of node closest to a given point.

If during last operation of MeshEditor some elements were created this method returns list of it's IDs, if new elements not creared - returns empty list.

If during last operation of MeshEditor some nodes were created this method returns list of it's IDs, if new nodes not creared - returns empty list.

short SMESH::SMESH_MeshEditor::GetPointState ( in double  x,
in double  y,
in double  z 
)

Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.

TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.

Return data of mesh edition preview which is computed provided that the editor was obtained trough SMESH_Mesh::GetMeshEditPreviewer()

bool SMESH_MeshEditor::InverseDiag ( in long  NodeID1,
in long  NodeID2 
)

Definition at line 569 of file SMESH_MeshEditor.cxx.

{
  MESSAGE("InverseDiag");
  myLastCreatedElems.Clear();
  myLastCreatedNodes.Clear();

  if (!theTria1 || !theTria2)
    return false;

  const SMDS_VtkFace* F1 = dynamic_cast<const SMDS_VtkFace*>( theTria1 );
  if (!F1) return false;
  const SMDS_VtkFace* F2 = dynamic_cast<const SMDS_VtkFace*>( theTria2 );
  if (!F2) return false;
  if ((theTria1->GetEntityType() == SMDSEntity_Triangle) &&
      (theTria2->GetEntityType() == SMDSEntity_Triangle)) {

    //  1 +--+ A  theTria1: ( 1 A B ) A->2 ( 1 2 B ) 1 +--+ A
    //    | /|    theTria2: ( B A 2 ) B->1 ( 1 A 2 )   |\ |
    //    |/ |                                         | \|
    //  B +--+ 2                                     B +--+ 2

    // put nodes in array and find out indices of the same ones
    const SMDS_MeshNode* aNodes [6];
    int sameInd [] = { 0, 0, 0, 0, 0, 0 };
    int i = 0;
    SMDS_ElemIteratorPtr it = theTria1->nodesIterator();
    while ( it->more() ) {
      aNodes[ i ] = static_cast<const SMDS_MeshNode*>( it->next() );

      if ( i > 2 ) // theTria2
        // find same node of theTria1
        for ( int j = 0; j < 3; j++ )
          if ( aNodes[ i ] == aNodes[ j ]) {
            sameInd[ j ] = i;
            sameInd[ i ] = j;
            break;
          }
      // next
      i++;
      if ( i == 3 ) {
        if ( it->more() )
          return false; // theTria1 is not a triangle
        it = theTria2->nodesIterator();
      }
      if ( i == 6 && it->more() )
        return false; // theTria2 is not a triangle
    }

    // find indices of 1,2 and of A,B in theTria1
    int iA = 0, iB = 0, i1 = 0, i2 = 0;
    for ( i = 0; i < 6; i++ ) {
      if ( sameInd [ i ] == 0 ) {
        if ( i < 3 ) i1 = i;
        else         i2 = i;
      }
      else if (i < 3) {
        if ( iA ) iB = i;
        else      iA = i;
      }
    }
    // nodes 1 and 2 should not be the same
    if ( aNodes[ i1 ] == aNodes[ i2 ] )
      return false;

    // theTria1: A->2
    aNodes[ iA ] = aNodes[ i2 ];
    // theTria2: B->1
    aNodes[ sameInd[ iB ]] = aNodes[ i1 ];

    GetMeshDS()->ChangeElementNodes( theTria1, aNodes, 3 );
    GetMeshDS()->ChangeElementNodes( theTria2, &aNodes[ 3 ], 3 );

    return true;

  } // end if(F1 && F2)

  // check case of quadratic faces
  if (theTria1->GetEntityType() != SMDSEntity_Quad_Triangle)
    return false;
  if (theTria2->GetEntityType() != SMDSEntity_Quad_Triangle)
    return false;

  //       5
  //  1 +--+--+ 2  theTria1: (1 2 4 5 9 7) or (2 4 1 9 7 5) or (4 1 2 7 5 9)
  //    |    /|    theTria2: (2 3 4 6 8 9) or (3 4 2 8 9 6) or (4 2 3 9 6 8)
  //    |   / |
  //  7 +  +  + 6
  //    | /9  |
  //    |/    |
  //  4 +--+--+ 3
  //       8

  const SMDS_MeshNode* N1 [6];
  const SMDS_MeshNode* N2 [6];
  if(!GetNodesFromTwoTria(theTria1,theTria2,N1,N2))
    return false;
  // now we receive following N1 and N2 (using numeration as above image)
  // tria1 : (1 2 4 5 9 7)  and  tria2 : (3 4 2 8 9 6)
  // i.e. first nodes from both arrays determ new diagonal

  const SMDS_MeshNode* N1new [6];
  const SMDS_MeshNode* N2new [6];
  N1new[0] = N1[0];
  N1new[1] = N2[0];
  N1new[2] = N2[1];
  N1new[3] = N1[4];
  N1new[4] = N2[3];
  N1new[5] = N1[5];
  N2new[0] = N1[0];
  N2new[1] = N1[1];
  N2new[2] = N2[0];
  N2new[3] = N1[3];
  N2new[4] = N2[5];
  N2new[5] = N1[4];
  // replaces nodes in faces
  GetMeshDS()->ChangeElementNodes( theTria1, N1new, 6 );
  GetMeshDS()->ChangeElementNodes( theTria2, N2new, 6 );

  return true;
}

Here is the call graph for this function:

double_array SMESH::SMESH_MeshEditor::LinearAnglesVariation ( in SMESH_Mesh  PathMesh,
in GEOM::GEOM_Object  PathShape,
in double_array  Angles 
)

Compute rotation angles for ExtrusionAlongPath as linear variation of given angles along path steps param PathMesh mesh containing a 1D sub-mesh on the edge, along which proceeds the extrusion param PathShape is shape(edge); as the mesh can be complex, the edge is used to define the sub-mesh for the path.

Generates skin mesh (containing 2D cells) from 3D mesh The created 2D mesh elements based on nodes of free faces of boundary volumes.

Returns:
TRUE if operation has been completed successfully, FALSE otherwise

Definition at line 11252 of file SMESH_MeshEditor.cxx.

{
  // iterates on volume elements and detect all free faces on them
  SMESHDS_Mesh* aMesh = GetMeshDS();
  if (!aMesh)
    return false;
  //bool res = false;
  int nbFree = 0, nbExisted = 0, nbCreated = 0;
  SMDS_VolumeIteratorPtr vIt = aMesh->volumesIterator();
  while(vIt->more())
  {
    const SMDS_MeshVolume* volume = vIt->next();
    SMDS_VolumeTool vTool( volume, /*ignoreCentralNodes=*/false );
    vTool.SetExternalNormal();
    //const bool isPoly = volume->IsPoly();
    const int iQuad = volume->IsQuadratic();
    for ( int iface = 0, n = vTool.NbFaces(); iface < n; iface++ )
    {
      if (!vTool.IsFreeFace(iface))
        continue;
      nbFree++;
      vector<const SMDS_MeshNode *> nodes;
      int nbFaceNodes = vTool.NbFaceNodes(iface);
      const SMDS_MeshNode** faceNodes = vTool.GetFaceNodes(iface);
      int inode = 0;
      for ( ; inode < nbFaceNodes; inode += iQuad+1)
        nodes.push_back(faceNodes[inode]);
      if (iQuad) { // add medium nodes
        for ( inode = 1; inode < nbFaceNodes; inode += 2)
          nodes.push_back(faceNodes[inode]);
        if ( nbFaceNodes == 9 ) // bi-quadratic quad
          nodes.push_back(faceNodes[8]);
      }
      // add new face based on volume nodes
      if (aMesh->FindElement( nodes, SMDSAbs_Face, /*noMedium=*/false) ) {
        nbExisted++;
        continue; // face already exsist
      }
      AddElement(nodes, SMDSAbs_Face, ( !iQuad && nbFaceNodes/(iQuad+1) > 4 ));
      nbCreated++;
    }
  }
  return ( nbFree==(nbExisted+nbCreated) );
}
long SMESH::SMESH_MeshEditor::MakeBoundaryElements ( in Bnd_Dimension  dimension,
in string  groupName,
in string  meshName,
in boolean  toCopyAll,
in ListOfIDSources  groups,
out SMESH_Mesh  mesh,
out SMESH_Group  group 
) raises (SALOME::SALOME_Exception)

Creates missing boundary elements around either the whole mesh or groups of 2D elements.

Parameters:
dimension- defines type of boundary elements to create
groupName- a name of group to store all boundary elements in, "" means not to create the group
meshName- a name of a new mesh, which is a copy of the initial mesh + created boundary elements; "" means not to create the new mesh
toCopyAll- if true, the whole initial mesh will be copied into the new mesh else only boundary elements will be copied into the new mesh
groups- optional groups of 2D elements to make boundary around
mesh- returns the mesh where elements were added to
group- returns the created group, if any
Return values:
long- number of added boundary elements
int SMESH_MeshEditor::MakeBoundaryMesh ( in SMESH_IDSource  elements,
in Bnd_Dimension  dimension,
in string  groupName,
in string  meshName,
in boolean  toCopyElements,
in boolean  toCopyExistingBondary,
out SMESH_Group  group 
)

Creates missing boundary elements.

Parameters:
elements- elements whose boundary is to be checked
dimension- defines type of boundary elements to create BND_1DFROM3D creates mesh edges on all borders of free facets of 3D elements.
groupName- a name of group to store created boundary elements in, "" means not to create the group
meshName- a name of new mesh to store created boundary elements in, "" means not to create the new mesh
toCopyElements- if true, the checked elements will be copied into the new mesh else only boundary elements will be copied into the new mesh
toCopyExistingBondary- if true, not only new but also pre-existing boundary elements will be copied into the new mesh
group- returns the create group, if any
Return values:
SMESH::SMESH_Mesh- the mesh where elements were added to
Parameters:
elements- elements whose boundary is to be checked
dimension- defines type of boundary elements to create
group- a group to store created boundary elements in
targetMesh- a mesh to store created boundary elements in
toCopyElements- if true, the checked elements will be copied into the targetMesh
toCopyExistingBoundary- if true, not only new but also pre-existing boundary elements will be copied into the targetMesh
toAddExistingBondary- if true, not only new but also pre-existing boundary elements will be added into the new group
aroundElements- if true, elements will be created on boundary of given elements else, on boundary of the whole mesh.
Returns:
nb of added boundary elements

Definition at line 11324 of file SMESH_MeshEditor.cxx.

{
  SMDSAbs_ElementType missType = (dimension == BND_2DFROM3D) ? SMDSAbs_Face : SMDSAbs_Edge;
  SMDSAbs_ElementType elemType = (dimension == BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume;
  // hope that all elements are of the same type, do not check them all
  if ( !elements.empty() && (*elements.begin())->GetType() != elemType )
    throw SALOME_Exception(LOCALIZED("wrong element type"));

  if ( !targetMesh )
    toCopyElements = toCopyExistingBoundary = false;

  SMESH_MeshEditor tgtEditor( targetMesh ? targetMesh : myMesh );
  SMESHDS_Mesh* aMesh = GetMeshDS(), *tgtMeshDS = tgtEditor.GetMeshDS();
  int nbAddedBnd = 0;

  // editor adding present bnd elements and optionally holding elements to add to the group
  SMESH_MeshEditor* presentEditor;
  SMESH_MeshEditor tgtEditor2( tgtEditor.GetMesh() );
  presentEditor = toAddExistingBondary ? &tgtEditor : &tgtEditor2;

  SMESH_MesherHelper helper( *myMesh );
  const TopAbs_ShapeEnum missShapeType = ( missType==SMDSAbs_Face ? TopAbs_FACE : TopAbs_EDGE );
  SMDS_VolumeTool vTool;
  TIDSortedElemSet avoidSet;
  const TIDSortedElemSet emptySet, *elemSet = aroundElements ? &elements : &emptySet;
  int inode;

  typedef vector<const SMDS_MeshNode*> TConnectivity;

  SMDS_ElemIteratorPtr eIt;
  if (elements.empty())
    eIt = aMesh->elementsIterator(elemType);
  else
    eIt = SMDS_ElemIteratorPtr( new TSetIterator( elements.begin(), elements.end() ));

  while (eIt->more())
  {
    const SMDS_MeshElement* elem = eIt->next();
    const int iQuad = elem->IsQuadratic();

    // ------------------------------------------------------------------------------------
    // 1. For an elem, get present bnd elements and connectivities of missing bnd elements
    // ------------------------------------------------------------------------------------
    vector<const SMDS_MeshElement*> presentBndElems;
    vector<TConnectivity>           missingBndElems;
    TConnectivity nodes;
    if ( vTool.Set(elem, /*ignoreCentralNodes=*/true) ) // elem is a volume --------------
    {
      vTool.SetExternalNormal();
      const SMDS_MeshElement* otherVol = 0;
      for ( int iface = 0, n = vTool.NbFaces(); iface < n; iface++ )
      {
        if ( !vTool.IsFreeFace(iface, &otherVol) &&
             ( !aroundElements || elements.count( otherVol )))
          continue;
        const int nbFaceNodes = vTool.NbFaceNodes(iface);
        const SMDS_MeshNode** nn = vTool.GetFaceNodes(iface);
        if ( missType == SMDSAbs_Edge ) // boundary edges
        {
          nodes.resize( 2+iQuad );
          for ( int i = 0; i < nbFaceNodes; i += 1+iQuad)
          {
            for ( int j = 0; j < nodes.size(); ++j )
              nodes[j] =nn[i+j];
            if ( const SMDS_MeshElement* edge =
                 aMesh->FindElement(nodes,SMDSAbs_Edge,/*noMedium=*/false))
              presentBndElems.push_back( edge );
            else
              missingBndElems.push_back( nodes );
          }
        }
        else // boundary face
        {
          nodes.clear();
          for ( inode = 0; inode < nbFaceNodes; inode += 1+iQuad)
            nodes.push_back( nn[inode] );
          if (iQuad) // add medium nodes
            for ( inode = 1; inode < nbFaceNodes; inode += 2)
              nodes.push_back( nn[inode] );
          int iCenter = vTool.GetCenterNodeIndex(iface); // for HEX27
          if ( iCenter > 0 )
            nodes.push_back( vTool.GetNodes()[ iCenter ] );

          if (const SMDS_MeshElement * f = aMesh->FindElement( nodes,
                                                               SMDSAbs_Face, /*noMedium=*/false ))
            presentBndElems.push_back( f );
          else
            missingBndElems.push_back( nodes );

          if ( targetMesh != myMesh )
          {
            // add 1D elements on face boundary to be added to a new mesh
            const SMDS_MeshElement* edge;
            for ( inode = 0; inode < nbFaceNodes; inode += 1+iQuad)
            {
              if ( iQuad )
                edge = aMesh->FindEdge( nn[inode], nn[inode+1], nn[inode+2]);
              else
                edge = aMesh->FindEdge( nn[inode], nn[inode+1]);
              if ( edge && avoidSet.insert( edge ).second )
                presentBndElems.push_back( edge );
            }
          }
        }
      }
    }
    else                     // elem is a face ------------------------------------------
    {
      avoidSet.clear(), avoidSet.insert( elem );
      int nbNodes = elem->NbCornerNodes();
      nodes.resize( 2 /*+ iQuad*/);
      for ( int i = 0; i < nbNodes; i++ )
      {
        nodes[0] = elem->GetNode(i);
        nodes[1] = elem->GetNode((i+1)%nbNodes);
        if ( FindFaceInSet( nodes[0], nodes[1], *elemSet, avoidSet))
          continue; // not free link

        //if ( iQuad )
        //nodes[2] = elem->GetNode( i + nbNodes );
        if ( const SMDS_MeshElement* edge =
             aMesh->FindElement(nodes,SMDSAbs_Edge,/*noMedium=*/true))
          presentBndElems.push_back( edge );
        else
          missingBndElems.push_back( nodes );
      }
    }

    // ---------------------------------
    // 2. Add missing boundary elements
    // ---------------------------------
    if ( targetMesh != myMesh )
      // instead of making a map of nodes in this mesh and targetMesh,
      // we create nodes with same IDs.
      for ( int i = 0; i < missingBndElems.size(); ++i )
      {
        TConnectivity& srcNodes = missingBndElems[i];
        TConnectivity  nodes( srcNodes.size() );
        for ( inode = 0; inode < nodes.size(); ++inode )
          nodes[inode] = getNodeWithSameID( tgtMeshDS, srcNodes[inode] );
        if ( aroundElements && tgtEditor.GetMeshDS()->FindElement( nodes,
                                                                   missType,
                                                                   /*noMedium=*/false))
          continue;
        tgtEditor.AddElement(nodes, missType, !iQuad && nodes.size()/(iQuad+1)>4);
        ++nbAddedBnd;
      }
    else
      for ( int i = 0; i < missingBndElems.size(); ++i )
      {
        TConnectivity& nodes = missingBndElems[i];
        if ( aroundElements && tgtEditor.GetMeshDS()->FindElement( nodes,
                                                                   missType,
                                                                   /*noMedium=*/false))
          continue;
        SMDS_MeshElement* elem = 
          tgtEditor.AddElement(nodes, missType, !iQuad && nodes.size()/(iQuad+1)>4);
        ++nbAddedBnd;

        // try to set a new element to a shape
        if ( myMesh->HasShapeToMesh() )
        {
          bool ok = true;
          set< pair<TopAbs_ShapeEnum, int > > mediumShapes;
          const int nbN = nodes.size() / (iQuad+1 );
          for ( inode = 0; inode < nbN && ok; ++inode )
          {
            pair<int, TopAbs_ShapeEnum> i_stype =
              helper.GetMediumPos( nodes[inode], nodes[(inode+1)%nbN]);
            if (( ok = ( i_stype.first > 0 && i_stype.second >= TopAbs_FACE )))
              mediumShapes.insert( make_pair ( i_stype.second, i_stype.first ));
          }
          if ( ok && mediumShapes.size() > 1 )
          {
            set< pair<TopAbs_ShapeEnum, int > >::iterator stype_i = mediumShapes.begin();
            pair<TopAbs_ShapeEnum, int> stype_i_0 = *stype_i;
            for ( ++stype_i; stype_i != mediumShapes.end() && ok; ++stype_i )
            {
              if (( ok = ( stype_i->first != stype_i_0.first )))
                ok = helper.IsSubShape( aMesh->IndexToShape( stype_i->second ),
                                        aMesh->IndexToShape( stype_i_0.second ));
            }
          }
          if ( ok && mediumShapes.begin()->first == missShapeType )
            aMesh->SetMeshElementOnShape( elem, mediumShapes.begin()->second );
        }
      }

    // ----------------------------------
    // 3. Copy present boundary elements
    // ----------------------------------
    if ( toCopyExistingBoundary )
      for ( int i = 0 ; i < presentBndElems.size(); ++i )
      {
        const SMDS_MeshElement* e = presentBndElems[i];
        TConnectivity nodes( e->NbNodes() );
        for ( inode = 0; inode < nodes.size(); ++inode )
          nodes[inode] = getNodeWithSameID( tgtMeshDS, e->GetNode(inode) );
        presentEditor->AddElement(nodes, e->GetType(), e->IsPoly());
      }
    else // store present elements to add them to a group
      for ( int i = 0 ; i < presentBndElems.size(); ++i )
      {
        presentEditor->myLastCreatedElems.Append(presentBndElems[i]);
      }
      
  } // loop on given elements

  // ---------------------------------------------
  // 4. Fill group with boundary elements
  // ---------------------------------------------
  if ( group )
  {
    if ( SMESHDS_Group* g = dynamic_cast<SMESHDS_Group*>( group->GetGroupDS() ))
      for ( int i = 0; i < tgtEditor.myLastCreatedElems.Size(); ++i )
        g->SMDSGroup().Add( tgtEditor.myLastCreatedElems( i+1 ));
  }
  tgtEditor.myLastCreatedElems.Clear();
  tgtEditor2.myLastCreatedElems.Clear();

  // -----------------------
  // 5. Copy given elements
  // -----------------------
  if ( toCopyElements && targetMesh != myMesh )
  {
    if (elements.empty())
      eIt = aMesh->elementsIterator(elemType);
    else
      eIt = SMDS_ElemIteratorPtr( new TSetIterator( elements.begin(), elements.end() ));
    while (eIt->more())
    {
      const SMDS_MeshElement* elem = eIt->next();
      TConnectivity nodes( elem->NbNodes() );
      for ( inode = 0; inode < nodes.size(); ++inode )
        nodes[inode] = getNodeWithSameID( tgtMeshDS, elem->GetNode(inode) );
      tgtEditor.AddElement(nodes, elemType, elem->IsPoly());

      tgtEditor.myLastCreatedElems.Clear();
    }
  }
  return nbAddedBnd;
}

Wrap a sequence of ids in a SMESH_IDSource.

Parameters:
IDsOfElementslist of mesh elements identifiers
Returns:
new ID source object
void SMESH_MeshEditor::MergeElements ( in array_of_long_array  GroupsOfElementsID)

Merge elements in each given group.

Parameters:
GroupsOfElementsIDGroups of elements for merging.

Definition at line 7808 of file SMESH_MeshEditor.cxx.

{
  myLastCreatedElems.Clear();
  myLastCreatedNodes.Clear();

  typedef list<int> TListOfIDs;
  TListOfIDs rmElemIds; // IDs of elems to remove

  SMESHDS_Mesh* aMesh = GetMeshDS();

  TListOfListOfElementsID::iterator groupsIt = theGroupsOfElementsID.begin();
  while ( groupsIt != theGroupsOfElementsID.end() ) {
    TListOfIDs& aGroupOfElemID = *groupsIt;
    aGroupOfElemID.sort();
    int elemIDToKeep = aGroupOfElemID.front();
    const SMDS_MeshElement* elemToKeep = aMesh->FindElement(elemIDToKeep);
    aGroupOfElemID.pop_front();
    TListOfIDs::iterator idIt = aGroupOfElemID.begin();
    while ( idIt != aGroupOfElemID.end() ) {
      int elemIDToRemove = *idIt;
      const SMDS_MeshElement* elemToRemove = aMesh->FindElement(elemIDToRemove);
      // add the kept element in groups of removed one (PAL15188)
      AddToSameGroups( elemToKeep, elemToRemove, aMesh );
      rmElemIds.push_back( elemIDToRemove );
      ++idIt;
    }
    ++groupsIt;
  }

  Remove( rmElemIds, false );
}

Merge equal elements in the whole mesh.

Definition at line 7845 of file SMESH_MeshEditor.cxx.

{
  set<const SMDS_MeshElement*> aMeshElements; /* empty input -
                                                 to merge equal elements in the whole mesh */
  TListOfListOfElementsID aGroupsOfElementsID;
  FindEqualElements(aMeshElements, aGroupsOfElementsID);
  MergeElements(aGroupsOfElementsID);
}

Definition at line 7072 of file SMESH_MeshEditor.cxx.

{
  MESSAGE("MergeNodes");
  myLastCreatedElems.Clear();
  myLastCreatedNodes.Clear();

  SMESHDS_Mesh* aMesh = GetMeshDS();

  TNodeNodeMap nodeNodeMap; // node to replace - new node
  set<const SMDS_MeshElement*> elems; // all elements with changed nodes
  list< int > rmElemIds, rmNodeIds;

  // Fill nodeNodeMap and elems

  TListOfListOfNodes::iterator grIt = theGroupsOfNodes.begin();
  for ( ; grIt != theGroupsOfNodes.end(); grIt++ ) {
    list<const SMDS_MeshNode*>& nodes = *grIt;
    list<const SMDS_MeshNode*>::iterator nIt = nodes.begin();
    const SMDS_MeshNode* nToKeep = *nIt;
    //MESSAGE("node to keep " << nToKeep->GetID());
    for ( ++nIt; nIt != nodes.end(); nIt++ ) {
      const SMDS_MeshNode* nToRemove = *nIt;
      nodeNodeMap.insert( TNodeNodeMap::value_type( nToRemove, nToKeep ));
      if ( nToRemove != nToKeep ) {
        //MESSAGE("  node to remove " << nToRemove->GetID());
        rmNodeIds.push_back( nToRemove->GetID() );
        AddToSameGroups( nToKeep, nToRemove, aMesh );
      }

      SMDS_ElemIteratorPtr invElemIt = nToRemove->GetInverseElementIterator();
      while ( invElemIt->more() ) {
        const SMDS_MeshElement* elem = invElemIt->next();
        elems.insert(elem);
      }
    }
  }
  // Change element nodes or remove an element

  set<const SMDS_MeshElement*>::iterator eIt = elems.begin();
  for ( ; eIt != elems.end(); eIt++ ) {
    const SMDS_MeshElement* elem = *eIt;
    //MESSAGE(" ---- inverse elem on node to remove " << elem->GetID());
    int nbNodes = elem->NbNodes();
    int aShapeId = FindShape( elem );

    set<const SMDS_MeshNode*> nodeSet;
    vector< const SMDS_MeshNode*> curNodes( nbNodes ), uniqueNodes( nbNodes );
    int iUnique = 0, iCur = 0, nbRepl = 0;
    vector<int> iRepl( nbNodes );

    // get new seq of nodes
    SMDS_ElemIteratorPtr itN = elem->nodesIterator();
    while ( itN->more() ) {
      const SMDS_MeshNode* n =
        static_cast<const SMDS_MeshNode*>( itN->next() );

      TNodeNodeMap::iterator nnIt = nodeNodeMap.find( n );
      if ( nnIt != nodeNodeMap.end() ) { // n sticks
        n = (*nnIt).second;
        // BUG 0020185: begin
        {
          bool stopRecur = false;
          set<const SMDS_MeshNode*> nodesRecur;
          nodesRecur.insert(n);
          while (!stopRecur) {
            TNodeNodeMap::iterator nnIt_i = nodeNodeMap.find( n );
            if ( nnIt_i != nodeNodeMap.end() ) { // n sticks
              n = (*nnIt_i).second;
              if (!nodesRecur.insert(n).second) {
                // error: recursive dependancy
                stopRecur = true;
              }
            }
            else
              stopRecur = true;
          }
        }
        // BUG 0020185: end
      }
      curNodes[ iCur ] = n;
      bool isUnique = nodeSet.insert( n ).second;
      if ( isUnique )
        uniqueNodes[ iUnique++ ] = n;
      else
        iRepl[ nbRepl++ ] = iCur;
      iCur++;
    }

    // Analyse element topology after replacement

    bool isOk = true;
    int nbUniqueNodes = nodeSet.size();
    //MESSAGE("nbNodes nbUniqueNodes " << nbNodes << " " << nbUniqueNodes);
    if ( nbNodes != nbUniqueNodes ) { // some nodes stick
      // Polygons and Polyhedral volumes
      if (elem->IsPoly()) {

        if (elem->GetType() == SMDSAbs_Face) {
          // Polygon
          vector<const SMDS_MeshNode *> face_nodes (nbNodes);
          int inode = 0;
          for (; inode < nbNodes; inode++) {
            face_nodes[inode] = curNodes[inode];
          }

          vector<const SMDS_MeshNode *> polygons_nodes;
          vector<int> quantities;
          int nbNew = SimplifyFace(face_nodes, polygons_nodes, quantities);
          if (nbNew > 0) {
            inode = 0;
            for (int iface = 0; iface < nbNew; iface++) {
              int nbNodes = quantities[iface];
              vector<const SMDS_MeshNode *> poly_nodes (nbNodes);
              for (int ii = 0; ii < nbNodes; ii++, inode++) {
                poly_nodes[ii] = polygons_nodes[inode];
              }
              SMDS_MeshElement* newElem = aMesh->AddPolygonalFace(poly_nodes);
              myLastCreatedElems.Append(newElem);
              if (aShapeId)
                aMesh->SetMeshElementOnShape(newElem, aShapeId);
            }

            MESSAGE("ChangeElementNodes MergeNodes Polygon");
            //aMesh->ChangeElementNodes(elem, &polygons_nodes[inode], quantities[nbNew - 1]);
            vector<const SMDS_MeshNode *> polynodes(polygons_nodes.begin()+inode,polygons_nodes.end());
            int quid =0;
            if (nbNew > 0) quid = nbNew - 1;
            vector<int> newquant(quantities.begin()+quid, quantities.end());
            const SMDS_MeshElement* newElem = 0;
            newElem = aMesh->AddPolyhedralVolume(polynodes, newquant);
            myLastCreatedElems.Append(newElem);
            if ( aShapeId && newElem )
              aMesh->SetMeshElementOnShape( newElem, aShapeId );
            rmElemIds.push_back(elem->GetID());
          }
          else {
            rmElemIds.push_back(elem->GetID());
          }

        }
        else if (elem->GetType() == SMDSAbs_Volume) {
          // Polyhedral volume
          if (nbUniqueNodes < 4) {
            rmElemIds.push_back(elem->GetID());
          }
          else {
            // each face has to be analyzed in order to check volume validity
            const SMDS_VtkVolume* aPolyedre =
              dynamic_cast<const SMDS_VtkVolume*>( elem );
            if (aPolyedre) {
              int nbFaces = aPolyedre->NbFaces();

              vector<const SMDS_MeshNode *> poly_nodes;
              vector<int> quantities;

              for (int iface = 1; iface <= nbFaces; iface++) {
                int nbFaceNodes = aPolyedre->NbFaceNodes(iface);
                vector<const SMDS_MeshNode *> faceNodes (nbFaceNodes);

                for (int inode = 1; inode <= nbFaceNodes; inode++) {
                  const SMDS_MeshNode * faceNode = aPolyedre->GetFaceNode(iface, inode);
                  TNodeNodeMap::iterator nnIt = nodeNodeMap.find(faceNode);
                  if (nnIt != nodeNodeMap.end()) { // faceNode sticks
                    faceNode = (*nnIt).second;
                  }
                  faceNodes[inode - 1] = faceNode;
                }

                SimplifyFace(faceNodes, poly_nodes, quantities);
              }

              if (quantities.size() > 3) {
                // to be done: remove coincident faces
              }

              if (quantities.size() > 3)
                {
                  MESSAGE("ChangeElementNodes MergeNodes Polyhedron");
                  //aMesh->ChangePolyhedronNodes(elem, poly_nodes, quantities);
                  const SMDS_MeshElement* newElem = 0;
                  newElem = aMesh->AddPolyhedralVolume(poly_nodes, quantities);
                  myLastCreatedElems.Append(newElem);
                  if ( aShapeId && newElem )
                    aMesh->SetMeshElementOnShape( newElem, aShapeId );
                  rmElemIds.push_back(elem->GetID());
                }
            }
            else {
              rmElemIds.push_back(elem->GetID());
            }
          }
        }
        else {
        }

        continue;
      } // poly element

      // Regular elements
      // TODO not all the possible cases are solved. Find something more generic?
      switch ( nbNodes ) {
      case 2: 
        isOk = false; break;
      case 3: 
        isOk = false; break;
      case 4:
        if ( elem->GetType() == SMDSAbs_Volume ) // TETRAHEDRON
          isOk = false;
        else { 
          if ( nbUniqueNodes < 3 )
            isOk = false;
          else if ( nbRepl == 2 && iRepl[ 1 ] - iRepl[ 0 ] == 2 )
            isOk = false; // opposite nodes stick
          //MESSAGE("isOk " << isOk);
        }
        break;
      case 6: 
        if ( nbUniqueNodes == 4 ) {
          // ---------------------------------> tetrahedron
          if (nbRepl == 3 &&
              iRepl[ 0 ] > 2 && iRepl[ 1 ] > 2 && iRepl[ 2 ] > 2 ) {
            // all top nodes stick: reverse a bottom
            uniqueNodes[ 0 ] = curNodes [ 1 ];
            uniqueNodes[ 1 ] = curNodes [ 0 ];
          }
          else if (nbRepl == 3 &&
                   iRepl[ 0 ] < 3 && iRepl[ 1 ] < 3 && iRepl[ 2 ] < 3 ) {
            // all bottom nodes stick: set a top before
            uniqueNodes[ 3 ] = uniqueNodes [ 0 ];
            uniqueNodes[ 0 ] = curNodes [ 3 ];
            uniqueNodes[ 1 ] = curNodes [ 4 ];
            uniqueNodes[ 2 ] = curNodes [ 5 ];
          }
          else if (nbRepl == 4 &&
                   iRepl[ 2 ] - iRepl [ 0 ] == 3 && iRepl[ 3 ] - iRepl [ 1 ] == 3 ) {
            // a lateral face turns into a line: reverse a bottom
            uniqueNodes[ 0 ] = curNodes [ 1 ];
            uniqueNodes[ 1 ] = curNodes [ 0 ];
          }
          else
            isOk = false;
        }
        else if ( nbUniqueNodes == 5 ) {
          // PENTAHEDRON --------------------> 2 tetrahedrons
          if ( nbRepl == 2 && iRepl[ 1 ] - iRepl [ 0 ] == 3 ) {
            // a bottom node sticks with a linked top one
            // 1.
            SMDS_MeshElement* newElem =
              aMesh->AddVolume(curNodes[ 3 ],
                               curNodes[ 4 ],
                               curNodes[ 5 ],
                               curNodes[ iRepl[ 0 ] == 2 ? 1 : 2 ]);
            myLastCreatedElems.Append(newElem);
            if ( aShapeId )
              aMesh->SetMeshElementOnShape( newElem, aShapeId );
            // 2. : reverse a bottom
            uniqueNodes[ 0 ] = curNodes [ 1 ];
            uniqueNodes[ 1 ] = curNodes [ 0 ];
            nbUniqueNodes = 4;
          }
          else
            isOk = false;
        }
        else
          isOk = false;
        break;
      case 8: {
        if(elem->IsQuadratic()) { // Quadratic quadrangle
          //   1    5    2
          //    +---+---+
          //    |       |
          //    |       |
          //   4+       +6
          //    |       |
          //    |       |
          //    +---+---+
          //   0    7    3
          isOk = false;
          if(nbRepl==2) {
            MESSAGE("nbRepl=2: " << iRepl[0] << " " << iRepl[1]);
          }
          if(nbRepl==3) {
            MESSAGE("nbRepl=3: " << iRepl[0] << " " << iRepl[1]  << " " << iRepl[2]);
            nbUniqueNodes = 6;
            if( iRepl[0]==0 && iRepl[1]==1 && iRepl[2]==4 ) {
              uniqueNodes[0] = curNodes[0];
              uniqueNodes[1] = curNodes[2];
              uniqueNodes[2] = curNodes[3];
              uniqueNodes[3] = curNodes[5];
              uniqueNodes[4] = curNodes[6];
              uniqueNodes[5] = curNodes[7];
              isOk = true;
            }
            if( iRepl[0]==0 && iRepl[1]==3 && iRepl[2]==7 ) {
              uniqueNodes[0] = curNodes[0];
              uniqueNodes[1] = curNodes[1];
              uniqueNodes[2] = curNodes[2];
              uniqueNodes[3] = curNodes[4];
              uniqueNodes[4] = curNodes[5];
              uniqueNodes[5] = curNodes[6];
              isOk = true;
            }
            if( iRepl[0]==0 && iRepl[1]==4 && iRepl[2]==7 ) {
              uniqueNodes[0] = curNodes[1];
              uniqueNodes[1] = curNodes[2];
              uniqueNodes[2] = curNodes[3];
              uniqueNodes[3] = curNodes[5];
              uniqueNodes[4] = curNodes[6];
              uniqueNodes[5] = curNodes[0];
              isOk = true;
            }
            if( iRepl[0]==1 && iRepl[1]==2 && iRepl[2]==5 ) {
              uniqueNodes[0] = curNodes[0];
              uniqueNodes[1] = curNodes[1];
              uniqueNodes[2] = curNodes[3];
              uniqueNodes[3] = curNodes[4];
              uniqueNodes[4] = curNodes[6];
              uniqueNodes[5] = curNodes[7];
              isOk = true;
            }
            if( iRepl[0]==1 && iRepl[1]==4 && iRepl[2]==5 ) {
              uniqueNodes[0] = curNodes[0];
              uniqueNodes[1] = curNodes[2];
              uniqueNodes[2] = curNodes[3];
              uniqueNodes[3] = curNodes[1];
              uniqueNodes[4] = curNodes[6];
              uniqueNodes[5] = curNodes[7];
              isOk = true;
            }
            if( iRepl[0]==2 && iRepl[1]==3 && iRepl[2]==6 ) {
              uniqueNodes[0] = curNodes[0];
              uniqueNodes[1] = curNodes[1];
              uniqueNodes[2] = curNodes[2];
              uniqueNodes[3] = curNodes[4];
              uniqueNodes[4] = curNodes[5];
              uniqueNodes[5] = curNodes[7];
              isOk = true;
            }
            if( iRepl[0]==2 && iRepl[1]==5 && iRepl[2]==6 ) {
              uniqueNodes[0] = curNodes[0];
              uniqueNodes[1] = curNodes[1];
              uniqueNodes[2] = curNodes[3];
              uniqueNodes[3] = curNodes[4];
              uniqueNodes[4] = curNodes[2];
              uniqueNodes[5] = curNodes[7];
              isOk = true;
            }
            if( iRepl[0]==3 && iRepl[1]==6 && iRepl[2]==7 ) {
              uniqueNodes[0] = curNodes[0];
              uniqueNodes[1] = curNodes[1];
              uniqueNodes[2] = curNodes[2];
              uniqueNodes[3] = curNodes[4];
              uniqueNodes[4] = curNodes[5];
              uniqueNodes[5] = curNodes[3];
              isOk = true;
            }
          }
          if(nbRepl==4) {
            MESSAGE("nbRepl=4: " << iRepl[0] << " " << iRepl[1]  << " " << iRepl[2] << " " << iRepl[3]);
          }
          if(nbRepl==5) {
            MESSAGE("nbRepl=5: " << iRepl[0] << " " << iRepl[1]  << " " << iRepl[2] << " " << iRepl[3] << " " << iRepl[4]);
          }
          break;
        }
        isOk = false;
        SMDS_VolumeTool hexa (elem);
        hexa.SetExternalNormal();
        if ( nbUniqueNodes == 4 && nbRepl == 4 ) {
          for ( int iFace = 0; iFace < 6; iFace++ ) {
            const int *ind = hexa.GetFaceNodesIndices( iFace ); // indices of face nodes
            if (curNodes[ind[ 0 ]] == curNodes[ind[ 1 ]] &&
                curNodes[ind[ 0 ]] == curNodes[ind[ 2 ]] &&
                curNodes[ind[ 0 ]] == curNodes[ind[ 3 ]] ) {
              // one face turns into a point ...
              int iOppFace = hexa.GetOppFaceIndex( iFace );
              ind = hexa.GetFaceNodesIndices( iOppFace );
              int nbStick = 0;
              for ( iCur = 0; iCur < 4 && nbStick < 2; iCur++ ) {
                if ( curNodes[ind[ iCur ]] == curNodes[ind[ iCur + 1 ]] )
                  nbStick++;
              }
              if ( nbStick == 1 ) {
                // ... and the opposite one - into a triangle.
                // set a top node
                ind = hexa.GetFaceNodesIndices( iFace );
                uniqueNodes[ 3 ] = curNodes[ind[ 0 ]];
                isOk = true;
              }
              break;
            }
          }
        }
        else if ( nbUniqueNodes == 6 && nbRepl == 2 ) {
          int nbTria = 0, iTria[3];
          const int *ind; // indices of face nodes
          // look for triangular faces
          for ( int iFace = 0; iFace < 6 && nbTria < 3; iFace++ ) {
            ind = hexa.GetFaceNodesIndices( iFace );
            TIDSortedNodeSet faceNodes;
            for ( iCur = 0; iCur < 4; iCur++ )
              faceNodes.insert( curNodes[ind[iCur]] );
            if ( faceNodes.size() == 3 )
              iTria[ nbTria++ ] = iFace;
          }
          // check if triangles are opposite
          if ( nbTria == 2 && iTria[0] == hexa.GetOppFaceIndex( iTria[1] ))
          {
            isOk = true;
            // set nodes of the bottom triangle
            ind = hexa.GetFaceNodesIndices( iTria[ 0 ]);
            vector<int> indB;
            for ( iCur = 0; iCur < 4; iCur++ )
              if ( ind[iCur] != iRepl[0] && ind[iCur] != iRepl[1])
                indB.push_back( ind[iCur] );
            if ( !hexa.IsForward() )
              std::swap( indB[0], indB[2] );
            for ( iCur = 0; iCur < 3; iCur++ )
              uniqueNodes[ iCur ] = curNodes[indB[iCur]];
            // set nodes of the top triangle
            const int *indT = hexa.GetFaceNodesIndices( iTria[ 1 ]);
            for ( iCur = 0; iCur < 3; ++iCur )
              for ( int j = 0; j < 4; ++j )
                if ( hexa.IsLinked( indB[ iCur ], indT[ j ] ))
                {
                  uniqueNodes[ iCur + 3 ] = curNodes[ indT[ j ]];
                  break;
                }
          }
          break;
        }
        else if (nbUniqueNodes == 5 && nbRepl == 4 ) {
          for ( int iFace = 0; iFace < 6; iFace++ ) {
            const int *ind = hexa.GetFaceNodesIndices( iFace ); // indices of face nodes
            if (curNodes[ind[ 0 ]] == curNodes[ind[ 1 ]] &&
                curNodes[ind[ 0 ]] == curNodes[ind[ 2 ]] &&
                curNodes[ind[ 0 ]] == curNodes[ind[ 3 ]] ) {
              // one face turns into a point ...
              int iOppFace = hexa.GetOppFaceIndex( iFace );
              ind = hexa.GetFaceNodesIndices( iOppFace );
              int nbStick = 0;
              iUnique = 2;  // reverse a tetrahedron 1 bottom
              for ( iCur = 0; iCur < 4 && nbStick == 0; iCur++ ) {
                if ( curNodes[ind[ iCur ]] == curNodes[ind[ iCur + 1 ]] )
                  nbStick++;
                else if ( iUnique >= 0 )
                  uniqueNodes[ iUnique-- ] = curNodes[ind[ iCur ]];
              }
              if ( nbStick == 0 ) {
                // ... and the opposite one is a quadrangle
                // set a top node
                const int* indTop = hexa.GetFaceNodesIndices( iFace );
                uniqueNodes[ 3 ] = curNodes[indTop[ 0 ]];
                nbUniqueNodes = 4;
                // tetrahedron 2
                SMDS_MeshElement* newElem =
                  aMesh->AddVolume(curNodes[ind[ 0 ]],
                                   curNodes[ind[ 3 ]],
                                   curNodes[ind[ 2 ]],
                                   curNodes[indTop[ 0 ]]);
                myLastCreatedElems.Append(newElem);
                if ( aShapeId )
                  aMesh->SetMeshElementOnShape( newElem, aShapeId );
                isOk = true;
              }
              break;
            }
          }
        }
        else if ( nbUniqueNodes == 6 && nbRepl == 4 ) {
          // find indices of quad and tri faces
          int iQuadFace[ 6 ], iTriFace[ 6 ], nbQuad = 0, nbTri = 0, iFace;
          for ( iFace = 0; iFace < 6; iFace++ ) {
            const int *ind = hexa.GetFaceNodesIndices( iFace ); // indices of face nodes
            nodeSet.clear();
            for ( iCur = 0; iCur < 4; iCur++ )
              nodeSet.insert( curNodes[ind[ iCur ]] );
            nbUniqueNodes = nodeSet.size();
            if ( nbUniqueNodes == 3 )
              iTriFace[ nbTri++ ] = iFace;
            else if ( nbUniqueNodes == 4 )
              iQuadFace[ nbQuad++ ] = iFace;
          }
          if (nbQuad == 2 && nbTri == 4 &&
              hexa.GetOppFaceIndex( iQuadFace[ 0 ] ) == iQuadFace[ 1 ]) {
            // 2 opposite quadrangles stuck with a diagonal;
            // sample groups of merged indices: (0-4)(2-6)
            // --------------------------------------------> 2 tetrahedrons
            const int *ind1 = hexa.GetFaceNodesIndices( iQuadFace[ 0 ]); // indices of quad1 nodes
            const int *ind2 = hexa.GetFaceNodesIndices( iQuadFace[ 1 ]);
            int i0, i1d, i2, i3d, i0t, i2t; // d-daigonal, t-top
            if (curNodes[ind1[ 0 ]] == curNodes[ind2[ 0 ]] &&
                curNodes[ind1[ 2 ]] == curNodes[ind2[ 2 ]]) {
              // stuck with 0-2 diagonal
              i0  = ind1[ 3 ];
              i1d = ind1[ 0 ];
              i2  = ind1[ 1 ];
              i3d = ind1[ 2 ];
              i0t = ind2[ 1 ];
              i2t = ind2[ 3 ];
            }
            else if (curNodes[ind1[ 1 ]] == curNodes[ind2[ 3 ]] &&
                     curNodes[ind1[ 3 ]] == curNodes[ind2[ 1 ]]) {
              // stuck with 1-3 diagonal
              i0  = ind1[ 0 ];
              i1d = ind1[ 1 ];
              i2  = ind1[ 2 ];
              i3d = ind1[ 3 ];
              i0t = ind2[ 0 ];
              i2t = ind2[ 1 ];
            }
            else {
              ASSERT(0);
            }
            // tetrahedron 1
            uniqueNodes[ 0 ] = curNodes [ i0 ];
            uniqueNodes[ 1 ] = curNodes [ i1d ];
            uniqueNodes[ 2 ] = curNodes [ i3d ];
            uniqueNodes[ 3 ] = curNodes [ i0t ];
            nbUniqueNodes = 4;
            // tetrahedron 2
            SMDS_MeshElement* newElem = aMesh->AddVolume(curNodes[ i1d ],
                                                         curNodes[ i2 ],
                                                         curNodes[ i3d ],
                                                         curNodes[ i2t ]);
            myLastCreatedElems.Append(newElem);
            if ( aShapeId )
              aMesh->SetMeshElementOnShape( newElem, aShapeId );
            isOk = true;
          }
          else if (( nbTri == 2 && nbQuad == 3 ) || // merged (0-4)(1-5)
                   ( nbTri == 4 && nbQuad == 2 )) { // merged (7-4)(1-5)
            // --------------------------------------------> prism
            // find 2 opposite triangles
            nbUniqueNodes = 6;
            for ( iFace = 0; iFace + 1 < nbTri; iFace++ ) {
              if ( hexa.GetOppFaceIndex( iTriFace[ iFace ] ) == iTriFace[ iFace + 1 ]) {
                // find indices of kept and replaced nodes
                // and fill unique nodes of 2 opposite triangles
                const int *ind1 = hexa.GetFaceNodesIndices( iTriFace[ iFace ]);
                const int *ind2 = hexa.GetFaceNodesIndices( iTriFace[ iFace + 1 ]);
                const SMDS_MeshNode** hexanodes = hexa.GetNodes();
                // fill unique nodes
                iUnique = 0;
                isOk = true;
                for ( iCur = 0; iCur < 4 && isOk; iCur++ ) {
                  const SMDS_MeshNode* n     = curNodes[ind1[ iCur ]];
                  const SMDS_MeshNode* nInit = hexanodes[ind1[ iCur ]];
                  if ( n == nInit ) {
                    // iCur of a linked node of the opposite face (make normals co-directed):
                    int iCurOpp = ( iCur == 1 || iCur == 3 ) ? 4 - iCur : iCur;
                    // check that correspondent corners of triangles are linked
                    if ( !hexa.IsLinked( ind1[ iCur ], ind2[ iCurOpp ] ))
                      isOk = false;
                    else {
                      uniqueNodes[ iUnique ] = n;
                      uniqueNodes[ iUnique + 3 ] = curNodes[ind2[ iCurOpp ]];
                      iUnique++;
                    }
                  }
                }
                break;
              }
            }
          }
        } // if ( nbUniqueNodes == 6 && nbRepl == 4 )
        else
        {
          MESSAGE("MergeNodes() removes hexahedron "<< elem);
        }
        break;
      } // HEXAHEDRON

      default:
        isOk = false;
      } // switch ( nbNodes )

    } // if ( nbNodes != nbUniqueNodes ) // some nodes stick

    if ( isOk ) { // the elem remains valid after sticking nodes
      if (elem->IsPoly() && elem->GetType() == SMDSAbs_Volume)
      {
        // Change nodes of polyedre
        const SMDS_VtkVolume* aPolyedre =
          dynamic_cast<const SMDS_VtkVolume*>( elem );
        if (aPolyedre) {
          int nbFaces = aPolyedre->NbFaces();

          vector<const SMDS_MeshNode *> poly_nodes;
          vector<int> quantities (nbFaces);

          for (int iface = 1; iface <= nbFaces; iface++) {
            int inode, nbFaceNodes = aPolyedre->NbFaceNodes(iface);
            quantities[iface - 1] = nbFaceNodes;

            for (inode = 1; inode <= nbFaceNodes; inode++) {
              const SMDS_MeshNode* curNode = aPolyedre->GetFaceNode(iface, inode);

              TNodeNodeMap::iterator nnIt = nodeNodeMap.find( curNode );
              if (nnIt != nodeNodeMap.end()) { // curNode sticks
                curNode = (*nnIt).second;
              }
              poly_nodes.push_back(curNode);
            }
          }
          aMesh->ChangePolyhedronNodes( elem, poly_nodes, quantities );
        }
      }
      else // replace non-polyhedron elements
      {
        const SMDSAbs_ElementType etyp = elem->GetType();
        const int elemId               = elem->GetID();
        const bool isPoly              = (elem->GetEntityType() == SMDSEntity_Polygon);
        uniqueNodes.resize(nbUniqueNodes);

        SMESHDS_SubMesh * sm = aShapeId > 0 ? aMesh->MeshElements(aShapeId) : 0;

        aMesh->RemoveFreeElement(elem, sm, /*fromGroups=*/false);
        SMDS_MeshElement* newElem = this->AddElement(uniqueNodes, etyp, isPoly, elemId);
        if ( sm && newElem )
          sm->AddElement( newElem );
        if ( elem != newElem )
          ReplaceElemInGroups( elem, newElem, aMesh );
      }
    }
    else {
      // Remove invalid regular element or invalid polygon
      rmElemIds.push_back( elem->GetID() );
    }

  } // loop on elements

  // Remove bad elements, then equal nodes (order important)

  Remove( rmElemIds, false );
  Remove( rmNodeIds, true );

}
void SMESH::SMESH_MeshEditor::Mirror ( in long_array  IDsOfElements,
in AxisStruct  Mirror,
in MirrorType  Type,
in boolean  Copy 
)
SMESH_Mesh SMESH::SMESH_MeshEditor::MirrorMakeMesh ( in long_array  IDsOfElements,
in AxisStruct  Mirror,
in MirrorType  Type,
in boolean  CopyGroups,
in string  MeshName 
)
void SMESH::SMESH_MeshEditor::MirrorObject ( in SMESH_IDSource  theObject,
in AxisStruct  Mirror,
in MirrorType  Type,
in boolean  Copy 
)
SMESH_Mesh SMESH::SMESH_MeshEditor::MirrorObjectMakeMesh ( in SMESH_IDSource  theObject,
in AxisStruct  Mirror,
in MirrorType  Type,
in boolean  CopyGroups,
in string  MeshName 
)
long SMESH::SMESH_MeshEditor::MoveClosestNodeToPoint ( in double  x,
in double  y,
in double  z,
in long  nodeID 
)

If the given ID is a valid node ID (nodeID > 0), just move this node, else move the node closest to the point to point's location and return ID of the node.

boolean SMESH::SMESH_MeshEditor::MoveNode ( in long  NodeID,
in double  x,
in double  y,
in double  z 
)
bool SMESH_MeshEditor::QuadToTri ( in long_array  IDsOfElements,
in NumericalFunctor  Criterion 
)

Split quadrangles into triangles.

Parameters:
theElemsThe faces to be splitted.
theCriterionIs used to choose a diagonal for splitting.
Returns:
TRUE in case of success, FALSE otherwise.

Definition at line 1075 of file SMESH_MeshEditor.cxx.

{
  myLastCreatedElems.Clear();
  myLastCreatedNodes.Clear();

  MESSAGE( "::QuadToTri()" );

  if ( !theCrit.get() )
    return false;

  SMESHDS_Mesh * aMesh = GetMeshDS();

  Handle(Geom_Surface) surface;
  SMESH_MesherHelper   helper( *GetMesh() );

  TIDSortedElemSet::iterator itElem;
  for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) {
    const SMDS_MeshElement* elem = *itElem;
    if ( !elem || elem->GetType() != SMDSAbs_Face )
      continue;
    if ( elem->NbCornerNodes() != 4 )
      continue;

    // retrieve element nodes
    vector< const SMDS_MeshNode* > aNodes( elem->begin_nodes(), elem->end_nodes() );

    // compare two sets of possible triangles
    double aBadRate1, aBadRate2; // to what extent a set is bad
    SMDS_FaceOfNodes tr1 ( aNodes[0], aNodes[1], aNodes[2] );
    SMDS_FaceOfNodes tr2 ( aNodes[2], aNodes[3], aNodes[0] );
    aBadRate1 = getBadRate( &tr1, theCrit ) + getBadRate( &tr2, theCrit );

    SMDS_FaceOfNodes tr3 ( aNodes[1], aNodes[2], aNodes[3] );
    SMDS_FaceOfNodes tr4 ( aNodes[3], aNodes[0], aNodes[1] );
    aBadRate2 = getBadRate( &tr3, theCrit ) + getBadRate( &tr4, theCrit );

    int aShapeId = FindShape( elem );
    const SMDS_MeshElement* newElem1 = 0;
    const SMDS_MeshElement* newElem2 = 0;

    if( !elem->IsQuadratic() ) {

      // split liner quadrangle

      if ( aBadRate1 <= aBadRate2 ) {
        // tr1 + tr2 is better
        newElem1 = aMesh->AddFace( aNodes[2], aNodes[3], aNodes[0] );
        newElem2 = aMesh->AddFace( aNodes[2], aNodes[0], aNodes[1] );
      }
      else {
        // tr3 + tr4 is better
        newElem1 = aMesh->AddFace( aNodes[3], aNodes[0], aNodes[1] );
        newElem2 = aMesh->AddFace( aNodes[3], aNodes[1], aNodes[2] );
      }
    }
    else {

      // split quadratic quadrangle

      // get surface elem is on
      if ( aShapeId != helper.GetSubShapeID() ) {
        surface.Nullify();
        TopoDS_Shape shape;
        if ( aShapeId > 0 )
          shape = aMesh->IndexToShape( aShapeId );
        if ( !shape.IsNull() && shape.ShapeType() == TopAbs_FACE ) {
          TopoDS_Face face = TopoDS::Face( shape );
          surface = BRep_Tool::Surface( face );
          if ( !surface.IsNull() )
            helper.SetSubShape( shape );
        }
      }
      // find middle point for (0,1,2,3)
      // and create a node in this point;
      const SMDS_MeshNode* newN = 0;
      if ( aNodes.size() == 9 )
      {
        // SMDSEntity_BiQuad_Quadrangle
        newN = aNodes.back();
      }
      else
      {
        gp_XYZ p( 0,0,0 );
        if ( surface.IsNull() )
        {
          for ( int i = 0; i < 4; i++ )
            p += gp_XYZ(aNodes[i]->X(), aNodes[i]->Y(), aNodes[i]->Z() );
          p /= 4;
        }
        else
        {
          const SMDS_MeshNode* inFaceNode = 0;
          if ( helper.GetNodeUVneedInFaceNode() )
            for ( size_t i = 0; i < aNodes.size() && !inFaceNode; ++i )
              if ( aNodes[ i ]->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE )
                inFaceNode = aNodes[ i ];

          TopoDS_Face face = TopoDS::Face( helper.GetSubShape() );
          gp_XY uv( 0,0 );
          for ( int i = 0; i < 4; i++ )
            uv += helper.GetNodeUV( face, aNodes[i], inFaceNode );
          uv /= 4.;
          p = surface->Value( uv.X(), uv.Y() ).XYZ();
        }
        newN = aMesh->AddNode( p.X(), p.Y(), p.Z() );
        myLastCreatedNodes.Append(newN);
      }
      // create a new element
      if ( aBadRate1 <= aBadRate2 ) {
        newElem1 = aMesh->AddFace(aNodes[2], aNodes[3], aNodes[0],
                                  aNodes[6], aNodes[7], newN );
        newElem2 = aMesh->AddFace(aNodes[2], aNodes[0], aNodes[1],
                                  newN,      aNodes[4], aNodes[5] );
      }
      else {
        newElem1 = aMesh->AddFace(aNodes[3], aNodes[0], aNodes[1],
                                  aNodes[7], aNodes[4], newN );
        newElem2 = aMesh->AddFace(aNodes[3], aNodes[1], aNodes[2],
                                  newN,      aNodes[5], aNodes[6] );
      }
    } // quadratic case

    // care of a new element

    myLastCreatedElems.Append(newElem1);
    myLastCreatedElems.Append(newElem2);
    AddToSameGroups( newElem1, elem, aMesh );
    AddToSameGroups( newElem2, elem, aMesh );

    // put a new triangle on the same shape
    if ( aShapeId )
      {
        aMesh->SetMeshElementOnShape( newElem1, aShapeId );
        aMesh->SetMeshElementOnShape( newElem2, aShapeId );
      }
    aMesh->RemoveElement( elem );
  }
  return true;
}

Here is the call graph for this function:

boolean SMESH::SMESH_MeshEditor::QuadToTriObject ( in SMESH_IDSource  theObject,
in NumericalFunctor  Criterion 
)

Split quadrangles into triangles.

Behaves like the above method, taking list of elements from theObject

boolean SMESH::SMESH_MeshEditor::RemoveElements ( in long_array  IDsOfElements)

Remove mesh elements specified by their identifiers.

Parameters:
IDsOfElementslist of mesh elements identifiers
Returns:
true if elements are correctly removed or false otherwise

Remove mesh nodes specified by their identifiers.

Parameters:
IDsOfNodeslist of mesh nodes identifiers
Returns:
true if nodes are correctly removed or false otherwise

Remove all orphan nodes.

Returns:
number of removed nodes
bool SMESH_MeshEditor::Reorient ( in long_array  IDsOfElements)

Definition at line 963 of file SMESH_MeshEditor.cxx.

{
  MESSAGE("Reorient");
  myLastCreatedElems.Clear();
  myLastCreatedNodes.Clear();

  if (!theElem)
    return false;
  SMDS_ElemIteratorPtr it = theElem->nodesIterator();
  if ( !it || !it->more() )
    return false;

  switch ( theElem->GetType() ) {

  case SMDSAbs_Edge:
  case SMDSAbs_Face: {
    if(!theElem->IsQuadratic()) {
      int i = theElem->NbNodes();
      vector<const SMDS_MeshNode*> aNodes( i );
      while ( it->more() )
        aNodes[ --i ]= static_cast<const SMDS_MeshNode*>( it->next() );
      return GetMeshDS()->ChangeElementNodes( theElem, &aNodes[0], theElem->NbNodes() );
    }
    else {
      // quadratic elements
      if(theElem->GetType()==SMDSAbs_Edge) {
        vector<const SMDS_MeshNode*> aNodes(3);
        aNodes[1]= static_cast<const SMDS_MeshNode*>( it->next() );
        aNodes[0]= static_cast<const SMDS_MeshNode*>( it->next() );
        aNodes[2]= static_cast<const SMDS_MeshNode*>( it->next() );
        return GetMeshDS()->ChangeElementNodes( theElem, &aNodes[0], 3 );
      }
      else {
        int nbn = theElem->NbNodes();
        vector<const SMDS_MeshNode*> aNodes(nbn);
        aNodes[0]= static_cast<const SMDS_MeshNode*>( it->next() );
        int i=1;
        for(; i<nbn/2; i++) {
          aNodes[nbn/2-i]= static_cast<const SMDS_MeshNode*>( it->next() );
        }
        for(i=0; i<nbn/2; i++) {
          aNodes[nbn-i-1]= static_cast<const SMDS_MeshNode*>( it->next() );
        }
        return GetMeshDS()->ChangeElementNodes( theElem, &aNodes[0], nbn );
      }
    }
  }
  case SMDSAbs_Volume: {
    if (theElem->IsPoly()) {
      // TODO reorient vtk polyhedron
      MESSAGE("reorient vtk polyhedron ?");
      const SMDS_VtkVolume* aPolyedre =
        dynamic_cast<const SMDS_VtkVolume*>( theElem );
      if (!aPolyedre) {
        MESSAGE("Warning: bad volumic element");
        return false;
      }

      int nbFaces = aPolyedre->NbFaces();
      vector<const SMDS_MeshNode *> poly_nodes;
      vector<int> quantities (nbFaces);

      // reverse each face of the polyedre
      for (int iface = 1; iface <= nbFaces; iface++) {
        int inode, nbFaceNodes = aPolyedre->NbFaceNodes(iface);
        quantities[iface - 1] = nbFaceNodes;

        for (inode = nbFaceNodes; inode >= 1; inode--) {
          const SMDS_MeshNode* curNode = aPolyedre->GetFaceNode(iface, inode);
          poly_nodes.push_back(curNode);
        }
      }

      return GetMeshDS()->ChangePolyhedronNodes( theElem, poly_nodes, quantities );

    }
    else {
      SMDS_VolumeTool vTool;
      if ( !vTool.Set( theElem ))
        return false;
      vTool.Inverse();
      MESSAGE("ChangeElementNodes reorient: check vTool.Inverse");
      return GetMeshDS()->ChangeElementNodes( theElem, vTool.GetNodes(), vTool.NbNodes() );
    }
  }
  default:;
  }

  return false;
}
void SMESH::SMESH_MeshEditor::Rotate ( in long_array  IDsOfElements,
in AxisStruct  Axis,
in double  AngleInRadians,
in boolean  Copy 
)
ListOfGroups SMESH::SMESH_MeshEditor::RotateMakeGroups ( in long_array  IDsOfElements,
in AxisStruct  Axis,
in double  AngleInRadians 
)
SMESH_Mesh SMESH::SMESH_MeshEditor::RotateMakeMesh ( in long_array  IDsOfElements,
in AxisStruct  Axis,
in double  AngleInRadians,
in boolean  CopyGroups,
in string  MeshName 
)
void SMESH::SMESH_MeshEditor::RotateObject ( in SMESH_IDSource  theObject,
in AxisStruct  Axis,
in double  AngleInRadians,
in boolean  Copy 
)
ListOfGroups SMESH::SMESH_MeshEditor::RotateObjectMakeGroups ( in SMESH_IDSource  theObject,
in AxisStruct  Axis,
in double  AngleInRadians 
)
SMESH_Mesh SMESH::SMESH_MeshEditor::RotateObjectMakeMesh ( in SMESH_IDSource  theObject,
in AxisStruct  Axis,
in double  AngleInRadians,
in boolean  CopyGroups,
in string  MeshName 
)
SMESH_MeshEditor::PGroupIDs SMESH_MeshEditor::RotationSweep ( in long_array  IDsOfElements,
in AxisStruct  Axix,
in double  AngleInRadians,
in long  NbOfSteps,
in double  Tolerance 
)

Genarate dim+1 elements by rotation of given elements around axis.

Parameters:
IDsOfElements- elements to ratate
Axix- rotation axis
AngleInRadians- rotation angle
NbOfSteps- number of elements to generate from one element

Definition at line 4316 of file SMESH_MeshEditor.cxx.

{
  myLastCreatedElems.Clear();
  myLastCreatedNodes.Clear();

  // source elements for each generated one
  SMESH_SequenceOfElemPtr srcElems, srcNodes;

  MESSAGE( "RotationSweep()");
  gp_Trsf aTrsf;
  aTrsf.SetRotation( theAxis, theAngle );
  gp_Trsf aTrsf2;
  aTrsf2.SetRotation( theAxis, theAngle/2. );

  gp_Lin aLine( theAxis );
  double aSqTol = theTol * theTol;

  SMESHDS_Mesh* aMesh = GetMeshDS();

  TNodeOfNodeListMap mapNewNodes;
  TElemOfVecOfNnlmiMap mapElemNewNodes;
  TElemOfElemListMap newElemsMap;

  const bool isQuadraticMesh = bool( myMesh->NbEdges(ORDER_QUADRATIC) +
                                     myMesh->NbFaces(ORDER_QUADRATIC) +
                                     myMesh->NbVolumes(ORDER_QUADRATIC) );
  // loop on theElems
  TIDSortedElemSet::iterator itElem;
  for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) {
    const SMDS_MeshElement* elem = *itElem;
    if ( !elem || elem->GetType() == SMDSAbs_Volume )
      continue;
    vector<TNodeOfNodeListMapItr> & newNodesItVec = mapElemNewNodes[ elem ];
    newNodesItVec.reserve( elem->NbNodes() );

    // loop on elem nodes
    SMDS_ElemIteratorPtr itN = elem->nodesIterator();
    while ( itN->more() )
    {
      // check if a node has been already sweeped
      const SMDS_MeshNode* node = cast2Node( itN->next() );

      gp_XYZ aXYZ( node->X(), node->Y(), node->Z() );
      double coord[3];
      aXYZ.Coord( coord[0], coord[1], coord[2] );
      bool isOnAxis = ( aLine.SquareDistance( aXYZ ) <= aSqTol );

      TNodeOfNodeListMapItr nIt =
        mapNewNodes.insert( make_pair( node, list<const SMDS_MeshNode*>() )).first;
      list<const SMDS_MeshNode*>& listNewNodes = nIt->second;
      if ( listNewNodes.empty() )
      {
        // check if we are to create medium nodes between corner ones
        bool needMediumNodes = false;
        if ( isQuadraticMesh )
        {
          SMDS_ElemIteratorPtr it = node->GetInverseElementIterator();
          while (it->more() && !needMediumNodes )
          {
            const SMDS_MeshElement* invElem = it->next();
            if ( invElem != elem && !theElems.count( invElem )) continue;
            needMediumNodes = ( invElem->IsQuadratic() && !invElem->IsMediumNode(node) );
            if ( !needMediumNodes && invElem->GetEntityType() == SMDSEntity_BiQuad_Quadrangle )
              needMediumNodes = true;
          }
        }

        // make new nodes
        const SMDS_MeshNode * newNode = node;
        for ( int i = 0; i < theNbSteps; i++ ) {
          if ( !isOnAxis ) {
            if ( needMediumNodes )  // create a medium node
            {
              aTrsf2.Transforms( coord[0], coord[1], coord[2] );
              newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
              myLastCreatedNodes.Append(newNode);
              srcNodes.Append( node );
              listNewNodes.push_back( newNode );
              aTrsf2.Transforms( coord[0], coord[1], coord[2] );
            }
            else {
              aTrsf.Transforms( coord[0], coord[1], coord[2] );
            }
            // create a corner node
            newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
            myLastCreatedNodes.Append(newNode);
            srcNodes.Append( node );
            listNewNodes.push_back( newNode );
          }
          else {
            listNewNodes.push_back( newNode );
            // if ( needMediumNodes )
            //   listNewNodes.push_back( newNode );
          }
        }
      }
      newNodesItVec.push_back( nIt );
    }
    // make new elements
    sweepElement( elem, newNodesItVec, newElemsMap[elem], theNbSteps, srcElems );
  }

  if ( theMakeWalls )
    makeWalls( mapNewNodes, newElemsMap, mapElemNewNodes, theElems, theNbSteps, srcElems );

  PGroupIDs newGroupIDs;
  if ( theMakeGroups )
    newGroupIDs = generateGroups( srcNodes, srcElems, "rotated");

  return newGroupIDs;
}

Here is the call graph for this function:

ListOfGroups SMESH::SMESH_MeshEditor::RotationSweepMakeGroups ( in long_array  IDsOfElements,
in AxisStruct  Axix,
in double  AngleInRadians,
in long  NbOfSteps,
in double  Tolerance 
)

Same as previous but additionally create groups of elements generated from elements belonging to preexisting groups.

void SMESH::SMESH_MeshEditor::RotationSweepObject ( in SMESH_IDSource  theObject,
in AxisStruct  Axix,
in double  AngleInRadians,
in long  NbOfSteps,
in double  Tolerance 
)

Genarate dim+1 elements by rotation of the object around axis.

Parameters:
theObject- object containing elements to ratate
Axix- rotation axis
AngleInRadians- rotation angle
NbOfSteps- number of elements to generate from one element
void SMESH::SMESH_MeshEditor::RotationSweepObject1D ( in SMESH_IDSource  theObject,
in AxisStruct  Axix,
in double  AngleInRadians,
in long  NbOfSteps,
in double  Tolerance 
)

Genarate dim+1 elements by rotation of the object around axis.

Parameters:
theObject- object containing elements to ratate
Axix- rotation axis
AngleInRadians- rotation angle
NbOfSteps- number of elements to generate from one element
ListOfGroups SMESH::SMESH_MeshEditor::RotationSweepObject1DMakeGroups ( in SMESH_IDSource  theObject,
in AxisStruct  Axix,
in double  AngleInRadians,
in long  NbOfSteps,
in double  Tolerance 
)

Same as previous but additionally create groups of elements generated from elements belonging to preexisting groups.

void SMESH::SMESH_MeshEditor::RotationSweepObject2D ( in SMESH_IDSource  theObject,
in AxisStruct  Axix,
in double  AngleInRadians,
in long  NbOfSteps,
in double  Tolerance 
)

Genarate dim+1 elements by rotation of the object around axis.

Parameters:
theObject- object containing elements to ratate
Axix- rotation axis
AngleInRadians- rotation angle
NbOfSteps- number of elements to generate from one element
ListOfGroups SMESH::SMESH_MeshEditor::RotationSweepObject2DMakeGroups ( in SMESH_IDSource  theObject,
in AxisStruct  Axix,
in double  AngleInRadians,
in long  NbOfSteps,
in double  Tolerance 
)

Same as previous but additionally create groups of elements generated from elements belonging to preexisting groups.

ListOfGroups SMESH::SMESH_MeshEditor::RotationSweepObjectMakeGroups ( in SMESH_IDSource  theObject,
in AxisStruct  Axix,
in double  AngleInRadians,
in long  NbOfSteps,
in double  Tolerance 
)

Same as previous but additionally create groups of elements generated from elements belonging to preexisting groups.

void SMESH::SMESH_MeshEditor::Scale ( in SMESH_IDSource  theObject,
in PointStruct  thePoint,
in double_array  theScaleFact,
in boolean  Copy 
)
ListOfGroups SMESH::SMESH_MeshEditor::ScaleMakeGroups ( in SMESH_IDSource  theObject,
in PointStruct  thePoint,
in double_array  theScaleFact 
)
SMESH_Mesh SMESH::SMESH_MeshEditor::ScaleMakeMesh ( in SMESH_IDSource  theObject,
in PointStruct  thePoint,
in double_array  theScaleFact,
in boolean  CopyGroups,
in string  MeshName 
)
void SMESH::SMESH_MeshEditor::SetMeshElementOnShape ( in long  ElementID,
in long  ShapeID 
) raises (SALOME::SALOME_Exception)

Bind an element to a shape.

Parameters:
ElementID- element ID
ShapeID- shape ID available through GEOM_Object.GetSubShapeIndices()[0]
void SMESH::SMESH_MeshEditor::SetNodeInVolume ( in long  NodeID,
in long  SolidID 
) raises (SALOME::SALOME_Exception)

Bind a node to a solid.

Parameters:
NodeID- node ID
SolidID- vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
void SMESH::SMESH_MeshEditor::SetNodeOnEdge ( in long  NodeID,
in long  EdgeID,
in double  paramOnEdge 
) raises (SALOME::SALOME_Exception)

Store node position on an edge.

Parameters:
NodeID- node ID
EdgeID- edge ID available through GEOM_Object.GetSubShapeIndices()[0]
paramOnEdge- parameter on edge where the node is located
void SMESH::SMESH_MeshEditor::SetNodeOnFace ( in long  NodeID,
in long  FaceID,
in double  u,
in double  v 
) raises (SALOME::SALOME_Exception)

Store node position on a face.

Parameters:
NodeID- node ID
FaceID- face ID available through GEOM_Object.GetSubShapeIndices()[0]
u- U parameter on face where the node is located
v- V parameter on face where the node is located
void SMESH::SMESH_MeshEditor::SetNodeOnVertex ( in long  NodeID,
in long  VertexID 
) raises (SALOME::SALOME_Exception)

Bind a node to a vertex.

Parameters:
NodeID- node ID
VertexID- vertex ID available through GEOM_Object.GetSubShapeIndices()[0]
Sew_Error SMESH::SMESH_MeshEditor::SewBorderToSide ( in long  FirstNodeIDOnFreeBorder,
in long  SecondNodeIDOnFreeBorder,
in long  LastNodeIDOnFreeBorder,
in long  FirstNodeIDOnSide,
in long  LastNodeIDOnSide,
in boolean  CreatePolygons,
in boolean  CreatePolyedrs 
)
Sew_Error SMESH::SMESH_MeshEditor::SewConformFreeBorders ( in long  FirstNodeID1,
in long  SecondNodeID1,
in long  LastNodeID1,
in long  FirstNodeID2,
in long  SecondNodeID2 
)
Sew_Error SMESH::SMESH_MeshEditor::SewFreeBorders ( in long  FirstNodeID1,
in long  SecondNodeID1,
in long  LastNodeID1,
in long  FirstNodeID2,
in long  SecondNodeID2,
in long  LastNodeID2,
in boolean  CreatePolygons,
in boolean  CreatePolyedrs 
)
SMESH_MeshEditor::Sew_Error SMESH_MeshEditor::SewSideElements ( in long_array  IDsOfSide1Elements,
in long_array  IDsOfSide2Elements,
in long  NodeID1OfSide1ToMerge,
in long  NodeID1OfSide2ToMerge,
in long  NodeID2OfSide1ToMerge,
in long  NodeID2OfSide2ToMerge 
)

Definition at line 9553 of file SMESH_MeshEditor.cxx.

{
  myLastCreatedElems.Clear();
  myLastCreatedNodes.Clear();

  MESSAGE ("::::SewSideElements()");
  if ( theSide1.size() != theSide2.size() )
    return SEW_DIFF_NB_OF_ELEMENTS;

  Sew_Error aResult = SEW_OK;
  // Algo:
  // 1. Build set of faces representing each side
  // 2. Find which nodes of the side 1 to merge with ones on the side 2
  // 3. Replace nodes in elements of the side 1 and remove replaced nodes

  // =======================================================================
  // 1. Build set of faces representing each side:
  // =======================================================================
  // a. build set of nodes belonging to faces
  // b. complete set of faces: find missing faces whose nodes are in set of nodes
  // c. create temporary faces representing side of volumes if correspondent
  //    face does not exist

  SMESHDS_Mesh* aMesh = GetMeshDS();
  // TODO algoritm not OK with vtkUnstructuredGrid: 2 meshes can't share nodes
  //SMDS_Mesh aTmpFacesMesh; // try to use the same mesh
  TIDSortedElemSet             faceSet1, faceSet2;
  set<const SMDS_MeshElement*> volSet1,  volSet2;
  set<const SMDS_MeshNode*>    nodeSet1, nodeSet2;
  TIDSortedElemSet             * faceSetPtr[] = { &faceSet1, &faceSet2 };
  set<const SMDS_MeshElement*> *  volSetPtr[] = { &volSet1,  &volSet2  };
  set<const SMDS_MeshNode*>    * nodeSetPtr[] = { &nodeSet1, &nodeSet2 };
  TIDSortedElemSet             * elemSetPtr[] = { &theSide1, &theSide2 };
  int iSide, iFace, iNode;

  list<const SMDS_MeshElement* > tempFaceList;
  for ( iSide = 0; iSide < 2; iSide++ ) {
    set<const SMDS_MeshNode*>    * nodeSet = nodeSetPtr[ iSide ];
    TIDSortedElemSet             * elemSet = elemSetPtr[ iSide ];
    TIDSortedElemSet             * faceSet = faceSetPtr[ iSide ];
    set<const SMDS_MeshElement*> * volSet  = volSetPtr [ iSide ];
    set<const SMDS_MeshElement*>::iterator vIt;
    TIDSortedElemSet::iterator eIt;
    set<const SMDS_MeshNode*>::iterator    nIt;

    // check that given nodes belong to given elements
    const SMDS_MeshNode* n1 = ( iSide == 0 ) ? theFirstNode1 : theFirstNode2;
    const SMDS_MeshNode* n2 = ( iSide == 0 ) ? theSecondNode1 : theSecondNode2;
    int firstIndex = -1, secondIndex = -1;
    for (eIt = elemSet->begin(); eIt != elemSet->end(); eIt++ ) {
      const SMDS_MeshElement* elem = *eIt;
      if ( firstIndex  < 0 ) firstIndex  = elem->GetNodeIndex( n1 );
      if ( secondIndex < 0 ) secondIndex = elem->GetNodeIndex( n2 );
      if ( firstIndex > -1 && secondIndex > -1 ) break;
    }
    if ( firstIndex < 0 || secondIndex < 0 ) {
      // we can simply return until temporary faces created
      return (iSide == 0 ) ? SEW_BAD_SIDE1_NODES : SEW_BAD_SIDE2_NODES;
    }

    // -----------------------------------------------------------
    // 1a. Collect nodes of existing faces
    //     and build set of face nodes in order to detect missing
    //     faces corresponding to sides of volumes
    // -----------------------------------------------------------

    set< set <const SMDS_MeshNode*> > setOfFaceNodeSet;

    // loop on the given element of a side
    for (eIt = elemSet->begin(); eIt != elemSet->end(); eIt++ ) {
      //const SMDS_MeshElement* elem = *eIt;
      const SMDS_MeshElement* elem = *eIt;
      if ( elem->GetType() == SMDSAbs_Face ) {
        faceSet->insert( elem );
        set <const SMDS_MeshNode*> faceNodeSet;
        SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator();
        while ( nodeIt->more() ) {
          const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
          nodeSet->insert( n );
          faceNodeSet.insert( n );
        }
        setOfFaceNodeSet.insert( faceNodeSet );
      }
      else if ( elem->GetType() == SMDSAbs_Volume )
        volSet->insert( elem );
    }
    // ------------------------------------------------------------------------------
    // 1b. Complete set of faces: find missing faces whose nodes are in set of nodes
    // ------------------------------------------------------------------------------

    for ( nIt = nodeSet->begin(); nIt != nodeSet->end(); nIt++ ) { // loop on nodes of iSide
      SMDS_ElemIteratorPtr fIt = (*nIt)->GetInverseElementIterator(SMDSAbs_Face);
      while ( fIt->more() ) { // loop on faces sharing a node
        const SMDS_MeshElement* f = fIt->next();
        if ( faceSet->find( f ) == faceSet->end() ) {
          // check if all nodes are in nodeSet and
          // complete setOfFaceNodeSet if they are
          set <const SMDS_MeshNode*> faceNodeSet;
          SMDS_ElemIteratorPtr nodeIt = f->nodesIterator();
          bool allInSet = true;
          while ( nodeIt->more() && allInSet ) { // loop on nodes of a face
            const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
            if ( nodeSet->find( n ) == nodeSet->end() )
              allInSet = false;
            else
              faceNodeSet.insert( n );
          }
          if ( allInSet ) {
            faceSet->insert( f );
            setOfFaceNodeSet.insert( faceNodeSet );
          }
        }
      }
    }

    // -------------------------------------------------------------------------
    // 1c. Create temporary faces representing sides of volumes if correspondent
    //     face does not exist
    // -------------------------------------------------------------------------

    if ( !volSet->empty() ) {
      //int nodeSetSize = nodeSet->size();

      // loop on given volumes
      for ( vIt = volSet->begin(); vIt != volSet->end(); vIt++ ) {
        SMDS_VolumeTool vol (*vIt);
        // loop on volume faces: find free faces
        // --------------------------------------
        list<const SMDS_MeshElement* > freeFaceList;
        for ( iFace = 0; iFace < vol.NbFaces(); iFace++ ) {
          if ( !vol.IsFreeFace( iFace ))
            continue;
          // check if there is already a face with same nodes in a face set
          const SMDS_MeshElement* aFreeFace = 0;
          const SMDS_MeshNode** fNodes = vol.GetFaceNodes( iFace );
          int nbNodes = vol.NbFaceNodes( iFace );
          set <const SMDS_MeshNode*> faceNodeSet;
          vol.GetFaceNodes( iFace, faceNodeSet );
          bool isNewFace = setOfFaceNodeSet.insert( faceNodeSet ).second;
          if ( isNewFace ) {
            // no such a face is given but it still can exist, check it
            vector<const SMDS_MeshNode *> nodes ( fNodes, fNodes + nbNodes);
            aFreeFace = aMesh->FindElement( nodes, SMDSAbs_Face, /*noMedium=*/false );
          }
          if ( !aFreeFace ) {
            // create a temporary face
            if ( nbNodes == 3 ) {
              //aFreeFace = aTmpFacesMesh.AddFace( fNodes[0],fNodes[1],fNodes[2] );
              aFreeFace = aMesh->AddFace( fNodes[0],fNodes[1],fNodes[2] );
            }
            else if ( nbNodes == 4 ) {
              //aFreeFace = aTmpFacesMesh.AddFace( fNodes[0],fNodes[1],fNodes[2],fNodes[3] );
              aFreeFace = aMesh->AddFace( fNodes[0],fNodes[1],fNodes[2],fNodes[3] );
            }
            else {
              vector<const SMDS_MeshNode *> poly_nodes ( fNodes, & fNodes[nbNodes]);
              //aFreeFace = aTmpFacesMesh.AddPolygonalFace(poly_nodes);
              aFreeFace = aMesh->AddPolygonalFace(poly_nodes);
            }
            if ( aFreeFace )
              tempFaceList.push_back( aFreeFace );
          }

          if ( aFreeFace )
            freeFaceList.push_back( aFreeFace );

        } // loop on faces of a volume

        // choose one of several free faces of a volume
        // --------------------------------------------
        if ( freeFaceList.size() > 1 ) {
          // choose a face having max nb of nodes shared by other elems of a side
          int maxNbNodes = -1;
          list<const SMDS_MeshElement* >::iterator fIt = freeFaceList.begin();
          while ( fIt != freeFaceList.end() ) { // loop on free faces
            int nbSharedNodes = 0;
            SMDS_ElemIteratorPtr nodeIt = (*fIt)->nodesIterator();
            while ( nodeIt->more() ) { // loop on free face nodes
              const SMDS_MeshNode* n =
                static_cast<const SMDS_MeshNode*>( nodeIt->next() );
              SMDS_ElemIteratorPtr invElemIt = n->GetInverseElementIterator();
              while ( invElemIt->more() ) {
                const SMDS_MeshElement* e = invElemIt->next();
                nbSharedNodes += faceSet->count( e );
                nbSharedNodes += elemSet->count( e );
              }
            }
            if ( nbSharedNodes > maxNbNodes ) {
              maxNbNodes = nbSharedNodes;
              freeFaceList.erase( freeFaceList.begin(), fIt++ );
            }
            else if ( nbSharedNodes == maxNbNodes ) {
              fIt++;
            }
            else {
              freeFaceList.erase( fIt++ ); // here fIt++ occurs before erase
            }
          }
          if ( freeFaceList.size() > 1 )
          {
            // could not choose one face, use another way
            // choose a face most close to the bary center of the opposite side
            gp_XYZ aBC( 0., 0., 0. );
            set <const SMDS_MeshNode*> addedNodes;
            TIDSortedElemSet * elemSet2 = elemSetPtr[ 1 - iSide ];
            eIt = elemSet2->begin();
            for ( eIt = elemSet2->begin(); eIt != elemSet2->end(); eIt++ ) {
              SMDS_ElemIteratorPtr nodeIt = (*eIt)->nodesIterator();
              while ( nodeIt->more() ) { // loop on free face nodes
                const SMDS_MeshNode* n =
                  static_cast<const SMDS_MeshNode*>( nodeIt->next() );
                if ( addedNodes.insert( n ).second )
                  aBC += gp_XYZ( n->X(),n->Y(),n->Z() );
              }
            }
            aBC /= addedNodes.size();
            double minDist = DBL_MAX;
            fIt = freeFaceList.begin();
            while ( fIt != freeFaceList.end() ) { // loop on free faces
              double dist = 0;
              SMDS_ElemIteratorPtr nodeIt = (*fIt)->nodesIterator();
              while ( nodeIt->more() ) { // loop on free face nodes
                const SMDS_MeshNode* n =
                  static_cast<const SMDS_MeshNode*>( nodeIt->next() );
                gp_XYZ p( n->X(),n->Y(),n->Z() );
                dist += ( aBC - p ).SquareModulus();
              }
              if ( dist < minDist ) {
                minDist = dist;
                freeFaceList.erase( freeFaceList.begin(), fIt++ );
              }
              else
                fIt = freeFaceList.erase( fIt++ );
            }
          }
        } // choose one of several free faces of a volume

        if ( freeFaceList.size() == 1 ) {
          const SMDS_MeshElement* aFreeFace = freeFaceList.front();
          faceSet->insert( aFreeFace );
          // complete a node set with nodes of a found free face
          //           for ( iNode = 0; iNode < ; iNode++ )
          //             nodeSet->insert( fNodes[ iNode ] );
        }

      } // loop on volumes of a side

      //       // complete a set of faces if new nodes in a nodeSet appeared
      //       // ----------------------------------------------------------
      //       if ( nodeSetSize != nodeSet->size() ) {
      //         for ( ; nIt != nodeSet->end(); nIt++ ) { // loop on nodes of iSide
      //           SMDS_ElemIteratorPtr fIt = (*nIt)->GetInverseElementIterator(SMDSAbs_Face);
      //           while ( fIt->more() ) { // loop on faces sharing a node
      //             const SMDS_MeshElement* f = fIt->next();
      //             if ( faceSet->find( f ) == faceSet->end() ) {
      //               // check if all nodes are in nodeSet and
      //               // complete setOfFaceNodeSet if they are
      //               set <const SMDS_MeshNode*> faceNodeSet;
      //               SMDS_ElemIteratorPtr nodeIt = f->nodesIterator();
      //               bool allInSet = true;
      //               while ( nodeIt->more() && allInSet ) { // loop on nodes of a face
      //                 const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
      //                 if ( nodeSet->find( n ) == nodeSet->end() )
      //                   allInSet = false;
      //                 else
      //                   faceNodeSet.insert( n );
      //               }
      //               if ( allInSet ) {
      //                 faceSet->insert( f );
      //                 setOfFaceNodeSet.insert( faceNodeSet );
      //               }
      //             }
      //           }
      //         }
      //       }
    } // Create temporary faces, if there are volumes given
  } // loop on sides

  if ( faceSet1.size() != faceSet2.size() ) {
    // delete temporary faces: they are in reverseElements of actual nodes
//    SMDS_FaceIteratorPtr tmpFaceIt = aTmpFacesMesh.facesIterator();
//    while ( tmpFaceIt->more() )
//      aTmpFacesMesh.RemoveElement( tmpFaceIt->next() );
//    list<const SMDS_MeshElement* >::iterator tmpFaceIt = tempFaceList.begin();
//    for (; tmpFaceIt !=tempFaceList.end(); ++tmpFaceIt)
//      aMesh->RemoveElement(*tmpFaceIt);
    MESSAGE("Diff nb of faces");
    return SEW_TOPO_DIFF_SETS_OF_ELEMENTS;
  }

  // ============================================================
  // 2. Find nodes to merge:
  //              bind a node to remove to a node to put instead
  // ============================================================

  TNodeNodeMap nReplaceMap; // bind a node to remove to a node to put instead
  if ( theFirstNode1 != theFirstNode2 )
    nReplaceMap.insert( make_pair( theFirstNode1, theFirstNode2 ));
  if ( theSecondNode1 != theSecondNode2 )
    nReplaceMap.insert( make_pair( theSecondNode1, theSecondNode2 ));

  LinkID_Gen aLinkID_Gen( GetMeshDS() );
  set< long > linkIdSet; // links to process
  linkIdSet.insert( aLinkID_Gen.GetLinkID( theFirstNode1, theSecondNode1 ));

  typedef pair< const SMDS_MeshNode*, const SMDS_MeshNode* > NLink;
  list< NLink > linkList[2];
  linkList[0].push_back( NLink( theFirstNode1, theSecondNode1 ));
  linkList[1].push_back( NLink( theFirstNode2, theSecondNode2 ));
  // loop on links in linkList; find faces by links and append links
  // of the found faces to linkList
  list< NLink >::iterator linkIt[] = { linkList[0].begin(), linkList[1].begin() } ;
  for ( ; linkIt[0] != linkList[0].end(); linkIt[0]++, linkIt[1]++ )
  {
    NLink link[] = { *linkIt[0], *linkIt[1] };
    long linkID = aLinkID_Gen.GetLinkID( link[0].first, link[0].second );
    if ( !linkIdSet.count( linkID ) )
      continue;

    // by links, find faces in the face sets,
    // and find indices of link nodes in the found faces;
    // in a face set, there is only one or no face sharing a link
    // ---------------------------------------------------------------

    const SMDS_MeshElement* face[] = { 0, 0 };
    vector<const SMDS_MeshNode*> fnodes[2];
    int iLinkNode[2][2];
    TIDSortedElemSet avoidSet;
    for ( iSide = 0; iSide < 2; iSide++ ) { // loop on 2 sides
      const SMDS_MeshNode* n1 = link[iSide].first;
      const SMDS_MeshNode* n2 = link[iSide].second;
      //cout << "Side " << iSide << " ";
      //cout << "L( " << n1->GetID() << ", " << n2->GetID() << " ) " << endl;
      // find a face by two link nodes
      face[ iSide ] = FindFaceInSet( n1, n2, *faceSetPtr[ iSide ], avoidSet,
                                     &iLinkNode[iSide][0], &iLinkNode[iSide][1] );
      if ( face[ iSide ])
      {
        //cout << " F " << face[ iSide]->GetID() <<endl;
        faceSetPtr[ iSide ]->erase( face[ iSide ]);
        // put face nodes to fnodes
        if ( face[ iSide ]->IsQuadratic() )
        {
          // use interlaced nodes iterator
          const SMDS_VtkFace* F = dynamic_cast<const SMDS_VtkFace*>( face[ iSide ]);
          if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace"));
          SMDS_ElemIteratorPtr nIter = F->interlacedNodesElemIterator();
          while ( nIter->more() )
            fnodes[ iSide ].push_back( cast2Node( nIter->next() ));
        }
        else
        {
          fnodes[ iSide ].assign( face[ iSide ]->begin_nodes(),
                                  face[ iSide ]->end_nodes() );
        }
        fnodes[ iSide ].push_back( fnodes[ iSide ].front());
      }
    }

    // check similarity of elements of the sides
    if (aResult == SEW_OK && (( face[0] && !face[1] ) || ( !face[0] && face[1] ))) {
      MESSAGE("Correspondent face not found on side " << ( face[0] ? 1 : 0 ));
      if ( nReplaceMap.size() == 2 ) { // faces on input nodes not found
        aResult = ( face[0] ? SEW_BAD_SIDE2_NODES : SEW_BAD_SIDE1_NODES );
      }
      else {
        aResult = SEW_TOPO_DIFF_SETS_OF_ELEMENTS;
      }
      break; // do not return because it's necessary to remove tmp faces
    }

    // set nodes to merge
    // -------------------

    if ( face[0] && face[1] )  {
      const int nbNodes = face[0]->NbNodes();
      if ( nbNodes != face[1]->NbNodes() ) {
        MESSAGE("Diff nb of face nodes");
        aResult = SEW_TOPO_DIFF_SETS_OF_ELEMENTS;
        break; // do not return because it s necessary to remove tmp faces
      }
      bool reverse[] = { false, false }; // order of nodes in the link
      for ( iSide = 0; iSide < 2; iSide++ ) { // loop on 2 sides
        // analyse link orientation in faces
        int i1 = iLinkNode[ iSide ][ 0 ];
        int i2 = iLinkNode[ iSide ][ 1 ];
        reverse[ iSide ] = Abs( i1 - i2 ) == 1 ? i1 > i2 : i2 > i1;
      }
      int di1 = reverse[0] ? -1 : +1, i1 = iLinkNode[0][1] + di1;
      int di2 = reverse[1] ? -1 : +1, i2 = iLinkNode[1][1] + di2;
      for ( int i = nbNodes - 2; i > 0; --i, i1 += di1, i2 += di2 )
      {
        nReplaceMap.insert  ( make_pair ( fnodes[0][ ( i1 + nbNodes ) % nbNodes ],
                                          fnodes[1][ ( i2 + nbNodes ) % nbNodes ]));
      }

      // add other links of the faces to linkList
      // -----------------------------------------

      for ( iNode = 0; iNode < nbNodes; iNode++ )  {
        linkID = aLinkID_Gen.GetLinkID( fnodes[0][iNode], fnodes[0][iNode+1] );
        pair< set<long>::iterator, bool > iter_isnew = linkIdSet.insert( linkID );
        if ( !iter_isnew.second ) { // already in a set: no need to process
          linkIdSet.erase( iter_isnew.first );
        }
        else // new in set == encountered for the first time: add
        {
          const SMDS_MeshNode* n1 = fnodes[0][ iNode ];
          const SMDS_MeshNode* n2 = fnodes[0][ iNode + 1];
          linkList[0].push_back ( NLink( n1, n2 ));
          linkList[1].push_back ( NLink( nReplaceMap[n1], nReplaceMap[n2] ));
        }
      }
    } // 2 faces found

    if ( faceSetPtr[0]->empty() || faceSetPtr[1]->empty() )
      break;

  } // loop on link lists

  if ( aResult == SEW_OK &&
       ( //linkIt[0] != linkList[0].end() ||
         !faceSetPtr[0]->empty() || !faceSetPtr[1]->empty() )) {
    MESSAGE( (linkIt[0] != linkList[0].end()) <<" "<< (faceSetPtr[0]->empty()) <<
             " " << (faceSetPtr[1]->empty()));
    aResult = SEW_TOPO_DIFF_SETS_OF_ELEMENTS;
  }

  // ====================================================================
  // 3. Replace nodes in elements of the side 1 and remove replaced nodes
  // ====================================================================

  // delete temporary faces
//  SMDS_FaceIteratorPtr tmpFaceIt = aTmpFacesMesh.facesIterator();
//  while ( tmpFaceIt->more() )
//    aTmpFacesMesh.RemoveElement( tmpFaceIt->next() );
  list<const SMDS_MeshElement* >::iterator tmpFaceIt = tempFaceList.begin();
  for (; tmpFaceIt !=tempFaceList.end(); ++tmpFaceIt)
    aMesh->RemoveElement(*tmpFaceIt);

  if ( aResult != SEW_OK)
    return aResult;

  list< int > nodeIDsToRemove/*, elemIDsToRemove*/;
  // loop on nodes replacement map
  TNodeNodeMap::iterator nReplaceMapIt = nReplaceMap.begin(), nnIt;
  for ( ; nReplaceMapIt != nReplaceMap.end(); nReplaceMapIt++ )
    if ( (*nReplaceMapIt).first != (*nReplaceMapIt).second ) {
      const SMDS_MeshNode* nToRemove = (*nReplaceMapIt).first;
      nodeIDsToRemove.push_back( nToRemove->GetID() );
      // loop on elements sharing nToRemove
      SMDS_ElemIteratorPtr invElemIt = nToRemove->GetInverseElementIterator();
      while ( invElemIt->more() ) {
        const SMDS_MeshElement* e = invElemIt->next();
        // get a new suite of nodes: make replacement
        int nbReplaced = 0, i = 0, nbNodes = e->NbNodes();
        vector< const SMDS_MeshNode*> nodes( nbNodes );
        SMDS_ElemIteratorPtr nIt = e->nodesIterator();
        while ( nIt->more() ) {
          const SMDS_MeshNode* n =
            static_cast<const SMDS_MeshNode*>( nIt->next() );
          nnIt = nReplaceMap.find( n );
          if ( nnIt != nReplaceMap.end() ) {
            nbReplaced++;
            n = (*nnIt).second;
          }
          nodes[ i++ ] = n;
        }
        //       if ( nbReplaced == nbNodes && e->GetType() == SMDSAbs_Face )
        //         elemIDsToRemove.push_back( e->GetID() );
        //       else
        if ( nbReplaced )
          {
            SMDSAbs_ElementType etyp = e->GetType();
            SMDS_MeshElement* newElem = this->AddElement(nodes, etyp, false);
            if (newElem)
              {
                myLastCreatedElems.Append(newElem);
                AddToSameGroups(newElem, e, aMesh);
                int aShapeId = e->getshapeId();
                if ( aShapeId )
                  {
                    aMesh->SetMeshElementOnShape( newElem, aShapeId );
                  }
              }
            aMesh->RemoveElement(e);
          }
      }
    }

  Remove( nodeIDsToRemove, true );

  return aResult;
}

Here is the call graph for this function:

void SMESH_MeshEditor::Smooth ( in long_array  IDsOfElements,
in long_array  IDsOfFixedNodes,
in long  MaxNbOfIterations,
in double  MaxAspectRatio,
in Smooth_Method  Method 
)

Definition at line 2939 of file SMESH_MeshEditor.cxx.

{
  myLastCreatedElems.Clear();
  myLastCreatedNodes.Clear();

  MESSAGE((theSmoothMethod==LAPLACIAN ? "LAPLACIAN" : "CENTROIDAL") << "--::Smooth()");

  if ( theTgtAspectRatio < 1.0 )
    theTgtAspectRatio = 1.0;

  const double disttol = 1.e-16;

  SMESH::Controls::AspectRatio aQualityFunc;

  SMESHDS_Mesh* aMesh = GetMeshDS();

  if ( theElems.empty() ) {
    // add all faces to theElems
    SMDS_FaceIteratorPtr fIt = aMesh->facesIterator();
    while ( fIt->more() ) {
      const SMDS_MeshElement* face = fIt->next();
      theElems.insert( face );
    }
  }
  // get all face ids theElems are on
  set< int > faceIdSet;
  TIDSortedElemSet::iterator itElem;
  if ( the2D )
    for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) {
      int fId = FindShape( *itElem );
      // check that corresponding submesh exists and a shape is face
      if (fId &&
          faceIdSet.find( fId ) == faceIdSet.end() &&
          aMesh->MeshElements( fId )) {
        TopoDS_Shape F = aMesh->IndexToShape( fId );
        if ( !F.IsNull() && F.ShapeType() == TopAbs_FACE )
          faceIdSet.insert( fId );
      }
    }
  faceIdSet.insert( 0 ); // to smooth elements that are not on any TopoDS_Face

  // ===============================================
  // smooth elements on each TopoDS_Face separately
  // ===============================================

  set< int >::reverse_iterator fId = faceIdSet.rbegin(); // treate 0 fId at the end
  for ( ; fId != faceIdSet.rend(); ++fId ) {
    // get face surface and submesh
    Handle(Geom_Surface) surface;
    SMESHDS_SubMesh* faceSubMesh = 0;
    TopoDS_Face face;
    double fToler2 = 0, f,l;
    double u1 = 0, u2 = 0, v1 = 0, v2 = 0;
    bool isUPeriodic = false, isVPeriodic = false;
    if ( *fId ) {
      face = TopoDS::Face( aMesh->IndexToShape( *fId ));
      surface = BRep_Tool::Surface( face );
      faceSubMesh = aMesh->MeshElements( *fId );
      fToler2 = BRep_Tool::Tolerance( face );
      fToler2 *= fToler2 * 10.;
      isUPeriodic = surface->IsUPeriodic();
      if ( isUPeriodic )
        surface->UPeriod();
      isVPeriodic = surface->IsVPeriodic();
      if ( isVPeriodic )
        surface->VPeriod();
      surface->Bounds( u1, u2, v1, v2 );
    }
    // ---------------------------------------------------------
    // for elements on a face, find movable and fixed nodes and
    // compute UV for them
    // ---------------------------------------------------------
    bool checkBoundaryNodes = false;
    bool isQuadratic = false;
    set<const SMDS_MeshNode*> setMovableNodes;
    map< const SMDS_MeshNode*, gp_XY* > uvMap, uvMap2;
    list< gp_XY > listUV; // uvs the 2 uvMaps refer to
    list< const SMDS_MeshElement* > elemsOnFace;

    Extrema_GenExtPS projector;
    GeomAdaptor_Surface surfAdaptor;
    if ( !surface.IsNull() ) {
      surfAdaptor.Load( surface );
      projector.Initialize( surfAdaptor, 20,20, 1e-5,1e-5 );
    }
    int nbElemOnFace = 0;
    itElem = theElems.begin();
    // loop on not yet smoothed elements: look for elems on a face
    while ( itElem != theElems.end() ) {
      if ( faceSubMesh && nbElemOnFace == faceSubMesh->NbElements() )
        break; // all elements found

      const SMDS_MeshElement* elem = *itElem;
      if ( !elem || elem->GetType() != SMDSAbs_Face || elem->NbNodes() < 3 ||
           ( faceSubMesh && !faceSubMesh->Contains( elem ))) {
        ++itElem;
        continue;
      }
      elemsOnFace.push_back( elem );
      theElems.erase( itElem++ );
      nbElemOnFace++;

      if ( !isQuadratic )
        isQuadratic = elem->IsQuadratic();

      // get movable nodes of elem
      const SMDS_MeshNode* node;
      SMDS_TypeOfPosition posType;
      SMDS_ElemIteratorPtr itN = elem->nodesIterator();
      int nn = 0, nbn =  elem->NbNodes();
      if(elem->IsQuadratic())
        nbn = nbn/2;
      while ( nn++ < nbn ) {
        node = static_cast<const SMDS_MeshNode*>( itN->next() );
        const SMDS_PositionPtr& pos = node->GetPosition();
        posType = pos ? pos->GetTypeOfPosition() : SMDS_TOP_3DSPACE;
        if (posType != SMDS_TOP_EDGE &&
            posType != SMDS_TOP_VERTEX &&
            theFixedNodes.find( node ) == theFixedNodes.end())
        {
          // check if all faces around the node are on faceSubMesh
          // because a node on edge may be bound to face
          SMDS_ElemIteratorPtr eIt = node->GetInverseElementIterator(SMDSAbs_Face);
          bool all = true;
          if ( faceSubMesh ) {
            while ( eIt->more() && all ) {
              const SMDS_MeshElement* e = eIt->next();
              all = faceSubMesh->Contains( e );
            }
          }
          if ( all )
            setMovableNodes.insert( node );
          else
            checkBoundaryNodes = true;
        }
        if ( posType == SMDS_TOP_3DSPACE )
          checkBoundaryNodes = true;
      }

      if ( surface.IsNull() )
        continue;

      // get nodes to check UV
      list< const SMDS_MeshNode* > uvCheckNodes;
      itN = elem->nodesIterator();
      nn = 0; nbn =  elem->NbNodes();
      if(elem->IsQuadratic())
        nbn = nbn/2;
      while ( nn++ < nbn ) {
        node = static_cast<const SMDS_MeshNode*>( itN->next() );
        if ( uvMap.find( node ) == uvMap.end() )
          uvCheckNodes.push_back( node );
        // add nodes of elems sharing node
        //         SMDS_ElemIteratorPtr eIt = node->GetInverseElementIterator(SMDSAbs_Face);
        //         while ( eIt->more() ) {
        //           const SMDS_MeshElement* e = eIt->next();
        //           if ( e != elem ) {
        //             SMDS_ElemIteratorPtr nIt = e->nodesIterator();
        //             while ( nIt->more() ) {
        //               const SMDS_MeshNode* n =
        //                 static_cast<const SMDS_MeshNode*>( nIt->next() );
        //               if ( uvMap.find( n ) == uvMap.end() )
        //                 uvCheckNodes.push_back( n );
        //             }
        //           }
        //         }
      }
      // check UV on face
      list< const SMDS_MeshNode* >::iterator n = uvCheckNodes.begin();
      for ( ; n != uvCheckNodes.end(); ++n ) {
        node = *n;
        gp_XY uv( 0, 0 );
        const SMDS_PositionPtr& pos = node->GetPosition();
        posType = pos ? pos->GetTypeOfPosition() : SMDS_TOP_3DSPACE;
        // get existing UV
        switch ( posType ) {
        case SMDS_TOP_FACE: {
          SMDS_FacePosition* fPos = ( SMDS_FacePosition* ) pos;
          uv.SetCoord( fPos->GetUParameter(), fPos->GetVParameter() );
          break;
        }
        case SMDS_TOP_EDGE: {
          TopoDS_Shape S = aMesh->IndexToShape( node->getshapeId() );
          Handle(Geom2d_Curve) pcurve;
          if ( !S.IsNull() && S.ShapeType() == TopAbs_EDGE )
            pcurve = BRep_Tool::CurveOnSurface( TopoDS::Edge( S ), face, f,l );
          if ( !pcurve.IsNull() ) {
            double u = (( SMDS_EdgePosition* ) pos )->GetUParameter();
            uv = pcurve->Value( u ).XY();
          }
          break;
        }
        case SMDS_TOP_VERTEX: {
          TopoDS_Shape S = aMesh->IndexToShape( node->getshapeId() );
          if ( !S.IsNull() && S.ShapeType() == TopAbs_VERTEX )
            uv = BRep_Tool::Parameters( TopoDS::Vertex( S ), face ).XY();
          break;
        }
        default:;
        }
        // check existing UV
        bool project = true;
        gp_Pnt pNode ( node->X(), node->Y(), node->Z() );
        double dist1 = DBL_MAX, dist2 = 0;
        if ( posType != SMDS_TOP_3DSPACE ) {
          dist1 = pNode.SquareDistance( surface->Value( uv.X(), uv.Y() ));
          project = dist1 > fToler2;
        }
        if ( project ) { // compute new UV
          gp_XY newUV;
          if ( !getClosestUV( projector, pNode, newUV )) {
            MESSAGE("Node Projection Failed " << node);
          }
          else {
            if ( isUPeriodic )
              newUV.SetX( ElCLib::InPeriod( newUV.X(), u1, u2 ));
            if ( isVPeriodic )
              newUV.SetY( ElCLib::InPeriod( newUV.Y(), v1, v2 ));
            // check new UV
            if ( posType != SMDS_TOP_3DSPACE )
              dist2 = pNode.SquareDistance( surface->Value( newUV.X(), newUV.Y() ));
            if ( dist2 < dist1 )
              uv = newUV;
          }
        }
        // store UV in the map
        listUV.push_back( uv );
        uvMap.insert( make_pair( node, &listUV.back() ));
      }
    } // loop on not yet smoothed elements

    if ( !faceSubMesh || nbElemOnFace != faceSubMesh->NbElements() )
      checkBoundaryNodes = true;

    // fix nodes on mesh boundary

    if ( checkBoundaryNodes ) {
      map< SMESH_TLink, int > linkNbMap; // how many times a link encounters in elemsOnFace
      map< SMESH_TLink, int >::iterator link_nb;
      // put all elements links to linkNbMap
      list< const SMDS_MeshElement* >::iterator elemIt = elemsOnFace.begin();
      for ( ; elemIt != elemsOnFace.end(); ++elemIt ) {
        const SMDS_MeshElement* elem = (*elemIt);
        int nbn =  elem->NbCornerNodes();
        // loop on elem links: insert them in linkNbMap
        for ( int iN = 0; iN < nbn; ++iN ) {
          const SMDS_MeshNode* n1 = elem->GetNode( iN );
          const SMDS_MeshNode* n2 = elem->GetNode(( iN+1 ) % nbn);
          SMESH_TLink link( n1, n2 );
          link_nb = linkNbMap.insert( make_pair( link, 0 )).first;
          link_nb->second++;
        }
      }
      // remove nodes that are in links encountered only once from setMovableNodes
      for ( link_nb = linkNbMap.begin(); link_nb != linkNbMap.end(); ++link_nb ) {
        if ( link_nb->second == 1 ) {
          setMovableNodes.erase( link_nb->first.node1() );
          setMovableNodes.erase( link_nb->first.node2() );
        }
      }
    }

    // -----------------------------------------------------
    // for nodes on seam edge, compute one more UV ( uvMap2 );
    // find movable nodes linked to nodes on seam and which
    // are to be smoothed using the second UV ( uvMap2 )
    // -----------------------------------------------------

    set<const SMDS_MeshNode*> nodesNearSeam; // to smooth using uvMap2
    if ( !surface.IsNull() ) {
      TopExp_Explorer eExp( face, TopAbs_EDGE );
      for ( ; eExp.More(); eExp.Next() ) {
        TopoDS_Edge edge = TopoDS::Edge( eExp.Current() );
        if ( !BRep_Tool::IsClosed( edge, face ))
          continue;
        SMESHDS_SubMesh* sm = aMesh->MeshElements( edge );
        if ( !sm ) continue;
        // find out which parameter varies for a node on seam
        double f,l;
        gp_Pnt2d uv1, uv2;
        Handle(Geom2d_Curve) pcurve = BRep_Tool::CurveOnSurface( edge, face, f, l );
        if ( pcurve.IsNull() ) continue;
        uv1 = pcurve->Value( f );
        edge.Reverse();
        pcurve = BRep_Tool::CurveOnSurface( edge, face, f, l );
        if ( pcurve.IsNull() ) continue;
        uv2 = pcurve->Value( f );
        int iPar = Abs( uv1.X() - uv2.X() ) > Abs( uv1.Y() - uv2.Y() ) ? 1 : 2;
        // assure uv1 < uv2
        if ( uv1.Coord( iPar ) > uv2.Coord( iPar )) {
          gp_Pnt2d tmp = uv1; uv1 = uv2; uv2 = tmp;
        }
        // get nodes on seam and its vertices
        list< const SMDS_MeshNode* > seamNodes;
        SMDS_NodeIteratorPtr nSeamIt = sm->GetNodes();
        while ( nSeamIt->more() ) {
          const SMDS_MeshNode* node = nSeamIt->next();
          if ( !isQuadratic || !IsMedium( node ))
            seamNodes.push_back( node );
        }
        TopExp_Explorer vExp( edge, TopAbs_VERTEX );
        for ( ; vExp.More(); vExp.Next() ) {
          sm = aMesh->MeshElements( vExp.Current() );
          if ( sm ) {
            nSeamIt = sm->GetNodes();
            while ( nSeamIt->more() )
              seamNodes.push_back( nSeamIt->next() );
          }
        }
        // loop on nodes on seam
        list< const SMDS_MeshNode* >::iterator noSeIt = seamNodes.begin();
        for ( ; noSeIt != seamNodes.end(); ++noSeIt ) {
          const SMDS_MeshNode* nSeam = *noSeIt;
          map< const SMDS_MeshNode*, gp_XY* >::iterator n_uv = uvMap.find( nSeam );
          if ( n_uv == uvMap.end() )
            continue;
          // set the first UV
          n_uv->second->SetCoord( iPar, uv1.Coord( iPar ));
          // set the second UV
          listUV.push_back( *n_uv->second );
          listUV.back().SetCoord( iPar, uv2.Coord( iPar ));
          if ( uvMap2.empty() )
            uvMap2 = uvMap; // copy the uvMap contents
          uvMap2[ nSeam ] = &listUV.back();

          // collect movable nodes linked to ones on seam in nodesNearSeam
          SMDS_ElemIteratorPtr eIt = nSeam->GetInverseElementIterator(SMDSAbs_Face);
          while ( eIt->more() ) {
            const SMDS_MeshElement* e = eIt->next();
            int nbUseMap1 = 0, nbUseMap2 = 0;
            SMDS_ElemIteratorPtr nIt = e->nodesIterator();
            int nn = 0, nbn =  e->NbNodes();
            if(e->IsQuadratic()) nbn = nbn/2;
            while ( nn++ < nbn )
            {
              const SMDS_MeshNode* n =
                static_cast<const SMDS_MeshNode*>( nIt->next() );
              if (n == nSeam ||
                  setMovableNodes.find( n ) == setMovableNodes.end() )
                continue;
              // add only nodes being closer to uv2 than to uv1
              gp_Pnt pMid (0.5 * ( n->X() + nSeam->X() ),
                           0.5 * ( n->Y() + nSeam->Y() ),
                           0.5 * ( n->Z() + nSeam->Z() ));
              gp_XY uv;
              getClosestUV( projector, pMid, uv );
              if ( uv.Coord( iPar ) > uvMap[ n ]->Coord( iPar ) ) {
                nodesNearSeam.insert( n );
                nbUseMap2++;
              }
              else
                nbUseMap1++;
            }
            // for centroidalSmooth all element nodes must
            // be on one side of a seam
            if ( theSmoothMethod == CENTROIDAL && nbUseMap1 && nbUseMap2 ) {
              SMDS_ElemIteratorPtr nIt = e->nodesIterator();
              nn = 0;
              while ( nn++ < nbn ) {
                const SMDS_MeshNode* n =
                  static_cast<const SMDS_MeshNode*>( nIt->next() );
                setMovableNodes.erase( n );
              }
            }
          }
        } // loop on nodes on seam
      } // loop on edge of a face
    } // if ( !face.IsNull() )

    if ( setMovableNodes.empty() ) {
      MESSAGE( "Face id : " << *fId << " - NO SMOOTHING: no nodes to move!!!");
      continue; // goto next face
    }

    // -------------
    // SMOOTHING //
    // -------------

    int it = -1;
    double maxRatio = -1., maxDisplacement = -1.;
    set<const SMDS_MeshNode*>::iterator nodeToMove;
    for ( it = 0; it < theNbIterations; it++ ) {
      maxDisplacement = 0.;
      nodeToMove = setMovableNodes.begin();
      for ( ; nodeToMove != setMovableNodes.end(); nodeToMove++ ) {
        const SMDS_MeshNode* node = (*nodeToMove);
        gp_XYZ aPrevPos ( node->X(), node->Y(), node->Z() );

        // smooth
        bool map2 = ( nodesNearSeam.find( node ) != nodesNearSeam.end() );
        if ( theSmoothMethod == LAPLACIAN )
          laplacianSmooth( node, surface, map2 ? uvMap2 : uvMap );
        else
          centroidalSmooth( node, surface, map2 ? uvMap2 : uvMap );

        // node displacement
        gp_XYZ aNewPos ( node->X(), node->Y(), node->Z() );
        Standard_Real aDispl = (aPrevPos - aNewPos).SquareModulus();
        if ( aDispl > maxDisplacement )
          maxDisplacement = aDispl;
      }
      // no node movement => exit
      //if ( maxDisplacement < 1.e-16 ) {
      if ( maxDisplacement < disttol ) {
        MESSAGE("-- no node movement --");
        break;
      }

      // check elements quality
      maxRatio  = 0;
      list< const SMDS_MeshElement* >::iterator elemIt = elemsOnFace.begin();
      for ( ; elemIt != elemsOnFace.end(); ++elemIt ) {
        const SMDS_MeshElement* elem = (*elemIt);
        if ( !elem || elem->GetType() != SMDSAbs_Face )
          continue;
        SMESH::Controls::TSequenceOfXYZ aPoints;
        if ( aQualityFunc.GetPoints( elem, aPoints )) {
          double aValue = aQualityFunc.GetValue( aPoints );
          if ( aValue > maxRatio )
            maxRatio = aValue;
        }
      }
      if ( maxRatio <= theTgtAspectRatio ) {
        MESSAGE("-- quality achived --");
        break;
      }
      if (it+1 == theNbIterations) {
        MESSAGE("-- Iteration limit exceeded --");
      }
    } // smoothing iterations

    MESSAGE(" Face id: " << *fId <<
            " Nb iterstions: " << it <<
            " Displacement: " << maxDisplacement <<
            " Aspect Ratio " << maxRatio);

    // ---------------------------------------
    // new nodes positions are computed,
    // record movement in DS and set new UV
    // ---------------------------------------
    nodeToMove = setMovableNodes.begin();
    for ( ; nodeToMove != setMovableNodes.end(); nodeToMove++ ) {
      SMDS_MeshNode* node = const_cast< SMDS_MeshNode* > (*nodeToMove);
      aMesh->MoveNode( node, node->X(), node->Y(), node->Z() );
      map< const SMDS_MeshNode*, gp_XY* >::iterator node_uv = uvMap.find( node );
      if ( node_uv != uvMap.end() ) {
        gp_XY* uv = node_uv->second;
        node->SetPosition
          ( SMDS_PositionPtr( new SMDS_FacePosition( uv->X(), uv->Y() )));
      }
    }

    // move medium nodes of quadratic elements
    if ( isQuadratic )
    {
      SMESH_MesherHelper helper( *GetMesh() );
      if ( !face.IsNull() )
        helper.SetSubShape( face );
      list< const SMDS_MeshElement* >::iterator elemIt = elemsOnFace.begin();
      for ( ; elemIt != elemsOnFace.end(); ++elemIt ) {
        const SMDS_VtkFace* QF =
          dynamic_cast<const SMDS_VtkFace*> (*elemIt);
        if(QF && QF->IsQuadratic()) {
          vector<const SMDS_MeshNode*> Ns;
          Ns.reserve(QF->NbNodes()+1);
          SMDS_ElemIteratorPtr anIter = QF->interlacedNodesElemIterator();
          while ( anIter->more() )
            Ns.push_back( cast2Node(anIter->next()) );
          Ns.push_back( Ns[0] );
          double x, y, z;
          for(int i=0; i<QF->NbNodes(); i=i+2) {
            if ( !surface.IsNull() ) {
              gp_XY uv1 = helper.GetNodeUV( face, Ns[i], Ns[i+2] );
              gp_XY uv2 = helper.GetNodeUV( face, Ns[i+2], Ns[i] );
              gp_XY uv = ( uv1 + uv2 ) / 2.;
              gp_Pnt xyz = surface->Value( uv.X(), uv.Y() );
              x = xyz.X(); y = xyz.Y(); z = xyz.Z();
            }
            else {
              x = (Ns[i]->X() + Ns[i+2]->X())/2;
              y = (Ns[i]->Y() + Ns[i+2]->Y())/2;
              z = (Ns[i]->Z() + Ns[i+2]->Z())/2;
            }
            if( fabs( Ns[i+1]->X() - x ) > disttol ||
                fabs( Ns[i+1]->Y() - y ) > disttol ||
                fabs( Ns[i+1]->Z() - z ) > disttol ) {
              // we have to move i+1 node
              aMesh->MoveNode( Ns[i+1], x, y, z );
            }
          }
        }
      }
    }

  } // loop on face ids

}

Here is the call graph for this function:

boolean SMESH::SMESH_MeshEditor::SmoothObject ( in SMESH_IDSource  theObject,
in long_array  IDsOfFixedNodes,
in long  MaxNbOfIterations,
in double  MaxAspectRatio,
in Smooth_Method  Method 
)
boolean SMESH::SMESH_MeshEditor::SmoothParametric ( in long_array  IDsOfElements,
in long_array  IDsOfFixedNodes,
in long  MaxNbOfIterations,
in double  MaxAspectRatio,
in Smooth_Method  Method 
)
boolean SMESH::SMESH_MeshEditor::SmoothParametricObject ( in SMESH_IDSource  theObject,
in long_array  IDsOfFixedNodes,
in long  MaxNbOfIterations,
in double  MaxAspectRatio,
in Smooth_Method  Method 
)
boolean SMESH::SMESH_MeshEditor::SplitQuad ( in long_array  IDsOfElements,
in boolean  Diag13 
)

Split quadrangles into triangles.

Parameters:
theElemsThe faces to be splitted.
the13DiagIs used to choose a diagonal for splitting.
Returns:
TRUE in case of success, FALSE otherwise.

Here is the caller graph for this function:

boolean SMESH::SMESH_MeshEditor::SplitQuadObject ( in SMESH_IDSource  theObject,
in boolean  Diag13 
)

Split quadrangles into triangles.

Behaves like the above method, taking list of elements from theObject

void SMESH_MeshEditor::SplitVolumesIntoTetra ( in SMESH_IDSource  elems,
in short  methodFlags 
) raises (SALOME::SALOME_Exception)

Split volumic elements into tetrahedrons.

Parameters:
elems- elements to split
methodFlags- flags passing splitting method: 1 - split the hexahedron into 5 tetrahedrons 2 - split the hexahedron into 6 tetrahedrons 3 - split the hexahedron into 24 tetrahedrons

Definition at line 1632 of file SMESH_MeshEditor.cxx.

{
  // std-like iterator on coordinates of nodes of mesh element
  typedef SMDS_StdIterator< SMESH_TNodeXYZ, SMDS_ElemIteratorPtr > NXyzIterator;
  NXyzIterator xyzEnd;

  SMDS_VolumeTool    volTool;
  SMESH_MesherHelper helper( *GetMesh());

  SMESHDS_SubMesh* subMesh = 0;//GetMeshDS()->MeshElements(1);
  SMESHDS_SubMesh* fSubMesh = 0;//subMesh;
  
  SMESH_SequenceOfElemPtr newNodes, newElems;

  // map face of volume to it's baricenrtic node
  map< TVolumeFaceKey, const SMDS_MeshNode* > volFace2BaryNode;
  double bc[3];

  TIDSortedElemSet::const_iterator elem = theElems.begin();
  for ( ; elem != theElems.end(); ++elem )
  {
    if ( (*elem)->GetType() != SMDSAbs_Volume )
      continue;
    SMDSAbs_EntityType geomType = (*elem)->GetEntityType();
    if ( geomType == SMDSEntity_Tetra || geomType == SMDSEntity_Quad_Tetra )
      continue;

    if ( !volTool.Set( *elem, /*ignoreCentralNodes=*/false )) continue; // strange...

    TSplitMethod splitMethod = getSplitMethod( volTool, theMethodFlags );
    if ( splitMethod._nbTetra < 1 ) continue;

    // find submesh to add new tetras to
    if ( !subMesh || !subMesh->Contains( *elem ))
    {
      int shapeID = FindShape( *elem );
      helper.SetSubShape( shapeID ); // helper will add tetras to the found submesh
      subMesh = GetMeshDS()->MeshElements( shapeID );
    }
    int iQ;
    if ( (*elem)->IsQuadratic() )
    {
      iQ = 2;
      // add quadratic links to the helper
      for ( int iF = 0; iF < volTool.NbFaces(); ++iF )
      {
        const SMDS_MeshNode** fNodes = volTool.GetFaceNodes( iF );
        int nbN = volTool.NbFaceNodes( iF ) - bool( volTool.GetCenterNodeIndex(iF) > 0 );
        for ( int iN = 0; iN < nbN; iN += iQ )
          helper.AddTLinkNode( fNodes[iN], fNodes[iN+2], fNodes[iN+1] );
      }
      helper.SetIsQuadratic( true );
    }
    else
    {
      iQ = 1;
      helper.SetIsQuadratic( false );
    }
    vector<const SMDS_MeshNode*> nodes( (*elem)->begin_nodes(), (*elem)->end_nodes() );
    helper.SetElementsOnShape( true );
    if ( splitMethod._baryNode )
    {
      // make a node at barycenter
      volTool.GetBaryCenter( bc[0], bc[1], bc[2] );
      SMDS_MeshNode* gcNode = helper.AddNode( bc[0], bc[1], bc[2] );
      nodes.push_back( gcNode );
      newNodes.Append( gcNode );
    }
    if ( !splitMethod._faceBaryNode.empty() )
    {
      // make or find baricentric nodes of faces
      map<int, const SMDS_MeshNode*>::iterator iF_n = splitMethod._faceBaryNode.begin();
      for ( ; iF_n != splitMethod._faceBaryNode.end(); ++iF_n )
      {
        map< TVolumeFaceKey, const SMDS_MeshNode* >::iterator f_n =
          volFace2BaryNode.insert
          ( make_pair( TVolumeFaceKey( volTool,iF_n->first ), iF_n->second )).first;
        if ( !f_n->second )
        {
          volTool.GetFaceBaryCenter( iF_n->first, bc[0], bc[1], bc[2] );
          newNodes.Append( f_n->second = helper.AddNode( bc[0], bc[1], bc[2] ));
        }
        nodes.push_back( iF_n->second = f_n->second );
      }
    }

    // make tetras
    vector<const SMDS_MeshElement* > tetras( splitMethod._nbTetra ); // splits of a volume
    const int* tetConn = splitMethod._connectivity;
    for ( int i = 0; i < splitMethod._nbTetra; ++i, tetConn += 4 )
      newElems.Append( tetras[ i ] = helper.AddVolume( nodes[ tetConn[0] ],
                                                       nodes[ tetConn[1] ],
                                                       nodes[ tetConn[2] ],
                                                       nodes[ tetConn[3] ]));

    ReplaceElemInGroups( *elem, tetras, GetMeshDS() );

    // Split faces on sides of the split volume

    const SMDS_MeshNode** volNodes = volTool.GetNodes();
    for ( int iF = 0; iF < volTool.NbFaces(); ++iF )
    {
      const int nbNodes = volTool.NbFaceNodes( iF ) / iQ;
      if ( nbNodes < 4 ) continue;

      // find an existing face
      vector<const SMDS_MeshNode*> fNodes( volTool.GetFaceNodes( iF ),
                                           volTool.GetFaceNodes( iF ) + volTool.NbFaceNodes( iF ));
      while ( const SMDS_MeshElement* face = GetMeshDS()->FindElement( fNodes, SMDSAbs_Face,
                                                                       /*noMedium=*/false))
      {
        // make triangles
        helper.SetElementsOnShape( false );
        vector< const SMDS_MeshElement* > triangles;

        // find submesh to add new triangles in
        if ( !fSubMesh || !fSubMesh->Contains( face ))
        {
          int shapeID = FindShape( face );
          fSubMesh = GetMeshDS()->MeshElements( shapeID );
        }
        map<int, const SMDS_MeshNode*>::iterator iF_n = splitMethod._faceBaryNode.find(iF);
        if ( iF_n != splitMethod._faceBaryNode.end() )
        {
          for ( int iN = 0; iN < nbNodes*iQ; iN += iQ )
          {
            const SMDS_MeshNode* n1 = fNodes[iN];
            const SMDS_MeshNode *n2 = fNodes[(iN+iQ)%(nbNodes*iQ)];
            const SMDS_MeshNode *n3 = iF_n->second;
            if ( !volTool.IsFaceExternal( iF ))
              swap( n2, n3 );
            triangles.push_back( helper.AddFace( n1,n2,n3 ));

            if ( fSubMesh && n3->getshapeId() < 1 )
              fSubMesh->AddNode( n3 );
          }
        }
        else
        {
          // among possible triangles create ones discribed by split method
          const int* nInd = volTool.GetFaceNodesIndices( iF );
          int nbVariants = ( nbNodes == 4 ? 2 : nbNodes );
          int iCom = 0; // common node of triangle faces to split into
          list< TTriangleFacet > facets;
          for ( int iVar = 0; iVar < nbVariants; ++iVar, ++iCom )
          {
            TTriangleFacet t012( nInd[ iQ * ( iCom                )],
                                 nInd[ iQ * ( (iCom+1)%nbNodes )],
                                 nInd[ iQ * ( (iCom+2)%nbNodes )]);
            TTriangleFacet t023( nInd[ iQ * ( iCom                )],
                                 nInd[ iQ * ( (iCom+2)%nbNodes )],
                                 nInd[ iQ * ( (iCom+3)%nbNodes )]);
            if ( splitMethod.hasFacet( t012 ) && splitMethod.hasFacet( t023 ))
            {
              facets.push_back( t012 );
              facets.push_back( t023 );
              for ( int iLast = iCom+4; iLast < iCom+nbNodes; ++iLast )
                facets.push_back( TTriangleFacet( nInd[ iQ * ( iCom             )],
                                                  nInd[ iQ * ((iLast-1)%nbNodes )],
                                                  nInd[ iQ * ((iLast  )%nbNodes )]));
              break;
            }
          }
          list< TTriangleFacet >::iterator facet = facets.begin();
          for ( ; facet != facets.end(); ++facet )
          {
            if ( !volTool.IsFaceExternal( iF ))
              swap( facet->_n2, facet->_n3 );
            triangles.push_back( helper.AddFace( volNodes[ facet->_n1 ],
                                                 volNodes[ facet->_n2 ],
                                                 volNodes[ facet->_n3 ]));
          }
        }
        for ( int i = 0; i < triangles.size(); ++i )
        {
          if ( !triangles[i] ) continue;
          if ( fSubMesh )
            fSubMesh->AddElement( triangles[i]);
          newElems.Append( triangles[i] );
        }
        ReplaceElemInGroups( face, triangles, GetMeshDS() );
        GetMeshDS()->RemoveFreeElement( face, fSubMesh, /*fromGroups=*/false );
      }

    } // loop on volume faces to split them into triangles

    GetMeshDS()->RemoveFreeElement( *elem, subMesh, /*fromGroups=*/false );

    if ( geomType == SMDSEntity_TriQuad_Hexa )
    {
      // remove medium nodes that could become free
      for ( int i = 20; i < volTool.NbNodes(); ++i )
        if ( volNodes[i]->NbInverseElements() == 0 )
          GetMeshDS()->RemoveNode( volNodes[i] );
    }
  } // loop on volumes to split

  myLastCreatedNodes = newNodes;
  myLastCreatedElems = newElems;
}
void SMESH::SMESH_MeshEditor::Translate ( in long_array  IDsOfElements,
in DirStruct  Vector,
in boolean  Copy 
)
SMESH_Mesh SMESH::SMESH_MeshEditor::TranslateMakeMesh ( in long_array  IDsOfElements,
in DirStruct  Vector,
in boolean  CopyGroups,
in string  MeshName 
)
void SMESH::SMESH_MeshEditor::TranslateObject ( in SMESH_IDSource  theObject,
in DirStruct  Vector,
in boolean  Copy 
)
SMESH_Mesh SMESH::SMESH_MeshEditor::TranslateObjectMakeMesh ( in SMESH_IDSource  theObject,
in DirStruct  Vector,
in boolean  CopyGroups,
in string  MeshName 
)
bool SMESH_MeshEditor::TriToQuad ( in long_array  IDsOfElements,
in NumericalFunctor  Criterion,
in double  MaxAngle 
)

Fuse neighbour triangles into quadrangles.

Parameters:
theElemsThe triangles to be fused.
theCriterionIs used to choose a neighbour to fuse with.
theMaxAngleIs a max angle between element normals at which fusion is still performed; theMaxAngle is mesured in radians.
Returns:
TRUE in case of success, FALSE otherwise.

Definition at line 2166 of file SMESH_MeshEditor.cxx.

{
  myLastCreatedElems.Clear();
  myLastCreatedNodes.Clear();

  MESSAGE( "::TriToQuad()" );

  if ( !theCrit.get() )
    return false;

  SMESHDS_Mesh * aMesh = GetMeshDS();

  // Prepare data for algo: build
  // 1. map of elements with their linkIDs
  // 2. map of linkIDs with their elements

  map< SMESH_TLink, list< const SMDS_MeshElement* > > mapLi_listEl;
  map< SMESH_TLink, list< const SMDS_MeshElement* > >::iterator itLE;
  map< const SMDS_MeshElement*, set< SMESH_TLink > >  mapEl_setLi;
  map< const SMDS_MeshElement*, set< SMESH_TLink > >::iterator itEL;

  TIDSortedElemSet::iterator itElem;
  for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) {
    const SMDS_MeshElement* elem = *itElem;
    if(!elem || elem->GetType() != SMDSAbs_Face ) continue;
    bool IsTria = elem->NbNodes()==3 || (elem->NbNodes()==6 && elem->IsQuadratic());
    if(!IsTria) continue;

    // retrieve element nodes
    const SMDS_MeshNode* aNodes [4];
    SMDS_ElemIteratorPtr itN = elem->nodesIterator();
    int i = 0;
    while ( i<3 )
      aNodes[ i++ ] = cast2Node( itN->next() );
    aNodes[ 3 ] = aNodes[ 0 ];

    // fill maps
    for ( i = 0; i < 3; i++ ) {
      SMESH_TLink link( aNodes[i], aNodes[i+1] );
      // check if elements sharing a link can be fused
      itLE = mapLi_listEl.find( link );
      if ( itLE != mapLi_listEl.end() ) {
        if ((*itLE).second.size() > 1 ) // consider only 2 elems adjacent by a link
          continue;
        const SMDS_MeshElement* elem2 = (*itLE).second.front();
        //if ( FindShape( elem ) != FindShape( elem2 ))
        //  continue; // do not fuse triangles laying on different shapes
        if ( getAngle( elem, elem2, aNodes[i], aNodes[i+1] ) > theMaxAngle )
          continue; // avoid making badly shaped quads
        (*itLE).second.push_back( elem );
      }
      else {
        mapLi_listEl[ link ].push_back( elem );
      }
      mapEl_setLi [ elem ].insert( link );
    }
  }
  // Clean the maps from the links shared by a sole element, ie
  // links to which only one element is bound in mapLi_listEl

  for ( itLE = mapLi_listEl.begin(); itLE != mapLi_listEl.end(); itLE++ ) {
    int nbElems = (*itLE).second.size();
    if ( nbElems < 2  ) {
      const SMDS_MeshElement* elem = (*itLE).second.front();
      SMESH_TLink link = (*itLE).first;
      mapEl_setLi[ elem ].erase( link );
      if ( mapEl_setLi[ elem ].empty() )
        mapEl_setLi.erase( elem );
    }
  }

  // Algo: fuse triangles into quadrangles

  while ( ! mapEl_setLi.empty() ) {
    // Look for the start element:
    // the element having the least nb of shared links
    const SMDS_MeshElement* startElem = 0;
    int minNbLinks = 4;
    for ( itEL = mapEl_setLi.begin(); itEL != mapEl_setLi.end(); itEL++ ) {
      int nbLinks = (*itEL).second.size();
      if ( nbLinks < minNbLinks ) {
        startElem = (*itEL).first;
        minNbLinks = nbLinks;
        if ( minNbLinks == 1 )
          break;
      }
    }

    // search elements to fuse starting from startElem or links of elements
    // fused earlyer - startLinks
    list< SMESH_TLink > startLinks;
    while ( startElem || !startLinks.empty() ) {
      while ( !startElem && !startLinks.empty() ) {
        // Get an element to start, by a link
        SMESH_TLink linkId = startLinks.front();
        startLinks.pop_front();
        itLE = mapLi_listEl.find( linkId );
        if ( itLE != mapLi_listEl.end() ) {
          list< const SMDS_MeshElement* > & listElem = (*itLE).second;
          list< const SMDS_MeshElement* >::iterator itE = listElem.begin();
          for ( ; itE != listElem.end() ; itE++ )
            if ( mapEl_setLi.find( (*itE) ) != mapEl_setLi.end() )
              startElem = (*itE);
          mapLi_listEl.erase( itLE );
        }
      }

      if ( startElem ) {
        // Get candidates to be fused
        const SMDS_MeshElement *tr1 = startElem, *tr2 = 0, *tr3 = 0;
        const SMESH_TLink *link12, *link13;
        startElem = 0;
        ASSERT( mapEl_setLi.find( tr1 ) != mapEl_setLi.end() );
        set< SMESH_TLink >& setLi = mapEl_setLi[ tr1 ];
        ASSERT( !setLi.empty() );
        set< SMESH_TLink >::iterator itLi;
        for ( itLi = setLi.begin(); itLi != setLi.end(); itLi++ )
        {
          const SMESH_TLink & link = (*itLi);
          itLE = mapLi_listEl.find( link );
          if ( itLE == mapLi_listEl.end() )
            continue;

          const SMDS_MeshElement* elem = (*itLE).second.front();
          if ( elem == tr1 )
            elem = (*itLE).second.back();
          mapLi_listEl.erase( itLE );
          if ( mapEl_setLi.find( elem ) == mapEl_setLi.end())
            continue;
          if ( tr2 ) {
            tr3 = elem;
            link13 = &link;
          }
          else {
            tr2 = elem;
            link12 = &link;
          }

          // add other links of elem to list of links to re-start from
          set< SMESH_TLink >& links = mapEl_setLi[ elem ];
          set< SMESH_TLink >::iterator it;
          for ( it = links.begin(); it != links.end(); it++ ) {
            const SMESH_TLink& link2 = (*it);
            if ( link2 != link )
              startLinks.push_back( link2 );
          }
        }

        // Get nodes of possible quadrangles
        const SMDS_MeshNode *n12 [4], *n13 [4];
        bool Ok12 = false, Ok13 = false;
        const SMDS_MeshNode *linkNode1, *linkNode2;
        if(tr2) {
          linkNode1 = link12->first;
          linkNode2 = link12->second;
          if ( tr2 && getQuadrangleNodes( n12, linkNode1, linkNode2, tr1, tr2 ))
            Ok12 = true;
        }
        if(tr3) {
          linkNode1 = link13->first;
          linkNode2 = link13->second;
          if ( tr3 && getQuadrangleNodes( n13, linkNode1, linkNode2, tr1, tr3 ))
            Ok13 = true;
        }

        // Choose a pair to fuse
        if ( Ok12 && Ok13 ) {
          SMDS_FaceOfNodes quad12 ( n12[ 0 ], n12[ 1 ], n12[ 2 ], n12[ 3 ] );
          SMDS_FaceOfNodes quad13 ( n13[ 0 ], n13[ 1 ], n13[ 2 ], n13[ 3 ] );
          double aBadRate12 = getBadRate( &quad12, theCrit );
          double aBadRate13 = getBadRate( &quad13, theCrit );
          if (  aBadRate13 < aBadRate12 )
            Ok12 = false;
          else
            Ok13 = false;
        }

        // Make quadrangles
        // and remove fused elems and removed links from the maps
        mapEl_setLi.erase( tr1 );
        if ( Ok12 ) {
          mapEl_setLi.erase( tr2 );
          mapLi_listEl.erase( *link12 );
          if(tr1->NbNodes()==3) {
            const SMDS_MeshElement* newElem = 0;
            newElem = aMesh->AddFace(n12[0], n12[1], n12[2], n12[3] );
            myLastCreatedElems.Append(newElem);
            AddToSameGroups( newElem, tr1, aMesh );
            int aShapeId = tr1->getshapeId();
            if ( aShapeId )
              {
                aMesh->SetMeshElementOnShape( newElem, aShapeId );
              }
            aMesh->RemoveElement( tr1 );
            aMesh->RemoveElement( tr2 );
          }
          else {
            const SMDS_MeshNode* N1 [6];
            const SMDS_MeshNode* N2 [6];
            GetNodesFromTwoTria(tr1,tr2,N1,N2);
            // now we receive following N1 and N2 (using numeration as above image)
            // tria1 : (1 2 4 5 9 7)  and  tria2 : (3 4 2 8 9 6)
            // i.e. first nodes from both arrays determ new diagonal
            const SMDS_MeshNode* aNodes[8];
            aNodes[0] = N1[0];
            aNodes[1] = N1[1];
            aNodes[2] = N2[0];
            aNodes[3] = N2[1];
            aNodes[4] = N1[3];
            aNodes[5] = N2[5];
            aNodes[6] = N2[3];
            aNodes[7] = N1[5];
            const SMDS_MeshElement* newElem = 0;
            newElem = aMesh->AddFace(aNodes[0], aNodes[1], aNodes[2], aNodes[3],
                                     aNodes[4], aNodes[5], aNodes[6], aNodes[7]);
            myLastCreatedElems.Append(newElem);
            AddToSameGroups( newElem, tr1, aMesh );
            int aShapeId = tr1->getshapeId();
            if ( aShapeId )
              {
                aMesh->SetMeshElementOnShape( newElem, aShapeId );
              }
            aMesh->RemoveElement( tr1 );
            aMesh->RemoveElement( tr2 );
            // remove middle node (9)
            GetMeshDS()->RemoveNode( N1[4] );
          }
        }
        else if ( Ok13 ) {
          mapEl_setLi.erase( tr3 );
          mapLi_listEl.erase( *link13 );
          if(tr1->NbNodes()==3) {
            const SMDS_MeshElement* newElem = 0;
            newElem = aMesh->AddFace(n13[0], n13[1], n13[2], n13[3] );
            myLastCreatedElems.Append(newElem);
            AddToSameGroups( newElem, tr1, aMesh );
            int aShapeId = tr1->getshapeId();
            if ( aShapeId )
              {
                aMesh->SetMeshElementOnShape( newElem, aShapeId );
              }
            aMesh->RemoveElement( tr1 );
            aMesh->RemoveElement( tr3 );
          }
          else {
            const SMDS_MeshNode* N1 [6];
            const SMDS_MeshNode* N2 [6];
            GetNodesFromTwoTria(tr1,tr3,N1,N2);
            // now we receive following N1 and N2 (using numeration as above image)
            // tria1 : (1 2 4 5 9 7)  and  tria2 : (3 4 2 8 9 6)
            // i.e. first nodes from both arrays determ new diagonal
            const SMDS_MeshNode* aNodes[8];
            aNodes[0] = N1[0];
            aNodes[1] = N1[1];
            aNodes[2] = N2[0];
            aNodes[3] = N2[1];
            aNodes[4] = N1[3];
            aNodes[5] = N2[5];
            aNodes[6] = N2[3];
            aNodes[7] = N1[5];
            const SMDS_MeshElement* newElem = 0;
            newElem = aMesh->AddFace(aNodes[0], aNodes[1], aNodes[2], aNodes[3],
                                     aNodes[4], aNodes[5], aNodes[6], aNodes[7]);
            myLastCreatedElems.Append(newElem);
            AddToSameGroups( newElem, tr1, aMesh );
            int aShapeId = tr1->getshapeId();
            if ( aShapeId )
              {
                aMesh->SetMeshElementOnShape( newElem, aShapeId );
              }
            aMesh->RemoveElement( tr1 );
            aMesh->RemoveElement( tr3 );
            // remove middle node (9)
            GetMeshDS()->RemoveNode( N1[4] );
          }
        }

        // Next element to fuse: the rejected one
        if ( tr3 )
          startElem = Ok12 ? tr3 : tr2;

      } // if ( startElem )
    } // while ( startElem || !startLinks.empty() )
  } // while ( ! mapEl_setLi.empty() )

  return true;
}

Here is the call graph for this function:

boolean SMESH::SMESH_MeshEditor::TriToQuadObject ( in SMESH_IDSource  theObject,
in NumericalFunctor  Criterion,
in double  MaxAngle 
)

Fuse neighbour triangles into quadrangles.

Behaves like the above method, taking list of elements from theObject


The documentation for this interface was generated from the following files: