Version: 6.3.1
Data Structures | Public Types | Public Member Functions | Static Public Member Functions | Private Types | Private Member Functions | Private Attributes

SMESH_MeshEditor Class Reference

Editor of a mesh. More...

#include <SMESH_MeshEditor.hxx>

Data Structures

struct  ExtrusParam
 special structure for control of extrusion functionality More...
struct  SMESH_MeshEditor_PathPoint

Public Types

enum  SplitVolumToTetraFlags { HEXA_TO_5 = 1, HEXA_TO_6 = 2, HEXA_TO_24 = 3 }
enum  SmoothMethod { LAPLACIAN = 0, CENTROIDAL }
enum  ExtrusionFlags { EXTRUSION_FLAG_BOUNDARY = 0x01, EXTRUSION_FLAG_SEW = 0x02 }
 

Auxilary flag for advanced extrusion.

More...
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  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, SEW_INTERNAL_ERROR
}
enum  Bnd_Dimension { BND_2DFROM3D, BND_1DFROM3D, BND_1DFROM2D }
typedef std::auto_ptr
< std::list< int > > 
PGroupIDs
typedef std::list< std::list
< const SMDS_MeshNode * > > 
TListOfListOfNodes
typedef std::list< std::list
< int > > 
TListOfListOfElementsID

Public Member Functions

 SMESH_MeshEditor (SMESH_Mesh *theMesh)
SMDS_MeshElementAddElement (const std::vector< const SMDS_MeshNode * > &nodes, const SMDSAbs_ElementType type, const bool isPoly, const int ID=-1)
 Add element.
SMDS_MeshElementAddElement (const std::vector< int > &nodeIDs, const SMDSAbs_ElementType type, const bool isPoly, const int ID=-1)
 Add element.
int Remove (const std::list< int > &theElemIDs, const bool isNodes)
bool InverseDiag (const SMDS_MeshElement *theTria1, const SMDS_MeshElement *theTria2)
bool InverseDiag (const SMDS_MeshNode *theNode1, const SMDS_MeshNode *theNode2)
bool DeleteDiag (const SMDS_MeshNode *theNode1, const SMDS_MeshNode *theNode2)
bool Reorient (const SMDS_MeshElement *theElement)
bool TriToQuad (TIDSortedElemSet &theElems, SMESH::Controls::NumericalFunctorPtr theCriterion, const double theMaxAngle)
 Fuse neighbour triangles into quadrangles.
bool QuadToTri (TIDSortedElemSet &theElems, SMESH::Controls::NumericalFunctorPtr theCriterion)
 Split quadrangles into triangles.
bool QuadToTri (TIDSortedElemSet &theElems, const bool the13Diag)
 Split quadrangles into triangles.
int BestSplit (const SMDS_MeshElement *theQuad, SMESH::Controls::NumericalFunctorPtr theCriterion)
 Find better diagonal for splitting.
void SplitVolumesIntoTetra (const TIDSortedElemSet &theElems, const int theMethodFlags)
 Split volumic elements into tetrahedra.
void Smooth (TIDSortedElemSet &theElements, std::set< const SMDS_MeshNode * > &theFixedNodes, const SmoothMethod theSmoothMethod, const int theNbIterations, double theTgtAspectRatio=1.0, const bool the2D=true)
PGroupIDs RotationSweep (TIDSortedElemSet &theElements, const gp_Ax1 &theAxis, const double theAngle, const int theNbSteps, const double theToler, const bool theMakeGroups, const bool theMakeWalls=true)
const SMDS_MeshNodeCreateNode (const double x, const double y, const double z, const double tolnode, SMESH_SequenceOfNode &aNodes)
 Create new node in the mesh with given coordinates (auxiliary for advanced extrusion)
PGroupIDs ExtrusionSweep (TIDSortedElemSet &theElems, const gp_Vec &theStep, const int theNbSteps, TElemOfElemListMap &newElemsMap, const bool theMakeGroups, const int theFlags=EXTRUSION_FLAG_BOUNDARY, const double theTolerance=1.e-6)
 Generate new elements by extrusion of theElements It is a method used in .idl file.
PGroupIDs ExtrusionSweep (TIDSortedElemSet &theElems, ExtrusParam &theParams, TElemOfElemListMap &newElemsMap, const bool theMakeGroups, const int theFlags, const double theTolerance)
 Generate new elements by extrusion of theElements.
Extrusion_Error ExtrusionAlongTrack (TIDSortedElemSet &theElements, SMESH_subMesh *theTrackPattern, const SMDS_MeshNode *theNodeStart, const bool theHasAngles, std::list< double > &theAngles, const bool theLinearVariation, const bool theHasRefPoint, const gp_Pnt &theRefPoint, const bool theMakeGroups)
Extrusion_Error ExtrusionAlongTrack (TIDSortedElemSet &theElements, SMESH_Mesh *theTrackPattern, const SMDS_MeshNode *theNodeStart, const bool theHasAngles, std::list< double > &theAngles, const bool theLinearVariation, const bool theHasRefPoint, const gp_Pnt &theRefPoint, const bool theMakeGroups)
PGroupIDs Transform (TIDSortedElemSet &theElements, const gp_Trsf &theTrsf, const bool theCopy, const bool theMakeGroups, SMESH_Mesh *theTargetMesh=0)
 Move or copy theElements applying theTrsf to their nodes.
void FindCoincidentNodes (TIDSortedNodeSet &theNodes, const double theTolerance, TListOfListOfNodes &theGroupsOfNodes)
 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.
SMESH_NodeSearcherGetNodeSearcher ()
 Return SMESH_NodeSearcher.
SMESH_ElementSearcherGetElementSearcher ()
 Return SMESH_ElementSearcher.
SMESH_ElementSearcherGetElementSearcher (SMDS_ElemIteratorPtr elemIt)
 Return SMESH_ElementSearcher.
int SimplifyFace (const std::vector< const SMDS_MeshNode * > faceNodes, std::vector< const SMDS_MeshNode * > &poly_nodes, std::vector< int > &quantities) const
void MergeNodes (TListOfListOfNodes &theNodeGroups)
void FindEqualElements (std::set< const SMDS_MeshElement * > &theElements, TListOfListOfElementsID &theGroupsOfElementsID)
void MergeElements (TListOfListOfElementsID &theGroupsOfElementsID)
void MergeEqualElements ()
Sew_Error SewFreeBorder (const SMDS_MeshNode *theBorderFirstNode, const SMDS_MeshNode *theBorderSecondNode, const SMDS_MeshNode *theBorderLastNode, const SMDS_MeshNode *theSide2FirstNode, const SMDS_MeshNode *theSide2SecondNode, const SMDS_MeshNode *theSide2ThirdNode=0, const bool theSide2IsFreeBorder=true, const bool toCreatePolygons=false, const bool toCreatePolyedrs=false)
Sew_Error SewSideElements (TIDSortedElemSet &theSide1, TIDSortedElemSet &theSide2, const SMDS_MeshNode *theFirstNode1ToMerge, const SMDS_MeshNode *theFirstNode2ToMerge, const SMDS_MeshNode *theSecondNode1ToMerge, const SMDS_MeshNode *theSecondNode2ToMerge)
void InsertNodesIntoLink (const SMDS_MeshElement *theFace, const SMDS_MeshNode *theBetweenNode1, const SMDS_MeshNode *theBetweenNode2, std::list< const SMDS_MeshNode * > &theNodesToInsert, const bool toCreatePoly=false)
void UpdateVolumes (const SMDS_MeshNode *theBetweenNode1, const SMDS_MeshNode *theBetweenNode2, std::list< const SMDS_MeshNode * > &theNodesToInsert)
void ConvertToQuadratic (const bool theForce3d)
void ConvertToQuadratic (const bool theForce3d, TIDSortedElemSet &theElements)
 Makes given elements quadratic.
bool ConvertFromQuadratic ()
void ConvertFromQuadratic (TIDSortedElemSet &theElements)
 Makes given elements linear.
int FindShape (const SMDS_MeshElement *theElem)
SMESH_MeshGetMesh ()
SMESHDS_MeshGetMeshDS ()
const SMESH_SequenceOfElemPtr & GetLastCreatedNodes () const
const SMESH_SequenceOfElemPtr & GetLastCreatedElems () const
bool DoubleNodes (const std::list< int > &theListOfNodes, const std::list< int > &theListOfModifiedElems)
 Creates a hole in a mesh by doubling the nodes of some particular elements.
bool DoubleNodes (const TIDSortedElemSet &theElems, const TIDSortedElemSet &theNodesNot, const TIDSortedElemSet &theAffectedElems)
 Creates a hole in a mesh by doubling the nodes of some particular elements.
bool DoubleNodesInRegion (const TIDSortedElemSet &theElems, const TIDSortedElemSet &theNodesNot, const TopoDS_Shape &theShape)
 Creates a hole in a mesh by doubling the nodes of some particular elements.
double OrientedAngle (const gp_Pnt &p0, const gp_Pnt &p1, const gp_Pnt &g1, const gp_Pnt &g2)
 compute an oriented angle between two planes defined by four points.
bool DoubleNodesOnGroupBoundaries (const std::vector< TIDSortedElemSet > &theElems, bool createJointElems)
 Double nodes on shared faces between groups of volumes and create flat elements on demand.
bool CreateFlatElementsOnFacesGroups (const std::vector< TIDSortedElemSet > &theElems)
 Double nodes on some external faces and create flat elements.
bool Make2DMeshFrom3D ()
 Generated skin mesh (containing 2D cells) from 3D mesh The created 2D mesh elements based on nodes of free faces of boundary volumes.
int MakeBoundaryMesh (const TIDSortedElemSet &elements, Bnd_Dimension dimension, SMESH_Group *group=0, SMESH_Mesh *targetMesh=0, bool toCopyElements=false, bool toCopyExistingBondary=false, bool toAddExistingBondary=false, bool aroundElements=false)

Static Public Member Functions

static bool isOut (const SMDS_MeshElement *element, const gp_Pnt &point, double tol)
 Return true if the point is IN or ON of the element.
static bool CheckFreeBorderNodes (const SMDS_MeshNode *theNode1, const SMDS_MeshNode *theNode2, const SMDS_MeshNode *theNode3=0)
static bool FindFreeBorder (const SMDS_MeshNode *theFirstNode, const SMDS_MeshNode *theSecondNode, const SMDS_MeshNode *theLastNode, std::list< const SMDS_MeshNode * > &theNodes, std::list< const SMDS_MeshElement * > &theFaces)
static void AddToSameGroups (const SMDS_MeshElement *elemToAdd, const SMDS_MeshElement *elemInGroups, SMESHDS_Mesh *aMesh)
static void RemoveElemFromGroups (const SMDS_MeshElement *element, SMESHDS_Mesh *aMesh)
static void ReplaceElemInGroups (const SMDS_MeshElement *elemToRm, const SMDS_MeshElement *elemToAdd, SMESHDS_Mesh *aMesh)
 Replace elemToRm by elemToAdd in the all groups.
static void ReplaceElemInGroups (const SMDS_MeshElement *elemToRm, const std::vector< const SMDS_MeshElement * > &elemToAdd, SMESHDS_Mesh *aMesh)
static void GetLinkedNodes (const SMDS_MeshNode *node, TIDSortedElemSet &linkedNodes, SMDSAbs_ElementType type=SMDSAbs_All)
 Return nodes linked to the given one in elements of the type.
static const SMDS_MeshElementFindFaceInSet (const SMDS_MeshNode *n1, const SMDS_MeshNode *n2, const TIDSortedElemSet &elemSet, const TIDSortedElemSet &avoidSet, int *i1=0, int *i2=0)
static Sew_Error FindMatchingNodes (std::set< const SMDS_MeshElement * > &theSide1, std::set< const SMDS_MeshElement * > &theSide2, const SMDS_MeshNode *theFirstNode1, const SMDS_MeshNode *theFirstNode2, const SMDS_MeshNode *theSecondNode1, const SMDS_MeshNode *theSecondNode2, TNodeNodeMap &theNodeReplaceMap)
 Find corresponding nodes in two sets of faces.
static bool IsMedium (const SMDS_MeshNode *node, const SMDSAbs_ElementType typeToCheck=SMDSAbs_All)
 Returns true if given node is medium.

Private Types

typedef std::map< const
SMDS_MeshNode *, std::list
< const SMDS_MeshNode * > > 
TNodeOfNodeListMap
typedef
TNodeOfNodeListMap::iterator 
TNodeOfNodeListMapItr
typedef std::vector
< TNodeOfNodeListMapItr
TVecOfNnlmiMap
typedef std::map< const
SMDS_MeshElement
*, TVecOfNnlmiMap
TElemOfVecOfNnlmiMap

Private Member Functions

int convertElemToQuadratic (SMESHDS_SubMesh *theSm, SMESH_MesherHelper &theHelper, const bool theForce3d)
 Convert elements contained in a submesh to quadratic.
int removeQuadElem (SMESHDS_SubMesh *theSm, SMDS_ElemIteratorPtr theItr, const int theShapeID)
 Convert quadratic elements to linear ones and remove quadratic nodes.
PGroupIDs generateGroups (const SMESH_SequenceOfElemPtr &nodeGens, const SMESH_SequenceOfElemPtr &elemGens, const std::string &postfix, SMESH_Mesh *targetMesh=0)
 Create groups of elements made during transformation.
void sweepElement (const SMDS_MeshElement *elem, const std::vector< TNodeOfNodeListMapItr > &newNodesItVec, std::list< const SMDS_MeshElement * > &newElems, const int nbSteps, SMESH_SequenceOfElemPtr &srcElements)
 Create elements by sweeping an element.
void makeWalls (TNodeOfNodeListMap &mapNewNodes, TElemOfElemListMap &newElemsMap, TElemOfVecOfNnlmiMap &elemNewNodesMap, TIDSortedElemSet &elemSet, const int nbSteps, SMESH_SequenceOfElemPtr &srcElements)
 Create 1D and 2D elements around swept elements.
Extrusion_Error MakeEdgePathPoints (std::list< double > &aPrms, const TopoDS_Edge &aTrackEdge, bool aFirstIsStart, std::list< SMESH_MeshEditor_PathPoint > &aLPP)
Extrusion_Error MakeExtrElements (TIDSortedElemSet &theElements, std::list< SMESH_MeshEditor_PathPoint > &theFullList, const bool theHasAngles, std::list< double > &theAngles, const bool theLinearVariation, const bool theHasRefPoint, const gp_Pnt &theRefPoint, const bool theMakeGroups)
void LinearAngleVariation (const int NbSteps, list< double > &theAngles)
bool doubleNodes (SMESHDS_Mesh *theMeshDS, const TIDSortedElemSet &theElems, const TIDSortedElemSet &theNodesNot, std::map< const SMDS_MeshNode *, const SMDS_MeshNode * > &theNodeNodeMap, const bool theIsDoubleElem)
 Creates a hole in a mesh by doubling the nodes of some particular elements.

Private Attributes

SMESH_MeshmyMesh
SMESH_SequenceOfElemPtr myLastCreatedNodes
 Sequence for keeping nodes created during last operation.
SMESH_SequenceOfElemPtr myLastCreatedElems
 Sequence for keeping elements created during last operation.

Detailed Description

Editor of a mesh.

Definition at line 99 of file SMESH_MeshEditor.hxx.


Member Typedef Documentation

typedef std::auto_ptr< std::list<int> > SMESH_MeshEditor.PGroupIDs

Definition at line 210 of file SMESH_MeshEditor.hxx.

Definition at line 626 of file SMESH_MeshEditor.hxx.

typedef std::list< std::list< int > > SMESH_MeshEditor.TListOfListOfElementsID

Definition at line 365 of file SMESH_MeshEditor.hxx.

typedef std::list< std::list< const SMDS_MeshNode* > > SMESH_MeshEditor.TListOfListOfNodes

Definition at line 331 of file SMESH_MeshEditor.hxx.

typedef std::map<const SMDS_MeshNode*, std::list<const SMDS_MeshNode*> > SMESH_MeshEditor.TNodeOfNodeListMap [private]

Definition at line 623 of file SMESH_MeshEditor.hxx.

typedef TNodeOfNodeListMap::iterator SMESH_MeshEditor.TNodeOfNodeListMapItr [private]

Definition at line 624 of file SMESH_MeshEditor.hxx.

Definition at line 625 of file SMESH_MeshEditor.hxx.


Member Enumeration Documentation

Enumerator:
BND_2DFROM3D 
BND_1DFROM3D 
BND_1DFROM2D 

Definition at line 582 of file SMESH_MeshEditor.hxx.

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 292 of file SMESH_MeshEditor.hxx.

Auxilary flag for advanced extrusion.

BOUNDARY: create or not boundary for result of extrusion SEW: try to use existing nodes or create new nodes in any case

Enumerator:
EXTRUSION_FLAG_BOUNDARY 
EXTRUSION_FLAG_SEW 

Definition at line 227 of file SMESH_MeshEditor.hxx.

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 
SEW_INTERNAL_ERROR 

Definition at line 391 of file SMESH_MeshEditor.hxx.

Enumerator:
LAPLACIAN 
CENTROIDAL 

Definition at line 193 of file SMESH_MeshEditor.hxx.

Enumerator:
HEXA_TO_5 
HEXA_TO_6 
HEXA_TO_24 

Definition at line 186 of file SMESH_MeshEditor.hxx.

{ HEXA_TO_5 = 1, HEXA_TO_6 = 2, HEXA_TO_24 = 3 };

Constructor & Destructor Documentation

SMESH_MeshEditor::SMESH_MeshEditor ( SMESH_Mesh theMesh)

Definition at line 115 of file SMESH_MeshEditor.cxx.

  :myMesh( theMesh ) // theMesh may be NULL
{
}

Member Function Documentation

SMDS_MeshElement* SMESH_MeshEditor.AddElement ( const std::vector< const SMDS_MeshNode * > &  nodes,
const SMDSAbs_ElementType  type,
const bool  isPoly,
const int  ID = -1 
)

Add element.

SMDS_MeshElement* SMESH_MeshEditor.AddElement ( const std::vector< int > &  nodeIDs,
const SMDSAbs_ElementType  type,
const bool  isPoly,
const int  ID = -1 
)

Add element.

void SMESH_MeshEditor::AddToSameGroups ( const SMDS_MeshElement elemToAdd,
const SMDS_MeshElement elemInGroups,
SMESHDS_Mesh aMesh 
) [static]

Definition at line 1757 of file SMESH_MeshEditor.cxx.

References SMDS_MeshGroup.Add(), SMESHDS_Group.Contains(), SMESHDS_Mesh.GetGroups(), ex21_lamp.group, and SMESHDS_Group.SMDSGroup().

{
  const set<SMESHDS_GroupBase*>& groups = aMesh->GetGroups();
  if (!groups.empty()) {
    set<SMESHDS_GroupBase*>::const_iterator grIt = groups.begin();
    for ( ; grIt != groups.end(); grIt++ ) {
      SMESHDS_Group* group = dynamic_cast<SMESHDS_Group*>( *grIt );
      if ( group && group->Contains( elemInGroups ))
        group->SMDSGroup().Add( elemToAdd );
    }
  }
}
int SMESH_MeshEditor.BestSplit ( const SMDS_MeshElement theQuad,
SMESH::Controls::NumericalFunctorPtr  theCriterion 
)

Find better diagonal for splitting.

Parameters:
theQuad- The face to find better splitting of.
theCriterion- Is used to choose a diagonal for splitting.
Returns:
int - 1 for 1-3 diagonal, 2 for 2-4, -1 - for errors.
bool SMESH_MeshEditor::CheckFreeBorderNodes ( const SMDS_MeshNode theNode1,
const SMDS_MeshNode theNode2,
const SMDS_MeshNode theNode3 = 0 
) [static]

Definition at line 8322 of file SMESH_MeshEditor.cxx.

References ex21_lamp.faces, and SMESH_AdvancedEditor.nodes.

{
  list< const SMDS_MeshNode* > nodes;
  list< const SMDS_MeshElement* > faces;
  return FindFreeBorder( theNode1, theNode2, theNode3, nodes, faces);
}
int SMESH_MeshEditor::convertElemToQuadratic ( SMESHDS_SubMesh theSm,
SMESH_MesherHelper theHelper,
const bool  theForce3d 
) [private]

Convert elements contained in a submesh to quadratic.

Returns:
int - nb of checked elements

Definition at line 9228 of file SMESH_MeshEditor.cxx.

References SMESH_MesherHelper.AddEdge(), SMESHDS_SubMesh.AddElement(), SMESH_MesherHelper.AddFace(), SMESH_MesherHelper.AddPolygonalFace(), SMESH_MesherHelper.AddPolyhedralVolume(), SMESH_MesherHelper.AddVolume(), SMDS_MeshElement.begin_nodes(), SMDS_MeshElement.end_nodes(), SMESHDS_SubMesh.GetElements(), SMDS_MeshElement.GetEntityType(), SMDS_MeshElement.GetID(), SMDS_MeshElement.GetType(), SMDS_MeshElement.IsQuadratic(), SMDS_MeshElement.NbNodes(), SMESH_AdvancedEditor.nodes, SMDSAbs_Edge, SMDSAbs_Face, SMDSAbs_Volume, and SMDSEntity_Polyhedra.

{
  int nbElem = 0;
  if( !theSm ) return nbElem;

  vector<int> nbNodeInFaces;
  SMDS_ElemIteratorPtr ElemItr = theSm->GetElements();
  while(ElemItr->more())
  {
    nbElem++;
    const SMDS_MeshElement* elem = ElemItr->next();
    if( !elem || elem->IsQuadratic() ) continue;

    int id = elem->GetID();
    int nbNodes = elem->NbNodes();
    SMDSAbs_ElementType aType = elem->GetType();

    vector<const SMDS_MeshNode *> nodes (elem->begin_nodes(), elem->end_nodes());
    if ( elem->GetEntityType() == SMDSEntity_Polyhedra )
      nbNodeInFaces = static_cast<const SMDS_VtkVolume* >( elem )->GetQuantities();

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

    const SMDS_MeshElement* NewElem = 0;

    switch( aType )
    {
    case SMDSAbs_Edge :
      {
        NewElem = theHelper.AddEdge(nodes[0], nodes[1], id, theForce3d);
        break;
      }
    case SMDSAbs_Face :
      {
        switch(nbNodes)
        {
        case 3:
          NewElem = theHelper.AddFace(nodes[0], nodes[1], nodes[2], id, theForce3d);
          break;
        case 4:
          NewElem = theHelper.AddFace(nodes[0], nodes[1], nodes[2], nodes[3], id, theForce3d);
          break;
        default:
          NewElem = theHelper.AddPolygonalFace(nodes, id, theForce3d);
          continue;
        }
        break;
      }
    case SMDSAbs_Volume :
      {
        switch(nbNodes)
        {
        case 4:
          NewElem = theHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], id, theForce3d);
          break;
        case 5:
          NewElem = theHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4], id, theForce3d);
          break;
        case 6:
          NewElem = theHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4], nodes[5], id, theForce3d);
          break;
        case 8:
          NewElem = theHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3],
                                        nodes[4], nodes[5], nodes[6], nodes[7], id, theForce3d);
          break;
        default:
          NewElem = theHelper.AddPolyhedralVolume(nodes, nbNodeInFaces, id, theForce3d);
        }
        break;
      }
    default :
      continue;
    }
    ReplaceElemInGroups( elem, NewElem, GetMeshDS());
    if( NewElem )
      theSm->AddElement( NewElem );
  }
//  if (!GetMeshDS()->isCompacted())
//    GetMeshDS()->compactMesh();
  return nbElem;
}
bool SMESH_MeshEditor.ConvertFromQuadratic ( )
void SMESH_MeshEditor::ConvertFromQuadratic ( TIDSortedElemSet theElements)

Makes given elements linear.

Definition at line 9675 of file SMESH_MeshEditor.cxx.

References SMESH_Algo.GetCommonNodes(), SMDS_MeshElement.GetID(), SMDS_MeshElement.GetNode(), SMDS_MeshElement.GetType(), SMDS_MeshElement.IsQuadratic(), SMDS_MeshElement.NbCornerNodes(), SMDS_MeshElement.NbNodes(), SMDSAbs_0DElement, and SMDSAbs_NbElementTypes.

{
  if ( theElements.empty() ) return;

  // collect IDs of medium nodes of theElements; some of these nodes will be removed
  set<int> mediumNodeIDs;
  TIDSortedElemSet::iterator eIt = theElements.begin();
  for ( ; eIt != theElements.end(); ++eIt )
  {
    const SMDS_MeshElement* e = *eIt;
    for ( int i = e->NbCornerNodes(); i < e->NbNodes(); ++i )
      mediumNodeIDs.insert( e->GetNode(i)->GetID() );
  }

  // replace given elements by linear ones
  typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::iterator> TSetIterator;
  SMDS_ElemIteratorPtr elemIt( new TSetIterator( theElements.begin(), theElements.end() ));
  removeQuadElem( /*theSm=*/0, elemIt, /*theShapeID=*/0 );

  // we need to convert remaining elements whose all medium nodes are in mediumNodeIDs
  // except those elements sharing medium nodes of quadratic element whose medium nodes
  // are not all in mediumNodeIDs

  // get remaining medium nodes
  TIDSortedNodeSet mediumNodes;
  set<int>::iterator nIdsIt = mediumNodeIDs.begin();
  for ( ; nIdsIt != mediumNodeIDs.end(); ++nIdsIt )
    if ( const SMDS_MeshNode* n = GetMeshDS()->FindNode( *nIdsIt ))
      mediumNodes.insert( mediumNodes.end(), n );

  // find more quadratic elements to convert
  TIDSortedElemSet moreElemsToConvert;
  TIDSortedNodeSet::iterator nIt = mediumNodes.begin();
  for ( ; nIt != mediumNodes.end(); ++nIt )
  {
    SMDS_ElemIteratorPtr invIt = (*nIt)->GetInverseElementIterator();
    while ( invIt->more() )
    {
      const SMDS_MeshElement* e = invIt->next();
      if ( e->IsQuadratic() && allMediumNodesIn( e, mediumNodes ))
      {
        // find a more complex element including e and
        // whose medium nodes are not in mediumNodes
        bool complexFound = false;
        for ( int type = e->GetType() + 1; type < SMDSAbs_0DElement; ++type )
        {
          SMDS_ElemIteratorPtr invIt2 =
            (*nIt)->GetInverseElementIterator( SMDSAbs_ElementType( type ));
          while ( invIt2->more() )
          {
            const SMDS_MeshElement* eComplex = invIt2->next();
            if ( eComplex->IsQuadratic() && !allMediumNodesIn( eComplex, mediumNodes))
            {
              int nbCommonNodes = SMESH_Algo::GetCommonNodes( e, eComplex ).size();
              if ( nbCommonNodes == e->NbNodes())
              {
                complexFound = true;
                type = SMDSAbs_NbElementTypes; // to quit from the outer loop
                break;
              }
            }
          }
        }
        if ( !complexFound )
          moreElemsToConvert.insert( e );
      }
    }
  }
  elemIt = SMDS_ElemIteratorPtr
    (new TSetIterator( moreElemsToConvert.begin(), moreElemsToConvert.end() ));
  removeQuadElem( /*theSm=*/0, elemIt, /*theShapeID=*/0 );
}
void SMESH_MeshEditor::ConvertToQuadratic ( const bool  theForce3d)

Definition at line 9316 of file SMESH_MeshEditor.cxx.

