X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSMESH%2FSMESH_MeshEditor.cxx;h=13e319ab58a3da2ab1f2e2ffa6fad1dec2a818b9;hb=6fae6dddb4668825724fe4f126b48e352df0c18d;hp=71a4d3c1136e7bb1d70a09471d8f6d99c137ee71;hpb=e4737e85f0da6d3f90fd08f6be1c2825195fe16f;p=modules%2Fsmesh.git diff --git a/src/SMESH/SMESH_MeshEditor.cxx b/src/SMESH/SMESH_MeshEditor.cxx index 71a4d3c11..13e319ab5 100644 --- a/src/SMESH/SMESH_MeshEditor.cxx +++ b/src/SMESH/SMESH_MeshEditor.cxx @@ -28,31 +28,46 @@ #include "SMESH_MeshEditor.hxx" +#include "SMESH_ControlsDef.hxx" + #include "SMDS_FaceOfNodes.hxx" #include "SMDS_VolumeTool.hxx" #include "SMESHDS_Group.hxx" #include "SMESHDS_Mesh.hxx" #include "SMESH_subMesh.hxx" +#include "SMESH_ControlsDef.hxx" #include "utilities.h" -#include #include #include +#include +#include #include #include #include #include +#include #include #include +#include +#include +#include + #include +#include "utilities.h" + using namespace std; +using namespace SMESH::Controls; -typedef map TNodeNodeMap; -typedef map > TNodeOfNodeListMap; -typedef map > TElemOfNodeListMap; +typedef map TNodeNodeMap; +typedef map > TElemOfNodeListMap; +typedef map > TElemOfElemListMap; +typedef map > TNodeOfNodeListMap; +typedef TNodeOfNodeListMap::iterator TNodeOfNodeListMapItr; +typedef map > TElemOfVecOfNnlmiMap; //======================================================================= //function : SMESH_MeshEditor @@ -455,34 +470,40 @@ bool SMESH_MeshEditor::DeleteDiag (const SMDS_MeshNode * theNode1, //======================================================================= //function : Reorient -//purpose : Reverse the normal of theFace -// Return false if theFace is null +//purpose : Reverse theElement orientation //======================================================================= -bool SMESH_MeshEditor::Reorient (const SMDS_MeshElement * theFace) +bool SMESH_MeshEditor::Reorient (const SMDS_MeshElement * theElem) { - if (!theFace) return false; - const SMDS_FaceOfNodes* F = dynamic_cast( theFace ); - if (!F) return false; - - const SMDS_MeshNode* aNodes [4], *tmpNode; - int i = 0; - SMDS_ElemIteratorPtr it = theFace->nodesIterator(); - while ( it->more() ) - aNodes[ i++ ] = static_cast( it->next() ); - - // exchange nodes with indeces 0 and 2 - tmpNode = aNodes[ 0 ]; - aNodes[ 0 ] = aNodes[ 2 ]; - aNodes[ 2 ] = tmpNode; - - //MESSAGE( theFace ); - - GetMeshDS()->ChangeElementNodes( theFace, aNodes, theFace->NbNodes() ); + if (!theElem) + return false; + SMDS_ElemIteratorPtr it = theElem->nodesIterator(); + if ( !it || !it->more() ) + return false; - //MESSAGE( theFace ); + switch ( theElem->GetType() ) { + + case SMDSAbs_Edge: + case SMDSAbs_Face: + { + int i = theElem->NbNodes(); + vector aNodes( i ); + while ( it->more() ) + aNodes[ --i ]= static_cast( it->next() ); + return GetMeshDS()->ChangeElementNodes( theElem, &aNodes[0], theElem->NbNodes() ); + } + case SMDSAbs_Volume: + { + SMDS_VolumeTool vTool; + if ( !vTool.Set( theElem )) + return false; + vTool.Inverse(); + return GetMeshDS()->ChangeElementNodes( theElem, vTool.GetNodes(), vTool.NbNodes() ); + } + default:; + } - return true; + return false; } //======================================================================= @@ -493,7 +514,7 @@ bool SMESH_MeshEditor::Reorient (const SMDS_MeshElement * theFace) static double getBadRate (const SMDS_MeshElement* theElem, SMESH::Controls::NumericalFunctorPtr& theCrit) { - TColgp_SequenceOfXYZ P; + SMESH::Controls::TSequenceOfXYZ P; if ( !theElem || !theCrit->GetPoints( theElem, P )) return 1e100; return theCrit->GetBadRate( theCrit->GetValue( P ), theElem->NbNodes() ); @@ -568,13 +589,13 @@ bool SMESH_MeshEditor::QuadToTri (set & theElems, } //======================================================================= -//function : addToSameGroups +//function : AddToSameGroups //purpose : add elemToAdd to the groups the elemInGroups belongs to //======================================================================= -static void addToSameGroups (const SMDS_MeshElement* elemToAdd, - const SMDS_MeshElement* elemInGroups, - SMESHDS_Mesh * aMesh) +void SMESH_MeshEditor::AddToSameGroups (const SMDS_MeshElement* elemToAdd, + const SMDS_MeshElement* elemInGroups, + SMESHDS_Mesh * aMesh) { const set& groups = aMesh->GetGroups(); set::const_iterator grIt = groups.begin(); @@ -630,7 +651,7 @@ bool SMESH_MeshEditor::QuadToTri (std::set & theElems, if ( aShapeId ) aMesh->SetMeshElementOnShape( newElem, aShapeId ); - addToSameGroups( newElem, elem, aMesh ); + AddToSameGroups( newElem, elem, aMesh ); } return true; @@ -649,7 +670,7 @@ double getAngle(const SMDS_MeshElement * tr1, double angle = 2*PI; // bad angle // get normals - TColgp_SequenceOfXYZ P1, P2; + SMESH::Controls::TSequenceOfXYZ P1, P2; if ( !SMESH::Controls::NumericalFunctor::GetPoints( tr1, P1 ) || !SMESH::Controls::NumericalFunctor::GetPoints( tr2, P2 )) return angle; @@ -1315,13 +1336,13 @@ void centroidalSmooth(SMESHDS_Mesh * theMesh, nbElems++; gp_XYZ elemCenter(0.,0.,0.); - TColgp_SequenceOfXYZ aNodePoints; + SMESH::Controls::TSequenceOfXYZ aNodePoints; SMDS_ElemIteratorPtr itN = elem->nodesIterator(); while ( itN->more() ) { const SMDS_MeshNode* aNode = static_cast( itN->next() ); gp_XYZ aP( aNode->X(), aNode->Y(), aNode->Z() ); - aNodePoints.Append( aP ); + aNodePoints.push_back( aP ); elemCenter += aP; } double elemArea = anAreaFunc.GetValue( aNodePoints ); @@ -1453,7 +1474,7 @@ void SMESH_MeshEditor::Smooth (set & theElems, const SMDS_MeshElement* elem = (*itElem); if ( !elem || elem->GetType() != SMDSAbs_Face ) continue; - TColgp_SequenceOfXYZ aPoints; + SMESH::Controls::TSequenceOfXYZ aPoints; if ( aQualityFunc.GetPoints( elem, aPoints )) { double aValue = aQualityFunc.GetValue( aPoints ); if ( aValue > maxRatio ) @@ -1472,7 +1493,9 @@ void SMESH_MeshEditor::Smooth (set & theElems, //======================================================================= //function : isReverse -//purpose : +//purpose : Return true if normal of prevNodes is not co-directied with +// gp_Vec(prevNodes[iNotSame],nextNodes[iNotSame]). +// iNotSame is where prevNodes and nextNodes are different //======================================================================= static bool isReverse(const SMDS_MeshNode* prevNodes[], @@ -1500,42 +1523,39 @@ static bool isReverse(const SMDS_MeshNode* prevNodes[], //======================================================================= //function : sweepElement -//purpose : +//purpose : //======================================================================= -static void sweepElement(SMESHDS_Mesh* aMesh, - const SMDS_MeshElement* elem, - const TNodeOfNodeListMap& mapNewNodes ) +static void sweepElement(SMESHDS_Mesh* aMesh, + const SMDS_MeshElement* elem, + const vector & newNodesItVec, + list& newElems) { // Loop on elem nodes: // find new nodes and detect same nodes indices - list::const_iterator itNN[ 4 ]; - const SMDS_MeshNode* prevNod[ 4 ], *nextNod[ 4 ]; - int nbSame = 0, iNotSameNode = 0, iSameNode = 0; - - TNodeOfNodeListMap::const_iterator mapIt; - int iNode = 0; - SMDS_ElemIteratorPtr itN = elem->nodesIterator(); - while ( itN->more() ) + int nbNodes = elem->NbNodes(); + list::const_iterator itNN[ nbNodes ]; + const SMDS_MeshNode* prevNod[ nbNodes ], *nextNod[ nbNodes ]; + int iNode, nbSame = 0, iNotSameNode = 0, iSameNode = 0; + + for ( iNode = 0; iNode < nbNodes; iNode++ ) { - const SMDS_MeshNode* node = - static_cast( itN->next() ); - mapIt = mapNewNodes.find( node ); - if ( mapIt == mapNewNodes.end() ) - return; // not duplicated node + TNodeOfNodeListMapItr nnIt = newNodesItVec[ iNode ]; + const SMDS_MeshNode* node = nnIt->first; + const list< const SMDS_MeshNode* > & listNewNodes = nnIt->second; + if ( listNewNodes.empty() ) + return; - itNN[ iNode ] = (*mapIt).second.begin(); + itNN[ iNode ] = listNewNodes.begin(); prevNod[ iNode ] = node; - nextNod[ iNode ] = (*mapIt).second.front(); + nextNod[ iNode ] = listNewNodes.front(); if ( prevNod[ iNode ] != nextNod [ iNode ]) iNotSameNode = iNode; else { iSameNode = iNode; nbSame++; } - iNode++; } - int nbNodes = iNode; if ( nbSame == nbNodes || nbSame > 2) { MESSAGE( " Too many same nodes of element " << elem->GetID() ); return; @@ -1550,8 +1570,8 @@ static void sweepElement(SMESHDS_Mesh* aMesh, // check element orientation int i0 = 0, i2 = 2; - if ( nbNodes > 2 && isReverse( prevNod, nextNod, nbNodes, iNotSameNode )) { -// MESSAGE("Reversed elem " << elem->GetID() ); + if ( nbNodes > 2 && !isReverse( prevNod, nextNod, nbNodes, iNotSameNode )) { + //MESSAGE("Reversed elem " << elem ); i0 = 2; i2 = 0; if ( nbSame > 0 ) { @@ -1562,7 +1582,7 @@ static void sweepElement(SMESHDS_Mesh* aMesh, } // make new elements - int iStep, nbSteps = (*mapIt).second.size(); + int iStep, nbSteps = newNodesItVec[ 0 ]->second.size(); for (iStep = 0; iStep < nbSteps; iStep++ ) { // get next nodes @@ -1570,69 +1590,76 @@ static void sweepElement(SMESHDS_Mesh* aMesh, nextNod[ iNode ] = *itNN[ iNode ]; itNN[ iNode ]++; } + SMDS_MeshElement* aNewElem = 0; switch ( nbNodes ) { + case 1: { // NODE + if ( nbSame == 0 ) + aNewElem = aMesh->AddEdge( prevNod[ 0 ], nextNod[ 0 ] ); + break; + } case 2: { // EDGE if ( nbSame == 0 ) - aMesh->AddFace( prevNod[ 0 ], prevNod[ 1 ], nextNod[ 1 ], nextNod[ 0 ] ); + aNewElem = aMesh->AddFace(prevNod[ 0 ], prevNod[ 1 ], + nextNod[ 1 ], nextNod[ 0 ] ); else - aMesh->AddFace( prevNod[ 0 ], prevNod[ 1 ], nextNod[ iNotSameNode ] ); + aNewElem = aMesh->AddFace(prevNod[ 0 ], prevNod[ 1 ], + nextNod[ iNotSameNode ] ); break; } case 3: { // TRIANGLE - if ( nbSame == 0 ) // --- 1 pentahedron - { - aMesh->AddVolume (prevNod[ i2 ], prevNod[ 1 ], prevNod[ i0 ], - nextNod[ i2 ], nextNod[ 1 ], nextNod[ i0 ] ); - } - else if ( nbSame == 1 ) // --- 2 tetrahedrons - { - aMesh->AddVolume (prevNod[ i0 ], prevNod[ 1 ], prevNod[ i2 ], - nextNod[ iBeforeSame ]); - aMesh->AddVolume (nextNod[ i2 ], nextNod[ 1 ], nextNod[ i0 ], - prevNod[ iAfterSame ]); - } - else // 2 same nodes: --- 1 tetrahedron - { - aMesh->AddVolume (prevNod[ i0 ], prevNod[ 1 ], prevNod[ i2 ], - nextNod[ iNotSameNode ]); - } + if ( nbSame == 0 ) // --- pentahedron + aNewElem = aMesh->AddVolume (prevNod[ i0 ], prevNod[ 1 ], prevNod[ i2 ], + nextNod[ i0 ], nextNod[ 1 ], nextNod[ i2 ] ); + + else if ( nbSame == 1 ) // --- pyramid + aNewElem = aMesh->AddVolume (prevNod[ iAfterSame ], prevNod[ iBeforeSame ], + nextNod[ iBeforeSame ], nextNod[ iAfterSame ], + nextNod[ iSameNode ]); + + else // 2 same nodes: --- tetrahedron + aNewElem = aMesh->AddVolume (prevNod[ i0 ], prevNod[ 1 ], prevNod[ i2 ], + nextNod[ iNotSameNode ]); break; } case 4: { // QUADRANGLE - if ( nbSame == 0 ) // --- 1 hexahedron - { - aMesh->AddVolume (prevNod[ i0 ], prevNod[ 1 ], prevNod[ i2 ], prevNod[ 3 ], - nextNod[ i0 ], nextNod[ 1 ], nextNod[ i2 ], nextNod[ 3 ]); - } - else if ( nbSame == 1 ) // --- 2 tetrahedrons + 1 pentahedron + 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 { - aMesh->AddVolume (prevNod[ iBeforeSame ], prevNod[ iSameNode ], - prevNod[ iAfterSame ], nextNod[ iBeforeSame ]); - aMesh->AddVolume (nextNod[ iAfterSame ], nextNod[ iSameNode ], - nextNod[ iBeforeSame ], prevNod[ iAfterSame ]); - aMesh->AddVolume (prevNod[ iBeforeSame ], prevNod[ iOpposSame ], prevNod[ iAfterSame ], - nextNod[ iBeforeSame ], nextNod[ iOpposSame ], nextNod[ iAfterSame ] ); + aNewElem = aMesh->AddVolume (prevNod[ iAfterSame ], prevNod[ iBeforeSame ], + nextNod[ iBeforeSame ], nextNod[ iAfterSame ], + nextNod[ iSameNode ]); + newElems.push_back( aNewElem ); + aNewElem = aMesh->AddVolume (prevNod[ iBeforeSame ], prevNod[ iOpposSame ], + prevNod[ iAfterSame ], nextNod[ iBeforeSame ], + nextNod[ iOpposSame ], nextNod[ iAfterSame ] ); } - else if ( nbSame == 2 ) // 1 pentahedron + else if ( nbSame == 2 ) // pentahedron { if ( prevNod[ iBeforeSame ] == nextNod[ iBeforeSame ] ) // iBeforeSame is same too - aMesh->AddVolume (prevNod[ iOpposSame ], prevNod[ iBeforeSame ], nextNod[ iOpposSame ], - prevNod[ iAfterSame ], prevNod[ iSameNode ], nextNod[ iAfterSame ]); + aNewElem = aMesh->AddVolume (prevNod[ iOpposSame ], prevNod[ iBeforeSame ], + nextNod[ iOpposSame ], prevNod[ iAfterSame ], + prevNod[ iSameNode ], nextNod[ iAfterSame ]); else // iAfterSame is same too - aMesh->AddVolume (prevNod[ iBeforeSame ], prevNod[ iSameNode ], nextNod[ iBeforeSame ], - prevNod[ iOpposSame ], prevNod[ iAfterSame ], nextNod[ iOpposSame ]); + aNewElem = aMesh->AddVolume (prevNod[ iBeforeSame ], prevNod[ iSameNode ], + nextNod[ iBeforeSame ], prevNod[ iOpposSame ], + prevNod[ iAfterSame ], nextNod[ iOpposSame ]); } break; } default: return; } + if ( aNewElem ) + newElems.push_back( aNewElem ); // set new prev nodes for ( iNode = 0; iNode < nbNodes; iNode++ ) @@ -1641,6 +1668,162 @@ static void sweepElement(SMESHDS_Mesh* aMesh, } // for steps } +//======================================================================= +//function : makeWalls +//purpose : create 1D and 2D elements around swept elements +//======================================================================= + +static void makeWalls (SMESHDS_Mesh* aMesh, + TNodeOfNodeListMap & mapNewNodes, + TElemOfElemListMap & newElemsMap, + TElemOfVecOfNnlmiMap & elemNewNodesMap, + set& elemSet) +{ + ASSERT( newElemsMap.size() == elemNewNodesMap.size() ); + + // Find nodes belonging to only one initial element - sweep them to get edges. + + TNodeOfNodeListMapItr nList = mapNewNodes.begin(); + for ( ; nList != mapNewNodes.end(); nList++ ) + { + const SMDS_MeshNode* node = + static_cast( nList->first ); + SMDS_ElemIteratorPtr eIt = node->GetInverseElementIterator(); + int nbInitElems = 0; + while ( eIt->more() && nbInitElems < 2 ) + if ( elemSet.find( eIt->next() ) != elemSet.end() ) + nbInitElems++; + if ( nbInitElems < 2 ) { + vector newNodesItVec( 1, nList ); + list newEdges; + sweepElement( aMesh, node, newNodesItVec, newEdges ); + } + } + + // Make a ceiling for each element ie an equal element of last new nodes. + // Find free links of faces - make edges and sweep them into faces. + + TElemOfElemListMap::iterator itElem = newElemsMap.begin(); + TElemOfVecOfNnlmiMap::iterator itElemNodes = elemNewNodesMap.begin(); + for ( ; itElem != newElemsMap.end(); itElem++, itElemNodes++ ) + { + const SMDS_MeshElement* elem = itElem->first; + vector& vecNewNodes = itElemNodes->second; + + if ( elem->GetType() == SMDSAbs_Edge ) + { + // create a ceiling edge + aMesh->AddEdge(vecNewNodes[ 0 ]->second.back(), + vecNewNodes[ 1 ]->second.back() ); + } + if ( elem->GetType() != SMDSAbs_Face ) + continue; + + bool hasFreeLinks = false; + + set avoidSet; + avoidSet.insert( elem ); + + // loop on a face nodes + set aFaceLastNodes; + int iNode, nbNodes = vecNewNodes.size(); + for ( iNode = 0; iNode < nbNodes; iNode++ ) + { + aFaceLastNodes.insert( vecNewNodes[ iNode ]->second.back() ); + // look for free links of a face + int iNext = ( iNode + 1 == nbNodes ) ? 0 : iNode + 1; + const SMDS_MeshNode* n1 = vecNewNodes[ iNode ]->first; + const SMDS_MeshNode* n2 = vecNewNodes[ iNext ]->first; + // check if a link is free + if ( ! SMESH_MeshEditor::FindFaceInSet ( n1, n2, elemSet, avoidSet )) + { + hasFreeLinks = true; + // make an edge and a ceiling for a new edge + if ( !aMesh->FindEdge( n1, n2 )) + aMesh->AddEdge( n1, n2 ); + n1 = vecNewNodes[ iNode ]->second.back(); + n2 = vecNewNodes[ iNext ]->second.back(); + if ( !aMesh->FindEdge( n1, n2 )) + aMesh->AddEdge( n1, n2 ); + } + } + // sweep free links into faces + + 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++ ) + initNodeSet.insert( vecNewNodes[ iNode ]->first ); + + 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; + 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 ( fInd.empty() ) + continue; + + // create faces for all steps + for ( iStep = 0; iStep < nbSteps; iStep++ ) + { + vTool.Set( *v ); + vTool.SetExternalNormal(); + list< int >::iterator ind = fInd.begin(); + for ( ; ind != fInd.end(); ind++ ) + { + const SMDS_MeshNode** nodes = vTool.GetFaceNodes( *ind ); + switch ( vTool.NbFaceNodes( *ind ) ) { + case 3: + aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] ); break; + case 4: + aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ] ); break; + } + } + // go to the next volume + iVol = 0; + while ( iVol++ < nbVolumesByStep ) v++; + } + } + } // sweep free links into faces + + // make a ceiling face with a normal external to a volume + + SMDS_VolumeTool lastVol( itElem->second.back() ); + int iF = lastVol.GetFaceIndex( aFaceLastNodes ); + if ( iF >= 0 ) + { + lastVol.SetExternalNormal(); + const SMDS_MeshNode** nodes = lastVol.GetFaceNodes( iF ); + switch ( lastVol.NbFaceNodes( iF ) ) { + case 3: + if (!hasFreeLinks || + !aMesh->FindFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ])) + aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] ); + break; + case 4: + if (!hasFreeLinks || + !aMesh->FindFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ])) + aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ] ); + break; + } + } + + } // loop on swept elements +} + //======================================================================= //function : RotationSweep //purpose : @@ -1652,6 +1835,7 @@ void SMESH_MeshEditor::RotationSweep(set & theElems, const int theNbSteps, const double theTol) { + MESSAGE( "RotationSweep()"); gp_Trsf aTrsf; aTrsf.SetRotation( theAxis, theAngle ); @@ -1661,17 +1845,18 @@ void SMESH_MeshEditor::RotationSweep(set & theElems, SMESHDS_Mesh* aMesh = GetMeshDS(); TNodeOfNodeListMap mapNewNodes; + TElemOfVecOfNnlmiMap mapElemNewNodes; + TElemOfElemListMap newElemsMap; // loop on theElems set< const SMDS_MeshElement* >::iterator itElem; for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) { - // check element type const SMDS_MeshElement* elem = (*itElem); - if ( !elem || - (elem->GetType() != SMDSAbs_Face && - elem->GetType() != SMDSAbs_Edge )) + if ( !elem ) continue; + vector & newNodesItVec = mapElemNewNodes[ elem ]; + newNodesItVec.reserve( elem->NbNodes() ); // loop on elem nodes SMDS_ElemIteratorPtr itN = elem->nodesIterator(); @@ -1680,28 +1865,34 @@ void SMESH_MeshEditor::RotationSweep(set & theElems, // check if a node has been already sweeped const SMDS_MeshNode* node = static_cast( itN->next() ); - if (mapNewNodes.find( node ) != mapNewNodes.end() ) - continue; - - list& listNewNodes = mapNewNodes[ node ]; - - // make new nodes - gp_XYZ aXYZ( node->X(), node->Y(), node->Z() ); - double coord[3]; - aXYZ.Coord( coord[0], coord[1], coord[2] ); - bool isOnAxis = ( aLine.SquareDistance( aXYZ ) <= aSqTol ); - const SMDS_MeshNode * newNode = node; - for ( int i = 0; i < theNbSteps; i++ ) { - if ( !isOnAxis ) { - aTrsf.Transforms( coord[0], coord[1], coord[2] ); - newNode = aMesh->AddNode( coord[0], coord[1], coord[2] ); + TNodeOfNodeListMapItr nIt = mapNewNodes.find( node ); + if ( nIt == mapNewNodes.end() ) + { + nIt = mapNewNodes.insert( make_pair( node, list() )).first; + list& listNewNodes = nIt->second; + + // make new nodes + gp_XYZ aXYZ( node->X(), node->Y(), node->Z() ); + double coord[3]; + aXYZ.Coord( coord[0], coord[1], coord[2] ); + bool isOnAxis = ( aLine.SquareDistance( aXYZ ) <= aSqTol ); + const SMDS_MeshNode * newNode = node; + for ( int i = 0; i < theNbSteps; i++ ) { + if ( !isOnAxis ) { + aTrsf.Transforms( coord[0], coord[1], coord[2] ); + newNode = aMesh->AddNode( coord[0], coord[1], coord[2] ); + } + listNewNodes.push_back( newNode ); } - listNewNodes.push_back( newNode ); } + newNodesItVec.push_back( nIt ); } // make new elements - sweepElement( aMesh, elem, mapNewNodes ); + sweepElement( aMesh, elem, newNodesItVec, newElemsMap[elem] ); } + + makeWalls( aMesh, mapNewNodes, newElemsMap, mapElemNewNodes, theElems ); + } //======================================================================= //function : ExtrusionSweep @@ -1718,6 +1909,8 @@ void SMESH_MeshEditor::ExtrusionSweep(set & theElems, SMESHDS_Mesh* aMesh = GetMeshDS(); TNodeOfNodeListMap mapNewNodes; + TElemOfVecOfNnlmiMap mapElemNewNodes; + TElemOfElemListMap newElemsMap; // loop on theElems set< const SMDS_MeshElement* >::iterator itElem; @@ -1725,11 +1918,12 @@ void SMESH_MeshEditor::ExtrusionSweep(set & theElems, { // check element type const SMDS_MeshElement* elem = (*itElem); - if ( !elem || - (elem->GetType() != SMDSAbs_Face && - elem->GetType() != SMDSAbs_Edge)) + if ( !elem ) continue; + vector & newNodesItVec = mapElemNewNodes[ elem ]; + newNodesItVec.reserve( elem->NbNodes() ); + // loop on elem nodes SMDS_ElemIteratorPtr itN = elem->nodesIterator(); while ( itN->more() ) { @@ -1737,25 +1931,353 @@ void SMESH_MeshEditor::ExtrusionSweep(set & theElems, // check if a node has been already sweeped const SMDS_MeshNode* node = static_cast( itN->next() ); - if (mapNewNodes.find( node ) != mapNewNodes.end() ) - continue; + TNodeOfNodeListMap::iterator nIt = mapNewNodes.find( node ); + if ( nIt == mapNewNodes.end() ) + { + nIt = mapNewNodes.insert( make_pair( node, list() )).first; + list& listNewNodes = nIt->second; - list& listNewNodes = mapNewNodes[ node ]; + // make new nodes + double coord[] = { node->X(), node->Y(), node->Z() }; + for ( int i = 0; i < theNbSteps; i++ ) { + aTrsf.Transforms( coord[0], coord[1], coord[2] ); + const SMDS_MeshNode * newNode = aMesh->AddNode( coord[0], coord[1], coord[2] ); + listNewNodes.push_back( newNode ); + } + } + newNodesItVec.push_back( nIt ); + } + // make new elements + sweepElement( aMesh, elem, newNodesItVec, newElemsMap[elem] ); + } + makeWalls( aMesh, mapNewNodes, newElemsMap, mapElemNewNodes, theElems ); +} - // make new nodes - double coord[3]; - coord[0] = node->X(); - coord[1] = node->Y(); - coord[2] = node->Z(); - for ( int i = 0; i < theNbSteps; i++ ) { - aTrsf.Transforms( coord[0], coord[1], coord[2] ); - const SMDS_MeshNode * newNode = aMesh->AddNode( coord[0], coord[1], coord[2] ); - listNewNodes.push_back( newNode ); +//======================================================================= +//class : SMESH_MeshEditor_PathPoint +//purpose : auxiliary class +//======================================================================= +class SMESH_MeshEditor_PathPoint { +public: + SMESH_MeshEditor_PathPoint() { + myPnt.SetCoord(99., 99., 99.); + myTgt.SetCoord(1.,0.,0.); + myAngle=0.; + myPrm=0.; + } + void SetPnt(const gp_Pnt& aP3D){ + myPnt=aP3D; + } + void SetTangent(const gp_Dir& aTgt){ + myTgt=aTgt; + } + void SetAngle(const double& aBeta){ + myAngle=aBeta; + } + void SetParameter(const double& aPrm){ + myPrm=aPrm; + } + const gp_Pnt& Pnt()const{ + return myPnt; + } + const gp_Dir& Tangent()const{ + return myTgt; + } + double Angle()const{ + return myAngle; + } + double Parameter()const{ + return myPrm; + } + +protected: + gp_Pnt myPnt; + gp_Dir myTgt; + double myAngle; + double myPrm; +}; + +//======================================================================= +//function : ExtrusionAlongTrack +//purpose : +//======================================================================= +SMESH_MeshEditor::Extrusion_Error + SMESH_MeshEditor::ExtrusionAlongTrack (std::set & theElements, + SMESH_subMesh* theTrack, + const SMDS_MeshNode* theN1, + const bool theHasAngles, + std::list& theAngles, + const bool theHasRefPoint, + const gp_Pnt& theRefPoint) +{ + MESSAGE("SMESH_MeshEditor::ExtrusionAlongTrack") + int j, aNbTP, aNbE, aNb; + double aT1, aT2, aT, aAngle, aX, aY, aZ; + std::list aPrms; + std::list::iterator aItD; + std::set< const SMDS_MeshElement* >::iterator itElem; + + Standard_Real aTx1, aTx2, aL2, aTolVec, aTolVec2; + gp_Pnt aP3D, aV0; + gp_Vec aVec; + gp_XYZ aGC; + Handle(Geom_Curve) aC3D; + TopoDS_Edge aTrackEdge; + TopoDS_Vertex aV1, aV2; + + SMDS_ElemIteratorPtr aItE; + SMDS_NodeIteratorPtr aItN; + SMDSAbs_ElementType aTypeE; + + TNodeOfNodeListMap mapNewNodes; + TElemOfVecOfNnlmiMap mapElemNewNodes; + TElemOfElemListMap newElemsMap; + + aTolVec=1.e-7; + aTolVec2=aTolVec*aTolVec; + + // 1. Check data + aNbE = theElements.size(); + // nothing to do + if ( !aNbE ) + return EXTR_NO_ELEMENTS; + + // 1.1 Track Pattern + ASSERT( theTrack ); + + SMESHDS_SubMesh* pSubMeshDS=theTrack->GetSubMeshDS(); + + aItE = pSubMeshDS->GetElements(); + while ( aItE->more() ) { + const SMDS_MeshElement* pE = aItE->next(); + aTypeE = pE->GetType(); + // Pattern must contain links only + if ( aTypeE != SMDSAbs_Edge ) + return EXTR_PATH_NOT_EDGE; + } + + const TopoDS_Shape& aS = theTrack->GetSubShape(); + // Sub shape for the Pattern must be an Edge + if ( aS.ShapeType() != TopAbs_EDGE ) + return EXTR_BAD_PATH_SHAPE; + + aTrackEdge = TopoDS::Edge( aS ); + // the Edge must not be degenerated + if ( BRep_Tool::Degenerated( aTrackEdge ) ) + return EXTR_BAD_PATH_SHAPE; + + TopExp::Vertices( aTrackEdge, aV1, aV2 ); + aT1=BRep_Tool::Parameter( aV1, aTrackEdge ); + aT2=BRep_Tool::Parameter( aV2, aTrackEdge ); + + aItN = theTrack->GetFather()->GetSubMesh( aV1 )->GetSubMeshDS()->GetNodes(); + const SMDS_MeshNode* aN1 = aItN->next(); + + aItN = theTrack->GetFather()->GetSubMesh( aV2 )->GetSubMeshDS()->GetNodes(); + const SMDS_MeshNode* aN2 = aItN->next(); + + // starting node must be aN1 or aN2 + if ( !( aN1 == theN1 || aN2 == theN1 ) ) + return EXTR_BAD_STARTING_NODE; + + aNbTP = pSubMeshDS->NbNodes() + 2; + + // 1.2. Angles + vector aAngles( aNbTP ); + + for ( j=0; j < aNbTP; ++j ) { + aAngles[j] = 0.; + } + + if ( theHasAngles ) { + aItD = theAngles.begin(); + for ( j=1; (aItD != theAngles.end()) && (jGetNodes(); + while ( aItN->more() ) { + const SMDS_MeshNode* pNode = aItN->next(); + const SMDS_EdgePosition* pEPos = + static_cast( pNode->GetPosition().get() ); + aT = pEPos->GetUParameter(); + aPrms.push_back( aT ); + } + + // sort parameters + aPrms.sort(); + if ( aN1 == theN1 ) { + if ( aT1 > aT2 ) { + aPrms.reverse(); + } + } + else { + if ( aT2 > aT1 ) { + aPrms.reverse(); + } + } + + // 3. Path Points + SMESH_MeshEditor_PathPoint aPP; + vector aPPs( aNbTP ); + // + aC3D = BRep_Tool::Curve( aTrackEdge, aTx1, aTx2 ); + // + aItD = aPrms.begin(); + for ( j=0; aItD != aPrms.end(); ++aItD, ++j ) { + aT = *aItD; + aC3D->D1( aT, aP3D, aVec ); + aL2 = aVec.SquareMagnitude(); + if ( aL2 < aTolVec2 ) + return EXTR_CANT_GET_TANGENT; + + gp_Dir aTgt( aVec ); + aAngle = aAngles[j]; + + aPP.SetPnt( aP3D ); + aPP.SetTangent( aTgt ); + aPP.SetAngle( aAngle ); + aPP.SetParameter( aT ); + aPPs[j]=aPP; + } + + // 3. Center of rotation aV0 + aV0 = theRefPoint; + if ( !theHasRefPoint ) { + aNb = 0; + aGC.SetCoord( 0.,0.,0. ); + + itElem = theElements.begin(); + for ( ; itElem != theElements.end(); itElem++ ) { + const SMDS_MeshElement* elem = (*itElem); + + SMDS_ElemIteratorPtr itN = elem->nodesIterator(); + while ( itN->more() ) { + const SMDS_MeshNode* node = static_cast( itN->next() ); + aX = node->X(); + aY = node->Y(); + aZ = node->Z(); + + if ( mapNewNodes.find( node ) == mapNewNodes.end() ) { + list aLNx; + mapNewNodes[node] = aLNx; + // + gp_XYZ aXYZ( aX, aY, aZ ); + aGC += aXYZ; + ++aNb; + } + } + } + aGC /= aNb; + aV0.SetXYZ( aGC ); + } // if (!theHasRefPoint) { + mapNewNodes.clear(); + + // 4. Processing the elements + SMESHDS_Mesh* aMesh = GetMeshDS(); + + for ( itElem = theElements.begin(); itElem != theElements.end(); itElem++ ) { + // check element type + const SMDS_MeshElement* elem = (*itElem); + aTypeE = elem->GetType(); + if ( !elem || ( aTypeE != SMDSAbs_Face && aTypeE != SMDSAbs_Edge ) ) + continue; + + vector & newNodesItVec = mapElemNewNodes[ elem ]; + newNodesItVec.reserve( elem->NbNodes() ); + + // loop on elem nodes + SMDS_ElemIteratorPtr itN = elem->nodesIterator(); + while ( itN->more() ) { + + // check if a node has been already processed + const SMDS_MeshNode* node = + static_cast( itN->next() ); + TNodeOfNodeListMap::iterator nIt = mapNewNodes.find( node ); + if ( nIt == mapNewNodes.end() ) { + nIt = mapNewNodes.insert( make_pair( node, list() )).first; + list& listNewNodes = nIt->second; + + // make new nodes + aX = node->X(); aY = node->Y(); aZ = node->Z(); + + Standard_Real aAngle1x, aAngleT1T0, aTolAng; + gp_Pnt aP0x, aP1x, aPN0, aPN1, aV0x, aV1x; + gp_Ax1 anAx1, anAxT1T0; + gp_Dir aDT1x, aDT0x, aDT1T0; + + aTolAng=1.e-4; + + aV0x = aV0; + aPN0.SetCoord(aX, aY, aZ); + + const SMESH_MeshEditor_PathPoint& aPP0 = aPPs[0]; + aP0x = aPP0.Pnt(); + aDT0x= aPP0.Tangent(); + + for ( j = 1; j < aNbTP; ++j ) { + const SMESH_MeshEditor_PathPoint& aPP1 = aPPs[j]; + aP1x = aPP1.Pnt(); + aDT1x = aPP1.Tangent(); + aAngle1x = aPP1.Angle(); + + gp_Trsf aTrsf, aTrsfRot, aTrsfRotT1T0; + // Translation + gp_Vec aV01x( aP0x, aP1x ); + aTrsf.SetTranslation( aV01x ); + + // traslated point + aV1x = aV0x.Transformed( aTrsf ); + aPN1 = aPN0.Transformed( aTrsf ); + + // rotation 1 [ T1,T0 ] + aAngleT1T0=-aDT1x.Angle( aDT0x ); + if (fabs(aAngleT1T0) > aTolAng) { + aDT1T0=aDT1x^aDT0x; + anAxT1T0.SetLocation( aV1x ); + anAxT1T0.SetDirection( aDT1T0 ); + aTrsfRotT1T0.SetRotation( anAxT1T0, aAngleT1T0 ); + + aPN1 = aPN1.Transformed( aTrsfRotT1T0 ); + } + + // rotation 2 + if ( theHasAngles ) { + anAx1.SetLocation( aV1x ); + anAx1.SetDirection( aDT1x ); + aTrsfRot.SetRotation( anAx1, aAngle1x ); + + aPN1 = aPN1.Transformed( aTrsfRot ); + } + + // make new node + aX = aPN1.X(); + aY = aPN1.Y(); + aZ = aPN1.Z(); + const SMDS_MeshNode* newNode = aMesh->AddNode( aX, aY, aZ ); + listNewNodes.push_back( newNode ); + + aPN0 = aPN1; + aP0x = aP1x; + aV0x = aV1x; + aDT0x = aDT1x; + } } + newNodesItVec.push_back( nIt ); } // make new elements - sweepElement( aMesh, elem, mapNewNodes ); + sweepElement( aMesh, elem, newNodesItVec, newElemsMap[elem] ); } + + makeWalls( aMesh, mapNewNodes, newElemsMap, mapElemNewNodes, theElements ); + + return EXTR_OK; } //======================================================================= @@ -1928,17 +2450,26 @@ void SMESH_MeshEditor::Transform (set & theElems, //======================================================================= //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. //======================================================================= -void SMESH_MeshEditor::FindCoincidentNodes (const double theTolerance, - TListOfListOfNodes & theGroupsOfNodes) +void SMESH_MeshEditor::FindCoincidentNodes (set & theNodes, + const double theTolerance, + TListOfListOfNodes & theGroupsOfNodes) { double tol2 = theTolerance * theTolerance; list nodes; - SMDS_NodeIteratorPtr nIt = GetMeshDS()->nodesIterator(); - while ( nIt->more() ) - nodes.push_back( nIt->next() ); + if ( theNodes.empty() ) + { // get all nodes in the mesh + SMDS_NodeIteratorPtr nIt = GetMeshDS()->nodesIterator(); + while ( nIt->more() ) + nodes.push_back( nIt->next() ); + } + else + { + nodes.insert( nodes.end(), theNodes.begin(), theNodes.end() ); + } list::iterator it2, it1 = nodes.begin(); for ( ; it1 != nodes.end(); it1++ ) @@ -1995,7 +2526,7 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes) nodeNodeMap.insert( TNodeNodeMap::value_type( nToRemove, nToKeep )); if ( nToRemove != nToKeep ) { rmNodeIds.push_back( nToRemove->GetID() ); - addToSameGroups( nToKeep, nToRemove, aMesh ); + AddToSameGroups( nToKeep, nToRemove, aMesh ); } SMDS_ElemIteratorPtr invElemIt = nToRemove->GetInverseElementIterator(); @@ -2343,41 +2874,63 @@ void SMESH_MeshEditor::MergeEqualElements() Remove( rmElemIds, false ); } +//======================================================================= +//function : FindFaceInSet +//purpose : Return a face having linked nodes n1 and n2 and which is +// - not in avoidSet, +// - in elemSet provided that !elemSet.empty() +//======================================================================= + +const SMDS_MeshElement* + SMESH_MeshEditor::FindFaceInSet(const SMDS_MeshNode* n1, + const SMDS_MeshNode* n2, + const set& elemSet, + const set& avoidSet) + +{ + SMDS_ElemIteratorPtr invElemIt = n1->GetInverseElementIterator(); + while ( invElemIt->more() ) { // loop on inverse elements of n1 + const SMDS_MeshElement* elem = invElemIt->next(); + if (elem->GetType() != SMDSAbs_Face || + avoidSet.find( elem ) != avoidSet.end() ) + continue; + if ( !elemSet.empty() && elemSet.find( elem ) == elemSet.end()) + continue; + // get face nodes and find index of n1 + int i1, nbN = elem->NbNodes(), iNode = 0; + const SMDS_MeshNode* faceNodes[ nbN ], *n; + SMDS_ElemIteratorPtr nIt = elem->nodesIterator(); + while ( nIt->more() ) { + faceNodes[ iNode ] = static_cast( nIt->next() ); + if ( faceNodes[ iNode++ ] == n1 ) + i1 = iNode - 1; + } + // find a n2 linked to n1 + for ( iNode = 0; iNode < 2; iNode++ ) { + if ( iNode ) // node before n1 + n = faceNodes[ i1 == 0 ? nbN - 1 : i1 - 1 ]; + else // node after n1 + n = faceNodes[ i1 + 1 == nbN ? 0 : i1 + 1 ]; + if ( n == n2 ) + return elem; + } + } + return 0; +} + //======================================================================= //function : findAdjacentFace //purpose : //======================================================================= -#define CHECKIND(max,val) {if ( (val) >= (max) ) \ static const SMDS_MeshElement* findAdjacentFace(const SMDS_MeshNode* n1, const SMDS_MeshNode* n2, const SMDS_MeshElement* elem) { - SMDS_ElemIteratorPtr invElemIt = n1->facesIterator(); - while ( invElemIt->more() ) { // loop on inverse elements of n1 - const SMDS_MeshElement* adjElem = invElemIt->next(); - if ( elem != adjElem ) { - // get face nodes and find index of n1 - int i1, nbN = adjElem->NbNodes(), iNode = 0; - const SMDS_MeshNode* faceNodes[ nbN ], *n; - SMDS_ElemIteratorPtr nIt = adjElem->nodesIterator(); - while ( nIt->more() ) { - faceNodes[ iNode ] = static_cast( nIt->next() ); - if ( faceNodes[ iNode++ ] == n1 ) - i1 = iNode - 1; - } - // find a n2 linked to n1 - for ( iNode = 0; iNode < 2; iNode++ ) { - if ( iNode ) // node before n1 - n = faceNodes[ i1 == 0 ? nbN - 1 : i1 - 1 ]; - else // node after n1 - n = faceNodes[ i1 + 1 == nbN ? 0 : i1 + 1 ]; - if ( n == n2 ) - return adjElem; - } - } - } - return 0; + set elemSet, avoidSet; + if ( elem ) + avoidSet.insert ( elem ); + return SMESH_MeshEditor::FindFaceInSet( n1, n2, elemSet, avoidSet ); } //=======================================================================