From ee8681450251eecc6499717278aa481be460bbe8 Mon Sep 17 00:00:00 2001 From: eap Date: Fri, 1 Oct 2010 12:48:49 +0000 Subject: [PATCH] 0021015: EDF 1578 SMESH: Free nodes are removed when translating a mesh * Treate orphan nodes in Transform() * Remove Scale() as being a paricular case of Transform() --- src/SMESH/SMESH_MeshEditor.cxx | 376 ++++----------------------------- src/SMESH/SMESH_MeshEditor.hxx | 17 -- 2 files changed, 45 insertions(+), 348 deletions(-) diff --git a/src/SMESH/SMESH_MeshEditor.cxx b/src/SMESH/SMESH_MeshEditor.cxx index 4280daa27..3d85b87e2 100644 --- a/src/SMESH/SMESH_MeshEditor.cxx +++ b/src/SMESH/SMESH_MeshEditor.cxx @@ -5108,10 +5108,17 @@ void SMESH_MeshEditor::LinearAngleVariation(const int nbSteps, } -//======================================================================= -//function : Transform -//purpose : -//======================================================================= +//================================================================================ +/*! + * \brief Move or copy theElements applying theTrsf to their nodes + * \param theElems - elements to transform, if theElems is empty then apply to all mesh nodes + * \param theTrsf - transformation to apply + * \param theCopy - if true, create translated copies of theElems + * \param theMakeGroups - if true and theCopy, create translated groups + * \param theTargetMesh - mesh to copy translated elements into + * \retval SMESH_MeshEditor::PGroupIDs - list of ids of created groups + */ +//================================================================================ SMESH_MeshEditor::PGroupIDs SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems, @@ -5139,6 +5146,7 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems, groupPostfix = "translated"; break; case gp_Scale: + case gp_CompoundTrsf: // different scale by axis groupPostfix = "scaled"; break; default: @@ -5161,7 +5169,36 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems, // source elements for each generated one SMESH_SequenceOfElemPtr srcElems, srcNodes; - // loop on theElems + // issue 021015: EDF 1578 SMESH: Free nodes are removed when translating a mesh + list orphanCopy; // copies of orphan nodes + vector orphanNode; // original orphan nodes + + if ( theElems.empty() ) // transform the whole mesh + { + // add all elements + SMDS_ElemIteratorPtr eIt = aMesh->elementsIterator(); + while ( eIt->more() ) theElems.insert( eIt->next() ); + // add orphan nodes + SMDS_MeshElementIDFactory idFactory; + SMDS_NodeIteratorPtr nIt = aMesh->nodesIterator(); + while ( nIt->more() ) + { + const SMDS_MeshNode* node = nIt->next(); + if ( node->NbInverseElements() == 0 && !theElems.insert( node ).second ) + { + // node was not inserted into theElems because an element with the same ID + // is already there. As a work around we insert a copy of node with + // an ID = - + orphanCopy.push_back( *node ); // copy node + SMDS_MeshNode* nodeCopy = &orphanCopy.back(); + int uniqueID = -orphanNode.size(); + orphanNode.push_back( node ); + idFactory.BindID( uniqueID, nodeCopy ); + theElems.insert( nodeCopy ); + } + } + } + // loop on theElems to transorm nodes TIDSortedElemSet::iterator itElem; for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) { const SMDS_MeshElement* elem = *itElem; @@ -5172,8 +5209,10 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems, SMDS_ElemIteratorPtr itN = elem->nodesIterator(); while ( itN->more() ) { - // check if a node has been already transformed const SMDS_MeshNode* node = cast2Node( itN->next() ); + if ( node->GetID() < 0 ) + node = orphanNode[ -node->GetID() ]; + // check if a node has been already transformed pair n2n_isnew = nodeMap.insert( make_pair ( node, node )); if ( !n2n_isnew.second ) @@ -5424,331 +5463,6 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems, return newGroupIDs; } - -//======================================================================= -//function : Scale -//purpose : -//======================================================================= - -SMESH_MeshEditor::PGroupIDs -SMESH_MeshEditor::Scale (TIDSortedElemSet & theElems, - const gp_Pnt& thePoint, - const std::list& theScaleFact, - const bool theCopy, - const bool theMakeGroups, - SMESH_Mesh* theTargetMesh) -{ - myLastCreatedElems.Clear(); - myLastCreatedNodes.Clear(); - - SMESH_MeshEditor targetMeshEditor( theTargetMesh ); - SMESHDS_Mesh* aTgtMesh = theTargetMesh ? theTargetMesh->GetMeshDS() : 0; - SMESHDS_Mesh* aMesh = GetMeshDS(); - - double scaleX=1.0, scaleY=1.0, scaleZ=1.0; - std::list::const_iterator itS = theScaleFact.begin(); - scaleX = (*itS); - if(theScaleFact.size()==1) { - scaleY = (*itS); - scaleZ= (*itS); - } - if(theScaleFact.size()==2) { - itS++; - scaleY = (*itS); - scaleZ= (*itS); - } - if(theScaleFact.size()>2) { - itS++; - scaleY = (*itS); - itS++; - scaleZ= (*itS); - } - - // map old node to new one - TNodeNodeMap nodeMap; - - // elements sharing moved nodes; those of them which have all - // nodes mirrored but are not in theElems are to be reversed - TIDSortedElemSet inverseElemSet; - - // source elements for each generated one - SMESH_SequenceOfElemPtr srcElems, srcNodes; - - // loop on theElems - TIDSortedElemSet::iterator itElem; - for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) { - const SMDS_MeshElement* elem = *itElem; - if ( !elem ) - continue; - - // loop on elem nodes - SMDS_ElemIteratorPtr itN = elem->nodesIterator(); - while ( itN->more() ) { - - // check if a node has been already transformed - const SMDS_MeshNode* node = cast2Node( itN->next() ); - pair n2n_isnew = - nodeMap.insert( make_pair ( node, node )); - if ( !n2n_isnew.second ) - continue; - - //double coord[3]; - //coord[0] = node->X(); - //coord[1] = node->Y(); - //coord[2] = node->Z(); - //theTrsf.Transforms( coord[0], coord[1], coord[2] ); - double dx = (node->X() - thePoint.X()) * scaleX; - double dy = (node->Y() - thePoint.Y()) * scaleY; - double dz = (node->Z() - thePoint.Z()) * scaleZ; - if ( theTargetMesh ) { - //const SMDS_MeshNode * newNode = aTgtMesh->AddNode( coord[0], coord[1], coord[2] ); - const SMDS_MeshNode * newNode = - aTgtMesh->AddNode( thePoint.X()+dx, thePoint.Y()+dy, thePoint.Z()+dz ); - 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] ); - const SMDS_MeshNode * newNode = - aMesh->AddNode( thePoint.X()+dx, thePoint.Y()+dy, thePoint.Z()+dz ); - n2n_isnew.first->second = newNode; - myLastCreatedNodes.Append(newNode); - srcNodes.Append( node ); - } - else { - //aMesh->MoveNode( node, coord[0], coord[1], coord[2] ); - aMesh->MoveNode( node, thePoint.X()+dx, thePoint.Y()+dy, thePoint.Z()+dz ); - // node position on shape becomes invalid - const_cast< SMDS_MeshNode* > ( node )->SetPosition - ( SMDS_SpacePosition::originSpacePosition() ); - } - - // keep inverse elements - //if ( !theCopy && !theTargetMesh && needReverse ) { - // SMDS_ElemIteratorPtr invElemIt = node->GetInverseElementIterator(); - // while ( invElemIt->more() ) { - // const SMDS_MeshElement* iel = invElemIt->next(); - // inverseElemSet.insert( iel ); - // } - //} - } - } - - // either create new elements or reverse mirrored ones - //if ( !theCopy && !needReverse && !theTargetMesh ) - if ( !theCopy && !theTargetMesh ) - return PGroupIDs(); - - TIDSortedElemSet::iterator invElemIt = inverseElemSet.begin(); - for ( ; invElemIt != inverseElemSet.end(); invElemIt++ ) - theElems.insert( *invElemIt ); - - // replicate or reverse elements - - enum { - REV_TETRA = 0, // = nbNodes - 4 - REV_PYRAMID = 1, // = nbNodes - 4 - REV_PENTA = 2, // = nbNodes - 4 - REV_FACE = 3, - REV_HEXA = 4, // = nbNodes - 4 - FORWARD = 5 - }; - int index[][8] = { - { 2, 1, 0, 3, 4, 0, 0, 0 }, // REV_TETRA - { 2, 1, 0, 3, 4, 0, 0, 0 }, // REV_PYRAMID - { 2, 1, 0, 5, 4, 3, 0, 0 }, // REV_PENTA - { 2, 1, 0, 3, 0, 0, 0, 0 }, // REV_FACE - { 2, 1, 0, 3, 6, 5, 4, 7 }, // REV_HEXA - { 0, 1, 2, 3, 4, 5, 6, 7 } // FORWARD - }; - - for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) - { - const SMDS_MeshElement* elem = *itElem; - if ( !elem || elem->GetType() == SMDSAbs_Node ) - continue; - - int nbNodes = elem->NbNodes(); - int elemType = elem->GetType(); - - if (elem->IsPoly()) { - // Polygon or Polyhedral Volume - switch ( elemType ) { - case SMDSAbs_Face: - { - vector poly_nodes (nbNodes); - int iNode = 0; - SMDS_ElemIteratorPtr itN = elem->nodesIterator(); - while (itN->more()) { - const SMDS_MeshNode* node = - static_cast(itN->next()); - TNodeNodeMap::iterator nodeMapIt = nodeMap.find(node); - if (nodeMapIt == nodeMap.end()) - break; // not all nodes transformed - //if (needReverse) { - // // reverse mirrored faces and volumes - // poly_nodes[nbNodes - iNode - 1] = (*nodeMapIt).second; - //} else { - poly_nodes[iNode] = (*nodeMapIt).second; - //} - iNode++; - } - if ( iNode != nbNodes ) - continue; // not all nodes transformed - - if ( theTargetMesh ) { - myLastCreatedElems.Append(aTgtMesh->AddPolygonalFace(poly_nodes)); - srcElems.Append( elem ); - } - else if ( theCopy ) { - myLastCreatedElems.Append(aMesh->AddPolygonalFace(poly_nodes)); - srcElems.Append( elem ); - } - else { - aMesh->ChangePolygonNodes(elem, poly_nodes); - } - } - break; - case SMDSAbs_Volume: - { - // ATTENTION: Reversing is not yet done!!! - const SMDS_PolyhedralVolumeOfNodes* aPolyedre = - dynamic_cast( elem ); - if (!aPolyedre) { - MESSAGE("Warning: bad volumic element"); - continue; - } - - vector poly_nodes; - vector quantities; - - bool allTransformed = true; - int nbFaces = aPolyedre->NbFaces(); - for (int iface = 1; iface <= nbFaces && allTransformed; iface++) { - int nbFaceNodes = aPolyedre->NbFaceNodes(iface); - for (int inode = 1; inode <= nbFaceNodes && allTransformed; inode++) { - const SMDS_MeshNode* node = aPolyedre->GetFaceNode(iface, inode); - TNodeNodeMap::iterator nodeMapIt = nodeMap.find(node); - if (nodeMapIt == nodeMap.end()) { - allTransformed = false; // not all nodes transformed - } else { - poly_nodes.push_back((*nodeMapIt).second); - } - } - quantities.push_back(nbFaceNodes); - } - if ( !allTransformed ) - continue; // not all nodes transformed - - if ( theTargetMesh ) { - myLastCreatedElems.Append(aTgtMesh->AddPolyhedralVolume(poly_nodes, quantities)); - srcElems.Append( elem ); - } - else if ( theCopy ) { - myLastCreatedElems.Append(aMesh->AddPolyhedralVolume(poly_nodes, quantities)); - srcElems.Append( elem ); - } - else { - aMesh->ChangePolyhedronNodes(elem, poly_nodes, quantities); - } - } - break; - default:; - } - continue; - } - - // Regular elements - int* i = index[ FORWARD ]; - //if ( needReverse && nbNodes > 2) // reverse mirrored faces and volumes - // if ( elemType == SMDSAbs_Face ) - // i = index[ REV_FACE ]; - // else - // i = index[ nbNodes - 4 ]; - - if(elem->IsQuadratic()) { - static int anIds[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}; - i = anIds; - //if(needReverse) { - // if(nbNodes==3) { // quadratic edge - // static int anIds[] = {1,0,2}; - // i = anIds; - // } - // else if(nbNodes==6) { // quadratic triangle - // static int anIds[] = {0,2,1,5,4,3}; - // i = anIds; - // } - // else if(nbNodes==8) { // quadratic quadrangle - // static int anIds[] = {0,3,2,1,7,6,5,4}; - // i = anIds; - // } - // else if(nbNodes==10) { // quadratic tetrahedron of 10 nodes - // static int anIds[] = {0,2,1,3,6,5,4,7,9,8}; - // i = anIds; - // } - // else if(nbNodes==13) { // quadratic pyramid of 13 nodes - // static int anIds[] = {0,3,2,1,4,8,7,6,5,9,12,11,10}; - // i = anIds; - // } - // else if(nbNodes==15) { // quadratic pentahedron with 15 nodes - // static int anIds[] = {0,2,1,3,5,4,8,7,6,11,10,9,12,14,13}; - // i = anIds; - // } - // else { // nbNodes==20 - quadratic hexahedron with 20 nodes - // static int anIds[] = {0,3,2,1,4,7,6,5,11,10,9,8,15,14,13,12,16,19,18,17}; - // i = anIds; - // } - //} - } - - // find transformed nodes - vector nodes(nbNodes); - int iNode = 0; - SMDS_ElemIteratorPtr itN = elem->nodesIterator(); - while ( itN->more() ) { - const SMDS_MeshNode* node = - static_cast( itN->next() ); - TNodeNodeMap::iterator nodeMapIt = nodeMap.find( node ); - if ( nodeMapIt == nodeMap.end() ) - break; // not all nodes transformed - nodes[ i [ iNode++ ]] = (*nodeMapIt).second; - } - if ( iNode != nbNodes ) - continue; // not all nodes transformed - - if ( theTargetMesh ) { - if ( SMDS_MeshElement* copy = - targetMeshEditor.AddElement( nodes, elem->GetType(), elem->IsPoly() )) { - myLastCreatedElems.Append( copy ); - srcElems.Append( elem ); - } - } - else if ( theCopy ) { - if ( 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[0], nbNodes ); - } - } - - PGroupIDs newGroupIDs; - - if ( theMakeGroups && theCopy || - theMakeGroups && theTargetMesh ) { - string groupPostfix = "scaled"; - newGroupIDs = generateGroups( srcNodes, srcElems, groupPostfix, theTargetMesh ); - } - - return newGroupIDs; -} - - //======================================================================= /*! * \brief Create groups of elements made during transformation diff --git a/src/SMESH/SMESH_MeshEditor.hxx b/src/SMESH/SMESH_MeshEditor.hxx index f191158fd..3b6b469d2 100644 --- a/src/SMESH/SMESH_MeshEditor.hxx +++ b/src/SMESH/SMESH_MeshEditor.hxx @@ -390,23 +390,6 @@ public: // Move or copy theElements applying theTrsf to their nodes - /*! - * Generate new elements by extrusion of theElements - * param theElems - list of elements for scale - * param thePoint - base point for scale - * param theScaleFact - scale factors for axises - * param theCopy - allows copying the translated elements - * param theMakeGroups - forces the generation of new groups from existing ones - * param theTargetMesh - the name of the newly created mesh - * return instance of Mesh class - */ - PGroupIDs Scale (TIDSortedElemSet& theElements, - const gp_Pnt& thePoint, - const std::list& theScaleFact, - const bool theCopy, - const bool theMakeGroups, - SMESH_Mesh* theTargetMesh=0); - typedef std::list< std::list< const SMDS_MeshNode* > > TListOfListOfNodes; void FindCoincidentNodes (TIDSortedNodeSet & theNodes, -- 2.39.2