References SMESH_MesherHelper.AddEdge(), SMESH_MesherHelper.AddFace(), SMESH_MesherHelper.AddPolygonalFace(), SMESH_MesherHelper.AddPolyhedralVolume(), SMESH_MesherHelper.AddVolume(), SMDS_MeshElement.begin_nodes(), SMDS_Mesh.edgesIterator(), SMDS_MeshElement.end_nodes(), SMDS_Mesh.facesIterator(), SMESH_MesherHelper.FixQuadraticElements(), SMDS_MeshElement.GetEntityType(), SMDS_MeshElement.GetID(), SMDS_MeshElement.GetNode(), SMDS_MeshElement.IsQuadratic(), SMDS_Mesh.NbEdges(), SMDS_Mesh.NbFaces(), SMDS_MeshElement.NbNodes(), SMDS_Mesh.NbVolumes(), SMESH_AdvancedEditor.nodes, SMESHDS_Mesh.RemoveFreeElement(), SMESH_MesherHelper.SetIsQuadratic(), SMESH_MesherHelper.SetSubShape(), SMDSEntity_Polyhedra, and SMDS_Mesh.volumesIterator().

{
  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;

      int id = face->GetID();
      int nbNodes = face->NbNodes();
      vector<const SMDS_MeshNode *> nodes ( face->begin_nodes(), face->end_nodes());

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

      SMDS_MeshFace * NewFace = 0;
      switch(nbNodes)
      {
      case 3:
        NewFace = aHelper.AddFace(nodes[0], nodes[1], nodes[2], id, theForce3d);
        break;
      case 4:
        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;

      int id = volume->GetID();
      int nbNodes = volume->NbNodes();
      vector<const SMDS_MeshNode *> nodes (volume->begin_nodes(), volume->end_nodes());
      if ( volume->GetEntityType() == SMDSEntity_Polyhedra )
        nbNodeInFaces = static_cast<const SMDS_VtkVolume* >(volume)->GetQuantities();

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

      SMDS_MeshVolume * NewVolume = 0;
      switch(nbNodes)
      {
      case 4:
        NewVolume = aHelper.AddVolume(nodes[0], nodes[1], nodes[2],
                                      nodes[3], id, theForce3d );
        break;
      case 5:
        NewVolume = aHelper.AddVolume(nodes[0], nodes[1], nodes[2],
                                      nodes[3], nodes[4], id, theForce3d);
        break;
      case 6:
        NewVolume = aHelper.AddVolume(nodes[0], nodes[1], nodes[2],
                                      nodes[3], nodes[4], nodes[5], id, theForce3d);
        break;
      case 8:
        NewVolume = aHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3],
                                      nodes[4], nodes[5], nodes[6], nodes[7], id, theForce3d);
        break;
      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();
  }
}
void SMESH_MeshEditor::ConvertToQuadratic ( const bool  theForce3d,
TIDSortedElemSet theElements 
)

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 9441 of file SMESH_MeshEditor.cxx.

References SMESH_MesherHelper.AddEdge(), SMESHDS_SubMesh.AddElement(), SMESH_MesherHelper.AddFace(), SMESH_MesherHelper.AddTLinks(), SMESH_MesherHelper.AddVolume(), SMDS_MeshElement.begin_nodes(), cast2Node, SMESHDS_SubMesh.Contains(), SMDS_MeshElement.end_nodes(), SMESH_MesherHelper.FixQuadraticElements(), SMDS_MeshElement.GetID(), SMDS_MeshNode.GetInverseElementIterator(), SMDS_MeshElement.getshapeId(), SMDS_MeshElement.GetType(), SMDS_MeshElement.IsPoly(), SMDS_MeshElement.IsQuadratic(), SMESHDS_Mesh.MeshElements(), SMDS_MeshElement.NbNodes(), SMESH_AdvancedEditor.nodes, SMDS_MeshElement.nodesIterator(), SMESHDS_Mesh.RemoveFreeElement(), SMESH_MesherHelper.SetIsQuadratic(), SMESH_MesherHelper.SetSubShape(), SMDSAbs_Edge, SMDSAbs_Face, SMDSAbs_NbElementTypes, and SMDSAbs_Volume.

{
  if ( theElements.empty() ) return;

  // we believe that all theElements are of the same type
  SMDSAbs_ElementType elemType = (*theElements.begin())->GetType();
  
  // get all nodes shared by theElements
  TIDSortedNodeSet allNodes;
  TIDSortedElemSet::iterator eIt = theElements.begin();
  for ( ; eIt != theElements.end(); ++eIt )
    allNodes.insert( (*eIt)->begin_nodes(), (*eIt)->end_nodes() );

  // complete theElements with elements of lower dim whose all nodes are in allNodes

  TIDSortedElemSet quadAdjacentElems    [ SMDSAbs_NbElementTypes ]; // quadratic adjacent elements
  TIDSortedElemSet checkedAdjacentElems [ SMDSAbs_NbElementTypes ];
  TIDSortedNodeSet::iterator nIt = allNodes.begin();
  for ( ; nIt != allNodes.end(); ++nIt )
  {
    const SMDS_MeshNode* n = *nIt;
    SMDS_ElemIteratorPtr invIt = n->GetInverseElementIterator();
    while ( invIt->more() )
    {
      const SMDS_MeshElement* e = invIt->next();
      if ( e->IsQuadratic() )
      {
        quadAdjacentElems[ e->GetType() ].insert( e );
        continue;
      }
      if ( e->GetType() >= elemType )
      {
        continue; // same type of more complex linear element
      }

      if ( !checkedAdjacentElems[ e->GetType() ].insert( e ).second )
        continue; // e is already checked

      // check nodes
      bool allIn = true;
      SMDS_ElemIteratorPtr nodeIt = e->nodesIterator();
      while ( nodeIt->more() && allIn )
        allIn = allNodes.count( cast2Node( nodeIt->next() ));
      if ( allIn )
        theElements.insert(e );
    }
  }

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

  // add links of quadratic adjacent elements to the helper

  if ( !quadAdjacentElems[SMDSAbs_Edge].empty() )
    for ( eIt  = quadAdjacentElems[SMDSAbs_Edge].begin();
          eIt != quadAdjacentElems[SMDSAbs_Edge].end(); ++eIt )
    {
      helper.AddTLinks( static_cast< const SMDS_MeshEdge*> (*eIt) );
    }
  if ( !quadAdjacentElems[SMDSAbs_Face].empty() )
    for ( eIt  = quadAdjacentElems[SMDSAbs_Face].begin();
          eIt != quadAdjacentElems[SMDSAbs_Face].end(); ++eIt )
    {
      helper.AddTLinks( static_cast< const SMDS_MeshFace*> (*eIt) );
    }
  if ( !quadAdjacentElems[SMDSAbs_Volume].empty() )
    for ( eIt  = quadAdjacentElems[SMDSAbs_Volume].begin();
          eIt != quadAdjacentElems[SMDSAbs_Volume].end(); ++eIt )
    {
      helper.AddTLinks( static_cast< const SMDS_MeshVolume*> (*eIt) );
    }

  // make quadratic elements instead of linear ones

  SMESHDS_Mesh* meshDS = GetMeshDS();
  SMESHDS_SubMesh* smDS = 0;
  for ( eIt = theElements.begin(); eIt != theElements.end(); ++eIt )
  {
    const SMDS_MeshElement* elem = *eIt;
    if( elem->IsQuadratic() || elem->NbNodes() < 2 || elem->IsPoly() )
      continue;

    int id = elem->GetID();
    SMDSAbs_ElementType type = elem->GetType();
    vector<const SMDS_MeshNode *> nodes ( elem->begin_nodes(), elem->end_nodes());

    if ( !smDS || !smDS->Contains( elem ))
      smDS = meshDS->MeshElements( elem->getshapeId() );
    meshDS->RemoveFreeElement(elem, smDS, /*fromGroups=*/false);

    SMDS_MeshElement * newElem = 0;
    switch( nodes.size() )
    {
    case 4: // cases for most multiple element types go first (for optimization)
      if ( type == SMDSAbs_Volume )
        newElem = helper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], id, theForce3d);
      else
        newElem = helper.AddFace  (nodes[0], nodes[1], nodes[2], nodes[3], id, theForce3d);
      break;
    case 8:
      newElem = helper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3],
                                 nodes[4], nodes[5], nodes[6], nodes[7], id, theForce3d);
      break;
    case 3:
      newElem = helper.AddFace  (nodes[0], nodes[1], nodes[2], id, theForce3d);
      break;
    case 2:
      newElem = helper.AddEdge(nodes[0], nodes[1], id, theForce3d);
      break;
    case 5:
      newElem = helper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3],
                                 nodes[4], id, theForce3d);
      break;
    case 6:
      newElem = helper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3],
                                 nodes[4], nodes[5], id, theForce3d);
      break;
    default:;
    }
    ReplaceElemInGroups( elem, newElem, meshDS);
    if( newElem && smDS )
      smDS->AddElement( newElem );
  }

  if ( !theForce3d  && !getenv("NO_FixQuadraticElements"))
  { // setenv NO_FixQuadraticElements to know if FixQuadraticElements() is guilty of bad conversion
    helper.SetSubShape(0); // apply FixQuadraticElements() to the whole mesh
    helper.FixQuadraticElements();
  }
}
bool SMESH_MeshEditor::CreateFlatElementsOnFacesGroups ( const std::vector< TIDSortedElemSet > &  theElems)

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:
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 11357 of file SMESH_MeshEditor.cxx.

References SMESHDS_Group.Add(), SMESHDS_Mesh.AddNode(), SMESHDS_Mesh.AddVolume(), SMDS_MeshCell.ChangeNodes(), SMDS_MeshElement.GetID(), SMDS_MeshFace.GetVtkType(), SMDS_MeshElement.IsMediumNode(), SMDS_MeshElement.IsQuadratic(), MESSAGE, ex29_refine.node(), SMDS_MeshElement.nodesIterator(), SMDSAbs_Volume, SMDS_MeshNode.X(), SMDS_MeshNode.Y(), and SMDS_MeshNode.Z().

{
  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;
}
const SMDS_MeshNode* SMESH_MeshEditor.CreateNode ( const double  x,
const double  y,
const double  z,
const double  tolnode,
SMESH_SequenceOfNode &  aNodes 
)

Create new node in the mesh with given coordinates (auxiliary for advanced extrusion)

bool SMESH_MeshEditor::DeleteDiag ( const SMDS_MeshNode theNode1,
const SMDS_MeshNode theNode2 
)

Definition at line 816 of file SMESH_MeshEditor.cxx.

References SMESHDS_Mesh.AddFace(), findTriangles(), SMDS_MeshElement.GetEntityType(), GetNodesFromTwoTria(), getQuadrangleNodes(), SMDS_MeshElement.getshapeId(), MESSAGE, SMESHDS_Mesh.RemoveElement(), SMESHDS_Mesh.SetMeshElementOnShape(), SMDSEntity_Quad_Triangle, and SMDSEntity_Triangle.

{
  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;
}
bool SMESH_MeshEditor::doubleNodes ( SMESHDS_Mesh theMeshDS,
const TIDSortedElemSet theElems,
const TIDSortedElemSet theNodesNot,
std::map< const SMDS_MeshNode *, const SMDS_MeshNode * > &  theNodeNodeMap,
const bool  theIsDoubleElem 
) [private]

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

Parameters:
theMeshDS- mesh instance
theElems- the elements replicated or modified (nodes should be changed)
theNodesNot- nodes to NOT replicate
theNodeNodeMap- relation of old node to new created node
theIsDoubleElem- flag os to replicate element or modify
Returns:
TRUE if operation has been completed successfully, FALSE otherwise

Definition at line 10587 of file SMESH_MeshEditor.cxx.

References SMESHDS_Mesh.AddNode(), SMESHDS_Mesh.ChangeElementNodes(), SMDS_MeshElement.GetType(), SMDS_MeshElement.IsPoly(), MESSAGE, SMDS_MeshElement.NbNodes(), SMDS_MeshElement.nodesIterator(), SMESH_AdvancedEditor.res, SMDS_MeshNode.X(), SMDS_MeshNode.Y(), and SMDS_MeshNode.Z().

{
  MESSAGE("doubleNodes");
  // iterate on through element and duplicate them (by nodes duplication)
  bool res = false;
  TIDSortedElemSet::const_iterator elemItr = theElems.begin();
  for ( ;  elemItr != theElems.end(); ++elemItr )
  {
    const SMDS_MeshElement* anElem = *elemItr;
    if (!anElem)
      continue;

    bool isDuplicate = false;
    // duplicate nodes to duplicate element
    std::vector<const SMDS_MeshNode*> newNodes( anElem->NbNodes() );
    SMDS_ElemIteratorPtr anIter = anElem->nodesIterator();
    int ind = 0;
    while ( anIter->more() ) 
    { 

      SMDS_MeshNode* aCurrNode = (SMDS_MeshNode*)anIter->next();
      SMDS_MeshNode* aNewNode = aCurrNode;
      if ( theNodeNodeMap.find( aCurrNode ) != theNodeNodeMap.end() )
        aNewNode = (SMDS_MeshNode*)theNodeNodeMap[ aCurrNode ];
      else if ( theIsDoubleElem && theNodesNot.find( aCurrNode ) == theNodesNot.end() )
      {
        // duplicate node
        aNewNode = theMeshDS->AddNode( aCurrNode->X(), aCurrNode->Y(), aCurrNode->Z() );
        theNodeNodeMap[ aCurrNode ] = aNewNode;
        myLastCreatedNodes.Append( aNewNode );
      }
      isDuplicate |= (aCurrNode != aNewNode);
      newNodes[ ind++ ] = aNewNode;
    }
    if ( !isDuplicate )
      continue;

    if ( theIsDoubleElem )
      AddElement(newNodes, anElem->GetType(), anElem->IsPoly());
    else
      {
      MESSAGE("ChangeElementNodes");
      theMeshDS->ChangeElementNodes( anElem, &newNodes[ 0 ], anElem->NbNodes() );
      }
    res = true;
  }
  return res;
}
bool SMESH_MeshEditor::DoubleNodes ( const std::list< int > &  theListOfNodes,
const std::list< int > &  theListOfModifiedElems 
)

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

Definition at line 10652 of file SMESH_MeshEditor.cxx.

