X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSMESH%2FSMESH_MeshEditor.cxx;h=14ea394da07e837d9c9386af91e7776485225452;hb=19d95d14264fe00d3640126f912287dbc38f972c;hp=3ace850f359b990791c4f94da9dd860d5f23f8d1;hpb=9d11375af40826e967ab2c3bcb77d1f9d439c90c;p=modules%2Fsmesh.git diff --git a/src/SMESH/SMESH_MeshEditor.cxx b/src/SMESH/SMESH_MeshEditor.cxx index 3ace850f3..14ea394da 100644 --- a/src/SMESH/SMESH_MeshEditor.cxx +++ b/src/SMESH/SMESH_MeshEditor.cxx @@ -35,6 +35,7 @@ #include "SMDS_FacePosition.hxx" #include "SMDS_SpacePosition.hxx" #include "SMDS_QuadraticFaceOfNodes.hxx" +#include "SMDS_MeshGroup.hxx" #include "SMESHDS_Group.hxx" #include "SMESHDS_Mesh.hxx" @@ -42,56 +43,194 @@ #include "SMESH_subMesh.hxx" #include "SMESH_ControlsDef.hxx" #include "SMESH_MesherHelper.hxx" +#include "SMESH_OctreeNode.hxx" +#include "SMESH_Group.hxx" #include "utilities.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include +#include #include #include +#include #include -#include +#include +#include #include +#include +#include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include + +#define cast2Node(elem) static_cast( elem ) using namespace std; using namespace SMESH::Controls; typedef map > TElemOfNodeListMap; typedef map > TElemOfElemListMap; -typedef map > TNodeOfNodeListMap; -typedef TNodeOfNodeListMap::iterator TNodeOfNodeListMapItr; //typedef map > TNodeOfNodeVecMap; //typedef TNodeOfNodeVecMap::iterator TNodeOfNodeVecMapItr; -typedef map > TElemOfVecOfNnlmiMap; //typedef map > TElemOfVecOfMapNodesMap; -typedef pair< const SMDS_MeshNode*, const SMDS_MeshNode* > NLink; +struct TNodeXYZ : public gp_XYZ { + TNodeXYZ( const SMDS_MeshNode* n ):gp_XYZ( n->X(), n->Y(), n->Z() ) {} +}; //======================================================================= //function : SMESH_MeshEditor //purpose : //======================================================================= -SMESH_MeshEditor::SMESH_MeshEditor( SMESH_Mesh* theMesh ): -myMesh( theMesh ) +SMESH_MeshEditor::SMESH_MeshEditor( SMESH_Mesh* theMesh ) + :myMesh( theMesh ) // theMesh may be NULL +{ +} + +//======================================================================= +/*! + * \brief Add element + */ +//======================================================================= + +SMDS_MeshElement* +SMESH_MeshEditor::AddElement(const vector & node, + const SMDSAbs_ElementType type, + const bool isPoly, + const int ID) +{ + SMDS_MeshElement* e = 0; + int nbnode = node.size(); + SMESHDS_Mesh* mesh = GetMeshDS(); + switch ( type ) { + case SMDSAbs_Edge: + if ( nbnode == 2 ) + if ( ID ) e = mesh->AddEdgeWithID(node[0], node[1], ID); + else e = mesh->AddEdge (node[0], node[1] ); + else if ( nbnode == 3 ) + if ( ID ) e = mesh->AddEdgeWithID(node[0], node[1], node[2], ID); + else e = mesh->AddEdge (node[0], node[1], node[2] ); + break; + case SMDSAbs_Face: + if ( !isPoly ) { + if (nbnode == 3) + if ( ID ) e = mesh->AddFaceWithID(node[0], node[1], node[2], ID); + else e = mesh->AddFace (node[0], node[1], node[2] ); + else if (nbnode == 4) + if ( ID ) e = mesh->AddFaceWithID(node[0], node[1], node[2], node[3], ID); + else e = mesh->AddFace (node[0], node[1], node[2], node[3] ); + else if (nbnode == 6) + if ( ID ) e = mesh->AddFaceWithID(node[0], node[1], node[2], node[3], + node[4], node[5], ID); + else e = mesh->AddFace (node[0], node[1], node[2], node[3], + node[4], node[5] ); + else if (nbnode == 8) + if ( ID ) e = mesh->AddFaceWithID(node[0], node[1], node[2], node[3], + node[4], node[5], node[6], node[7], ID); + else e = mesh->AddFace (node[0], node[1], node[2], node[3], + node[4], node[5], node[6], node[7] ); + } else { + if ( ID ) e = mesh->AddPolygonalFaceWithID(node, ID); + else e = mesh->AddPolygonalFace (node ); + } + break; + case SMDSAbs_Volume: + if ( !isPoly ) { + if (nbnode == 4) + if ( ID ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], ID); + else e = mesh->AddVolume (node[0], node[1], node[2], node[3] ); + else if (nbnode == 5) + if ( ID ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], + node[4], ID); + else e = mesh->AddVolume (node[0], node[1], node[2], node[3], + node[4] ); + else if (nbnode == 6) + if ( ID ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], + node[4], node[5], ID); + else e = mesh->AddVolume (node[0], node[1], node[2], node[3], + node[4], node[5] ); + else if (nbnode == 8) + if ( ID ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], + node[4], node[5], node[6], node[7], ID); + else e = mesh->AddVolume (node[0], node[1], node[2], node[3], + node[4], node[5], node[6], node[7] ); + else if (nbnode == 10) + if ( ID ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], + node[4], node[5], node[6], node[7], + node[8], node[9], ID); + else e = mesh->AddVolume (node[0], node[1], node[2], node[3], + node[4], node[5], node[6], node[7], + node[8], node[9] ); + else if (nbnode == 13) + if ( ID ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], + node[4], node[5], node[6], node[7], + node[8], node[9], node[10],node[11], + node[12],ID); + else e = mesh->AddVolume (node[0], node[1], node[2], node[3], + node[4], node[5], node[6], node[7], + node[8], node[9], node[10],node[11], + node[12] ); + else if (nbnode == 15) + if ( ID ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], + node[4], node[5], node[6], node[7], + node[8], node[9], node[10],node[11], + node[12],node[13],node[14],ID); + else e = mesh->AddVolume (node[0], node[1], node[2], node[3], + node[4], node[5], node[6], node[7], + node[8], node[9], node[10],node[11], + node[12],node[13],node[14] ); + else if (nbnode == 20) + if ( ID ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], + node[4], node[5], node[6], node[7], + node[8], node[9], node[10],node[11], + node[12],node[13],node[14],node[15], + node[16],node[17],node[18],node[19],ID); + else e = mesh->AddVolume (node[0], node[1], node[2], node[3], + node[4], node[5], node[6], node[7], + node[8], node[9], node[10],node[11], + node[12],node[13],node[14],node[15], + node[16],node[17],node[18],node[19] ); + } + } + return e; +} + +//======================================================================= +/*! + * \brief Add element + */ +//======================================================================= + +SMDS_MeshElement* SMESH_MeshEditor::AddElement(const vector & nodeIDs, + const SMDSAbs_ElementType type, + const bool isPoly, + const int ID) { + vector nodes; + nodes.reserve( nodeIDs.size() ); + vector::const_iterator id = nodeIDs.begin(); + while ( id != nodeIDs.end() ) { + if ( const SMDS_MeshNode* node = GetMeshDS()->FindNode( *id++ )) + nodes.push_back( node ); + else + return 0; + } + return AddElement( nodes, type, isPoly, ID ); } //======================================================================= @@ -119,18 +258,26 @@ bool SMESH_MeshEditor::Remove (const list< int >& theIDs, if ( !elem ) continue; - // Find sub-meshes to notify about modification - SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator(); - while ( nodeIt->more() ) { - const SMDS_MeshNode* node = static_cast( nodeIt->next() ); - const SMDS_PositionPtr& aPosition = node->GetPosition(); - if ( aPosition.get() ) { - if ( int aShapeID = aPosition->GetShapeId() ) { + // Notify VERTEX sub-meshes about modification + if ( isNodes ) { + const SMDS_MeshNode* node = cast2Node( elem ); + if ( node->GetPosition()->GetTypeOfPosition() == SMDS_TOP_VERTEX ) + if ( int aShapeID = node->GetPosition()->GetShapeId() ) if ( SMESH_subMesh * sm = GetMesh()->GetSubMeshContaining( aShapeID ) ) smmap.insert( sm ); - } - } } + // Find sub-meshes to notify about modification +// SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator(); +// while ( nodeIt->more() ) { +// const SMDS_MeshNode* node = static_cast( nodeIt->next() ); +// const SMDS_PositionPtr& aPosition = node->GetPosition(); +// if ( aPosition.get() ) { +// if ( int aShapeID = aPosition->GetShapeId() ) { +// if ( SMESH_subMesh * sm = GetMesh()->GetSubMeshContaining( aShapeID ) ) +// smmap.insert( sm ); +// } +// } +// } // Do remove if ( isNodes ) @@ -146,9 +293,9 @@ bool SMESH_MeshEditor::Remove (const list< int >& theIDs, (*smIt)->ComputeStateEngine( SMESH_subMesh::MESH_ENTITY_REMOVED ); } - // Check if the whole mesh becomes empty - if ( SMESH_subMesh * sm = GetMesh()->GetSubMeshContaining( 1 ) ) - sm->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE ); +// // Check if the whole mesh becomes empty +// if ( SMESH_subMesh * sm = GetMesh()->GetSubMeshContaining( 1 ) ) +// sm->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE ); return true; } @@ -216,19 +363,17 @@ int SMESH_MeshEditor::FindShape (const SMDS_MeshElement * theElem) //======================================================================= //function : IsMedium -//purpose : +//purpose : //======================================================================= bool SMESH_MeshEditor::IsMedium(const SMDS_MeshNode* node, const SMDSAbs_ElementType typeToCheck) { bool isMedium = false; - SMDS_ElemIteratorPtr it = node->GetInverseElementIterator(); - while (it->more()) { + SMDS_ElemIteratorPtr it = node->GetInverseElementIterator(typeToCheck); + while (it->more() && !isMedium ) { const SMDS_MeshElement* elem = it->next(); isMedium = elem->IsMediumNode(node); - if ( typeToCheck == SMDSAbs_All || elem->GetType() == typeToCheck ) - break; } return isMedium; } @@ -301,7 +446,7 @@ static bool GetNodesFromTwoTria(const SMDS_MeshElement * theTria1, ShiftNodesQuadTria(N2); } // now we receive following N1 and N2 (using numeration as above image) - // tria1 : (1 2 4 5 9 7) and tria2 : (3 4 2 8 9 6) + // 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 return true; } @@ -338,7 +483,7 @@ bool SMESH_MeshEditor::InverseDiag (const SMDS_MeshElement * theTria1, SMDS_ElemIteratorPtr it = theTria1->nodesIterator(); while ( it->more() ) { aNodes[ i ] = static_cast( it->next() ); - + if ( i > 2 ) // theTria2 // find same node of theTria1 for ( int j = 0; j < 3; j++ ) @@ -357,7 +502,7 @@ bool SMESH_MeshEditor::InverseDiag (const SMDS_MeshElement * theTria1, 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++ ) { @@ -378,14 +523,14 @@ bool SMESH_MeshEditor::InverseDiag (const SMDS_MeshElement * theTria1, aNodes[ sameInd[ iB ]] = aNodes[ i1 ]; //MESSAGE( theTria1 << theTria2 ); - + GetMeshDS()->ChangeElementNodes( theTria1, aNodes, 3 ); GetMeshDS()->ChangeElementNodes( theTria2, &aNodes[ 3 ], 3 ); - + //MESSAGE( theTria1 << theTria2 ); return true; - + } // end if(F1 && F2) // check case of quadratic faces @@ -399,19 +544,19 @@ bool SMESH_MeshEditor::InverseDiag (const SMDS_MeshElement * theTria1, // 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 + // 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) + // 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]; @@ -450,17 +595,16 @@ static bool findTriangles(const SMDS_MeshNode * theNode1, theTria1 = theTria2 = 0; set< const SMDS_MeshElement* > emap; - SMDS_ElemIteratorPtr it = theNode1->GetInverseElementIterator(); + SMDS_ElemIteratorPtr it = theNode1->GetInverseElementIterator(SMDSAbs_Face); while (it->more()) { const SMDS_MeshElement* elem = it->next(); - if ( elem->GetType() == SMDSAbs_Face && elem->NbNodes() == 3 ) + if ( elem->NbNodes() == 3 ) emap.insert( elem ); } - it = theNode2->GetInverseElementIterator(); + it = theNode2->GetInverseElementIterator(SMDSAbs_Face); while (it->more()) { const SMDS_MeshElement* elem = it->next(); - if ( elem->GetType() == SMDSAbs_Face && - emap.find( elem ) != emap.end() ) + if ( emap.find( elem ) != emap.end() ) if ( theTria1 ) { // theTria1 must be element with minimum ID if( theTria1->GetID() < elem->GetID() ) { @@ -530,7 +674,7 @@ bool SMESH_MeshEditor::InverseDiag (const SMDS_MeshNode * theNode1, 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; @@ -546,7 +690,7 @@ bool SMESH_MeshEditor::InverseDiag (const SMDS_MeshNode * theNode1, GetMeshDS()->ChangeElementNodes( tr2, aNodes2, 3 ); //MESSAGE( tr1 << tr2 ); - + return true; } @@ -579,9 +723,8 @@ bool getQuadrangleNodes(const SMDS_MeshNode * theQuadNodes [], const SMDS_MeshNode* n4 = 0; SMDS_ElemIteratorPtr it = tr2->nodesIterator(); int i=0; - //while ( !n4 && it->more() ) { while ( !n4 && i<3 ) { - const SMDS_MeshNode * n = static_cast( it->next() ); + const SMDS_MeshNode * n = cast2Node( it->next() ); i++; bool isDiag = ( n == theNode1 || n == theNode2 ); if ( !isDiag ) @@ -591,9 +734,8 @@ bool getQuadrangleNodes(const SMDS_MeshNode * theQuadNodes [], int iNode = 0, iFirstDiag = -1; it = tr1->nodesIterator(); i=0; - //while ( it->more() ) { while ( i<3 ) { - const SMDS_MeshNode * n = static_cast( it->next() ); + const SMDS_MeshNode * n = cast2Node( it->next() ); i++; bool isDiag = ( n == theNode1 || n == theNode2 ); if ( isDiag ) { @@ -664,19 +806,19 @@ bool SMESH_MeshEditor::DeleteDiag (const SMDS_MeshNode * theNode1, // 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 + // 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) + // 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]; @@ -767,13 +909,13 @@ bool SMESH_MeshEditor::Reorient (const SMDS_MeshElement * theElem) for (int iface = 1; iface <= nbFaces; iface++) { int inode, nbFaceNodes = aPolyedre->NbFaceNodes(iface); quantities[iface - 1] = nbFaceNodes; - + for (inode = nbFaceNodes; inode >= 1; inode--) { const SMDS_MeshNode* curNode = aPolyedre->GetFaceNode(iface, inode); poly_nodes.push_back(curNode); } } - + return GetMeshDS()->ChangePolyhedronNodes( theElem, poly_nodes, quantities ); } @@ -812,7 +954,7 @@ static double getBadRate (const SMDS_MeshElement* theElem, // theCrit is used to select a diagonal to cut //======================================================================= -bool SMESH_MeshEditor::QuadToTri (map & theElems, +bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet & theElems, SMESH::Controls::NumericalFunctorPtr theCrit) { myLastCreatedElems.Clear(); @@ -828,9 +970,9 @@ bool SMESH_MeshEditor::QuadToTri (map & theElems, Handle(Geom_Surface) surface; SMESH_MesherHelper helper( *GetMesh() ); - map::iterator itElem; + TIDSortedElemSet::iterator itElem; for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) { - const SMDS_MeshElement* elem = (*itElem).second; + const SMDS_MeshElement* elem = *itElem; if ( !elem || elem->GetType() != SMDSAbs_Face ) continue; if ( elem->NbNodes() != ( elem->IsQuadratic() ? 8 : 4 )) @@ -899,7 +1041,7 @@ bool SMESH_MeshEditor::QuadToTri (map & theElems, 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; @@ -1016,7 +1158,7 @@ void SMESH_MeshEditor::AddToSameGroups (const SMDS_MeshElement* elemToAdd, set::const_iterator grIt = groups.begin(); for ( ; grIt != groups.end(); grIt++ ) { SMESHDS_Group* group = dynamic_cast( *grIt ); - if ( group && group->SMDSGroup().Contains( elemInGroups )) + if ( group && group->Contains( elemInGroups )) group->SMDSGroup().Add( elemToAdd ); } } @@ -1030,10 +1172,10 @@ void SMESH_MeshEditor::RemoveElemFromGroups (const SMDS_MeshElement* removeelem, SMESHDS_Mesh * aMesh) { const set& groups = aMesh->GetGroups(); - if (!groups.empty()) + if (!groups.empty()) { set::const_iterator GrIt = groups.begin(); - for (; GrIt != groups.end(); GrIt++) + for (; GrIt != groups.end(); GrIt++) { SMESHDS_Group* grp = dynamic_cast(*GrIt); if (!grp || grp->IsEmpty()) continue; @@ -1049,8 +1191,8 @@ void SMESH_MeshEditor::RemoveElemFromGroups (const SMDS_MeshElement* removeelem, // theCrit is used to select a diagonal to cut //======================================================================= -bool SMESH_MeshEditor::QuadToTri (std::map & theElems, - const bool the13Diag) +bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet & theElems, + const bool the13Diag) { myLastCreatedElems.Clear(); myLastCreatedNodes.Clear(); @@ -1062,9 +1204,9 @@ bool SMESH_MeshEditor::QuadToTri (std::map & theEle Handle(Geom_Surface) surface; SMESH_MesherHelper helper( *GetMesh() ); - map::iterator itElem; + TIDSortedElemSet::iterator itElem; for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) { - const SMDS_MeshElement* elem = (*itElem).second; + const SMDS_MeshElement* elem = *itElem; if ( !elem || elem->GetType() != SMDSAbs_Face ) continue; bool isquad = elem->NbNodes()==4 || elem->NbNodes()==8; @@ -1124,7 +1266,7 @@ bool SMESH_MeshEditor::QuadToTri (std::map & theEle aNodes[ i-1 ]->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE ) { inFaceNode = aNodes[ i-1 ]; - } + } } // find middle point for (0,1,2,3) @@ -1284,7 +1426,7 @@ class LinkID_Gen { // fusion is still performed. //======================================================================= -bool SMESH_MeshEditor::TriToQuad (map & theElems, +bool SMESH_MeshEditor::TriToQuad (TIDSortedElemSet & theElems, SMESH::Controls::NumericalFunctorPtr theCrit, const double theMaxAngle) { @@ -1297,27 +1439,19 @@ bool SMESH_MeshEditor::TriToQuad (map & theEl return false; SMESHDS_Mesh * aMesh = GetMeshDS(); - //LinkID_Gen aLinkID_Gen( aMesh ); // Prepare data for algo: build // 1. map of elements with their linkIDs // 2. map of linkIDs with their elements - //map< long, list< const SMDS_MeshElement* > > mapLi_listEl; - //map< long, list< const SMDS_MeshElement* > >::iterator itLE; - //map< const SMDS_MeshElement*, set< long > > mapEl_setLi; - //map< const SMDS_MeshElement*, set< long > >::iterator itEL; - - map< NLink, list< const SMDS_MeshElement* > > mapLi_listEl; - map< NLink, list< const SMDS_MeshElement* > >::iterator itLE; - map< const SMDS_MeshElement*, set< NLink > > mapEl_setLi; - map< const SMDS_MeshElement*, set< NLink > >::iterator itEL; + map< SMESH_TLink, list< const SMDS_MeshElement* > > mapLi_listEl; + map< SMESH_TLink, list< const SMDS_MeshElement* > >::iterator itLE; + map< const SMDS_MeshElement*, set< SMESH_TLink > > mapEl_setLi; + map< const SMDS_MeshElement*, set< SMESH_TLink > >::iterator itEL; - map::iterator itElem; + TIDSortedElemSet::iterator itElem; for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) { - const SMDS_MeshElement* elem = (*itElem).second; - //if ( !elem || elem->NbNodes() != 3 ) - // continue; + const SMDS_MeshElement* elem = *itElem; if(!elem || elem->GetType() != SMDSAbs_Face ) continue; bool IsTria = elem->NbNodes()==3 || (elem->NbNodes()==6 && elem->IsQuadratic()); if(!IsTria) continue; @@ -1326,19 +1460,14 @@ bool SMESH_MeshEditor::TriToQuad (map & theEl const SMDS_MeshNode* aNodes [4]; SMDS_ElemIteratorPtr itN = elem->nodesIterator(); int i = 0; - //while ( itN->more() ) while ( i<3 ) - aNodes[ i++ ] = static_cast( itN->next() ); - ASSERT( i == 3 ); + aNodes[ i++ ] = cast2Node( itN->next() ); aNodes[ 3 ] = aNodes[ 0 ]; // fill maps for ( i = 0; i < 3; i++ ) { - //long linkID = aLinkID_Gen.GetLinkID( aNodes[ i ], aNodes[ i+1 ] ); - NLink link(( aNodes[i] < aNodes[i+1] ? aNodes[i] : aNodes[i+1] ), - ( aNodes[i] < aNodes[i+1] ? aNodes[i+1] : aNodes[i] )); + SMESH_TLink link( aNodes[i], aNodes[i+1] ); // check if elements sharing a link can be fused - //itLE = mapLi_listEl.find( linkID ); itLE = mapLi_listEl.find( link ); if ( itLE != mapLi_listEl.end() ) { if ((*itLE).second.size() > 1 ) // consider only 2 elems adjacent by a link @@ -1351,10 +1480,8 @@ bool SMESH_MeshEditor::TriToQuad (map & theEl (*itLE).second.push_back( elem ); } else { - //mapLi_listEl[ linkID ].push_back( elem ); mapLi_listEl[ link ].push_back( elem ); } - //mapEl_setLi [ elem ].insert( linkID ); mapEl_setLi [ elem ].insert( link ); } } @@ -1365,8 +1492,7 @@ bool SMESH_MeshEditor::TriToQuad (map & theEl int nbElems = (*itLE).second.size(); if ( nbElems < 2 ) { const SMDS_MeshElement* elem = (*itLE).second.front(); - //long link = (*itLE).first; - NLink link = (*itLE).first; + SMESH_TLink link = (*itLE).first; mapEl_setLi[ elem ].erase( link ); if ( mapEl_setLi[ elem ].empty() ) mapEl_setLi.erase( elem ); @@ -1378,7 +1504,6 @@ bool SMESH_MeshEditor::TriToQuad (map & theEl while ( ! mapEl_setLi.empty() ) { // Look for the start element: // the element having the least nb of shared links - const SMDS_MeshElement* startElem = 0; int minNbLinks = 4; for ( itEL = mapEl_setLi.begin(); itEL != mapEl_setLi.end(); itEL++ ) { @@ -1393,13 +1518,11 @@ bool SMESH_MeshEditor::TriToQuad (map & theEl // search elements to fuse starting from startElem or links of elements // fused earlyer - startLinks - //list< long > startLinks; - list< NLink > startLinks; + list< SMESH_TLink > startLinks; while ( startElem || !startLinks.empty() ) { while ( !startElem && !startLinks.empty() ) { // Get an element to start, by a link - //long linkId = startLinks.front(); - NLink linkId = startLinks.front(); + SMESH_TLink linkId = startLinks.front(); startLinks.pop_front(); itLE = mapLi_listEl.find( linkId ); if ( itLE != mapLi_listEl.end() ) { @@ -1415,19 +1538,16 @@ bool SMESH_MeshEditor::TriToQuad (map & theEl if ( startElem ) { // Get candidates to be fused const SMDS_MeshElement *tr1 = startElem, *tr2 = 0, *tr3 = 0; - //long link12, link13; - NLink link12, link13; + const SMESH_TLink *link12, *link13; startElem = 0; ASSERT( mapEl_setLi.find( tr1 ) != mapEl_setLi.end() ); - //set< long >& setLi = mapEl_setLi[ tr1 ]; - set< NLink >& setLi = mapEl_setLi[ tr1 ]; + set< SMESH_TLink >& setLi = mapEl_setLi[ tr1 ]; ASSERT( !setLi.empty() ); - //set< long >::iterator itLi; - set< NLink >::iterator itLi; - for ( itLi = setLi.begin(); itLi != setLi.end(); itLi++ ) { - //long linkID = (*itLi); - NLink linkID = (*itLi); - itLE = mapLi_listEl.find( linkID ); + set< SMESH_TLink >::iterator itLi; + for ( itLi = setLi.begin(); itLi != setLi.end(); itLi++ ) + { + const SMESH_TLink & link = (*itLi); + itLE = mapLi_listEl.find( link ); if ( itLE == mapLi_listEl.end() ) continue; @@ -1439,50 +1559,36 @@ bool SMESH_MeshEditor::TriToQuad (map & theEl continue; if ( tr2 ) { tr3 = elem; - link13 = linkID; + link13 = &link; } else { tr2 = elem; - link12 = linkID; + link12 = &link; } // add other links of elem to list of links to re-start from - //set< long >& links = mapEl_setLi[ elem ]; - //set< long >::iterator it; - set< NLink >& links = mapEl_setLi[ elem ]; - set< NLink >::iterator it; + set< SMESH_TLink >& links = mapEl_setLi[ elem ]; + set< SMESH_TLink >::iterator it; for ( it = links.begin(); it != links.end(); it++ ) { - //long linkID2 = (*it); - NLink linkID2 = (*it); - if ( linkID2 != linkID ) - startLinks.push_back( linkID2 ); + const SMESH_TLink& link2 = (*it); + if ( link2 != link ) + startLinks.push_back( link2 ); } } // Get nodes of possible quadrangles const SMDS_MeshNode *n12 [4], *n13 [4]; bool Ok12 = false, Ok13 = false; - //const SMDS_MeshNode *linkNode1, *linkNode2; const SMDS_MeshNode *linkNode1, *linkNode2; if(tr2) { - //const SMDS_MeshNode *linkNode1 = link12.first; - //const SMDS_MeshNode *linkNode2 = link12.second; - linkNode1 = link12.first; - linkNode2 = link12.second; - //if ( tr2 && - // aLinkID_Gen.GetNodes( link12, linkNode1, linkNode2 ) && - // getQuadrangleNodes( n12, linkNode1, linkNode2, tr1, tr2 )) - // Ok12 = true; + linkNode1 = link12->first; + linkNode2 = link12->second; if ( tr2 && getQuadrangleNodes( n12, linkNode1, linkNode2, tr1, tr2 )) Ok12 = true; } if(tr3) { - linkNode1 = link13.first; - linkNode2 = link13.second; - //if ( tr3 && - // aLinkID_Gen.GetNodes( link13, linkNode1, linkNode2 ) && - // getQuadrangleNodes( n13, linkNode1, linkNode2, tr1, tr3 )) - // Ok13 = true; + linkNode1 = link13->first; + linkNode2 = link13->second; if ( tr3 && getQuadrangleNodes( n13, linkNode1, linkNode2, tr1, tr3 )) Ok13 = true; } @@ -1504,7 +1610,7 @@ bool SMESH_MeshEditor::TriToQuad (map & theEl mapEl_setLi.erase( tr1 ); if ( Ok12 ) { mapEl_setLi.erase( tr2 ); - mapLi_listEl.erase( link12 ); + mapLi_listEl.erase( *link12 ); if(tr1->NbNodes()==3) { if( tr1->GetID() < tr2->GetID() ) { aMesh->ChangeElementNodes( tr1, n12, 4 ); @@ -1522,7 +1628,7 @@ bool SMESH_MeshEditor::TriToQuad (map & theEl const SMDS_MeshNode* N2 [6]; GetNodesFromTwoTria(tr1,tr2,N1,N2); // now we receive following N1 and N2 (using numeration as above image) - // tria1 : (1 2 4 5 9 7) and tria2 : (3 4 2 8 9 6) + // 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]; @@ -1549,7 +1655,7 @@ bool SMESH_MeshEditor::TriToQuad (map & theEl } else if ( Ok13 ) { mapEl_setLi.erase( tr3 ); - mapLi_listEl.erase( link13 ); + mapLi_listEl.erase( *link13 ); if(tr1->NbNodes()==3) { if( tr1->GetID() < tr2->GetID() ) { aMesh->ChangeElementNodes( tr1, n13, 4 ); @@ -1567,7 +1673,7 @@ bool SMESH_MeshEditor::TriToQuad (map & theEl const SMDS_MeshNode* N2 [6]; GetNodesFromTwoTria(tr1,tr3,N1,N2); // now we receive following N1 and N2 (using numeration as above image) - // tria1 : (1 2 4 5 9 7) and tria2 : (3 4 2 8 9 6) + // 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]; @@ -1884,6 +1990,55 @@ bool SMESH_MeshEditor::SortHexaNodes (const SMDS_Mesh * theMesh, return true; }*/ +//================================================================================ +/*! + * \brief Return nodes linked to the given one + * \param theNode - the node + * \param linkedNodes - the found nodes + * \param type - the type of elements to check + * + * Medium nodes are ignored + */ +//================================================================================ + +void SMESH_MeshEditor::GetLinkedNodes( const SMDS_MeshNode* theNode, + TIDSortedElemSet & linkedNodes, + SMDSAbs_ElementType type ) +{ + SMDS_ElemIteratorPtr elemIt = theNode->GetInverseElementIterator(type); + while ( elemIt->more() ) + { + const SMDS_MeshElement* elem = elemIt->next(); + 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->GetNode( iAfter )); + linkedNodes.insert( elem->GetNode( iBefore )); + } + } + } + } +} + //======================================================================= //function : laplacianSmooth //purpose : pulls theNode toward the center of surrounding nodes directly @@ -1896,39 +2051,15 @@ void laplacianSmooth(const SMDS_MeshNode* theNode, { // find surrounding nodes - set< const SMDS_MeshNode* > nodeSet; - SMDS_ElemIteratorPtr elemIt = theNode->GetInverseElementIterator(); - while ( elemIt->more() ) - { - const SMDS_MeshElement* elem = elemIt->next(); - if ( elem->GetType() != SMDSAbs_Face ) - continue; - - for ( int i = 0; i < elem->NbNodes(); ++i ) { - if ( elem->GetNode( i ) == theNode ) { - // add linked nodes - int iBefore = i - 1; - int iAfter = i + 1; - if ( elem->IsQuadratic() ) { - int nbCorners = elem->NbNodes() / 2; - if ( iAfter >= nbCorners ) - iAfter = 0; // elem->GetNode() wraps index - if ( iBefore == -1 ) - iBefore = nbCorners - 1; - } - nodeSet.insert( elem->GetNode( iAfter )); - nodeSet.insert( elem->GetNode( iBefore )); - break; - } - } - } + TIDSortedElemSet nodeSet; + SMESH_MeshEditor::GetLinkedNodes( theNode, nodeSet, SMDSAbs_Face ); // compute new coodrs double coord[] = { 0., 0., 0. }; - set< const SMDS_MeshNode* >::iterator nodeSetIt = nodeSet.begin(); + TIDSortedElemSet::iterator nodeSetIt = nodeSet.begin(); for ( ; nodeSetIt != nodeSet.end(); nodeSetIt++ ) { - const SMDS_MeshNode* node = (*nodeSetIt); + const SMDS_MeshNode* node = cast2Node(*nodeSetIt); if ( theSurface.IsNull() ) { // smooth in 3D coord[0] += node->X(); coord[1] += node->Y(); @@ -1980,12 +2111,10 @@ void centroidalSmooth(const SMDS_MeshNode* theNode, // compute new XYZ - SMDS_ElemIteratorPtr elemIt = theNode->GetInverseElementIterator(); + SMDS_ElemIteratorPtr elemIt = theNode->GetInverseElementIterator(SMDSAbs_Face); while ( elemIt->more() ) { const SMDS_MeshElement* elem = elemIt->next(); - if ( elem->GetType() != SMDSAbs_Face ) - continue; nbElems++; gp_XYZ elemCenter(0.,0.,0.); @@ -2056,12 +2185,12 @@ static bool getClosestUV (Extrema_GenExtPS& projector, // on edges and boundary nodes are always fixed. //======================================================================= -void SMESH_MeshEditor::Smooth (map & theElems, - set & theFixedNodes, - const SmoothMethod theSmoothMethod, - const int theNbIterations, - double theTgtAspectRatio, - const bool the2D) +void SMESH_MeshEditor::Smooth (TIDSortedElemSet & theElems, + set & theFixedNodes, + const SmoothMethod theSmoothMethod, + const int theNbIterations, + double theTgtAspectRatio, + const bool the2D) { myLastCreatedElems.Clear(); myLastCreatedNodes.Clear(); @@ -2082,15 +2211,15 @@ void SMESH_MeshEditor::Smooth (map & theElems, SMDS_FaceIteratorPtr fIt = aMesh->facesIterator(); while ( fIt->more() ) { const SMDS_MeshElement* face = fIt->next(); - theElems.insert( make_pair(face->GetID(),face) ); + theElems.insert( face ); } } // get all face ids theElems are on set< int > faceIdSet; - map::iterator itElem; + TIDSortedElemSet::iterator itElem; if ( the2D ) for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) { - int fId = FindShape( (*itElem).second ); + int fId = FindShape( *itElem ); // check that corresponding submesh exists and a shape is face if (fId && faceIdSet.find( fId ) == faceIdSet.end() && @@ -2153,7 +2282,7 @@ void SMESH_MeshEditor::Smooth (map & theElems, if ( faceSubMesh && nbElemOnFace == faceSubMesh->NbElements() ) break; // all elements found - const SMDS_MeshElement* elem = (*itElem).second; + const SMDS_MeshElement* elem = *itElem; if ( !elem || elem->GetType() != SMDSAbs_Face || elem->NbNodes() < 3 || ( faceSubMesh && !faceSubMesh->Contains( elem ))) { ++itElem; @@ -2183,13 +2312,12 @@ void SMESH_MeshEditor::Smooth (map & theElems, { // check if all faces around the node are on faceSubMesh // because a node on edge may be bound to face - SMDS_ElemIteratorPtr eIt = node->GetInverseElementIterator(); + SMDS_ElemIteratorPtr eIt = node->GetInverseElementIterator(SMDSAbs_Face); bool all = true; if ( faceSubMesh ) { while ( eIt->more() && all ) { const SMDS_MeshElement* e = eIt->next(); - if ( e->GetType() == SMDSAbs_Face ) - all = faceSubMesh->Contains( e ); + all = faceSubMesh->Contains( e ); } } if ( all ) @@ -2215,10 +2343,10 @@ void SMESH_MeshEditor::Smooth (map & theElems, if ( uvMap.find( node ) == uvMap.end() ) uvCheckNodes.push_back( node ); // add nodes of elems sharing node -// SMDS_ElemIteratorPtr eIt = node->GetInverseElementIterator(); +// SMDS_ElemIteratorPtr eIt = node->GetInverseElementIterator(SMDSAbs_Face); // while ( eIt->more() ) { // const SMDS_MeshElement* e = eIt->next(); -// if ( e != elem && e->GetType() == SMDSAbs_Face ) { +// if ( e != elem ) { // SMDS_ElemIteratorPtr nIt = e->nodesIterator(); // while ( nIt->more() ) { // const SMDS_MeshNode* n = @@ -2299,9 +2427,8 @@ void SMESH_MeshEditor::Smooth (map & theElems, // fix nodes on mesh boundary if ( checkBoundaryNodes ) { - typedef pair TLink; - map< TLink, int > linkNbMap; // how many times a link encounters in elemsOnFace - map< TLink, int >::iterator link_nb; + map< NLink, int > linkNbMap; // how many times a link encounters in elemsOnFace + map< NLink, int >::iterator link_nb; // put all elements links to linkNbMap list< const SMDS_MeshElement* >::iterator elemIt = elemsOnFace.begin(); for ( ; elemIt != elemsOnFace.end(); ++elemIt ) { @@ -2313,7 +2440,7 @@ void SMESH_MeshEditor::Smooth (map & theElems, const SMDS_MeshNode* curNode, *prevNode = elem->GetNode( nbn ); for ( int iN = 0; iN < nbn; ++iN ) { curNode = elem->GetNode( iN ); - TLink link; + NLink link; if ( curNode < prevNode ) link = make_pair( curNode , prevNode ); else link = make_pair( prevNode , curNode ); prevNode = curNode; @@ -2397,11 +2524,9 @@ void SMESH_MeshEditor::Smooth (map & theElems, uvMap2[ nSeam ] = &listUV.back(); // collect movable nodes linked to ones on seam in nodesNearSeam - SMDS_ElemIteratorPtr eIt = nSeam->GetInverseElementIterator(); + SMDS_ElemIteratorPtr eIt = nSeam->GetInverseElementIterator(SMDSAbs_Face); while ( eIt->more() ) { const SMDS_MeshElement* e = eIt->next(); - if ( e->GetType() != SMDSAbs_Face ) - continue; int nbUseMap1 = 0, nbUseMap2 = 0; SMDS_ElemIteratorPtr nIt = e->nodesIterator(); int nn = 0, nbn = e->NbNodes(); @@ -2549,7 +2674,7 @@ void SMESH_MeshEditor::Smooth (map & theElems, gp_XY uv2 = helper.GetNodeUV( face, Ns[i+2], Ns[i] ); gp_XY uv = ( uv1 + uv2 ) / 2.; gp_Pnt xyz = surface->Value( uv.X(), uv.Y() ); - x = xyz.X(); y = xyz.Y(); z = xyz.Z(); + x = xyz.X(); y = xyz.Y(); z = xyz.Z(); } else { x = (Ns[i]->X() + Ns[i+2]->X())/2; @@ -2566,7 +2691,7 @@ void SMESH_MeshEditor::Smooth (map & theElems, } } } - + } // loop on face ids } @@ -2602,23 +2727,28 @@ static bool isReverse(vector prevNodes, } //======================================================================= -//function : sweepElement -//purpose : +/*! + * \brief Create elements by sweeping an element + * \param elem - element to sweep + * \param newNodesItVec - nodes generated from each node of the element + * \param newElems - generated elements + * \param nbSteps - number of sweeping steps + * \param srcElements - to append elem for each generated element + */ //======================================================================= -static void sweepElement(SMESHDS_Mesh* aMesh, - const SMDS_MeshElement* elem, - const vector & newNodesItVec, - list& newElems, - const int nbSteps, - SMESH_SequenceOfElemPtr& myLastCreatedElems) +void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement* elem, + const vector & newNodesItVec, + list& newElems, + const int nbSteps, + SMESH_SequenceOfElemPtr& srcElements) { + SMESHDS_Mesh* aMesh = GetMeshDS(); + // Loop on elem nodes: // find new nodes and detect same nodes indices int nbNodes = elem->NbNodes(); - //list::const_iterator itNN[ nbNodes ]; - vector::const_iterator> itNN( nbNodes ); - //const SMDS_MeshNode* prevNod[ nbNodes ], *nextNod[ nbNodes ]; + vector < list< const SMDS_MeshNode* >::const_iterator > itNN( nbNodes ); vector prevNod( nbNodes ); vector nextNod( nbNodes ); vector midlNod( nbNodes ); @@ -2694,8 +2824,7 @@ static void sweepElement(SMESHDS_Mesh* aMesh, } // make new elements - int iStep;//, nbSteps = newNodesItVec[ 0 ]->second.size(); - for (iStep = 0; iStep < nbSteps; iStep++ ) { + for (int iStep = 0; iStep < nbSteps; iStep++ ) { // get next nodes for ( iNode = 0; iNode < nbNodes; iNode++ ) { if(issimple[iNode]) { @@ -2793,7 +2922,7 @@ static void sweepElement(SMESHDS_Mesh* aMesh, 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 ], @@ -2857,7 +2986,7 @@ static void sweepElement(SMESHDS_Mesh* aMesh, // realized for extrusion only //vector polyedre_nodes (nbNodes*2 + 4*nbNodes); //vector quantities (nbNodes + 2); - + //quantities[0] = nbNodes; // bottom of prism //for (int inode = 0; inode < nbNodes; inode++) { // polyedre_nodes[inode] = prevNod[inode]; @@ -2867,7 +2996,7 @@ static void sweepElement(SMESHDS_Mesh* aMesh, //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; @@ -2911,6 +3040,7 @@ static void sweepElement(SMESHDS_Mesh* aMesh, if ( aNewElem ) { newElems.push_back( aNewElem ); myLastCreatedElems.Append(aNewElem); + srcElements.Append( elem ); } // set new prev nodes @@ -2921,19 +3051,26 @@ static void sweepElement(SMESHDS_Mesh* aMesh, } //======================================================================= -//function : makeWalls -//purpose : create 1D and 2D elements around swept elements +/*! + * \brief Create 1D and 2D elements around swept elements + * \param mapNewNodes - source nodes and ones generated from them + * \param newElemsMap - source elements and ones generated from them + * \param elemNewNodesMap - nodes generated from each node of each element + * \param elemSet - all swept elements + * \param nbSteps - number of sweeping steps + * \param srcElements - to append elem for each generated element + */ //======================================================================= -static void makeWalls (SMESHDS_Mesh* aMesh, - TNodeOfNodeListMap & mapNewNodes, - TElemOfElemListMap & newElemsMap, - TElemOfVecOfNnlmiMap & elemNewNodesMap, - map& elemSet, - const int nbSteps, - SMESH_SequenceOfElemPtr& myLastCreatedElems) +void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap & mapNewNodes, + TElemOfElemListMap & newElemsMap, + TElemOfVecOfNnlmiMap & elemNewNodesMap, + TIDSortedElemSet& elemSet, + const int nbSteps, + SMESH_SequenceOfElemPtr& srcElements) { ASSERT( newElemsMap.size() == elemNewNodesMap.size() ); + SMESHDS_Mesh* aMesh = GetMeshDS(); // Find nodes belonging to only one initial element - sweep them to get edges. @@ -2953,7 +3090,7 @@ static void makeWalls (SMESHDS_Mesh* aMesh, nbInitElems = 0; highType = type; } - if ( elemSet.find(el->GetID()) != elemSet.end() ) + if ( elemSet.find(el) != elemSet.end() ) nbInitElems++; } if ( nbInitElems < 2 ) { @@ -2961,7 +3098,7 @@ static void makeWalls (SMESHDS_Mesh* aMesh, if(!NotCreateEdge) { vector newNodesItVec( 1, nList ); list newEdges; - sweepElement( aMesh, node, newNodesItVec, newEdges, nbSteps, myLastCreatedElems ); + sweepElement( node, newNodesItVec, newEdges, nbSteps, srcElements ); } } } @@ -2979,17 +3116,21 @@ static void makeWalls (SMESHDS_Mesh* aMesh, // create a ceiling edge if (!elem->IsQuadratic()) { if ( !aMesh->FindEdge( vecNewNodes[ 0 ]->second.back(), - vecNewNodes[ 1 ]->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())) + 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 ) @@ -2999,8 +3140,8 @@ static void makeWalls (SMESHDS_Mesh* aMesh, bool hasFreeLinks = false; - map avoidSet; - avoidSet.insert( make_pair(elem->GetID(),elem) ); + TIDSortedElemSet avoidSet; + avoidSet.insert( elem ); set aFaceLastNodes; int iNode, nbNodes = vecNewNodes.size(); @@ -3017,12 +3158,14 @@ static void makeWalls (SMESHDS_Mesh* aMesh, hasFreeLinks = true; // make an edge and a ceiling for a new edge if ( !aMesh->FindEdge( n1, n2 )) { - myLastCreatedElems.Append(aMesh->AddEdge( 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 )); + myLastCreatedElems.Append(aMesh->AddEdge( n1, n2 )); // ceiling edge + srcElements.Append( myLastCreatedElems.Last() ); } } } @@ -3041,13 +3184,15 @@ static void makeWalls (SMESHDS_Mesh* aMesh, // find medium node const SMDS_MeshNode* n3 = vecNewNodes[ iNode+nbn ]->first; if ( !aMesh->FindEdge( n1, n2, n3 )) { - myLastCreatedElems.Append(aMesh->AddEdge( 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 )); + myLastCreatedElems.Append(aMesh->AddEdge( n1, n2, n3 )); // ceiling edge + srcElements.Append( myLastCreatedElems.Last() ); } } } @@ -3060,37 +3205,62 @@ static void makeWalls (SMESHDS_Mesh* aMesh, if ( hasFreeLinks ) { list & newVolumes = itElem->second; - int iStep; //, nbSteps = vecNewNodes[0]->second.size(); int iVol, volNb, nbVolumesByStep = newVolumes.size() / nbSteps; - set initNodeSet, faceNodeSet; - for ( iNode = 0; iNode < nbNodes; iNode++ ) + set 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::iterator v = newVolumes.begin(); iVol = 0; while ( iVol++ < volNb ) v++; - // find indices of free faces of a volume - list< int > fInd; + // 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 - fInd.push_back( iF ); + { + if ( nbSteps == 1 && faceNodeSet == topNodeSet ) + continue; + freeInd.push_back( iF ); + // find source edge of a free face iF + vector 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 ( fInd.empty() ) + 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 ( iStep = 0; iStep < nbSteps; iStep++ ) { + // 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(); - list< int >::iterator ind = fInd.begin(); - for ( ; ind != fInd.end(); ind++ ) { + 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 ); switch ( nbn ) { @@ -3140,7 +3310,11 @@ static void makeWalls (SMESHDS_Mesh* aMesh, aMesh->ChangeElementNodes( f, nodes, nbn ); } } - } + while ( srcElements.Length() < myLastCreatedElems.Length() ) + srcElements.Append( *srcEdge ); + + } // loop on free faces + // go to the next volume iVol = 0; while ( iVol++ < nbVolumesByStep ) v++; @@ -3148,7 +3322,7 @@ static void makeWalls (SMESHDS_Mesh* aMesh, } } // sweep free links into faces - // make a ceiling face with a normal external to a volume + // Make a ceiling face with a normal external to a volume SMDS_VolumeTool lastVol( itElem->second.back() ); @@ -3192,6 +3366,9 @@ static void makeWalls (SMESHDS_Mesh* aMesh, myLastCreatedElems.Append(aMesh->AddPolygonalFace(polygon_nodes)); } } // switch + + while ( srcElements.Length() < myLastCreatedElems.Length() ) + srcElements.Append( myLastCreatedElems.Last() ); } } // loop on swept elements } @@ -3201,15 +3378,21 @@ static void makeWalls (SMESHDS_Mesh* aMesh, //purpose : //======================================================================= -void SMESH_MeshEditor::RotationSweep(map & theElems, - const gp_Ax1& theAxis, - const double theAngle, - const int theNbSteps, - const double theTol) +SMESH_MeshEditor::PGroupIDs +SMESH_MeshEditor::RotationSweep(TIDSortedElemSet & theElems, + const gp_Ax1& theAxis, + const double theAngle, + const int theNbSteps, + const double theTol, + const bool theMakeGroups, + const bool theMakeWalls) { myLastCreatedElems.Clear(); myLastCreatedNodes.Clear(); + // source elements for each generated one + SMESH_SequenceOfElemPtr srcElems, srcNodes; + MESSAGE( "RotationSweep()"); gp_Trsf aTrsf; aTrsf.SetRotation( theAxis, theAngle ); @@ -3226,21 +3409,20 @@ void SMESH_MeshEditor::RotationSweep(map & theElems TElemOfElemListMap newElemsMap; // loop on theElems - map::iterator itElem; + TIDSortedElemSet::iterator itElem; for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) { - const SMDS_MeshElement* elem = (*itElem).second; - if ( !elem ) + const SMDS_MeshElement* elem = *itElem; + if ( !elem || elem->GetType() == SMDSAbs_Volume ) continue; vector & newNodesItVec = mapElemNewNodes[ elem ]; newNodesItVec.reserve( elem->NbNodes() ); // loop on elem nodes SMDS_ElemIteratorPtr itN = elem->nodesIterator(); - while ( itN->more() ) { - + while ( itN->more() ) + { // check if a node has been already sweeped - const SMDS_MeshNode* node = - static_cast( itN->next() ); + const SMDS_MeshNode* node = cast2Node( itN->next() ); TNodeOfNodeListMapItr nIt = mapNewNodes.find( node ); if ( nIt == mapNewNodes.end() ) { nIt = mapNewNodes.insert( make_pair( node, list() )).first; @@ -3260,6 +3442,7 @@ void SMESH_MeshEditor::RotationSweep(map & theElems //aTrsf.Transforms( coord[0], coord[1], coord[2] ); newNode = aMesh->AddNode( coord[0], coord[1], coord[2] ); myLastCreatedNodes.Append(newNode); + srcNodes.Append( node ); listNewNodes.push_back( newNode ); aTrsf2.Transforms( coord[0], coord[1], coord[2] ); //aTrsf.Transforms( coord[0], coord[1], coord[2] ); @@ -3269,6 +3452,7 @@ void SMESH_MeshEditor::RotationSweep(map & theElems } newNode = aMesh->AddNode( coord[0], coord[1], coord[2] ); myLastCreatedNodes.Append(newNode); + srcNodes.Append( node ); } listNewNodes.push_back( newNode ); } @@ -3290,9 +3474,11 @@ void SMESH_MeshEditor::RotationSweep(map & theElems newNode = aMesh->AddNode( coord[0], coord[1], coord[2] ); myLastCreatedNodes.Append(newNode); listNewNodes.push_back( newNode ); + srcNodes.Append( node ); aTrsf2.Transforms( coord[0], coord[1], coord[2] ); newNode = aMesh->AddNode( coord[0], coord[1], coord[2] ); myLastCreatedNodes.Append(newNode); + srcNodes.Append( node ); listNewNodes.push_back( newNode ); } } @@ -3301,17 +3487,23 @@ void SMESH_MeshEditor::RotationSweep(map & theElems newNodesItVec.push_back( nIt ); } // make new elements - sweepElement( aMesh, elem, newNodesItVec, newElemsMap[elem], theNbSteps, myLastCreatedElems ); + sweepElement( elem, newNodesItVec, newElemsMap[elem], theNbSteps, srcElems ); } - makeWalls( aMesh, mapNewNodes, newElemsMap, mapElemNewNodes, theElems, theNbSteps, myLastCreatedElems ); + if ( theMakeWalls ) + makeWalls( mapNewNodes, newElemsMap, mapElemNewNodes, theElems, theNbSteps, srcElems ); + + PGroupIDs newGroupIDs; + if ( theMakeGroups ) + newGroupIDs = generateGroups( srcNodes, srcElems, "rotated"); + return newGroupIDs; } //======================================================================= //function : CreateNode -//purpose : +//purpose : //======================================================================= const SMDS_MeshNode* SMESH_MeshEditor::CreateNode(const double x, const double y, @@ -3343,7 +3535,7 @@ const SMDS_MeshNode* SMESH_MeshEditor::CreateNode(const double x, gp_Pnt P2(aN->X(),aN->Y(),aN->Z()); if(P1.Distance(P2) & theElems, - const gp_Vec& theStep, - const int theNbSteps, - TElemOfElemListMap& newElemsMap, - const int theFlags, - const double theTolerance) +SMESH_MeshEditor::PGroupIDs +SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet & theElems, + const gp_Vec& theStep, + const int theNbSteps, + TElemOfElemListMap& newElemsMap, + const bool theMakeGroups, + const int theFlags, + const double theTolerance) { ExtrusParam aParams; aParams.myDir = gp_Dir(theStep); @@ -3374,8 +3567,8 @@ void SMESH_MeshEditor::ExtrusionSweep for(i=1; i<=theNbSteps; i++) aParams.mySteps->Append(theStep.Magnitude()); - ExtrusionSweep(theElems,aParams,newElemsMap,theFlags,theTolerance); - + return + ExtrusionSweep(theElems,aParams,newElemsMap,theMakeGroups,theFlags,theTolerance); } @@ -3384,16 +3577,20 @@ void SMESH_MeshEditor::ExtrusionSweep //purpose : //======================================================================= -void SMESH_MeshEditor::ExtrusionSweep - (map & theElems, - ExtrusParam& theParams, - TElemOfElemListMap& newElemsMap, - const int theFlags, - const double theTolerance) +SMESH_MeshEditor::PGroupIDs +SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet & theElems, + ExtrusParam& theParams, + TElemOfElemListMap& newElemsMap, + const bool theMakeGroups, + const int theFlags, + const double theTolerance) { myLastCreatedElems.Clear(); myLastCreatedNodes.Clear(); + // source elements for each generated one + SMESH_SequenceOfElemPtr srcElems, srcNodes; + SMESHDS_Mesh* aMesh = GetMeshDS(); int nbsteps = theParams.mySteps->Length(); @@ -3404,11 +3601,11 @@ void SMESH_MeshEditor::ExtrusionSweep //TElemOfVecOfMapNodesMap mapElemNewNodes; // loop on theElems - map::iterator itElem; + TIDSortedElemSet::iterator itElem; for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) { // check element type - const SMDS_MeshElement* elem = (*itElem).second; - if ( !elem ) + const SMDS_MeshElement* elem = *itElem; + if ( !elem || elem->GetType() == SMDSAbs_Volume ) continue; vector & newNodesItVec = mapElemNewNodes[ elem ]; @@ -3417,11 +3614,10 @@ void SMESH_MeshEditor::ExtrusionSweep // loop on elem nodes SMDS_ElemIteratorPtr itN = elem->nodesIterator(); - while ( itN->more() ) { - + while ( itN->more() ) + { // check if a node has been already sweeped - const SMDS_MeshNode* node = - static_cast( itN->next() ); + const SMDS_MeshNode* node = cast2Node( itN->next() ); TNodeOfNodeListMap::iterator nIt = mapNewNodes.find( node ); //TNodeOfNodeVecMap::iterator nIt = mapNewNodes.find( node ); if ( nIt == mapNewNodes.end() ) { @@ -3448,6 +3644,7 @@ void SMESH_MeshEditor::ExtrusionSweep else { const SMDS_MeshNode * newNode = aMesh->AddNode(x, y, z); myLastCreatedNodes.Append(newNode); + srcNodes.Append( node ); listNewNodes.push_back( newNode ); } } @@ -3464,6 +3661,7 @@ void SMESH_MeshEditor::ExtrusionSweep 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; } @@ -3489,6 +3687,7 @@ void SMESH_MeshEditor::ExtrusionSweep 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); @@ -3502,6 +3701,7 @@ void SMESH_MeshEditor::ExtrusionSweep else { const SMDS_MeshNode * newNode = aMesh->AddNode( coord[0], coord[1], coord[2] ); myLastCreatedNodes.Append(newNode); + srcNodes.Append( node ); listNewNodes.push_back( newNode ); } } @@ -3511,12 +3711,17 @@ void SMESH_MeshEditor::ExtrusionSweep newNodesItVec.push_back( nIt ); } // make new elements - sweepElement( aMesh, elem, newNodesItVec, newElemsMap[elem], nbsteps, myLastCreatedElems ); + sweepElement( elem, newNodesItVec, newElemsMap[elem], nbsteps, srcElems ); } if( theFlags & EXTRUSION_FLAG_BOUNDARY ) { - makeWalls( aMesh, mapNewNodes, newElemsMap, mapElemNewNodes, theElems, nbsteps, myLastCreatedElems ); + makeWalls( mapNewNodes, newElemsMap, mapElemNewNodes, theElems, nbsteps, srcElems ); } + PGroupIDs newGroupIDs; + if ( theMakeGroups ) + newGroupIDs = generateGroups( srcNodes, srcElems, "extruded"); + + return newGroupIDs; } @@ -3569,23 +3774,26 @@ protected: //purpose : //======================================================================= SMESH_MeshEditor::Extrusion_Error - SMESH_MeshEditor::ExtrusionAlongTrack (std::map & theElements, - SMESH_subMesh* theTrack, + SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet & theElements, + SMESH_subMesh* theTrack, const SMDS_MeshNode* theN1, - const bool theHasAngles, - std::list& theAngles, - const bool theHasRefPoint, - const gp_Pnt& theRefPoint) + const bool theHasAngles, + list& theAngles, + const bool theHasRefPoint, + const gp_Pnt& theRefPoint, + const bool theMakeGroups) { myLastCreatedElems.Clear(); myLastCreatedNodes.Clear(); - MESSAGE("SMESH_MeshEditor::ExtrusionAlongTrack") + // source elements for each generated one + SMESH_SequenceOfElemPtr srcElems, srcNodes; + int j, aNbTP, aNbE, aNb; double aT1, aT2, aT, aAngle, aX, aY, aZ; std::list aPrms; std::list::iterator aItD; - std::map::iterator itElem; + TIDSortedElemSet::iterator itElem; Standard_Real aTx1, aTx2, aL2, aTolVec, aTolVec2; gp_Pnt aP3D, aV0; @@ -3725,7 +3933,7 @@ SMESH_MeshEditor::Extrusion_Error itElem = theElements.begin(); for ( ; itElem != theElements.end(); itElem++ ) { - const SMDS_MeshElement* elem = (*itElem).second; + const SMDS_MeshElement* elem = *itElem; SMDS_ElemIteratorPtr itN = elem->nodesIterator(); while ( itN->more() ) { @@ -3754,7 +3962,7 @@ SMESH_MeshEditor::Extrusion_Error for ( itElem = theElements.begin(); itElem != theElements.end(); itElem++ ) { // check element type - const SMDS_MeshElement* elem = (*itElem).second; + const SMDS_MeshElement* elem = *itElem; aTypeE = elem->GetType(); if ( !elem || ( aTypeE != SMDSAbs_Face && aTypeE != SMDSAbs_Edge ) ) continue; @@ -3763,9 +3971,11 @@ SMESH_MeshEditor::Extrusion_Error newNodesItVec.reserve( elem->NbNodes() ); // loop on elem nodes + int nodeIndex = -1; SMDS_ElemIteratorPtr itN = elem->nodesIterator(); - while ( itN->more() ) { - + while ( itN->more() ) + { + ++nodeIndex; // check if a node has been already processed const SMDS_MeshNode* node = static_cast( itN->next() ); @@ -3834,6 +4044,7 @@ SMESH_MeshEditor::Extrusion_Error 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(); @@ -3841,6 +4052,7 @@ SMESH_MeshEditor::Extrusion_Error aZ = aPN1.Z(); const SMDS_MeshNode* newNode = aMesh->AddNode( aX, aY, aZ ); myLastCreatedNodes.Append(newNode); + srcNodes.Append( node ); listNewNodes.push_back( newNode ); aPN0 = aPN1; @@ -3866,6 +4078,7 @@ SMESH_MeshEditor::Extrusion_Error 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; @@ -3884,12 +4097,13 @@ SMESH_MeshEditor::Extrusion_Error // make new elements //sweepElement( aMesh, elem, newNodesItVec, newElemsMap[elem], // newNodesItVec[0]->second.size(), myLastCreatedElems ); - sweepElement( aMesh, elem, newNodesItVec, newElemsMap[elem], - aNbTP-1, myLastCreatedElems ); + sweepElement( elem, newNodesItVec, newElemsMap[elem], aNbTP-1, srcElems ); } - makeWalls( aMesh, mapNewNodes, newElemsMap, mapElemNewNodes, theElements, - aNbTP-1, myLastCreatedElems ); + makeWalls( mapNewNodes, newElemsMap, mapElemNewNodes, theElements, aNbTP-1, srcElems ); + + if ( theMakeGroups ) + generateGroups( srcNodes, srcElems, "extruded"); return EXTR_OK; } @@ -3899,36 +4113,58 @@ SMESH_MeshEditor::Extrusion_Error //purpose : //======================================================================= -void SMESH_MeshEditor::Transform (map & theElems, - const gp_Trsf& theTrsf, - const bool theCopy) +SMESH_MeshEditor::PGroupIDs +SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems, + const gp_Trsf& theTrsf, + const bool theCopy, + const bool theMakeGroups, + SMESH_Mesh* theTargetMesh) { myLastCreatedElems.Clear(); myLastCreatedNodes.Clear(); - bool needReverse; + bool needReverse = false; + string groupPostfix; switch ( theTrsf.Form() ) { case gp_PntMirror: + case gp_Ax1Mirror: case gp_Ax2Mirror: needReverse = true; + groupPostfix = "mirrored"; + break; + case gp_Rotation: + groupPostfix = "rotated"; + break; + case gp_Translation: + groupPostfix = "translated"; + break; + case gp_Scale: + groupPostfix = "scaled"; break; default: needReverse = false; + groupPostfix = "transformed"; } - SMESHDS_Mesh* aMesh = GetMeshDS(); + 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 - map inverseElemSet; + TIDSortedElemSet inverseElemSet; + + // source elements for each generated one + SMESH_SequenceOfElemPtr srcElems, srcNodes; // loop on theElems - map::iterator itElem; + TIDSortedElemSet::iterator itElem; for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) { - const SMDS_MeshElement* elem = (*itElem).second; + const SMDS_MeshElement* elem = *itElem; if ( !elem ) continue; @@ -3937,9 +4173,10 @@ void SMESH_MeshEditor::Transform (map & theElems, while ( itN->more() ) { // check if a node has been already transformed - const SMDS_MeshNode* node = - static_cast( itN->next() ); - if (nodeMap.find( node ) != nodeMap.end() ) + const SMDS_MeshNode* node = cast2Node( itN->next() ); + pair n2n_isnew = + nodeMap.insert( make_pair ( node, node )); + if ( !n2n_isnew.second ) continue; double coord[3]; @@ -3947,10 +4184,17 @@ void SMESH_MeshEditor::Transform (map & theElems, coord[1] = node->Y(); coord[2] = node->Z(); theTrsf.Transforms( coord[0], coord[1], coord[2] ); - const SMDS_MeshNode * newNode = node; - if ( theCopy ) { - newNode = aMesh->AddNode( 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] ); @@ -3958,29 +4202,25 @@ void SMESH_MeshEditor::Transform (map & theElems, const_cast< SMDS_MeshNode* > ( node )->SetPosition ( SMDS_SpacePosition::originSpacePosition() ); } - nodeMap.insert( TNodeNodeMap::value_type( node, newNode )); // keep inverse elements - if ( !theCopy && needReverse ) { + if ( !theCopy && !theTargetMesh && needReverse ) { SMDS_ElemIteratorPtr invElemIt = node->GetInverseElementIterator(); while ( invElemIt->more() ) { - const SMDS_MeshElement* iel = invElemIt->next(); - inverseElemSet.insert( make_pair(iel->GetID(),iel) ); + const SMDS_MeshElement* iel = invElemIt->next(); + inverseElemSet.insert( iel ); } } } } - // either new elements are to be created - // or a mirrored element are to be reversed - if ( !theCopy && !needReverse) - return; + // either create new elements or reverse mirrored ones + if ( !theCopy && !needReverse && !theTargetMesh ) + return PGroupIDs(); - if ( !inverseElemSet.empty()) { - map::iterator invElemIt = inverseElemSet.begin(); - for ( ; invElemIt != inverseElemSet.end(); invElemIt++ ) - theElems.insert( *invElemIt ); - } + TIDSortedElemSet::iterator invElemIt = inverseElemSet.begin(); + for ( ; invElemIt != inverseElemSet.end(); invElemIt++ ) + theElems.insert( *invElemIt ); // replicate or reverse elements @@ -4001,8 +4241,9 @@ void SMESH_MeshEditor::Transform (map & theElems, { 0, 1, 2, 3, 4, 5, 6, 7 } // FORWARD }; - for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) { - const SMDS_MeshElement* elem = (*itElem).second; + for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) + { + const SMDS_MeshElement* elem = *itElem; if ( !elem || elem->GetType() == SMDSAbs_Node ) continue; @@ -4034,8 +4275,13 @@ void SMESH_MeshEditor::Transform (map & theElems, if ( iNode != nbNodes ) continue; // not all nodes transformed - if ( theCopy ) { + 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); @@ -4046,7 +4292,7 @@ void SMESH_MeshEditor::Transform (map & theElems, { // ATTENTION: Reversing is not yet done!!! const SMDS_PolyhedralVolumeOfNodes* aPolyedre = - (const SMDS_PolyhedralVolumeOfNodes*) elem; + dynamic_cast( elem ); if (!aPolyedre) { MESSAGE("Warning: bad volumic element"); continue; @@ -4073,26 +4319,31 @@ void SMESH_MeshEditor::Transform (map & theElems, if ( !allTransformed ) continue; // not all nodes transformed - if ( theCopy ) { + 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; + 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 ]; + // 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}; @@ -4130,7 +4381,7 @@ void SMESH_MeshEditor::Transform (map & theElems, } // find transformed nodes - const SMDS_MeshNode* nodes[8]; + vector nodes(nbNodes); int iNode = 0; SMDS_ElemIteratorPtr itN = elem->nodesIterator(); while ( itN->more() ) { @@ -4144,72 +4395,166 @@ void SMESH_MeshEditor::Transform (map & theElems, if ( iNode != nbNodes ) continue; // not all nodes transformed - if ( theCopy ) { - // add a new element - switch ( elemType ) { - case SMDSAbs_Edge: - if ( nbNodes == 2 ) - myLastCreatedElems.Append(aMesh->AddEdge( nodes[ 0 ], nodes[ 1 ] )); - else - myLastCreatedElems.Append(aMesh->AddEdge( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] )); - break; - case SMDSAbs_Face: - if ( nbNodes == 3 ) - myLastCreatedElems.Append(aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] )); - else if(nbNodes==4) - myLastCreatedElems.Append(aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] , nodes[ 3 ])); - else if(nbNodes==6) - myLastCreatedElems.Append(aMesh->AddFace(nodes[0], nodes[1], nodes[2], nodes[3], - nodes[4], nodes[5])); - else // nbNodes==8 - myLastCreatedElems.Append(aMesh->AddFace(nodes[0], nodes[1], nodes[2], nodes[3], - nodes[4], nodes[5], nodes[6], nodes[7])); - break; - case SMDSAbs_Volume: - if ( nbNodes == 4 ) - myLastCreatedElems.Append(aMesh->AddVolume( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] , nodes[ 3 ] )); - else if ( nbNodes == 8 ) - myLastCreatedElems.Append(aMesh->AddVolume( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] , nodes[ 3 ], - nodes[ 4 ], nodes[ 5 ], nodes[ 6 ] , nodes[ 7 ])); - else if ( nbNodes == 6 ) - myLastCreatedElems.Append(aMesh->AddVolume( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] , nodes[ 3 ], - nodes[ 4 ], nodes[ 5 ])); - else if ( nbNodes == 5 ) - myLastCreatedElems.Append(aMesh->AddVolume( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] , nodes[ 3 ], - nodes[ 4 ])); - else if(nbNodes==10) - myLastCreatedElems.Append(aMesh->AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4], - nodes[5], nodes[6], nodes[7], nodes[8], nodes[9])); - else if(nbNodes==13) - myLastCreatedElems.Append(aMesh->AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4], - nodes[5], nodes[6], nodes[7], nodes[8], nodes[9], - nodes[10], nodes[11], nodes[12])); - else if(nbNodes==15) - myLastCreatedElems.Append(aMesh->AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4], - nodes[5], nodes[6], nodes[7], nodes[8], nodes[9], - nodes[10], nodes[11], nodes[12], nodes[13], nodes[14])); - else // nbNodes==20 - myLastCreatedElems.Append(aMesh->AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4], - nodes[5], nodes[6], nodes[7], nodes[8], nodes[9], - nodes[10], nodes[11], nodes[12], nodes[13], nodes[14], - nodes[15], nodes[16], nodes[17], nodes[18], nodes[19])); - break; - default:; + if ( theTargetMesh ) { + if ( SMDS_MeshElement* copy = + targetMeshEditor.AddElement( nodes, elem->GetType(), elem->IsPoly() )) { + myLastCreatedElems.Append( copy ); + srcElems.Append( elem ); } } - else - { + else if ( theCopy ) { + if ( SMDS_MeshElement* copy = AddElement( nodes, elem->GetType(), elem->IsPoly() )) { + myLastCreatedElems.Append( copy ); + srcElems.Append( elem ); + } + } + else { // reverse element as it was reversed by transformation if ( nbNodes > 2 ) - aMesh->ChangeElementNodes( elem, nodes, nbNodes ); + aMesh->ChangeElementNodes( elem, &nodes[0], nbNodes ); } } + + PGroupIDs newGroupIDs; + + if ( theMakeGroups && theCopy || + theMakeGroups && theTargetMesh ) + newGroupIDs = generateGroups( srcNodes, srcElems, groupPostfix, theTargetMesh ); + + return newGroupIDs; +} + +//======================================================================= +/*! + * \brief Create groups of elements made during transformation + * \param nodeGens - nodes making corresponding myLastCreatedNodes + * \param elemGens - elements making corresponding myLastCreatedElems + * \param postfix - to append to names of new groups + */ +//======================================================================= + +SMESH_MeshEditor::PGroupIDs +SMESH_MeshEditor::generateGroups(const SMESH_SequenceOfElemPtr& nodeGens, + const SMESH_SequenceOfElemPtr& elemGens, + const std::string& postfix, + SMESH_Mesh* targetMesh) +{ + PGroupIDs newGroupIDs( new list ); + 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(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; } //======================================================================= //function : FindCoincidentNodes //purpose : Return list of group of nodes close to each other within theTolerance -// Search among theNodes or in the whole mesh if theNodes is empty. +// Search among theNodes or in the whole mesh if theNodes is empty using +// an Octree algorithm //======================================================================= void SMESH_MeshEditor::FindCoincidentNodes (set & theNodes, @@ -4219,48 +4564,123 @@ void SMESH_MeshEditor::FindCoincidentNodes (set & theNodes myLastCreatedElems.Clear(); myLastCreatedNodes.Clear(); - double tol2 = theTolerance * theTolerance; - - list nodes; + set nodes; if ( theNodes.empty() ) { // get all nodes in the mesh SMDS_NodeIteratorPtr nIt = GetMeshDS()->nodesIterator(); while ( nIt->more() ) - nodes.push_back( nIt->next() ); + nodes.insert( nodes.end(),nIt->next()); } else + nodes=theNodes; + SMESH_OctreeNode::FindCoincidentNodes ( nodes, &theGroupsOfNodes, theTolerance); + +} + +//======================================================================= +/*! + * \brief Implementation of search for the node closest to point + */ +//======================================================================= + +struct SMESH_NodeSearcherImpl: public SMESH_NodeSearcher +{ + /*! + * \brief Constructor + */ + SMESH_NodeSearcherImpl( const SMESHDS_Mesh* theMesh ) { - nodes.insert( nodes.end(), theNodes.begin(), theNodes.end() ); + set nodes; + if ( theMesh ) { + SMDS_NodeIteratorPtr nIt = theMesh->nodesIterator(); + while ( nIt->more() ) + nodes.insert( nodes.end(), nIt->next() ); + } + myOctreeNode = new SMESH_OctreeNode(nodes) ; } - - list::iterator it2, it1 = nodes.begin(); - for ( ; it1 != nodes.end(); it1++ ) + /*! + * \brief Do it's job + */ + const SMDS_MeshNode* FindClosestTo( const gp_Pnt& thePnt ) { - const SMDS_MeshNode* n1 = *it1; - gp_Pnt p1( n1->X(), n1->Y(), n1->Z() ); - - list * groupPtr = 0; - it2 = it1; - for ( it2++; it2 != nodes.end(); it2++ ) + SMDS_MeshNode tgtNode( thePnt.X(), thePnt.Y(), thePnt.Z() ); + list nodes; + const double precision = 1e-6; + myOctreeNode->NodesAround( &tgtNode, &nodes, precision ); + + double minSqDist = DBL_MAX; + Bnd_B3d box; + if ( nodes.empty() ) // get all nodes of OctreeNode's closest to thePnt { - const SMDS_MeshNode* n2 = *it2; - gp_Pnt p2( n2->X(), n2->Y(), n2->Z() ); - if ( p1.SquareDistance( p2 ) <= tol2 ) + // sort leafs by their distance from thePnt + typedef map< double, SMESH_OctreeNode* > TDistTreeMap; + TDistTreeMap treeMap; + list< SMESH_OctreeNode* > treeList; + list< SMESH_OctreeNode* >::iterator trIt; + treeList.push_back( myOctreeNode ); + for ( trIt = treeList.begin(); trIt != treeList.end(); ++trIt) { - if ( !groupPtr ) { - theGroupsOfNodes.push_back( list() ); - groupPtr = & theGroupsOfNodes.back(); - groupPtr->push_back( n1 ); + SMESH_OctreeNode* tree = *trIt; + if ( !tree->isLeaf() ) { // put children to the queue + SMESH_OctreeNodeIteratorPtr cIt = tree->GetChildrenIterator(); + while ( cIt->more() ) + treeList.push_back( cIt->next() ); } - if(groupPtr->front()>n2) - groupPtr->push_front( n2 ); - else - groupPtr->push_back( n2 ); - it2 = nodes.erase( it2 ); - it2--; + else if ( tree->NbNodes() ) { // put tree to treeMap + tree->getBox( box ); + double sqDist = thePnt.SquareDistance( 0.5 * ( box.CornerMin() + box.CornerMax() )); + pair it_in = treeMap.insert( make_pair( sqDist, tree )); + if ( !it_in.second ) // not unique distance to box center + treeMap.insert( it_in.first, make_pair( sqDist - 1e-13*treeMap.size(), tree )); + } + } + // find distance after which there is no sense to check tree's + double sqLimit = DBL_MAX; + TDistTreeMap::iterator sqDist_tree = treeMap.begin(); + if ( treeMap.size() > 5 ) { + SMESH_OctreeNode* closestTree = sqDist_tree->second; + closestTree->getBox( box ); + double limit = sqrt( sqDist_tree->first ) + sqrt ( box.SquareExtent() ); + sqLimit = limit * limit; + } + // get all nodes from trees + for ( ; sqDist_tree != treeMap.end(); ++sqDist_tree) { + if ( sqDist_tree->first > sqLimit ) + break; + SMESH_OctreeNode* tree = sqDist_tree->second; + tree->NodesAround( tree->GetNodeIterator()->next(), &nodes ); } } + // find closest among nodes + minSqDist = DBL_MAX; + const SMDS_MeshNode* closestNode = 0; + list::iterator nIt = nodes.begin(); + for ( ; nIt != nodes.end(); ++nIt ) { + double sqDist = thePnt.SquareDistance( TNodeXYZ( *nIt ) ); + if ( minSqDist > sqDist ) { + closestNode = *nIt; + minSqDist = sqDist; + } + } + return closestNode; } + /*! + * \brief Destructor + */ + ~SMESH_NodeSearcherImpl() { delete myOctreeNode; } +private: + SMESH_OctreeNode* myOctreeNode; +}; + +//======================================================================= +/*! + * \brief Return SMESH_NodeSearcher + */ +//======================================================================= + +SMESH_NodeSearcher* SMESH_MeshEditor::GetNodeSearcher() +{ + return new SMESH_NodeSearcherImpl( GetMeshDS() ); } //======================================================================= @@ -4394,10 +4814,7 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) int aShapeId = FindShape( elem ); set nodeSet; - //const SMDS_MeshNode* curNodes[ nbNodes ], *uniqueNodes[ nbNodes ]; - const SMDS_MeshNode** curNodes = new const SMDS_MeshNode*[ nbNodes ]; - const SMDS_MeshNode** uniqueNodes = new const SMDS_MeshNode*[ nbNodes ]; - + vector< const SMDS_MeshNode*> curNodes( nbNodes ), uniqueNodes( nbNodes ); int iUnique = 0, iCur = 0, nbRepl = 0; vector iRepl( nbNodes ); @@ -4577,7 +4994,7 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) else isOk = false; break; - case 8: { + case 8: { if(elem->IsQuadratic()) { // Quadratic quadrangle // 1 5 2 // +---+---+ @@ -4875,7 +5292,7 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) } else { // Change regular element or polygon - aMesh->ChangeElementNodes( elem, uniqueNodes, nbUniqueNodes ); + aMesh->ChangeElementNodes( elem, & uniqueNodes[0], nbUniqueNodes ); } } else { @@ -4883,99 +5300,153 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) rmElemIds.push_back( elem->GetID() ); } - delete curNodes; - delete uniqueNodes; } // loop on elements // Remove equal nodes and bad elements Remove( rmNodeIds, true ); Remove( rmElemIds, false ); + } -// ================================================= +// ======================================================== // class : SortableElement -// purpose : auxilary -// ================================================= +// purpose : allow sorting elements basing on their nodes +// ======================================================== class SortableElement : public set { public: SortableElement( const SMDS_MeshElement* theElem ) { - myID = theElem->GetID(); + myElem = theElem; SMDS_ElemIteratorPtr nodeIt = theElem->nodesIterator(); while ( nodeIt->more() ) this->insert( nodeIt->next() ); } - const long GetID() const - { return myID; } + const SMDS_MeshElement* Get() const + { return myElem; } - void SetID(const long anID) const - { myID = anID; } + void Set(const SMDS_MeshElement* e) const + { myElem = e; } private: - mutable long myID; + mutable const SMDS_MeshElement* myElem; }; +//======================================================================= +//function : FindEqualElements +//purpose : Return list of group of elements built on the same nodes. +// Search among theElements or in the whole mesh if theElements is empty +//======================================================================= +void SMESH_MeshEditor::FindEqualElements(set & theElements, + TListOfListOfElementsID & theGroupsOfElementsID) +{ + myLastCreatedElems.Clear(); + myLastCreatedNodes.Clear(); + + typedef set TElemsSet; + typedef map< SortableElement, int > TMapOfNodeSet; + typedef list TGroupOfElems; + + TElemsSet elems; + if ( theElements.empty() ) + { // get all elements in the mesh + SMDS_ElemIteratorPtr eIt = GetMeshDS()->elementsIterator(); + while ( eIt->more() ) + elems.insert( elems.end(), eIt->next()); + } + else + elems = theElements; + + vector< TGroupOfElems > arrayOfGroups; + TGroupOfElems groupOfElems; + TMapOfNodeSet mapOfNodeSet; + + TElemsSet::iterator elemIt = elems.begin(); + for ( int i = 0, j=0; elemIt != elems.end(); ++elemIt, ++j ) { + const SMDS_MeshElement* curElem = *elemIt; + SortableElement SE(curElem); + int ind = -1; + // check uniqueness + pair< TMapOfNodeSet::iterator, bool> pp = mapOfNodeSet.insert(make_pair(SE, i)); + if( !(pp.second) ) { + TMapOfNodeSet::iterator& itSE = pp.first; + ind = (*itSE).second; + arrayOfGroups[ind].push_back(curElem->GetID()); + } + else { + groupOfElems.clear(); + groupOfElems.push_back(curElem->GetID()); + arrayOfGroups.push_back(groupOfElems); + i++; + } + } + + vector< TGroupOfElems >::iterator groupIt = arrayOfGroups.begin(); + for ( ; groupIt != arrayOfGroups.end(); ++groupIt ) { + groupOfElems = *groupIt; + if ( groupOfElems.size() > 1 ) { + groupOfElems.sort(); + theGroupsOfElementsID.push_back(groupOfElems); + } + } +} //======================================================================= -//function : MergeEqualElements -//purpose : Remove all but one of elements built on the same nodes. +//function : MergeElements +//purpose : In each given group, substitute all elements by the first one. //======================================================================= -void SMESH_MeshEditor::MergeEqualElements() +void SMESH_MeshEditor::MergeElements(TListOfListOfElementsID & theGroupsOfElementsID) { myLastCreatedElems.Clear(); myLastCreatedNodes.Clear(); + typedef list TListOfIDs; + TListOfIDs rmElemIds; // IDs of elems to remove + SMESHDS_Mesh* aMesh = GetMeshDS(); - SMDS_EdgeIteratorPtr eIt = aMesh->edgesIterator(); - SMDS_FaceIteratorPtr fIt = aMesh->facesIterator(); - SMDS_VolumeIteratorPtr vIt = aMesh->volumesIterator(); - - list< int > rmElemIds; // IDs of elems to remove - - for ( int iDim = 1; iDim <= 3; iDim++ ) { - - set< SortableElement > setOfNodeSet; - while ( 1 ) { - // get next element - const SMDS_MeshElement* elem = 0; - if ( iDim == 1 ) { - if ( eIt->more() ) elem = eIt->next(); - } else if ( iDim == 2 ) { - if ( fIt->more() ) elem = fIt->next(); - } else { - if ( vIt->more() ) elem = vIt->next(); - } - if ( !elem ) break; - - SortableElement SE(elem); - - // check uniqueness - pair< set::iterator, bool> pp = setOfNodeSet.insert(SE); - if( !(pp.second) ) { - set::iterator itSE = pp.first; - SortableElement SEold = *itSE; - if( SEold.GetID() > SE.GetID() ) { - rmElemIds.push_back( SEold.GetID() ); - (*itSE).SetID(SE.GetID()); - } - else { - rmElemIds.push_back( SE.GetID() ); - } - } + 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 ); } +//======================================================================= +//function : MergeEqualElements +//purpose : Remove all but one of elements built on the same nodes. +//======================================================================= + +void SMESH_MeshEditor::MergeEqualElements() +{ + set aMeshElements; /* empty input - + to merge equal elements in the whole mesh */ + TListOfListOfElementsID aGroupsOfElementsID; + FindEqualElements(aMeshElements, aGroupsOfElementsID); + MergeElements(aGroupsOfElementsID); +} + //======================================================================= //function : FindFaceInSet //purpose : Return a face having linked nodes n1 and n2 and which is @@ -4984,19 +5455,18 @@ void SMESH_MeshEditor::MergeEqualElements() //======================================================================= const SMDS_MeshElement* - SMESH_MeshEditor::FindFaceInSet(const SMDS_MeshNode* n1, - const SMDS_MeshNode* n2, - const map& elemSet, - const map& avoidSet) + SMESH_MeshEditor::FindFaceInSet(const SMDS_MeshNode* n1, + const SMDS_MeshNode* n2, + const TIDSortedElemSet& elemSet, + const TIDSortedElemSet& avoidSet) { - SMDS_ElemIteratorPtr invElemIt = n1->GetInverseElementIterator(); + SMDS_ElemIteratorPtr invElemIt = n1->GetInverseElementIterator(SMDSAbs_Face); while ( invElemIt->more() ) { // loop on inverse elements of n1 const SMDS_MeshElement* elem = invElemIt->next(); - if (elem->GetType() != SMDSAbs_Face || - avoidSet.find( elem->GetID() ) != avoidSet.end() ) + if (avoidSet.find( elem ) != avoidSet.end() ) continue; - if ( !elemSet.empty() && elemSet.find( elem->GetID() ) == elemSet.end()) + if ( !elemSet.empty() && elemSet.find( elem ) == elemSet.end()) continue; // get face nodes and find index of n1 int i1, nbN = elem->NbNodes(), iNode = 0; @@ -5070,9 +5540,9 @@ static const SMDS_MeshElement* findAdjacentFace(const SMDS_MeshNode* n1, const SMDS_MeshNode* n2, const SMDS_MeshElement* elem) { - map elemSet, avoidSet; + TIDSortedElemSet elemSet, avoidSet; if ( elem ) - avoidSet.insert ( make_pair(elem->GetID(),elem) ); + avoidSet.insert ( elem ); return SMESH_MeshEditor::FindFaceInSet( n1, n2, elemSet, avoidSet ); } @@ -5113,7 +5583,7 @@ bool SMESH_MeshEditor::FindFreeBorder (const SMDS_MeshNode* theFirst list< const SMDS_MeshElement* > curElemList; list< const SMDS_MeshNode* > nStartList; - SMDS_ElemIteratorPtr invElemIt = nStart->facesIterator(); + SMDS_ElemIteratorPtr invElemIt = nStart->GetInverseElementIterator(SMDSAbs_Face); while ( invElemIt->more() ) { const SMDS_MeshElement* e = invElemIt->next(); if ( e == curElem || foundElems.insert( e ).second ) { @@ -5388,13 +5858,11 @@ SMESH_MeshEditor::Sew_Error 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(); - //const SMDS_MeshNode* faceNodes[ nbNodes ]; - const SMDS_MeshNode** faceNodes = new const SMDS_MeshNode*[ nbNodes ]; + vector< const SMDS_MeshNode* > faceNodes( nbNodes, (const SMDS_MeshNode*)0 ); bool isVolume = volume.Set( elem ); - const SMDS_MeshNode** nodes = isVolume ? volume.GetNodes() : faceNodes; + const SMDS_MeshNode** nodes = isVolume ? volume.GetNodes() : & faceNodes[0]; if ( isVolume ) // --volume hasVolumes = true; - //else if ( nbNodes > 2 ) { // --face else if ( elem->GetType()==SMDSAbs_Face ) { // --face // retrieve all face nodes and find iPrevNode - an index of the prevSideNode if(elem->IsQuadratic()) { @@ -5411,7 +5879,7 @@ SMESH_MeshEditor::Sew_Error else { SMDS_ElemIteratorPtr nIt = elem->nodesIterator(); while ( nIt->more() ) { - nodes[ iNode ] = static_cast( nIt->next() ); + nodes[ iNode ] = cast2Node( nIt->next() ); if ( nodes[ iNode++ ] == prevSideNode ) iPrevNode = iNode - 1; } @@ -5461,7 +5929,6 @@ SMESH_MeshEditor::Sew_Error } } } - delete faceNodes; } // loop on inverse elements of prevSideNode if ( !sideNode ) { @@ -5516,7 +5983,7 @@ SMESH_MeshEditor::Sew_Error { nodeGroupsToMerge.push_back( list() ); nodeGroupsToMerge.back().push_back( *nIt[1] ); // to keep - nodeGroupsToMerge.back().push_back( *nIt[0] ); // tp remove + nodeGroupsToMerge.back().push_back( *nIt[0] ); // to remove } } else { @@ -5888,11 +6355,11 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement* theFace, } } } - + // create new elements SMESHDS_Mesh *aMesh = GetMeshDS(); int aShapeId = FindShape( theFace ); - + i1 = 0; i2 = 1; for ( iSplit = 0; iSplit < nbSplits - 1; iSplit++ ) { SMDS_MeshElement* newElem = 0; @@ -5909,7 +6376,7 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement* theFace, if ( aShapeId && newElem ) aMesh->SetMeshElementOnShape( newElem, aShapeId ); } - + // change nodes of theFace const SMDS_MeshNode* newNodes[ 4 ]; newNodes[ 0 ] = linkNodes[ i1 ]; @@ -5934,7 +6401,7 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement* theFace, 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 @@ -6043,11 +6510,9 @@ void SMESH_MeshEditor::UpdateVolumes (const SMDS_MeshNode* theBetweenNode myLastCreatedElems.Clear(); myLastCreatedNodes.Clear(); - SMDS_ElemIteratorPtr invElemIt = theBetweenNode1->GetInverseElementIterator(); + SMDS_ElemIteratorPtr invElemIt = theBetweenNode1->GetInverseElementIterator(SMDSAbs_Volume); while (invElemIt->more()) { // loop on inverse elements of theBetweenNode1 const SMDS_MeshElement* elem = invElemIt->next(); - if (elem->GetType() != SMDSAbs_Volume) - continue; // check, if current volume has link theBetweenNode1 - theBetweenNode2 SMDS_VolumeTool aVolume (elem); @@ -6121,90 +6586,93 @@ void SMESH_MeshEditor::UpdateVolumes (const SMDS_MeshNode* theBetweenNode } //======================================================================= -//function : ConvertElemToQuadratic -//purpose : +/*! + * \brief Convert elements contained in a submesh to quadratic + * \retval int - nb of checked elements + */ //======================================================================= -void SMESH_MeshEditor::ConvertElemToQuadratic(SMESHDS_SubMesh *theSm, - SMESH_MesherHelper* theHelper, - const bool theForce3d) + +int SMESH_MeshEditor::convertElemToQuadratic(SMESHDS_SubMesh * theSm, + SMESH_MesherHelper& theHelper, + const bool theForce3d) { - if( !theSm ) return; - SMESHDS_Mesh* meshDS = GetMeshDS(); + int nbElem = 0; + if( !theSm ) return nbElem; SMDS_ElemIteratorPtr ElemItr = theSm->GetElements(); while(ElemItr->more()) { + nbElem++; const SMDS_MeshElement* elem = ElemItr->next(); - if( !elem ) continue; + if( !elem || elem->IsQuadratic() ) continue; int id = elem->GetID(); int nbNodes = elem->NbNodes(); vector aNds (nbNodes); - + for(int i = 0; i < nbNodes; i++) { aNds[i] = elem->GetNode(i); } - SMDSAbs_ElementType aType = elem->GetType(); + + theSm->RemoveElement(elem); + GetMeshDS()->SMDS_Mesh::RemoveFreeElement(elem); + const SMDS_MeshElement* NewElem = 0; switch( aType ) { case SMDSAbs_Edge : { - meshDS->RemoveFreeElement(elem, theSm); - NewElem = theHelper->AddQuadraticEdge(aNds[0], aNds[1], id, theForce3d); + NewElem = theHelper.AddEdge(aNds[0], aNds[1], id, theForce3d); break; } case SMDSAbs_Face : { - if(elem->IsQuadratic()) continue; - - meshDS->RemoveFreeElement(elem, theSm); switch(nbNodes) { case 3: - NewElem = theHelper->AddFace(aNds[0], aNds[1], aNds[2], id, theForce3d); + NewElem = theHelper.AddFace(aNds[0], aNds[1], aNds[2], id, theForce3d); break; case 4: - NewElem = theHelper->AddFace(aNds[0], aNds[1], aNds[2], aNds[3], id, theForce3d); + NewElem = theHelper.AddFace(aNds[0], aNds[1], aNds[2], aNds[3], id, theForce3d); break; default: continue; } - break; + break; } case SMDSAbs_Volume : { - if( elem->IsQuadratic() ) continue; - - meshDS->RemoveFreeElement(elem, theSm); switch(nbNodes) { case 4: - NewElem = theHelper->AddVolume(aNds[0], aNds[1], aNds[2], aNds[3], id, true); + NewElem = theHelper.AddVolume(aNds[0], aNds[1], aNds[2], aNds[3], id, true); break; case 6: - NewElem = theHelper->AddVolume(aNds[0], aNds[1], aNds[2], aNds[3], aNds[4], aNds[5], id, true); + NewElem = theHelper.AddVolume(aNds[0], aNds[1], aNds[2], aNds[3], aNds[4], aNds[5], id, true); break; case 8: - NewElem = theHelper->AddVolume(aNds[0], aNds[1], aNds[2], aNds[3], - aNds[4], aNds[5], aNds[6], aNds[7], id, true); + NewElem = theHelper.AddVolume(aNds[0], aNds[1], aNds[2], aNds[3], + aNds[4], aNds[5], aNds[6], aNds[7], id, true); break; default: continue; } - break; + break; } default : continue; } if( NewElem ) { - AddToSameGroups( NewElem, elem, meshDS); + AddToSameGroups( NewElem, elem, GetMeshDS()); theSm->AddElement( NewElem ); } + if ( NewElem != elem ) + RemoveElemFromGroups (elem, GetMeshDS()); } + return nbElem; } //======================================================================= @@ -6215,42 +6683,44 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d) { SMESHDS_Mesh* meshDS = GetMeshDS(); - SMESH_MesherHelper* aHelper = new SMESH_MesherHelper(*myMesh); - aHelper->SetKeyIsQuadratic( true ); - const TopoDS_Shape& aShape = meshDS->ShapeToMesh(); + SMESH_MesherHelper aHelper(*myMesh); + aHelper.SetIsQuadratic( true ); - if ( !aShape.IsNull() && GetMesh()->GetSubMeshContaining(aShape) ) + int nbCheckedElems = 0; + if ( myMesh->HasShapeToMesh() ) { - SMESH_subMesh *aSubMesh = GetMesh()->GetSubMeshContaining(aShape); - - const map < int, SMESH_subMesh * >& aMapSM = aSubMesh->DependsOn(); - map < int, SMESH_subMesh * >::const_iterator itsub; - for (itsub = aMapSM.begin(); itsub != aMapSM.end(); itsub++) + if ( SMESH_subMesh *aSubMesh = myMesh->GetSubMeshContaining(myMesh->GetShapeToMesh())) { - SMESHDS_SubMesh *sm = ((*itsub).second)->GetSubMeshDS(); - aHelper->SetSubShape( (*itsub).second->GetSubShape() ); - ConvertElemToQuadratic(sm, aHelper, theForce3d); + 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); + } + } } - aHelper->SetSubShape( aSubMesh->GetSubShape() ); - ConvertElemToQuadratic(aSubMesh->GetSubMeshDS(), aHelper, theForce3d); } - else + int totalNbElems = meshDS->NbEdges() + meshDS->NbFaces() + meshDS->NbVolumes(); + if ( nbCheckedElems < totalNbElems ) // not all elements in submeshes { SMDS_EdgeIteratorPtr aEdgeItr = meshDS->edgesIterator(); while(aEdgeItr->more()) { const SMDS_MeshEdge* edge = aEdgeItr->next(); - if(edge) + if(edge && !edge->IsQuadratic()) { int id = edge->GetID(); const SMDS_MeshNode* n1 = edge->GetNode(0); const SMDS_MeshNode* n2 = edge->GetNode(1); - RemoveElemFromGroups (edge, meshDS); meshDS->SMDS_Mesh::RemoveFreeElement(edge); - const SMDS_QuadraticEdge* NewEdge = aHelper->AddQuadraticEdge(n1, n2, id, theForce3d); - AddToSameGroups(NewEdge, edge, meshDS); + const SMDS_MeshEdge* NewEdge = aHelper.AddEdge(n1, n2, id, theForce3d); + if ( NewEdge ) + AddToSameGroups(NewEdge, edge, meshDS); + if ( NewEdge != edge ) + RemoveElemFromGroups (edge, meshDS); } } SMDS_FaceIteratorPtr aFaceItr = meshDS->facesIterator(); @@ -6258,7 +6728,7 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d) { const SMDS_MeshFace* face = aFaceItr->next(); if(!face || face->IsQuadratic() ) continue; - + int id = face->GetID(); int nbNodes = face->NbNodes(); vector aNds (nbNodes); @@ -6268,29 +6738,31 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d) aNds[i] = face->GetNode(i); } - RemoveElemFromGroups (face, meshDS); meshDS->SMDS_Mesh::RemoveFreeElement(face); SMDS_MeshFace * NewFace = 0; switch(nbNodes) { case 3: - NewFace = aHelper->AddFace(aNds[0], aNds[1], aNds[2], id, theForce3d); + NewFace = aHelper.AddFace(aNds[0], aNds[1], aNds[2], id, theForce3d); break; case 4: - NewFace = aHelper->AddFace(aNds[0], aNds[1], aNds[2], aNds[3], id, theForce3d); + NewFace = aHelper.AddFace(aNds[0], aNds[1], aNds[2], aNds[3], id, theForce3d); break; default: continue; } - AddToSameGroups(NewFace, face, meshDS); + if ( NewFace ) + AddToSameGroups(NewFace, face, meshDS); + if ( NewFace != face ) + RemoveElemFromGroups (face, meshDS); } 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 aNds (nbNodes); @@ -6300,149 +6772,127 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d) aNds[i] = volume->GetNode(i); } - RemoveElemFromGroups (volume, meshDS); meshDS->SMDS_Mesh::RemoveFreeElement(volume); SMDS_MeshVolume * NewVolume = 0; switch(nbNodes) { case 4: - NewVolume = aHelper->AddVolume(aNds[0], aNds[1], aNds[2], - aNds[3], id, true ); + NewVolume = aHelper.AddVolume(aNds[0], aNds[1], aNds[2], + aNds[3], id, true ); break; case 6: - NewVolume = aHelper->AddVolume(aNds[0], aNds[1], aNds[2], - aNds[3], aNds[4], aNds[5], id, true); + NewVolume = aHelper.AddVolume(aNds[0], aNds[1], aNds[2], + aNds[3], aNds[4], aNds[5], id, true); break; case 8: - NewVolume = aHelper->AddVolume(aNds[0], aNds[1], aNds[2], aNds[3], - aNds[4], aNds[5], aNds[6], aNds[7], id, true); + NewVolume = aHelper.AddVolume(aNds[0], aNds[1], aNds[2], aNds[3], + aNds[4], aNds[5], aNds[6], aNds[7], id, true); break; default: continue; } - AddToSameGroups(NewVolume, volume, meshDS); + if ( NewVolume ) + AddToSameGroups(NewVolume, volume, meshDS); + if ( NewVolume != volume ) + RemoveElemFromGroups (volume, meshDS); } } - delete aHelper; } //======================================================================= -//function : RemoveQuadElem -//purpose : +/*! + * \brief Convert quadratic elements to linear ones and remove quadratic nodes + * \retval int - nb of checked elements + */ //======================================================================= -void SMESH_MeshEditor::RemoveQuadElem(SMESHDS_SubMesh *theSm, - SMDS_ElemIteratorPtr theItr, - RemoveQuadNodeMap& theRemoveNodeMap) + +int SMESH_MeshEditor::removeQuadElem(SMESHDS_SubMesh * theSm, + SMDS_ElemIteratorPtr theItr, + const int theShapeID) { + int nbElem = 0; SMESHDS_Mesh* meshDS = GetMeshDS(); while( theItr->more() ) { const SMDS_MeshElement* elem = theItr->next(); - if( elem ) + nbElem++; + if( elem && elem->IsQuadratic()) { - if( !elem->IsQuadratic() ) - continue; - int id = elem->GetID(); - - int nbNodes = elem->NbNodes(), idx = 0; - vector aNds; + int nbNodes = elem->NbNodes(); + vector aNds, mediumNodes; + aNds.reserve( nbNodes ); + mediumNodes.reserve( nbNodes ); for(int i = 0; i < nbNodes; i++) { const SMDS_MeshNode* n = elem->GetNode(i); if( elem->IsMediumNode( n ) ) - { - ItRemoveQuadNodeMap itRNM = theRemoveNodeMap.find( n ); - if( itRNM == theRemoveNodeMap.end() ) - { - theRemoveNodeMap.insert(RemoveQuadNodeMap::value_type( n,theSm )); - } - } - else + mediumNodes.push_back( n ); + else aNds.push_back( n ); } + if( aNds.empty() ) continue; + SMDSAbs_ElementType aType = elem->GetType(); - idx = aNds.size(); - if( !idx ) continue; - SMDSAbs_ElementType aType = elem->GetType(); - - //remove old quadratic elements - meshDS->RemoveFreeElement( elem, theSm ); + //remove old quadratic element + meshDS->SMDS_Mesh::RemoveFreeElement( elem ); + if ( theSm ) + theSm->RemoveElement( elem ); - SMDS_MeshElement * NewElem = 0; - switch(aType) - { - case SMDSAbs_Edge: - NewElem = meshDS->AddEdgeWithID( aNds[0], aNds[1] ,id ); - break; - case SMDSAbs_Face: - if( idx==3 ) NewElem = meshDS->AddFaceWithID( aNds[0], - aNds[1], aNds[2], id ); - if( idx==4 ) NewElem = meshDS->AddFaceWithID( aNds[0], - aNds[1], aNds[2], aNds[3],id ); - break; - case SMDSAbs_Volume: - if( idx==4 ) NewElem = meshDS->AddVolumeWithID( aNds[0], - aNds[1], aNds[2], aNds[3], id ); - if( idx==6 ) NewElem = meshDS->AddVolumeWithID( aNds[0], - aNds[1], aNds[2], aNds[3], - aNds[4], aNds[5], id ); - if( idx==8 ) NewElem = meshDS->AddVolumeWithID(aNds[0], - aNds[1], aNds[2], aNds[3], - aNds[4], aNds[5], aNds[6], - aNds[7] ,id ); - break; - default: - break; - } - - AddToSameGroups(NewElem, elem, meshDS); - if( theSm ) + SMDS_MeshElement * NewElem = AddElement( aNds, aType, false, id ); + if ( NewElem ) + AddToSameGroups(NewElem, elem, meshDS); + if ( NewElem != elem ) + RemoveElemFromGroups (elem, meshDS); + if( theSm && NewElem ) theSm->AddElement( NewElem ); + + // remove medium nodes + vector::iterator nIt = mediumNodes.begin(); + for ( ; nIt != mediumNodes.end(); ++nIt ) { + const SMDS_MeshNode* n = *nIt; + if ( n->NbInverseElements() == 0 ) { + if ( n->GetPosition()->GetShapeId() != theShapeID ) + meshDS->RemoveFreeNode( n, meshDS->MeshElements + ( n->GetPosition()->GetShapeId() )); + else + meshDS->RemoveFreeNode( n, theSm ); + } + } } } + return nbElem; } + //======================================================================= //function : ConvertFromQuadratic //purpose : //======================================================================= bool SMESH_MeshEditor::ConvertFromQuadratic() { - SMESHDS_Mesh* meshDS = GetMeshDS(); - RemoveQuadNodeMap aRemoveNodeMap; - - const TopoDS_Shape& aShape = meshDS->ShapeToMesh(); - - if ( !aShape.IsNull() && GetMesh()->GetSubMeshContaining(aShape) ) + int nbCheckedElems = 0; + if ( myMesh->HasShapeToMesh() ) { - SMESH_subMesh *aSubMesh = GetMesh()->GetSubMeshContaining(aShape); - - const map < int, SMESH_subMesh * >& aMapSM = aSubMesh->DependsOn(); - map < int, SMESH_subMesh * >::const_iterator itsub; - for (itsub = aMapSM.begin(); itsub != aMapSM.end(); itsub++) + if ( SMESH_subMesh *aSubMesh = myMesh->GetSubMeshContaining(myMesh->GetShapeToMesh())) { - SMESHDS_SubMesh *sm = ((*itsub).second)->GetSubMeshDS(); - if( sm ) - RemoveQuadElem( sm, sm->GetElements(), aRemoveNodeMap ); + SMESH_subMeshIteratorPtr smIt = aSubMesh->getDependsOnIterator(true,false); + while ( smIt->more() ) { + SMESH_subMesh* sm = smIt->next(); + if ( SMESHDS_SubMesh *smDS = sm->GetSubMeshDS() ) + nbCheckedElems += removeQuadElem( smDS, smDS->GetElements(), sm->GetId() ); + } } - SMESHDS_SubMesh *Sm = aSubMesh->GetSubMeshDS(); - if( Sm ) - RemoveQuadElem( Sm, Sm->GetElements(), aRemoveNodeMap ); } - else + + int totalNbElems = + GetMeshDS()->NbEdges() + GetMeshDS()->NbFaces() + GetMeshDS()->NbVolumes(); + if ( nbCheckedElems < totalNbElems ) // not all elements in submeshes { SMESHDS_SubMesh *aSM = 0; - RemoveQuadElem( aSM, meshDS->elementsIterator(), aRemoveNodeMap ); - } - - //remove all quadratic nodes - ItRemoveQuadNodeMap itRNM = aRemoveNodeMap.begin(); - for ( ; itRNM != aRemoveNodeMap.end(); itRNM++ ) - { - meshDS->RemoveFreeNode( (*itRNM).first, (*itRNM).second ); + removeQuadElem( aSM, GetMeshDS()->elementsIterator(), 0 ); } return true; @@ -6454,12 +6904,12 @@ bool SMESH_MeshEditor::ConvertFromQuadratic() //======================================================================= SMESH_MeshEditor::Sew_Error - SMESH_MeshEditor::SewSideElements (map& theSide1, - map& theSide2, - const SMDS_MeshNode* theFirstNode1, - const SMDS_MeshNode* theFirstNode2, - const SMDS_MeshNode* theSecondNode1, - const SMDS_MeshNode* theSecondNode2) + SMESH_MeshEditor::SewSideElements (TIDSortedElemSet& theSide1, + TIDSortedElemSet& theSide2, + const SMDS_MeshNode* theFirstNode1, + const SMDS_MeshNode* theFirstNode2, + const SMDS_MeshNode* theSecondNode1, + const SMDS_MeshNode* theSecondNode2) { myLastCreatedElems.Clear(); myLastCreatedNodes.Clear(); @@ -6490,16 +6940,16 @@ SMESH_MeshEditor::Sew_Error set * faceSetPtr[] = { &faceSet1, &faceSet2 }; set * volSetPtr[] = { &volSet1, &volSet2 }; set * nodeSetPtr[] = { &nodeSet1, &nodeSet2 }; - map * elemSetPtr[] = { &theSide1, &theSide2 }; + TIDSortedElemSet * elemSetPtr[] = { &theSide1, &theSide2 }; int iSide, iFace, iNode; for ( iSide = 0; iSide < 2; iSide++ ) { set * nodeSet = nodeSetPtr[ iSide ]; - map * elemSet = elemSetPtr[ iSide ]; + TIDSortedElemSet * elemSet = elemSetPtr[ iSide ]; set * faceSet = faceSetPtr[ iSide ]; set * volSet = volSetPtr [ iSide ]; set::iterator vIt; - map::iterator eIt; + TIDSortedElemSet::iterator eIt; set::iterator nIt; // check that given nodes belong to given elements @@ -6507,7 +6957,7 @@ SMESH_MeshEditor::Sew_Error const SMDS_MeshNode* n2 = ( iSide == 0 ) ? theSecondNode1 : theSecondNode2; int firstIndex = -1, secondIndex = -1; for (eIt = elemSet->begin(); eIt != elemSet->end(); eIt++ ) { - const SMDS_MeshElement* elem = (*eIt).second; + const SMDS_MeshElement* elem = *eIt; if ( firstIndex < 0 ) firstIndex = elem->GetNodeIndex( n1 ); if ( secondIndex < 0 ) secondIndex = elem->GetNodeIndex( n2 ); if ( firstIndex > -1 && secondIndex > -1 ) break; @@ -6528,7 +6978,7 @@ SMESH_MeshEditor::Sew_Error // loop on the given element of a side for (eIt = elemSet->begin(); eIt != elemSet->end(); eIt++ ) { //const SMDS_MeshElement* elem = *eIt; - const SMDS_MeshElement* elem = (*eIt).second; + const SMDS_MeshElement* elem = *eIt; if ( elem->GetType() == SMDSAbs_Face ) { faceSet->insert( elem ); set faceNodeSet; @@ -6548,7 +6998,7 @@ SMESH_MeshEditor::Sew_Error // ------------------------------------------------------------------------------ for ( nIt = nodeSet->begin(); nIt != nodeSet->end(); nIt++ ) { // loop on nodes of iSide - SMDS_ElemIteratorPtr fIt = (*nIt)->facesIterator(); + SMDS_ElemIteratorPtr fIt = (*nIt)->GetInverseElementIterator(SMDSAbs_Face); while ( fIt->more() ) { // loop on faces sharing a node const SMDS_MeshElement* f = fIt->next(); if ( faceSet->find( f ) == faceSet->end() ) { @@ -6644,7 +7094,7 @@ SMESH_MeshEditor::Sew_Error const SMDS_MeshElement* e = invElemIt->next(); if ( faceSet->find( e ) != faceSet->end() ) nbSharedNodes++; - if ( elemSet->find( e->GetID() ) != elemSet->end() ) + if ( elemSet->find( e ) != elemSet->end() ) nbSharedNodes++; } } @@ -6661,10 +7111,10 @@ SMESH_MeshEditor::Sew_Error // choose a face most close to the bary center of the opposite side gp_XYZ aBC( 0., 0., 0. ); set addedNodes; - map * elemSet2 = elemSetPtr[ 1 - iSide ]; + TIDSortedElemSet * elemSet2 = elemSetPtr[ 1 - iSide ]; eIt = elemSet2->begin(); for ( eIt = elemSet2->begin(); eIt != elemSet2->end(); eIt++ ) { - SMDS_ElemIteratorPtr nodeIt = (*eIt).second->nodesIterator(); + SMDS_ElemIteratorPtr nodeIt = (*eIt)->nodesIterator(); while ( nodeIt->more() ) { // loop on free face nodes const SMDS_MeshNode* n = static_cast( nodeIt->next() ); @@ -6708,7 +7158,7 @@ SMESH_MeshEditor::Sew_Error // // ---------------------------------------------------------- // if ( nodeSetSize != nodeSet->size() ) { // for ( ; nIt != nodeSet->end(); nIt++ ) { // loop on nodes of iSide -// SMDS_ElemIteratorPtr fIt = (*nIt)->facesIterator(); +// SMDS_ElemIteratorPtr fIt = (*nIt)->GetInverseElementIterator(SMDSAbs_Face); // while ( fIt->more() ) { // loop on faces sharing a node // const SMDS_MeshElement* f = fIt->next(); // if ( faceSet->find( f ) == faceSet->end() ) { @@ -6792,7 +7242,7 @@ SMESH_MeshEditor::Sew_Error set< const SMDS_MeshElement* > fMap; for ( int i = 0; i < 2; i++ ) { // loop on 2 nodes of a link const SMDS_MeshNode* n = i ? n1 : n2; // a node of a link - SMDS_ElemIteratorPtr fIt = n->facesIterator(); + 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 @@ -7039,20 +7489,9 @@ SMESH_MeshEditor::Sew_Error return aResult; } -/*! - * \brief A sorted pair of nodes - */ -struct TLink: public NLink -{ - TLink(const SMDS_MeshNode* n1, const SMDS_MeshNode* n2 ):NLink( n1, n2 ) - { if ( n1 < n2 ) std::swap( first, second ); } - TLink(const NLink& link ):NLink( link ) - { if ( first < second ) std::swap( first, second ); } -}; - //================================================================================ /*! - * \brief Find corresponding nodes in two sets of faces + * \brief Find corresponding nodes in two sets of faces * \param theSide1 - first face set * \param theSide2 - second first face * \param theFirstNode1 - a boundary node of set 1 @@ -7064,7 +7503,9 @@ struct TLink: public NLink */ //================================================================================ +#ifdef _DEBUG_ //#define DEBUG_MATCHING_NODES +#endif SMESH_MeshEditor::Sew_Error SMESH_MeshEditor::FindMatchingNodes(set& theSide1, @@ -7083,8 +7524,8 @@ SMESH_MeshEditor::FindMatchingNodes(set& theSide1, if ( theSecondNode1 != theSecondNode2 ) nReplaceMap.insert( make_pair( theSecondNode1, theSecondNode2 )); - set< TLink > linkSet; // set of nodes where order of nodes is ignored - linkSet.insert( TLink( theFirstNode1, theSecondNode1 )); + 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 )); @@ -7118,11 +7559,10 @@ SMESH_MeshEditor::FindMatchingNodes(set& theSide1, // 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(); + SMDS_ElemIteratorPtr fIt = n->GetInverseElementIterator(SMDSAbs_Face); while ( fIt->more() ) { // loop on faces sharing a node const SMDS_MeshElement* f = fIt->next(); - if (f->GetType() == SMDSAbs_Face && - faceSet->find( f ) != faceSet->end() && // f is in face set + if (faceSet->find( f ) != faceSet->end() && // f is in face set ! facesOfNode1.insert( f ).second ) // f encounters twice { if ( face[ iSide ] ) { @@ -7176,10 +7616,9 @@ SMESH_MeshEditor::FindMatchingNodes(set& theSide1, return SEW_TOPO_DIFF_SETS_OF_ELEMENTS; } #ifdef DEBUG_MATCHING_NODES - cout << " Link 1: " << link[0].first->GetID() <<" "<< link[0].second->GetID() - << " F 1: " << face[0]; - cout << "| Link 2: " << link[1].first->GetID() <<" "<< link[1].second->GetID() - << " F 2: " << face[1] << " | Bind: "<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]; { @@ -7187,7 +7626,7 @@ SMESH_MeshEditor::FindMatchingNodes(set& theSide1, list::iterator n2 = notLinkNodes[1].begin(); for ( int i = 0 ; i < nbN - 2; ++i ) { #ifdef DEBUG_MATCHING_NODES - cout << (*n1)->GetID() << " to " << (*n2)->GetID() << endl; + MESSAGE ( (*n1)->GetID() << " to " << (*n2)->GetID() ); #endif nReplaceMap.insert( make_pair( *(n1++), *(n2++) )); } @@ -7201,16 +7640,16 @@ SMESH_MeshEditor::FindMatchingNodes(set& theSide1, for ( int i = 0; i < nbN; i++ ) { const SMDS_MeshNode* n2 = f0->GetNode( i ); - pair< set< TLink >::iterator, bool > iter_isnew = - linkSet.insert( TLink( n1, n2 )); + 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 - cout << "Add link 1: " << n1->GetID() << " " << n2->GetID() << " "; - cout << " | link 2: " << nReplaceMap[n1]->GetID() << " " << nReplaceMap[n2]->GetID() << " " << endl; + 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] )); @@ -7222,3 +7661,92 @@ SMESH_MeshEditor::FindMatchingNodes(set& theSide1, return SEW_OK; } + +/*! + \brief Creates a hole in a mesh by doubling the nodes of some particular elements + \param theNodes - identifiers of nodes to be doubled + \param 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 + \return TRUE if operation has been completed successfully, FALSE otherwise +*/ +bool SMESH_MeshEditor::DoubleNodes( const std::list< int >& theListOfNodes, + const std::list< int >& theListOfModifiedElems ) +{ + 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 > 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 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 >::iterator + anElemToNodesIter = anElemToNodes.begin(); + for ( ; anElemToNodesIter != anElemToNodes.end(); ++anElemToNodesIter ) + { + const SMDS_MeshElement* anElem = anElemToNodesIter->first; + vector aNodeArr = anElemToNodesIter->second; + if ( anElem ) + aMeshDS->ChangeElementNodes( anElem, &aNodeArr[ 0 ], anElem->NbNodes() ); + } + + return true; +}