From 0562181892fb13be22546d8c6ced68f0e1020aa8 Mon Sep 17 00:00:00 2001 From: eap Date: Mon, 12 Nov 2007 09:58:54 +0000 Subject: [PATCH] PAL16842 (Genertion of groups when a mesh is transformed) + /*! + * \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 + */ + PGroupIDs generateGroups(const SMESH_SequenceOfElemPtr& nodeGens, + const SMESH_SequenceOfElemPtr& elemGens, + const std::string& postfix); --- src/SMESH/SMESH_MeshEditor.cxx | 443 +++++++++++++++++++++++++-------- src/SMESH/SMESH_MeshEditor.hxx | 100 ++++++-- 2 files changed, 415 insertions(+), 128 deletions(-) diff --git a/src/SMESH/SMESH_MeshEditor.cxx b/src/SMESH/SMESH_MeshEditor.cxx index 79995e3e4..99f81e844 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" @@ -43,6 +44,7 @@ #include "SMESH_ControlsDef.hxx" #include "SMESH_MesherHelper.hxx" #include "SMESH_OctreeNode.hxx" +#include "SMESH_Group.hxx" #include "utilities.h" @@ -82,11 +84,8 @@ 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; struct TNodeXYZ : public gp_XYZ { @@ -2742,17 +2741,24 @@ 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(); @@ -2832,8 +2838,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]) { @@ -3049,6 +3054,7 @@ static void sweepElement(SMESHDS_Mesh* aMesh, if ( aNewElem ) { newElems.push_back( aNewElem ); myLastCreatedElems.Append(aNewElem); + srcElements.Append( elem ); } // set new prev nodes @@ -3059,19 +3065,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, - TIDSortedElemSet& 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. @@ -3099,7 +3112,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 ); } } } @@ -3117,17 +3130,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 ) @@ -3155,12 +3172,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() ); } } } @@ -3179,13 +3198,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() ); } } } @@ -3198,7 +3219,6 @@ 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; @@ -3211,24 +3231,51 @@ static void makeWalls (SMESHDS_Mesh* aMesh, while ( iVol++ < volNb ) v++; // find indices of free faces of a volume list< int > fInd; + 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 ); + // 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 (!commonNodes[ 1 + int((*v)->IsQuadratic()) ]) { +#ifdef _DEBUG_ + throw SALOME_Exception(LOCALIZED("Common nodes not found")); +#else + srcEdges.push_back( NULL ); +#endif + } + 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() ) + throw SALOME_Exception(LOCALIZED("Source edge not found")); +#endif + } } if ( fInd.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< const SMDS_MeshElement* >::iterator srcEdge = srcEdges.begin(); + for ( ; ind != fInd.end(); ++ind, ++srcEdge ) // loop on free faces + { const SMDS_MeshNode** nodes = vTool.GetFaceNodes( *ind ); int nbn = vTool.NbFaceNodes( *ind ); switch ( nbn ) { @@ -3278,7 +3325,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++; @@ -3286,7 +3337,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() ); @@ -3330,6 +3381,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 } @@ -3339,16 +3393,21 @@ static void makeWalls (SMESHDS_Mesh* aMesh, //purpose : //======================================================================= -void SMESH_MeshEditor::RotationSweep(TIDSortedElemSet & theElems, - const gp_Ax1& theAxis, - const double theAngle, - const int theNbSteps, - const double theTol, - const bool theMakeWalls) +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 ); @@ -3375,11 +3434,10 @@ void SMESH_MeshEditor::RotationSweep(TIDSortedElemSet & theElems, // 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; @@ -3399,6 +3457,7 @@ void SMESH_MeshEditor::RotationSweep(TIDSortedElemSet & 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] ); @@ -3408,6 +3467,7 @@ void SMESH_MeshEditor::RotationSweep(TIDSortedElemSet & theElems, } newNode = aMesh->AddNode( coord[0], coord[1], coord[2] ); myLastCreatedNodes.Append(newNode); + srcNodes.Append( node ); } listNewNodes.push_back( newNode ); } @@ -3429,9 +3489,11 @@ void SMESH_MeshEditor::RotationSweep(TIDSortedElemSet & 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 ); } } @@ -3440,12 +3502,17 @@ void SMESH_MeshEditor::RotationSweep(TIDSortedElemSet & theElems, newNodesItVec.push_back( nIt ); } // make new elements - sweepElement( aMesh, elem, newNodesItVec, newElemsMap[elem], theNbSteps, myLastCreatedElems ); + sweepElement( elem, newNodesItVec, newElemsMap[elem], theNbSteps, srcElems ); } if ( theMakeWalls ) - makeWalls( aMesh, mapNewNodes, newElemsMap, mapElemNewNodes, - theElems, theNbSteps, myLastCreatedElems ); + makeWalls( mapNewNodes, newElemsMap, mapElemNewNodes, theElems, theNbSteps, srcElems ); + + PGroupIDs newGroupIDs; + if ( theMakeGroups ) + newGroupIDs = generateGroups( srcNodes, srcElems, "rotated"); + + return newGroupIDs; } @@ -3498,12 +3565,14 @@ const SMDS_MeshNode* SMESH_MeshEditor::CreateNode(const double x, //purpose : //======================================================================= -void SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet & 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); @@ -3513,8 +3582,8 @@ void SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet & theElems, 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); } @@ -3523,15 +3592,20 @@ void SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet & theElems, //purpose : //======================================================================= -void SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet & 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(); @@ -3555,11 +3629,10 @@ void SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet & theElems, // 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() ) { @@ -3586,6 +3659,7 @@ void SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet & theElems, else { const SMDS_MeshNode * newNode = aMesh->AddNode(x, y, z); myLastCreatedNodes.Append(newNode); + srcNodes.Append( node ); listNewNodes.push_back( newNode ); } } @@ -3602,6 +3676,7 @@ void SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet & theElems, 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; } @@ -3627,6 +3702,7 @@ void SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet & theElems, 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); @@ -3640,6 +3716,7 @@ void SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet & theElems, else { const SMDS_MeshNode * newNode = aMesh->AddNode( coord[0], coord[1], coord[2] ); myLastCreatedNodes.Append(newNode); + srcNodes.Append( node ); listNewNodes.push_back( newNode ); } } @@ -3649,12 +3726,17 @@ void SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet & theElems, 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; } @@ -3713,12 +3795,15 @@ SMESH_MeshEditor::Extrusion_Error const bool theHasAngles, list& theAngles, const bool theHasRefPoint, - const gp_Pnt& theRefPoint) + 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; @@ -3901,9 +3986,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() ); @@ -3972,6 +4059,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(); @@ -3979,6 +4067,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; @@ -4004,6 +4093,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; @@ -4022,12 +4112,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; } @@ -4037,21 +4128,36 @@ SMESH_MeshEditor::Extrusion_Error //purpose : //======================================================================= -void SMESH_MeshEditor::Transform (TIDSortedElemSet & 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) { 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(); @@ -4063,6 +4169,9 @@ void SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems, // nodes mirrored but are not in theElems are to be reversed TIDSortedElemSet inverseElemSet; + // source elements for each generated one + SMESH_SequenceOfElemPtr srcElems, srcNodes; + // loop on theElems TIDSortedElemSet::iterator itElem; for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) { @@ -4075,9 +4184,10 @@ void SMESH_MeshEditor::Transform (TIDSortedElemSet & 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 iter_isnew = + nodeMap.insert( make_pair ( node, node )); + if ( !iter_isnew.second ) continue; double coord[3]; @@ -4085,10 +4195,11 @@ void SMESH_MeshEditor::Transform (TIDSortedElemSet & 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] ); + const SMDS_MeshNode * newNode = aMesh->AddNode( coord[0], coord[1], coord[2] ); + iter_isnew.first->second = newNode; myLastCreatedNodes.Append(newNode); + srcNodes.Append( node ); } else { aMesh->MoveNode( node, coord[0], coord[1], coord[2] ); @@ -4096,7 +4207,6 @@ void SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems, const_cast< SMDS_MeshNode* > ( node )->SetPosition ( SMDS_SpacePosition::originSpacePosition() ); } - nodeMap.insert( make_pair( node, newNode )); // keep inverse elements if ( !theCopy && needReverse ) { @@ -4109,16 +4219,13 @@ void SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems, } } - // either new elements are to be created - // or a mirrored element are to be reversed + // either create new elements or reverse mirrored ones if ( !theCopy && !needReverse) - return; + return PGroupIDs(); - if ( !inverseElemSet.empty()) { - TIDSortedElemSet::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 @@ -4139,7 +4246,8 @@ void SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems, { 0, 1, 2, 3, 4, 5, 6, 7 } // FORWARD }; - for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) { + for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) + { const SMDS_MeshElement* elem = *itElem; if ( !elem || elem->GetType() == SMDSAbs_Node ) continue; @@ -4174,6 +4282,7 @@ void SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems, if ( theCopy ) { myLastCreatedElems.Append(aMesh->AddPolygonalFace(poly_nodes)); + srcElems.Append( elem ); } else { aMesh->ChangePolygonNodes(elem, poly_nodes); @@ -4184,7 +4293,7 @@ void SMESH_MeshEditor::Transform (TIDSortedElemSet & 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; @@ -4213,6 +4322,7 @@ void SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems, if ( theCopy ) { myLastCreatedElems.Append(aMesh->AddPolyhedralVolume(poly_nodes, quantities)); + srcElems.Append( elem ); } else { aMesh->ChangePolyhedronNodes(elem, poly_nodes, quantities); @@ -4283,8 +4393,10 @@ void SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems, continue; // not all nodes transformed if ( theCopy ) { - if ( SMDS_MeshElement* copy = AddElement( nodes, elem->GetType(), elem->IsPoly() )) + if ( SMDS_MeshElement* copy = AddElement( nodes, elem->GetType(), elem->IsPoly() )) { myLastCreatedElems.Append( copy ); + srcElems.Append( elem ); + } } else { @@ -4293,6 +4405,133 @@ void SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems, aMesh->ChangeElementNodes( elem, &nodes[0], nbNodes ); } } + + PGroupIDs newGroupIDs; + + if ( theCopy && theMakeGroups ) + newGroupIDs = generateGroups( srcNodes, srcElems, groupPostfix ); + + 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) +{ + PGroupIDs newGroupIDs( new list ); + // Sort existing groups by types and collect their names + + // store an old group and a generated new one + typedef pair< SMESHDS_Group*, 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_Group* groupDS = dynamic_cast< SMESHDS_Group* >( group->GetGroupDS() ); + if ( !groupDS ) 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; + 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_Group* oldGroup = gOldNew->first; + if ( oldGroup->SMDSGroup().Contains( sourceElem )) // sourceElem in oldGroup + { + SMDS_MeshGroup* & newGroup = gOldNew->second; + if ( !newGroup )// create a new group + { + // make a name + string name = oldGroup->GetStoreName(); + name += "_"; + name += postfix; + int nb = 0; + while ( !groupNames.insert( name ).second ) // name exists + { + if ( nb == 0 ) { + name += "_1"; + } + else { + TCollection_AsciiString nbStr(++nb); + name.resize( name.rfind('_') ); + name += nbStr.ToCString(); + } + } + // make a group + int id; + SMESH_Group* group = GetMesh()->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; } //======================================================================= @@ -6337,7 +6576,7 @@ void SMESH_MeshEditor::UpdateVolumes (const SMDS_MeshNode* theBetweenNode */ //======================================================================= -int SMESH_MeshEditor::ConvertElemToQuadratic(SMESHDS_SubMesh * theSm, +int SMESH_MeshEditor::convertElemToQuadratic(SMESHDS_SubMesh * theSm, SMESH_MesherHelper& theHelper, const bool theForce3d) { @@ -6441,7 +6680,7 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d) SMESH_subMesh* sm = smIt->next(); if ( SMESHDS_SubMesh *smDS = sm->GetSubMeshDS() ) { aHelper.SetSubShape( sm->GetSubShape() ); - nbCheckedElems += ConvertElemToQuadratic(smDS, aHelper, theForce3d); + nbCheckedElems += convertElemToQuadratic(smDS, aHelper, theForce3d); } } } @@ -6552,7 +6791,7 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d) */ //======================================================================= -int SMESH_MeshEditor::RemoveQuadElem(SMESHDS_SubMesh * theSm, +int SMESH_MeshEditor::removeQuadElem(SMESHDS_SubMesh * theSm, SMDS_ElemIteratorPtr theItr, const int theShapeID) { @@ -6627,7 +6866,7 @@ bool SMESH_MeshEditor::ConvertFromQuadratic() while ( smIt->more() ) { SMESH_subMesh* sm = smIt->next(); if ( SMESHDS_SubMesh *smDS = sm->GetSubMeshDS() ) - nbCheckedElems += RemoveQuadElem( smDS, smDS->GetElements(), sm->GetId() ); + nbCheckedElems += removeQuadElem( smDS, smDS->GetElements(), sm->GetId() ); } } } @@ -6637,7 +6876,7 @@ bool SMESH_MeshEditor::ConvertFromQuadratic() if ( nbCheckedElems < totalNbElems ) // not all elements in submeshes { SMESHDS_SubMesh *aSM = 0; - RemoveQuadElem( aSM, GetMeshDS()->elementsIterator(), 0 ); + removeQuadElem( aSM, GetMeshDS()->elementsIterator(), 0 ); } return true; diff --git a/src/SMESH/SMESH_MeshEditor.hxx b/src/SMESH/SMESH_MeshEditor.hxx index 9b56a1f6c..5c4d11b7c 100644 --- a/src/SMESH/SMESH_MeshEditor.hxx +++ b/src/SMESH/SMESH_MeshEditor.hxx @@ -190,13 +190,15 @@ public: // If the2D, smoothing is performed using UV parameters of nodes // on geometrical faces - - void RotationSweep (TIDSortedElemSet & theElements, - const gp_Ax1& theAxis, - const double theAngle, - const int theNbSteps, - const double theToler, - const bool theMakeWalls=true); + typedef std::auto_ptr< std::list > PGroupIDs; + + PGroupIDs RotationSweep (TIDSortedElemSet & theElements, + const gp_Ax1& theAxis, + const double theAngle, + const int theNbSteps, + const double theToler, + const bool theMakeGroups, + const bool theMakeWalls=true); // Generate new elements by rotation of theElements around theAxis // by theAngle by theNbSteps @@ -241,13 +243,13 @@ public: * param theTolerance - uses for comparing locations of nodes if flag * EXTRUSION_FLAG_SEW is set */ - void ExtrusionSweep - (TIDSortedElemSet & theElems, - const gp_Vec& theStep, - const int theNbSteps, - TElemOfElemListMap& newElemsMap, - const int theFlags = EXTRUSION_FLAG_BOUNDARY, - const double theTolerance = 1.e-6); + PGroupIDs ExtrusionSweep (TIDSortedElemSet & theElems, + const gp_Vec& theStep, + const int theNbSteps, + TElemOfElemListMap& newElemsMap, + const bool theMakeGroups, + const int theFlags = EXTRUSION_FLAG_BOUNDARY, + const double theTolerance = 1.e-6); /*! * Generate new elements by extrusion of theElements @@ -259,11 +261,12 @@ public: * EXTRUSION_FLAG_SEW is set * param theParams - special structure for manage of extrusion */ - void ExtrusionSweep (TIDSortedElemSet & theElems, - ExtrusParam& theParams, - TElemOfElemListMap& newElemsMap, - const int theFlags, - const double theTolerance); + PGroupIDs ExtrusionSweep (TIDSortedElemSet & theElems, + ExtrusParam& theParams, + TElemOfElemListMap& newElemsMap, + const bool theMakeGroups, + const int theFlags, + const double theTolerance); // Generate new elements by extrusion of theElements @@ -285,13 +288,15 @@ public: const bool theHasAngles, std::list& theAngles, const bool theHasRefPoint, - const gp_Pnt& theRefPoint); + const gp_Pnt& theRefPoint, + const bool theMakeGroups); // Generate new elements by extrusion of theElements along path given by theTrackPattern, // theHasAngles are the rotation angles, base point can be given by theRefPoint - void Transform (TIDSortedElemSet & theElements, - const gp_Trsf& theTrsf, - const bool theCopy); + PGroupIDs Transform (TIDSortedElemSet & theElements, + const gp_Trsf& theTrsf, + const bool theCopy, + const bool theMakeGroups); // Move or copy theElements applying theTrsf to their nodes typedef std::list< std::list< const SMDS_MeshNode* > > TListOfListOfNodes; @@ -507,7 +512,7 @@ private: * \brief Convert elements contained in a submesh to quadratic * \retval int - nb of checked elements */ - int ConvertElemToQuadratic(SMESHDS_SubMesh * theSm, + int convertElemToQuadratic(SMESHDS_SubMesh * theSm, SMESH_MesherHelper& theHelper, const bool theForce3d); @@ -515,11 +520,54 @@ private: * \brief Convert quadratic elements to linear ones and remove quadratic nodes * \retval int - nb of checked elements */ - int RemoveQuadElem( SMESHDS_SubMesh * theSm, + int removeQuadElem( SMESHDS_SubMesh * theSm, SMDS_ElemIteratorPtr theItr, const int theShapeID); - //Auxiliary function for "ConvertFromQuadratic" is intended to + /*! + * \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 + */ + PGroupIDs generateGroups(const SMESH_SequenceOfElemPtr& nodeGens, + const SMESH_SequenceOfElemPtr& elemGens, + const std::string& postfix); + + + typedef std::map > TNodeOfNodeListMap; + typedef TNodeOfNodeListMap::iterator TNodeOfNodeListMapItr; + typedef std::vector TVecOfNnlmiMap; + typedef std::map TElemOfVecOfNnlmiMap; + /*! + * \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 + */ + void sweepElement(const SMDS_MeshElement* elem, + const std::vector & newNodesItVec, + std::list& newElems, + const int nbSteps, + SMESH_SequenceOfElemPtr& srcElements); + + /*! + * \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 + */ + void makeWalls (TNodeOfNodeListMap & mapNewNodes, + TElemOfElemListMap & newElemsMap, + TElemOfVecOfNnlmiMap & elemNewNodesMap, + TIDSortedElemSet& elemSet, + const int nbSteps, + SMESH_SequenceOfElemPtr& srcElements); private: SMESH_Mesh * myMesh; -- 2.39.2