References SMESHDS_Mesh.AddNode(), SMESHDS_Mesh.ChangeElementNodes(), SMDS_Mesh.FindElement(), SMDS_Mesh.FindNode(), MESSAGE, SMDS_MeshElement.NbNodes(), SMDS_MeshElement.nodesIterator(), SMDS_MeshNode.X(), SMDS_MeshNode.Y(), and SMDS_MeshNode.Z().

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

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

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

  // iterate through nodes and duplicate them

  std::map< const SMDS_MeshNode*, const SMDS_MeshNode* > anOldNodeToNewNode;

  std::list< int >::const_iterator aNodeIter;
  for ( aNodeIter = theListOfNodes.begin(); aNodeIter != theListOfNodes.end(); ++aNodeIter )
  {
    int aCurr = *aNodeIter;
    SMDS_MeshNode* aNode = (SMDS_MeshNode*)aMeshDS->FindNode( aCurr );
    if ( !aNode )
      continue;

    // duplicate node

    const SMDS_MeshNode* aNewNode = aMeshDS->AddNode( aNode->X(), aNode->Y(), aNode->Z() );
    if ( aNewNode )
    {
      anOldNodeToNewNode[ aNode ] = aNewNode;
      myLastCreatedNodes.Append( aNewNode );
    }
  }

  // Create map of new nodes for modified elements

  std::map< SMDS_MeshElement*, vector<const SMDS_MeshNode*> > anElemToNodes;

  std::list< int >::const_iterator anElemIter;
  for ( anElemIter = theListOfModifiedElems.begin(); 
        anElemIter != theListOfModifiedElems.end(); ++anElemIter )
  {
    int aCurr = *anElemIter;
    SMDS_MeshElement* anElem = (SMDS_MeshElement*)aMeshDS->FindElement( aCurr );
    if ( !anElem )
      continue;

    vector<const SMDS_MeshNode*> aNodeArr( anElem->NbNodes() );

    SMDS_ElemIteratorPtr anIter = anElem->nodesIterator();
    int ind = 0;
    while ( anIter->more() ) 
    { 
      SMDS_MeshNode* aCurrNode = (SMDS_MeshNode*)anIter->next();
      if ( aCurr && anOldNodeToNewNode.find( aCurrNode ) != anOldNodeToNewNode.end() )
      {
        const SMDS_MeshNode* aNewNode = anOldNodeToNewNode[ aCurrNode ];
        aNodeArr[ ind++ ] = aNewNode;
      }
      else
        aNodeArr[ ind++ ] = aCurrNode;
    }
    anElemToNodes[ anElem ] = aNodeArr;
  }

  // Change nodes of elements  

  std::map< SMDS_MeshElement*, vector<const SMDS_MeshNode*> >::iterator
    anElemToNodesIter = anElemToNodes.begin();
  for ( ; anElemToNodesIter != anElemToNodes.end(); ++anElemToNodesIter )
  {
    const SMDS_MeshElement* anElem = anElemToNodesIter->first;
    vector<const SMDS_MeshNode*> aNodeArr = anElemToNodesIter->second;
    if ( anElem )
      {
      MESSAGE("ChangeElementNodes");
      aMeshDS->ChangeElementNodes( anElem, &aNodeArr[ 0 ], anElem->NbNodes() );
      }
  }

  return true;
}
bool SMESH_MeshEditor::DoubleNodes ( const TIDSortedElemSet theElems,
const TIDSortedElemSet theNodesNot,
const TIDSortedElemSet 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

Definition at line 10552 of file SMESH_MeshEditor.cxx.

References SMESH_AdvancedEditor.res.

{
  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::DoubleNodesInRegion ( const TIDSortedElemSet theElems,
const TIDSortedElemSet theNodesNot,
const TopoDS_Shape &  theShape 
)

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

Parameters:
theElems- group of of elements (edges or faces) to be replicated
theNodesNot- group of nodes not to 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

Definition at line 10809 of file SMESH_MeshEditor.cxx.

References cast2Node, SMDS_MeshNode.GetInverseElementIterator(), and SMDS_MeshElement.nodesIterator().

{
  if ( theShape.IsNull() )
    return false;

  const double aTol = Precision::Confusion();
  auto_ptr< BRepClass3d_SolidClassifier> bsc3d;
  auto_ptr<_FaceClassifier>              aFaceClassifier;
  if ( theShape.ShapeType() == TopAbs_SOLID )
  {
    bsc3d.reset( new BRepClass3d_SolidClassifier(theShape));;
    bsc3d->PerformInfinitePoint(aTol);
  }
  else if (theShape.ShapeType() == TopAbs_FACE )
  {
    aFaceClassifier.reset( new _FaceClassifier(TopoDS::Face(theShape)));
  }

  // iterates on indicated elements and get elements by back references from their nodes
  TIDSortedElemSet anAffected;
  TIDSortedElemSet::const_iterator elemItr = theElems.begin();
  for ( ;  elemItr != theElems.end(); ++elemItr )
  {
    SMDS_MeshElement* anElem = (SMDS_MeshElement*)*elemItr;
    if (!anElem)
      continue;

    SMDS_ElemIteratorPtr nodeItr = anElem->nodesIterator();
    while ( nodeItr->more() )
    {
      const SMDS_MeshNode* aNode = cast2Node(nodeItr->next());
      if ( !aNode || theNodesNot.find(aNode) != theNodesNot.end() )
        continue;
      SMDS_ElemIteratorPtr backElemItr = aNode->GetInverseElementIterator();
      while ( backElemItr->more() )
      {
        const SMDS_MeshElement* curElem = backElemItr->next();
        if ( curElem && theElems.find(curElem) == theElems.end() &&
             ( bsc3d.get() ?
               isInside( curElem, *bsc3d, aTol ) :
               isInside( curElem, *aFaceClassifier, aTol )))
          anAffected.insert( curElem );
      }
    }
  }
  return DoubleNodes( theElems, theNodesNot, anAffected );
}
bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries ( const std::vector< TIDSortedElemSet > &  theElems,
bool  createJointElems 
)

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

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 10893 of file SMESH_MeshEditor.cxx.

References SMESHDS_Group.Add(), SMESHDS_Mesh.AddNode(), SMESHDS_Mesh.BuildDownWardConnectivity(), SMDS_UnstructuredGrid.BuildLinks(), DownIdType.cellId, SMDS_UnstructuredGrid.CellIdToDownId(), DownIdType.cellType, CHRONO, CHRONOSTOP, SMESHDS_Mesh.CleanDownWardConnectivity(), SMDS_UnstructuredGrid.extrudeVolumeFromFace(), PAL_MESH_043_3D.face, SMDS_Mesh.FindElement(), SMDS_Mesh.fromVtkToSmds(), SMDS_UnstructuredGrid.getDownArray(), SMDS_Downward.getDownCells(), SMDS_Downward.getDownTypes(), SMDS_Mesh.getGrid(), SMDS_MeshElement.GetID(), SMDS_UnstructuredGrid.GetNeighbors(), SMDS_UnstructuredGrid.GetNodeIds(), SMDS_Downward.getNodes(), SMDS_Downward.getNumberOfDownCells(), SMDS_UnstructuredGrid.GetParentVolumes(), SMDS_MeshElement.getVtkId(), SMDS_VtkVolume.gravityCenter(), ex11_grid3partition.grid, ex30_tepal.m, MESSAGE, SMESHDS_Mesh.ModifyCellNodes(), NBMAXNEIGHBORS, SMESH_fixation.p0, PAL_MESH_041_mesh.p1, ex21_lamp.size, SMDSAbs_Volume, and counters.stats().

{
  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.

      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();
          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("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++)
    {
      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;
                }
            }
        }
    }

  // --- 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 muti domains with domain order

  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;
              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_MeshVolume *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(SMDSAbs_Volume, 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 edgesMultiDomains

  if (createJointElems)
    {
      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_MeshEditor.ExtrusionAlongTrack ( TIDSortedElemSet theElements,
SMESH_Mesh theTrackPattern,
const SMDS_MeshNode theNodeStart,
const bool  theHasAngles,
std::list< double > &  theAngles,
const bool  theLinearVariation,
const bool  theHasRefPoint,
const gp_Pnt &  theRefPoint,
const bool  theMakeGroups 
)
Extrusion_Error SMESH_MeshEditor.ExtrusionAlongTrack ( TIDSortedElemSet theElements,
SMESH_subMesh theTrackPattern,
const SMDS_MeshNode theNodeStart,
const bool  theHasAngles,
std::list< double > &  theAngles,
const bool  theLinearVariation,
const bool  theHasRefPoint,
const gp_Pnt &  theRefPoint,
const bool  theMakeGroups 
)
SMESH_MeshEditor::PGroupIDs SMESH_MeshEditor::ExtrusionSweep ( TIDSortedElemSet theElems,
ExtrusParam theParams,
TElemOfElemListMap newElemsMap,
const bool  theMakeGroups,
const int  theFlags,
const double  theTolerance 
)

Generate new elements by extrusion of theElements.

Parameters:
theElems- list of elements for extrusion
newElemsMapreturns history of extrusion
theFlagsset flags for performing extrusion (see description of enum ExtrusionFlags for additional information)
theTolerance- uses for comparing locations of nodes if flag EXTRUSION_FLAG_SEW is set
theParams- special structure for manage of extrusion

Definition at line 4411 of file SMESH_MeshEditor.cxx.

References SMESHDS_Mesh.AddNode(), cast2Node, SMESH.EXTRUSION_FLAG_BOUNDARY, SMESH.EXTRUSION_FLAG_SEW, SMDS_MeshElement.GetType(), SMDS_MeshElement.IsMediumNode(), SMDS_MeshElement.IsQuadratic(), MESSAGE, SMESH_MeshEditor.ExtrusParam.myDir, SMESH_MeshEditor.ExtrusParam.myNodes, SMDS_MeshElement.NbNodes(), SMDS_MeshElement.nodesIterator(), SMDSAbs_Volume, SMDS_MeshNode.X(), SMDS_MeshNode.Y(), and SMDS_MeshNode.Z().

{
  MESSAGE("ExtrusionSweep " << theMakeGroups << " " << theFlags << " " << theTolerance);
  myLastCreatedElems.Clear();
  myLastCreatedNodes.Clear();

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

  SMESHDS_Mesh* aMesh = GetMeshDS();

  int nbsteps = theParams.mySteps->Length();

  TNodeOfNodeListMap mapNewNodes;
  //TNodeOfNodeVecMap mapNewNodes;
  TElemOfVecOfNnlmiMap mapElemNewNodes;
  //TElemOfVecOfMapNodesMap mapElemNewNodes;

  // loop on theElems
  TIDSortedElemSet::iterator itElem;
  for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) {
    // check element type
    const SMDS_MeshElement* elem = *itElem;
    if ( !elem  || elem->GetType() == SMDSAbs_Volume )
      continue;

    vector<TNodeOfNodeListMapItr> & newNodesItVec = mapElemNewNodes[ elem ];
    //vector<TNodeOfNodeVecMapItr> & 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() );
      TNodeOfNodeListMap::iterator nIt = mapNewNodes.find( node );
      //TNodeOfNodeVecMap::iterator nIt = mapNewNodes.find( node );
      if ( nIt == mapNewNodes.end() ) {
        nIt = mapNewNodes.insert( make_pair( node, list<const SMDS_MeshNode*>() )).first;
        //nIt = mapNewNodes.insert( make_pair( node, vector<const SMDS_MeshNode*>() )).first;
        list<const SMDS_MeshNode*>& listNewNodes = nIt->second;
        //vector<const SMDS_MeshNode*>& vecNewNodes = nIt->second;
        //vecNewNodes.reserve(nbsteps);

        // make new nodes
        double coord[] = { node->X(), node->Y(), node->Z() };
        //int nbsteps = theParams.mySteps->Length();
        for ( int i = 0; i < nbsteps; i++ ) {
          if( elem->IsQuadratic() && !elem->IsMediumNode(node) ) {
            // create additional node
            double x = coord[0] + theParams.myDir.X()*theParams.mySteps->Value(i+1)/2.;
            double y = coord[1] + theParams.myDir.Y()*theParams.mySteps->Value(i+1)/2.;
            double z = coord[2] + theParams.myDir.Z()*theParams.mySteps->Value(i+1)/2.;
            if( theFlags & EXTRUSION_FLAG_SEW ) {
              const SMDS_MeshNode * newNode = CreateNode(x, y, z,
                                                         theTolerance, theParams.myNodes);
              listNewNodes.push_back( newNode );
            }
            else {
              const SMDS_MeshNode * newNode = aMesh->AddNode(x, y, z);
              myLastCreatedNodes.Append(newNode);
              srcNodes.Append( node );
              listNewNodes.push_back( newNode );
            }
          }
          //aTrsf.Transforms( coord[0], coord[1], coord[2] );
          coord[0] = coord[0] + theParams.myDir.X()*theParams.mySteps->Value(i+1);
          coord[1] = coord[1] + theParams.myDir.Y()*theParams.mySteps->Value(i+1);
          coord[2] = coord[2] + theParams.myDir.Z()*theParams.mySteps->Value(i+1);
          if( theFlags & EXTRUSION_FLAG_SEW ) {
            const SMDS_MeshNode * newNode = CreateNode(coord[0], coord[1], coord[2],
                                                       theTolerance, theParams.myNodes);
            listNewNodes.push_back( newNode );
            //vecNewNodes[i]=newNode;
          }
          else {
            const SMDS_MeshNode * newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
            myLastCreatedNodes.Append(newNode);
            srcNodes.Append( node );
            listNewNodes.push_back( newNode );
            //vecNewNodes[i]=newNode;
          }
        }
      }
      else {
        // if current elem is quadratic and current node is not medium
        // we have to check - may be it is needed to insert additional nodes
        if( elem->IsQuadratic() && !elem->IsMediumNode(node) ) {
          list< const SMDS_MeshNode* > & listNewNodes = nIt->second;
          if(listNewNodes.size()==nbsteps) {
            listNewNodes.clear();
            double coord[] = { node->X(), node->Y(), node->Z() };
            for ( int i = 0; i < nbsteps; i++ ) {
              double x = coord[0] + theParams.myDir.X()*theParams.mySteps->Value(i+1);
              double y = coord[1] + theParams.myDir.Y()*theParams.mySteps->Value(i+1);
              double z = coord[2] + theParams.myDir.Z()*theParams.mySteps->Value(i+1);
              if( theFlags & EXTRUSION_FLAG_SEW ) {
                const SMDS_MeshNode * newNode = CreateNode(x, y, z,
                                                           theTolerance, theParams.myNodes);
                listNewNodes.push_back( newNode );
              }
              else {
                const SMDS_MeshNode * newNode = aMesh->AddNode(x, y, z);
                myLastCreatedNodes.Append(newNode);
                srcNodes.Append( node );
                listNewNodes.push_back( newNode );
              }
              coord[0] = coord[0] + theParams.myDir.X()*theParams.mySteps->Value(i+1);
              coord[1] = coord[1] + theParams.myDir.Y()*theParams.mySteps->Value(i+1);
              coord[2] = coord[2] + theParams.myDir.Z()*theParams.mySteps->Value(i+1);
              if( theFlags & EXTRUSION_FLAG_SEW ) {
                const SMDS_MeshNode * newNode = CreateNode(coord[0], coord[1], coord[2],
                                                           theTolerance, theParams.myNodes);
                listNewNodes.push_back( newNode );
              }
              else {
                const SMDS_MeshNode * newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
                myLastCreatedNodes.Append(newNode);
                srcNodes.Append( node );
                listNewNodes.push_back( newNode );
              }
            }
          }
        }
      }
      newNodesItVec.push_back( nIt );
    }
    // make new elements
    sweepElement( elem, newNodesItVec, newElemsMap[elem], nbsteps, srcElems );
  }

  if( theFlags & EXTRUSION_FLAG_BOUNDARY ) {
    makeWalls( mapNewNodes, newElemsMap, mapElemNewNodes, theElems, nbsteps, srcElems );
  }
  PGroupIDs newGroupIDs;
  if ( theMakeGroups )
    newGroupIDs = generateGroups( srcNodes, srcElems, "extruded");

  return newGroupIDs;
}
PGroupIDs SMESH_MeshEditor.ExtrusionSweep ( TIDSortedElemSet theElems,
const gp_Vec &  theStep,
const int  theNbSteps,
TElemOfElemListMap newElemsMap,
const bool  theMakeGroups,
const int  theFlags = EXTRUSION_FLAG_BOUNDARY,
const double  theTolerance = 1.e-6 
)

Generate new elements by extrusion of theElements It is a method used in .idl file.

All functionality is implemented in the next method (see below) which is used in the current method.

Parameters:
theElems- list of elements for extrusion
newElemsMapreturns history of extrusion
theFlagsset flags for performing extrusion (see description of enum ExtrusionFlags for additional information)
theTolerance- uses for comparing locations of nodes if flag EXTRUSION_FLAG_SEW is set
void SMESH_MeshEditor::FindCoincidentNodes ( TIDSortedNodeSet theNodes,
const double  theTolerance,
TListOfListOfNodes theGroupsOfNodes 
)

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 6115 of file SMESH_MeshEditor.cxx.

References SMESH_OctreeNode.FindCoincidentNodes().

{
  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_MeshEditor.FindEqualElements ( std::set< const SMDS_MeshElement * > &  theElements,
TListOfListOfElementsID theGroupsOfElementsID 
)
const SMDS_MeshElement * SMESH_MeshEditor::FindFaceInSet ( const SMDS_MeshNode n1,
const SMDS_MeshNode n2,
const TIDSortedElemSet elemSet,
const TIDSortedElemSet avoidSet,
int i1 = 0,
int i2 = 0 
) [static]

Definition at line 8096 of file SMESH_MeshEditor.cxx.

References cast2Node, PAL_MESH_043_3D.face, SMDS_MeshNode.GetInverseElementIterator(), SMDS_MeshElement.GetNode(), SMDS_MeshElement.GetNodeIndex(), SMESH_test.i1, SMESH_test.i2, SMDS_VtkFace.interlacedNodesElemIterator(), SMDS_MeshElement.IsQuadratic(), SMESH_AdvancedEditor.n2, SMDS_MeshElement.NbNodes(), and SMDSAbs_Face.

Referenced by findAdjacentFace(), StdMeshers_ProjectionUtils.FindMatchingNodesOnFaces(), SMESH_ElementSearcherImpl.findOuterBoundary(), _QuadFaceGrid.LoadGrid(), StdMeshers_Penta_3D.LoadIJNodes(), SMESH_MesherHelper.LoadNodeColumns(), SMESH_Pattern.makePolyElements(), and makeWalls().

{
  int i1, i2;
  const SMDS_MeshElement* face = 0;

  SMDS_ElemIteratorPtr invElemIt = n1->GetInverseElementIterator(SMDSAbs_Face);
  //MESSAGE("n1->GetInverseElementIterator(SMDSAbs_Face) " << invElemIt);
  while ( invElemIt->more() && !face ) // loop on inverse faces of n1
  {
    //MESSAGE("in while ( invElemIt->more() && !face )");
    const SMDS_MeshElement* elem = invElemIt->next();
    if (avoidSet.count( elem ))
      continue;
    if ( !elemSet.empty() && !elemSet.count( elem ))
      continue;
    // index of n1
    i1 = elem->GetNodeIndex( n1 );
    // find a n2 linked to n1
    int nbN = elem->IsQuadratic() ? elem->NbNodes()/2 : elem->NbNodes();
    for ( int di = -1; di < 2 && !face; di += 2 )
    {
      i2 = (i1+di+nbN) % nbN;
      if ( elem->GetNode( i2 ) == n2 )
        face = elem;
    }
    if ( !face && elem->IsQuadratic())
    {
      // analysis for quadratic elements using all nodes
      const SMDS_VtkFace* F =
        dynamic_cast<const SMDS_VtkFace*>(elem);
      if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace"));
      // use special nodes iterator
      SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator();
      const SMDS_MeshNode* prevN = cast2Node( anIter->next() );
      for ( i1 = -1, i2 = 0; anIter->more() && !face; i1++, i2++ )
      {
        const SMDS_MeshNode* n = cast2Node( anIter->next() );
        if ( n1 == prevN && n2 == n )
        {
          face = elem;
        }
        else if ( n2 == prevN && n1 == n )
        {
          face = elem; swap( i1, i2 );
        }
        prevN = n;
      }
    }
  }
  if ( n1ind ) *n1ind = i1;
  if ( n2ind ) *n2ind = i2;
  return face;
}
bool SMESH_MeshEditor::FindFreeBorder ( const SMDS_MeshNode theFirstNode,
const SMDS_MeshNode theSecondNode,
const SMDS_MeshNode theLastNode,
std::list< const SMDS_MeshNode * > &  theNodes,
std::list< const SMDS_MeshElement * > &  theFaces 
) [static]

Definition at line 8178 of file SMESH_MeshEditor.cxx.

References cast2Node, ControlFreeBorder, findAdjacentFace(), SMDS_MeshElement.GetID(), SMDS_VtkFace.interlacedNodesElemIterator(), SMDS_MeshElement.IsQuadratic(), SMDS_MeshElement.NbNodes(), SMESH_AdvancedEditor.nodes, SMDS_MeshElement.nodesIterator(), and SMDSAbs_Face.

{
  if ( !theFirstNode || !theSecondNode )
    return false;
  // find border face between theFirstNode and theSecondNode
  const SMDS_MeshElement* curElem = findAdjacentFace( theFirstNode, theSecondNode, 0 );
  if ( !curElem )
    return false;

  theFaces.push_back( curElem );
  theNodes.push_back( theFirstNode );
  theNodes.push_back( theSecondNode );

  //vector<const SMDS_MeshNode*> nodes;
  const SMDS_MeshNode *nIgnore = theFirstNode, *nStart = theSecondNode;
  TIDSortedElemSet foundElems;
  bool needTheLast = ( theLastNode != 0 );

  while ( nStart != theLastNode ) {
    if ( nStart == theFirstNode )
      return !needTheLast;

    // find all free border faces sharing form nStart

    list< const SMDS_MeshElement* > curElemList;
    list< const SMDS_MeshNode* > nStartList;
    SMDS_ElemIteratorPtr invElemIt = nStart->GetInverseElementIterator(SMDSAbs_Face);
    while ( invElemIt->more() ) {
      const SMDS_MeshElement* e = invElemIt->next();
      if ( e == curElem || foundElems.insert( e ).second ) {
        // get nodes
        int iNode = 0, nbNodes = e->NbNodes();
        //const SMDS_MeshNode* nodes[nbNodes+1];
        vector<const SMDS_MeshNode*> nodes(nbNodes+1);

        if(e->IsQuadratic()) {
          const SMDS_VtkFace* F =
            dynamic_cast<const SMDS_VtkFace*>(e);
          if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace"));
          // use special nodes iterator
          SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator();
          while( anIter->more() ) {
            nodes[ iNode++ ] = cast2Node(anIter->next());
          }
        }
        else {
          SMDS_ElemIteratorPtr nIt = e->nodesIterator();
          while ( nIt->more() )
            nodes[ iNode++ ] = static_cast<const SMDS_MeshNode*>( nIt->next() );
        }
        nodes[ iNode ] = nodes[ 0 ];
        // check 2 links
        for ( iNode = 0; iNode < nbNodes; iNode++ )
          if (((nodes[ iNode ] == nStart && nodes[ iNode + 1] != nIgnore ) ||
               (nodes[ iNode + 1] == nStart && nodes[ iNode ] != nIgnore )) &&
              ControlFreeBorder( &nodes[ iNode ], e->GetID() ))
          {
            nStartList.push_back( nodes[ iNode + ( nodes[ iNode ] == nStart ? 1 : 0 )]);
            curElemList.push_back( e );
          }
      }
    }
    // analyse the found

    int nbNewBorders = curElemList.size();
    if ( nbNewBorders == 0 ) {
      // no free border furthermore
      return !needTheLast;
    }
    else if ( nbNewBorders == 1 ) {
      // one more element found
      nIgnore = nStart;
      nStart = nStartList.front();
      curElem = curElemList.front();
      theFaces.push_back( curElem );
      theNodes.push_back( nStart );
    }
    else {
      // several continuations found
      list< const SMDS_MeshElement* >::iterator curElemIt;
      list< const SMDS_MeshNode* >::iterator nStartIt;
      // check if one of them reached the last node
      if ( needTheLast ) {
        for (curElemIt = curElemList.begin(), nStartIt = nStartList.begin();
             curElemIt!= curElemList.end();
             curElemIt++, nStartIt++ )
          if ( *nStartIt == theLastNode ) {
            theFaces.push_back( *curElemIt );
            theNodes.push_back( *nStartIt );
            return true;
          }
      }
      // find the best free border by the continuations
      list<const SMDS_MeshNode*>    contNodes[ 2 ], *cNL;
      list<const SMDS_MeshElement*> contFaces[ 2 ], *cFL;
      for (curElemIt = curElemList.begin(), nStartIt = nStartList.begin();
           curElemIt!= curElemList.end();
           curElemIt++, nStartIt++ )
      {
        cNL = & contNodes[ contNodes[0].empty() ? 0 : 1 ];
        cFL = & contFaces[ contFaces[0].empty() ? 0 : 1 ];
        // find one more free border
        if ( ! FindFreeBorder( nStart, *nStartIt, theLastNode, *cNL, *cFL )) {
          cNL->clear();
          cFL->clear();
        }
        else if ( !contNodes[0].empty() && !contNodes[1].empty() ) {
          // choice: clear a worse one
          int iLongest = ( contNodes[0].size() < contNodes[1].size() ? 1 : 0 );
          int iWorse = ( needTheLast ? 1 - iLongest : iLongest );
          contNodes[ iWorse ].clear();
          contFaces[ iWorse ].clear();
        }
      }
      if ( contNodes[0].empty() && contNodes[1].empty() )
        return false;

      // append the best free border
      cNL = & contNodes[ contNodes[0].empty() ? 1 : 0 ];
      cFL = & contFaces[ contFaces[0].empty() ? 1 : 0 ];
      theNodes.pop_back(); // remove nIgnore
      theNodes.pop_back(); // remove nStart
      theFaces.pop_back(); // remove curElem
      list< const SMDS_MeshNode* >::iterator nIt = cNL->begin();
      list< const SMDS_MeshElement* >::iterator fIt = cFL->begin();
      for ( ; nIt != cNL->end(); nIt++ ) theNodes.push_back( *nIt );
      for ( ; fIt != cFL->end(); fIt++ ) theFaces.push_back( *fIt );
      return true;

    } // several continuations found
  } // while ( nStart != theLastNode )

  return true;
}
SMESH_MeshEditor::Sew_Error SMESH_MeshEditor::FindMatchingNodes ( std::set< const SMDS_MeshElement * > &  theSide1,
std::set< const SMDS_MeshElement * > &  theSide2,
const SMDS_MeshNode theFirstNode1,
const SMDS_MeshNode theFirstNode2,
const SMDS_MeshNode theSecondNode1,
const SMDS_MeshNode theSecondNode2,
TNodeNodeMap nReplaceMap 
) [static]

Find corresponding nodes in two sets of faces.

Parameters:
theSide1- first face set
theSide2- second first face
theFirstNode1- a boundary node of set 1
theFirstNode2- a node of set 2 corresponding to theFirstNode1
theSecondNode1- a boundary node of set 1 linked with theFirstNode1
theSecondNode2- a node of set 2 corresponding to theSecondNode1
nReplaceMap- output map of corresponding nodes
Returns:
Sew_Error - is a success or not
Parameters:
theSide1- first face set
theSide2- second first face
theFirstNode1- a boundary node of set 1
theFirstNode2- a node of set 2 corresponding to theFirstNode1
theSecondNode1- a boundary node of set 1 linked with theFirstNode1
theSecondNode2- a node of set 2 corresponding to theSecondNode1
nReplaceMap- output map of corresponding nodes
Returns:
bool - is a success or not

Definition at line 10386 of file SMESH_MeshEditor.cxx.

References Abs(), SMDS_MeshElement.GetID(), SMDS_MeshNode.GetInverseElementIterator(), SMDS_MeshElement.GetNode(), SMDS_MeshElement.GetNodeIndex(), SMESH_test.i1, SMESH_test.i2, SMDS_MeshElement.IsQuadratic(), MESSAGE, SMESH_AdvancedEditor.n1, SMESH_AdvancedEditor.n2, SMDS_MeshElement.NbNodes(), and SMDSAbs_Face.

Referenced by StdMeshers_ProjectionUtils.FindMatchingNodesOnFaces().

{
  set<const SMDS_MeshElement*> * faceSetPtr[] = { &theSide1, &theSide2 };

  nReplaceMap.clear();
  if ( theFirstNode1 != theFirstNode2 )
    nReplaceMap.insert( make_pair( theFirstNode1, theFirstNode2 ));
  if ( theSecondNode1 != theSecondNode2 )
    nReplaceMap.insert( make_pair( theSecondNode1, theSecondNode2 ));

  set< SMESH_TLink > linkSet; // set of nodes where order of nodes is ignored
  linkSet.insert( SMESH_TLink( theFirstNode1, theSecondNode1 ));

  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] };
    if ( linkSet.find( link[0] ) == linkSet.end() )
      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 };
    list<const SMDS_MeshNode*> notLinkNodes[2];
    //bool reverse[] = { false, false }; // order of notLinkNodes
    int nbNodes[2];
    for ( int iSide = 0; iSide < 2; iSide++ ) // loop on 2 sides
    {
      const SMDS_MeshNode* n1 = link[iSide].first;
      const SMDS_MeshNode* n2 = link[iSide].second;
      set<const SMDS_MeshElement*> * faceSet = faceSetPtr[ iSide ];
      set< const SMDS_MeshElement* > facesOfNode1;
      for ( int iNode = 0; iNode < 2; iNode++ ) // loop on 2 nodes of a link
      {
        // during a loop of the first node, we find all faces around n1,
        // during a loop of the second node, we find one face sharing both n1 and n2
        const SMDS_MeshNode* n = iNode ? n1 : n2; // a node of a link
        SMDS_ElemIteratorPtr fIt = n->GetInverseElementIterator(SMDSAbs_Face);
        while ( fIt->more() ) { // loop on faces sharing a node
          const SMDS_MeshElement* f = fIt->next();
          if (faceSet->find( f ) != faceSet->end() && // f is in face set
              ! facesOfNode1.insert( f ).second ) // f encounters twice
          {
            if ( face[ iSide ] ) {
              MESSAGE( "2 faces per link " );
              return ( iSide ? SEW_BAD_SIDE2_NODES : SEW_BAD_SIDE1_NODES );
            }
            face[ iSide ] = f;
            faceSet->erase( f );

            // get not link nodes
            int nbN = f->NbNodes();
            if ( f->IsQuadratic() )
              nbN /= 2;
            nbNodes[ iSide ] = nbN;
            list< const SMDS_MeshNode* > & nodes = notLinkNodes[ iSide ];
            int i1 = f->GetNodeIndex( n1 );
            int i2 = f->GetNodeIndex( n2 );
            int iEnd = nbN, iBeg = -1, iDelta = 1;
            bool reverse = ( Abs( i1 - i2 ) == 1 ? i1 > i2 : i2 > i1 );
            if ( reverse ) {
              std::swap( iEnd, iBeg ); iDelta = -1;
            }
            int i = i2;
            while ( true ) {
              i += iDelta;
              if ( i == iEnd ) i = iBeg + iDelta;
              if ( i == i1 ) break;
              nodes.push_back ( f->GetNode( i ) );
            }
          }
        }
      }
    }
    // check similarity of elements of the sides
    if (( 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
        return ( face[0] ? SEW_BAD_SIDE2_NODES : SEW_BAD_SIDE1_NODES );
      }
      else {
        return SEW_TOPO_DIFF_SETS_OF_ELEMENTS;
      }
    }

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

    if ( face[0] && face[1] )  {
      if ( nbNodes[0] != nbNodes[1] ) {
        MESSAGE("Diff nb of face nodes");
        return SEW_TOPO_DIFF_SETS_OF_ELEMENTS;
      }
#ifdef DEBUG_MATCHING_NODES
      MESSAGE ( " Link 1: " << link[0].first->GetID() <<" "<< link[0].second->GetID()
                << " F 1: " << face[0] << "| Link 2: " << link[1].first->GetID() <<" "
                << link[1].second->GetID() << " F 2: " << face[1] << " | Bind: " ) ;
#endif
      int nbN = nbNodes[0];
      {
        list<const SMDS_MeshNode*>::iterator n1 = notLinkNodes[0].begin();
        list<const SMDS_MeshNode*>::iterator n2 = notLinkNodes[1].begin();
        for ( int i = 0 ; i < nbN - 2; ++i ) {
#ifdef DEBUG_MATCHING_NODES
          MESSAGE ( (*n1)->GetID() << " to " << (*n2)->GetID() );
#endif
          nReplaceMap.insert( make_pair( *(n1++), *(n2++) ));
        }
      }

      // add other links of the face 1 to linkList
      // -----------------------------------------

      const SMDS_MeshElement* f0 = face[0];
      const SMDS_MeshNode* n1 = f0->GetNode( nbN - 1 );
      for ( int i = 0; i < nbN; i++ )
      {
        const SMDS_MeshNode* n2 = f0->GetNode( i );
        pair< set< SMESH_TLink >::iterator, bool > iter_isnew =
          linkSet.insert( SMESH_TLink( n1, n2 ));
        if ( !iter_isnew.second ) { // already in a set: no need to process
          linkSet.erase( iter_isnew.first );
        }
        else // new in set == encountered for the first time: add
        {
#ifdef DEBUG_MATCHING_NODES
          MESSAGE ( "Add link 1: " << n1->GetID() << " " << n2->GetID() << " "
                    << " | link 2: " << nReplaceMap[n1]->GetID() << " " << nReplaceMap[n2]->GetID() << " " );
#endif
          linkList[0].push_back ( NLink( n1, n2 ));
          linkList[1].push_back ( NLink( nReplaceMap[n1], nReplaceMap[n2] ));
        }
        n1 = n2;
      }
    } // 2 faces found
  } // loop on link lists

  return SEW_OK;
}
int SMESH_MeshEditor::FindShape ( const SMDS_MeshElement theElem)

Definition at line 359 of file SMESH_MeshEditor.cxx.

References SMESH_fixation.aShape, SMESHDS_SubMesh.Contains(), SMDS_MeshElement.GetID(), SMDS_MeshElement.getshapeId(), SMDS_MeshElement.GetType(), SMESHDS_Mesh.IndexToShape(), SMESHDS_Mesh.MeshElements(), MESSAGE, SMDS_MeshElement.nodesIterator(), SMESHDS_Mesh.ShapeToIndex(), SMESHDS_Mesh.ShapeToMesh(), and SMDSAbs_Node.

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

  SMESHDS_Mesh * aMesh = GetMeshDS();
  if ( aMesh->ShapeToMesh().IsNull() )
    return 0;

  int aShapeID = theElem->getshapeId();
  if ( aShapeID < 1 )
    return 0;

  if ( SMESHDS_SubMesh * sm = aMesh->MeshElements( aShapeID ))
    if ( sm->Contains( theElem ))
      return aShapeID;

  if ( theElem->GetType() == SMDSAbs_Node ) {
    MESSAGE( ":( Error: invalid myShapeId of node " << theElem->GetID() );
  }
  else {
    MESSAGE( ":( Error: invalid myShapeId of element " << theElem->GetID() );
  }

  TopoDS_Shape aShape; // the shape a node of theElem is on
  if ( theElem->GetType() != SMDSAbs_Node )
  {
    SMDS_ElemIteratorPtr nodeIt = theElem->nodesIterator();
    while ( nodeIt->more() ) {
      const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
      if ((aShapeID = node->getshapeId()) > 0) {
        if ( SMESHDS_SubMesh * sm = aMesh->MeshElements( aShapeID ) ) {
          if ( sm->Contains( theElem ))
            return aShapeID;
          if ( aShape.IsNull() )
            aShape = aMesh->IndexToShape( aShapeID );
        }
      }
    }
  }

  // None of nodes is on a proper shape,
  // find the shape among ancestors of aShape on which a node is
  if ( !aShape.IsNull() ) {
    TopTools_ListIteratorOfListOfShape ancIt( GetMesh()->GetAncestors( aShape ));
    for ( ; ancIt.More(); ancIt.Next() ) {
      SMESHDS_SubMesh * sm = aMesh->MeshElements( ancIt.Value() );
      if ( sm && sm->Contains( theElem ))
        return aMesh->ShapeToIndex( ancIt.Value() );
    }
  }
  else
  {
    const map<int,SMESHDS_SubMesh*>& id2sm = GetMeshDS()->SubMeshes();
    map<int,SMESHDS_SubMesh*>::const_iterator id_sm = id2sm.begin();
    for ( ; id_sm != id2sm.end(); ++id_sm )
      if ( id_sm->second->Contains( theElem ))
        return id_sm->first;
  }

  //MESSAGE ("::FindShape() - SHAPE NOT FOUND")
  return 0;
}
SMESH_MeshEditor::PGroupIDs SMESH_MeshEditor::generateGroups ( const SMESH_SequenceOfElemPtr &  nodeGens,
const SMESH_SequenceOfElemPtr &  elemGens,
const std::string &  postfix,
SMESH_Mesh targetMesh = 0 
) [private]

Create groups of elements made during transformation.

Parameters:
nodeGens- nodes making corresponding myLastCreatedNodes
elemGens- elements making corresponding myLastCreatedElems
postfix- to append to names of new groups

Definition at line 5991 of file SMESH_MeshEditor.cxx.

References SMDS_MeshGroup.Add(), SMESHDS_GroupBase.Contains(), SMESHDS_GroupBase.GetStoreName(), SMDS_MeshElement.GetType(), SMESHDS_GroupBase.GetType(), SMESHDS_GroupBase.IsEmpty(), MESSAGE, ex21_lamp.name, SMESHDS_GroupBase.SetStoreName(), SMDSAbs_NbElementTypes, SMDSAbs_Node, and SMESHDS_Group.SMDSGroup().

{
  PGroupIDs newGroupIDs( new list<int> );
  SMESH_Mesh* mesh = targetMesh ? targetMesh : GetMesh();

  // Sort existing groups by types and collect their names

  // to store an old group and a generated new one
  typedef pair< SMESHDS_GroupBase*, SMDS_MeshGroup* > TOldNewGroup;
  vector< list< TOldNewGroup > > groupsByType( SMDSAbs_NbElementTypes );
  // group names
  set< string > groupNames;
  //
  SMDS_MeshGroup* nullNewGroup = (SMDS_MeshGroup*) 0;
  SMESH_Mesh::GroupIteratorPtr groupIt = GetMesh()->GetGroups();
  while ( groupIt->more() ) {
    SMESH_Group * group = groupIt->next();
    if ( !group ) continue;
    SMESHDS_GroupBase* groupDS = group->GetGroupDS();
    if ( !groupDS || groupDS->IsEmpty() ) continue;
    groupNames.insert( group->GetName() );
    groupDS->SetStoreName( group->GetName() );
    groupsByType[ groupDS->GetType() ].push_back( make_pair( groupDS, nullNewGroup ));
  }

  // Groups creation

  // loop on nodes and elements
  for ( int isNodes = 0; isNodes < 2; ++isNodes )
  {
    const SMESH_SequenceOfElemPtr& gens  = isNodes ? nodeGens : elemGens;
    const SMESH_SequenceOfElemPtr& elems = isNodes ? myLastCreatedNodes : myLastCreatedElems;
    if ( gens.Length() != elems.Length() )
      throw SALOME_Exception(LOCALIZED("invalid args"));

    // loop on created elements
    for (int iElem = 1; iElem <= elems.Length(); ++iElem )
    {
      const SMDS_MeshElement* sourceElem = gens( iElem );
      if ( !sourceElem ) {
        MESSAGE("generateGroups(): NULL source element");
        continue;
      }
      list< TOldNewGroup > & groupsOldNew = groupsByType[ sourceElem->GetType() ];
      if ( groupsOldNew.empty() ) {
        while ( iElem < gens.Length() && gens( iElem+1 ) == sourceElem )
          ++iElem; // skip all elements made by sourceElem
        continue;
      }
      // collect all elements made by sourceElem
      list< const SMDS_MeshElement* > resultElems;
      if ( const SMDS_MeshElement* resElem = elems( iElem ))
        if ( resElem != sourceElem )
          resultElems.push_back( resElem );
      while ( iElem < gens.Length() && gens( iElem+1 ) == sourceElem )
        if ( const SMDS_MeshElement* resElem = elems( ++iElem ))
          if ( resElem != sourceElem )
            resultElems.push_back( resElem );
      // do not generate element groups from node ones
      if ( sourceElem->GetType() == SMDSAbs_Node &&
           elems( iElem )->GetType() != SMDSAbs_Node )
        continue;

      // add resultElems to groups made by ones the sourceElem belongs to
      list< TOldNewGroup >::iterator gOldNew, gLast = groupsOldNew.end();
      for ( gOldNew = groupsOldNew.begin(); gOldNew != gLast; ++gOldNew )
      {
        SMESHDS_GroupBase* oldGroup = gOldNew->first;
        if ( oldGroup->Contains( sourceElem )) // sourceElem in oldGroup
        {
          SMDS_MeshGroup* & newGroup = gOldNew->second;
          if ( !newGroup )// create a new group
          {
            // make a name
            string name = oldGroup->GetStoreName();
            if ( !targetMesh ) {
              name += "_";
              name += postfix;
              int nb = 0;
              while ( !groupNames.insert( name ).second ) // name exists
              {
                if ( nb == 0 ) {
                  name += "_1";
                }
                else {
                  TCollection_AsciiString nbStr(nb+1);
                  name.resize( name.rfind('_')+1 );
                  name += nbStr.ToCString();
                }
                ++nb;
              }
            }
            // make a group
            int id;
            SMESH_Group* group = mesh->AddGroup( resultElems.back()->GetType(),
                                                 name.c_str(), id );
            SMESHDS_Group* groupDS = static_cast<SMESHDS_Group*>(group->GetGroupDS());
            newGroup = & groupDS->SMDSGroup();
            newGroupIDs->push_back( id );
          }

          // fill in a new group
          list< const SMDS_MeshElement* >::iterator resLast = resultElems.end(), resElemIt;
          for ( resElemIt = resultElems.begin(); resElemIt != resLast; ++resElemIt )
            newGroup->Add( *resElemIt );
        }
      }
    } // loop on created elements
  }// loop on nodes and elements

  return newGroupIDs;
}
SMESH_ElementSearcher * SMESH_MeshEditor::GetElementSearcher ( )

