0031378: Modeling algorithms - brep incremental mesh is frozen during STEP file loading
authoroan <oan@opencascade.com>
Thu, 12 Mar 2020 14:37:09 +0000 (17:37 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 26 Mar 2020 16:56:21 +0000 (19:56 +0300)
Refactoring of BRepMesh_Delaun::isBoundToFrontier() to unwind the recursion loop.

src/BRepMesh/BRepMesh_Delaun.cxx
src/BRepMesh/BRepMesh_Delaun.hxx
tests/bugs/mesh/bug31378 [new file with mode: 0644]

index 44b1a8b..435aae6 100644 (file)
@@ -34,6 +34,7 @@
 #include <NCollection_Vector.hxx>
 
 #include <algorithm>
+#include <stack>
 
 const Standard_Real AngDeviation1Deg  = M_PI/180.;
 const Standard_Real AngDeviation90Deg = 90 * AngDeviation1Deg;
@@ -652,53 +653,56 @@ void BRepMesh_Delaun::insertInternalEdges()
 
 //=======================================================================
 //function : isBoundToFrontier
-//purpose  : Goes through the neighbour triangles around the given node 
-//           started from the given link, returns TRUE if some triangle 
-//           has a bounding frontier edge or FALSE elsewhere.
-//           Stop link is used to prevent cycles.
-//           Previous element Id is used to identify next neighbor element.
+//purpose  : 
 //=======================================================================
 Standard_Boolean BRepMesh_Delaun::isBoundToFrontier(
   const Standard_Integer theRefNodeId,
-  const Standard_Integer theRefLinkId,
-  const Standard_Integer theStopLinkId,
-  const Standard_Integer thePrevElementId)
+  const Standard_Integer theRefLinkId)
 {
-  const BRepMesh_PairOfIndex& aPair = 
-    myMeshData->ElementsConnectedTo( theRefLinkId );
-  if ( aPair.IsEmpty() )
-    return Standard_False;
+  std::stack<Standard_Integer> aLinkStack;
+  TColStd_PackedMapOfInteger   aVisitedLinks;
 
-  Standard_Integer aNbElements = aPair.Extent();
-  for ( Standard_Integer anElemIt = 1; anElemIt <= aNbElements; ++anElemIt )
+  aLinkStack.push (theRefLinkId);
+  while (!aLinkStack.empty ())
   {
-    const Standard_Integer aTriId = aPair.Index(anElemIt);
-    if ( aTriId < 0 || aTriId == thePrevElementId )
-      continue;
+    const Standard_Integer aCurrentLinkId = aLinkStack.top ();
+    aLinkStack.pop ();
 
-    const BRepMesh_Triangle& aElement = GetTriangle(aTriId);
-    const Standard_Integer(&anEdges)[3] = aElement.myEdges;
+    const BRepMesh_PairOfIndex& aPair = myMeshData->ElementsConnectedTo (aCurrentLinkId);
+    if (aPair.IsEmpty ())
+      return Standard_False;
 
-    for ( Standard_Integer anEdgeIt = 0; anEdgeIt < 3; ++anEdgeIt )
+    const Standard_Integer aNbElements = aPair.Extent ();
+    for (Standard_Integer anElemIt = 1; anElemIt <= aNbElements; ++anElemIt)
     {
-      const Standard_Integer anEdgeId = anEdges[anEdgeIt];
-      if ( anEdgeId == theRefLinkId )
+      const Standard_Integer aTriId = aPair.Index (anElemIt);
+      if (aTriId < 0)
         continue;
 
-      if ( anEdgeId == theStopLinkId )
-        return Standard_False;
+      const BRepMesh_Triangle& aElement = GetTriangle (aTriId);
+      const Standard_Integer (&anEdges)[3] = aElement.myEdges;
 
-      const BRepMesh_Edge& anEdge = GetEdge( anEdgeId );
-      if ( anEdge.FirstNode() != theRefNodeId &&
-           anEdge.LastNode()  != theRefNodeId )
+      for (Standard_Integer anEdgeIt = 0; anEdgeIt < 3; ++anEdgeIt)
       {
-        continue;
-      }
+        const Standard_Integer anEdgeId = anEdges[anEdgeIt];
+        if (anEdgeId == aCurrentLinkId)
+          continue;
 
-      if ( anEdge.Movability() != BRepMesh_Free )
-        return Standard_True;
+        const BRepMesh_Edge& anEdge = GetEdge (anEdgeId);
+        if (anEdge.FirstNode () != theRefNodeId &&
+            anEdge.LastNode  () != theRefNodeId)
+        {
+          continue;
+        }
+
+        if (anEdge.Movability () != BRepMesh_Free)
+          return Standard_True;
 
-      return isBoundToFrontier( theRefNodeId, anEdgeId, theStopLinkId, aTriId );
+        if (aVisitedLinks.Add (anEdgeId))
+        {
+          aLinkStack.push (anEdgeId);
+        }
+      }
     }
   }
 
@@ -792,8 +796,7 @@ void BRepMesh_Delaun::cleanupMesh()
       for ( Standard_Integer aLinkNodeIt = 0; aLinkNodeIt < 2; ++aLinkNodeIt )
       {
         isConnected[aLinkNodeIt] = isBoundToFrontier( ( aLinkNodeIt == 0 ) ? 
-          anEdge.FirstNode() : anEdge.LastNode(), 
-          aFreeEdgeId, aFreeEdgeId, -1);
+          anEdge.FirstNode() : anEdge.LastNode(), aFreeEdgeId);
       }
 
       if ( !isConnected[0] || !isConnected[1] )
index f03a333..5038e89 100755 (executable)
@@ -292,12 +292,8 @@ private:
   //! Goes through the neighbour triangles around the given node started
   //! from the given link, returns TRUE if some triangle has a bounding
   //! frontier edge or FALSE elsewhere.
-  //! Stop link is used to prevent cycles.
-  //! Previous element Id is used to identify next neighbor element.
   Standard_Boolean isBoundToFrontier (const Standard_Integer theRefNodeId,
-                                      const Standard_Integer theRefLinkId,
-                                      const Standard_Integer theStopLinkId,
-                                      const Standard_Integer thePrevElementId);
+                                      const Standard_Integer theRefLinkId);
 
   //! Remove internal triangles from the given polygon.
   void cleanupPolygon (const IMeshData::SequenceOfInteger& thePolygon,
diff --git a/tests/bugs/mesh/bug31378 b/tests/bugs/mesh/bug31378
new file mode 100644 (file)
index 0000000..f949795
--- /dev/null
@@ -0,0 +1,20 @@
+puts "======="
+puts "0031378: Modeling algorithms - brep incremental mesh is frozen during STEP file loading"
+puts "======="
+puts ""
+
+pload ALL
+
+ReadStep D [locate_data_file bug31378_lego-FP.stp]
+XGetOneShape result D
+incmesh result 1.7 -parallel
+
+vinit
+vdefaults -autoTriang 0
+vsetdispmode 1
+vdisplay result
+vfit
+
+checktrinfo result -tri
+
+checkview -screenshot -3d -path ${imagedir}/${test_image}.png