X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FSMESH%2FSMESH_MeshEditor.cxx;h=7466070e46f335978bf01c4b6e44712c5ff055c7;hp=b86d7f5e0d270e71075857179eb6294365413b65;hb=2c751a0eddb8c36cbd7582543d6b18d6a3e827e1;hpb=3a821b48ba986795abde72f524fa1a62a5802df2 diff --git a/src/SMESH/SMESH_MeshEditor.cxx b/src/SMESH/SMESH_MeshEditor.cxx index b86d7f5e0..7466070e4 100644 --- a/src/SMESH/SMESH_MeshEditor.cxx +++ b/src/SMESH/SMESH_MeshEditor.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2019 CEA/DEN, EDF R&D, OPEN CASCADE // // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS @@ -97,7 +97,6 @@ #include #include -#include #include "SMESH_TryCatch.hxx" // include after OCCT headers! @@ -162,7 +161,7 @@ SMESH_MeshEditor::ElemFeatures::Init( const SMDS_MeshElement* elem, bool basicOn myIsQuad = elem->IsQuadratic(); if ( myType == SMDSAbs_Volume && !basicOnly ) { - vector quant = static_cast( elem )->GetQuantities(); + vector quant = static_cast( elem )->GetQuantities(); myPolyhedQuantities.swap( quant ); } } @@ -607,25 +606,6 @@ static void shiftNodesQuadTria(vector< const SMDS_MeshNode* >& aNodes) aNodes[5] = nd2; } -//======================================================================= -//function : nbEdgeConnectivity -//purpose : return number of the edges connected with the theNode. -// if theEdges has connections with the other type of the -// elements, return -1 -//======================================================================= - -static int nbEdgeConnectivity(const SMDS_MeshNode* theNode) -{ - // SMDS_ElemIteratorPtr elemIt = theNode->GetInverseElementIterator(); - // int nb=0; - // while(elemIt->more()) { - // elemIt->next(); - // nb++; - // } - // return nb; - return theNode->NbInverseElements(); -} - //======================================================================= //function : getNodesFromTwoTria //purpose : @@ -682,16 +662,16 @@ bool SMESH_MeshEditor::InverseDiag (const SMDS_MeshElement * theTria1, { ClearLastCreated(); - if (!theTria1 || !theTria2) + if ( !theTria1 || !theTria2 || + !dynamic_cast( theTria1 ) || + !dynamic_cast( theTria2 ) || + theTria1->GetType() != SMDSAbs_Face || + theTria2->GetType() != SMDSAbs_Face ) return false; - const SMDS_VtkFace* F1 = dynamic_cast( theTria1 ); - if (!F1) return false; - const SMDS_VtkFace* F2 = dynamic_cast( theTria2 ); - if (!F2) return false; if ((theTria1->GetEntityType() == SMDSEntity_Triangle) && - (theTria2->GetEntityType() == SMDSEntity_Triangle)) { - + (theTria2->GetEntityType() == SMDSEntity_Triangle)) + { // 1 +--+ A theTria1: ( 1 A B ) A->2 ( 1 2 B ) 1 +--+ A // | /| theTria2: ( B A 2 ) B->1 ( 1 A 2 ) |\ | // |/ | | \| @@ -805,9 +785,9 @@ bool SMESH_MeshEditor::InverseDiag (const SMDS_MeshElement * theTria1, gp_Pnt xyz; if ( F.IsNull() ) { - xyz = ( SMESH_TNodeXYZ( nodes[3] ) + - SMESH_TNodeXYZ( nodes[4] ) + - SMESH_TNodeXYZ( nodes[5] )) / 3.; + xyz = ( SMESH_NodeXYZ( nodes[3] ) + + SMESH_NodeXYZ( nodes[4] ) + + SMESH_NodeXYZ( nodes[5] )) / 3.; } else { @@ -886,10 +866,10 @@ bool SMESH_MeshEditor::InverseDiag (const SMDS_MeshNode * theNode1, if ( !findTriangles( theNode1, theNode2, tr1, tr2 )) return false; - const SMDS_VtkFace* F1 = dynamic_cast( tr1 ); - if (!F1) return false; - const SMDS_VtkFace* F2 = dynamic_cast( tr2 ); - if (!F2) return false; + if ( !dynamic_cast( tr1 ) || + !dynamic_cast( tr2 )) + return false; + if ((tr1->GetEntityType() == SMDSEntity_Triangle) && (tr2->GetEntityType() == SMDSEntity_Triangle)) { @@ -1006,15 +986,15 @@ bool SMESH_MeshEditor::DeleteDiag (const SMDS_MeshNode * theNode1, if ( !findTriangles( theNode1, theNode2, tr1, tr2 )) return false; - const SMDS_VtkFace* F1 = dynamic_cast( tr1 ); - if (!F1) return false; - const SMDS_VtkFace* F2 = dynamic_cast( tr2 ); - if (!F2) return false; + if ( !dynamic_cast( tr1 ) || + !dynamic_cast( tr2 )) + return false; + SMESHDS_Mesh * aMesh = GetMeshDS(); if ((tr1->GetEntityType() == SMDSEntity_Triangle) && - (tr2->GetEntityType() == SMDSEntity_Triangle)) { - + (tr2->GetEntityType() == SMDSEntity_Triangle)) + { const SMDS_MeshNode* aNodes [ 4 ]; if ( ! getQuadrangleNodes( aNodes, theNode1, theNode2, tr1, tr2 )) return false; @@ -1025,9 +1005,8 @@ bool SMESH_MeshEditor::DeleteDiag (const SMDS_MeshNode * theNode1, AddToSameGroups( newElem, tr1, aMesh ); int aShapeId = tr1->getshapeId(); if ( aShapeId ) - { aMesh->SetMeshElementOnShape( newElem, aShapeId ); - } + aMesh->RemoveElement( tr1 ); aMesh->RemoveElement( tr2 ); @@ -1109,8 +1088,7 @@ bool SMESH_MeshEditor::Reorient (const SMDS_MeshElement * theElem) const SMDSAbs_EntityType geomType = theElem->GetEntityType(); if ( geomType == SMDSEntity_Polyhedra ) // polyhedron { - const SMDS_VtkVolume* aPolyedre = - dynamic_cast( theElem ); + const SMDS_MeshVolume* aPolyedre = SMDS_Mesh::DownCast< SMDS_MeshVolume >( theElem ); if (!aPolyedre) { MESSAGE("Warning: bad volumic element"); return false; @@ -1168,7 +1146,7 @@ int SMESH_MeshEditor::Reorient2D (TIDSortedElemSet & theFaces, if ( theFaces.empty() ) { - SMDS_FaceIteratorPtr fIt = GetMeshDS()->facesIterator(/*idInceasingOrder=*/true); + SMDS_FaceIteratorPtr fIt = GetMeshDS()->facesIterator(/*idInceasingOrder=true*/); while ( fIt->more() ) theFaces.insert( theFaces.end(), fIt->next() ); } @@ -1425,7 +1403,7 @@ bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet & theElems, const SMDS_MeshElement* newElem1 = 0; const SMDS_MeshElement* newElem2 = 0; - if ( !elem->IsQuadratic() ) // split liner quadrangle + if ( !elem->IsQuadratic() ) // split linear quadrangle { // for MaxElementLength2D functor we return minimum diagonal for splitting, // because aBadRate1=2*len(diagonal 1-3); aBadRate2=2*len(diagonal 2-4) @@ -1556,7 +1534,7 @@ void SMESH_MeshEditor::QuadTo4Tri (TIDSortedElemSet & theElems) if ( F.IsNull() ) { for ( ; iN < nodes.size(); ++iN ) - xyz[ iN ] = SMESH_TNodeXYZ( nodes[ iN ] ); + xyz[ iN ] = SMESH_NodeXYZ( nodes[ iN ] ); for ( ; iN < 8; ++iN ) // mid-side points of a linear qudrangle xyz[ iN ] = 0.5 * ( xyz[ iN - 4 ] + xyz[( iN - 3 )%4 ] ); @@ -2361,7 +2339,7 @@ void SMESH_MeshEditor::SplitVolumes (const TFacetOfElem & theElems, if ( fSubMesh ) // update position of the bary node on geometry { if ( subMesh ) - subMesh->RemoveNode( baryNode, false ); + subMesh->RemoveNode( baryNode ); GetMeshDS()->SetNodeOnFace( baryNode, fSubMesh->GetID() ); const TopoDS_Shape& s = GetMeshDS()->IndexToShape( fSubMesh->GetID() ); if ( !s.IsNull() && s.ShapeType() == TopAbs_FACE ) @@ -3830,7 +3808,7 @@ void SMESH_MeshEditor::Smooth (TIDSortedElemSet & theElems, // } if ( project ) { // compute new UV gp_XY newUV; - gp_Pnt pNode = SMESH_TNodeXYZ( node ); + gp_Pnt pNode = SMESH_NodeXYZ( node ); if ( !getClosestUV( projector, pNode, newUV )) { MESSAGE("Node Projection Failed " << node); } @@ -4085,7 +4063,7 @@ void SMESH_MeshEditor::Smooth (TIDSortedElemSet & theElems, const SMDS_MeshElement* QF = *elemIt; if ( QF->IsQuadratic() ) { - nodes.assign( SMDS_MeshElement::iterator( QF->interlacedNodesElemIterator() ), + nodes.assign( SMDS_MeshElement::iterator( QF->interlacedNodesIterator() ), SMDS_MeshElement::iterator() ); nodes.push_back( nodes[0] ); gp_Pnt xyz; @@ -4099,9 +4077,9 @@ void SMESH_MeshEditor::Smooth (TIDSortedElemSet & theElems, xyz = surface->Value( uv.X(), uv.Y() ); } else { - xyz = 0.5 * ( SMESH_TNodeXYZ( nodes[i-1] ) + SMESH_TNodeXYZ( nodes[i+1] )); + xyz = 0.5 * ( SMESH_NodeXYZ( nodes[i-1] ) + SMESH_NodeXYZ( nodes[i+1] )); } - if (( SMESH_TNodeXYZ( nodes[i] ) - xyz.XYZ() ).Modulus() > disttol ) + if (( SMESH_NodeXYZ( nodes[i] ) - xyz.XYZ() ).Modulus() > disttol ) // we have to move a medium node aMesh->MoveNode( nodes[i], xyz.X(), xyz.Y(), xyz.Z() ); } @@ -4129,8 +4107,8 @@ namespace const int iNotSame) { - SMESH_TNodeXYZ pP = prevNodes[ iNotSame ]; - SMESH_TNodeXYZ pN = nextNodes[ iNotSame ]; + SMESH_NodeXYZ pP = prevNodes[ iNotSame ]; + SMESH_NodeXYZ pN = nextNodes[ iNotSame ]; gp_XYZ extrDir( pN - pP ), faceNorm; SMESH_MeshAlgos::FaceNormal( face, faceNorm, /*normalized=*/false ); @@ -4834,9 +4812,9 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap & mapNewNodes, SMDS_VolumeTool vTool( *v, /*ignoreCentralNodes=*/false ); 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 + if ( vTool.IsFreeFace( iF ) && + vTool.GetFaceNodes( iF, faceNodeSet ) && + initNodeSet != faceNodeSet) // except an initial face { if ( nbSteps == 1 && faceNodeSet == topNodeSet ) continue; @@ -5186,6 +5164,7 @@ SMESH_MeshEditor::RotationSweep(TIDSortedElemSet theElemSets[2], SMESH_MeshEditor::ExtrusParam::ExtrusParam( const gp_Vec& theStep, const int theNbSteps, const std::list& theScales, + const std::list& theAngles, const gp_XYZ* theBasePoint, const int theFlags, const double theTolerance): @@ -5200,32 +5179,52 @@ SMESH_MeshEditor::ExtrusParam::ExtrusParam( const gp_Vec& theStep, for (int i=1; i<=theNbSteps; i++ ) mySteps->Append( stepSize ); - int nbScales = theScales.size(); - if ( nbScales > 0 ) + if ( !theScales.empty() ) { - if ( IsLinearVariation() && nbScales < theNbSteps ) + if ( IsScaleVariation() && (int)theScales.size() < theNbSteps ) + linearScaleVariation( theNbSteps, const_cast< std::list& >( theScales )); + + // add medium scales + std::list::const_iterator s2 = theScales.begin(), s1 = s2++; + myScales.reserve( theNbSteps * 2 ); + myScales.push_back( 0.5 * ( *s1 + 1. )); + myScales.push_back( *s1 ); + for ( ; s2 != theScales.end(); s1 = s2++ ) { - myScales.reserve( theNbSteps ); - std::list::const_iterator scale = theScales.begin(); - double prevScale = 1.0; - for ( int iSc = 1; scale != theScales.end(); ++scale, ++iSc ) - { - int iStep = int( iSc / double( nbScales ) * theNbSteps + 0.5 ); - int stDelta = Max( 1, iStep - myScales.size()); - double scDelta = ( *scale - prevScale ) / stDelta; - for ( int iStep = 0; iStep < stDelta; ++iStep ) - { - myScales.push_back( prevScale + scDelta ); - prevScale = myScales.back(); - } - prevScale = *scale; - } + myScales.push_back( 0.5 * ( *s1 + *s2 )); + myScales.push_back( *s2 ); } - else + } + + if ( !theAngles.empty() ) + { + std::list& angles = const_cast< std::list& >( theAngles ); + if ( IsAngleVariation() && (int)theAngles.size() < theNbSteps ) + linearAngleVariation( theNbSteps, angles ); + + // accumulate angles + double angle = 0; + int nbAngles = 0; + std::list::iterator a1 = angles.begin(), a2; + for ( ; a1 != angles.end(); ++a1, ++nbAngles ) + { + angle += *a1; + *a1 = angle; + } + while ( nbAngles++ < theNbSteps ) + angles.push_back( angles.back() ); + + // add medium angles + a2 = angles.begin(), a1 = a2++; + myAngles.push_back( 0.5 * *a1 ); + myAngles.push_back( *a1 ); + for ( ; a2 != angles.end(); a1 = a2++ ) { - myScales.assign( theScales.begin(), theScales.end() ); + myAngles.push_back( 0.5 * ( *a1 + *a2 )); + myAngles.push_back( *a2 ); } } + if ( theBasePoint ) { myBaseP = *theBasePoint; @@ -5296,6 +5295,41 @@ SMESH_MeshEditor::ExtrusParam::ExtrusParam( const double theStepSize, } } +//======================================================================= +//function : ExtrusParam +//purpose : for extrusion along path +//======================================================================= + +SMESH_MeshEditor::ExtrusParam::ExtrusParam( const std::vector< PathPoint >& thePoints, + const gp_Pnt* theBasePoint, + const std::list& theScales, + const bool theMakeGroups ) + : myBaseP( Precision::Infinite(), 0, 0 ), + myFlags( EXTRUSION_FLAG_BOUNDARY | ( theMakeGroups ? EXTRUSION_FLAG_GROUPS : 0 )), + myPathPoints( thePoints ) +{ + if ( theBasePoint ) + { + myBaseP = theBasePoint->XYZ(); + } + + if ( !theScales.empty() ) + { + // add medium scales + std::list::const_iterator s2 = theScales.begin(), s1 = s2++; + myScales.reserve( thePoints.size() * 2 ); + myScales.push_back( 0.5 * ( 1. + *s1 )); + myScales.push_back( *s1 ); + for ( ; s2 != theScales.end(); s1 = s2++ ) + { + myScales.push_back( 0.5 * ( *s1 + *s2 )); + myScales.push_back( *s2 ); + } + } + + myMakeNodesFun = & SMESH_MeshEditor::ExtrusParam::makeNodesAlongTrack; +} + //======================================================================= //function : ExtrusParam::SetElementsToUse //purpose : stores elements to use for extrusion by normal, depending on @@ -5325,7 +5359,7 @@ void SMESH_MeshEditor::ExtrusParam::SetElementsToUse( const TIDSortedElemSet& el while ( itN->more() ) { const SMDS_MeshElement* node = itN->next(); if ( newNodes.insert( node ).second ) - myBaseP += SMESH_TNodeXYZ( node ); + myBaseP += SMESH_NodeXYZ( node ); } } } @@ -5391,7 +5425,7 @@ makeNodesByDir( SMESHDS_Mesh* mesh, std::list & newNodes, const bool makeMediumNodes) { - gp_XYZ p = SMESH_TNodeXYZ( srcNode ); + gp_XYZ p = SMESH_NodeXYZ( srcNode ); int nbNodes = 0; for ( beginStepIter( makeMediumNodes ); moreSteps(); ++nbNodes ) // loop on steps @@ -5401,38 +5435,37 @@ makeNodesByDir( SMESHDS_Mesh* mesh, newNodes.push_back( newNode ); } - if ( !myScales.empty() ) + if ( !myScales.empty() || !myAngles.empty() ) { - if ( makeMediumNodes && myMediumScales.empty() ) - { - myMediumScales.resize( myScales.size() ); - double prevFactor = 1.; - for ( size_t i = 0; i < myScales.size(); ++i ) - { - myMediumScales[i] = 0.5 * ( prevFactor + myScales[i] ); - prevFactor = myScales[i]; - } - } - typedef std::vector::iterator ScaleIt; - ScaleIt scales[] = { myScales.begin(), myMediumScales.begin() }; - - size_t iSc = 0, nbScales = myScales.size() + myMediumScales.size(); + gp_XYZ center = myBaseP; + gp_Ax1 ratationAxis( center, myDir ); + gp_Trsf rotation; - gp_XYZ center = myBaseP; std::list::iterator nIt = newNodes.begin(); - size_t iN = 0; - for ( beginStepIter( makeMediumNodes ); moreSteps() && ( iN < nbScales ); ++nIt, ++iN ) + size_t i = !makeMediumNodes; + for ( beginStepIter( makeMediumNodes ); + moreSteps(); + ++nIt, i += 1 + !makeMediumNodes ) { center += myDir.XYZ() * nextStep(); - iSc += int( makeMediumNodes ); - ScaleIt& scale = scales[ iSc % 2 ]; - - gp_XYZ xyz = SMESH_TNodeXYZ( *nIt ); - xyz = ( *scale * ( xyz - center )) + center; - mesh->MoveNode( *nIt, xyz.X(), xyz.Y(), xyz.Z() ); - - ++scale; + gp_XYZ xyz = SMESH_NodeXYZ( *nIt ); + bool moved = false; + if ( i < myScales.size() ) + { + xyz = ( myScales[i] * ( xyz - center )) + center; + moved = true; + } + if ( !myAngles.empty() ) + { + rotation.SetRotation( ratationAxis, myAngles[i] ); + rotation.Transforms( xyz ); + moved = true; + } + if ( moved ) + mesh->MoveNode( *nIt, xyz.X(), xyz.Y(), xyz.Z() ); + else + break; } } return nbNodes; @@ -5449,7 +5482,7 @@ makeNodesByDirAndSew( SMESHDS_Mesh* mesh, std::list & newNodes, const bool makeMediumNodes) { - gp_XYZ P1 = SMESH_TNodeXYZ( srcNode ); + gp_XYZ P1 = SMESH_NodeXYZ( srcNode ); int nbNodes = 0; for ( beginStepIter( makeMediumNodes ); moreSteps(); ++nbNodes ) // loop on steps @@ -5460,10 +5493,11 @@ makeNodesByDirAndSew( SMESHDS_Mesh* mesh, // if myNodes.size()>0 we 'nave to use given sequence // else - use all nodes of mesh const SMDS_MeshNode * node = 0; - if ( myNodes.Length() > 0 ) { - int i; - for ( i = 1; i <= myNodes.Length(); i++ ) { - gp_XYZ P2 = SMESH_TNodeXYZ( myNodes.Value(i) ); + if ( myNodes.Length() > 0 ) + { + for ( int i = 1; i <= myNodes.Length(); i++ ) + { + SMESH_NodeXYZ P2 = myNodes.Value(i); if (( P1 - P2 ).SquareModulus() < myTolerance * myTolerance ) { node = myNodes.Value(i); @@ -5471,10 +5505,12 @@ makeNodesByDirAndSew( SMESHDS_Mesh* mesh, } } } - else { + else + { SMDS_NodeIteratorPtr itn = mesh->nodesIterator(); - while(itn->more()) { - SMESH_TNodeXYZ P2( itn->next() ); + while(itn->more()) + { + SMESH_NodeXYZ P2 = itn->next(); if (( P1 - P2 ).SquareModulus() < myTolerance * myTolerance ) { node = P2._node; @@ -5506,7 +5542,7 @@ makeNodesByNormal2D( SMESHDS_Mesh* mesh, { const bool alongAvgNorm = ( myFlags & EXTRUSION_FLAG_BY_AVG_NORMAL ); - gp_XYZ p = SMESH_TNodeXYZ( srcNode ); + gp_XYZ p = SMESH_NodeXYZ( srcNode ); // get normals to faces sharing srcNode vector< gp_XYZ > norms, baryCenters; @@ -5526,7 +5562,7 @@ makeNodesByNormal2D( SMESHDS_Mesh* mesh, gp_XYZ bc(0,0,0); int nbN = 0; for ( SMDS_ElemIteratorPtr nIt = face->nodesIterator(); nIt->more(); ++nbN ) - bc += SMESH_TNodeXYZ( nIt->next() ); + bc += SMESH_NodeXYZ( nIt->next() ); baryCenters.push_back( bc / nbN ); } } @@ -5596,6 +5632,100 @@ makeNodesByNormal1D( SMESHDS_Mesh* mesh, return 0; } +//======================================================================= +//function : ExtrusParam::makeNodesAlongTrack +//purpose : create nodes for extrusion along path +//======================================================================= + +int SMESH_MeshEditor::ExtrusParam:: +makeNodesAlongTrack( SMESHDS_Mesh* mesh, + const SMDS_MeshNode* srcNode, + std::list & newNodes, + const bool makeMediumNodes) +{ + const Standard_Real aTolAng=1.e-4; + + gp_Pnt aV0x = myBaseP; + gp_Pnt aPN0 = SMESH_NodeXYZ( srcNode ); + + const PathPoint& aPP0 = myPathPoints[0]; + gp_Pnt aP0x = aPP0.myPnt; + gp_Dir aDT0x= aPP0.myTgt; + + std::vector< gp_Pnt > centers; + centers.reserve( NbSteps() * 2 ); + + gp_Trsf aTrsf, aTrsfRot, aTrsfRotT1T0; + + for ( size_t j = 1; j < myPathPoints.size(); ++j ) + { + const PathPoint& aPP = myPathPoints[j]; + const gp_Pnt& aP1x = aPP.myPnt; + const gp_Dir& aDT1x = aPP.myTgt; + + // Translation + gp_Vec aV01x( aP0x, aP1x ); + aTrsf.SetTranslation( aV01x ); + gp_Pnt aV1x = aV0x.Transformed( aTrsf ); + gp_Pnt aPN1 = aPN0.Transformed( aTrsf ); + + // rotation 1 [ T1,T0 ] + Standard_Real aAngleT1T0 = -aDT1x.Angle( aDT0x ); + if ( fabs( aAngleT1T0 ) > aTolAng ) + { + gp_Dir aDT1T0 = aDT1x ^ aDT0x; + aTrsfRotT1T0.SetRotation( gp_Ax1( aV1x, aDT1T0 ), aAngleT1T0 ); + + aPN1 = aPN1.Transformed( aTrsfRotT1T0 ); + } + + // rotation 2 + if ( aPP.myAngle != 0. ) + { + aTrsfRot.SetRotation( gp_Ax1( aV1x, aDT1x ), aPP.myAngle ); + aPN1 = aPN1.Transformed( aTrsfRot ); + } + + // make new node + if ( makeMediumNodes ) + { + // create additional node + gp_XYZ midP = 0.5 * ( aPN1.XYZ() + aPN0.XYZ() ); + const SMDS_MeshNode* newNode = mesh->AddNode( midP.X(), midP.Y(), midP.Z() ); + newNodes.push_back( newNode ); + + } + const SMDS_MeshNode* newNode = mesh->AddNode( aPN1.X(), aPN1.Y(), aPN1.Z() ); + newNodes.push_back( newNode ); + + centers.push_back( 0.5 * ( aV0x.XYZ() + aV1x.XYZ() )); + centers.push_back( aV1x ); + + aPN0 = aPN1; + aP0x = aP1x; + aV0x = aV1x; + aDT0x = aDT1x; + } + + // scale + if ( !myScales.empty() ) + { + gp_Trsf aTrsfScale; + std::list::iterator node = newNodes.begin(); + for ( size_t i = !makeMediumNodes; + i < myScales.size() && node != newNodes.end(); + i += ( 1 + !makeMediumNodes ), ++node ) + { + aTrsfScale.SetScale( centers[ i ], myScales[ i ] ); + gp_Pnt aN = SMESH_NodeXYZ( *node ); + gp_Pnt aP = aN.Transformed( aTrsfScale ); + mesh->MoveNode( *node, aP.X(), aP.Y(), aP.Z() ); + } + } + + return myPathPoints.size() + makeMediumNodes * ( myPathPoints.size() - 2 ); +} + //======================================================================= //function : ExtrusionSweep //purpose : @@ -5609,10 +5739,31 @@ SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet theElems[2], const int theFlags, const double theTolerance) { - ExtrusParam aParams( theStep, theNbSteps, std::list(), 0, theFlags, theTolerance ); + std::list dummy; + ExtrusParam aParams( theStep, theNbSteps, dummy, dummy, 0, + theFlags, theTolerance ); return ExtrusionSweep( theElems, aParams, newElemsMap ); } +namespace +{ + +//======================================================================= +//function : getOriFactor +//purpose : Return -1 or 1 depending on if order of given nodes corresponds to +// edge curve orientation +//======================================================================= + + double getOriFactor( const TopoDS_Edge& edge, + const SMDS_MeshNode* n1, + const SMDS_MeshNode* n2, + SMESH_MesherHelper& helper) + { + double u1 = helper.GetNodeU( edge, n1, n2 ); + double u2 = helper.GetNodeU( edge, n2, n1 ); + return u1 < u2 ? 1. : -1.; + } +} //======================================================================= //function : ExtrusionSweep @@ -5661,11 +5812,11 @@ SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet theElemSets[2], newNodesItVec.reserve( nbNodes ); // loop on elem nodes - SMDS_ElemIteratorPtr itN = elem->nodesIterator(); + SMDS_NodeIteratorPtr itN = elem->nodeIterator(); while ( itN->more() ) { // check if a node has been already sweeped - const SMDS_MeshNode* node = cast2Node( itN->next() ); + const SMDS_MeshNode* node = itN->next(); TNodeOfNodeListMap::iterator nIt = mapNewNodes.insert( make_pair( node, list() )).first; list& listNewNodes = nIt->second; @@ -5699,6 +5850,11 @@ SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet theElemSets[2], } else { + if ( theParams.ToMakeBoundary() ) + { + GetMeshDS()->Modified(); + throw SALOME_Exception( SMESH_Comment("Can't extrude node #") << node->GetID() ); + } break; // newNodesItVec will be shorter than nbNodes } } @@ -5726,730 +5882,183 @@ SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet theElemSets[2], //======================================================================= SMESH_MeshEditor::Extrusion_Error SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet theElements[2], - SMESH_subMesh* theTrack, + SMESH_Mesh* theTrackMesh, + SMDS_ElemIteratorPtr theTrackIterator, const SMDS_MeshNode* theN1, - const bool theHasAngles, - list& theAngles, - const bool theLinearVariation, - const bool theHasRefPoint, - const gp_Pnt& theRefPoint, + std::list& theAngles, + const bool theAngleVariation, + std::list& theScales, + const bool theScaleVariation, + const gp_Pnt* theRefPoint, const bool theMakeGroups) { ClearLastCreated(); - int aNbE; - std::list aPrms; - TIDSortedElemSet::iterator itElem; - - gp_XYZ aGC; - TopoDS_Edge aTrackEdge; - TopoDS_Vertex aV1, aV2; - - SMDS_ElemIteratorPtr aItE; - SMDS_NodeIteratorPtr aItN; - SMDSAbs_ElementType aTypeE; - - TNodeOfNodeListMap mapNewNodes; - // 1. Check data - aNbE = theElements[0].size() + theElements[1].size(); - // nothing to do - if ( !aNbE ) + if ( theElements[0].empty() && theElements[1].empty() ) return EXTR_NO_ELEMENTS; - // 1.1 Track Pattern - ASSERT( theTrack ); - - SMESHDS_SubMesh* pSubMeshDS = theTrack->GetSubMeshDS(); - if ( !pSubMeshDS ) - return ExtrusionAlongTrack( theElements, theTrack->GetFather(), theN1, - theHasAngles, theAngles, theLinearVariation, - theHasRefPoint, theRefPoint, theMakeGroups ); - - 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; - } - - list fullList; - - const TopoDS_Shape& aS = theTrack->GetSubShape(); - // 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 ( SMESH_Algo::isDegenerated( 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() ); - 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() ); - 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 edge - 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; - } - - return makeExtrElements(theElements, fullList, theHasAngles, theAngles, theLinearVariation, - theHasRefPoint, theRefPoint, theMakeGroups); -} - - -//======================================================================= -//function : ExtrusionAlongTrack -//purpose : -//======================================================================= -SMESH_MeshEditor::Extrusion_Error -SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet theElements[2], - 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) -{ - ClearLastCreated(); - - int aNbE; - std::list aPrms; - TIDSortedElemSet::iterator itElem; - - gp_XYZ aGC; - TopoDS_Edge aTrackEdge; - TopoDS_Vertex aV1, aV2; - - SMDS_ElemIteratorPtr aItE; - SMDS_NodeIteratorPtr aItN; - SMDSAbs_ElementType aTypeE; + ASSERT( theTrackMesh ); + if ( ! theTrackIterator || !theTrackIterator->more() ) + return EXTR_NO_ELEMENTS; - TNodeOfNodeListMap mapNewNodes; + // 2. Get ordered nodes + SMESH_MeshAlgos::TElemGroupVector branchEdges; + SMESH_MeshAlgos::TNodeGroupVector branchNods; + SMESH_MeshAlgos::Get1DBranches( theTrackIterator, branchEdges, branchNods, theN1 ); + if ( branchEdges.empty() ) + return EXTR_PATH_NOT_EDGE; - // 1. Check data - aNbE = theElements[0].size() + theElements[1].size(); - // nothing to do - if ( !aNbE ) - return EXTR_NO_ELEMENTS; + if ( branchEdges.size() > 1 ) + return EXTR_BAD_PATH_SHAPE; - // 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; - } - - list fullList; - - const TopoDS_Shape& aS = theTrack->GetShapeToMesh(); - - if ( !theTrack->HasShapeToMesh() ) { - //Mesh without shape - const SMDS_MeshNode* currentNode = NULL; - const SMDS_MeshNode* prevNode = theN1; - std::vector aNodesList; - aNodesList.push_back(theN1); - int nbEdges = 0, conn=0; - const SMDS_MeshElement* prevElem = NULL; - const SMDS_MeshElement* currentElem = NULL; - int totalNbEdges = theTrack->NbEdges(); - SMDS_ElemIteratorPtr nIt; - - //check start node - if( !theTrack->GetMeshDS()->Contains(theN1) ) { - return EXTR_BAD_STARTING_NODE; - } - - conn = nbEdgeConnectivity(theN1); - if( conn != 1 ) - return EXTR_PATH_NOT_EDGE; - - aItE = theN1->GetInverseElementIterator(); - prevElem = aItE->next(); - currentElem = prevElem; - //Get all nodes - if(totalNbEdges == 1 ) { - nIt = currentElem->nodesIterator(); - currentNode = static_cast(nIt->next()); - if(currentNode == prevNode) - currentNode = static_cast(nIt->next()); - aNodesList.push_back(currentNode); - } else { - nIt = currentElem->nodesIterator(); - while( nIt->more() ) { - currentNode = static_cast(nIt->next()); - if(currentNode == prevNode) - currentNode = static_cast(nIt->next()); - aNodesList.push_back(currentNode); - - //case of the closed mesh - if(currentNode == theN1) { - nbEdges++; - break; - } + std::vector< const SMDS_MeshNode* >& pathNodes = branchNods[0]; + std::vector< const SMDS_MeshElement* >& pathEdges = branchEdges[0]; + if ( pathNodes[0] != theN1 && pathNodes[1] != theN1 ) + return EXTR_BAD_STARTING_NODE; - conn = nbEdgeConnectivity(currentNode); - if(conn > 2) { - return EXTR_PATH_NOT_EDGE; - }else if( conn == 1 && nbEdges > 0 ) { - //End of the path - nbEdges++; - break; - }else { - prevNode = currentNode; - aItE = currentNode->GetInverseElementIterator(); - currentElem = aItE->next(); - if( currentElem == prevElem) - currentElem = aItE->next(); - nIt = currentElem->nodesIterator(); - prevElem = currentElem; - nbEdges++; - } - } - } - - if(nbEdges != totalNbEdges) - return EXTR_PATH_NOT_EDGE; - - TopTools_SequenceOfShape Edges; - list< list > LLPPs; - int startNid = theN1->GetID(); - for ( size_t i = 1; i < aNodesList.size(); i++ ) - { - gp_Pnt p1 = SMESH_TNodeXYZ( aNodesList[i-1] ); - gp_Pnt p2 = SMESH_TNodeXYZ( aNodesList[i] ); - TopoDS_Edge e = BRepBuilderAPI_MakeEdge( p1, p2 ); - list LPP; - aPrms.clear(); - makeEdgePathPoints(aPrms, e, (aNodesList[i-1]->GetID()==startNid), LPP); - LLPPs.push_back(LPP); - if ( aNodesList[i-1]->GetID() == startNid ) startNid = aNodesList[i ]->GetID(); - else startNid = aNodesList[i-1]->GetID(); - } - - 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(); - SMESH_MeshEditor_PathPoint PP2; - fullList.pop_back(); - itLLPP++; - for(; itLLPP!=LLPPs.end(); itLLPP++) { - list currList = *itLLPP; - itPP = currList.begin(); - PP2 = currList.front(); - gp_Dir D1 = PP1.Tangent(); - gp_Dir D2 = PP2.Tangent(); - gp_Dir Dnew( 0.5 * ( D1.XYZ() + D2.XYZ() )); - PP1.SetTangent(Dnew); - fullList.push_back(PP1); - itPP++; - for(; itPP!=currList.end(); itPP++) { - fullList.push_back( *itPP ); - } - PP1 = fullList.back(); - fullList.pop_back(); - } - fullList.push_back(PP1); - - } // Sub-shape for the Pattern must be an Edge or Wire - else if ( aS.ShapeType() == TopAbs_EDGE ) - { - aTrackEdge = TopoDS::Edge( aS ); - // the Edge must not be degenerated - if ( SMESH_Algo::isDegenerated( aTrackEdge ) ) - return EXTR_BAD_PATH_SHAPE; - TopExp::Vertices( aTrackEdge, aV1, aV2 ); - const SMDS_MeshNode* aN1 = SMESH_Algo::VertexNode( aV1, pMeshDS ); - const SMDS_MeshNode* aN2 = SMESH_Algo::VertexNode( aV2, pMeshDS ); - // 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() ); - 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( SMESH_Algo::isDegenerated(E) ) continue; - SMESH_subMesh* SM = theTrack->GetSubMesh(E); - if(SM) { - LSM.push_back(SM); - Edges.Append(E); - } - } - list< list > LLPPs; - TopoDS_Vertex aVprev; - 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 ); - bool aN1isOK = false, aN2isOK = false; - if ( aVprev.IsNull() ) { - // if previous vertex is not yet defined, it means that we in the beginning of wire - // and we have to find initial vertex corresponding to starting node theN1 - const SMDS_MeshNode* aN1 = SMESH_Algo::VertexNode( aV1, pMeshDS ); - const SMDS_MeshNode* aN2 = SMESH_Algo::VertexNode( aV2, pMeshDS ); - // starting node must be aN1 or aN2 - aN1isOK = ( aN1 && aN1 == theN1 ); - aN2isOK = ( aN2 && aN2 == theN1 ); - } - else { - // we have specified ending vertex of the previous edge on the previous iteration - // and we have just to check that it corresponds to any vertex in current segment - aN1isOK = aVprev.IsSame( aV1 ); - aN2isOK = aVprev.IsSame( aV2 ); - } - if ( !aN1isOK && !aN2isOK ) 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() ); - double aT = pEPos->GetUParameter(); - aPrms.push_back( aT ); - } - list LPP; - //Extrusion_Error err = - makeEdgePathPoints(aPrms, aTrackEdge, aN1isOK, LPP); - LLPPs.push_back(LPP); - UsedNums.Add(k); - // update startN for search following edge - if ( aN1isOK ) aVprev = aV2; - else aVprev = aV1; - break; + if ( theTrackMesh->NbEdges( ORDER_QUADRATIC ) > 0 ) + { + // add medium nodes to pathNodes + std::vector< const SMDS_MeshNode* > pathNodes2; + std::vector< const SMDS_MeshElement* > pathEdges2; + pathNodes2.reserve( pathNodes.size() * 2 ); + pathEdges2.reserve( pathEdges.size() * 2 ); + for ( size_t i = 0; i < pathEdges.size(); ++i ) + { + pathNodes2.push_back( pathNodes[i] ); + pathEdges2.push_back( pathEdges[i] ); + if ( pathEdges[i]->IsQuadratic() ) + { + pathNodes2.push_back( pathEdges[i]->GetNode(2) ); + pathEdges2.push_back( pathEdges[i] ); } } - list< list >::iterator itLLPP = LLPPs.begin(); - list& firstList = *itLLPP; - fullList.splice( fullList.end(), firstList ); - - SMESH_MeshEditor_PathPoint PP1 = fullList.back(); - fullList.pop_back(); - itLLPP++; - for(; itLLPP!=LLPPs.end(); itLLPP++) { - list& currList = *itLLPP; - SMESH_MeshEditor_PathPoint PP2 = currList.front(); - gp_Dir D1 = PP1.Tangent(); - gp_Dir D2 = PP2.Tangent(); - gp_Dir Dnew( D1.XYZ() + D2.XYZ() ); - PP1.SetTangent(Dnew); - fullList.push_back(PP1); - fullList.splice( fullList.end(), currList, ++currList.begin(), currList.end() ); - PP1 = fullList.back(); - fullList.pop_back(); - } - // if wire not closed - fullList.push_back(PP1); - // else ??? - } - else { - return EXTR_BAD_PATH_SHAPE; + pathNodes2.push_back( pathNodes.back() ); + pathEdges.swap( pathEdges2 ); + pathNodes.swap( pathNodes2 ); } - return makeExtrElements(theElements, fullList, theHasAngles, theAngles, theLinearVariation, - theHasRefPoint, theRefPoint, theMakeGroups); -} + // 3. Get path data at pathNodes + std::vector< ExtrusParam::PathPoint > points( pathNodes.size() ); -//======================================================================= -//function : makeEdgePathPoints -//purpose : auxiliary 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( FirstIsStart ) { - if ( aT1 > aT2 ) { - aPrms.reverse(); - } - } - else { - if ( aT2 > aT1 ) { - aPrms.reverse(); - } - } - // 3. Path Points - SMESH_MeshEditor_PathPoint aPP; - 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( FirstIsStart ? aVec : -aVec ); - aPP.SetPnt( aP3D ); - aPP.SetTangent( aTgt ); - aPP.SetParameter( aT ); - LPP.push_back(aPP); - } - return EXTR_OK; -} + if ( theAngleVariation ) + linearAngleVariation( points.size()-1, theAngles ); + if ( theScaleVariation ) + linearScaleVariation( points.size()-1, theScales ); + theAngles.push_front( 0 ); // for the 1st point that is not transformed + std::list::iterator angle = theAngles.begin(); -//======================================================================= -//function : makeExtrElements -//purpose : auxiliary for ExtrusionAlongTrack -//======================================================================= -SMESH_MeshEditor::Extrusion_Error -SMESH_MeshEditor::makeExtrElements(TIDSortedElemSet theElemSets[2], - list& fullList, - const bool theHasAngles, - list& theAngles, - const bool theLinearVariation, - const bool theHasRefPoint, - const gp_Pnt& theRefPoint, - const bool theMakeGroups) -{ - const int aNbTP = fullList.size(); + SMESHDS_Mesh* pathMeshDS = theTrackMesh->GetMeshDS(); - // Angles - if( theHasAngles && !theAngles.empty() && theLinearVariation ) - linearAngleVariation(aNbTP-1, theAngles); + std::map< int, double > edgeID2OriFactor; // orientation of EDGEs + std::map< int, double >::iterator id2factor; + SMESH_MesherHelper pathHelper( *theTrackMesh ); + gp_Pnt p; gp_Vec tangent; + const double tol2 = gp::Resolution() * gp::Resolution(); - // fill vector of path points with angles - vector aPPs; - list::iterator itPP = fullList.begin(); - list::iterator itAngles = theAngles.begin(); - aPPs.push_back( *itPP++ ); - for( ; itPP != fullList.end(); itPP++) { - aPPs.push_back( *itPP ); - if ( theHasAngles && itAngles != theAngles.end() ) - aPPs.back().SetAngle( *itAngles++ ); - } + for ( size_t i = 0; i < pathNodes.size(); ++i ) + { + ExtrusParam::PathPoint & point = points[ i ]; - TNodeOfNodeListMap mapNewNodes; - TElemOfVecOfNnlmiMap mapElemNewNodes; - TTElemOfElemListMap newElemsMap; - TIDSortedElemSet::iterator itElem; - // source elements for each generated one - SMESH_SequenceOfElemPtr srcElems, srcNodes; + point.myPnt = SMESH_NodeXYZ( pathNodes[ i ]); - // 3. Center of rotation aV0 - gp_Pnt aV0 = theRefPoint; - if ( !theHasRefPoint ) - { - gp_XYZ aGC( 0.,0.,0. ); - TIDSortedElemSet newNodes; + if ( angle != theAngles.end() ) + point.myAngle = *angle++; - for ( int is2ndSet = 0; is2ndSet < 2; ++is2ndSet ) + tangent.SetCoord( 0,0,0 ); + const int shapeID = pathNodes[ i ]->GetShapeID(); + const TopoDS_Shape& shape = pathMeshDS->IndexToShape( shapeID ); + TopAbs_ShapeEnum shapeType = shape.IsNull() ? TopAbs_SHAPE : shape.ShapeType(); + switch ( shapeType ) { - TIDSortedElemSet& theElements = theElemSets[ is2ndSet ]; - itElem = theElements.begin(); - for ( ; itElem != theElements.end(); itElem++ ) + case TopAbs_EDGE: + { + TopoDS_Edge edge = TopoDS::Edge( shape ); + id2factor = edgeID2OriFactor.insert( std::make_pair( shapeID, 0 )).first; + if ( id2factor->second == 0 ) { - const SMDS_MeshElement* elem = *itElem; - SMDS_ElemIteratorPtr itN = elem->nodesIterator(); - while ( itN->more() ) { - const SMDS_MeshElement* node = itN->next(); - if ( newNodes.insert( node ).second ) - aGC += SMESH_TNodeXYZ( node ); - } + if ( i ) id2factor->second = getOriFactor( edge, pathNodes[i-1], pathNodes[i], pathHelper ); + else id2factor->second = getOriFactor( edge, pathNodes[i], pathNodes[i+1], pathHelper ); } + double u = pathHelper.GetNodeU( edge, pathNodes[i] ), u0, u1; + Handle(Geom_Curve) curve = BRep_Tool::Curve( edge, u0, u1 ); + curve->D1( u, p, tangent ); + tangent *= id2factor->second; + break; } - aGC /= newNodes.size(); - aV0.SetXYZ( aGC ); - } // if (!theHasRefPoint) { - - // 4. Processing the elements - SMESHDS_Mesh* aMesh = GetMeshDS(); - list emptyList; - - setElemsFirst( theElemSets ); - for ( int is2ndSet = 0; is2ndSet < 2; ++is2ndSet ) - { - TIDSortedElemSet& theElements = theElemSets[ is2ndSet ]; - for ( itElem = theElements.begin(); itElem != theElements.end(); itElem++ ) + case TopAbs_VERTEX: { - const SMDS_MeshElement* elem = *itElem; - - vector & newNodesItVec = mapElemNewNodes[ elem ]; - newNodesItVec.reserve( elem->NbNodes() ); - - // loop on elem nodes - int nodeIndex = -1; - SMDS_ElemIteratorPtr itN = elem->nodesIterator(); - while ( itN->more() ) + int nbEdges = 0; + PShapeIteratorPtr shapeIt = pathHelper.GetAncestors( shape, *theTrackMesh, TopAbs_EDGE ); + while ( const TopoDS_Shape* edgePtr = shapeIt->next() ) { - ++nodeIndex; - // check if a node has been already processed - const SMDS_MeshNode* node = cast2Node( itN->next() ); - TNodeOfNodeListMap::iterator nIt = mapNewNodes.insert( make_pair( node, emptyList )).first; - list& listNewNodes = nIt->second; - if ( listNewNodes.empty() ) + int edgeID = pathMeshDS->ShapeToIndex( *edgePtr ); + for ( int di = -1; di <= 0; ++di ) { - // make new nodes - 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 = SMESH_TNodeXYZ( node ); - - const SMESH_MeshEditor_PathPoint& aPP0 = aPPs[0]; - aP0x = aPP0.Pnt(); - aDT0x= aPP0.Tangent(); - - for ( int 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) + size_t j = i + di; + if ( j < pathEdges.size() && edgeID == pathEdges[ j ]->GetShapeID() ) + { + TopoDS_Edge edge = TopoDS::Edge( *edgePtr ); + id2factor = edgeID2OriFactor.insert( std::make_pair( edgeID, 0 )).first; + if ( id2factor->second == 0 ) { - 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 ); + if ( j < i ) + id2factor->second = getOriFactor( edge, pathNodes[i-1], pathNodes[i], pathHelper ); + else + id2factor->second = getOriFactor( edge, pathNodes[i], pathNodes[i+1], pathHelper ); } - - // make new node - if ( elem->IsQuadratic() && !elem->IsMediumNode(node) ) + double u = pathHelper.GetNodeU( edge, pathNodes[i] ), u0, u1; + Handle(Geom_Curve) curve = BRep_Tool::Curve( edge, u0, u1 ); + gp_Vec du; + curve->D1( u, p, du ); + double size2 = du.SquareMagnitude(); + if ( du.SquareMagnitude() > tol2 ) { - // create additional node - gp_XYZ midP = 0.5 * ( aPN1.XYZ() + aPN0.XYZ() ); - const SMDS_MeshNode* newNode = aMesh->AddNode( midP.X(), midP.Y(), midP.Z() ); - myLastCreatedNodes.push_back(newNode); - srcNodes.push_back( node ); - listNewNodes.push_back( newNode ); + tangent += du.Divided( Sqrt( size2 )) * id2factor->second; + nbEdges++; } - const SMDS_MeshNode* newNode = aMesh->AddNode( aPN1.X(), aPN1.Y(), aPN1.Z() ); - myLastCreatedNodes.push_back(newNode); - srcNodes.push_back( node ); - listNewNodes.push_back( newNode ); - - aPN0 = aPN1; - aP0x = aP1x; - aV0x = aV1x; - aDT0x = aDT1x; + break; } } - else if( elem->IsQuadratic() && !elem->IsMediumNode(node) ) + } + if ( nbEdges > 0 ) + break; + } + default: + { + for ( int di = -1; di <= 1; di += 2 ) + { + size_t j = i + di; + if ( j < pathNodes.size() ) { - // if current elem is quadratic and current node is not medium - // we have to check - may be it is needed to insert additional nodes - list< const SMDS_MeshNode* > & listNewNodes = nIt->second; - if ((int) listNewNodes.size() == aNbTP-1 ) - { - vector aNodes(2*(aNbTP-1)); - gp_XYZ P(node->X(), node->Y(), node->Z()); - list< const SMDS_MeshNode* >::iterator it = listNewNodes.begin(); - int i; - for(i=0; iX() + P.X() )/2.; - double y = ( N->Y() + P.Y() )/2.; - double z = ( N->Z() + P.Z() )/2.; - const SMDS_MeshNode* newN = aMesh->AddNode(x,y,z); - srcNodes.push_back( node ); - myLastCreatedNodes.push_back(newN); - aNodes[2*i] = newN; - aNodes[2*i+1] = N; - P = gp_XYZ(N->X(),N->Y(),N->Z()); - } - listNewNodes.clear(); - for(i=0; i<2*(aNbTP-1); i++) { - listNewNodes.push_back(aNodes[i]); - } - } + gp_Vec dir( point.myPnt, SMESH_NodeXYZ( pathNodes[ j ])); + double size2 = dir.SquareMagnitude(); + if ( size2 > tol2 ) + tangent += dir.Divided( Sqrt( size2 )) * di; } - - newNodesItVec.push_back( nIt ); } - - // make new elements - sweepElement( elem, newNodesItVec, newElemsMap[elem], aNbTP-1, srcElems ); } - } + } // switch ( shapeType ) + + if ( tangent.SquareMagnitude() < tol2 ) + return EXTR_CANT_GET_TANGENT; - makeWalls( mapNewNodes, newElemsMap, mapElemNewNodes, theElemSets[0], aNbTP-1, srcElems ); + point.myTgt = tangent; - if ( theMakeGroups ) - generateGroups( srcNodes, srcElems, "extruded"); + } // loop on pathNodes + + + ExtrusParam nodeMaker( points, theRefPoint, theScales, theMakeGroups ); + TTElemOfElemListMap newElemsMap; + + ExtrusionSweep( theElements, nodeMaker, newElemsMap ); return EXTR_OK; } - //======================================================================= //function : linearAngleVariation //purpose : spread values over nbSteps @@ -6494,6 +6103,33 @@ void SMESH_MeshEditor::linearAngleVariation(const int nbSteps, } } +//======================================================================= +//function : linearScaleVariation +//purpose : spread values over nbSteps +//======================================================================= + +void SMESH_MeshEditor::linearScaleVariation(const int theNbSteps, + std::list& theScales) +{ + int nbScales = theScales.size(); + std::vector myScales; + myScales.reserve( theNbSteps ); + std::list::const_iterator scale = theScales.begin(); + double prevScale = 1.0; + for ( int iSc = 1; scale != theScales.end(); ++scale, ++iSc ) + { + int iStep = int( iSc / double( nbScales ) * theNbSteps + 0.5 ); + int stDelta = Max( 1, iStep - myScales.size()); + double scDelta = ( *scale - prevScale ) / stDelta; + for ( int iStep = 0; iStep < stDelta; ++iStep ) + { + myScales.push_back( prevScale + scDelta ); + prevScale = myScales.back(); + } + prevScale = *scale; + } + theScales.assign( myScales.begin(), myScales.end() ); +} //================================================================================ /*! @@ -6660,8 +6296,8 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems, if ( geomType == SMDSGeom_POLYHEDRA ) // ------------------ polyhedral volume { - const SMDS_VtkVolume* aPolyedre = dynamic_cast( elem ); - if (!aPolyedre) + const SMDS_MeshVolume* aPolyedre = SMDS_Mesh::DownCast< SMDS_MeshVolume >( elem ); + if ( !aPolyedre ) continue; nodes.clear(); bool allTransformed = true; @@ -6736,7 +6372,7 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems, * \param [in] theValue - offset value * \param [out] theTgtMesh - a mesh to add offset elements to * \param [in] theMakeGroups - to generate groups - * \return PGroupIDs - IDs of created groups + * \return PGroupIDs - IDs of created groups. NULL means failure */ //================================================================================ @@ -6744,6 +6380,7 @@ SMESH_MeshEditor::PGroupIDs SMESH_MeshEditor::Offset( TIDSortedElemSet & theElem const double theValue, SMESH_Mesh* theTgtMesh, const bool theMakeGroups, + const bool theCopyElements, const bool theFixSelfIntersection) { SMESHDS_Mesh* meshDS = GetMeshDS(); @@ -6754,15 +6391,27 @@ SMESH_MeshEditor::PGroupIDs SMESH_MeshEditor::Offset( TIDSortedElemSet & theElem if ( theElements.empty() ) eIt = meshDS->elementsIterator( SMDSAbs_Face ); else eIt = SMESHUtils::elemSetIterator( theElements ); - SMESH_MeshAlgos::TEPairVec new2OldFaces; - SMESH_MeshAlgos::TNPairVec new2OldNodes; + SMESH_MeshAlgos::TElemIntPairVec new2OldFaces; + SMESH_MeshAlgos::TNodeIntPairVec new2OldNodes; std::unique_ptr< SMDS_Mesh > offsetMesh ( SMESH_MeshAlgos::MakeOffset( eIt, *meshDS, theValue, theFixSelfIntersection, new2OldFaces, new2OldNodes )); + if ( offsetMesh->NbElements() == 0 ) + return PGroupIDs(); // MakeOffset() failed + - offsetMesh->Modified(); - offsetMesh->CompactMesh(); // make IDs start from 1 + if ( theTgtMesh == myMesh && !theCopyElements ) + { + // clear the source elements + if ( theElements.empty() ) eIt = meshDS->elementsIterator( SMDSAbs_Face ); + else eIt = SMESHUtils::elemSetIterator( theElements ); + while ( eIt->more() ) + meshDS->RemoveFreeElement( eIt->next(), 0 ); + } + + // offsetMesh->Modified(); + // offsetMesh->CompactMesh(); // make IDs start from 1 // source elements for each generated one SMESH_SequenceOfElemPtr srcElems, srcNodes; @@ -6779,12 +6428,14 @@ SMESH_MeshEditor::PGroupIDs SMESH_MeshEditor::Offset( TIDSortedElemSet & theElem for ( size_t i = 0; i < new2OldNodes.size(); ++i ) if ( const SMDS_MeshNode* n = new2OldNodes[ i ].first ) { +#ifndef _DEBUG_ if ( n->NbInverseElements() > 0 ) +#endif { const SMDS_MeshNode* n2 = tgtMeshDS->AddNodeWithID( n->X(), n->Y(), n->Z(), idShift + n->GetID() ); myLastCreatedNodes.push_back( n2 ); - srcNodes.push_back( new2OldNodes[ i ].second ); + srcNodes.push_back( meshDS->FindNode( new2OldNodes[ i ].second )); } } @@ -6800,7 +6451,7 @@ SMESH_MeshEditor::PGroupIDs SMESH_MeshEditor::Offset( TIDSortedElemSet & theElem elemType.myNodes.push_back( tgtMeshDS->FindNode( idShift + n2->GetID() )); } tgtEditor.AddElement( elemType.myNodes, elemType ); - srcElems.push_back( new2OldFaces[ i ].second ); + srcElems.push_back( meshDS->FindElement( new2OldFaces[ i ].second )); } myLastCreatedElems.swap( tgtEditor.myLastCreatedElems ); @@ -6808,6 +6459,8 @@ SMESH_MeshEditor::PGroupIDs SMESH_MeshEditor::Offset( TIDSortedElemSet & theElem PGroupIDs newGroupIDs; if ( theMakeGroups ) newGroupIDs = generateGroups( srcNodes, srcElems, "offset", theTgtMesh, false ); + else + newGroupIDs.reset( new std::list< int > ); return newGroupIDs; } @@ -7035,7 +6688,7 @@ void SMESH_MeshEditor::FindCoincidentNodes (TIDSortedNodeSet & theNodes, if ( theNodes.empty() ) // get all nodes in the mesh { TIDSortedNodeSet* nodes[2] = { &corners, &medium }; - SMDS_NodeIteratorPtr nIt = GetMeshDS()->nodesIterator(/*idInceasingOrder=*/true); + SMDS_NodeIteratorPtr nIt = GetMeshDS()->nodesIterator(); if ( theSeparateCornersAndMedium ) while ( nIt->more() ) { @@ -7171,8 +6824,11 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes, const SMDS_MeshNode* nToKeep = nnIt->second; TNodeNodeMap::iterator nnIt_i = nodeNodeMap.find( nToKeep ); while ( nnIt_i != nodeNodeMap.end() && nnIt_i->second != nnIt->second ) + { nToKeep = nnIt_i->second; - nnIt->second = nToKeep; + nnIt->second = nToKeep; + nnIt_i = nodeNodeMap.find( nToKeep ); + } } if ( theAvoidMakingHoles ) @@ -7223,7 +6879,7 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes, AddToSameGroups( nToKeep, nToRemove, mesh ); // set _alwaysComputed to a sub-mesh of VERTEX to enable further mesh computing // w/o creating node in place of merged ones. - const SMDS_PositionPtr& pos = nToRemove->GetPosition(); + SMDS_PositionPtr pos = nToRemove->GetPosition(); if ( pos && pos->GetTypeOfPosition() == SMDS_TOP_VERTEX ) if ( SMESH_subMesh* sm = myMesh->GetSubMeshContaining( nToRemove->getshapeId() )) sm->SetIsAlwaysComputed( true ); @@ -7411,7 +7067,7 @@ bool SMESH_MeshEditor::applyMerge( const SMDS_MeshElement* elem, if ( nbUniqueNodes >= 4 ) { // each face has to be analyzed in order to check volume validity - if ( const SMDS_VtkVolume* aPolyedre = dynamic_cast( elem )) + if ( const SMDS_MeshVolume* aPolyedre = SMDS_Mesh::DownCast< SMDS_MeshVolume >( elem )) { int nbFaces = aPolyedre->NbFaces(); @@ -7729,26 +7385,55 @@ bool SMESH_MeshEditor::applyMerge( const SMDS_MeshElement* elem, // ======================================================== -// class : SortableElement -// purpose : allow sorting elements basing on their nodes +// class : ComparableElement +// purpose : allow comparing elements basing on their nodes // ======================================================== -class SortableElement : public set + +class ComparableElement : public boost::container::flat_set< int > { + typedef boost::container::flat_set< int > int_set; + + const SMDS_MeshElement* myElem; + int mySumID; + mutable int myGroupID; + public: - SortableElement( const SMDS_MeshElement* theElem ) + ComparableElement( const SMDS_MeshElement* theElem ): + myElem ( theElem ), mySumID( 0 ), myGroupID( -1 ) { - myElem = theElem; - SMDS_ElemIteratorPtr nodeIt = theElem->nodesIterator(); - while ( nodeIt->more() ) - this->insert( nodeIt->next() ); + this->reserve( theElem->NbNodes() ); + for ( SMDS_ElemIteratorPtr nodeIt = theElem->nodesIterator(); nodeIt->more(); ) + { + int id = nodeIt->next()->GetID(); + mySumID += id; + this->insert( id ); + } } - const SMDS_MeshElement* Get() const - { return myElem; } + const SMDS_MeshElement* GetElem() const { return myElem; } + + int& GroupID() const { return myGroupID; } + //int& GroupID() const { return const_cast< int& >( myGroupID ); } + + ComparableElement( const ComparableElement& theSource ) // move copy + { + ComparableElement& src = const_cast< ComparableElement& >( theSource ); + (int_set&) (*this ) = boost::move( src ); + myElem = src.myElem; + mySumID = src.mySumID; + myGroupID = src.myGroupID; + } + + static int HashCode(const ComparableElement& se, int limit ) + { + return ::HashCode( se.mySumID, limit ); + } + static Standard_Boolean IsEqual(const ComparableElement& se1, const ComparableElement& se2 ) + { + return ( se1 == se2 ); + } -private: - mutable const SMDS_MeshElement* myElem; }; //======================================================================= @@ -7757,48 +7442,47 @@ private: // Search among theElements or in the whole mesh if theElements is empty //======================================================================= -void SMESH_MeshEditor::FindEqualElements(TIDSortedElemSet & theElements, - TListOfListOfElementsID & theGroupsOfElementsID) +void SMESH_MeshEditor::FindEqualElements( TIDSortedElemSet & theElements, + TListOfListOfElementsID & theGroupsOfElementsID ) { ClearLastCreated(); - typedef map< SortableElement, int > TMapOfNodeSet; - typedef list TGroupOfElems; - SMDS_ElemIteratorPtr elemIt; if ( theElements.empty() ) elemIt = GetMeshDS()->elementsIterator(); else elemIt = SMESHUtils::elemSetIterator( theElements ); - vector< TGroupOfElems > arrayOfGroups; - TGroupOfElems groupOfElems; - TMapOfNodeSet mapOfNodeSet; + typedef NCollection_Map< ComparableElement, ComparableElement > TMapOfElements; + typedef std::list TGroupOfElems; + TMapOfElements mapOfElements; + std::vector< TGroupOfElems > arrayOfGroups; + TGroupOfElems groupOfElems; - for ( int iGroup = 0; elemIt->more(); ) + while ( elemIt->more() ) { const SMDS_MeshElement* curElem = elemIt->next(); - SortableElement SE(curElem); + ComparableElement compElem = curElem; // check uniqueness - pair< TMapOfNodeSet::iterator, bool> pp = mapOfNodeSet.insert(make_pair(SE, iGroup)); - if ( !pp.second ) { // one more coincident elem - TMapOfNodeSet::iterator& itSE = pp.first; - int iG = itSE->second; + const ComparableElement& elemInSet = mapOfElements.Added( compElem ); + if ( elemInSet.GetElem() != curElem ) // coincident elem + { + int& iG = elemInSet.GroupID(); + if ( iG < 0 ) + { + iG = arrayOfGroups.size(); + arrayOfGroups.push_back( groupOfElems ); + arrayOfGroups[ iG ].push_back( elemInSet.GetElem()->GetID() ); + } arrayOfGroups[ iG ].push_back( curElem->GetID() ); } - else { - arrayOfGroups.push_back( groupOfElems ); - arrayOfGroups.back().push_back( curElem->GetID() ); - iGroup++; - } } groupOfElems.clear(); - vector< TGroupOfElems >::iterator groupIt = arrayOfGroups.begin(); + std::vector< TGroupOfElems >::iterator groupIt = arrayOfGroups.begin(); for ( ; groupIt != arrayOfGroups.end(); ++groupIt ) { if ( groupIt->size() > 1 ) { - //groupOfElems.sort(); -- theElements is sorted already - theGroupsOfElementsID.push_back( groupOfElems ); - theGroupsOfElementsID.back().splice( theGroupsOfElementsID.back().end(), *groupIt ); + //groupOfElems.sort(); -- theElements are sorted already + theGroupsOfElementsID.emplace_back( *groupIt ); } } } @@ -7849,8 +7533,8 @@ void SMESH_MeshEditor::MergeEqualElements() TIDSortedElemSet aMeshElements; /* empty input == to merge equal elements in the whole mesh */ TListOfListOfElementsID aGroupsOfElementsID; - FindEqualElements(aMeshElements, aGroupsOfElementsID); - MergeElements(aGroupsOfElementsID); + FindEqualElements( aMeshElements, aGroupsOfElementsID ); + MergeElements( aGroupsOfElementsID ); } //======================================================================= @@ -7911,48 +7595,37 @@ bool SMESH_MeshEditor::FindFreeBorder (const SMDS_MeshNode* theFirst theNodes.push_back( theSecondNode ); const SMDS_MeshNode *nIgnore = theFirstNode, *nStart = theSecondNode; - TIDSortedElemSet foundElems; + //TIDSortedElemSet foundElems; bool needTheLast = ( theLastNode != 0 ); + vector nodes; + while ( nStart != theLastNode ) { if ( nStart == theFirstNode ) return !needTheLast; - // find all free border faces sharing form nStart + // find all free border faces sharing nStart list< const SMDS_MeshElement* > curElemList; list< const SMDS_MeshNode* > nStartList; SMDS_ElemIteratorPtr invElemIt = nStart->GetInverseElementIterator(SMDSAbs_Face); while ( invElemIt->more() ) { const SMDS_MeshElement* e = invElemIt->next(); - if ( e == curElem || foundElems.insert( e ).second ) { + //if ( e == curElem || foundElems.insert( e ).second ) // e can encounter twice in border + { // get nodes - int iNode = 0, nbNodes = e->NbNodes(); - vector nodes(nbNodes+1); - - if ( e->IsQuadratic() ) { - const SMDS_VtkFace* F = - dynamic_cast(e); - if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace")); - // use special nodes iterator - SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator(); - while( anIter->more() ) { - nodes[ iNode++ ] = cast2Node(anIter->next()); - } - } - else { - SMDS_ElemIteratorPtr nIt = e->nodesIterator(); - while ( nIt->more() ) - nodes[ iNode++ ] = static_cast( nIt->next() ); - } - nodes[ iNode ] = nodes[ 0 ]; + nodes.assign( SMDS_MeshElement::iterator( e->interlacedNodesIterator() ), + SMDS_MeshElement::iterator() ); + nodes.push_back( nodes[ 0 ]); + // check 2 links + int iNode = 0, nbNodes = nodes.size() - 1; for ( iNode = 0; iNode < nbNodes; iNode++ ) - if (((nodes[ iNode ] == nStart && nodes[ iNode + 1] != nIgnore ) || - (nodes[ iNode + 1] == nStart && nodes[ iNode ] != nIgnore )) && - ControlFreeBorder( &nodes[ iNode ], e->GetID() )) + if ((( nodes[ iNode ] == nStart && nodes[ iNode + 1] != nIgnore ) || + ( nodes[ iNode + 1] == nStart && nodes[ iNode ] != nIgnore )) && + ( ControlFreeBorder( &nodes[ iNode ], e->GetID() ))) { - nStartList.push_back( nodes[ iNode + ( nodes[ iNode ] == nStart ? 1 : 0 )]); + nStartList.push_back( nodes[ iNode + ( nodes[ iNode ] == nStart )]); curElemList.push_back( e ); } } @@ -8004,7 +7677,7 @@ bool SMESH_MeshEditor::FindFreeBorder (const SMDS_MeshNode* theFirst else if ( !contNodes[0].empty() && !contNodes[1].empty() ) { // choice: clear a worse one int iLongest = ( contNodes[0].size() < contNodes[1].size() ? 1 : 0 ); - int iWorse = ( needTheLast ? 1 - iLongest : iLongest ); + int iWorse = ( needTheLast ? 1 - iLongest : iLongest ); contNodes[ iWorse ].clear(); contFaces[ iWorse ].clear(); } @@ -8015,13 +7688,11 @@ bool SMESH_MeshEditor::FindFreeBorder (const SMDS_MeshNode* theFirst // push_back the best free border cNL = & contNodes[ contNodes[0].empty() ? 1 : 0 ]; cFL = & contFaces[ contFaces[0].empty() ? 1 : 0 ]; - theNodes.pop_back(); // remove nIgnore + //theNodes.pop_back(); // remove nIgnore theNodes.pop_back(); // remove nStart - theFaces.pop_back(); // remove curElem - list< const SMDS_MeshNode* >::iterator nIt = cNL->begin(); - list< const SMDS_MeshElement* >::iterator fIt = cFL->begin(); - for ( ; nIt != cNL->end(); nIt++ ) theNodes.push_back( *nIt ); - for ( ; fIt != cFL->end(); fIt++ ) theFaces.push_back( *fIt ); + //theFaces.pop_back(); // remove curElem + theNodes.splice( theNodes.end(), *cNL ); + theFaces.splice( theFaces.end(), *cFL ); return true; } // several continuations found @@ -8202,27 +7873,13 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode, const SMDS_MeshNode** nodes = isVolume ? volume.GetNodes() : & faceNodes[0]; if ( isVolume ) // --volume hasVolumes = true; - else if ( elem->GetType()==SMDSAbs_Face ) { // --face + else if ( elem->GetType() == SMDSAbs_Face ) { // --face // retrieve all face nodes and find iPrevNode - an index of the prevSideNode - if(elem->IsQuadratic()) { - const SMDS_VtkFace* F = - dynamic_cast(elem); - if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace")); - // use special nodes iterator - SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator(); - while( anIter->more() ) { - nodes[ iNode ] = cast2Node(anIter->next()); - if ( nodes[ iNode++ ] == prevSideNode ) - iPrevNode = iNode - 1; - } - } - else { - SMDS_ElemIteratorPtr nIt = elem->nodesIterator(); - while ( nIt->more() ) { - nodes[ iNode ] = cast2Node( nIt->next() ); - if ( nodes[ iNode++ ] == prevSideNode ) - iPrevNode = iNode - 1; - } + SMDS_NodeIteratorPtr nIt = elem->interlacedNodesIterator(); + while ( nIt->more() ) { + nodes[ iNode ] = cast2Node( nIt->next() ); + if ( nodes[ iNode++ ] == prevSideNode ) + iPrevNode = iNode - 1; } // there are 2 links to check nbNodes = 2; @@ -8376,6 +8033,10 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode, nIt[0] = nSide[0].begin(); eIt[0] = eSide[0].begin(); nIt[1] = nSide[1].begin(); eIt[1] = eSide[1].begin(); + // element can be split while iterating on border if it has two edges in the border + std::map< const SMDS_MeshElement* , const SMDS_MeshElement* > elemReplaceMap; + std::map< const SMDS_MeshElement* , const SMDS_MeshElement* >::iterator elemReplaceMapIt; + TElemOfNodeListMap insertMap; TElemOfNodeListMap::iterator insertMapIt; // insertMap is @@ -8423,12 +8084,15 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode, const SMDS_MeshNode* nIns = *nIt [ 1 - intoBord ]; if ( intoBord == 1 ) { // move node of the border to be on a link of elem of the side - gp_XYZ p1 (n1->X(), n1->Y(), n1->Z()); - gp_XYZ p2 (n2->X(), n2->Y(), n2->Z()); + SMESH_NodeXYZ p1( n1 ), p2( n2 ); double ratio = du / ( param[ 1 ][ i[1] ] - param[ 1 ][ i[1]-1 ]); gp_XYZ p = p2 * ( 1 - ratio ) + p1 * ratio; GetMeshDS()->MoveNode( nIns, p.X(), p.Y(), p.Z() ); } + elemReplaceMapIt = elemReplaceMap.find( elem ); + if ( elemReplaceMapIt != elemReplaceMap.end() ) + elem = elemReplaceMapIt->second; + insertMapIt = insertMap.find( elem ); bool notFound = ( insertMapIt == insertMap.end() ); bool otherLink = ( !notFound && (*insertMapIt).second.front() != n1 ); @@ -8451,8 +8115,10 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode, UpdateVolumes(n12, n22, nodeList); } // 3. find an element appeared on n1 and n2 after the insertion - insertMap.erase( elem ); - elem = findAdjacentFace( n1, n2, 0 ); + insertMap.erase( insertMapIt ); + const SMDS_MeshElement* elem2 = findAdjacentFace( n1, n2, 0 ); + elemReplaceMap.insert( std::make_pair( elem, elem2 )); + elem = elem2; } if ( notFound || otherLink ) { // add element and nodes of the side into the insertMap @@ -8485,6 +8151,7 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode, { const SMDS_MeshElement* elem = (*insertMapIt).first; list & nodeList = (*insertMapIt).second; + if ( nodeList.size() < 3 ) continue; const SMDS_MeshNode* n1 = nodeList.front(); nodeList.pop_front(); const SMDS_MeshNode* n2 = nodeList.front(); nodeList.pop_front(); @@ -8528,6 +8195,7 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode, for ( ; groupIt != nodeGroupsToMerge.end(); groupIt++ ) { const list& nodes = *groupIt; + if ( nodes.front()->IsNull() ) continue; SMDS_ElemIteratorPtr segIt = nodes.front()->GetInverseElementIterator( SMDSAbs_Edge ); while ( segIt->more() ) segments.insert( segIt->next() ); @@ -8682,48 +8350,21 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement* theElemen // add nodes of face up to first node of link bool isFLN = false; - - if ( theFace->IsQuadratic() ) { - const SMDS_VtkFace* F = dynamic_cast(theFace); - if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace")); - // use special nodes iterator - SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator(); - while( anIter->more() && !isFLN ) { - const SMDS_MeshNode* n = cast2Node(anIter->next()); - poly_nodes[iNode++] = n; - if (n == nodes[il1]) { - isFLN = true; - } - } - // add nodes to insert - list::iterator nIt = aNodesToInsert.begin(); - for (; nIt != aNodesToInsert.end(); nIt++) { - poly_nodes[iNode++] = *nIt; - } - // add nodes of face starting from last node of link - while ( anIter->more() ) { - poly_nodes[iNode++] = cast2Node(anIter->next()); - } + SMDS_NodeIteratorPtr nodeIt = theFace->interlacedNodesIterator(); + while ( nodeIt->more() && !isFLN ) { + const SMDS_MeshNode* n = nodeIt->next(); + poly_nodes[iNode++] = n; + isFLN = ( n == nodes[il1] ); } - else { - SMDS_ElemIteratorPtr nodeIt = theFace->nodesIterator(); - while ( nodeIt->more() && !isFLN ) { - const SMDS_MeshNode* n = static_cast( nodeIt->next() ); - poly_nodes[iNode++] = n; - if (n == nodes[il1]) { - isFLN = true; - } - } - // add nodes to insert - list::iterator nIt = aNodesToInsert.begin(); - for (; nIt != aNodesToInsert.end(); nIt++) { - poly_nodes[iNode++] = *nIt; - } - // add nodes of face starting from last node of link - while ( nodeIt->more() ) { - const SMDS_MeshNode* n = static_cast( nodeIt->next() ); - poly_nodes[iNode++] = n; - } + // add nodes to insert + list::iterator nIt = aNodesToInsert.begin(); + for (; nIt != aNodesToInsert.end(); nIt++) { + poly_nodes[iNode++] = *nIt; + } + // add nodes of face starting from last node of link + while ( nodeIt->more() ) { + const SMDS_MeshNode* n = static_cast( nodeIt->next() ); + poly_nodes[iNode++] = n; } // make a new face @@ -9065,7 +8706,7 @@ int SMESH_MeshEditor::convertElemToQuadratic(SMESHDS_SubMesh * theSm, const int nbNodes = elem->NbCornerNodes(); nodes.assign(elem->begin_nodes(), elem->end_nodes()); if ( aGeomType == SMDSEntity_Polyhedra ) - nbNodeInFaces = static_cast( elem )->GetQuantities(); + nbNodeInFaces = static_cast( elem )->GetQuantities(); else if ( aGeomType == SMDSEntity_Hexagonal_Prism ) volumeToPolyhedron( elem, nodes, nbNodeInFaces ); @@ -9286,7 +8927,7 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d, const bool theT const int id = volume->GetID(); vector nodes (volume->begin_nodes(), volume->end_nodes()); if ( type == SMDSEntity_Polyhedra ) - nbNodeInFaces = static_cast(volume)->GetQuantities(); + nbNodeInFaces = static_cast(volume)->GetQuantities(); else if ( type == SMDSEntity_Hexagonal_Prism ) volumeToPolyhedron( volume, nodes, nbNodeInFaces ); @@ -10048,20 +9689,8 @@ SMESH_MeshEditor::SewSideElements (TIDSortedElemSet& theSide1, //cout << " F " << face[ iSide]->GetID() <erase( face[ iSide ]); // put face nodes to fnodes - if ( face[ iSide ]->IsQuadratic() ) - { - // use interlaced nodes iterator - const SMDS_VtkFace* F = dynamic_cast( face[ iSide ]); - if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace")); - SMDS_ElemIteratorPtr nIter = F->interlacedNodesElemIterator(); - while ( nIter->more() ) - fnodes[ iSide ].push_back( cast2Node( nIter->next() )); - } - else - { - fnodes[ iSide ].assign( face[ iSide ]->begin_nodes(), - face[ iSide ]->end_nodes() ); - } + SMDS_MeshElement::iterator nIt( face[ iSide ]->interlacedNodesIterator() ), nEnd; + fnodes[ iSide ].assign( nIt, nEnd ); fnodes[ iSide ].push_back( fnodes[ iSide ].front()); } } @@ -10957,13 +10586,13 @@ void SMESH_MeshEditor::DoubleElements( const TIDSortedElemSet& theElements ) if ( mesh->GetMeshInfo().NbElements( types[i] )) { type = types[i]; + elemIt = mesh->elementsIterator( type ); break; } - elemIt = mesh->elementsIterator( type ); } else { - type = (*theElements.begin())->GetType(); + //type = (*theElements.begin())->GetType(); elemIt = SMESHUtils::elemSetIterator( theElements ); } @@ -10978,7 +10607,8 @@ void SMESH_MeshEditor::DoubleElements( const TIDSortedElemSet& theElements ) while ( elemIt->more() ) { const SMDS_MeshElement* elem = elemIt->next(); - if ( elem->GetType() != type || elem->isMarked() ) + if (( type != SMDSAbs_All && elem->GetType() != type ) || + ( elem->isMarked() )) continue; elemType.Init( elem, /*basicOnly=*/false ); @@ -11178,8 +10808,7 @@ namespace { const double theTol) { gp_XYZ centerXYZ (0, 0, 0); - SMDS_ElemIteratorPtr aNodeItr = theElem->nodesIterator(); - while ( aNodeItr->more() ) + for ( SMDS_ElemIteratorPtr aNodeItr = theElem->nodesIterator(); aNodeItr->more(); ) centerXYZ += SMESH_NodeXYZ( aNodeItr->next() ); gp_Pnt aPnt = centerXYZ / theElem->NbNodes(); @@ -11252,8 +10881,8 @@ bool SMESH_MeshEditor::AffectedElemGroupsInRegion( const TIDSortedElemSet& theEl else { const double aTol = Precision::Confusion(); - auto_ptr< BRepClass3d_SolidClassifier> bsc3d; - auto_ptr<_FaceClassifier> aFaceClassifier; + std::unique_ptr< BRepClass3d_SolidClassifier> bsc3d; + std::unique_ptr<_FaceClassifier> aFaceClassifier; if ( theShape.ShapeType() == TopAbs_SOLID ) { bsc3d.reset( new BRepClass3d_SolidClassifier(theShape));; @@ -11404,7 +11033,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vectormyMesh->GetMeshDS(); meshDS->BuildDownWardConnectivity(true); CHRONO(50); - SMDS_UnstructuredGrid *grid = meshDS->getGrid(); + SMDS_UnstructuredGrid *grid = meshDS->GetGrid(); // --- build the list of faces shared by 2 domains (group of elements), with their domain and volume indexes // build the list of cells with only a node or an edge on the border, with their domain and volume indexes @@ -11470,7 +11099,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vectorgetVtkId(); + int vtkId = anElem->GetVtkID(); //MESSAGE(" vtkId " << vtkId << " smdsId " << anElem->GetID()); int neighborsVtkIds[NBMAXNEIGHBORS]; int downIds[NBMAXNEIGHBORS]; @@ -11478,7 +11107,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vectorGetNeighbors(neighborsVtkIds, downIds, downTypes, vtkId); for (int n = 0; n < nbNeighbors; n++) { - int smdsId = meshDS->fromVtkToSmds(neighborsVtkIds[n]); + int smdsId = meshDS->FromVtkToSmds(neighborsVtkIds[n]); const SMDS_MeshElement* elem = meshDS->FindElement(smdsId); if (elem && ! domain.count(elem)) // neighbor is in another domain : face is shared { @@ -11541,7 +11170,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vectorFindElement(GetMeshDS()->fromVtkToSmds(vtkId)); + const SMDS_MeshElement* anElem = GetMeshDS()->FindElement(GetMeshDS()->FromVtkToSmds(vtkId)); if (!domain.count(anElem)) continue; int vtkType = grid->GetCellType(vtkId); @@ -11625,7 +11254,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vectorGetPoint(oldId); SMDS_MeshNode *newNode = meshDS->AddNode(coords[0], coords[1], coords[2]); copyPosition( meshDS->FindNodeVtk( oldId ), newNode ); - int newId = newNode->getVtkId(); + int newId = newNode->GetVtkID(); nodeDomains[oldId][idom] = newId; // cloned node for other domains //MESSAGE("-+-+-c oldNode " << oldId << " domain " << idomain << " newNode " << newId << " domain " << idom << " size=" < domvol; // domain --> a volume with the edge + map domvol; // domain --> a volume with the edge map angleDom; // oriented angles between planes defined by edge and volume centers int nbvol = grid->GetParentVolumes(vtkVolIds, downEdgeIds[ie], edgeType[ie]); for ( size_t id = 0; id < doms.size(); id++ ) @@ -11707,26 +11336,31 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vectorfromVtkToSmds(vtkVolIds[ivol]); - SMDS_MeshElement* elem = (SMDS_MeshElement*)meshDS->FindElement(smdsId); + int smdsId = meshDS->FromVtkToSmds(vtkVolIds[ivol]); + const SMDS_MeshElement* elem = meshDS->FindElement(smdsId); if (domain.count(elem)) { - SMDS_VtkVolume* svol = dynamic_cast(elem); - domvol[idom] = svol; + const SMDS_MeshVolume* svol = SMDS_Mesh::DownCast(elem); + domvol[idom] = (SMDS_MeshVolume*) svol; //MESSAGE(" domain " << idom << " volume " << elem->GetID()); - double values[3]; + double values[3] = { 0,0,0 }; vtkIdType npts = 0; vtkIdType* pts = 0; grid->GetCellPoints(vtkVolIds[ivol], npts, pts); - SMDS_VtkVolume::gravityCenter(grid, pts, npts, values); - if (id ==0) + for ( vtkIdType i = 0; i < npts; ++i ) + { + double *coords = grid->GetPoint( pts[i] ); + for ( int j = 0; j < 3; ++j ) + values[j] += coords[j] / npts; + } + if ( id == 0 ) { - gref.SetXYZ(gp_XYZ(values[0], values[1], values[2])); + gref.SetCoord( values[0], values[1], values[2] ); angleDom[idom] = 0; } else { - gp_Pnt g(values[0], values[1], values[2]); + gp_Pnt g( values[0], values[1], values[2] ); angleDom[idom] = OrientedAngle(p0, p1, gref, g); // -pimyMesh->AddGroup(SMDSAbs_Face, joints2DName.c_str(), idg); + mapOfJunctionGroups[joints2DName] = this->myMesh->AddGroup(SMDSAbs_Face, joints2DName.c_str()); SMESHDS_Group *joints2DGrp = dynamic_cast(mapOfJunctionGroups[joints2DName]->GetGroupDS()); string joints3DName = "joints3D"; - mapOfJunctionGroups[joints3DName] = this->myMesh->AddGroup(SMDSAbs_Volume, joints3DName.c_str(), idg); + mapOfJunctionGroups[joints3DName] = this->myMesh->AddGroup(SMDSAbs_Volume, joints3DName.c_str()); SMESHDS_Group *joints3DGrp = dynamic_cast(mapOfJunctionGroups[joints3DName]->GetGroupDS()); itface = faceDomains.begin(); @@ -11801,7 +11434,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vectormyMesh->AddGroup(vol->GetType(), namegrp.c_str(), idg); + mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(vol->GetType(), namegrp.c_str()); SMESHDS_Group *sgrp = dynamic_cast(mapOfJunctionGroups[namegrp]->GetGroupDS()); if (sgrp) sgrp->Add(vol->GetID()); @@ -11834,10 +11467,9 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vectormyMesh->AddGroup(SMDSAbs_Face, namegrp.c_str(), idg); + mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Face, namegrp.c_str()); SMESHDS_Group *sgrp = dynamic_cast(mapOfJunctionGroups[namegrp]->GetGroupDS()); if (sgrp) sgrp->Add(face->GetID()); @@ -11863,10 +11495,9 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vectorGetMeshDS()->AddVolumeFromVtkIds(orderedNodes); - int idg; string namegrp = "jointsMultiples"; if (!mapOfJunctionGroups.count(namegrp)) - mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Volume, namegrp.c_str(), idg); + mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Volume, namegrp.c_str()); SMESHDS_Group *sgrp = dynamic_cast(mapOfJunctionGroups[namegrp]->GetGroupDS()); if (sgrp) sgrp->Add(vol->GetID()); @@ -11915,7 +11546,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vectorGetMeshDS()->fromVtkToSmds(vtkId) << " domain " << idomain + //MESSAGE("affect cell " << this->GetMeshDS()->FromVtkToSmds(vtkId) << " domain " << idomain // << " type " << vtkType << " downId " << downId); } } @@ -11947,7 +11578,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vectorfirst; int vtkVolId = itdom->second; - //MESSAGE("modify nodes of cell " << this->GetMeshDS()->fromVtkToSmds(vtkVolId) << " domain " << idom); + //MESSAGE("modify nodes of cell " << this->GetMeshDS()->FromVtkToSmds(vtkVolId) << " domain " << idom); localClonedNodeIds.clear(); for (itn = oldNodes.begin(); itn != oldNodes.end(); ++itn) { @@ -12014,8 +11645,7 @@ bool SMESH_MeshEditor::CreateFlatElementsOnFacesGroups(const std::vector (anElem); + const SMDS_MeshFace* aFace = meshDS->DownCast ( *elemItr ); if (!aFace) continue; // MESSAGE("aFace=" << aFace->GetID()); @@ -12024,11 +11654,11 @@ bool SMESH_MeshEditor::CreateFlatElementsOnFacesGroups(const std::vectornodesIterator(); + SMDS_NodeIteratorPtr nodeIt = aFace->nodeIterator(); while (nodeIt->more()) { - const SMDS_MeshNode* node = static_cast (nodeIt->next()); - bool isMedium = isQuad && (aFace->IsMediumNode(node)); + const SMDS_MeshNode* node = nodeIt->next(); + bool isMedium = ( isQuad && aFace->IsMediumNode( node )); if (isMedium) ln2.push_back(node); else @@ -12125,10 +11755,9 @@ bool SMESH_MeshEditor::CreateFlatElementsOnFacesGroups(const std::vectormyMesh->AddGroup(SMDSAbs_Volume, namegrp.c_str(), idg); + mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Volume, namegrp.c_str()); SMESHDS_Group *sgrp = dynamic_cast(mapOfJunctionGroups[namegrp]->GetGroupDS()); if (sgrp) sgrp->Add(vol->GetID()); @@ -12136,7 +11765,7 @@ bool SMESH_MeshEditor::CreateFlatElementsOnFacesGroups(const std::vectorChangeNodes(&ln[0], ln.size()); + const_cast( aFace )->ChangeNodes( &ln[0], ln.size() ); } } return true; @@ -12199,10 +11828,10 @@ void SMESH_MeshEditor::CreateHoleSkin(double radius, // --- define groups to build - int idg; // --- group of SMDS volumes + // --- group of SMDS volumes string grpvName = groupName; grpvName += "_vol"; - SMESH_Group *grp = this->myMesh->AddGroup(SMDSAbs_Volume, grpvName.c_str(), idg); + SMESH_Group *grp = this->myMesh->AddGroup(SMDSAbs_Volume, grpvName.c_str()); if (!grp) { MESSAGE("group not created " << grpvName); @@ -12210,10 +11839,10 @@ void SMESH_MeshEditor::CreateHoleSkin(double radius, } SMESHDS_Group *sgrp = dynamic_cast(grp->GetGroupDS()); - int idgs; // --- group of SMDS faces on the skin + // --- group of SMDS faces on the skin string grpsName = groupName; grpsName += "_skin"; - SMESH_Group *grps = this->myMesh->AddGroup(SMDSAbs_Face, grpsName.c_str(), idgs); + SMESH_Group *grps = this->myMesh->AddGroup(SMDSAbs_Face, grpsName.c_str()); if (!grps) { MESSAGE("group not created " << grpsName); @@ -12221,10 +11850,10 @@ void SMESH_MeshEditor::CreateHoleSkin(double radius, } SMESHDS_Group *sgrps = dynamic_cast(grps->GetGroupDS()); - int idgi; // --- group of SMDS faces internal (several shapes) + // --- group of SMDS faces internal (several shapes) string grpiName = groupName; grpiName += "_internalFaces"; - SMESH_Group *grpi = this->myMesh->AddGroup(SMDSAbs_Face, grpiName.c_str(), idgi); + SMESH_Group *grpi = this->myMesh->AddGroup(SMDSAbs_Face, grpiName.c_str()); if (!grpi) { MESSAGE("group not created " << grpiName); @@ -12232,10 +11861,10 @@ void SMESH_MeshEditor::CreateHoleSkin(double radius, } SMESHDS_Group *sgrpi = dynamic_cast(grpi->GetGroupDS()); - int idgei; // --- group of SMDS faces internal (several shapes) + // --- group of SMDS faces internal (several shapes) string grpeiName = groupName; grpeiName += "_internalEdges"; - SMESH_Group *grpei = this->myMesh->AddGroup(SMDSAbs_Edge, grpeiName.c_str(), idgei); + SMESH_Group *grpei = this->myMesh->AddGroup(SMDSAbs_Edge, grpeiName.c_str()); if (!grpei) { MESSAGE("group not created " << grpeiName); @@ -12247,7 +11876,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double radius, SMESHDS_Mesh *meshDS = this->myMesh->GetMeshDS(); meshDS->BuildDownWardConnectivity(true); - SMDS_UnstructuredGrid* grid = meshDS->getGrid(); + SMDS_UnstructuredGrid* grid = meshDS->GetGrid(); // --- set of volumes detected inside @@ -12274,7 +11903,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double radius, while (volItr->more()) { vol = (SMDS_MeshElement*)volItr->next(); - setOfInsideVol.insert(vol->getVtkId()); + setOfInsideVol.insert(vol->GetVtkID()); sgrp->Add(vol->GetID()); } } @@ -12329,7 +11958,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double radius, while (volItr->more()) { startVol = (SMDS_MeshElement*)volItr->next(); - setOfVolToCheck.insert(startVol->getVtkId()); + setOfVolToCheck.insert(startVol->GetVtkID()); } if (setOfVolToCheck.empty()) { @@ -12348,7 +11977,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double radius, { std::set::iterator it = setOfVolToCheck.begin(); int vtkId = *it; - //MESSAGE("volume to check, vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId)); + //MESSAGE("volume to check, vtkId " << vtkId << " smdsId " << meshDS->FromVtkToSmds(vtkId)); bool volInside = false; vtkIdType npts = 0; vtkIdType* pts = 0; @@ -12382,14 +12011,14 @@ void SMESH_MeshEditor::CreateHoleSkin(double radius, if (distance2 < radius2) { volInside = true; // one or more nodes inside the domain - sgrp->Add(meshDS->fromVtkToSmds(vtkId)); + sgrp->Add(meshDS->FromVtkToSmds(vtkId)); break; } } if (volInside) { setOfInsideVol.insert(vtkId); - //MESSAGE(" volume inside, vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId)); + //MESSAGE(" volume inside, vtkId " << vtkId << " smdsId " << meshDS->FromVtkToSmds(vtkId)); int neighborsVtkIds[NBMAXNEIGHBORS]; int downIds[NBMAXNEIGHBORS]; unsigned char downTypes[NBMAXNEIGHBORS]; @@ -12401,7 +12030,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double radius, else { setOfOutsideVol.insert(vtkId); - //MESSAGE(" volume outside, vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId)); + //MESSAGE(" volume outside, vtkId " << vtkId << " smdsId " << meshDS->FromVtkToSmds(vtkId)); } setOfVolToCheck.erase(vtkId); } @@ -12436,7 +12065,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double radius, int vtkId = *it; if (grid->GetCellType(vtkId) == VTK_HEXAHEDRON) { - //MESSAGE("volume to recheck, vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId)); + //MESSAGE("volume to recheck, vtkId " << vtkId << " smdsId " << meshDS->FromVtkToSmds(vtkId)); int countInside = 0; int neighborsVtkIds[NBMAXNEIGHBORS]; int downIds[NBMAXNEIGHBORS]; @@ -12448,9 +12077,9 @@ void SMESH_MeshEditor::CreateHoleSkin(double radius, //MESSAGE("countInside " << countInside); if (countInside > 1) { - //MESSAGE(" volume inside, vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId)); + //MESSAGE(" volume inside, vtkId " << vtkId << " smdsId " << meshDS->FromVtkToSmds(vtkId)); setOfInsideVol.insert(vtkId); - sgrp->Add(meshDS->fromVtkToSmds(vtkId)); + sgrp->Add(meshDS->FromVtkToSmds(vtkId)); addedInside = true; } else @@ -12471,7 +12100,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double radius, for (; it != setOfInsideVol.end(); ++it) { int vtkId = *it; - //MESSAGE(" vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId)); + //MESSAGE(" vtkId " << vtkId << " smdsId " << meshDS->FromVtkToSmds(vtkId)); int neighborsVtkIds[NBMAXNEIGHBORS]; int downIds[NBMAXNEIGHBORS]; unsigned char downTypes[NBMAXNEIGHBORS]; @@ -12490,7 +12119,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double radius, int vtkFaceId = grid->getDownArray(downTypes[n])->getVtkCellId(downIds[n]); if (vtkFaceId >= 0) { - sgrpi->Add(meshDS->fromVtkToSmds(vtkFaceId)); + sgrpi->Add(meshDS->FromVtkToSmds(vtkFaceId)); // find also the smds edges on this face int nbEdges = grid->getDownArray(downTypes[n])->getNumberOfDownCells(downIds[n]); const int* dEdges = grid->getDownArray(downTypes[n])->getDownCells(downIds[n]); @@ -12499,7 +12128,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double radius, { int vtkEdgeId = grid->getDownArray(dTypes[i])->getVtkCellId(dEdges[i]); if (vtkEdgeId >= 0) - sgrpei->Add(meshDS->fromVtkToSmds(vtkEdgeId)); + sgrpei->Add(meshDS->FromVtkToSmds(vtkEdgeId)); } } } @@ -12509,7 +12138,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double radius, skinFaces[face] = vtkId; int vtkFaceId = grid->getDownArray(downTypes[n])->getVtkCellId(downIds[n]); if (vtkFaceId >= 0) - sgrps->Add(meshDS->fromVtkToSmds(vtkFaceId)); + sgrps->Add(meshDS->FromVtkToSmds(vtkFaceId)); } } } @@ -12528,7 +12157,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double radius, { const SMDS_MeshElement *elem = itelem->next(); int shapeId = elem->getshapeId(); - int vtkId = elem->getVtkId(); + int vtkId = elem->GetVtkID(); if (!shapeIdToVtkIdSet.count(shapeId)) { shapeIdToVtkIdSet[shapeId] = emptySet; @@ -12563,7 +12192,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double radius, { if (neighborsVtkIds[n]<0) // only smds faces are considered as neighbors here continue; - int smdsId = meshDS->fromVtkToSmds(neighborsVtkIds[n]); + int smdsId = meshDS->FromVtkToSmds(neighborsVtkIds[n]); const SMDS_MeshElement* elem = meshDS->FindElement(smdsId); if ( shapeIds.count(elem->getshapeId()) && !sgrps->Contains(elem)) // edge : neighbor in the set of shape, not in the group { @@ -12717,7 +12346,7 @@ bool SMESH_MeshEditor::Make2DMeshFrom3D() // add new face based on volume nodes if (aMesh->FindElement( nodes, SMDSAbs_Face, /*noMedium=*/false) ) { - nbExisted++; // face already exsist + nbExisted++; // face already exists } else { @@ -12803,7 +12432,7 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements, if (elements.empty()) eIt = aMesh->elementsIterator(elemType); else eIt = SMESHUtils::elemSetIterator( elements ); - while (eIt->more()) + while ( eIt->more() ) { const SMDS_MeshElement* elem = eIt->next(); const int iQuad = elem->IsQuadratic(); @@ -12884,7 +12513,7 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements, else if ( elem->GetType() == SMDSAbs_Face ) // elem is a face ------------------------ { avoidSet.clear(), avoidSet.insert( elem ); - elemNodes.assign( SMDS_MeshElement::iterator( elem->interlacedNodesElemIterator() ), + elemNodes.assign( SMDS_MeshElement::iterator( elem->interlacedNodesIterator() ), SMDS_MeshElement::iterator() ); elemNodes.push_back( elemNodes[0] ); nodes.resize( 2 + iQuad ); @@ -12917,7 +12546,7 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements, tgtNodes.resize( srcNodes.size() ); for ( inode = 0; inode < srcNodes.size(); ++inode ) tgtNodes[inode] = getNodeWithSameID( tgtMeshDS, srcNodes[inode] ); - if ( aroundElements && tgtEditor.GetMeshDS()->FindElement( tgtNodes, + if ( /*aroundElements && */tgtEditor.GetMeshDS()->FindElement( tgtNodes, missType, /*noMedium=*/false)) continue; @@ -12928,7 +12557,7 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements, for ( size_t i = 0; i < missingBndElems.size(); ++i ) { TConnectivity& nodes = missingBndElems[ i ]; - if ( aroundElements && tgtEditor.GetMeshDS()->FindElement( nodes, + if ( /*aroundElements && */tgtEditor.GetMeshDS()->FindElement( nodes, missType, /*noMedium=*/false)) continue; @@ -13038,7 +12667,7 @@ void SMESH_MeshEditor::copyPosition( const SMDS_MeshNode* from, case SMDS_TOP_FACE: { - const SMDS_FacePosition* fPos = static_cast< const SMDS_FacePosition* >( pos ); + SMDS_FacePositionPtr fPos = pos; GetMeshDS()->SetNodeOnFace( to, from->getshapeId(), fPos->GetUParameter(), fPos->GetVParameter() ); break; @@ -13046,7 +12675,7 @@ void SMESH_MeshEditor::copyPosition( const SMDS_MeshNode* from, case SMDS_TOP_EDGE: { // WARNING: it is dangerous to set equal nodes on one EDGE!!!!!!!! - const SMDS_EdgePosition* ePos = static_cast< const SMDS_EdgePosition* >( pos ); + SMDS_EdgePositionPtr ePos = pos; GetMeshDS()->SetNodeOnEdge( to, from->getshapeId(), ePos->GetUParameter() ); break; } @@ -13059,482 +12688,3 @@ void SMESH_MeshEditor::copyPosition( const SMDS_MeshNode* from, default:; } } - -namespace // utils for MakePolyLine -{ - //================================================================================ - /*! - * \brief Sequence of found points and a current point data - */ - struct Path - { - std::vector< gp_XYZ > myPoints; - double myLength; - - int mySrcPntInd; //!< start point index - const SMDS_MeshElement* myFace; - SMESH_NodeXYZ myNode1; - SMESH_NodeXYZ myNode2; - int myNodeInd1; - int myNodeInd2; - double myDot1; - double myDot2; - TIDSortedElemSet myElemSet, myAvoidSet; - - Path(): myLength(0.0), myFace(0) {} - - bool SetCutAtCorner( const SMESH_NodeXYZ& cornerNode, - const SMDS_MeshElement* face, - const gp_XYZ& plnNorm, - const gp_XYZ& plnOrig ); - - void AddPoint( const gp_XYZ& p ); - - bool Extend( const gp_XYZ& plnNorm, const gp_XYZ& plnOrig ); - - bool ReachSamePoint( const Path& other ); - - static void Remove( std::vector< Path > & paths, size_t& i ); - }; - - //================================================================================ - /*! - * \brief Return true if this Path meats another - */ - //================================================================================ - - bool Path::ReachSamePoint( const Path& other ) - { - return ( mySrcPntInd != other.mySrcPntInd && - myFace == other.myFace ); - } - - //================================================================================ - /*! - * \brief Remove a path from a vector - */ - //================================================================================ - - void Path::Remove( std::vector< Path > & paths, size_t& i ) - { - if ( paths.size() > 1 ) - { - size_t j = paths.size() - 1; // last item to be removed - if ( i < j ) - { - paths[ i ].myPoints.swap( paths[ j ].myPoints ); - paths[ i ].myLength = paths[ j ].myLength; - paths[ i ].mySrcPntInd = paths[ j ].mySrcPntInd; - paths[ i ].myFace = paths[ j ].myFace; - paths[ i ].myNode1 = paths[ j ].myNode1; - paths[ i ].myNode2 = paths[ j ].myNode2; - paths[ i ].myNodeInd1 = paths[ j ].myNodeInd1; - paths[ i ].myNodeInd2 = paths[ j ].myNodeInd2; - paths[ i ].myDot1 = paths[ j ].myDot1; - paths[ i ].myDot2 = paths[ j ].myDot2; - } - } - paths.pop_back(); - if ( i > 0 ) - --i; - } - - //================================================================================ - /*! - * \brief Store a point that is at a node of a face if the face is intersected by plane. - * Return false if the node is a sole intersection point of the face and the plane - */ - //================================================================================ - - bool Path::SetCutAtCorner( const SMESH_NodeXYZ& cornerNode, - const SMDS_MeshElement* face, - const gp_XYZ& plnNorm, - const gp_XYZ& plnOrig ) - { - if ( face == myFace ) - return false; - myNodeInd1 = face->GetNodeIndex( cornerNode._node ); - myNodeInd2 = ( myNodeInd1 + 1 ) % face->NbCornerNodes(); - int ind3 = ( myNodeInd1 + 2 ) % face->NbCornerNodes(); - myNode1.Set( face->GetNode( ind3 )); - myNode2.Set( face->GetNode( myNodeInd2 )); - - myDot1 = plnNorm * ( myNode1 - plnOrig ); - myDot2 = plnNorm * ( myNode2 - plnOrig ); - - bool ok = ( myDot1 * myDot2 < 0 ); - if ( !ok && myDot1 * myDot2 == 0 ) - { - ok = ( myDot1 != myDot2 ); - if ( ok && myFace ) - ok = ( myFace->GetNodeIndex(( myDot1 == 0 ? myNode1 : myNode2 )._node ) < 0 ); - } - if ( ok ) - { - myFace = face; - myDot1 = 0; - AddPoint( cornerNode ); - } - return ok; - } - - //================================================================================ - /*! - * \brief Store a point and update myLength - */ - //================================================================================ - - void Path::AddPoint( const gp_XYZ& p ) - { - if ( !myPoints.empty() ) - myLength += ( p - myPoints.back() ).Modulus(); - else - myLength = 0; - myPoints.push_back( p ); - } - - //================================================================================ - /*! - * \brief Try to find the next point - * \param [in] plnNorm - cutting plane normal - * \param [in] plnOrig - cutting plane origin - */ - //================================================================================ - - bool Path::Extend( const gp_XYZ& plnNorm, const gp_XYZ& plnOrig ) - { - int nodeInd3 = ( myNodeInd1 + 1 ) % myFace->NbCornerNodes(); - if ( myNodeInd2 == nodeInd3 ) - nodeInd3 = ( myNodeInd1 + 2 ) % myFace->NbCornerNodes(); - - SMESH_NodeXYZ node3 = myFace->GetNode( nodeInd3 ); - double dot3 = plnNorm * ( node3 - plnOrig ); - - if ( dot3 * myDot1 < 0. ) - { - myNode2 = node3; - myNodeInd2 = nodeInd3; - myDot2 = dot3; - } - else if ( dot3 * myDot2 < 0. ) - { - myNode1 = node3; - myNodeInd1 = nodeInd3; - myDot1 = dot3; - } - else if ( dot3 == 0. ) - { - SMDS_ElemIteratorPtr fIt = node3._node->GetInverseElementIterator(SMDSAbs_Face); - while ( fIt->more() ) - if ( SetCutAtCorner( node3, fIt->next(), plnNorm, plnOrig )) - return true; - return false; - } - else if ( myDot2 == 0. ) - { - SMESH_NodeXYZ node2 = myNode2; // copy as myNode2 changes in SetCutAtCorner() - SMDS_ElemIteratorPtr fIt = node2._node->GetInverseElementIterator(SMDSAbs_Face); - while ( fIt->more() ) - if ( SetCutAtCorner( node2, fIt->next(), plnNorm, plnOrig )) - return true; - return false; - } - - double r = Abs( myDot1 / ( myDot2 - myDot1 )); - AddPoint( myNode1 * ( 1 - r ) + myNode2 * r ); - - myAvoidSet.clear(); - myAvoidSet.insert( myFace ); - myFace = SMESH_MeshAlgos::FindFaceInSet( myNode1._node, myNode2._node, - myElemSet, myAvoidSet, - &myNodeInd1, &myNodeInd2 ); - return myFace; - } - - //================================================================================ - /*! - * \brief Compute a path between two points of PolySegment - */ - struct PolyPathCompute - { - SMESH_MeshEditor::TListOfPolySegments& mySegments; //!< inout PolySegment's - std::vector< Path >& myPaths; //!< path of each of segments to compute - SMESH_Mesh* myMesh; - mutable std::vector< std::string > myErrors; - - PolyPathCompute( SMESH_MeshEditor::TListOfPolySegments& theSegments, - std::vector< Path >& thePaths, - SMESH_Mesh* theMesh): - mySegments( theSegments ), - myPaths( thePaths ), - myMesh( theMesh ), - myErrors( theSegments.size() ) - { - } -#undef SMESH_CAUGHT -#define SMESH_CAUGHT myErrors[i] = - void operator() ( const int i ) const - { - SMESH_TRY; - const_cast< PolyPathCompute* >( this )->Compute( i ); - SMESH_CATCH( SMESH::returnError ); - } -#undef SMESH_CAUGHT - //================================================================================ - /*! - * \brief Compute a path of a given segment - */ - //================================================================================ - - void Compute( const int iSeg ) - { - SMESH_MeshEditor::PolySegment& polySeg = mySegments[ iSeg ]; - - // get a cutting plane - - gp_XYZ p1 = SMESH_NodeXYZ( polySeg.myNode1[0] ); - gp_XYZ p2 = SMESH_NodeXYZ( polySeg.myNode1[1] ); - if ( polySeg.myNode2[0] ) p1 = 0.5 * ( p1 + SMESH_NodeXYZ( polySeg.myNode2[0] )); - if ( polySeg.myNode2[1] ) p2 = 0.5 * ( p2 + SMESH_NodeXYZ( polySeg.myNode2[1] )); - - gp_XYZ plnNorm = ( p1 - p2 ) ^ polySeg.myVector.XYZ(); - gp_XYZ plnOrig = p2; - - // find paths connecting the 2 end points of polySeg - - std::vector< Path > paths; paths.reserve(10); - - // initialize paths - - for ( int iP = 0; iP < 2; ++iP ) // loop on the polySeg end points - { - Path path; - path.mySrcPntInd = iP; - size_t nbPaths = paths.size(); - - if ( polySeg.myNode2[ iP ] && polySeg.myNode2[ iP ] != polySeg.myNode1[ iP ] ) - { - while (( path.myFace = SMESH_MeshAlgos::FindFaceInSet( polySeg.myNode1[ iP ], - polySeg.myNode2[ iP ], - path.myElemSet, - path.myAvoidSet, - &path.myNodeInd1, - &path.myNodeInd2 ))) - { - path.myNode1.Set( polySeg.myNode1[ iP ]); - path.myNode2.Set( polySeg.myNode2[ iP ]); - path.myDot1 = plnNorm * ( path.myNode1 - plnOrig ); - path.myDot2 = plnNorm * ( path.myNode2 - plnOrig ); - path.myPoints.clear(); - path.AddPoint( 0.5 * ( path.myNode1 + path.myNode2 )); - path.myAvoidSet.insert( path.myFace ); - paths.push_back( path ); - } - if ( nbPaths == paths.size() ) - throw SALOME_Exception ( SMESH_Comment("No face edge found by point ") << iP+1 - << " in a PolySegment " << iSeg ); - } - else // an end point is at node - { - std::set nodes; - SMDS_ElemIteratorPtr fIt = polySeg.myNode1[ iP ]->GetInverseElementIterator(SMDSAbs_Face); - while ( fIt->more() ) - { - path.myPoints.clear(); - if ( path.SetCutAtCorner( polySeg.myNode1[ iP ], fIt->next(), plnNorm, plnOrig )) - { - if (( path.myDot1 * path.myDot2 != 0 ) || - ( nodes.insert( path.myDot1 == 0 ? path.myNode1._node : path.myNode2._node ).second )) - paths.push_back( path ); - } - } - } - - // look for a one-segment path - for ( size_t i = 0; i < nbPaths; ++i ) - for ( size_t j = nbPaths; j < paths.size(); ++j ) - if ( paths[i].myFace == paths[j].myFace ) - { - myPaths[ iSeg ].myPoints.push_back( paths[i].myPoints[0] ); - myPaths[ iSeg ].myPoints.push_back( paths[j].myPoints[0] ); - paths.clear(); - } - } - - // extend paths - - myPaths[ iSeg ].myLength = 1e100; - - while ( paths.size() >= 2 ) - { - for ( size_t i = 0; i < paths.size(); ++i ) - { - Path& path = paths[ i ]; - if ( !path.Extend( plnNorm, plnOrig ) || // path reached a mesh boundary - path.myLength > myPaths[ iSeg ].myLength ) // path is longer than others - { - Path::Remove( paths, i ); - continue; - } - - // join paths that reach same point - for ( size_t j = 0; j < paths.size(); ++j ) - { - if ( i != j && paths[i].ReachSamePoint( paths[j] )) - { - double distLast = ( paths[i].myPoints.back() - paths[j].myPoints.back() ).Modulus(); - double fullLength = ( paths[i].myLength + paths[j].myLength + distLast ); - if ( fullLength < myPaths[ iSeg ].myLength ) - { - myPaths[ iSeg ].myLength = fullLength; - std::vector< gp_XYZ > & allPoints = myPaths[ iSeg ].myPoints; - allPoints.swap( paths[i].myPoints ); - allPoints.insert( allPoints.end(), - paths[j].myPoints.rbegin(), - paths[j].myPoints.rend() ); - } - Path::Remove( paths, i ); - Path::Remove( paths, j ); - } - } - } - if ( !paths.empty() && (int) paths[0].myPoints.size() > myMesh->NbFaces() ) - throw SALOME_Exception(LOCALIZED( "Infinite loop in MakePolyLine()")); - } - - if ( myPaths[ iSeg ].myPoints.empty() ) - throw SALOME_Exception( SMESH_Comment("Can't find a full path for PolySegment #") << iSeg ); - - } // PolyPathCompute::Compute() - - }; // struct PolyPathCompute - -} // namespace - -//======================================================================= -//function : MakePolyLine -//purpose : Create a polyline consisting of 1D mesh elements each lying on a 2D element of -// the initial mesh -//======================================================================= - -void SMESH_MeshEditor::MakePolyLine( TListOfPolySegments& theSegments, - SMESHDS_Group* theGroup, - SMESH_ElementSearcher* theSearcher) -{ - std::vector< Path > segPaths( theSegments.size() ); // path of each of segments - - SMESH_ElementSearcher* searcher = theSearcher; - SMESHUtils::Deleter delSearcher; - if ( !searcher ) - { - searcher = SMESH_MeshAlgos::GetElementSearcher( *GetMeshDS() ); - delSearcher._obj = searcher; - } - - // get cutting planes - - std::vector< bool > isVectorOK( theSegments.size(), true ); - const double planarCoef = 0.333; // plane height in planar case - - for ( size_t iSeg = 0; iSeg < theSegments.size(); ++iSeg ) - { - PolySegment& polySeg = theSegments[ iSeg ]; - - gp_XYZ p1 = SMESH_NodeXYZ( polySeg.myNode1[0] ); - gp_XYZ p2 = SMESH_NodeXYZ( polySeg.myNode1[1] ); - if ( polySeg.myNode2[0] ) p1 = 0.5 * ( p1 + SMESH_NodeXYZ( polySeg.myNode2[0] )); - if ( polySeg.myNode2[1] ) p2 = 0.5 * ( p2 + SMESH_NodeXYZ( polySeg.myNode2[1] )); - - gp_XYZ plnNorm = ( p1 - p2 ) ^ polySeg.myVector.XYZ(); - - isVectorOK[ iSeg ] = ( plnNorm.Modulus() > std::numeric_limits::min() ); - if ( !isVectorOK[ iSeg ]) - { - gp_XYZ pMid = 0.5 * ( p1 + p2 ); - const SMDS_MeshElement* face; - polySeg.myMidProjPoint = searcher->Project( pMid, SMDSAbs_Face, &face ); - polySeg.myVector = polySeg.myMidProjPoint.XYZ() - pMid; - - gp_XYZ faceNorm; - SMESH_MeshAlgos::FaceNormal( face, faceNorm ); - - if ( polySeg.myVector.Magnitude() < Precision::Confusion() || - polySeg.myVector * faceNorm < Precision::Confusion() ) - { - polySeg.myVector = faceNorm; - polySeg.myMidProjPoint = pMid + faceNorm * ( p1 - p2 ).Modulus() * planarCoef; - } - } - else - { - polySeg.myVector = plnNorm ^ ( p1 - p2 ); - } - } - - // assure that inverse elements are constructed, avoid their concurrent building in threads - GetMeshDS()->nodesIterator()->next()->NbInverseElements(); - - // find paths - - PolyPathCompute algo( theSegments, segPaths, myMesh ); - OSD_Parallel::For( 0, theSegments.size(), algo, theSegments.size() == 1 ); - - for ( size_t iSeg = 0; iSeg < theSegments.size(); ++iSeg ) - if ( !algo.myErrors[ iSeg ].empty() ) - throw SALOME_Exception( algo.myErrors[ iSeg ].c_str() ); - - // create an 1D mesh - - const SMDS_MeshNode *n, *nPrev = 0; - SMESHDS_Mesh* mesh = GetMeshDS(); - - for ( size_t iSeg = 0; iSeg < theSegments.size(); ++iSeg ) - { - const Path& path = segPaths[iSeg]; - if ( path.myPoints.size() < 2 ) - continue; - - double tol = path.myLength / path.myPoints.size() / 1000.; - if ( !nPrev || ( SMESH_NodeXYZ( nPrev ) - path.myPoints[0] ).SquareModulus() > tol*tol ) - { - nPrev = mesh->AddNode( path.myPoints[0].X(), path.myPoints[0].Y(), path.myPoints[0].Z() ); - myLastCreatedNodes.push_back( nPrev ); - } - for ( size_t iP = 1; iP < path.myPoints.size(); ++iP ) - { - n = mesh->AddNode( path.myPoints[iP].X(), path.myPoints[iP].Y(), path.myPoints[iP].Z() ); - myLastCreatedNodes.push_back( n ); - - const SMDS_MeshElement* elem = mesh->AddEdge( nPrev, n ); - myLastCreatedElems.push_back( elem ); - if ( theGroup ) - theGroup->Add( elem ); - - nPrev = n; - } - - // return a vector - - gp_XYZ pMid = 0.5 * ( path.myPoints[0] + path.myPoints.back() ); - if ( isVectorOK[ iSeg ]) - { - // find the most distance point of a path - double maxDist = 0; - for ( size_t iP = 1; iP < path.myPoints.size(); ++iP ) - { - double dist = Abs( theSegments[iSeg].myVector * ( path.myPoints[iP] - path.myPoints[0] )); - if ( dist > maxDist ) - { - maxDist = dist; - theSegments[iSeg].myMidProjPoint = path.myPoints[iP]; - } - } - if ( maxDist < Precision::Confusion() ) // planar case - theSegments[iSeg].myMidProjPoint = - pMid + theSegments[iSeg].myVector.XYZ().Normalized() * path.myLength * planarCoef; - } - theSegments[iSeg].myVector = gp_Vec( pMid, theSegments[iSeg].myMidProjPoint ); - } - - return; -}