Return SMESH_ElementSearcher.

The caller is responsible for deleting it

Definition at line 7039 of file SMESH_MeshEditor.cxx.

{
  return new SMESH_ElementSearcherImpl( *GetMeshDS() );
}
SMESH_ElementSearcher * SMESH_MeshEditor::GetElementSearcher ( SMDS_ElemIteratorPtr  elemIt)

Return SMESH_ElementSearcher.

Definition at line 7050 of file SMESH_MeshEditor.cxx.

{
  return new SMESH_ElementSearcherImpl( *GetMeshDS(), elemIt );
}
const SMESH_SequenceOfElemPtr& SMESH_MeshEditor.GetLastCreatedElems ( ) const

Definition at line 555 of file SMESH_MeshEditor.hxx.

{ return myLastCreatedElems; }
const SMESH_SequenceOfElemPtr& SMESH_MeshEditor.GetLastCreatedNodes ( ) const

Definition at line 553 of file SMESH_MeshEditor.hxx.

{ return myLastCreatedNodes; }
void SMESH_MeshEditor::GetLinkedNodes ( const SMDS_MeshNode theNode,
TIDSortedElemSet linkedNodes,
SMDSAbs_ElementType  type = SMDSAbs_All 
) [static]

Return nodes linked to the given one in elements of the type.

Return nodes linked to the given one.

Parameters:
theNode- the node
linkedNodes- the found nodes
type- the type of elements to check

Medium nodes are ignored

Definition at line 2665 of file SMESH_MeshEditor.cxx.

References cast2Node, SMDS_MeshNode.GetInverseElementIterator(), SMDS_MeshElement.GetNodeWrap(), SMDS_MeshElement.GetType(), SMDS_VolumeTool.IsLinked(), SMDS_MeshElement.IsQuadratic(), SMDS_MeshElement.NbNodes(), SMDS_MeshElement.nodesIterator(), SMDSAbs_0DElement, SMDSAbs_Volume, SMESH_demo_hexa2_upd.vol, and SMESH_MesherHelper.WrapIndex().

Referenced by laplacianSmooth(), SMESH_MeshEditor_i.MoveClosestNodeToPoint(), and SMESH_MeshEditor_i.MoveNode().

{
  SMDS_ElemIteratorPtr elemIt = theNode->GetInverseElementIterator(type);
  while ( elemIt->more() )
  {
    const SMDS_MeshElement* elem = elemIt->next();
    if(elem->GetType() == SMDSAbs_0DElement)
      continue;
    
    SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator();
    if ( elem->GetType() == SMDSAbs_Volume )
    {
      SMDS_VolumeTool vol( elem );
      while ( nodeIt->more() ) {
        const SMDS_MeshNode* n = cast2Node( nodeIt->next() );
        if ( theNode != n && vol.IsLinked( theNode, n ))
          linkedNodes.insert( n );
      }
    }
    else
    {
      for ( int i = 0; nodeIt->more(); ++i ) {
        const SMDS_MeshNode* n = cast2Node( nodeIt->next() );
        if ( n == theNode ) {
          int iBefore = i - 1;
          int iAfter  = i + 1;
          if ( elem->IsQuadratic() ) {
            int nb = elem->NbNodes() / 2;
            iAfter  = SMESH_MesherHelper::WrapIndex( iAfter, nb );
            iBefore = SMESH_MesherHelper::WrapIndex( iBefore, nb );
          }
          linkedNodes.insert( elem->GetNodeWrap( iAfter ));
          linkedNodes.insert( elem->GetNodeWrap( iBefore ));
        }
      }
    }
  }
}
SMESH_Mesh* SMESH_MeshEditor.GetMesh ( )

Definition at line 549 of file SMESH_MeshEditor.hxx.

{ return myMesh; }
SMESHDS_Mesh* SMESH_MeshEditor.GetMeshDS ( )

Definition at line 551 of file SMESH_MeshEditor.hxx.

{ return myMesh->GetMeshDS(); }
SMESH_NodeSearcher * SMESH_MeshEditor::GetNodeSearcher ( )

Return SMESH_NodeSearcher.

The caller is responsible for deleteing it

Definition at line 6277 of file SMESH_MeshEditor.cxx.

{
  return new SMESH_NodeSearcherImpl( GetMeshDS() );
}
void SMESH_MeshEditor::InsertNodesIntoLink ( const SMDS_MeshElement theFace,
const SMDS_MeshNode theBetweenNode1,
const SMDS_MeshNode theBetweenNode2,
std::list< const SMDS_MeshNode * > &  theNodesToInsert,
const bool  toCreatePoly = false 
)

Definition at line 8797 of file SMESH_MeshEditor.cxx.

References Abs(), SMESHDS_Mesh.AddFace(), SMESHDS_Mesh.AddPolygonalFace(), cast2Node, SMESHDS_Mesh.ChangePolygonNodes(), getBadRate(), SMDS_MeshElement.GetType(), SMESH_test.i1, SMESH_test.i2, SMESH_test.i3, SMDS_VtkFace.interlacedNodesElemIterator(), SMDS_MeshElement.IsMediumNode(), SMDS_MeshElement.IsPoly(), SMDS_MeshElement.IsQuadratic(), SMESH_AdvancedEditor.n1, SMESH_AdvancedEditor.n2, SMESH_AdvancedEditor.n3, SMESH_AdvancedEditor.nbn, SMDS_MeshElement.NbNodes(), SMESH_AdvancedEditor.nodes, SMDS_MeshElement.nodesIterator(), SMESHDS_Mesh.RemoveElement(), reverse(), SMESHDS_Mesh.SetMeshElementOnShape(), and SMDSAbs_Face.

{
  if ( theFace->GetType() != SMDSAbs_Face ) return;

  // find indices of 2 link nodes and of the rest nodes
  int iNode = 0, il1, il2, i3, i4;
  il1 = il2 = i3 = i4 = -1;
  //const SMDS_MeshNode* nodes[ theFace->NbNodes() ];
  vector<const SMDS_MeshNode*> nodes( theFace->NbNodes() );

  if(theFace->IsQuadratic()) {
    const SMDS_VtkFace* F =
      dynamic_cast<const SMDS_VtkFace*>(theFace);
    if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace"));
    // use special nodes iterator
    SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator();
    while( anIter->more() ) {
      const SMDS_MeshNode* n = cast2Node(anIter->next());
      if ( n == theBetweenNode1 )
        il1 = iNode;
      else if ( n == theBetweenNode2 )
        il2 = iNode;
      else if ( i3 < 0 )
        i3 = iNode;
      else
        i4 = iNode;
      nodes[ iNode++ ] = n;
    }
  }
  else {
    SMDS_ElemIteratorPtr nodeIt = theFace->nodesIterator();
    while ( nodeIt->more() ) {
      const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
      if ( n == theBetweenNode1 )
        il1 = iNode;
      else if ( n == theBetweenNode2 )
        il2 = iNode;
      else if ( i3 < 0 )
        i3 = iNode;
      else
        i4 = iNode;
      nodes[ iNode++ ] = n;
    }
  }
  if ( il1 < 0 || il2 < 0 || i3 < 0 )
    return ;

  // arrange link nodes to go one after another regarding the face orientation
  bool reverse = ( Abs( il2 - il1 ) == 1 ? il2 < il1 : il1 < il2 );
  list<const SMDS_MeshNode *> aNodesToInsert = theNodesToInsert;
  if ( reverse ) {
    iNode = il1;
    il1 = il2;
    il2 = iNode;
    aNodesToInsert.reverse();
  }
  // check that not link nodes of a quadrangles are in good order
  int nbFaceNodes = theFace->NbNodes();
  if ( nbFaceNodes == 4 && i4 - i3 != 1 ) {
    iNode = i3;
    i3 = i4;
    i4 = iNode;
  }

  if (toCreatePoly || theFace->IsPoly()) {

    iNode = 0;
    vector<const SMDS_MeshNode *> poly_nodes (nbFaceNodes + aNodesToInsert.size());

    // add nodes of face up to first node of link
    bool isFLN = false;

    if(theFace->IsQuadratic()) {
      const SMDS_VtkFace* F =
        dynamic_cast<const SMDS_VtkFace*>(theFace);
      if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace"));
      // use special nodes iterator
      SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator();
      while( anIter->more()  && !isFLN ) {
        const SMDS_MeshNode* n = cast2Node(anIter->next());
        poly_nodes[iNode++] = n;
        if (n == nodes[il1]) {
          isFLN = true;
        }
      }
      // add nodes to insert
      list<const SMDS_MeshNode*>::iterator nIt = aNodesToInsert.begin();
      for (; nIt != aNodesToInsert.end(); nIt++) {
        poly_nodes[iNode++] = *nIt;
      }
      // add nodes of face starting from last node of link
      while ( anIter->more() ) {
        poly_nodes[iNode++] = cast2Node(anIter->next());
      }
    }
    else {
      SMDS_ElemIteratorPtr nodeIt = theFace->nodesIterator();
      while ( nodeIt->more() && !isFLN ) {
        const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
        poly_nodes[iNode++] = n;
        if (n == nodes[il1]) {
          isFLN = true;
        }
      }
      // add nodes to insert
      list<const SMDS_MeshNode*>::iterator nIt = aNodesToInsert.begin();
      for (; nIt != aNodesToInsert.end(); nIt++) {
        poly_nodes[iNode++] = *nIt;
      }
      // add nodes of face starting from last node of link
      while ( nodeIt->more() ) {
        const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
        poly_nodes[iNode++] = n;
      }
    }

    // edit or replace the face
    SMESHDS_Mesh *aMesh = GetMeshDS();

    if (theFace->IsPoly()) {
      aMesh->ChangePolygonNodes(theFace, poly_nodes);
    }
    else {
      int aShapeId = FindShape( theFace );

      SMDS_MeshElement* newElem = aMesh->AddPolygonalFace(poly_nodes);
      myLastCreatedElems.Append(newElem);
      if ( aShapeId && newElem )
        aMesh->SetMeshElementOnShape( newElem, aShapeId );

      aMesh->RemoveElement(theFace);
    }
    return;
  }

  SMESHDS_Mesh *aMesh = GetMeshDS();
  if( !theFace->IsQuadratic() ) {

    // put aNodesToInsert between theBetweenNode1 and theBetweenNode2
    int nbLinkNodes = 2 + aNodesToInsert.size();
    //const SMDS_MeshNode* linkNodes[ nbLinkNodes ];
    vector<const SMDS_MeshNode*> linkNodes( nbLinkNodes );
    linkNodes[ 0 ] = nodes[ il1 ];
    linkNodes[ nbLinkNodes - 1 ] = nodes[ il2 ];
    list<const SMDS_MeshNode*>::iterator nIt = aNodesToInsert.begin();
    for ( iNode = 1; nIt != aNodesToInsert.end(); nIt++ ) {
      linkNodes[ iNode++ ] = *nIt;
    }
    // decide how to split a quadrangle: compare possible variants
    // and choose which of splits to be a quadrangle
    int i1, i2, iSplit, nbSplits = nbLinkNodes - 1, iBestQuad;
    if ( nbFaceNodes == 3 ) {
      iBestQuad = nbSplits;
      i4 = i3;
    }
    else if ( nbFaceNodes == 4 ) {
      SMESH::Controls::NumericalFunctorPtr aCrit( new SMESH::Controls::AspectRatio);
      double aBestRate = DBL_MAX;
      for ( int iQuad = 0; iQuad < nbSplits; iQuad++ ) {
        i1 = 0; i2 = 1;
        double aBadRate = 0;
        // evaluate elements quality
        for ( iSplit = 0; iSplit < nbSplits; iSplit++ ) {
          if ( iSplit == iQuad ) {
            SMDS_FaceOfNodes quad (linkNodes[ i1++ ],
                                   linkNodes[ i2++ ],
                                   nodes[ i3 ],
                                   nodes[ i4 ]);
            aBadRate += getBadRate( &quad, aCrit );
          }
          else {
            SMDS_FaceOfNodes tria (linkNodes[ i1++ ],
                                   linkNodes[ i2++ ],
                                   nodes[ iSplit < iQuad ? i4 : i3 ]);
            aBadRate += getBadRate( &tria, aCrit );
          }
        }
        // choice
        if ( aBadRate < aBestRate ) {
          iBestQuad = iQuad;
          aBestRate = aBadRate;
        }
      }
    }

    // create new elements
    int aShapeId = FindShape( theFace );

    i1 = 0; i2 = 1;
    for ( iSplit = 0; iSplit < nbSplits - 1; iSplit++ ) {
      SMDS_MeshElement* newElem = 0;
      if ( iSplit == iBestQuad )
        newElem = aMesh->AddFace (linkNodes[ i1++ ],
                                  linkNodes[ i2++ ],
                                  nodes[ i3 ],
                                  nodes[ i4 ]);
      else
        newElem = aMesh->AddFace (linkNodes[ i1++ ],
                                  linkNodes[ i2++ ],
                                  nodes[ iSplit < iBestQuad ? i4 : i3 ]);
      myLastCreatedElems.Append(newElem);
      if ( aShapeId && newElem )
        aMesh->SetMeshElementOnShape( newElem, aShapeId );
    }

    // change nodes of theFace
    const SMDS_MeshNode* newNodes[ 4 ];
    newNodes[ 0 ] = linkNodes[ i1 ];
    newNodes[ 1 ] = linkNodes[ i2 ];
    newNodes[ 2 ] = nodes[ iSplit >= iBestQuad ? i3 : i4 ];
    newNodes[ 3 ] = nodes[ i4 ];
    //aMesh->ChangeElementNodes( theFace, newNodes, iSplit == iBestQuad ? 4 : 3 );
    const SMDS_MeshElement* newElem = 0;
    if (iSplit == iBestQuad)
      newElem = aMesh->AddFace( newNodes[0], newNodes[1], newNodes[2], newNodes[3] );
    else
      newElem = aMesh->AddFace( newNodes[0], newNodes[1], newNodes[2] );
    myLastCreatedElems.Append(newElem);
    if ( aShapeId && newElem )
      aMesh->SetMeshElementOnShape( newElem, aShapeId );
} // end if(!theFace->IsQuadratic())
  else { // theFace is quadratic
    // we have to split theFace on simple triangles and one simple quadrangle
    int tmp = il1/2;
    int nbshift = tmp*2;
    // shift nodes in nodes[] by nbshift
    int i,j;
    for(i=0; i<nbshift; i++) {
      const SMDS_MeshNode* n = nodes[0];
      for(j=0; j<nbFaceNodes-1; j++) {
        nodes[j] = nodes[j+1];
      }
      nodes[nbFaceNodes-1] = n;
    }
    il1 = il1 - nbshift;
    // now have to insert nodes between n0 and n1 or n1 and n2 (see below)
    //   n0      n1     n2    n0      n1     n2
    //     +-----+-----+        +-----+-----+
    //      \         /         |           |
    //       \       /          |           |
    //      n5+     +n3       n7+           +n3
    //         \   /            |           |
    //          \ /             |           |
    //           +              +-----+-----+
    //           n4           n6      n5     n4

    // create new elements
    int aShapeId = FindShape( theFace );

    int n1,n2,n3;
    if(nbFaceNodes==6) { // quadratic triangle
      SMDS_MeshElement* newElem =
        aMesh->AddFace(nodes[3],nodes[4],nodes[5]);
      myLastCreatedElems.Append(newElem);
      if ( aShapeId && newElem )
        aMesh->SetMeshElementOnShape( newElem, aShapeId );
      if(theFace->IsMediumNode(nodes[il1])) {
        // create quadrangle
        newElem = aMesh->AddFace(nodes[0],nodes[1],nodes[3],nodes[5]);
        myLastCreatedElems.Append(newElem);
        if ( aShapeId && newElem )
          aMesh->SetMeshElementOnShape( newElem, aShapeId );
        n1 = 1;
        n2 = 2;
        n3 = 3;
      }
      else {
        // create quadrangle
        newElem = aMesh->AddFace(nodes[1],nodes[2],nodes[3],nodes[5]);
        myLastCreatedElems.Append(newElem);
        if ( aShapeId && newElem )
          aMesh->SetMeshElementOnShape( newElem, aShapeId );
        n1 = 0;
        n2 = 1;
        n3 = 5;
      }
    }
    else { // nbFaceNodes==8 - quadratic quadrangle
      SMDS_MeshElement* newElem =
        aMesh->AddFace(nodes[3],nodes[4],nodes[5]);
      myLastCreatedElems.Append(newElem);
      if ( aShapeId && newElem )
        aMesh->SetMeshElementOnShape( newElem, aShapeId );
      newElem = aMesh->AddFace(nodes[5],nodes[6],nodes[7]);
      myLastCreatedElems.Append(newElem);
      if ( aShapeId && newElem )
        aMesh->SetMeshElementOnShape( newElem, aShapeId );
      newElem = aMesh->AddFace(nodes[5],nodes[7],nodes[3]);
      myLastCreatedElems.Append(newElem);
      if ( aShapeId && newElem )
        aMesh->SetMeshElementOnShape( newElem, aShapeId );
      if(theFace->IsMediumNode(nodes[il1])) {
        // create quadrangle
        newElem = aMesh->AddFace(nodes[0],nodes[1],nodes[3],nodes[7]);
        myLastCreatedElems.Append(newElem);
        if ( aShapeId && newElem )
          aMesh->SetMeshElementOnShape( newElem, aShapeId );
        n1 = 1;
        n2 = 2;
        n3 = 3;
      }
      else {
        // create quadrangle
        newElem = aMesh->AddFace(nodes[1],nodes[2],nodes[3],nodes[7]);
        myLastCreatedElems.Append(newElem);
        if ( aShapeId && newElem )
          aMesh->SetMeshElementOnShape( newElem, aShapeId );
        n1 = 0;
        n2 = 1;
        n3 = 7;
      }
    }
    // create needed triangles using n1,n2,n3 and inserted nodes
    int nbn = 2 + aNodesToInsert.size();
    //const SMDS_MeshNode* aNodes[nbn];
    vector<const SMDS_MeshNode*> aNodes(nbn);
    aNodes[0] = nodes[n1];
    aNodes[nbn-1] = nodes[n2];
    list<const SMDS_MeshNode*>::iterator nIt = aNodesToInsert.begin();
    for ( iNode = 1; nIt != aNodesToInsert.end(); nIt++ ) {
      aNodes[iNode++] = *nIt;
    }
    for(i=1; i<nbn; i++) {
      SMDS_MeshElement* newElem =
        aMesh->AddFace(aNodes[i-1],aNodes[i],nodes[n3]);
      myLastCreatedElems.Append(newElem);
      if ( aShapeId && newElem )
        aMesh->SetMeshElementOnShape( newElem, aShapeId );
    }
  }
  // remove old face
  aMesh->RemoveElement(theFace);
}
bool SMESH_MeshEditor::InverseDiag ( const SMDS_MeshElement theTria1,
const SMDS_MeshElement theTria2 
)

Definition at line 520 of file SMESH_MeshEditor.cxx.

References SMDS_MeshElement.GetEntityType(), GetNodesFromTwoTria(), SMESH_test.i1, SMESH_test.i2, MESSAGE, SMDS_MeshElement.nodesIterator(), SMDSEntity_Quad_Triangle, and SMDSEntity_Triangle.

{
  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;
}
bool SMESH_MeshEditor::InverseDiag ( const SMDS_MeshNode theNode1,
const SMDS_MeshNode theNode2 
)

Definition at line 693 of file SMESH_MeshEditor.cxx.

References findTriangles(), SMDS_MeshElement.GetEntityType(), SMESH_test.i1, SMESH_test.i2, MESSAGE, SMDS_MeshElement.nodesIterator(), and SMDSEntity_Triangle.

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

  MESSAGE( "::InverseDiag()" );

  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;
  if ((tr1->GetEntityType() == SMDSEntity_Triangle) &&
      (tr2->GetEntityType() == SMDSEntity_Triangle)) {

    //  1 +--+ A  tr1: ( 1 A B ) A->2 ( 1 2 B ) 1 +--+ A
    //    | /|    tr2: ( B A 2 ) B->1 ( 1 A 2 )   |\ |
    //    |/ |                                    | \|
    //  B +--+ 2                                B +--+ 2

    // put nodes in array
    // and find indices of 1,2 and of A in tr1 and of B in tr2
    int i, iA1 = 0, i1 = 0;
    const SMDS_MeshNode* aNodes1 [3];
    SMDS_ElemIteratorPtr it;
    for (i = 0, it = tr1->nodesIterator(); it->more(); i++ ) {
      aNodes1[ i ] = static_cast<const SMDS_MeshNode*>( it->next() );
      if ( aNodes1[ i ] == theNode1 )
        iA1 = i; // node A in tr1
      else if ( aNodes1[ i ] != theNode2 )
        i1 = i;  // node 1
    }
    int iB2 = 0, i2 = 0;
    const SMDS_MeshNode* aNodes2 [3];
    for (i = 0, it = tr2->nodesIterator(); it->more(); i++ ) {
      aNodes2[ i ] = static_cast<const SMDS_MeshNode*>( it->next() );
      if ( aNodes2[ i ] == theNode2 )
        iB2 = i; // node B in tr2
      else if ( aNodes2[ i ] != theNode1 )
        i2 = i;  // node 2
    }

    // nodes 1 and 2 should not be the same
    if ( aNodes1[ i1 ] == aNodes2[ i2 ] )
      return false;

    // tr1: A->2
    aNodes1[ iA1 ] = aNodes2[ i2 ];
    // tr2: B->1
    aNodes2[ iB2 ] = aNodes1[ i1 ];

    GetMeshDS()->ChangeElementNodes( tr1, aNodes1, 3 );
    GetMeshDS()->ChangeElementNodes( tr2, aNodes2, 3 );

    return true;
  }

  // check case of quadratic faces
  return InverseDiag(tr1,tr2);
}
static bool SMESH_MeshEditor.IsMedium ( const SMDS_MeshNode node,
const SMDSAbs_ElementType  typeToCheck = SMDSAbs_All 
) [static]

Returns true if given node is medium.

Parameters:
n- node to check
typeToCheck- type of elements containing the node to ask about node status
Returns:
bool - check result

Referenced by StdMeshers_FaceSide.GetUVPtStruct(), and SMESH_Pattern.Load().

bool SMESH_MeshEditor::isOut ( const SMDS_MeshElement element,
const gp_Pnt &  point,
double  tol 
) [static]

Return true if the point is IN or ON of the element.

Definition at line 7061 of file SMESH_MeshEditor.cxx.

References cast2Node, SMESH_test.edge, ex06_hole1boolean.edge1, ex06_hole1boolean.edge2, SMDS_MeshElement.GetType(), SMDS_MeshElement.interlacedNodesElemIterator(), SMDS_VolumeTool.IsOut(), SMDS_MeshElement.IsQuadratic(), SMDS_MeshElement.NbNodes(), SMDS_MeshElement.nodesIterator(), PAL_MESH_041_mesh.p1, PAL_MESH_041_mesh.p2, SMDSAbs_Edge, SMDSAbs_Face, SMDSAbs_Volume, SMESH_AdvancedEditor.tol, and SMESH_AdvancedEditor.xyz.

Referenced by SMESH_ElementSearcherImpl.FindElementsByPoint(), and SMESH_ElementSearcherImpl.GetPointState().

{
  if ( element->GetType() == SMDSAbs_Volume)
  {
    return SMDS_VolumeTool( element ).IsOut( point.X(), point.Y(), point.Z(), tol );
  }

  // get ordered nodes

  vector< gp_XYZ > xyz;
  vector<const SMDS_MeshNode*> nodeList;

  SMDS_ElemIteratorPtr nodeIt = element->nodesIterator();
  if ( element->IsQuadratic() ) {
    if (const SMDS_VtkFace* f=dynamic_cast<const SMDS_VtkFace*>(element))
      nodeIt = f->interlacedNodesElemIterator();
    else if (const SMDS_VtkEdge*  e =dynamic_cast<const SMDS_VtkEdge*>(element))
      nodeIt = e->interlacedNodesElemIterator();
  }
  while ( nodeIt->more() )
    {
      const SMDS_MeshNode* node = cast2Node( nodeIt->next() );
      xyz.push_back( SMESH_TNodeXYZ(node) );
      nodeList.push_back(node);
    }

  int i, nbNodes = element->NbNodes();

  if ( element->GetType() == SMDSAbs_Face ) // --------------------------------------------------
  {
    // compute face normal
    gp_Vec faceNorm(0,0,0);
    xyz.push_back( xyz.front() );
    nodeList.push_back( nodeList.front() );
    for ( i = 0; i < nbNodes; ++i )
    {
      gp_Vec edge1( xyz[i+1], xyz[i]);
      gp_Vec edge2( xyz[i+1], xyz[(i+2)%nbNodes] );
      faceNorm += edge1 ^ edge2;
    }
    double normSize = faceNorm.Magnitude();
    if ( normSize <= tol )
    {
      // degenerated face: point is out if it is out of all face edges
      for ( i = 0; i < nbNodes; ++i )
      {
        SMDS_LinearEdge edge( nodeList[i], nodeList[i+1] );
        if ( !isOut( &edge, point, tol ))
          return false;
      }
      return true;
    }
    faceNorm /= normSize;

    // check if the point lays on face plane
    gp_Vec n2p( xyz[0], point );
    if ( fabs( n2p * faceNorm ) > tol )
      return true; // not on face plane

    // check if point is out of face boundary:
    // define it by closest transition of a ray point->infinity through face boundary
    // on the face plane.
    // First, find normal of a plane perpendicular to face plane, to be used as a cutting tool
    // to find intersections of the ray with the boundary.
    gp_Vec ray = n2p;
    gp_Vec plnNorm = ray ^ faceNorm;
    normSize = plnNorm.Magnitude();
    if ( normSize <= tol ) return false; // point coincides with the first node
    plnNorm /= normSize;
    // for each node of the face, compute its signed distance to the plane
    vector<double> dist( nbNodes + 1);
    for ( i = 0; i < nbNodes; ++i )
    {
      gp_Vec n2p( xyz[i], point );
      dist[i] = n2p * plnNorm;
    }
    dist.back() = dist.front();
    // find the closest intersection
    int    iClosest = -1;
    double rClosest, distClosest = 1e100;;
    gp_Pnt pClosest;
    for ( i = 0; i < nbNodes; ++i )
    {
      double r;
      if ( fabs( dist[i]) < tol )
        r = 0.;
      else if ( fabs( dist[i+1]) < tol )
        r = 1.;
      else if ( dist[i] * dist[i+1] < 0 )
        r = dist[i] / ( dist[i] - dist[i+1] );
      else
        continue; // no intersection
      gp_Pnt pInt = xyz[i] * (1.-r) + xyz[i+1] * r;
      gp_Vec p2int ( point, pInt);
      if ( p2int * ray > -tol ) // right half-space
      {
        double intDist = p2int.SquareMagnitude();
        if ( intDist < distClosest )
        {
          iClosest = i;
          rClosest = r;
          pClosest = pInt;
          distClosest = intDist;
        }
      }
    }
    if ( iClosest < 0 )
      return true; // no intesections - out

    // analyse transition
    gp_Vec edge( xyz[iClosest], xyz[iClosest+1] );
    gp_Vec edgeNorm = -( edge ^ faceNorm ); // normal to intersected edge pointing out of face
    gp_Vec p2int ( point, pClosest );
    bool out = (edgeNorm * p2int) < -tol;
    if ( rClosest > 0. && rClosest < 1. ) // not node intersection
      return out;

    // ray pass through a face node; analyze transition through an adjacent edge
    gp_Pnt p1 = xyz[ (rClosest == 0.) ? ((iClosest+nbNodes-1) % nbNodes) : (iClosest+1) ];
    gp_Pnt p2 = xyz[ (rClosest == 0.) ? iClosest : ((iClosest+2) % nbNodes) ];
    gp_Vec edgeAdjacent( p1, p2 );
    gp_Vec edgeNorm2 = -( edgeAdjacent ^ faceNorm );
    bool out2 = (edgeNorm2 * p2int) < -tol;

    bool covexCorner = ( edgeNorm * edgeAdjacent * (rClosest==1. ? 1. : -1.)) < 0;
    return covexCorner ? (out || out2) : (out && out2);
  }
  if ( element->GetType() == SMDSAbs_Edge ) // --------------------------------------------------
  {
    // point is out of edge if it is NOT ON any straight part of edge
    // (we consider quadratic edge as being composed of two straight parts)
    for ( i = 1; i < nbNodes; ++i )
    {
      gp_Vec edge( xyz[i-1], xyz[i]);
      gp_Vec n1p ( xyz[i-1], point);
      double dist = ( edge ^ n1p ).Magnitude() / edge.Magnitude();
      if ( dist > tol )
        continue;
      gp_Vec n2p( xyz[i], point );
      if ( fabs( edge.Magnitude() - n1p.Magnitude() - n2p.Magnitude()) > tol )
        continue;
      return false; // point is ON this part
    }
    return true;
  }
  // Node or 0D element -------------------------------------------------------------------------
  {
    gp_Vec n2p ( xyz[0], point );
    return n2p.Magnitude() <= tol;
  }
  return true;
}
void SMESH_MeshEditor::LinearAngleVariation ( const int  NbSteps,
list< double > &  theAngles 
) [private]

