Salome HOME
bos #34269 [CEA] Function to check same face orientation for polyhedrals used on... cce/34269 V9_12_0a1 V9_12_0a2
authorcconopoima <cesar.conopoima@gmail.com>
Wed, 14 Jun 2023 11:25:23 +0000 (08:25 -0300)
committerChristophe Bourcier <christophe.bourcier@cea.fr>
Tue, 3 Oct 2023 11:45:48 +0000 (13:45 +0200)
src/SMDS/SMDS_VolumeTool.cxx
src/SMDS/SMDS_VolumeTool.hxx
test/SMESH_create_dual_mesh_adapt.py
test/SMESH_create_dual_mesh_tpipe.py

index efe591ca65818067ff6e7d9f03c23a9db4c763b0..f72a130026a5ae89f128adca4b521997bc7e37d8 100644 (file)
@@ -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<Link, std::vector<int>> 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<Link, int>::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<Link, std::vector<int>>::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
index 0db821edbcbd4b1dc000a535743e2b69b18bf4b4..226eb2536952f0425b316da60c931d01c767efee 100644 (file)
@@ -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
 
index d701478ffadedc36d78aeaf4a14f827600ec129c..9b82dec8db95fa0e7d8135402bc04276a1b25ba9 100644 (file)
@@ -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()
index fce3c252afe0b981debab0c0e77aaa45cdea1d4e..c1aa3c5c1feec4790f77ad3c1ee699090764e742 100644 (file)
@@ -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()