From c9125b6232e39e3c9ecc9c284da94a4e6654255d Mon Sep 17 00:00:00 2001 From: oan Date: Thu, 12 Mar 2020 17:37:09 +0300 Subject: [PATCH] 0031378: Modeling algorithms - brep incremental mesh is frozen during STEP file loading Refactoring of BRepMesh_Delaun::isBoundToFrontier() to unwind the recursion loop. --- src/BRepMesh/BRepMesh_Delaun.cxx | 73 +++++++++++++++++--------------- src/BRepMesh/BRepMesh_Delaun.hxx | 6 +-- tests/bugs/mesh/bug31378 | 20 +++++++++ 3 files changed, 59 insertions(+), 40 deletions(-) create mode 100644 tests/bugs/mesh/bug31378 diff --git a/src/BRepMesh/BRepMesh_Delaun.cxx b/src/BRepMesh/BRepMesh_Delaun.cxx index 44b1a8b027..435aae6f15 100644 --- a/src/BRepMesh/BRepMesh_Delaun.cxx +++ b/src/BRepMesh/BRepMesh_Delaun.cxx @@ -34,6 +34,7 @@ #include #include +#include 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 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; + + const BRepMesh_Edge& anEdge = GetEdge (anEdgeId); + if (anEdge.FirstNode () != theRefNodeId && + anEdge.LastNode () != theRefNodeId) + { + continue; + } + + if (anEdge.Movability () != BRepMesh_Free) + return Standard_True; + + if (aVisitedLinks.Add (anEdgeId)) + { + aLinkStack.push (anEdgeId); + } } - - if ( anEdge.Movability() != BRepMesh_Free ) - return Standard_True; - - return isBoundToFrontier( theRefNodeId, anEdgeId, theStopLinkId, aTriId ); } } @@ -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] ) diff --git a/src/BRepMesh/BRepMesh_Delaun.hxx b/src/BRepMesh/BRepMesh_Delaun.hxx index f03a333a11..5038e89bd8 100755 --- a/src/BRepMesh/BRepMesh_Delaun.hxx +++ b/src/BRepMesh/BRepMesh_Delaun.hxx @@ -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 index 0000000000..f9497951fa --- /dev/null +++ b/tests/bugs/mesh/bug31378 @@ -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