Definition at line 5253 of file SMESH_MeshEditor.cxx.

References SMESH_demo_hexa2_upd.angle, and SMESH_AdvancedEditor.res.

{
  int nbAngles = Angles.size();
  if( nbSteps > nbAngles ) {
    vector<double> theAngles(nbAngles);
    list<double>::iterator it = Angles.begin();
    int i = -1;
    for(; it!=Angles.end(); it++) {
      i++;
      theAngles[i] = (*it);
    }
    list<double> res;
    double rAn2St = double( nbAngles ) / double( nbSteps );
    double angPrev = 0, angle;
    for ( int iSt = 0; iSt < nbSteps; ++iSt ) {
      double angCur = rAn2St * ( iSt+1 );
      double angCurFloor  = floor( angCur );
      double angPrevFloor = floor( angPrev );
      if ( angPrevFloor == angCurFloor )
        angle = rAn2St * theAngles[ int( angCurFloor ) ];
      else {
        int iP = int( angPrevFloor );
        double angPrevCeil = ceil(angPrev);
        angle = ( angPrevCeil - angPrev ) * theAngles[ iP ];

        int iC = int( angCurFloor );
        if ( iC < nbAngles )
          angle += ( angCur - angCurFloor ) * theAngles[ iC ];

        iP = int( angPrevCeil );
        while ( iC-- > iP )
          angle += theAngles[ iC ];
      }
      res.push_back(angle);
      angPrev = angCur;
    }
    Angles.clear();
    it = res.begin();
    for(; it!=res.end(); it++)
      Angles.push_back( *it );
  }
}
bool SMESH_MeshEditor.Make2DMeshFrom3D ( )

Generated 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
int SMESH_MeshEditor.MakeBoundaryMesh ( const TIDSortedElemSet elements,
Bnd_Dimension  dimension,
SMESH_Group group = 0,
SMESH_Mesh targetMesh = 0,
bool  toCopyElements = false,
bool  toCopyExistingBondary = false,
bool  toAddExistingBondary = false,
bool  aroundElements = false 
)
SMESH_MeshEditor::Extrusion_Error SMESH_MeshEditor::MakeEdgePathPoints ( std::list< double > &  aPrms,
const TopoDS_Edge &  aTrackEdge,
bool  aFirstIsStart,
std::list< SMESH_MeshEditor_PathPoint > &  aLPP 
) [private]

Definition at line 4956 of file SMESH_MeshEditor.cxx.

References Handle(), SMESH_MeshEditor.SMESH_MeshEditor_PathPoint.SetParameter(), SMESH_MeshEditor.SMESH_MeshEditor_PathPoint.SetPnt(), and SMESH_MeshEditor.SMESH_MeshEditor_PathPoint.SetTangent().

{
  Standard_Real aTx1, aTx2, aL2, aTolVec, aTolVec2;
  aTolVec=1.e-7;
  aTolVec2=aTolVec*aTolVec;
  double aT1, aT2;
  TopoDS_Vertex aV1, aV2;
  TopExp::Vertices( aTrackEdge, aV1, aV2 );
  aT1=BRep_Tool::Parameter( aV1, aTrackEdge );
  aT2=BRep_Tool::Parameter( aV2, aTrackEdge );
  // 2. Collect parameters on the track edge
  aPrms.push_front( aT1 );
  aPrms.push_back( aT2 );
  // sort parameters
  aPrms.sort();
  if( FirstIsStart ) {
    if ( aT1 > aT2 ) {
      aPrms.reverse();
    }
  }
  else {
    if ( aT2 > aT1 ) {
      aPrms.reverse();
    }
  }
  // 3. Path Points
  SMESH_MeshEditor_PathPoint aPP;
  Handle(Geom_Curve) aC3D = BRep_Tool::Curve( aTrackEdge, aTx1, aTx2 );
  std::list<double>::iterator aItD = aPrms.begin();
  for(; aItD != aPrms.end(); ++aItD) {
    double aT = *aItD;
    gp_Pnt aP3D;
    gp_Vec aVec;
    aC3D->D1( aT, aP3D, aVec );
    aL2 = aVec.SquareMagnitude();
    if ( aL2 < aTolVec2 )
      return EXTR_CANT_GET_TANGENT;
    gp_Dir aTgt( aVec );
    aPP.SetPnt( aP3D );
    aPP.SetTangent( aTgt );
    aPP.SetParameter( aT );
    LPP.push_back(aPP);
  }
  return EXTR_OK;
}
SMESH_MeshEditor::Extrusion_Error SMESH_MeshEditor::MakeExtrElements ( TIDSortedElemSet theElements,
std::list< SMESH_MeshEditor_PathPoint > &  theFullList,
const bool  theHasAngles,
std::list< double > &  theAngles,
const bool  theLinearVariation,
const bool  theHasRefPoint,
const gp_Pnt &  theRefPoint,
const bool  theMakeGroups 
) [private]

Definition at line 5011 of file SMESH_MeshEditor.cxx.

References SMESHDS_Mesh.AddNode(), SMESH_MeshEditor.SMESH_MeshEditor_PathPoint.Angle(), SMDS_MeshElement.GetType(), SMDS_MeshElement.IsMediumNode(), SMDS_MeshElement.IsQuadratic(), MESSAGE, SMDS_MeshElement.NbNodes(), ex29_refine.node(), SMDS_MeshElement.nodesIterator(), SMESH_MeshEditor.SMESH_MeshEditor_PathPoint.Pnt(), SMESH_MeshEditor.SMESH_MeshEditor_PathPoint.SetAngle(), SMDSAbs_Edge, SMDSAbs_Face, SMESH_MeshEditor.SMESH_MeshEditor_PathPoint.Tangent(), SMDS_MeshNode.X(), SMDS_MeshNode.Y(), and SMDS_MeshNode.Z().

{
  MESSAGE("MakeExtrElements");
  //cout<<"MakeExtrElements  fullList.size() = "<<fullList.size()<<endl;
  int aNbTP = fullList.size();
  vector<SMESH_MeshEditor_PathPoint> aPPs(aNbTP);
  // Angles
  if( theHasAngles && theAngles.size()>0 && theLinearVariation ) {
    LinearAngleVariation(aNbTP-1, theAngles);
  }
  vector<double> aAngles( aNbTP );
  int j = 0;
  for(; j<aNbTP; ++j) {
    aAngles[j] = 0.;
  }
  if ( theHasAngles ) {
    double anAngle;;
    std::list<double>::iterator aItD = theAngles.begin();
    for ( j=1; (aItD != theAngles.end()) && (j<aNbTP); ++aItD, ++j ) {
      anAngle = *aItD;
      aAngles[j] = anAngle;
    }
  }
  // fill vector of path points with angles
  //aPPs.resize(fullList.size());
  j = -1;
  list<SMESH_MeshEditor_PathPoint>::iterator itPP = fullList.begin();
  for(; itPP!=fullList.end(); itPP++) {
    j++;
    SMESH_MeshEditor_PathPoint PP = *itPP;
    PP.SetAngle(aAngles[j]);
    aPPs[j] = PP;
  }

  TNodeOfNodeListMap mapNewNodes;
  TElemOfVecOfNnlmiMap mapElemNewNodes;
  TElemOfElemListMap newElemsMap;
  TIDSortedElemSet::iterator itElem;
  double aX, aY, aZ;
  int aNb;
  SMDSAbs_ElementType aTypeE;
  // source elements for each generated one
  SMESH_SequenceOfElemPtr srcElems, srcNodes;

  // 3. Center of rotation aV0
  gp_Pnt aV0 = theRefPoint;
  gp_XYZ aGC;
  if ( !theHasRefPoint ) {
    aNb = 0;
    aGC.SetCoord( 0.,0.,0. );

    itElem = theElements.begin();
    for ( ; itElem != theElements.end(); itElem++ ) {
      const SMDS_MeshElement* elem = *itElem;

      SMDS_ElemIteratorPtr itN = elem->nodesIterator();
      while ( itN->more() ) {
        const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( itN->next() );
        aX = node->X();
        aY = node->Y();
        aZ = node->Z();

        if ( mapNewNodes.find( node ) == mapNewNodes.end() ) {
          list<const SMDS_MeshNode*> aLNx;
          mapNewNodes[node] = aLNx;
          //
          gp_XYZ aXYZ( aX, aY, aZ );
          aGC += aXYZ;
          ++aNb;
        }
      }
    }
    aGC /= aNb;
    aV0.SetXYZ( aGC );
  } // if (!theHasRefPoint) {
  mapNewNodes.clear();

  // 4. Processing the elements
  SMESHDS_Mesh* aMesh = GetMeshDS();

  for ( itElem = theElements.begin(); itElem != theElements.end(); itElem++ ) {
    // check element type
    const SMDS_MeshElement* elem = *itElem;
    aTypeE = elem->GetType();
    if ( !elem || ( aTypeE != SMDSAbs_Face && aTypeE != SMDSAbs_Edge ) )
      continue;

    vector<TNodeOfNodeListMapItr> & newNodesItVec = mapElemNewNodes[ elem ];
    newNodesItVec.reserve( elem->NbNodes() );

    // loop on elem nodes
    int nodeIndex = -1;
    SMDS_ElemIteratorPtr itN = elem->nodesIterator();
    while ( itN->more() )
    {
      ++nodeIndex;
      // check if a node has been already processed
      const SMDS_MeshNode* node =
        static_cast<const SMDS_MeshNode*>( itN->next() );
      TNodeOfNodeListMap::iterator nIt = mapNewNodes.find( node );
      if ( nIt == mapNewNodes.end() ) {
        nIt = mapNewNodes.insert( make_pair( node, list<const SMDS_MeshNode*>() )).first;
        list<const SMDS_MeshNode*>& listNewNodes = nIt->second;

        // make new nodes
        aX = node->X();  aY = node->Y(); aZ = node->Z();

        Standard_Real aAngle1x, aAngleT1T0, aTolAng;
        gp_Pnt aP0x, aP1x, aPN0, aPN1, aV0x, aV1x;
        gp_Ax1 anAx1, anAxT1T0;
        gp_Dir aDT1x, aDT0x, aDT1T0;

        aTolAng=1.e-4;

        aV0x = aV0;
        aPN0.SetCoord(aX, aY, aZ);

        const SMESH_MeshEditor_PathPoint& aPP0 = aPPs[0];
        aP0x = aPP0.Pnt();
        aDT0x= aPP0.Tangent();
        //cout<<"j = 0   PP: Pnt("<<aP0x.X()<<","<<aP0x.Y()<<","<<aP0x.Z()<<")"<<endl;

        for ( j = 1; j < aNbTP; ++j ) {
          const SMESH_MeshEditor_PathPoint& aPP1 = aPPs[j];
          aP1x = aPP1.Pnt();
          aDT1x = aPP1.Tangent();
          aAngle1x = aPP1.Angle();

          gp_Trsf aTrsf, aTrsfRot, aTrsfRotT1T0;
          // Translation
          gp_Vec aV01x( aP0x, aP1x );
          aTrsf.SetTranslation( aV01x );

          // traslated point
          aV1x = aV0x.Transformed( aTrsf );
          aPN1 = aPN0.Transformed( aTrsf );

          // rotation 1 [ T1,T0 ]
          aAngleT1T0=-aDT1x.Angle( aDT0x );
          if (fabs(aAngleT1T0) > aTolAng) {
            aDT1T0=aDT1x^aDT0x;
            anAxT1T0.SetLocation( aV1x );
            anAxT1T0.SetDirection( aDT1T0 );
            aTrsfRotT1T0.SetRotation( anAxT1T0, aAngleT1T0 );

            aPN1 = aPN1.Transformed( aTrsfRotT1T0 );
          }

          // rotation 2
          if ( theHasAngles ) {
            anAx1.SetLocation( aV1x );
            anAx1.SetDirection( aDT1x );
            aTrsfRot.SetRotation( anAx1, aAngle1x );

            aPN1 = aPN1.Transformed( aTrsfRot );
          }

          // make new node
          //MESSAGE("elem->IsQuadratic " << elem->IsQuadratic() << " " << elem->IsMediumNode(node));
          if( elem->IsQuadratic() && !elem->IsMediumNode(node) ) {
            // create additional node
            double x = ( aPN1.X() + aPN0.X() )/2.;
            double y = ( aPN1.Y() + aPN0.Y() )/2.;
            double z = ( aPN1.Z() + aPN0.Z() )/2.;
            const SMDS_MeshNode* newNode = aMesh->AddNode(x,y,z);
            myLastCreatedNodes.Append(newNode);
            srcNodes.Append( node );
            listNewNodes.push_back( newNode );
          }
          aX = aPN1.X();
          aY = aPN1.Y();
          aZ = aPN1.Z();
          const SMDS_MeshNode* newNode = aMesh->AddNode( aX, aY, aZ );
          myLastCreatedNodes.Append(newNode);
          srcNodes.Append( node );
          listNewNodes.push_back( newNode );

          aPN0 = aPN1;
          aP0x = aP1x;
          aV0x = aV1x;
          aDT0x = aDT1x;
        }
      }

      else {
        // if current elem is quadratic and current node is not medium
        // we have to check - may be it is needed to insert additional nodes
        if( elem->IsQuadratic() && !elem->IsMediumNode(node) ) {
          list< const SMDS_MeshNode* > & listNewNodes = nIt->second;
          if(listNewNodes.size()==aNbTP-1) {
            vector<const SMDS_MeshNode*> aNodes(2*(aNbTP-1));
            gp_XYZ P(node->X(), node->Y(), node->Z());
            list< const SMDS_MeshNode* >::iterator it = listNewNodes.begin();
            int i;
            for(i=0; i<aNbTP-1; i++) {
              const SMDS_MeshNode* N = *it;
              double x = ( N->X() + P.X() )/2.;
              double y = ( N->Y() + P.Y() )/2.;
              double z = ( N->Z() + P.Z() )/2.;
              const SMDS_MeshNode* newN = aMesh->AddNode(x,y,z);
              srcNodes.Append( node );
              myLastCreatedNodes.Append(newN);
              aNodes[2*i] = newN;
              aNodes[2*i+1] = N;
              P = gp_XYZ(N->X(),N->Y(),N->Z());
            }
            listNewNodes.clear();
            for(i=0; i<2*(aNbTP-1); i++) {
              listNewNodes.push_back(aNodes[i]);
            }
          }
        }
      }

      newNodesItVec.push_back( nIt );
    }
    // make new elements
    //sweepElement( aMesh, elem, newNodesItVec, newElemsMap[elem],
    //              newNodesItVec[0]->second.size(), myLastCreatedElems );
    sweepElement( elem, newNodesItVec, newElemsMap[elem], aNbTP-1, srcElems );
  }

  makeWalls( mapNewNodes, newElemsMap, mapElemNewNodes, theElements, aNbTP-1, srcElems );

  if ( theMakeGroups )
    generateGroups( srcNodes, srcElems, "extruded");

  return EXTR_OK;
}
void SMESH_MeshEditor::makeWalls ( TNodeOfNodeListMap mapNewNodes,
TElemOfElemListMap newElemsMap,
TElemOfVecOfNnlmiMap elemNewNodesMap,
TIDSortedElemSet elemSet,
const int  nbSteps,
SMESH_SequenceOfElemPtr &  srcElements 
) [private]

Create 1D and 2D elements around swept elements.

Parameters:
mapNewNodes- source nodes and ones generated from them
newElemsMap- source elements and ones generated from them
elemNewNodesMap- nodes generated from each node of each element
elemSet- all swept elements
nbSteps- number of sweeping steps
srcElements- to append elem for each generated element

Definition at line 3821 of file SMESH_MeshEditor.cxx.

References FindFaceInSet(), SMDS_VolumeTool.GetFaceNodes(), SMDS_MeshNode.GetInverseElementIterator(), SMDS_MeshElement.GetNodeIndex(), SMDS_MeshElement.GetNodeWrap(), SMDS_MeshElement.GetType(), SMDS_VolumeTool.ID(), SMESH_test.ind, SMDS_VolumeTool.IsForward(), SMDS_VolumeTool.IsFreeFace(), SMDS_MeshElement.IsMediumNode(), SMDS_MeshElement.IsQuadratic(), MESSAGE, SMDS_VolumeTool.NbFaceNodes(), SMDS_VolumeTool.NbFaces(), SMESH_AdvancedEditor.nbn, reverse(), SMDS_VolumeTool.Set(), SMDS_VolumeTool.SetExternalNormal(), SMDSAbs_Edge, SMDSAbs_Face, and SMDSAbs_Volume.

{
  MESSAGE("makeWalls");
  ASSERT( newElemsMap.size() == elemNewNodesMap.size() );
  SMESHDS_Mesh* aMesh = GetMeshDS();

  // Find nodes belonging to only one initial element - sweep them to get edges.

  TNodeOfNodeListMapItr nList = mapNewNodes.begin();
  for ( ; nList != mapNewNodes.end(); nList++ ) {
    const SMDS_MeshNode* node =
      static_cast<const SMDS_MeshNode*>( nList->first );
    SMDS_ElemIteratorPtr eIt = node->GetInverseElementIterator();
    int nbInitElems = 0;
    const SMDS_MeshElement* el = 0;
    SMDSAbs_ElementType highType = SMDSAbs_Edge; // count most complex elements only
    while ( eIt->more() && nbInitElems < 2 ) {
      el = eIt->next();
      SMDSAbs_ElementType type = el->GetType();
      if ( type == SMDSAbs_Volume || type < highType ) continue;
      if ( type > highType ) {
        nbInitElems = 0;
        highType = type;
      }
      if ( elemSet.find(el) != elemSet.end() )
        nbInitElems++;
    }
    if ( nbInitElems < 2 ) {
      bool NotCreateEdge = el && el->IsQuadratic() && el->IsMediumNode(node);
      if(!NotCreateEdge) {
        vector<TNodeOfNodeListMapItr> newNodesItVec( 1, nList );
        list<const SMDS_MeshElement*> newEdges;
        sweepElement( node, newNodesItVec, newEdges, nbSteps, srcElements );
      }
    }
  }

  // Make a ceiling for each element ie an equal element of last new nodes.
  // Find free links of faces - make edges and sweep them into faces.

  TElemOfElemListMap::iterator   itElem      = newElemsMap.begin();
  TElemOfVecOfNnlmiMap::iterator itElemNodes = elemNewNodesMap.begin();
  for ( ; itElem != newElemsMap.end(); itElem++, itElemNodes++ ) {
    const SMDS_MeshElement* elem = itElem->first;
    vector<TNodeOfNodeListMapItr>& vecNewNodes = itElemNodes->second;

    if(itElem->second.size()==0) continue;

    if ( elem->GetType() == SMDSAbs_Edge ) {
      // create a ceiling edge
      if (!elem->IsQuadratic()) {
        if ( !aMesh->FindEdge( vecNewNodes[ 0 ]->second.back(),
                               vecNewNodes[ 1 ]->second.back())) {
          myLastCreatedElems.Append(aMesh->AddEdge(vecNewNodes[ 0 ]->second.back(),
                                                   vecNewNodes[ 1 ]->second.back()));
          srcElements.Append( myLastCreatedElems.Last() );
        }
      }
      else {
        if ( !aMesh->FindEdge( vecNewNodes[ 0 ]->second.back(),
                               vecNewNodes[ 1 ]->second.back(),
                               vecNewNodes[ 2 ]->second.back())) {
          myLastCreatedElems.Append(aMesh->AddEdge(vecNewNodes[ 0 ]->second.back(),
                                                   vecNewNodes[ 1 ]->second.back(),
                                                   vecNewNodes[ 2 ]->second.back()));
          srcElements.Append( myLastCreatedElems.Last() );
        }
      }
    }
    if ( elem->GetType() != SMDSAbs_Face )
      continue;

    bool hasFreeLinks = false;

    TIDSortedElemSet avoidSet;
    avoidSet.insert( elem );

    set<const SMDS_MeshNode*> aFaceLastNodes;
    int iNode, nbNodes = vecNewNodes.size();
    if(!elem->IsQuadratic()) {
      // loop on the face nodes
      for ( iNode = 0; iNode < nbNodes; iNode++ ) {
        aFaceLastNodes.insert( vecNewNodes[ iNode ]->second.back() );
        // look for free links of the face
        int iNext = ( iNode + 1 == nbNodes ) ? 0 : iNode + 1;
        const SMDS_MeshNode* n1 = vecNewNodes[ iNode ]->first;
        const SMDS_MeshNode* n2 = vecNewNodes[ iNext ]->first;
        // check if a link is free
        if ( ! SMESH_MeshEditor::FindFaceInSet ( n1, n2, elemSet, avoidSet )) {
          hasFreeLinks = true;
          // make an edge and a ceiling for a new edge
          if ( !aMesh->FindEdge( n1, n2 )) {
            myLastCreatedElems.Append(aMesh->AddEdge( n1, n2 )); // free link edge
            srcElements.Append( myLastCreatedElems.Last() );
          }
          n1 = vecNewNodes[ iNode ]->second.back();
          n2 = vecNewNodes[ iNext ]->second.back();
          if ( !aMesh->FindEdge( n1, n2 )) {
            myLastCreatedElems.Append(aMesh->AddEdge( n1, n2 )); // ceiling edge
            srcElements.Append( myLastCreatedElems.Last() );
          }
        }
      }
    }
    else { // elem is quadratic face
      int nbn = nbNodes/2;
      for ( iNode = 0; iNode < nbn; iNode++ ) {
        aFaceLastNodes.insert( vecNewNodes[ iNode ]->second.back() );
        int iNext = ( iNode + 1 == nbn ) ? 0 : iNode + 1;
        const SMDS_MeshNode* n1 = vecNewNodes[ iNode ]->first;
        const SMDS_MeshNode* n2 = vecNewNodes[ iNext ]->first;
        // check if a link is free
        if ( ! SMESH_MeshEditor::FindFaceInSet ( n1, n2, elemSet, avoidSet )) {
          hasFreeLinks = true;
          // make an edge and a ceiling for a new edge
          // find medium node
          const SMDS_MeshNode* n3 = vecNewNodes[ iNode+nbn ]->first;
          if ( !aMesh->FindEdge( n1, n2, n3 )) {
            myLastCreatedElems.Append(aMesh->AddEdge( n1, n2, n3 )); // free link edge
            srcElements.Append( myLastCreatedElems.Last() );
          }
          n1 = vecNewNodes[ iNode ]->second.back();
          n2 = vecNewNodes[ iNext ]->second.back();
          n3 = vecNewNodes[ iNode+nbn ]->second.back();
          if ( !aMesh->FindEdge( n1, n2, n3 )) {
            myLastCreatedElems.Append(aMesh->AddEdge( n1, n2, n3 )); // ceiling edge
            srcElements.Append( myLastCreatedElems.Last() );
          }
        }
      }
      for ( iNode = nbn; iNode < 2*nbn; iNode++ ) {
        aFaceLastNodes.insert( vecNewNodes[ iNode ]->second.back() );
      }
    }

    // sweep free links into faces

    if ( hasFreeLinks )  {
      list<const SMDS_MeshElement*> & newVolumes = itElem->second;
      int iVol, volNb, nbVolumesByStep = newVolumes.size() / nbSteps;

      set<const SMDS_MeshNode*> initNodeSet, topNodeSet, faceNodeSet;
      for ( iNode = 0; iNode < nbNodes; iNode++ ) {
        initNodeSet.insert( vecNewNodes[ iNode ]->first );
        topNodeSet .insert( vecNewNodes[ iNode ]->second.back() );
      }
      for ( volNb = 0; volNb < nbVolumesByStep; volNb++ ) {
        list<const SMDS_MeshElement*>::iterator v = newVolumes.begin();
        iVol = 0;
        while ( iVol++ < volNb ) v++;
        // find indices of free faces of a volume and their source edges
        list< int > freeInd;
        list< const SMDS_MeshElement* > srcEdges; // source edges of free faces
        SMDS_VolumeTool vTool( *v );
        int iF, nbF = vTool.NbFaces();
        for ( iF = 0; iF < nbF; iF ++ ) {
          if (vTool.IsFreeFace( iF ) &&
              vTool.GetFaceNodes( iF, faceNodeSet ) &&
              initNodeSet != faceNodeSet) // except an initial face
          {
            if ( nbSteps == 1 && faceNodeSet == topNodeSet )
              continue;
            freeInd.push_back( iF );
            // find source edge of a free face iF
            vector<const SMDS_MeshNode*> commonNodes; // shared by the initial and free faces
            commonNodes.resize( initNodeSet.size(), NULL ); // avoid spoiling memory
            std::set_intersection( faceNodeSet.begin(), faceNodeSet.end(),
                                   initNodeSet.begin(), initNodeSet.end(),
                                   commonNodes.begin());
            if ( (*v)->IsQuadratic() )
              srcEdges.push_back(aMesh->FindEdge (commonNodes[0],commonNodes[1],commonNodes[2]));
            else
              srcEdges.push_back(aMesh->FindEdge (commonNodes[0],commonNodes[1]));
#ifdef _DEBUG_
            if ( !srcEdges.back() )
            {
              cout << "SMESH_MeshEditor::makeWalls(), no source edge found for a free face #"
                   << iF << " of volume #" << vTool.ID() << endl;
            }
#endif
          }
        }
        if ( freeInd.empty() )
          continue;

        // create faces for all steps;
        // if such a face has been already created by sweep of edge,
        // assure that its orientation is OK
        for ( int iStep = 0; iStep < nbSteps; iStep++ )  {
          vTool.Set( *v );
          vTool.SetExternalNormal();
          const int nextShift = vTool.IsForward() ? +1 : -1;
          list< int >::iterator ind = freeInd.begin();
          list< const SMDS_MeshElement* >::iterator srcEdge = srcEdges.begin();
          for ( ; ind != freeInd.end(); ++ind, ++srcEdge ) // loop on free faces
          {
            const SMDS_MeshNode** nodes = vTool.GetFaceNodes( *ind );
            int nbn = vTool.NbFaceNodes( *ind );
            if ( ! (*v)->IsPoly() )
              switch ( nbn ) {
              case 3: { 
                const SMDS_MeshFace * f = aMesh->FindFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ]);
                if ( !f ||
                     nodes[ 1 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ]) + nextShift ))
                {
                  const SMDS_MeshNode* newOrder[3] = { nodes[ 1 - nextShift ],
                                                       nodes[ 1 ],
                                                       nodes[ 1 + nextShift ] };
                  if ( f )
                    aMesh->ChangeElementNodes( f, &newOrder[0], nbn );
                  else
                    myLastCreatedElems.Append(aMesh->AddFace( newOrder[ 0 ], newOrder[ 1 ],
                                                              newOrder[ 2 ] ));
                }
                break;
              }
              case 4: { 
                const SMDS_MeshFace * f =
                  aMesh->FindFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ]);
                if ( !f ||
                     nodes[ 1 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ]) + nextShift ))
                {
                  const SMDS_MeshNode* newOrder[4] = { nodes[ 0 ], nodes[ 2-nextShift ],
                                                       nodes[ 2 ], nodes[ 2+nextShift ] };
                  if ( f )
                    aMesh->ChangeElementNodes( f, &newOrder[0], nbn );
                  else
                    myLastCreatedElems.Append(aMesh->AddFace( newOrder[ 0 ], newOrder[ 1 ],
                                                              newOrder[ 2 ], newOrder[ 3 ]));
                }
                break;
              }
              case 6: { 
                const SMDS_MeshFace * f = aMesh->FindFace( nodes[0], nodes[2], nodes[4],
                                                           nodes[1], nodes[3], nodes[5] );
                if ( !f ||
                     nodes[2] != f->GetNodeWrap( f->GetNodeIndex( nodes[0] ) + 2*nextShift ))
                {
                  const SMDS_MeshNode* newOrder[6] = { nodes[2 - 2*nextShift],
                                                       nodes[2],
                                                       nodes[2 + 2*nextShift],
                                                       nodes[3 - 2*nextShift],
                                                       nodes[3],
                                                       nodes[3 + 2*nextShift]};
                  if ( f )
                    aMesh->ChangeElementNodes( f, &newOrder[0], nbn );
                  else
                    myLastCreatedElems.Append(aMesh->AddFace( newOrder[ 0 ],
                                                              newOrder[ 1 ],
                                                              newOrder[ 2 ],
                                                              newOrder[ 3 ],
                                                              newOrder[ 4 ],
                                                              newOrder[ 5 ] ));
                }
                break;
              }
              default:       
                const SMDS_MeshFace * f = aMesh->FindFace( nodes[0], nodes[2], nodes[4], nodes[6],
                                                           nodes[1], nodes[3], nodes[5], nodes[7] );
                if ( !f ||
                     nodes[ 2 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ] ) + 2*nextShift ))
                {
                  const SMDS_MeshNode* newOrder[8] = { nodes[0],
                                                       nodes[4 - 2*nextShift],
                                                       nodes[4],
                                                       nodes[4 + 2*nextShift],
                                                       nodes[1],
                                                       nodes[5 - 2*nextShift],
                                                       nodes[5],
                                                       nodes[5 + 2*nextShift] };
                  if ( f )
                    aMesh->ChangeElementNodes( f, &newOrder[0], nbn );
                  else
                    myLastCreatedElems.Append(aMesh->AddFace(newOrder[ 0 ], newOrder[ 1 ],
                                                             newOrder[ 2 ], newOrder[ 3 ],
                                                             newOrder[ 4 ], newOrder[ 5 ],
                                                             newOrder[ 6 ], newOrder[ 7 ]));
                }
              } // switch ( nbn )

            else { 

              vector<const SMDS_MeshNode*> polygon_nodes ( nodes, &nodes[nbn] );
              const SMDS_MeshFace * f = aMesh->FindFace( polygon_nodes );
              if ( !f ||
                   nodes[ 1 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ] ) + nextShift ))
              {
                if ( !vTool.IsForward() )
                  std::reverse( polygon_nodes.begin(), polygon_nodes.end());
                if ( f )
                  aMesh->ChangeElementNodes( f, &polygon_nodes[0], nbn );
                else
                  AddElement(polygon_nodes, SMDSAbs_Face, polygon_nodes.size()>4);
              }
            }

            while ( srcElements.Length() < myLastCreatedElems.Length() )
              srcElements.Append( *srcEdge );

          }  // loop on free faces

          // go to the next volume
          iVol = 0;
          while ( iVol++ < nbVolumesByStep ) v++;

        } // loop on steps
      } // loop on volumes of one step
    } // sweep free links into faces

    // Make a ceiling face with a normal external to a volume

    SMDS_VolumeTool lastVol( itElem->second.back() );

    int iF = lastVol.GetFaceIndex( aFaceLastNodes );
    if ( iF >= 0 ) {
      lastVol.SetExternalNormal();
      const SMDS_MeshNode** nodes = lastVol.GetFaceNodes( iF );
      int nbn = lastVol.NbFaceNodes( iF );
      switch ( nbn ) {
      case 3:
        if (!hasFreeLinks ||
            !aMesh->FindFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ]))
          myLastCreatedElems.Append(aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] ));
        break;
      case 4:
        if (!hasFreeLinks ||
            !aMesh->FindFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ]))
          myLastCreatedElems.Append(aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ] ));
        break;
      default:
        if(itElem->second.back()->IsQuadratic()) {
          if(nbn==6) {
            if (!hasFreeLinks ||
                !aMesh->FindFace(nodes[0], nodes[2], nodes[4],
                                 nodes[1], nodes[3], nodes[5]) ) {
              myLastCreatedElems.Append(aMesh->AddFace(nodes[0], nodes[2], nodes[4],
                                                       nodes[1], nodes[3], nodes[5]));
            }
          }
          else { // nbn==8
            if (!hasFreeLinks ||
                !aMesh->FindFace(nodes[0], nodes[2], nodes[4], nodes[6],
                                 nodes[1], nodes[3], nodes[5], nodes[7]) )
              myLastCreatedElems.Append(aMesh->AddFace(nodes[0], nodes[2], nodes[4], nodes[6],
                                                       nodes[1], nodes[3], nodes[5], nodes[7]));
          }
        }
        else {
          vector<const SMDS_MeshNode*> polygon_nodes ( nodes, &nodes[nbn] );
          if (!hasFreeLinks || !aMesh->FindFace(polygon_nodes))
            myLastCreatedElems.Append(aMesh->AddPolygonalFace(polygon_nodes));
        }
      } // switch

      while ( srcElements.Length() < myLastCreatedElems.Length() )
        srcElements.Append( myLastCreatedElems.Last() );
    }
  } // loop on swept elements
}
void SMESH_MeshEditor::MergeElements ( TListOfListOfElementsID theGroupsOfElementsID)

