From e3d582dca70275fa15c65d7d01a3b9c019017c8d Mon Sep 17 00:00:00 2001 From: cconopoima Date: Wed, 14 Jun 2023 08:25:23 -0300 Subject: [PATCH] bos #34269 [CEA] Function to check same face orientation for polyhedrals used on the computation of their volume. --- src/SMDS/SMDS_VolumeTool.cxx | 57 +++++++++++++++++++++++++++- src/SMDS/SMDS_VolumeTool.hxx | 4 ++ test/SMESH_create_dual_mesh_adapt.py | 1 + test/SMESH_create_dual_mesh_tpipe.py | 1 + 4 files changed, 61 insertions(+), 2 deletions(-) diff --git a/src/SMDS/SMDS_VolumeTool.cxx b/src/SMDS/SMDS_VolumeTool.cxx index efe591ca6..f72a13002 100644 --- a/src/SMDS/SMDS_VolumeTool.cxx +++ b/src/SMDS/SMDS_VolumeTool.cxx @@ -730,7 +730,7 @@ double SMDS_VolumeTool::GetSize() const // split a polyhedron into tetrahedrons - bool oriOk = true; + bool oriOk = AllFacesSameOriented(); SMDS_VolumeTool* me = const_cast< SMDS_VolumeTool* > ( this ); for ( int f = 0; f < NbFaces(); ++f ) { @@ -743,7 +743,6 @@ double SMDS_VolumeTool::GetSize() const p1 = p2; } V += p1.Dot( area ); - oriOk = oriOk && IsFaceExternal( f ); } V /= 6; if ( !oriOk && V > 0 ) @@ -1596,6 +1595,60 @@ bool SMDS_VolumeTool::GetFaceBaryCenter (int faceIndex, double & X, double & Y, return true; } +//================================================================================ +/*! + * \brief Check that all the faces in a polyhedron follow the same orientation + * \remark there is no differentiation for outward and inward face orientation. + */ +//================================================================================ +bool SMDS_VolumeTool::AllFacesSameOriented() const +{ + SMDS_VolumeTool* me = const_cast< SMDS_VolumeTool* > ( this ); + bool validOrientation = true; + std::map> collectLinksOrientations; + me->myFwdLinks.clear(); + for ( int faceId = 0; faceId < NbFaces(); ++faceId ) + { + me->setFace( faceId ); + myExternalFaces = false; + + // Build the links + for ( int i = 0; i < myCurFace.myNbNodes; ++i ) + { + NLink link( myCurFace.myNodes[i], myCurFace.myNodes[i+1] ); + std::map::const_iterator foundLink = myFwdLinks.find( link ); + + if ( foundLink == myFwdLinks.end() ) + me->myFwdLinks.insert( make_pair( link, link.myOri )); + + collectLinksOrientations[ link ].push_back( link.myOri ); + } + } + + // Check duality of the orientations + std::map>::const_iterator theLinks; + for ( theLinks = collectLinksOrientations.begin(); theLinks != collectLinksOrientations.end(); theLinks++ ) + { + if ( theLinks->second.size() == 2 ) // 99% of the cases there are 2 faces per link + { + if ( 1 != -1*theLinks->second[0]*theLinks->second[1] ) + return false; + continue; + } + + if ( theLinks->second.size() % 2 != 0 )// Dont treat uneven number of links + continue; + + // In the other 1% of the cases we count the number occurrence and check that they match + int minusOne = std::count( theLinks->second.begin(), theLinks->second.end(), -1 ); + int plusOne = std::count( theLinks->second.begin(), theLinks->second.end(), 1 ); + if ( minusOne != plusOne ) + return false; + } + + return validOrientation; +} + //======================================================================= //function : GetFaceArea //purpose : Return face area diff --git a/src/SMDS/SMDS_VolumeTool.hxx b/src/SMDS/SMDS_VolumeTool.hxx index 0db821edb..226eb2536 100644 --- a/src/SMDS/SMDS_VolumeTool.hxx +++ b/src/SMDS/SMDS_VolumeTool.hxx @@ -199,6 +199,10 @@ class SMDS_EXPORT SMDS_VolumeTool bool GetFaceBaryCenter (int faceIndex, double & X, double & Y, double & Z) const; // Return barycenter of a face + bool AllFacesSameOriented() const; + // Check that all the faces of a polyhedron have the same orientation + // no differentiation between inward and outward orientation is made. + double GetFaceArea( int faceIndex ) const; // Return face area diff --git a/test/SMESH_create_dual_mesh_adapt.py b/test/SMESH_create_dual_mesh_adapt.py index d701478ff..9b82dec8d 100644 --- a/test/SMESH_create_dual_mesh_adapt.py +++ b/test/SMESH_create_dual_mesh_adapt.py @@ -93,6 +93,7 @@ print("dual_volume: ", dual_volume) print("dual_raw_volume: ", dual_raw_volume) assert (dual_volume >= dual_raw_volume) +assert abs( tetra_volume - dual_raw_volume )/tetra_volume < 1e-12 if salome.sg.hasDesktop(): salome.sg.updateObjBrowser() diff --git a/test/SMESH_create_dual_mesh_tpipe.py b/test/SMESH_create_dual_mesh_tpipe.py index fce3c252a..c1aa3c5c1 100644 --- a/test/SMESH_create_dual_mesh_tpipe.py +++ b/test/SMESH_create_dual_mesh_tpipe.py @@ -128,6 +128,7 @@ print("dual_raw_volume: ", dual_raw_volume) assert (dual_volume >= dual_raw_volume) assert abs(dual_volume-shape_volume)/shape_volume < 0.14 +assert abs(dual_raw_volume-tetra_volume)/tetra_volume < 1e-12 # Check groups dual_Mesh_groups = dual_Mesh_1.GetGroups() -- 2.30.2