X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSMESH%2FSMESH_MeshEditor.cxx;h=09bc9e4cb09faec258cfcbddba3373c2de1a74df;hb=40b2818f18601091d81e0d9d749a3fd6808c31ce;hp=3e51f4a935c8435b976ddfbdf08c7d8be4741b81;hpb=73a829efdfe513595f56fbb8184d0869acd5b2f0;p=modules%2Fsmesh.git diff --git a/src/SMESH/SMESH_MeshEditor.cxx b/src/SMESH/SMESH_MeshEditor.cxx index 3e51f4a93..09bc9e4cb 100644 --- a/src/SMESH/SMESH_MeshEditor.cxx +++ b/src/SMESH/SMESH_MeshEditor.cxx @@ -47,6 +47,7 @@ #include "utilities.h" #include +#include #include #include #include @@ -54,11 +55,14 @@ #include #include #include +#include #include +#include #include #include #include #include +#include #include #include #include @@ -2050,8 +2054,8 @@ void SMESH_MeshEditor::GetLinkedNodes( const SMDS_MeshNode* theNode, iAfter = SMESH_MesherHelper::WrapIndex( iAfter, nb ); iBefore = SMESH_MesherHelper::WrapIndex( iBefore, nb ); } - linkedNodes.insert( elem->GetNode( iAfter )); - linkedNodes.insert( elem->GetNode( iBefore )); + linkedNodes.insert( elem->GetNodeWrap( iAfter )); + linkedNodes.insert( elem->GetNodeWrap( iBefore )); } } } @@ -2456,7 +2460,7 @@ void SMESH_MeshEditor::Smooth (TIDSortedElemSet & theElems, if(elem->IsQuadratic()) nbn = nbn/2; // loop on elem links: insert them in linkNbMap - const SMDS_MeshNode* curNode, *prevNode = elem->GetNode( nbn ); + const SMDS_MeshNode* curNode, *prevNode = elem->GetNodeWrap( nbn ); for ( int iN = 0; iN < nbn; ++iN ) { curNode = elem->GetNode( iN ); NLink link; @@ -2780,27 +2784,30 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement* elem, TNodeOfNodeListMapItr nnIt = newNodesItVec[ iNode ]; const SMDS_MeshNode* node = nnIt->first; const list< const SMDS_MeshNode* > & listNewNodes = nnIt->second; - if ( listNewNodes.empty() ) + if ( listNewNodes.empty() ) { return; + } issimple[iNode] = (listNewNodes.size()==nbSteps); itNN[ iNode ] = listNewNodes.begin(); prevNod[ iNode ] = node; nextNod[ iNode ] = listNewNodes.front(); -//cout<<"iNode="<GetID() ); + //MESSAGE( " Too many same nodes of element " << elem->GetID() ); + INFOS( " Too many same nodes of element " << elem->GetID() ); return; } @@ -2810,9 +2817,10 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement* elem, // } int iBeforeSame = 0, iAfterSame = 0, iOpposSame = 0; + int nbBaseNodes = ( elem->IsQuadratic() ? nbNodes/2 : nbNodes ); if ( nbSame > 0 ) { - iBeforeSame = ( iSameNode == 0 ? nbNodes - 1 : iSameNode - 1 ); - iAfterSame = ( iSameNode + 1 == nbNodes ? 0 : iSameNode + 1 ); + iBeforeSame = ( iSameNode == 0 ? nbBaseNodes - 1 : iSameNode - 1 ); + iAfterSame = ( iSameNode + 1 == nbBaseNodes ? 0 : iSameNode + 1 ); iOpposSame = ( iSameNode - 2 < 0 ? iSameNode + 2 : iSameNode - 2 ); } @@ -2829,7 +2837,7 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement* elem, i0 = 2; i2 = 0; if ( nbSame > 0 ) - std::swap( iAfterSame, iAfterSame ); + std::swap( iBeforeSame, iAfterSame ); } // make new elements @@ -2850,7 +2858,7 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement* elem, } else if(!elem->IsQuadratic() || elem->IsMediumNode(prevNod[iNode]) ) { // we have to use each second node - itNN[ iNode ]++; + //itNN[ iNode ]++; nextNod[ iNode ] = *itNN[ iNode ]; itNN[ iNode ]++; } @@ -2909,8 +2917,9 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement* elem, midlNod[0], nextNod[2], midlNod[1], prevNod[2]); } else if(nbSame==1) { // quadratic triangle - if(sames[0]==2) + if(sames[0]==2) { return; // medium node on axis + } else if(sames[0]==0) { aNewElem = aMesh->AddFace(prevNod[0], nextNod[1], prevNod[1], nextNod[2], midlNod[1], prevNod[2]); @@ -2920,8 +2929,9 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement* elem, midlNod[0], nextNod[2], prevNod[2]); } } - else + else { return; + } } break; } @@ -2956,38 +2966,140 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement* elem, } case 6: { // quadratic triangle // create pentahedron with 15 nodes - if(i0>0) { // reversed case - aNewElem = aMesh->AddVolume (prevNod[0], prevNod[2], prevNod[1], - nextNod[0], nextNod[2], nextNod[1], - prevNod[5], prevNod[4], prevNod[3], - nextNod[5], nextNod[4], nextNod[3], - midlNod[0], midlNod[2], midlNod[1]); - } - else { // not reversed case - aNewElem = aMesh->AddVolume (prevNod[0], prevNod[1], prevNod[2], - nextNod[0], nextNod[1], nextNod[2], - prevNod[3], prevNod[4], prevNod[5], - nextNod[3], nextNod[4], nextNod[5], - midlNod[0], midlNod[1], midlNod[2]); - } + if(nbSame==0) { + if(i0>0) { // reversed case + aNewElem = aMesh->AddVolume (prevNod[0], prevNod[2], prevNod[1], + nextNod[0], nextNod[2], nextNod[1], + prevNod[5], prevNod[4], prevNod[3], + nextNod[5], nextNod[4], nextNod[3], + midlNod[0], midlNod[2], midlNod[1]); + } + else { // not reversed case + aNewElem = aMesh->AddVolume (prevNod[0], prevNod[1], prevNod[2], + nextNod[0], nextNod[1], nextNod[2], + prevNod[3], prevNod[4], prevNod[5], + nextNod[3], nextNod[4], nextNod[5], + midlNod[0], midlNod[1], midlNod[2]); + } + } + else if(nbSame==1) { + // 2d order pyramid of 13 nodes + //SMDS_MeshVolume* AddVolumeWithID(int n1, int n2, int n3, int n4, int n5, + // int n12,int n23,int n34,int n41, + // int n15,int n25,int n35,int n45, int ID); + int n5 = iSameNode; + int n1,n4,n41,n15,n45; + if(i0>0) { // reversed case + n1 = ( n5 + 1 == nbBaseNodes ? 0 : n5 + 1 ); + n4 = ( n5 == 0 ? nbBaseNodes - 1 : n5 - 1 ); + n41 = n1 + 3; + n15 = n5 + 3; + n45 = n4 + 3; + } + else { + n1 = ( n5 == 0 ? nbBaseNodes - 1 : n5 - 1 ); + n4 = ( n5 + 1 == nbBaseNodes ? 0 : n5 + 1 ); + n41 = n4 + 3; + n15 = n1 + 3; + n45 = n5 + 3; + } + aNewElem = aMesh->AddVolume(prevNod[n1], nextNod[n1], + nextNod[n4], prevNod[n4], prevNod[n5], + midlNod[n1], nextNod[n41], + midlNod[n4], prevNod[n41], + prevNod[n15], nextNod[n15], + nextNod[n45], prevNod[n45]); + } + else if(nbSame==2) { + // 2d order tetrahedron of 10 nodes + //SMDS_MeshVolume* AddVolumeWithID(int n1, int n2, int n3, int n4, + // int n12,int n23,int n31, + // int n14,int n24,int n34, int ID); + int n1 = iNotSameNode; + int n2,n3,n12,n23,n31; + if(i0>0) { // reversed case + n2 = ( n1 == 0 ? nbBaseNodes - 1 : n1 - 1 ); + n3 = ( n1 + 1 == nbBaseNodes ? 0 : n1 + 1 ); + n12 = n2 + 3; + n23 = n3 + 3; + n31 = n1 + 3; + } + else { + n2 = ( n1 + 1 == nbBaseNodes ? 0 : n1 + 1 ); + n3 = ( n1 == 0 ? nbBaseNodes - 1 : n1 - 1 ); + n12 = n1 + 3; + n23 = n2 + 3; + n31 = n3 + 3; + } + aNewElem = aMesh->AddVolume (prevNod[n1], prevNod[n2], prevNod[n3], nextNod[n1], + prevNod[n12], prevNod[n23], prevNod[n31], + midlNod[n1], nextNod[n12], nextNod[n31]); + } break; } case 8: { // quadratic quadrangle - // create hexahedron with 20 nodes - if(i0>0) { // reversed case - aNewElem = aMesh->AddVolume (prevNod[0], prevNod[3], prevNod[2], prevNod[1], - nextNod[0], nextNod[3], nextNod[2], nextNod[1], - prevNod[7], prevNod[6], prevNod[5], prevNod[4], - nextNod[7], nextNod[6], nextNod[5], nextNod[4], - midlNod[0], midlNod[3], midlNod[2], midlNod[1]); - } - else { // not reversed case - aNewElem = aMesh->AddVolume (prevNod[0], prevNod[1], prevNod[2], prevNod[3], - nextNod[0], nextNod[1], nextNod[2], nextNod[3], - prevNod[4], prevNod[5], prevNod[6], prevNod[7], - nextNod[4], nextNod[5], nextNod[6], nextNod[7], - midlNod[0], midlNod[1], midlNod[2], midlNod[3]); - } + if(nbSame==0) { + // create hexahedron with 20 nodes + if(i0>0) { // reversed case + aNewElem = aMesh->AddVolume (prevNod[0], prevNod[3], prevNod[2], prevNod[1], + nextNod[0], nextNod[3], nextNod[2], nextNod[1], + prevNod[7], prevNod[6], prevNod[5], prevNod[4], + nextNod[7], nextNod[6], nextNod[5], nextNod[4], + midlNod[0], midlNod[3], midlNod[2], midlNod[1]); + } + else { // not reversed case + aNewElem = aMesh->AddVolume (prevNod[0], prevNod[1], prevNod[2], prevNod[3], + nextNod[0], nextNod[1], nextNod[2], nextNod[3], + prevNod[4], prevNod[5], prevNod[6], prevNod[7], + nextNod[4], nextNod[5], nextNod[6], nextNod[7], + midlNod[0], midlNod[1], midlNod[2], midlNod[3]); + } + } + else if(nbSame==1) { + // --- pyramid + pentahedron - can not be created since it is needed + // additional middle node ot the center of face + INFOS( " Sweep for face " << elem->GetID() << " can not be created" ); + return; + } + else if(nbSame==2) { + // 2d order Pentahedron with 15 nodes + //SMDS_MeshVolume* AddVolumeWithID(int n1, int n2, int n3, int n4, int n5, int n6, + // int n12,int n23,int n31,int n45,int n56,int n64, + // int n14,int n25,int n36, int ID); + int n1,n2,n4,n5; + if ( prevNod[ iBeforeSame ] == nextNod[ iBeforeSame ] ) { + // iBeforeSame is same too + n1 = iBeforeSame; + n2 = iOpposSame; + n4 = iSameNode; + n5 = iAfterSame; + } + else { + // iAfterSame is same too + n1 = iSameNode; + n2 = iBeforeSame; + n4 = iAfterSame; + n5 = iOpposSame; + } + int n12,n45,n14,n25; + if(i0>0) { //reversed case + n12 = n1 + 4; + n45 = n5 + 4; + n14 = n4 + 4; + n25 = n2 + 4; + } + else { + n12 = n2 + 4; + n45 = n4 + 4; + n14 = n1 + 4; + n25 = n5 + 4; + } + aNewElem = aMesh->AddVolume (prevNod[n1], prevNod[n2], nextNod[n2], + prevNod[n4], prevNod[n5], nextNod[n5], + prevNod[n12], midlNod[n2], nextNod[n12], + prevNod[n45], midlNod[n5], nextNod[n45], + prevNod[n14], prevNod[n25], nextNod[n25]); + } break; } default: { @@ -3276,7 +3388,7 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap & mapNewNodes, const SMDS_MeshFace * f = aMesh->FindFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ]); if ( !f ) myLastCreatedElems.Append(aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] )); - else if ( nodes[ 1 ] != f->GetNode( f->GetNodeIndex( nodes[ 0 ] ) + 1 )) + else if ( nodes[ 1 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ] ) + 1 )) aMesh->ChangeElementNodes( f, nodes, nbn ); break; } @@ -3284,7 +3396,7 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap & mapNewNodes, const SMDS_MeshFace * f = aMesh->FindFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ]); if ( !f ) myLastCreatedElems.Append(aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ] )); - else if ( nodes[ 1 ] != f->GetNode( f->GetNodeIndex( nodes[ 0 ] ) + 1 )) + else if ( nodes[ 1 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ] ) + 1 )) aMesh->ChangeElementNodes( f, nodes, nbn ); break; } @@ -3293,20 +3405,40 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap & mapNewNodes, if(nbn==6) { /////// quadratic triangle const SMDS_MeshFace * f = aMesh->FindFace( nodes[0], nodes[2], nodes[4], nodes[1], nodes[3], nodes[5] ); - if ( !f ) + if ( !f ) { myLastCreatedElems.Append(aMesh->AddFace(nodes[0], nodes[2], nodes[4], nodes[1], nodes[3], nodes[5])); - else if ( nodes[ 2 ] != f->GetNode( f->GetNodeIndex( nodes[ 0 ] ) + 1 )) - aMesh->ChangeElementNodes( f, nodes, nbn ); + } + else if ( nodes[ 2 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ] ) + 1 )) { + const SMDS_MeshNode** tmpnodes = new const SMDS_MeshNode*[6]; + tmpnodes[0] = nodes[0]; + tmpnodes[1] = nodes[2]; + tmpnodes[2] = nodes[4]; + tmpnodes[3] = nodes[1]; + tmpnodes[4] = nodes[3]; + tmpnodes[5] = nodes[5]; + aMesh->ChangeElementNodes( f, tmpnodes, nbn ); + } } else { /////// quadratic quadrangle const SMDS_MeshFace * f = aMesh->FindFace( nodes[0], nodes[2], nodes[4], nodes[6], nodes[1], nodes[3], nodes[5], nodes[7] ); - if ( !f ) + if ( !f ) { myLastCreatedElems.Append(aMesh->AddFace(nodes[0], nodes[2], nodes[4], nodes[6], nodes[1], nodes[3], nodes[5], nodes[7])); - else if ( nodes[ 2 ] != f->GetNode( f->GetNodeIndex( nodes[ 0 ] ) + 1 )) - aMesh->ChangeElementNodes( f, nodes, nbn ); + } + else if ( nodes[ 2 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ] ) + 1 )) { + const SMDS_MeshNode** tmpnodes = new const SMDS_MeshNode*[8]; + tmpnodes[0] = nodes[0]; + tmpnodes[1] = nodes[2]; + tmpnodes[2] = nodes[4]; + tmpnodes[3] = nodes[6]; + tmpnodes[4] = nodes[1]; + tmpnodes[5] = nodes[3]; + tmpnodes[6] = nodes[5]; + tmpnodes[7] = nodes[7]; + aMesh->ChangeElementNodes( f, tmpnodes, nbn ); + } } } else { //////// polygon @@ -3314,7 +3446,7 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap & mapNewNodes, const SMDS_MeshFace * f = aMesh->FindFace( polygon_nodes ); if ( !f ) myLastCreatedElems.Append(aMesh->AddPolygonalFace(polygon_nodes)); - else if ( nodes[ 1 ] != f->GetNode( f->GetNodeIndex( nodes[ 0 ] ) + 1 )) + else if ( nodes[ 1 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ] ) + 1 )) aMesh->ChangeElementNodes( f, nodes, nbn ); } } @@ -3427,20 +3559,25 @@ 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 = cast2Node( itN->next() ); + + 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 ); + 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 ); + //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 ) { @@ -3461,10 +3598,17 @@ SMESH_MeshEditor::RotationSweep(TIDSortedElemSet & theElems, newNode = aMesh->AddNode( coord[0], coord[1], coord[2] ); myLastCreatedNodes.Append(newNode); srcNodes.Append( node ); + listNewNodes.push_back( newNode ); } - listNewNodes.push_back( newNode ); + else { + listNewNodes.push_back( newNode ); + if( elem->IsQuadratic() && !elem->IsMediumNode(node) ) { + listNewNodes.push_back( newNode ); + } + } } } + /* else { // if current elem is quadratic and current node is not medium // we have to check - may be it is needed to insert additional nodes @@ -3473,25 +3617,33 @@ SMESH_MeshEditor::RotationSweep(TIDSortedElemSet & theElems, if(listNewNodes.size()==theNbSteps) { listNewNodes.clear(); // make new nodes - gp_XYZ aXYZ( node->X(), node->Y(), node->Z() ); - double coord[3]; - aXYZ.Coord( coord[0], coord[1], coord[2] ); + //gp_XYZ aXYZ( node->X(), node->Y(), node->Z() ); + //double coord[3]; + //aXYZ.Coord( coord[0], coord[1], coord[2] ); const SMDS_MeshNode * newNode = node; - for(int i = 0; iAddNode( 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 ); + if ( !isOnAxis ) { + for(int i = 0; iAddNode( coord[0], coord[1], coord[2] ); + cout<<" 3 AddNode: "<AddNode( coord[0], coord[1], coord[2] ); + cout<<" 4 AddNode: "<& theAngles, + const bool theLinearVariation, const bool theHasRefPoint, const gp_Pnt& theRefPoint, const bool theMakeGroups) @@ -3794,20 +3948,11 @@ SMESH_MeshEditor::Extrusion_Error myLastCreatedElems.Clear(); myLastCreatedNodes.Clear(); - // source elements for each generated one - SMESH_SequenceOfElemPtr srcElems, srcNodes; - - int j, aNbTP, aNbE, aNb; - double aT1, aT2, aT, aAngle, aX, aY, aZ; + int aNbE; std::list aPrms; - std::list::iterator aItD; TIDSortedElemSet::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; @@ -3816,11 +3961,6 @@ SMESH_MeshEditor::Extrusion_Error SMDSAbs_ElementType aTypeE; TNodeOfNodeListMap mapNewNodes; - TElemOfVecOfNnlmiMap mapElemNewNodes; - TElemOfElemListMap newElemsMap; - - aTolVec=1.e-7; - aTolVec2=aTolVec*aTolVec; // 1. Check data aNbE = theElements.size(); @@ -3831,7 +3971,7 @@ SMESH_MeshEditor::Extrusion_Error // 1.1 Track Pattern ASSERT( theTrack ); - SMESHDS_SubMesh* pSubMeshDS=theTrack->GetSubMeshDS(); + SMESHDS_SubMesh* pSubMeshDS = theTrack->GetSubMeshDS(); aItE = pSubMeshDS->GetElements(); while ( aItE->more() ) { @@ -3842,63 +3982,327 @@ SMESH_MeshEditor::Extrusion_Error return EXTR_PATH_NOT_EDGE; } + list fullList; + const TopoDS_Shape& aS = theTrack->GetSubShape(); - // Sub shape for the Pattern must be an Edge - if ( aS.ShapeType() != TopAbs_EDGE ) + // Sub shape for the Pattern must be an Edge or Wire + if( aS.ShapeType() == TopAbs_EDGE ) { + 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 ); + 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; + aItN = pSubMeshDS->GetNodes(); + while ( aItN->more() ) { + const SMDS_MeshNode* pNode = aItN->next(); + const SMDS_EdgePosition* pEPos = + static_cast( pNode->GetPosition().get() ); + double aT = pEPos->GetUParameter(); + aPrms.push_back( aT ); + } + //Extrusion_Error err = + MakeEdgePathPoints(aPrms, aTrackEdge, (aN1==theN1), fullList); + } + else if( aS.ShapeType() == TopAbs_WIRE ) { + list< SMESH_subMesh* > LSM; + TopTools_SequenceOfShape Edges; + SMESH_subMeshIteratorPtr itSM = theTrack->getDependsOnIterator(false,true); + while(itSM->more()) { + SMESH_subMesh* SM = itSM->next(); + LSM.push_back(SM); + const TopoDS_Shape& aS = SM->GetSubShape(); + Edges.Append(aS); + } + list< list > LLPPs; + int startNid = theN1->GetID(); + TColStd_MapOfInteger UsedNums; + int NbEdges = Edges.Length(); + int i = 1; + for(; i<=NbEdges; i++) { + int k = 0; + list< SMESH_subMesh* >::iterator itLSM = LSM.begin(); + for(; itLSM!=LSM.end(); itLSM++) { + k++; + if(UsedNums.Contains(k)) continue; + aTrackEdge = TopoDS::Edge( Edges.Value(k) ); + SMESH_subMesh* locTrack = *itLSM; + SMESHDS_SubMesh* locMeshDS = locTrack->GetSubMeshDS(); + TopExp::Vertices( aTrackEdge, aV1, aV2 ); + aItN = locTrack->GetFather()->GetSubMesh(aV1)->GetSubMeshDS()->GetNodes(); + const SMDS_MeshNode* aN1 = aItN->next(); + aItN = locTrack->GetFather()->GetSubMesh(aV2)->GetSubMeshDS()->GetNodes(); + const SMDS_MeshNode* aN2 = aItN->next(); + // starting node must be aN1 or aN2 + if ( !( aN1->GetID() == startNid || aN2->GetID() == startNid ) ) continue; + // 2. Collect parameters on the track edge + aPrms.clear(); + aItN = locMeshDS->GetNodes(); + while ( aItN->more() ) { + const SMDS_MeshNode* pNode = aItN->next(); + const SMDS_EdgePosition* pEPos = + static_cast( pNode->GetPosition().get() ); + double aT = pEPos->GetUParameter(); + aPrms.push_back( aT ); + } + list LPP; + //Extrusion_Error err = + MakeEdgePathPoints(aPrms, aTrackEdge,(aN1->GetID()==startNid), LPP); + LLPPs.push_back(LPP); + UsedNums.Add(k); + // update startN for search following egde + if( aN1->GetID() == startNid ) startNid = aN2->GetID(); + else startNid = aN1->GetID(); + break; + } + } + list< list >::iterator itLLPP = LLPPs.begin(); + list firstList = *itLLPP; + list::iterator itPP = firstList.begin(); + for(; itPP!=firstList.end(); itPP++) { + fullList.push_back( *itPP ); + } + SMESH_MeshEditor_PathPoint PP1 = fullList.back(); + fullList.pop_back(); + itLLPP++; + for(; itLLPP!=LLPPs.end(); itLLPP++) { + list currList = *itLLPP; + itPP = currList.begin(); + SMESH_MeshEditor_PathPoint PP2 = currList.front(); + gp_Dir D1 = PP1.Tangent(); + gp_Dir D2 = PP2.Tangent(); + gp_Dir Dnew( gp_Vec( (D1.X()+D2.X())/2, (D1.Y()+D2.Y())/2, + (D1.Z()+D2.Z())/2 ) ); + PP1.SetTangent(Dnew); + fullList.push_back(PP1); + itPP++; + for(; itPP!=firstList.end(); itPP++) { + fullList.push_back( *itPP ); + } + PP1 = fullList.back(); + fullList.pop_back(); + } + // if wire not closed + fullList.push_back(PP1); + // else ??? + } + else { 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; + return MakeExtrElements(theElements, fullList, theHasAngles, theAngles, theLinearVariation, + theHasRefPoint, theRefPoint, theMakeGroups); +} - 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(); +//======================================================================= +//function : ExtrusionAlongTrack +//purpose : +//======================================================================= +SMESH_MeshEditor::Extrusion_Error + SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet & theElements, + SMESH_Mesh* theTrack, + const SMDS_MeshNode* theN1, + const bool theHasAngles, + list& theAngles, + const bool theLinearVariation, + const bool theHasRefPoint, + const gp_Pnt& theRefPoint, + const bool theMakeGroups) +{ + myLastCreatedElems.Clear(); + myLastCreatedNodes.Clear(); - aItN = theTrack->GetFather()->GetSubMesh( aV2 )->GetSubMeshDS()->GetNodes(); - const SMDS_MeshNode* aN2 = aItN->next(); + int aNbE; + std::list aPrms; + TIDSortedElemSet::iterator itElem; - // starting node must be aN1 or aN2 - if ( !( aN1 == theN1 || aN2 == theN1 ) ) - return EXTR_BAD_STARTING_NODE; + gp_XYZ aGC; + TopoDS_Edge aTrackEdge; + TopoDS_Vertex aV1, aV2; - aNbTP = pSubMeshDS->NbNodes() + 2; + SMDS_ElemIteratorPtr aItE; + SMDS_NodeIteratorPtr aItN; + SMDSAbs_ElementType aTypeE; - // 1.2. Angles - vector aAngles( aNbTP ); + TNodeOfNodeListMap mapNewNodes; - for ( j=0; j < aNbTP; ++j ) { - aAngles[j] = 0.; + // 1. Check data + aNbE = theElements.size(); + // nothing to do + if ( !aNbE ) + return EXTR_NO_ELEMENTS; + + // 1.1 Track Pattern + ASSERT( theTrack ); + + SMESHDS_Mesh* pMeshDS = theTrack->GetMeshDS(); + + aItE = pMeshDS->elementsIterator(); + 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; } - if ( theHasAngles ) { - aItD = theAngles.begin(); - for ( j=1; (aItD != theAngles.end()) && (j fullList; + + const TopoDS_Shape& aS = theTrack->GetShapeToMesh(); + // Sub shape for the Pattern must be an Edge or Wire + if( aS.ShapeType() == TopAbs_EDGE ) { + 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 ); + aItN = theTrack->GetSubMesh( aV1 )->GetSubMeshDS()->GetNodes(); + const SMDS_MeshNode* aN1 = aItN->next(); + aItN = theTrack->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; + aItN = pMeshDS->nodesIterator(); + while ( aItN->more() ) { + const SMDS_MeshNode* pNode = aItN->next(); + if( pNode==aN1 || pNode==aN2 ) continue; + const SMDS_EdgePosition* pEPos = + static_cast( pNode->GetPosition().get() ); + double aT = pEPos->GetUParameter(); + aPrms.push_back( aT ); + } + //Extrusion_Error err = + MakeEdgePathPoints(aPrms, aTrackEdge, (aN1==theN1), fullList); + } + else if( aS.ShapeType() == TopAbs_WIRE ) { + list< SMESH_subMesh* > LSM; + TopTools_SequenceOfShape Edges; + TopExp_Explorer eExp(aS, TopAbs_EDGE); + for(; eExp.More(); eExp.Next()) { + TopoDS_Edge E = TopoDS::Edge( eExp.Current() ); + if( BRep_Tool::Degenerated(E) ) continue; + SMESH_subMesh* SM = theTrack->GetSubMesh(E); + if(SM) { + LSM.push_back(SM); + Edges.Append(E); + } + } + list< list > LLPPs; + int startNid = theN1->GetID(); + TColStd_MapOfInteger UsedNums; + int NbEdges = Edges.Length(); + int i = 1; + for(; i<=NbEdges; i++) { + int k = 0; + list< SMESH_subMesh* >::iterator itLSM = LSM.begin(); + for(; itLSM!=LSM.end(); itLSM++) { + k++; + if(UsedNums.Contains(k)) continue; + aTrackEdge = TopoDS::Edge( Edges.Value(k) ); + SMESH_subMesh* locTrack = *itLSM; + SMESHDS_SubMesh* locMeshDS = locTrack->GetSubMeshDS(); + TopExp::Vertices( aTrackEdge, aV1, aV2 ); + aItN = locTrack->GetFather()->GetSubMesh(aV1)->GetSubMeshDS()->GetNodes(); + const SMDS_MeshNode* aN1 = aItN->next(); + aItN = locTrack->GetFather()->GetSubMesh(aV2)->GetSubMeshDS()->GetNodes(); + const SMDS_MeshNode* aN2 = aItN->next(); + // starting node must be aN1 or aN2 + if ( !( aN1->GetID() == startNid || aN2->GetID() == startNid ) ) continue; + // 2. Collect parameters on the track edge + aPrms.clear(); + aItN = locMeshDS->GetNodes(); + while ( aItN->more() ) { + const SMDS_MeshNode* pNode = aItN->next(); + const SMDS_EdgePosition* pEPos = + static_cast( pNode->GetPosition().get() ); + double aT = pEPos->GetUParameter(); + aPrms.push_back( aT ); + } + list LPP; + //Extrusion_Error err = + MakeEdgePathPoints(aPrms, aTrackEdge,(aN1->GetID()==startNid), LPP); + LLPPs.push_back(LPP); + UsedNums.Add(k); + // update startN for search following egde + if( aN1->GetID() == startNid ) startNid = aN2->GetID(); + else startNid = aN1->GetID(); + break; + } } + list< list >::iterator itLLPP = LLPPs.begin(); + list firstList = *itLLPP; + list::iterator itPP = firstList.begin(); + for(; itPP!=firstList.end(); itPP++) { + fullList.push_back( *itPP ); + } + SMESH_MeshEditor_PathPoint PP1 = fullList.back(); + fullList.pop_back(); + itLLPP++; + for(; itLLPP!=LLPPs.end(); itLLPP++) { + list currList = *itLLPP; + itPP = currList.begin(); + SMESH_MeshEditor_PathPoint PP2 = currList.front(); + gp_Pnt P1 = PP1.Pnt(); + //cout<<" PP1: Pnt("<GetNodes(); - 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 ); - } +//======================================================================= +//function : MakeEdgePathPoints +//purpose : auxilary for ExtrusionAlongTrack +//======================================================================= +SMESH_MeshEditor::Extrusion_Error +SMESH_MeshEditor::MakeEdgePathPoints(std::list& aPrms, + const TopoDS_Edge& aTrackEdge, + bool FirstIsStart, + list& LPP) +{ + Standard_Real aTx1, aTx2, aL2, aTolVec, aTolVec2; + aTolVec=1.e-7; + aTolVec2=aTolVec*aTolVec; + double aT1, aT2; + TopoDS_Vertex aV1, aV2; + TopExp::Vertices( aTrackEdge, aV1, aV2 ); + aT1=BRep_Tool::Parameter( aV1, aTrackEdge ); + aT2=BRep_Tool::Parameter( aV2, aTrackEdge ); + // 2. Collect parameters on the track edge + aPrms.push_front( aT1 ); + aPrms.push_back( aT2 ); // sort parameters aPrms.sort(); - if ( aN1 == theN1 ) { + if( FirstIsStart ) { if ( aT1 > aT2 ) { aPrms.reverse(); } @@ -3908,48 +4312,101 @@ SMESH_MeshEditor::Extrusion_Error 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; + Handle(Geom_Curve) aC3D = BRep_Tool::Curve( aTrackEdge, aTx1, aTx2 ); + std::list::iterator aItD = aPrms.begin(); + for(; aItD != aPrms.end(); ++aItD) { + double aT = *aItD; + gp_Pnt aP3D; + gp_Vec aVec; aC3D->D1( aT, aP3D, aVec ); aL2 = aVec.SquareMagnitude(); if ( aL2 < aTolVec2 ) return EXTR_CANT_GET_TANGENT; - gp_Dir aTgt( aVec ); - aAngle = aAngles[j]; - aPP.SetPnt( aP3D ); aPP.SetTangent( aTgt ); - aPP.SetAngle( aAngle ); aPP.SetParameter( aT ); - aPPs[j]=aPP; + LPP.push_back(aPP); } + return EXTR_OK; +} + + +//======================================================================= +//function : MakeExtrElements +//purpose : auxilary for ExtrusionAlongTrack +//======================================================================= +SMESH_MeshEditor::Extrusion_Error +SMESH_MeshEditor::MakeExtrElements(TIDSortedElemSet& theElements, + list& fullList, + const bool theHasAngles, + list& theAngles, + const bool theLinearVariation, + const bool theHasRefPoint, + const gp_Pnt& theRefPoint, + const bool theMakeGroups) +{ + //cout<<"MakeExtrElements fullList.size() = "< aPPs(aNbTP); + // Angles + if( theHasAngles && theAngles.size()>0 && theLinearVariation ) { + LinearAngleVariation(aNbTP-1, theAngles); + } + vector aAngles( aNbTP ); + int j = 0; + for(; j::iterator aItD = theAngles.begin(); + for ( j=1; (aItD != theAngles.end()) && (j::iterator itPP = fullList.begin(); + for(; itPP!=fullList.end(); itPP++) { + j++; + SMESH_MeshEditor_PathPoint PP = *itPP; + PP.SetAngle(aAngles[j]); + aPPs[j] = PP; + } + + TNodeOfNodeListMap mapNewNodes; + TElemOfVecOfNnlmiMap mapElemNewNodes; + TElemOfElemListMap newElemsMap; + TIDSortedElemSet::iterator itElem; + double aX, aY, aZ; + int aNb; + SMDSAbs_ElementType aTypeE; + // source elements for each generated one + SMESH_SequenceOfElemPtr srcElems, srcNodes; // 3. Center of rotation aV0 - aV0 = theRefPoint; + gp_Pnt aV0 = theRefPoint; + gp_XYZ aGC; if ( !theHasRefPoint ) { aNb = 0; aGC.SetCoord( 0.,0.,0. ); - + itElem = theElements.begin(); for ( ; itElem != theElements.end(); itElem++ ) { const SMDS_MeshElement* elem = *itElem; - + SMDS_ElemIteratorPtr itN = elem->nodesIterator(); while ( itN->more() ) { const SMDS_MeshNode* node = static_cast( itN->next() ); aX = node->X(); aY = node->Y(); aZ = node->Z(); - + if ( mapNewNodes.find( node ) == mapNewNodes.end() ) { list aLNx; mapNewNodes[node] = aLNx; @@ -4008,6 +4465,7 @@ SMESH_MeshEditor::Extrusion_Error const SMESH_MeshEditor_PathPoint& aPP0 = aPPs[0]; aP0x = aPP0.Pnt(); aDT0x= aPP0.Tangent(); + //cout<<"j = 0 PP: Pnt("<& Angles) +{ + int nbAngles = Angles.size(); + if( nbSteps > nbAngles ) { + vector theAngles(nbAngles); + list::iterator it = Angles.begin(); + int i = -1; + for(; it!=Angles.end(); it++) { + i++; + theAngles[i] = (*it); + } + list res; + double rAn2St = double( nbAngles ) / double( nbSteps ); + double angPrev = 0, angle; + for ( int iSt = 0; iSt < nbSteps; ++iSt ) { + double angCur = rAn2St * ( iSt+1 ); + double angCurFloor = floor( angCur ); + double angPrevFloor = floor( angPrev ); + if ( angPrevFloor == angCurFloor ) + angle = rAn2St * theAngles[ int( angCurFloor ) ]; + else { + int iP = int( angPrevFloor ); + double angPrevCeil = ceil(angPrev); + angle = ( angPrevCeil - angPrev ) * theAngles[ iP ]; + + int iC = int( angCurFloor ); + if ( iC < nbAngles ) + angle += ( angCur - angCurFloor ) * theAngles[ iC ]; + + iP = int( angPrevCeil ); + while ( iC-- > iP ) + angle += theAngles[ iC ]; + } + res.push_back(angle); + angPrev = angCur; + } + Angles.clear(); + it = res.begin(); + for(; it!=res.end(); it++) + Angles.push_back( *it ); + } +} + + //======================================================================= //function : Transform //purpose : @@ -4614,7 +5122,7 @@ struct SMESH_NodeSearcherImpl: public SMESH_NodeSearcher SMDS_MeshNode tgtNode( thePnt.X(), thePnt.Y(), thePnt.Z() ); list nodes; const double precision = 1e-6; - myOctreeNode->NodesAround( &tgtNode, &nodes, precision ); + //myOctreeNode->NodesAround( &tgtNode, &nodes, precision ); double minSqDist = DBL_MAX; Bnd_B3d box; @@ -6721,6 +7229,7 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d) SMESH_subMesh* sm = smIt->next(); if ( SMESHDS_SubMesh *smDS = sm->GetSubMeshDS() ) { aHelper.SetSubShape( sm->GetSubShape() ); + if ( !theForce3d) aHelper.SetCheckNodePosition(true); nbCheckedElems += convertElemToQuadratic(smDS, aHelper, theForce3d); } } @@ -6815,6 +7324,10 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d) ReplaceElemInGroups(volume, NewVolume, meshDS); } } + if ( !theForce3d ) { + aHelper.SetSubShape(0); // apply to the whole mesh + aHelper.FixQuadraticElements(); + } } //======================================================================= @@ -7678,89 +8191,166 @@ SMESH_MeshEditor::FindMatchingNodes(set& theSide1, /*! \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 + \param theElems - the list of elements (edges or faces) to be replicated + The nodes for duplication could be found from these elements + \param theNodesNot - list of nodes to NOT replicate + \param theAffectedElems - the list of elements (cells and edges) to which the + replicated nodes should be associated to. \return TRUE if operation has been completed successfully, FALSE otherwise */ -bool SMESH_MeshEditor::DoubleNodes( const std::list< int >& theListOfNodes, - const std::list< int >& theListOfModifiedElems ) +bool SMESH_MeshEditor::DoubleNodes( const TIDSortedElemSet& theElems, + const TIDSortedElemSet& theNodesNot, + const TIDSortedElemSet& theAffectedElems ) { myLastCreatedElems.Clear(); myLastCreatedNodes.Clear(); - if ( theListOfNodes.size() == 0 ) + if ( theElems.size() == 0 ) return false; SMESHDS_Mesh* aMeshDS = GetMeshDS(); if ( !aMeshDS ) return false; - // iterate through nodes and duplicate them - + bool res = false; std::map< const SMDS_MeshNode*, const SMDS_MeshNode* > anOldNodeToNewNode; + // duplicate elements and nodes + res = doubleNodes( aMeshDS, theElems, theNodesNot, anOldNodeToNewNode, true ); + // replce nodes by duplications + res = doubleNodes( aMeshDS, theAffectedElems, theNodesNot, anOldNodeToNewNode, false ); + return res; +} - 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 ) +/*! + \brief Creates a hole in a mesh by doubling the nodes of some particular elements + \param theMeshDS - mesh instance + \param theElems - the elements replicated or modified (nodes should be changed) + \param theNodesNot - nodes to NOT replicate + \param theNodeNodeMap - relation of old node to new created node + \param theIsDoubleElem - flag os to replicate element or modify + \return TRUE if operation has been completed successfully, FALSE otherwise +*/ +bool SMESH_MeshEditor::doubleNodes( SMESHDS_Mesh* theMeshDS, + const TIDSortedElemSet& theElems, + const TIDSortedElemSet& theNodesNot, + std::map< const SMDS_MeshNode*, + const SMDS_MeshNode* >& theNodeNodeMap, + const bool theIsDoubleElem ) +{ + // iterate on through element and duplicate them (by nodes duplication) + bool res = false; + TIDSortedElemSet::iterator elemItr = theElems.begin(); + for ( ; elemItr != theElems.end(); ++elemItr ) { - int aCurr = *anElemIter; - SMDS_MeshElement* anElem = (SMDS_MeshElement*)aMeshDS->FindElement( aCurr ); - if ( !anElem ) + const SMDS_MeshElement* anElem = *elemItr; + if (!anElem) continue; - vector aNodeArr( anElem->NbNodes() ); - + bool isDuplicate = false; + // duplicate nodes to duplicate element + std::vector newNodes( 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() ) + SMDS_MeshNode* aNewNode = aCurrNode; + if ( theNodeNodeMap.find( aCurrNode ) != theNodeNodeMap.end() ) + aNewNode = (SMDS_MeshNode*)theNodeNodeMap[ aCurrNode ]; + else if ( theIsDoubleElem && theNodesNot.find( aCurrNode ) == theNodesNot.end() ) { - const SMDS_MeshNode* aNewNode = anOldNodeToNewNode[ aCurrNode ]; - aNodeArr[ ind++ ] = aNewNode; + // duplicate node + aNewNode = theMeshDS->AddNode( aCurrNode->X(), aCurrNode->Y(), aCurrNode->Z() ); + theNodeNodeMap[ aCurrNode ] = aNewNode; + myLastCreatedNodes.Append( aNewNode ); } - else - aNodeArr[ ind++ ] = aCurrNode; + isDuplicate |= (aCurrNode == aNewNode); + newNodes[ ind++ ] = aNewNode; } - anElemToNodes[ anElem ] = aNodeArr; + if ( !isDuplicate ) + continue; + + if ( theIsDoubleElem ) + myLastCreatedElems.Append( AddElement(newNodes, anElem->GetType(), anElem->IsPoly()) ); + else + theMeshDS->ChangeElementNodes( anElem, &newNodes[ 0 ], anElem->NbNodes() ); + + res = true; } + return res; +} - // Change nodes of elements +/*! + \brief Check if element located inside shape + \return TRUE if IN or ON shape, FALSE otherwise +*/ - std::map< SMDS_MeshElement*, vector >::iterator - anElemToNodesIter = anElemToNodes.begin(); - for ( ; anElemToNodesIter != anElemToNodes.end(); ++anElemToNodesIter ) +static bool isInside(const SMDS_MeshElement* theElem, + BRepClass3d_SolidClassifier& theBsc3d, + const double theTol) +{ + gp_XYZ centerXYZ (0, 0, 0); + SMDS_ElemIteratorPtr aNodeItr = theElem->nodesIterator(); + while (aNodeItr->more()) { - const SMDS_MeshElement* anElem = anElemToNodesIter->first; - vector aNodeArr = anElemToNodesIter->second; - if ( anElem ) - aMeshDS->ChangeElementNodes( anElem, &aNodeArr[ 0 ], anElem->NbNodes() ); + SMDS_MeshNode* aNode = (SMDS_MeshNode*)aNodeItr->next(); + centerXYZ += gp_XYZ(aNode->X(), aNode->Y(), aNode->Z()); } + gp_Pnt aPnt(centerXYZ); + theBsc3d.Perform(aPnt, theTol); + TopAbs_State aState = theBsc3d.State(); + return (aState == TopAbs_IN || aState == TopAbs_ON ); +} - return true; +/*! + \brief Creates a hole in a mesh by doubling the nodes of some particular elements + \param theElems - group of of elements (edges or faces) to be replicated + \param theNodesNot - group of nodes not to replicated + \param theShape - shape to detect affected elements (element which geometric center + located on or inside shape). + The replicated nodes should be associated to affected elements. + \return TRUE if operation has been completed successfully, FALSE otherwise +*/ + +bool SMESH_MeshEditor::DoubleNodesInRegion( const TIDSortedElemSet& theElems, + const TIDSortedElemSet& theNodesNot, + const TopoDS_Shape& theShape ) +{ + SMESHDS_Mesh* aMesh = GetMeshDS(); + if (!aMesh) + return false; + if ( theShape.IsNull() ) + return false; + + const double aTol = Precision::Confusion(); + BRepClass3d_SolidClassifier bsc3d(theShape); + bsc3d.PerformInfinitePoint(aTol); + + // iterates on indicated elements and get elements by back references from their nodes + TIDSortedElemSet anAffected; + TIDSortedElemSet::iterator elemItr = theElems.begin(); + for ( ; elemItr != theElems.end(); ++elemItr ) + { + SMDS_MeshElement* anElem = (SMDS_MeshElement*)*elemItr; + if (!anElem) + continue; + + SMDS_ElemIteratorPtr nodeItr = anElem->nodesIterator(); + while ( nodeItr->more() ) + { + const SMDS_MeshNode* aNode = static_cast(nodeItr->next()); + if ( !aNode || theNodesNot.find(aNode) != theNodesNot.end() ) + continue; + SMDS_ElemIteratorPtr backElemItr = aNode->GetInverseElementIterator(); + while ( backElemItr->more() ) + { + SMDS_MeshElement* curElem = (SMDS_MeshElement*)backElemItr->next(); + if ( curElem && theElems.find(curElem) == theElems.end() && + isInside( curElem, bsc3d, aTol ) ) + anAffected.insert( curElem ); + } + } + } + return DoubleNodes( theElems, theNodesNot, anAffected ); }