Definition at line 8041 of file SMESH_MeshEditor.cxx.

References SMDS_Mesh.FindElement().

{
  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 );
}
void SMESH_MeshEditor.MergeEqualElements ( )
void SMESH_MeshEditor.MergeNodes ( TListOfListOfNodes theNodeGroups)
double SMESH_MeshEditor::OrientedAngle ( const gp_Pnt &  p0,
const gp_Pnt &  p1,
const gp_Pnt &  g1,
const gp_Pnt &  g2 
)

compute an oriented angle between two planes defined by four points.

The vector (p0,p1) defines the intersection of the 2 planes (p0,p1,g1) and (p0,p1,g2)

Parameters:
p0base of the rotation axe
p1extremity of the rotation axe
g1belongs to the first plane
g2belongs to the second plane

Definition at line 10867 of file SMESH_MeshEditor.cxx.

{
//  MESSAGE("    p0: " << p0.X() << " " << p0.Y() << " " << p0.Z());
//  MESSAGE("    p1: " << p1.X() << " " << p1.Y() << " " << p1.Z());
//  MESSAGE("    g1: " << g1.X() << " " << g1.Y() << " " << g1.Z());
//  MESSAGE("    g2: " << g2.X() << " " << g2.Y() << " " << g2.Z());
  gp_Vec vref(p0, p1);
  gp_Vec v1(p0, g1);
  gp_Vec v2(p0, g2);
  gp_Vec n1 = vref.Crossed(v1);
  gp_Vec n2 = vref.Crossed(v2);
  return n2.AngleWithRef(n1, vref);
}
bool SMESH_MeshEditor.QuadToTri ( TIDSortedElemSet theElems,
SMESH::Controls::NumericalFunctorPtr  theCriterion 
)

Split quadrangles into triangles.

Parameters:
theElems- The faces to be splitted.
theCriterion- Is used to choose a diagonal for splitting.
Returns:
bool - Success or not.
bool SMESH_MeshEditor::QuadToTri ( TIDSortedElemSet theElems,
const bool  the13Diag 
)

Split quadrangles into triangles.

Parameters:
theElems- The faces to be splitted.
the13Diag- Is used to choose a diagonal for splitting.
Returns:
bool - Success or not.

Definition at line 1843 of file SMESH_MeshEditor.cxx.

References SMESHDS_Mesh.AddFace(), SMESHDS_Mesh.AddNode(), SMESH_MesherHelper.GetNodeUV(), SMESH_MesherHelper.GetNodeUVneedInFaceNode(), SMDS_MeshNode.GetPosition(), SMESH_MesherHelper.GetSubShape(), SMESH_MesherHelper.GetSubShapeID(), SMDS_MeshElement.GetType(), SMDS_Position.GetTypeOfPosition(), Handle(), SMESHDS_Mesh.IndexToShape(), SMDS_MeshElement.IsQuadratic(), MESSAGE, SMDS_MeshElement.NbNodes(), SMDS_MeshElement.nodesIterator(), SMESHDS_Mesh.RemoveElement(), SMESHDS_Mesh.SetMeshElementOnShape(), SMESH_MesherHelper.SetSubShape(), SMESH_fixation.shape, SMDS_TOP_FACE, SMDSAbs_Face, SMDS_MeshNode.Y(), and SMDS_MeshNode.Z().

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

  MESSAGE( "::QuadToTri()" );

  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;
    bool isquad = elem->NbNodes()==4 || elem->NbNodes()==8;
    if(!isquad) continue;

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

      int aShapeId = FindShape( elem );
      const SMDS_MeshElement* newElem1 = 0;
      const SMDS_MeshElement* newElem2 = 0;
      if ( the13Diag ) {
        newElem1 = aMesh->AddFace( aNodes[2], aNodes[0], aNodes[1] );
        newElem2 = aMesh->AddFace( aNodes[2], aNodes[3], aNodes[0] );
      }
      else {
        newElem1 = aMesh->AddFace( aNodes[3], aNodes[0], aNodes[1] );
        newElem2 = aMesh->AddFace( aNodes[3], aNodes[1], aNodes[2] );
      }
      myLastCreatedElems.Append(newElem1);
      myLastCreatedElems.Append(newElem2);
      // put a new triangle on the same shape and add to the same groups
      if ( aShapeId )
        {
          aMesh->SetMeshElementOnShape( newElem1, aShapeId );
          aMesh->SetMeshElementOnShape( newElem2, aShapeId );
        }
      AddToSameGroups( newElem1, elem, aMesh );
      AddToSameGroups( newElem2, elem, aMesh );
      //aMesh->RemoveFreeElement(elem, aMesh->MeshElements(aShapeId), true);
      aMesh->RemoveElement( elem );
    }

    // Quadratic quadrangle

    if( elem->NbNodes()==8 && elem->IsQuadratic() ) {

      // get surface elem is on
      int aShapeId = FindShape( elem );
      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 );
        }
      }

      const SMDS_MeshNode* aNodes [8];
      const SMDS_MeshNode* inFaceNode = 0;
      SMDS_ElemIteratorPtr itN = elem->nodesIterator();
      int i = 0;
      while ( itN->more() ) {
        aNodes[ i++ ] = static_cast<const SMDS_MeshNode*>( itN->next() );
        if ( !inFaceNode && helper.GetNodeUVneedInFaceNode() &&
             aNodes[ i-1 ]->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE )
        {
          inFaceNode = aNodes[ i-1 ];
        }
      }

      // find middle point for (0,1,2,3)
      // and create a node in this point;
      gp_XYZ p( 0,0,0 );
      if ( surface.IsNull() ) {
        for(i=0; i<4; i++)
          p += gp_XYZ(aNodes[i]->X(), aNodes[i]->Y(), aNodes[i]->Z() );
        p /= 4;
      }
      else {
        TopoDS_Face geomFace = TopoDS::Face( helper.GetSubShape() );
        gp_XY uv( 0,0 );
        for(i=0; i<4; i++)
          uv += helper.GetNodeUV( geomFace, aNodes[i], inFaceNode );
        uv /= 4.;
        p = surface->Value( uv.X(), uv.Y() ).XYZ();
      }
      const SMDS_MeshNode* newN = aMesh->AddNode( p.X(), p.Y(), p.Z() );
      myLastCreatedNodes.Append(newN);

      // create a new element
      const SMDS_MeshElement* newElem1 = 0;
      const SMDS_MeshElement* newElem2 = 0;
      if ( the13Diag ) {
        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] );
      }
      myLastCreatedElems.Append(newElem1);
      myLastCreatedElems.Append(newElem2);
      // put a new triangle on the same shape and add to the same groups
      if ( aShapeId )
        {
          aMesh->SetMeshElementOnShape( newElem1, aShapeId );
          aMesh->SetMeshElementOnShape( newElem2, aShapeId );
        }
      AddToSameGroups( newElem1, elem, aMesh );
      AddToSameGroups( newElem2, elem, aMesh );
      aMesh->RemoveElement( elem );
    }
  }

  return true;
}
int SMESH_MeshEditor.Remove ( const std::list< int > &  theElemIDs,
const bool  isNodes 
)
void SMESH_MeshEditor::RemoveElemFromGroups ( const SMDS_MeshElement element,
SMESHDS_Mesh aMesh 
) [static]

Definition at line 1777 of file SMESH_MeshEditor.cxx.

References SMESHDS_Mesh.GetGroups(), SMESHDS_Group.IsEmpty(), SMDS_MeshGroup.Remove(), and SMESHDS_Group.SMDSGroup().

{
  const set<SMESHDS_GroupBase*>& groups = aMesh->GetGroups();
  if (!groups.empty())
  {
    set<SMESHDS_GroupBase*>::const_iterator GrIt = groups.begin();
    for (; GrIt != groups.end(); GrIt++)
    {
      SMESHDS_Group* grp = dynamic_cast<SMESHDS_Group*>(*GrIt);
      if (!grp || grp->IsEmpty()) continue;
      grp->SMDSGroup().Remove(removeelem);
    }
  }
}
int SMESH_MeshEditor::removeQuadElem ( SMESHDS_SubMesh theSm,
SMDS_ElemIteratorPtr  theItr,
const int  theShapeID 
) [private]

Convert quadratic elements to linear ones and remove quadratic nodes.

Returns:
nb of checked elements
int - nb of checked elements

Definition at line 9580 of file SMESH_MeshEditor.cxx.

References SMESHDS_SubMesh.AddElement(), SMDS_MeshElement.begin_nodes(), SMESHDS_SubMesh.Contains(), SMDS_MeshElement.end_nodes(), SMDS_MeshElement.GetID(), SMDS_MeshElement.getshapeId(), SMDS_MeshElement.GetType(), SMDS_MeshElement.IsQuadratic(), SMESHDS_Mesh.MeshElements(), SMDS_MeshElement.NbCornerNodes(), SMESH_AdvancedEditor.nodes, SMESHDS_Mesh.RemoveFreeElement(), and SMESHDS_Mesh.RemoveFreeNode().

{
  int nbElem = 0;
  SMESHDS_Mesh* meshDS = GetMeshDS();

  while( theItr->more() )
  {
    const SMDS_MeshElement* elem = theItr->next();
    nbElem++;
    if( elem && elem->IsQuadratic())
    {
      int id                    = elem->GetID();
      int nbCornerNodes         = elem->NbCornerNodes();
      SMDSAbs_ElementType aType = elem->GetType();

      vector<const SMDS_MeshNode *> nodes( elem->begin_nodes(), elem->end_nodes() );

      //remove a quadratic element
      if ( !theSm || !theSm->Contains( elem ))
        theSm = meshDS->MeshElements( elem->getshapeId() );
      meshDS->RemoveFreeElement( elem, theSm, /*fromGroups=*/false );

      // remove medium nodes
      for ( unsigned i = nbCornerNodes; i < nodes.size(); ++i )
        if ( nodes[i]->NbInverseElements() == 0 )
          meshDS->RemoveFreeNode( nodes[i], theSm );

      // add a linear element
      nodes.resize( nbCornerNodes );
      SMDS_MeshElement * newElem = AddElement( nodes, aType, false, id );
      ReplaceElemInGroups(elem, newElem, meshDS);
      if( theSm && newElem )
        theSm->AddElement( newElem );
    }
  }
  return nbElem;
}
bool SMESH_MeshEditor.Reorient ( const SMDS_MeshElement theElement)
void SMESH_MeshEditor::ReplaceElemInGroups ( const SMDS_MeshElement elemToRm,
const SMDS_MeshElement elemToAdd,
SMESHDS_Mesh aMesh 
) [static]

Replace elemToRm by elemToAdd in the all groups.

Definition at line 1799 of file SMESH_MeshEditor.cxx.

References SMDS_MeshGroup.Add(), SMESHDS_Mesh.GetGroups(), ex21_lamp.group, SMDS_MeshGroup.Remove(), and SMESHDS_Group.SMDSGroup().

{
  const set<SMESHDS_GroupBase*>& groups = aMesh->GetGroups();
  if (!groups.empty()) {
    set<SMESHDS_GroupBase*>::const_iterator grIt = groups.begin();
    for ( ; grIt != groups.end(); grIt++ ) {
      SMESHDS_Group* group = dynamic_cast<SMESHDS_Group*>( *grIt );
      if ( group && group->SMDSGroup().Remove( elemToRm ) && elemToAdd )
        group->SMDSGroup().Add( elemToAdd );
    }
  }
}
static void SMESH_MeshEditor.ReplaceElemInGroups ( const SMDS_MeshElement elemToRm,
const std::vector< const SMDS_MeshElement * > &  elemToAdd,
SMESHDS_Mesh aMesh 
) [static]
PGroupIDs SMESH_MeshEditor.RotationSweep ( TIDSortedElemSet theElements,
const gp_Ax1 &  theAxis,
const double  theAngle,
const int  theNbSteps,
const double  theToler,
const bool  theMakeGroups,
const bool  theMakeWalls = true 
)
SMESH_MeshEditor::Sew_Error SMESH_MeshEditor::SewFreeBorder ( const SMDS_MeshNode theBorderFirstNode,
const SMDS_MeshNode theBorderSecondNode,
const SMDS_MeshNode theBorderLastNode,
const SMDS_MeshNode theSide2FirstNode,
const SMDS_MeshNode theSide2SecondNode,
const SMDS_MeshNode theSide2ThirdNode = 0,
const bool  theSide2IsFreeBorder = true,
const bool  toCreatePolygons = false,
const bool  toCreatePolyedrs = false 
)

Definition at line 8337 of file SMESH_MeshEditor.cxx.

