X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FSMESH%2FSMESH_MeshEditor.cxx;h=e9c672c1edecea739e5fd7da0021354a878bf369;hp=efa01a4c2ff015bcb1ea03a28a4412a950a955bb;hb=HEAD;hpb=1b69b0f98a53cc4ba9bd3d8002aba861d71b4185 diff --git a/src/SMESH/SMESH_MeshEditor.cxx b/src/SMESH/SMESH_MeshEditor.cxx index efa01a4c2..125bbaa2e 100644 --- a/src/SMESH/SMESH_MeshEditor.cxx +++ b/src/SMESH/SMESH_MeshEditor.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2022 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2024 CEA, EDF, OPEN CASCADE // // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS @@ -62,6 +62,8 @@ #include #include #include +#include +#include #include #include #include @@ -101,6 +103,7 @@ #include "SMESH_TryCatch.hxx" // include after OCCT headers! #include +#include #define cast2Node(elem) static_cast( elem ) @@ -1505,7 +1508,7 @@ int SMESH_MeshEditor::Reorient2D( TIDSortedElemSet & theFaces, vector< const SMDS_MeshElement* > facesNearLink; vector< std::pair< int, int > > nodeIndsOfFace; TIDSortedElemSet avoidSet, emptySet; - NCollection_Map< SMESH_TLink, SMESH_TLink > checkedLinks; + NCollection_Map< SMESH_TLink, SMESH_TLinkHasher > checkedLinks; while ( !theRefFaces.empty() ) { @@ -3849,6 +3852,68 @@ void SMESH_MeshEditor::GetLinkedNodes( const SMDS_MeshNode* theNode, } } +//======================================================================= +//function : averageBySurface +//purpose : Auxiliar function to treat properly nodes in periodic faces in the laplacian smoother +//======================================================================= +void averageBySurface( const Handle(Geom_Surface)& theSurface, const SMDS_MeshNode* refNode, + TIDSortedElemSet& nodeSet, map< const SMDS_MeshNode*, gp_XY* >& theUVMap, double * coord ) +{ + if ( theSurface.IsNull() ) + { + TIDSortedElemSet::iterator nodeSetIt = nodeSet.begin(); + for ( ; nodeSetIt != nodeSet.end(); nodeSetIt++ ) + { + const SMDS_MeshNode* node = cast2Node(*nodeSetIt); + coord[0] += node->X(); + coord[1] += node->Y(); + coord[2] += node->Z(); + } + } + else + { + Standard_Real Umin,Umax,Vmin,Vmax; + theSurface->Bounds( Umin, Umax, Vmin, Vmax ); + ASSERT( theUVMap.find( refNode ) != theUVMap.end() ); + gp_XY* nodeUV = theUVMap[ refNode ]; + Standard_Real uref = nodeUV->X(); + Standard_Real vref = nodeUV->Y(); + + TIDSortedElemSet::iterator nodeSetIt = nodeSet.begin(); + for ( ; nodeSetIt != nodeSet.end(); nodeSetIt++ ) + { + const SMDS_MeshNode* node = cast2Node(*nodeSetIt); + ASSERT( theUVMap.find( node ) != theUVMap.end() ); + gp_XY* uv = theUVMap[ node ]; + + if ( theSurface->IsUPeriodic() || theSurface->IsVPeriodic() ) + { + Standard_Real u = uv->X(); + Standard_Real v = uv->Y(); + Standard_Real uCorrected = u; + Standard_Real vCorrected = v; + bool isUTobeCorrected = (std::fabs( uref - u ) >= 0.7 * std::fabs( Umax - Umin )); + bool isVTobeCorrected = (std::fabs( vref - v ) >= 0.7 * std::fabs( Vmax - Vmin )); + + if( isUTobeCorrected ) + uCorrected = uref > u ? Umax + std::fabs(Umin - u) : Umin - std::fabs(Umax - u); + + if( isVTobeCorrected ) + vCorrected = vref > v ? Vmax + std::fabs(Vmin - v) : Vmin - std::fabs(Vmax - v); + + coord[0] += uCorrected; + coord[1] += vCorrected; + + } + else + { + coord[0] += uv->X(); + coord[1] += uv->Y(); + } + } + } +} + //======================================================================= //function : laplacianSmooth //purpose : pulls theNode toward the center of surrounding nodes directly @@ -3865,26 +3930,14 @@ void laplacianSmooth(const SMDS_MeshNode* theNode, SMESH_MeshEditor::GetLinkedNodes( theNode, nodeSet, SMDSAbs_Face ); // compute new coodrs + double coord[] = { 0., 0., 0. }; + + averageBySurface( theSurface, theNode, nodeSet, theUVMap, coord ); - double coord[] = { 0., 0., 0. }; - TIDSortedElemSet::iterator nodeSetIt = nodeSet.begin(); - for ( ; nodeSetIt != nodeSet.end(); nodeSetIt++ ) { - const SMDS_MeshNode* node = cast2Node(*nodeSetIt); - if ( theSurface.IsNull() ) { // smooth in 3D - coord[0] += node->X(); - coord[1] += node->Y(); - coord[2] += node->Z(); - } - else { // smooth in 2D - ASSERT( theUVMap.find( node ) != theUVMap.end() ); - gp_XY* uv = theUVMap[ node ]; - coord[0] += uv->X(); - coord[1] += uv->Y(); - } - } int nbNodes = nodeSet.size(); if ( !nbNodes ) return; + coord[0] /= nbNodes; coord[1] /= nbNodes; @@ -3894,7 +3947,7 @@ void laplacianSmooth(const SMDS_MeshNode* theNode, gp_Pnt p3d = theSurface->Value( coord[0], coord[1] ); coord[0] = p3d.X(); coord[1] = p3d.Y(); - coord[2] = p3d.Z(); + coord[2] = p3d.Z(); } else coord[2] /= nbNodes; @@ -3904,6 +3957,72 @@ void laplacianSmooth(const SMDS_MeshNode* theNode, const_cast< SMDS_MeshNode* >( theNode )->setXYZ(coord[0],coord[1],coord[2]); } +//======================================================================= +//function : correctTheValue +//purpose : Given a boundaries of parametric space determine if the node coordinate (u,v) need correction +// based on the reference coordinate (uref,vref) +//======================================================================= +void correctTheValue( Standard_Real Umax, Standard_Real Umin, Standard_Real Vmax, Standard_Real Vmin, + Standard_Real uref, Standard_Real vref, Standard_Real &u, Standard_Real &v ) +{ + bool isUTobeCorrected = (std::fabs( uref - u ) >= 0.7 * std::fabs( Umax - Umin )); + bool isVTobeCorrected = (std::fabs( vref - v ) >= 0.7 * std::fabs( Vmax - Vmin )); + if ( isUTobeCorrected ) + u = std::fabs(u-Umin) < 1e-7 ? Umax : Umin; + if ( isVTobeCorrected ) + v = std::fabs(v-Vmin) < 1e-7 ? Vmax : Vmin; +} + +//======================================================================= +//function : averageByElement +//purpose : Auxiliar function to treat properly nodes in periodic faces in the centroidal smoother +//======================================================================= +void averageByElement( const Handle(Geom_Surface)& theSurface, const SMDS_MeshNode* refNode, const SMDS_MeshElement* elem, + map< const SMDS_MeshNode*, gp_XY* >& theUVMap, SMESH::Controls::TSequenceOfXYZ& aNodePoints, + gp_XYZ& elemCenter ) +{ + int nn = elem->NbNodes(); + if(elem->IsQuadratic()) nn = nn/2; + int i=0; + SMDS_ElemIteratorPtr itN = elem->nodesIterator(); + Standard_Real Umin,Umax,Vmin,Vmax; + while ( i( itN->next() ); + i++; + gp_XYZ aP( aNode->X(), aNode->Y(), aNode->Z() ); + aNodePoints.push_back( aP ); + if ( !theSurface.IsNull() ) // smooth in 2D + { + ASSERT( theUVMap.find( aNode ) != theUVMap.end() ); + gp_XY* uv = theUVMap[ aNode ]; + + if ( theSurface->IsUPeriodic() || theSurface->IsVPeriodic() ) + { + theSurface->Bounds( Umin, Umax, Vmin, Vmax ); + Standard_Real u = uv->X(); + Standard_Real v = uv->Y(); + bool isSingularPoint = std::fabs(u - Umin) < 1e-7 || std::fabs(v - Vmin) < 1e-7 || std::fabs(u - Umax) < 1e-7 || std::fabs( v - Vmax ) < 1e-7; + if ( !isSingularPoint ) + { + aP.SetCoord( uv->X(), uv->Y(), 0. ); + } + else + { + gp_XY* refPoint = theUVMap[ refNode ]; + Standard_Real uref = refPoint->X(); + Standard_Real vref = refPoint->Y(); + correctTheValue( Umax, Umin, Vmax, Vmin, uref, vref, u, v ); + aP.SetCoord( u, v, 0. ); + } + } + else + aP.SetCoord( uv->X(), uv->Y(), 0. ); + } + elemCenter += aP; + } +} + //======================================================================= //function : centroidalSmooth //purpose : pulls theNode toward the element-area-weighted centroid of the @@ -3918,48 +4037,46 @@ void centroidalSmooth(const SMDS_MeshNode* theNode, SMESH::Controls::Area anAreaFunc; double totalArea = 0.; int nbElems = 0; - // compute new XYZ - + bool notToMoveNode = false; + // Do not correct singular nodes + if ( !theSurface.IsNull() && (theSurface->IsUPeriodic() || theSurface->IsVPeriodic()) ) + { + Standard_Real Umin,Umax,Vmin,Vmax; + theSurface->Bounds( Umin, Umax, Vmin, Vmax ); + gp_XY* uv = theUVMap[ theNode ]; + Standard_Real u = uv->X(); + Standard_Real v = uv->Y(); + notToMoveNode = std::fabs(u - Umin) < 1e-7 || std::fabs(v - Vmin) < 1e-7 || std::fabs(u - Umax) < 1e-7 || std::fabs( v - Vmax ) < 1e-7; + } + SMDS_ElemIteratorPtr elemIt = theNode->GetInverseElementIterator(SMDSAbs_Face); - while ( elemIt->more() ) + while ( elemIt->more() && !notToMoveNode ) { const SMDS_MeshElement* elem = elemIt->next(); nbElems++; gp_XYZ elemCenter(0.,0.,0.); SMESH::Controls::TSequenceOfXYZ aNodePoints; - SMDS_ElemIteratorPtr itN = elem->nodesIterator(); int nn = elem->NbNodes(); if(elem->IsQuadratic()) nn = nn/2; - int i=0; - //while ( itN->more() ) { - while ( i( itN->next() ); - i++; - gp_XYZ aP( aNode->X(), aNode->Y(), aNode->Z() ); - aNodePoints.push_back( aP ); - if ( !theSurface.IsNull() ) { // smooth in 2D - ASSERT( theUVMap.find( aNode ) != theUVMap.end() ); - gp_XY* uv = theUVMap[ aNode ]; - aP.SetCoord( uv->X(), uv->Y(), 0. ); - } - elemCenter += aP; - } + averageByElement( theSurface, theNode, elem, theUVMap, aNodePoints, elemCenter ); + double elemArea = anAreaFunc.GetValue( aNodePoints ); totalArea += elemArea; elemCenter /= nn; aNewXYZ += elemCenter * elemArea; } aNewXYZ /= totalArea; - if ( !theSurface.IsNull() ) { + + if ( !theSurface.IsNull() && !notToMoveNode ) { theUVMap[ theNode ]->SetCoord( aNewXYZ.X(), aNewXYZ.Y() ); aNewXYZ = theSurface->Value( aNewXYZ.X(), aNewXYZ.Y() ).XYZ(); } // move node - - const_cast< SMDS_MeshNode* >( theNode )->setXYZ(aNewXYZ.X(),aNewXYZ.Y(),aNewXYZ.Z()); + if ( !notToMoveNode ) + const_cast< SMDS_MeshNode* >( theNode )->setXYZ(aNewXYZ.X(),aNewXYZ.Y(),aNewXYZ.Z()); } //======================================================================= @@ -4262,7 +4379,8 @@ void SMESH_MeshEditor::Smooth (TIDSortedElemSet & theElems, if ( !BRep_Tool::IsClosed( edge, face )) continue; SMESHDS_SubMesh* sm = aMesh->MeshElements( edge ); - if ( !sm ) continue; + if ( !sm ) + continue; // find out which parameter varies for a node on seam double f,l; gp_Pnt2d uv1, uv2; @@ -5219,13 +5337,12 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap & mapNewNodes, srcEdges.push_back(aMesh->FindEdge (commonNodes[0],commonNodes[1],commonNodes[2])); else srcEdges.push_back(aMesh->FindEdge (commonNodes[0],commonNodes[1])); -#ifdef _DEBUG_ - if ( !srcEdges.back() ) + + if (SALOME::VerbosityActivated() && !srcEdges.back()) { cout << "SMESH_MeshEditor::makeWalls(), no source edge found for a free face #" - << iF << " of volume #" << vTool.ID() << endl; + << iF << " of volume #" << vTool.ID() << endl; } -#endif } } if ( freeInd.empty() ) @@ -6816,9 +6933,8 @@ 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 + + if (!SALOME::VerbosityActivated() || n->NbInverseElements() > 0 ) { const SMDS_MeshNode* n2 = tgtMeshDS->AddNodeWithID( n->X(), n->Y(), n->Z(), idShift + n->GetID() ); @@ -7281,6 +7397,7 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes, { const SMDS_MeshElement* elem = *eIt; SMESHDS_SubMesh* sm = mesh->MeshElements( elem->getshapeId() ); + bool marked = elem->isMarked(); bool keepElem = applyMerge( elem, newElemDefs, nodeNodeMap, /*noHoles=*/false ); if ( !keepElem ) @@ -7317,6 +7434,8 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes, sm->AddElement( newElem ); if ( elem != newElem ) ReplaceElemInGroups( elem, newElem, mesh ); + if ( marked && newElem ) + newElem->setIsMarked( true ); } } } @@ -7788,6 +7907,8 @@ bool SMESH_MeshEditor::applyMerge( const SMDS_MeshElement* elem, // purpose : allow comparing elements basing on their nodes // ======================================================== +struct ComparableElementHasher; + class ComparableElement : public boost::container::flat_set< smIdType > { typedef boost::container::flat_set< smIdType > int_set; @@ -7796,6 +7917,8 @@ class ComparableElement : public boost::container::flat_set< smIdType > smIdType mySumID; mutable int myGroupID; + friend ComparableElementHasher; + public: ComparableElement( const SMDS_MeshElement* theElem ): @@ -7824,7 +7947,11 @@ public: mySumID = src.mySumID; myGroupID = src.myGroupID; } +}; +struct ComparableElementHasher +{ +#if OCC_VERSION_LARGE < 0x07080000 static int HashCode(const ComparableElement& se, int limit ) { return ::HashCode( FromSmIdType(se.mySumID), limit ); @@ -7833,7 +7960,17 @@ public: { return ( se1 == se2 ); } +#else + size_t operator()(const ComparableElement& se) const + { + return static_cast(FromSmIdType(se.mySumID)); + } + bool operator()(const ComparableElement& se1, const ComparableElement& se2) const + { + return ( se1 == se2 ); + } +#endif }; //======================================================================= @@ -7851,8 +7988,8 @@ void SMESH_MeshEditor::FindEqualElements( TIDSortedElemSet & theElements, if ( theElements.empty() ) elemIt = GetMeshDS()->elementsIterator(); else elemIt = SMESHUtils::elemSetIterator( theElements ); - typedef NCollection_Map< ComparableElement, ComparableElement > TMapOfElements; - typedef std::list TGroupOfElems; + typedef NCollection_Map< ComparableElement, ComparableElementHasher > TMapOfElements; + typedef std::list TGroupOfElems; TMapOfElements mapOfElements; std::vector< TGroupOfElems > arrayOfGroups; TGroupOfElems groupOfElems; @@ -12808,7 +12945,8 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements, bool toCopyElements/*=false*/, bool toCopyExistingBoundary/*=false*/, bool toAddExistingBondary/*= false*/, - bool aroundElements/*= false*/) + bool aroundElements/*= false*/, + bool toCreateAllElements/*= false*/) { SMDSAbs_ElementType missType = (dimension == BND_2DFROM3D) ? SMDSAbs_Face : SMDSAbs_Edge; SMDSAbs_ElementType elemType = (dimension == BND_1DFROM2D) ? SMDSAbs_Face : SMDSAbs_Volume; @@ -12827,7 +12965,6 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements, SMESH_MeshEditor* presentEditor; SMESH_MeshEditor tgtEditor2( tgtEditor.GetMesh() ); presentEditor = toAddExistingBondary ? &tgtEditor : &tgtEditor2; - SMESH_MesherHelper helper( *myMesh ); const TopAbs_ShapeEnum missShapeType = ( missType==SMDSAbs_Face ? TopAbs_FACE : TopAbs_EDGE ); SMDS_VolumeTool vTool; @@ -12865,8 +13002,9 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements, const SMDS_MeshElement* otherVol = 0; for ( int iface = 0, n = vTool.NbFaces(); iface < n; iface++ ) { - if ( !vTool.IsFreeFace(iface, &otherVol) && - ( !aroundElements || elements.count( otherVol ))) + if ( !toCreateAllElements && + !vTool.IsFreeFace(iface, &otherVol) && + ( !aroundElements || elements.count( otherVol ))) continue; freeFacets.push_back( iface ); }