References Abs(), cast2Node, findAdjacentFace(), SMDS_MeshNode.GetInverseElementIterator(), LinkID_Gen.GetLinkID(), SMDS_VolumeTool.GetNodes(), SMDS_MeshElement.GetType(), SMDS_VtkFace.interlacedNodesElemIterator(), SMDS_VolumeTool.IsLinked(), SMDS_MeshElement.IsQuadratic(), Max(), MESSAGE, Min(), SMESH_AdvancedEditor.n1, SMDS_MeshElement.NbNodes(), SMDS_MeshElement.nodesIterator(), PAL_MESH_041_mesh.p1, PAL_MESH_041_mesh.p2, SMDS_VolumeTool.Set(), SMDSAbs_Face, SMDS_MeshNode.X(), SMESH_AdvancedEditor.xyz, SMDS_MeshNode.Y(), and SMDS_MeshNode.Z().

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

  MESSAGE("::SewFreeBorder()");
  Sew_Error aResult = SEW_OK;

  // ====================================
  //    find side nodes and elements
  // ====================================

  list< const SMDS_MeshNode* > nSide[ 2 ];
  list< const SMDS_MeshElement* > eSide[ 2 ];
  list< const SMDS_MeshNode* >::iterator nIt[ 2 ];
  list< const SMDS_MeshElement* >::iterator eIt[ 2 ];

  // Free border 1
  // --------------
  if (!FindFreeBorder(theBordFirstNode,theBordSecondNode,theBordLastNode,
                      nSide[0], eSide[0])) {
    MESSAGE(" Free Border 1 not found " );
    aResult = SEW_BORDER1_NOT_FOUND;
  }
  if (theSideIsFreeBorder) {
    // Free border 2
    // --------------
    if (!FindFreeBorder(theSideFirstNode, theSideSecondNode, theSideThirdNode,
                        nSide[1], eSide[1])) {
      MESSAGE(" Free Border 2 not found " );
      aResult = ( aResult != SEW_OK ? SEW_BOTH_BORDERS_NOT_FOUND : SEW_BORDER2_NOT_FOUND );
    }
  }
  if ( aResult != SEW_OK )
    return aResult;

  if (!theSideIsFreeBorder) {
    // Side 2
    // --------------

    // -------------------------------------------------------------------------
    // Algo:
    // 1. If nodes to merge are not coincident, move nodes of the free border
    //    from the coord sys defined by the direction from the first to last
    //    nodes of the border to the correspondent sys of the side 2
    // 2. On the side 2, find the links most co-directed with the correspondent
    //    links of the free border
    // -------------------------------------------------------------------------

    // 1. Since sewing may break if there are volumes to split on the side 2,
    //    we wont move nodes but just compute new coordinates for them
    typedef map<const SMDS_MeshNode*, gp_XYZ> TNodeXYZMap;
    TNodeXYZMap nBordXYZ;
    list< const SMDS_MeshNode* >& bordNodes = nSide[ 0 ];
    list< const SMDS_MeshNode* >::iterator nBordIt;

    gp_XYZ Pb1( theBordFirstNode->X(), theBordFirstNode->Y(), theBordFirstNode->Z() );
    gp_XYZ Pb2( theBordLastNode->X(), theBordLastNode->Y(), theBordLastNode->Z() );
    gp_XYZ Ps1( theSideFirstNode->X(), theSideFirstNode->Y(), theSideFirstNode->Z() );
    gp_XYZ Ps2( theSideSecondNode->X(), theSideSecondNode->Y(), theSideSecondNode->Z() );
    double tol2 = 1.e-8;
    gp_Vec Vbs1( Pb1 - Ps1 ),Vbs2( Pb2 - Ps2 );
    if ( Vbs1.SquareMagnitude() > tol2 || Vbs2.SquareMagnitude() > tol2 ) {
      // Need node movement.

      // find X and Z axes to create trsf
      gp_Vec Zb( Pb1 - Pb2 ), Zs( Ps1 - Ps2 );
      gp_Vec X = Zs ^ Zb;
      if ( X.SquareMagnitude() <= gp::Resolution() * gp::Resolution() )
        // Zb || Zs
        X = gp_Ax2( gp::Origin(), Zb ).XDirection();

      // coord systems
      gp_Ax3 toBordAx( Pb1, Zb, X );
      gp_Ax3 fromSideAx( Ps1, Zs, X );
      gp_Ax3 toGlobalAx( gp::Origin(), gp::DZ(), gp::DX() );
      // set trsf
      gp_Trsf toBordSys, fromSide2Sys;
      toBordSys.SetTransformation( toBordAx );
      fromSide2Sys.SetTransformation( fromSideAx, toGlobalAx );
      fromSide2Sys.SetScaleFactor( Zs.Magnitude() / Zb.Magnitude() );

      // move
      for ( nBordIt = bordNodes.begin(); nBordIt != bordNodes.end(); nBordIt++ ) {
        const SMDS_MeshNode* n = *nBordIt;
        gp_XYZ xyz( n->X(),n->Y(),n->Z() );
        toBordSys.Transforms( xyz );
        fromSide2Sys.Transforms( xyz );
        nBordXYZ.insert( TNodeXYZMap::value_type( n, xyz ));
      }
    }
    else {
      // just insert nodes XYZ in the nBordXYZ map
      for ( nBordIt = bordNodes.begin(); nBordIt != bordNodes.end(); nBordIt++ ) {
        const SMDS_MeshNode* n = *nBordIt;
        nBordXYZ.insert( TNodeXYZMap::value_type( n, gp_XYZ( n->X(),n->Y(),n->Z() )));
      }
    }

    // 2. On the side 2, find the links most co-directed with the correspondent
    //    links of the free border

    list< const SMDS_MeshElement* >& sideElems = eSide[ 1 ];
    list< const SMDS_MeshNode* >& sideNodes = nSide[ 1 ];
    sideNodes.push_back( theSideFirstNode );

    bool hasVolumes = false;
    LinkID_Gen aLinkID_Gen( GetMeshDS() );
    set<long> foundSideLinkIDs, checkedLinkIDs;
    SMDS_VolumeTool volume;
    //const SMDS_MeshNode* faceNodes[ 4 ];

    const SMDS_MeshNode*    sideNode;
    const SMDS_MeshElement* sideElem;
    const SMDS_MeshNode* prevSideNode = theSideFirstNode;
    const SMDS_MeshNode* prevBordNode = theBordFirstNode;
    nBordIt = bordNodes.begin();
    nBordIt++;
    // border node position and border link direction to compare with
    gp_XYZ bordPos = nBordXYZ[ *nBordIt ];
    gp_XYZ bordDir = bordPos - nBordXYZ[ prevBordNode ];
    // choose next side node by link direction or by closeness to
    // the current border node:
    bool searchByDir = ( *nBordIt != theBordLastNode );
    do {
      // find the next node on the Side 2
      sideNode = 0;
      double maxDot = -DBL_MAX, minDist = DBL_MAX;
      long linkID;
      checkedLinkIDs.clear();
      gp_XYZ prevXYZ( prevSideNode->X(), prevSideNode->Y(), prevSideNode->Z() );

      // loop on inverse elements of current node (prevSideNode) on the Side 2
      SMDS_ElemIteratorPtr invElemIt = prevSideNode->GetInverseElementIterator();
      while ( invElemIt->more() )
      {
        const SMDS_MeshElement* elem = invElemIt->next();
        // prepare data for a loop on links coming to prevSideNode, of a face or a volume
        int iPrevNode, iNode = 0, nbNodes = elem->NbNodes();
        vector< const SMDS_MeshNode* > faceNodes( nbNodes, (const SMDS_MeshNode*)0 );
        bool isVolume = volume.Set( elem );
        const SMDS_MeshNode** nodes = isVolume ? volume.GetNodes() : & faceNodes[0];
        if ( isVolume ) // --volume
          hasVolumes = true;
        else if ( elem->GetType()==SMDSAbs_Face ) { // --face
          // retrieve all face nodes and find iPrevNode - an index of the prevSideNode
          if(elem->IsQuadratic()) {
            const SMDS_VtkFace* F =
              dynamic_cast<const SMDS_VtkFace*>(elem);
            if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace"));
            // use special nodes iterator
            SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator();
            while( anIter->more() ) {
              nodes[ iNode ] = cast2Node(anIter->next());
              if ( nodes[ iNode++ ] == prevSideNode )
                iPrevNode = iNode - 1;
            }
          }
          else {
            SMDS_ElemIteratorPtr nIt = elem->nodesIterator();
            while ( nIt->more() ) {
              nodes[ iNode ] = cast2Node( nIt->next() );
              if ( nodes[ iNode++ ] == prevSideNode )
                iPrevNode = iNode - 1;
            }
          }
          // there are 2 links to check
          nbNodes = 2;
        }
        else // --edge
          continue;
        // loop on links, to be precise, on the second node of links
        for ( iNode = 0; iNode < nbNodes; iNode++ ) {
          const SMDS_MeshNode* n = nodes[ iNode ];
          if ( isVolume ) {
            if ( !volume.IsLinked( n, prevSideNode ))
              continue;
          }
          else {
            if ( iNode ) // a node before prevSideNode
              n = nodes[ iPrevNode == 0 ? elem->NbNodes() - 1 : iPrevNode - 1 ];
            else         // a node after prevSideNode
              n = nodes[ iPrevNode + 1 == elem->NbNodes() ? 0 : iPrevNode + 1 ];
          }
          // check if this link was already used
          long iLink = aLinkID_Gen.GetLinkID( prevSideNode, n );
          bool isJustChecked = !checkedLinkIDs.insert( iLink ).second;
          if (!isJustChecked &&
              foundSideLinkIDs.find( iLink ) == foundSideLinkIDs.end() )
          {
            // test a link geometrically
            gp_XYZ nextXYZ ( n->X(), n->Y(), n->Z() );
            bool linkIsBetter = false;
            double dot = 0.0, dist = 0.0;
            if ( searchByDir ) { // choose most co-directed link
              dot = bordDir * ( nextXYZ - prevXYZ ).Normalized();
              linkIsBetter = ( dot > maxDot );
            }
            else { // choose link with the node closest to bordPos
              dist = ( nextXYZ - bordPos ).SquareModulus();
              linkIsBetter = ( dist < minDist );
            }
            if ( linkIsBetter ) {
              maxDot = dot;
              minDist = dist;
              linkID = iLink;
              sideNode = n;
              sideElem = elem;
            }
          }
        }
      } // loop on inverse elements of prevSideNode

      if ( !sideNode ) {
        MESSAGE(" Cant find path by links of the Side 2 ");
        return SEW_BAD_SIDE_NODES;
      }
      sideNodes.push_back( sideNode );
      sideElems.push_back( sideElem );
      foundSideLinkIDs.insert ( linkID );
      prevSideNode = sideNode;

      if ( *nBordIt == theBordLastNode )
        searchByDir = false;
      else {
        // find the next border link to compare with
        gp_XYZ sidePos( sideNode->X(), sideNode->Y(), sideNode->Z() );
        searchByDir = ( bordDir * ( sidePos - bordPos ) <= 0 );
        // move to next border node if sideNode is before forward border node (bordPos)
        while ( *nBordIt != theBordLastNode && !searchByDir ) {
          prevBordNode = *nBordIt;
          nBordIt++;
          bordPos = nBordXYZ[ *nBordIt ];
          bordDir = bordPos - nBordXYZ[ prevBordNode ];
          searchByDir = ( bordDir * ( sidePos - bordPos ) <= 0 );
        }
      }
    }
    while ( sideNode != theSideSecondNode );

    if ( hasVolumes && sideNodes.size () != bordNodes.size() && !toCreatePolyedrs) {
      MESSAGE("VOLUME SPLITTING IS FORBIDDEN");
      return SEW_VOLUMES_TO_SPLIT; // volume splitting is forbidden
    }
  } // end nodes search on the side 2

  // ============================
  // sew the border to the side 2
  // ============================

  int nbNodes[]  = { nSide[0].size(), nSide[1].size() };
  int maxNbNodes = Max( nbNodes[0], nbNodes[1] );

  TListOfListOfNodes nodeGroupsToMerge;
  if ( nbNodes[0] == nbNodes[1] ||
       ( theSideIsFreeBorder && !theSideThirdNode)) {

    // all nodes are to be merged

    for (nIt[0] = nSide[0].begin(), nIt[1] = nSide[1].begin();
         nIt[0] != nSide[0].end() && nIt[1] != nSide[1].end();
         nIt[0]++, nIt[1]++ )
    {
      nodeGroupsToMerge.push_back( list<const SMDS_MeshNode*>() );
      nodeGroupsToMerge.back().push_back( *nIt[1] ); // to keep
      nodeGroupsToMerge.back().push_back( *nIt[0] ); // to remove
    }
  }
  else {

    // insert new nodes into the border and the side to get equal nb of segments

    // get normalized parameters of nodes on the borders
    //double param[ 2 ][ maxNbNodes ];
    double* param[ 2 ];
    param[0] = new double [ maxNbNodes ];
    param[1] = new double [ maxNbNodes ];
    int iNode, iBord;
    for ( iBord = 0; iBord < 2; iBord++ ) { // loop on 2 borders
      list< const SMDS_MeshNode* >& nodes = nSide[ iBord ];
      list< const SMDS_MeshNode* >::iterator nIt = nodes.begin();
      const SMDS_MeshNode* nPrev = *nIt;
      double bordLength = 0;
      for ( iNode = 0; nIt != nodes.end(); nIt++, iNode++ ) { // loop on border nodes
        const SMDS_MeshNode* nCur = *nIt;
        gp_XYZ segment (nCur->X() - nPrev->X(),
                        nCur->Y() - nPrev->Y(),
                        nCur->Z() - nPrev->Z());
        double segmentLen = segment.Modulus();
        bordLength += segmentLen;
        param[ iBord ][ iNode ] = bordLength;
        nPrev = nCur;
      }
      // normalize within [0,1]
      for ( iNode = 0; iNode < nbNodes[ iBord ]; iNode++ ) {
        param[ iBord ][ iNode ] /= bordLength;
      }
    }

    // loop on border segments
    const SMDS_MeshNode *nPrev[ 2 ] = { 0, 0 };
    int i[ 2 ] = { 0, 0 };
    nIt[0] = nSide[0].begin(); eIt[0] = eSide[0].begin();
    nIt[1] = nSide[1].begin(); eIt[1] = eSide[1].begin();

    TElemOfNodeListMap insertMap;
    TElemOfNodeListMap::iterator insertMapIt;
    // insertMap is
    // key:   elem to insert nodes into
    // value: 2 nodes to insert between + nodes to be inserted
    do {
      bool next[ 2 ] = { false, false };

      // find min adjacent segment length after sewing
      double nextParam = 10., prevParam = 0;
      for ( iBord = 0; iBord < 2; iBord++ ) { // loop on 2 borders
        if ( i[ iBord ] + 1 < nbNodes[ iBord ])
          nextParam = Min( nextParam, param[iBord][ i[iBord] + 1 ]);
        if ( i[ iBord ] > 0 )
          prevParam = Max( prevParam, param[iBord][ i[iBord] - 1 ]);
      }
      double minParam = Min( param[ 0 ][ i[0] ], param[ 1 ][ i[1] ]);
      double maxParam = Max( param[ 0 ][ i[0] ], param[ 1 ][ i[1] ]);
      double minSegLen = Min( nextParam - minParam, maxParam - prevParam );

      // choose to insert or to merge nodes
      double du = param[ 1 ][ i[1] ] - param[ 0 ][ i[0] ];
      if ( Abs( du ) <= minSegLen * 0.2 ) {
        // merge
        // ------
        nodeGroupsToMerge.push_back( list<const SMDS_MeshNode*>() );
        const SMDS_MeshNode* n0 = *nIt[0];
        const SMDS_MeshNode* n1 = *nIt[1];
        nodeGroupsToMerge.back().push_back( n1 );
        nodeGroupsToMerge.back().push_back( n0 );
        // position of node of the border changes due to merge
        param[ 0 ][ i[0] ] += du;
        // move n1 for the sake of elem shape evaluation during insertion.
        // n1 will be removed by MergeNodes() anyway
        const_cast<SMDS_MeshNode*>( n0 )->setXYZ( n1->X(), n1->Y(), n1->Z() );
        next[0] = next[1] = true;
      }
      else {
        // insert
        // ------
        int intoBord = ( du < 0 ) ? 0 : 1;
        const SMDS_MeshElement* elem = *eIt[ intoBord ];
        const SMDS_MeshNode*    n1   = nPrev[ intoBord ];
        const SMDS_MeshNode*    n2   = *nIt[ intoBord ];
        const SMDS_MeshNode*    nIns = *nIt[ 1 - intoBord ];
        if ( intoBord == 1 ) {
          // move node of the border to be on a link of elem of the side
          gp_XYZ p1 (n1->X(), n1->Y(), n1->Z());
          gp_XYZ p2 (n2->X(), n2->Y(), n2->Z());
          double ratio = du / ( param[ 1 ][ i[1] ] - param[ 1 ][ i[1]-1 ]);
          gp_XYZ p = p2 * ( 1 - ratio ) + p1 * ratio;
          GetMeshDS()->MoveNode( nIns, p.X(), p.Y(), p.Z() );
        }
        insertMapIt = insertMap.find( elem );
        bool notFound = ( insertMapIt == insertMap.end() );
        bool otherLink = ( !notFound && (*insertMapIt).second.front() != n1 );
        if ( otherLink ) {
          // insert into another link of the same element:
          // 1. perform insertion into the other link of the elem
          list<const SMDS_MeshNode*> & nodeList = (*insertMapIt).second;
          const SMDS_MeshNode* n12 = nodeList.front(); nodeList.pop_front();
          const SMDS_MeshNode* n22 = nodeList.front(); nodeList.pop_front();
          InsertNodesIntoLink( elem, n12, n22, nodeList, toCreatePolygons );
          // 2. perform insertion into the link of adjacent faces
          while (true) {
            const SMDS_MeshElement* adjElem = findAdjacentFace( n12, n22, elem );
            if ( adjElem )
              InsertNodesIntoLink( adjElem, n12, n22, nodeList, toCreatePolygons );
            else
              break;
          }
          if (toCreatePolyedrs) {
            // perform insertion into the links of adjacent volumes
            UpdateVolumes(n12, n22, nodeList);
          }
          // 3. find an element appeared on n1 and n2 after the insertion
          insertMap.erase( elem );
          elem = findAdjacentFace( n1, n2, 0 );
        }
        if ( notFound || otherLink ) {
          // add element and nodes of the side into the insertMap
          insertMapIt = insertMap.insert
            ( TElemOfNodeListMap::value_type( elem, list<const SMDS_MeshNode*>() )).first;
          (*insertMapIt).second.push_back( n1 );
          (*insertMapIt).second.push_back( n2 );
        }
        // add node to be inserted into elem
        (*insertMapIt).second.push_back( nIns );
        next[ 1 - intoBord ] = true;
      }

      // go to the next segment
      for ( iBord = 0; iBord < 2; iBord++ ) { // loop on 2 borders
        if ( next[ iBord ] ) {
          if ( i[ iBord ] != 0 && eIt[ iBord ] != eSide[ iBord ].end())
            eIt[ iBord ]++;
          nPrev[ iBord ] = *nIt[ iBord ];
          nIt[ iBord ]++; i[ iBord ]++;
        }
      }
    }
    while ( nIt[0] != nSide[0].end() && nIt[1] != nSide[1].end());

    // perform insertion of nodes into elements

    for (insertMapIt = insertMap.begin();
         insertMapIt != insertMap.end();
         insertMapIt++ )
    {
      const SMDS_MeshElement* elem = (*insertMapIt).first;
      list<const SMDS_MeshNode*> & nodeList = (*insertMapIt).second;
      const SMDS_MeshNode* n1 = nodeList.front(); nodeList.pop_front();
      const SMDS_MeshNode* n2 = nodeList.front(); nodeList.pop_front();

      InsertNodesIntoLink( elem, n1, n2, nodeList, toCreatePolygons );

      if ( !theSideIsFreeBorder ) {
        // look for and insert nodes into the faces adjacent to elem
        while (true) {
          const SMDS_MeshElement* adjElem = findAdjacentFace( n1, n2, elem );
          if ( adjElem )
            InsertNodesIntoLink( adjElem, n1, n2, nodeList, toCreatePolygons );
          else
            break;
        }
      }
      if (toCreatePolyedrs) {
        // perform insertion into the links of adjacent volumes
        UpdateVolumes(n1, n2, nodeList);
      }
    }

    delete param[0];
    delete param[1];
  } // end: insert new nodes

  MergeNodes ( nodeGroupsToMerge );

  return aResult;
}
Sew_Error SMESH_MeshEditor.SewSideElements ( TIDSortedElemSet theSide1,
TIDSortedElemSet theSide2,
const SMDS_MeshNode theFirstNode1ToMerge,
const SMDS_MeshNode theFirstNode2ToMerge,
const SMDS_MeshNode theSecondNode1ToMerge,
const SMDS_MeshNode theSecondNode2ToMerge 
)
int SMESH_MeshEditor::SimplifyFace ( const std::vector< const SMDS_MeshNode * >  faceNodes,
std::vector< const SMDS_MeshNode * > &  poly_nodes,
std::vector< int > &  quantities 
) const

Definition at line 7218 of file SMESH_MeshEditor.cxx.

{
  int nbNodes = faceNodes.size();

  if (nbNodes < 3)
    return 0;

  set<const SMDS_MeshNode*> nodeSet;

  // get simple seq of nodes
  //const SMDS_MeshNode* simpleNodes[ nbNodes ];
  vector<const SMDS_MeshNode*> simpleNodes( nbNodes );
  int iSimple = 0, nbUnique = 0;

  simpleNodes[iSimple++] = faceNodes[0];
  nbUnique++;
  for (int iCur = 1; iCur < nbNodes; iCur++) {
    if (faceNodes[iCur] != simpleNodes[iSimple - 1]) {
      simpleNodes[iSimple++] = faceNodes[iCur];
      if (nodeSet.insert( faceNodes[iCur] ).second)
        nbUnique++;
    }
  }
  int nbSimple = iSimple;
  if (simpleNodes[nbSimple - 1] == simpleNodes[0]) {
    nbSimple--;
    iSimple--;
  }

  if (nbUnique < 3)
    return 0;

  // separate loops
  int nbNew = 0;
  bool foundLoop = (nbSimple > nbUnique);
  while (foundLoop) {
    foundLoop = false;
    set<const SMDS_MeshNode*> loopSet;
    for (iSimple = 0; iSimple < nbSimple && !foundLoop; iSimple++) {
      const SMDS_MeshNode* n = simpleNodes[iSimple];
      if (!loopSet.insert( n ).second) {
        foundLoop = true;

        // separate loop
        int iC = 0, curLast = iSimple;
        for (; iC < curLast; iC++) {
          if (simpleNodes[iC] == n) break;
        }
        int loopLen = curLast - iC;
        if (loopLen > 2) {
          // create sub-element
          nbNew++;
          quantities.push_back(loopLen);
          for (; iC < curLast; iC++) {
            poly_nodes.push_back(simpleNodes[iC]);
          }
        }
        // shift the rest nodes (place from the first loop position)
        for (iC = curLast + 1; iC < nbSimple; iC++) {
          simpleNodes[iC - loopLen] = simpleNodes[iC];
        }
        nbSimple -= loopLen;
        iSimple -= loopLen;
      }
    } // for (iSimple = 0; iSimple < nbSimple; iSimple++)
  } // while (foundLoop)

  if (iSimple > 2) {
    nbNew++;
    quantities.push_back(iSimple);
    for (int i = 0; i < iSimple; i++)
      poly_nodes.push_back(simpleNodes[i]);
  }

  return nbNew;
}
void SMESH_MeshEditor.Smooth ( TIDSortedElemSet theElements,
std::set< const SMDS_MeshNode * > &  theFixedNodes,
const SmoothMethod  theSmoothMethod,
const int  theNbIterations,
double  theTgtAspectRatio = 1.0,
const bool  the2D = true 
)
void SMESH_MeshEditor::SplitVolumesIntoTetra ( const TIDSortedElemSet theElems,
const int  theMethodFlags 
)

Split volumic elements into tetrahedra.

Definition at line 1561 of file SMESH_MeshEditor.cxx.

References SMESHDS_SubMesh.AddElement(), SMESH_MesherHelper.AddFace(), SMESHDS_SubMesh.AddNode(), SMESH_MesherHelper.AddNode(), SMESH_MesherHelper.AddTLinkNode(), SMESH_MesherHelper.AddVolume(), SMESHDS_SubMesh.Contains(), SMDS_VolumeTool.GetBaryCenter(), SMDS_MeshElement.GetEntityType(), SMDS_VolumeTool.GetFaceBaryCenter(), SMDS_VolumeTool.GetFaceNodes(), SMDS_VolumeTool.GetFaceNodesIndices(), SMDS_VolumeTool.GetNodes(), SMDS_VolumeTool.IsFaceExternal(), SMDS_VolumeTool.NbFaceNodes(), SMDS_VolumeTool.NbFaces(), SMESH_AdvancedEditor.nodes, SMDS_VolumeTool.Set(), SMESH_MesherHelper.SetElementsOnShape(), SMESH_MesherHelper.SetIsQuadratic(), SMESH_MesherHelper.SetSubShape(), and SMDSEntity_Quad_Tetra.

{
  // 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 )
  {
    SMDSAbs_EntityType geomType = (*elem)->GetEntityType();
    if ( geomType <= SMDSEntity_Quad_Tetra )
      continue; // tetra or face or ...

    if ( !volTool.Set( *elem )) continue; // not volume? 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 );
        for ( int iN = 0; iN < volTool.NbFaceNodes( iF ); iN += iQ )
          helper.AddTLinkNode( fNodes[iF], fNodes[iF+2], fNodes[iF+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 ), (const SMDS_MeshNode*)0) ).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 ) + nbNodes*iQ );
      while ( const SMDS_MeshElement* face = GetMeshDS()->FindFace( fNodes ))
      {
        // 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 );

  } // loop on volumes to split

  myLastCreatedNodes = newNodes;
  myLastCreatedElems = newElems;
}
void SMESH_MeshEditor::sweepElement ( const SMDS_MeshElement elem,
const std::vector< TNodeOfNodeListMapItr > &  newNodesItVec,
std::list< const SMDS_MeshElement * > &  newElems,
const int  nbSteps,
SMESH_SequenceOfElemPtr &  srcElements 
) [private]

Create elements by sweeping an element.

Parameters:
elem- element to sweep
newNodesItVec- nodes generated from each node of the element
newElems- generated elements
nbSteps- number of sweeping steps
srcElements- to append elem for each generated element

Definition at line 3396 of file SMESH_MeshEditor.cxx.

References SMESHDS_Mesh.AddEdge(), SMESHDS_Mesh.AddFace(), SMESHDS_Mesh.AddPolyhedralVolume(), SMESHDS_Mesh.AddVolume(), SMDS_MeshElement.GetID(), SMDS_MeshElement.GetType(), SMDS_MeshElement.IsMediumNode(), SMDS_MeshElement.IsPoly(), SMDS_MeshElement.IsQuadratic(), isReverse(), MESSAGE, SMESH_AdvancedEditor.n1, SMESH_AdvancedEditor.n2, SMESH_AdvancedEditor.n3, SMESH_AdvancedEditor.n4, SMESH_AdvancedEditor.n5, SMDS_MeshElement.NbNodes(), ex29_refine.node(), SMDSAbs_Face, and SMDSAbs_Node.

{
  //MESSAGE("sweepElement " << nbSteps);
  SMESHDS_Mesh* aMesh = GetMeshDS();

  // Loop on elem nodes:
  // find new nodes and detect same nodes indices
  int nbNodes = elem->NbNodes();
  vector < list< const SMDS_MeshNode* >::const_iterator > itNN( nbNodes );
  vector<const SMDS_MeshNode*> prevNod( nbNodes );
  vector<const SMDS_MeshNode*> nextNod( nbNodes );
  vector<const SMDS_MeshNode*> midlNod( nbNodes );

  int iNode, nbSame = 0, iNotSameNode = 0, iSameNode = 0;
  vector<int> sames(nbNodes);
  vector<bool> issimple(nbNodes);

  for ( iNode = 0; iNode < nbNodes; iNode++ ) {
    TNodeOfNodeListMapItr nnIt = newNodesItVec[ iNode ];
    const SMDS_MeshNode*                 node         = nnIt->first;
    const list< const SMDS_MeshNode* > & listNewNodes = nnIt->second;
    if ( listNewNodes.empty() ) {
      return;
    }

    issimple[iNode] = (listNewNodes.size()==nbSteps); // is node medium

    itNN[ iNode ] = listNewNodes.begin();
    prevNod[ iNode ] = node;
    nextNod[ iNode ] = listNewNodes.front();
    if( !elem->IsQuadratic() || !issimple[iNode] ) {
      if ( prevNod[ iNode ] != nextNod [ iNode ])
        iNotSameNode = iNode;
      else {
        iSameNode = iNode;
        //nbSame++;
        sames[nbSame++] = iNode;
      }
    }
  }

  //cerr<<"  nbSame = "<<nbSame<<endl;
  if ( nbSame == nbNodes || nbSame > 2) {
    MESSAGE( " Too many same nodes of element " << elem->GetID() );
    //INFOS( " Too many same nodes of element " << elem->GetID() );
    return;
  }

  //  if( elem->IsQuadratic() && nbSame>0 ) {
  //    MESSAGE( "Can not rotate quadratic element " << elem->GetID() );
  //    return;
  //  }

  int iBeforeSame = 0, iAfterSame = 0, iOpposSame = 0;
  int nbBaseNodes = ( elem->IsQuadratic() ? nbNodes/2 : nbNodes );
  if ( nbSame > 0 ) {
    iBeforeSame = ( iSameNode == 0 ? nbBaseNodes - 1 : iSameNode - 1 );
    iAfterSame  = ( iSameNode + 1 == nbBaseNodes ? 0 : iSameNode + 1 );
    iOpposSame  = ( iSameNode - 2 < 0  ? iSameNode + 2 : iSameNode - 2 );
  }

  //if(nbNodes==8)
  //cout<<" prevNod[0]="<< prevNod[0]<<" prevNod[1]="<< prevNod[1]
  //    <<" prevNod[2]="<< prevNod[2]<<" prevNod[3]="<< prevNod[4]
  //    <<" prevNod[4]="<< prevNod[4]<<" prevNod[5]="<< prevNod[5]
  //    <<" prevNod[6]="<< prevNod[6]<<" prevNod[7]="<< prevNod[7]<<endl;

  // check element orientation
  int i0 = 0, i2 = 2;
  if ( nbNodes > 2 && !isReverse( prevNod, nextNod, nbNodes, iNotSameNode )) {
    //MESSAGE("Reversed elem " << elem );
    i0 = 2;
    i2 = 0;
    if ( nbSame > 0 )
      std::swap( iBeforeSame, iAfterSame );
  }

  // make new elements
  const SMDS_MeshElement* lastElem = elem;
  for (int iStep = 0; iStep < nbSteps; iStep++ ) {
    // get next nodes
    for ( iNode = 0; iNode < nbNodes; iNode++ ) {
      if(issimple[iNode]) {
        nextNod[ iNode ] = *itNN[ iNode ];
        itNN[ iNode ]++;
      }
      else {
        if( elem->GetType()==SMDSAbs_Node ) {
          // we have to use two nodes
          midlNod[ iNode ] = *itNN[ iNode ];
          itNN[ iNode ]++;
          nextNod[ iNode ] = *itNN[ iNode ];
          itNN[ iNode ]++;
        }
        else if(!elem->IsQuadratic() || lastElem->IsMediumNode(prevNod[iNode]) ) {
          // we have to use each second node
          //itNN[ iNode ]++;
          nextNod[ iNode ] = *itNN[ iNode ];
          itNN[ iNode ]++;
        }
        else {
          // we have to use two nodes
          midlNod[ iNode ] = *itNN[ iNode ];
          itNN[ iNode ]++;
          nextNod[ iNode ] = *itNN[ iNode ];
          itNN[ iNode ]++;
        }
      }
    }
    SMDS_MeshElement* aNewElem = 0;
    if(!elem->IsPoly()) {
      switch ( nbNodes ) {
      case 0:
        return;
      case 1: { // NODE
        if ( nbSame == 0 ) {
          if(issimple[0])
            aNewElem = aMesh->AddEdge( prevNod[ 0 ], nextNod[ 0 ] );
          else
            aNewElem = aMesh->AddEdge( prevNod[ 0 ], nextNod[ 0 ], midlNod[ 0 ] );
        }
        break;
      }
      case 2: { // EDGE
        if ( nbSame == 0 )
          aNewElem = aMesh->AddFace(prevNod[ 0 ], prevNod[ 1 ],
                                    nextNod[ 1 ], nextNod[ 0 ] );
        else
          aNewElem = aMesh->AddFace(prevNod[ 0 ], prevNod[ 1 ],
                                    nextNod[ iNotSameNode ] );
        break;
      }

      case 3: { // TRIANGLE or quadratic edge
        if(elem->GetType() == SMDSAbs_Face) { // TRIANGLE

          if ( nbSame == 0 )       // --- pentahedron
            aNewElem = aMesh->AddVolume (prevNod[ i0 ], prevNod[ 1 ], prevNod[ i2 ],
                                         nextNod[ i0 ], nextNod[ 1 ], nextNod[ i2 ] );

          else if ( nbSame == 1 )  // --- pyramid
            aNewElem = aMesh->AddVolume (prevNod[ iBeforeSame ],  prevNod[ iAfterSame ],
                                         nextNod[ iAfterSame ], nextNod[ iBeforeSame ],
                                         nextNod[ iSameNode ]);

          else // 2 same nodes:      --- tetrahedron
            aNewElem = aMesh->AddVolume (prevNod[ i0 ], prevNod[ 1 ], prevNod[ i2 ],
                                         nextNod[ iNotSameNode ]);
        }
        else { // quadratic edge
          if(nbSame==0) {     // quadratic quadrangle
            aNewElem = aMesh->AddFace(prevNod[0], nextNod[0], nextNod[1], prevNod[1],
                                      midlNod[0], nextNod[2], midlNod[1], prevNod[2]);
          }
          else if(nbSame==1) { // quadratic triangle
            if(sames[0]==2) {
              return; // medium node on axis
            }
            else if(sames[0]==0) {
              aNewElem = aMesh->AddFace(prevNod[0], nextNod[1], prevNod[1],
                                        nextNod[2], midlNod[1], prevNod[2]);
            }
            else { // sames[0]==1
              aNewElem = aMesh->AddFace(prevNod[0], nextNod[0], prevNod[1],
                                        midlNod[0], nextNod[2], prevNod[2]);
            }
          }
          else {
            return;
          }
        }
        break;
      }
      case 4: { // QUADRANGLE

        if ( nbSame == 0 )       // --- hexahedron
          aNewElem = aMesh->AddVolume (prevNod[ i0 ], prevNod[ 1 ], prevNod[ i2 ], prevNod[ 3 ],
                                       nextNod[ i0 ], nextNod[ 1 ], nextNod[ i2 ], nextNod[ 3 ]);

        else if ( nbSame == 1 ) { // --- pyramid + pentahedron
          aNewElem = aMesh->AddVolume (prevNod[ iBeforeSame ],  prevNod[ iAfterSame ],
                                       nextNod[ iAfterSame ], nextNod[ iBeforeSame ],
                                       nextNod[ iSameNode ]);
          newElems.push_back( aNewElem );
          aNewElem = aMesh->AddVolume (prevNod[ iAfterSame ], prevNod[ iOpposSame ],
                                       prevNod[ iBeforeSame ],  nextNod[ iAfterSame ],
                                       nextNod[ iOpposSame ],  nextNod[ iBeforeSame ] );
        }
        else if ( nbSame == 2 ) { // pentahedron
          if ( prevNod[ iBeforeSame ] == nextNod[ iBeforeSame ] )
            // iBeforeSame is same too
            aNewElem = aMesh->AddVolume (prevNod[ iBeforeSame ], prevNod[ iOpposSame ],
                                         nextNod[ iOpposSame ], prevNod[ iSameNode ],
                                         prevNod[ iAfterSame ],  nextNod[ iAfterSame ]);
          else
            // iAfterSame is same too
            aNewElem = aMesh->AddVolume (prevNod[ iSameNode ], prevNod[ iBeforeSame ],
                                         nextNod[ iBeforeSame ], prevNod[ iAfterSame ],
                                         prevNod[ iOpposSame ],  nextNod[ iOpposSame ]);
        }
        break;
      }
      case 6: { // quadratic triangle
        // create pentahedron with 15 nodes
        if(nbSame==0) {
          if(i0>0) { // reversed case
            aNewElem = aMesh->AddVolume (prevNod[0], prevNod[2], prevNod[1],
                                         nextNod[0], nextNod[2], nextNod[1],
                                         prevNod[5], prevNod[4], prevNod[3],
                                         nextNod[5], nextNod[4], nextNod[3],
                                         midlNod[0], midlNod[2], midlNod[1]);
          }
          else { // not reversed case
            aNewElem = aMesh->AddVolume (prevNod[0], prevNod[1], prevNod[2],
                                         nextNod[0], nextNod[1], nextNod[2],
                                         prevNod[3], prevNod[4], prevNod[5],
                                         nextNod[3], nextNod[4], nextNod[5],
                                         midlNod[0], midlNod[1], midlNod[2]);
          }
        }
        else if(nbSame==1) {
          // 2d order pyramid of 13 nodes
          //SMDS_MeshVolume* AddVolumeWithID(int n1, int n2, int n3, int n4, int n5,
          //                                 int n12,int n23,int n34,int n41,
          //                                 int n15,int n25,int n35,int n45, int ID);
          int n5 = iSameNode;
          int n1,n4,n41,n15,n45;
          if(i0>0) { // reversed case
            n1 = ( n5 + 1 == nbBaseNodes ? 0 : n5 + 1 );
            n4 = ( n5 == 0 ? nbBaseNodes - 1 : n5 - 1 );
            n41 = n1 + 3;
            n15 = n5 + 3;
            n45 = n4 + 3;
          }
          else {
            n1 = ( n5 == 0 ? nbBaseNodes - 1 : n5 - 1 );
            n4 = ( n5 + 1 == nbBaseNodes ? 0 : n5 + 1 );
            n41 = n4 + 3;
            n15 = n1 + 3;
            n45 = n5 + 3;
          }
          aNewElem = aMesh->AddVolume(prevNod[n1], nextNod[n1],
                                      nextNod[n4], prevNod[n4], prevNod[n5],
                                      midlNod[n1], nextNod[n41],
                                      midlNod[n4], prevNod[n41],
                                      prevNod[n15], nextNod[n15],
                                      nextNod[n45], prevNod[n45]);
        }
        else if(nbSame==2) {
          // 2d order tetrahedron of 10 nodes
          //SMDS_MeshVolume* AddVolumeWithID(int n1, int n2, int n3, int n4,
          //                                 int n12,int n23,int n31,
          //                                 int n14,int n24,int n34, int ID);
          int n1 = iNotSameNode;
          int n2,n3,n12,n23,n31;
          if(i0>0) { // reversed case
            n2 = ( n1 == 0 ? nbBaseNodes - 1 : n1 - 1 );
            n3 = ( n1 + 1 == nbBaseNodes ? 0 : n1 + 1 );
            n12 = n2 + 3;
            n23 = n3 + 3;
            n31 = n1 + 3;
          }
          else {
            n2 = ( n1 + 1 == nbBaseNodes ? 0 : n1 + 1 );
            n3 = ( n1 == 0 ? nbBaseNodes - 1 : n1 - 1 );
            n12 = n1 + 3;
            n23 = n2 + 3;
            n31 = n3 + 3;
          }
          aNewElem = aMesh->AddVolume (prevNod[n1], prevNod[n2], prevNod[n3], nextNod[n1],
                                       prevNod[n12], prevNod[n23], prevNod[n31],
                                       midlNod[n1], nextNod[n12], nextNod[n31]);
        }
        break;
      }
      case 8: { // quadratic quadrangle
        if(nbSame==0) {
          // create hexahedron with 20 nodes
          if(i0>0) { // reversed case
            aNewElem = aMesh->AddVolume (prevNod[0], prevNod[3], prevNod[2], prevNod[1],
                                         nextNod[0], nextNod[3], nextNod[2], nextNod[1],
                                         prevNod[7], prevNod[6], prevNod[5], prevNod[4],
                                         nextNod[7], nextNod[6], nextNod[5], nextNod[4],
                                         midlNod[0], midlNod[3], midlNod[2], midlNod[1]);
          }
          else { // not reversed case
            aNewElem = aMesh->AddVolume (prevNod[0], prevNod[1], prevNod[2], prevNod[3],
                                         nextNod[0], nextNod[1], nextNod[2], nextNod[3],
                                         prevNod[4], prevNod[5], prevNod[6], prevNod[7],
                                         nextNod[4], nextNod[5], nextNod[6], nextNod[7],
                                         midlNod[0], midlNod[1], midlNod[2], midlNod[3]);
          }
        }
        else if(nbSame==1) { 
          // --- pyramid + pentahedron - can not be created since it is needed 
          // additional middle node ot the center of face
          INFOS( " Sweep for face " << elem->GetID() << " can not be created" );
          return;
        }
        else if(nbSame==2) {
          // 2d order Pentahedron with 15 nodes
          //SMDS_MeshVolume* AddVolumeWithID(int n1, int n2, int n3, int n4, int n5, int n6,
          //                                 int n12,int n23,int n31,int n45,int n56,int n64,
          //                                 int n14,int n25,int n36, int ID);
          int n1,n2,n4,n5;
          if ( prevNod[ iBeforeSame ] == nextNod[ iBeforeSame ] ) {
            // iBeforeSame is same too
            n1 = iBeforeSame;
            n2 = iOpposSame;
            n4 = iSameNode;
            n5 = iAfterSame;
          }
          else {
            // iAfterSame is same too
            n1 = iSameNode;
            n2 = iBeforeSame;
            n4 = iAfterSame;
            n5 = iOpposSame;
          }
          int n12,n45,n14,n25;
          if(i0>0) { //reversed case
            n12 = n1 + 4;
            n45 = n5 + 4;
            n14 = n4 + 4;
            n25 = n2 + 4;
          }
          else {
            n12 = n2 + 4;
            n45 = n4 + 4;
            n14 = n1 + 4;
            n25 = n5 + 4;
          }
          aNewElem = aMesh->AddVolume (prevNod[n1], prevNod[n2], nextNod[n2],
                                       prevNod[n4], prevNod[n5], nextNod[n5],
                                       prevNod[n12], midlNod[n2], nextNod[n12],
                                       prevNod[n45], midlNod[n5], nextNod[n45],
                                       prevNod[n14], prevNod[n25], nextNod[n25]);
        }
        break;
      }
      default: {
        // realized for extrusion only
        //vector<const SMDS_MeshNode*> polyedre_nodes (nbNodes*2 + 4*nbNodes);
        //vector<int> quantities (nbNodes + 2);

        //quantities[0] = nbNodes; // bottom of prism
        //for (int inode = 0; inode < nbNodes; inode++) {
        //  polyedre_nodes[inode] = prevNod[inode];
        //}

        //quantities[1] = nbNodes; // top of prism
        //for (int inode = 0; inode < nbNodes; inode++) {
        //  polyedre_nodes[nbNodes + inode] = nextNod[inode];
        //}

        //for (int iface = 0; iface < nbNodes; iface++) {
        //  quantities[iface + 2] = 4;
        //  int inextface = (iface == nbNodes - 1) ? 0 : iface + 1;
        //  polyedre_nodes[2*nbNodes + 4*iface + 0] = prevNod[iface];
        //  polyedre_nodes[2*nbNodes + 4*iface + 1] = prevNod[inextface];
        //  polyedre_nodes[2*nbNodes + 4*iface + 2] = nextNod[inextface];
        //  polyedre_nodes[2*nbNodes + 4*iface + 3] = nextNod[iface];
        //}
        //aNewElem = aMesh->AddPolyhedralVolume (polyedre_nodes, quantities);
        break;
      }
      }
    }

    if(!aNewElem) {
      // realized for extrusion only
      vector<const SMDS_MeshNode*> polyedre_nodes (nbNodes*2 + 4*nbNodes);
      vector<int> quantities (nbNodes + 2);

      quantities[0] = nbNodes; // bottom of prism
      for (int inode = 0; inode < nbNodes; inode++) {
        polyedre_nodes[inode] = prevNod[inode];
      }

      quantities[1] = nbNodes; // top of prism
      for (int inode = 0; inode < nbNodes; inode++) {
        polyedre_nodes[nbNodes + inode] = nextNod[inode];
      }

      for (int iface = 0; iface < nbNodes; iface++) {
        quantities[iface + 2] = 4;
        int inextface = (iface == nbNodes - 1) ? 0 : iface + 1;
        polyedre_nodes[2*nbNodes + 4*iface + 0] = prevNod[iface];
        polyedre_nodes[2*nbNodes + 4*iface + 1] = prevNod[inextface];
        polyedre_nodes[2*nbNodes + 4*iface + 2] = nextNod[inextface];
        polyedre_nodes[2*nbNodes + 4*iface + 3] = nextNod[iface];
      }
      aNewElem = aMesh->AddPolyhedralVolume (polyedre_nodes, quantities);
    }

    if ( aNewElem ) {
      newElems.push_back( aNewElem );
      myLastCreatedElems.Append(aNewElem);
      srcElements.Append( elem );
      lastElem = aNewElem;
    }

    // set new prev nodes
    for ( iNode = 0; iNode < nbNodes; iNode++ )
      prevNod[ iNode ] = nextNod[ iNode ];

  } // for steps
}
SMESH_MeshEditor::PGroupIDs SMESH_MeshEditor::Transform ( TIDSortedElemSet theElems,
const gp_Trsf &  theTrsf,
const bool  theCopy,
const bool  theMakeGroups,
SMESH_Mesh theTargetMesh = 0 
)

Move or copy theElements applying theTrsf to their nodes.

Parameters:
theElems- elements to transform, if theElems is empty then apply to all mesh nodes
theTrsf- transformation to apply
theCopy- if true, create translated copies of theElems
theMakeGroups- if true and theCopy, create translated groups
theTargetMesh- mesh to copy translated elements into
Returns:
SMESH_MeshEditor.PGroupIDs - list of ids of created groups

Definition at line 5311 of file SMESH_MeshEditor.cxx.

References SMESHDS_Mesh.AddNode(), SMESHDS_Mesh.AddPolygonalFace(), SMESHDS_Mesh.AddPolyhedralVolume(), SMESH_BelongToGeom.anIds, cast2Node, SMESHDS_Mesh.ChangeElementNodes(), SMESHDS_Mesh.ChangePolygonNodes(), SMESHDS_Mesh.ChangePolyhedronNodes(), SMDS_Mesh.elementsIterator(), SMDS_VtkVolume.GetFaceNode(), SMDS_MeshNode.GetInverseElementIterator(), SMDS_MeshElement.GetType(), SMDS_MeshElement.IsPoly(), SMDS_MeshElement.IsQuadratic(), MESSAGE, SMESHDS_Mesh.MoveNode(), SMDS_VtkVolume.NbFaceNodes(), SMDS_VtkVolume.NbFaces(), SMDS_MeshNode.NbInverseElements(), SMDS_MeshElement.NbNodes(), ex29_refine.node(), SMESH_AdvancedEditor.nodes, SMDS_MeshElement.nodesIterator(), SMDS_Mesh.nodesIterator(), SMDS_SpacePosition.originSpacePosition(), SMDSAbs_Face, SMDSAbs_Node, SMDSAbs_Volume, SMDS_MeshNode.X(), SMDS_MeshNode.Y(), and SMDS_MeshNode.Z().

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

  bool needReverse = false;
  string groupPostfix;
  switch ( theTrsf.Form() ) {
  case gp_PntMirror:
    MESSAGE("gp_PntMirror");
    needReverse = true;
    groupPostfix = "mirrored";
    break;
  case gp_Ax1Mirror:
    MESSAGE("gp_Ax1Mirror");
    groupPostfix = "mirrored";
    break;
  case gp_Ax2Mirror:
    MESSAGE("gp_Ax2Mirror");
    needReverse = true;
    groupPostfix = "mirrored";
    break;
  case gp_Rotation:
    MESSAGE("gp_Rotation");
    groupPostfix = "rotated";
    break;
  case gp_Translation:
    MESSAGE("gp_Translation");
    groupPostfix = "translated";
    break;
  case gp_Scale:
    MESSAGE("gp_Scale");
    groupPostfix = "scaled";
    break;
  case gp_CompoundTrsf: // different scale by axis
    MESSAGE("gp_CompoundTrsf");
    groupPostfix = "scaled";
    break;
  default:
    MESSAGE("default");
    needReverse = false;
    groupPostfix = "transformed";
  }

  SMESH_MeshEditor targetMeshEditor( theTargetMesh );
  SMESHDS_Mesh* aTgtMesh = theTargetMesh ? theTargetMesh->GetMeshDS() : 0;
  SMESHDS_Mesh* aMesh    = GetMeshDS();


  // map old node to new one
  TNodeNodeMap nodeMap;

  // elements sharing moved nodes; those of them which have all
  // nodes mirrored but are not in theElems are to be reversed
  TIDSortedElemSet inverseElemSet;

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

  // issue 021015: EDF 1578 SMESH: Free nodes are removed when translating a mesh
  TIDSortedElemSet orphanNode;

  if ( theElems.empty() ) // transform the whole mesh
  {
    // add all elements
    SMDS_ElemIteratorPtr eIt = aMesh->elementsIterator();
    while ( eIt->more() ) theElems.insert( eIt->next() );
    // add orphan nodes
    SMDS_NodeIteratorPtr nIt = aMesh->nodesIterator();
    while ( nIt->more() )
    {
      const SMDS_MeshNode* node = nIt->next();
      if ( node->NbInverseElements() == 0)
        orphanNode.insert( node );
    }
  }

  // loop on elements to transform nodes : first orphan nodes then elems
  TIDSortedElemSet::iterator itElem;
  TIDSortedElemSet *elements[] = {&orphanNode, &theElems };
  for (int i=0; i<2; i++)
  for ( itElem = elements[i]->begin(); itElem != elements[i]->end(); itElem++ ) {
    const SMDS_MeshElement* elem = *itElem;
    if ( !elem )
      continue;

    // loop on elem nodes
    SMDS_ElemIteratorPtr itN = elem->nodesIterator();
    while ( itN->more() ) {

      const SMDS_MeshNode* node = cast2Node( itN->next() );
      // check if a node has been already transformed
      pair<TNodeNodeMap::iterator,bool> n2n_isnew =
        nodeMap.insert( make_pair ( node, node ));
      if ( !n2n_isnew.second )
        continue;

      double coord[3];
      coord[0] = node->X();
      coord[1] = node->Y();
      coord[2] = node->Z();
      theTrsf.Transforms( coord[0], coord[1], coord[2] );
      if ( theTargetMesh ) {
        const SMDS_MeshNode * newNode = aTgtMesh->AddNode( coord[0], coord[1], coord[2] );
        n2n_isnew.first->second = newNode;
        myLastCreatedNodes.Append(newNode);
        srcNodes.Append( node );
      }
      else if ( theCopy ) {
        const SMDS_MeshNode * newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
        n2n_isnew.first->second = newNode;
        myLastCreatedNodes.Append(newNode);
        srcNodes.Append( node );
      }
      else {
        aMesh->MoveNode( node, coord[0], coord[1], coord[2] );
        // node position on shape becomes invalid
        const_cast< SMDS_MeshNode* > ( node )->SetPosition
          ( SMDS_SpacePosition::originSpacePosition() );
      }

      // keep inverse elements
      if ( !theCopy && !theTargetMesh && needReverse ) {
        SMDS_ElemIteratorPtr invElemIt = node->GetInverseElementIterator();
        while ( invElemIt->more() ) {
          const SMDS_MeshElement* iel = invElemIt->next();
          inverseElemSet.insert( iel );
        }
      }
    }
  }

  // either create new elements or reverse mirrored ones
  if ( !theCopy && !needReverse && !theTargetMesh )
    return PGroupIDs();

  TIDSortedElemSet::iterator invElemIt = inverseElemSet.begin();
  for ( ; invElemIt != inverseElemSet.end(); invElemIt++ )
    theElems.insert( *invElemIt );

  // replicate or reverse elements
  // TODO revoir ordre reverse vtk
  enum {
    REV_TETRA   = 0,  //  = nbNodes - 4
    REV_PYRAMID = 1,  //  = nbNodes - 4
    REV_PENTA   = 2,  //  = nbNodes - 4
    REV_FACE    = 3,
    REV_HEXA    = 4,  //  = nbNodes - 4
    FORWARD     = 5
  };
  int index[][8] = {
    { 2, 1, 0, 3, 4, 0, 0, 0 },  // REV_TETRA
    { 2, 1, 0, 3, 4, 0, 0, 0 },  // REV_PYRAMID
    { 2, 1, 0, 5, 4, 3, 0, 0 },  // REV_PENTA
    { 2, 1, 0, 3, 0, 0, 0, 0 },  // REV_FACE
    { 2, 1, 0, 3, 6, 5, 4, 7 },  // REV_HEXA
    { 0, 1, 2, 3, 4, 5, 6, 7 }   // FORWARD
  };

  for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
  {
    const SMDS_MeshElement* elem = *itElem;
    if ( !elem || elem->GetType() == SMDSAbs_Node )
      continue;

    int nbNodes = elem->NbNodes();
    int elemType = elem->GetType();

    if (elem->IsPoly()) {
      // Polygon or Polyhedral Volume
      switch ( elemType ) {
      case SMDSAbs_Face:
        {
          vector<const SMDS_MeshNode*> poly_nodes (nbNodes);
          int iNode = 0;
          SMDS_ElemIteratorPtr itN = elem->nodesIterator();
          while (itN->more()) {
            const SMDS_MeshNode* node =
              static_cast<const SMDS_MeshNode*>(itN->next());
            TNodeNodeMap::iterator nodeMapIt = nodeMap.find(node);
            if (nodeMapIt == nodeMap.end())
              break; // not all nodes transformed
            if (needReverse) {
              // reverse mirrored faces and volumes
              poly_nodes[nbNodes - iNode - 1] = (*nodeMapIt).second;
            } else {
              poly_nodes[iNode] = (*nodeMapIt).second;
            }
            iNode++;
          }
          if ( iNode != nbNodes )
            continue; // not all nodes transformed

          if ( theTargetMesh ) {
            myLastCreatedElems.Append(aTgtMesh->AddPolygonalFace(poly_nodes));
            srcElems.Append( elem );
          }
          else if ( theCopy ) {
            myLastCreatedElems.Append(aMesh->AddPolygonalFace(poly_nodes));
            srcElems.Append( elem );
          }
          else {
            aMesh->ChangePolygonNodes(elem, poly_nodes);
          }
        }
        break;
      case SMDSAbs_Volume:
        {
          // ATTENTION: Reversing is not yet done!!!
          const SMDS_VtkVolume* aPolyedre =
            dynamic_cast<const SMDS_VtkVolume*>( elem );
          if (!aPolyedre) {
            MESSAGE("Warning: bad volumic element");
            continue;
          }

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

          bool allTransformed = true;
          int nbFaces = aPolyedre->NbFaces();
          for (int iface = 1; iface <= nbFaces && allTransformed; iface++) {
            int nbFaceNodes = aPolyedre->NbFaceNodes(iface);
            for (int inode = 1; inode <= nbFaceNodes && allTransformed; inode++) {
              const SMDS_MeshNode* node = aPolyedre->GetFaceNode(iface, inode);
              TNodeNodeMap::iterator nodeMapIt = nodeMap.find(node);
              if (nodeMapIt == nodeMap.end()) {
                allTransformed = false; // not all nodes transformed
              } else {
                poly_nodes.push_back((*nodeMapIt).second);
              }
            }
            quantities.push_back(nbFaceNodes);
          }
          if ( !allTransformed )
            continue; // not all nodes transformed

          if ( theTargetMesh ) {
            myLastCreatedElems.Append(aTgtMesh->AddPolyhedralVolume(poly_nodes, quantities));
            srcElems.Append( elem );
          }
          else if ( theCopy ) {
            myLastCreatedElems.Append(aMesh->AddPolyhedralVolume(poly_nodes, quantities));
            srcElems.Append( elem );
          }
          else {
            aMesh->ChangePolyhedronNodes(elem, poly_nodes, quantities);
          }
        }
        break;
      default:;
      }
      continue;
    }

    // Regular elements
    int* i = index[ FORWARD ];
    if ( needReverse && nbNodes > 2) {// reverse mirrored faces and volumes
      if ( elemType == SMDSAbs_Face )
        i = index[ REV_FACE ];
      else
        i = index[ nbNodes - 4 ];
    }
    if(elem->IsQuadratic()) {
      static int anIds[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
      i = anIds;
      if(needReverse) {
        if(nbNodes==3) { // quadratic edge
          static int anIds[] = {1,0,2};
          i = anIds;
        }
        else if(nbNodes==6) { // quadratic triangle
          static int anIds[] = {0,2,1,5,4,3};
          i = anIds;
        }
        else if(nbNodes==8) { // quadratic quadrangle
          static int anIds[] = {0,3,2,1,7,6,5,4};
          i = anIds;
        }
        else if(nbNodes==10) { // quadratic tetrahedron of 10 nodes
          static int anIds[] = {0,2,1,3,6,5,4,7,9,8};
          i = anIds;
        }
        else if(nbNodes==13) { // quadratic pyramid of 13 nodes
          static int anIds[] = {0,3,2,1,4,8,7,6,5,9,12,11,10};
          i = anIds;
        }
        else if(nbNodes==15) { // quadratic pentahedron with 15 nodes
          static int anIds[] = {0,2,1,3,5,4,8,7,6,11,10,9,12,14,13};
          i = anIds;
        }
        else { // nbNodes==20 - quadratic hexahedron with 20 nodes
          static int anIds[] = {0,3,2,1,4,7,6,5,11,10,9,8,15,14,13,12,16,19,18,17};
          i = anIds;
        }
      }
    }

    // find transformed nodes
    vector<const SMDS_MeshNode*> nodes(nbNodes);
    int iNode = 0;
    SMDS_ElemIteratorPtr itN = elem->nodesIterator();
    while ( itN->more() ) {
      const SMDS_MeshNode* node =
        static_cast<const SMDS_MeshNode*>( itN->next() );
      TNodeNodeMap::iterator nodeMapIt = nodeMap.find( node );
      if ( nodeMapIt == nodeMap.end() )
        break; // not all nodes transformed
      nodes[ i [ iNode++ ]] = (*nodeMapIt).second;
    }
    if ( iNode != nbNodes )
      continue; // not all nodes transformed

    if ( theTargetMesh ) {
      if ( SMDS_MeshElement* copy =
           targetMeshEditor.AddElement( nodes, elem->GetType(), elem->IsPoly() )) {
        myLastCreatedElems.Append( copy );
        srcElems.Append( elem );
      }
    }
    else if ( theCopy ) {
      if ( AddElement( nodes, elem->GetType(), elem->IsPoly() ))
        srcElems.Append( elem );
    }
    else {
      // reverse element as it was reversed by transformation
      if ( nbNodes > 2 )
        aMesh->ChangeElementNodes( elem, &nodes[0], nbNodes );
    }
  }

  PGroupIDs newGroupIDs;

  if ( ( theMakeGroups && theCopy ) ||
       ( theMakeGroups && theTargetMesh ) )
    newGroupIDs = generateGroups( srcNodes, srcElems, groupPostfix, theTargetMesh );

  return newGroupIDs;
}
bool SMESH_MeshEditor.TriToQuad ( TIDSortedElemSet theElems,
SMESH::Controls::NumericalFunctorPtr  theCriterion,
const double  theMaxAngle 
)

Fuse neighbour triangles into quadrangles.

Parameters:
theElems- The triangles to be fused.
theCriterion- Is used to choose a neighbour to fuse with.
theMaxAngle- Is a max angle between element normals at which fusion is still performed; theMaxAngle is mesured in radians.
Returns:
bool - Success or not.
void SMESH_MeshEditor::UpdateVolumes ( const SMDS_MeshNode theBetweenNode1,
const SMDS_MeshNode theBetweenNode2,
std::list< const SMDS_MeshNode * > &  theNodesToInsert 
)

Definition at line 9139 of file SMESH_MeshEditor.cxx.

References SMESHDS_Mesh.AddPolyhedralVolume(), SMESHDS_Mesh.ChangePolyhedronNodes(), SMDS_VolumeTool.GetFaceNodes(), SMDS_MeshNode.GetInverseElementIterator(), SMDS_VolumeTool.IsLinked(), SMDS_MeshElement.IsPoly(), SMDS_VolumeTool.NbFaceNodes(), SMDS_VolumeTool.NbFaces(), SMESHDS_Mesh.RemoveElement(), SMESHDS_Mesh.SetMeshElementOnShape(), and SMDSAbs_Volume.

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

  SMDS_ElemIteratorPtr invElemIt = theBetweenNode1->GetInverseElementIterator(SMDSAbs_Volume);
  while (invElemIt->more()) { // loop on inverse elements of theBetweenNode1
    const SMDS_MeshElement* elem = invElemIt->next();

    // check, if current volume has link theBetweenNode1 - theBetweenNode2
    SMDS_VolumeTool aVolume (elem);
    if (!aVolume.IsLinked(theBetweenNode1, theBetweenNode2))
      continue;

    // insert new nodes in all faces of the volume, sharing link theBetweenNode1 - theBetweenNode2
    int iface, nbFaces = aVolume.NbFaces();
    vector<const SMDS_MeshNode *> poly_nodes;
    vector<int> quantities (nbFaces);

    for (iface = 0; iface < nbFaces; iface++) {
      int nbFaceNodes = aVolume.NbFaceNodes(iface), nbInserted = 0;
      // faceNodes will contain (nbFaceNodes + 1) nodes, last = first
      const SMDS_MeshNode** faceNodes = aVolume.GetFaceNodes(iface);

      for (int inode = 0; inode < nbFaceNodes; inode++) {
        poly_nodes.push_back(faceNodes[inode]);

        if (nbInserted == 0) {
          if (faceNodes[inode] == theBetweenNode1) {
            if (faceNodes[inode + 1] == theBetweenNode2) {
              nbInserted = theNodesToInsert.size();

              // add nodes to insert
              list<const SMDS_MeshNode*>::iterator nIt = theNodesToInsert.begin();
              for (; nIt != theNodesToInsert.end(); nIt++) {
                poly_nodes.push_back(*nIt);
              }
            }
          }
          else if (faceNodes[inode] == theBetweenNode2) {
            if (faceNodes[inode + 1] == theBetweenNode1) {
              nbInserted = theNodesToInsert.size();

              // add nodes to insert in reversed order
              list<const SMDS_MeshNode*>::iterator nIt = theNodesToInsert.end();
              nIt--;
              for (; nIt != theNodesToInsert.begin(); nIt--) {
                poly_nodes.push_back(*nIt);
              }
              poly_nodes.push_back(*nIt);
            }
          }
          else {
          }
        }
      }
      quantities[iface] = nbFaceNodes + nbInserted;
    }

    // Replace or update the volume
    SMESHDS_Mesh *aMesh = GetMeshDS();

    if (elem->IsPoly()) {
      aMesh->ChangePolyhedronNodes(elem, poly_nodes, quantities);

    }
    else {
      int aShapeId = FindShape( elem );

      SMDS_MeshElement* newElem =
        aMesh->AddPolyhedralVolume(poly_nodes, quantities);
      myLastCreatedElems.Append(newElem);
      if (aShapeId && newElem)
        aMesh->SetMeshElementOnShape(newElem, aShapeId);

      aMesh->RemoveElement(elem);
    }
  }
}

Field Documentation

SMESH_SequenceOfElemPtr SMESH_MeshEditor.myLastCreatedElems [private]

Sequence for keeping elements created during last operation.

Definition at line 707 of file SMESH_MeshEditor.hxx.

SMESH_SequenceOfElemPtr SMESH_MeshEditor.myLastCreatedNodes [private]

Sequence for keeping nodes created during last operation.

Definition at line 702 of file SMESH_MeshEditor.hxx.

Definition at line 697 of file SMESH_MeshEditor.hxx.

Copyright © 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE
Copyright © 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS