0023631: Infinite memory consumption in BRepMesh
authoroan <oan@opencascade.com>
Thu, 19 Jun 2014 09:23:53 +0000 (13:23 +0400)
committerapn <apn@opencascade.com>
Thu, 19 Jun 2014 09:26:20 +0000 (13:26 +0400)
Check is the shape to be meshed has correct poly data, i.e. PolygonOnTriangulation of particular edge connected to the same Triangulation data structure as stored inside a parent face.
Adding test cases for issue CR23631 bugs/mesh/bug23631
Parallel checking of faces/edges
Make BRepMesh_IncrementalMesh class imported from BRepMesh package.
Resolve GCC warnings on Linux platform
Fix compilation errors on MacOs: remove mutable modificator on reference fields.

src/BRepMesh/BRepMesh.cdl
src/BRepMesh/BRepMesh_EdgeChecker.hxx [new file with mode: 0644]
src/BRepMesh/BRepMesh_FaceChecker.hxx [new file with mode: 0644]
src/BRepMesh/BRepMesh_IncrementalMesh.cdl [deleted file]
src/BRepMesh/BRepMesh_IncrementalMesh.cxx
src/BRepMesh/BRepMesh_IncrementalMesh.hxx [new file with mode: 0644]
src/BRepMesh/FILES
tests/bugs/mesh/bug23631 [new file with mode: 0644]

index dcca4c2..52fe7b3 100644 (file)
@@ -89,6 +89,8 @@ is    enumeration DegreeOfFreedom is
       imported VertexInspector from BRepMesh;
       imported VertexCellFilter from BRepMesh;
       imported VectorOfVertex from BRepMesh;
+      imported EdgeChecker from BRepMesh;
+      imported FaceChecker from BRepMesh;
 
       primitive PluginEntryType;
 
@@ -166,7 +168,8 @@ is    enumeration DegreeOfFreedom is
       private class Classifier;
       imported ClassifierPtr; -- smart pointer on Classifier
 
-      class IncrementalMesh from BRepMesh;
+      imported IncrementalMesh from BRepMesh;
+
 
          ---- classes moved from MeshShape
       class GeomTool;
diff --git a/src/BRepMesh/BRepMesh_EdgeChecker.hxx b/src/BRepMesh/BRepMesh_EdgeChecker.hxx
new file mode 100644 (file)
index 0000000..8cc3a53
--- /dev/null
@@ -0,0 +1,82 @@
+// Created on: 2014-05-28
+// Created by: Oleg AGASHIN
+// Copyright (c) 2011-2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMesh_EdgeChecker_HeaderFile
+#define _BRepMesh_EdgeChecker_HeaderFile
+
+#include <Standard.hxx>
+#include <Standard_Mutex.hxx>
+#include <Poly_Triangulation.hxx>
+#include <TopLoc_Location.hxx>
+#include <TopoDS_Edge.hxx>
+#include <Poly_PolygonOnTriangulation.hxx>
+#include <BRep_Tool.hxx>
+
+//! Auxilary class implementing functionality for checking consistency 
+//! of polygon on triangulation of the given edge.
+class BRepMesh_EdgeChecker
+{
+public:
+
+  //! Constructor
+  //! \param theFaceTri Poly triangulation of face the edges relie to.
+  //! \param theFaceLoc Face location to be used to extract polygon on triangulation.
+  //! \param theMutex Upper level shared mutex to protect isFailed flag from concurrent write access.
+  //! \param isFailed Upper level shared flag indicating that polygon on triangulation of checked 
+  //! edge is not consistent. If this flag is set to TRUE, other tasks will not check details of their data.
+  BRepMesh_EdgeChecker( Handle(Poly_Triangulation)& theFaceTri,
+                        TopLoc_Location&            theFaceLoc,
+                        Standard_Mutex&             theMutex,
+                        Standard_Boolean&           isFailed)
+    : myMutex(theMutex),
+      myIsFailed(isFailed),
+      myFaceLoc(theFaceLoc),
+      myFaceTri(theFaceTri)
+  {
+  }
+
+  //! Checker's body.
+  //! \param theEdge edge to be checked.
+  void operator ()(const TopoDS_Edge& theEdge) const
+  {
+    if (theEdge.IsNull() || myIsFailed)
+      return;
+
+    const Handle(Poly_PolygonOnTriangulation)& aPoly =
+      BRep_Tool::PolygonOnTriangulation(theEdge, myFaceTri, myFaceLoc);
+
+    if (!aPoly.IsNull())
+      return;
+
+    // Trianglulation stored inside a face is different 
+    // than the one an edge data connected to.
+    Standard_Mutex::Sentry aSentry(myMutex);
+    myIsFailed = Standard_True;
+  }
+
+private:
+
+  void operator =(const BRepMesh_EdgeChecker& /*theOther*/)
+  {
+  }
+
+private:
+  Standard_Mutex&             myMutex;
+  Standard_Boolean&           myIsFailed;
+  TopLoc_Location&            myFaceLoc;
+  Handle(Poly_Triangulation)& myFaceTri;
+};
+
+#endif
diff --git a/src/BRepMesh/BRepMesh_FaceChecker.hxx b/src/BRepMesh/BRepMesh_FaceChecker.hxx
new file mode 100644 (file)
index 0000000..613ceb1
--- /dev/null
@@ -0,0 +1,99 @@
+// Created on: 2014-05-28
+// Created by: Oleg AGASHIN
+// Copyright (c) 2011-2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMesh_FaceChecker_HeaderFile
+#define _BRepMesh_FaceChecker_HeaderFile
+
+#include <Standard.hxx>
+#include <Standard_Mutex.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopLoc_Location.hxx>
+#include <Poly_Triangulation.hxx>
+#include <TopExp_Explorer.hxx>
+#include <BRepMesh_EdgeChecker.hxx>
+
+#include <vector>
+
+#ifdef HAVE_TBB
+  // paralleling using Intel TBB
+  #include <tbb/parallel_for_each.h>
+#endif
+
+//! Auxilary class implementing functionality for 
+//! checking consistency of triangulation on the given face.
+class BRepMesh_FaceChecker
+{
+public:
+
+  //! Constructor
+  //! \param isInParallel Flag indicates that face edges should be checked in parallel.
+  BRepMesh_FaceChecker(const Standard_Boolean isInParallel)
+    : myIsFailed(Standard_False),
+      myIsInParallel(isInParallel)
+  {
+  }
+
+  //! Checker's body.
+  //! \param theFace Face to be checked.
+  void operator ()(const TopoDS_Face& theFace) const
+  {
+    if (theFace.IsNull() || myIsFailed)
+      return;
+
+    TopLoc_Location aFaceLoc;
+    Handle(Poly_Triangulation) aFaceT =
+      BRep_Tool::Triangulation(theFace, aFaceLoc);
+
+    if (aFaceT.IsNull())
+      return;
+
+    std::vector<TopoDS_Edge> aEdges;
+    TopExp_Explorer aEdgeIt(theFace, TopAbs_EDGE);
+    for ( ; aEdgeIt.More(); aEdgeIt.Next())
+      aEdges.push_back(TopoDS::Edge(aEdgeIt.Current()));
+
+    BRepMesh_EdgeChecker aEdgeChecker(aFaceT, aFaceLoc, myMutex, myIsFailed);
+    if (myIsInParallel)
+    {
+    #ifdef HAVE_TBB
+      // check faces in parallel threads using TBB
+      tbb::parallel_for_each(aEdges.begin(), aEdges.end(), aEdgeChecker);
+    #else
+      // alternative parallelization not yet available
+      for (std::vector<TopoDS_Edge>::iterator it(aEdges.begin()); it != aEdges.end(); it++)
+        aEdgeChecker(*it);
+    #endif
+    }
+    else
+    {
+      for (std::vector<TopoDS_Edge>::iterator it(aEdges.begin()); it != aEdges.end(); it++)
+        aEdgeChecker(*it);
+    }
+  }
+
+  //! Returns status of the check.
+  Standard_Boolean IsValid() const 
+  {
+    return !myIsFailed;
+  }
+
+private:
+  mutable Standard_Mutex   myMutex;
+  mutable Standard_Boolean myIsFailed;
+  Standard_Boolean         myIsInParallel;
+};
+
+#endif
diff --git a/src/BRepMesh/BRepMesh_IncrementalMesh.cdl b/src/BRepMesh/BRepMesh_IncrementalMesh.cdl
deleted file mode 100644 (file)
index 218a812..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
--- Created on: 1995-06-20
--- Created by: Stagiaire Alain JOURDAIN <ajo@phobox>
--- Copyright (c) 1995-1999 Matra Datavision
--- Copyright (c) 1999-2014 OPEN CASCADE SAS
---
--- This file is part of Open CASCADE Technology software library.
---
--- This library is free software; you can redistribute it and/or modify it under
--- the terms of the GNU Lesser General Public License version 2.1 as published
--- by the Free Software Foundation, with special exception defined in the file
--- OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
--- distribution for complete text of the license and disclaimer of any warranty.
---
--- Alternatively, this file may be used under the terms of Open CASCADE
--- commercial license or contractual agreement.
-
-class IncrementalMesh from BRepMesh
-
-inherits DiscretRoot from BRepMesh
-
-    ---Purpose: Builds the mesh of a shape with respect of their
-    --          correctly triangulated parts.
-    --          Meshes faces from a Shape only if necessary.
-
-uses
-    Box from Bnd,
-    Shape from TopoDS,
-    Face  from TopoDS,
-    Edge  from TopoDS,
-    MapOfShape  from TopTools,
-    IndexedDataMapOfShapeListOfShape from TopTools,
-    DataMapOfShapeReal from TopTools,
-    FastDiscret  from BRepMesh,
-    Status       from BRepMesh,
-    PDiscretRoot from BRepMesh
-
-is
-    Create
-        returns IncrementalMesh from BRepMesh;
-    ---C++: alias "Standard_EXPORT virtual ~BRepMesh_IncrementalMesh();"
-
-    Create (S          : Shape   from TopoDS;
-            D          : Real    from Standard;
-            Relatif    : Boolean from Standard = Standard_False;
-            Ang        : Real    from Standard = 0.5;
-            InParallel : Boolean from Standard = Standard_False)
-        returns IncrementalMesh from BRepMesh;
-    ---Purpose: If the  boolean    <Relatif>   is  True,    the
-    --          deflection used   for the polygonalisation   of
-    --          each edge will be <D> * Size of Edge.
-    --          the deflection used for the faces will be the maximum
-    --          deflection of their edges.
-
-    SetRelative (     me : mutable;
-                 theFlag : Boolean from Standard);
-
-    Relative (me)
-        returns Boolean from Standard;
-
-    Init (me : mutable)
-        is redefined protected;
-
-    Perform (me : mutable)
-        is redefined;
-
-    Update (me : mutable;
-             S : Shape from TopoDS)
-        is static;
-    ---Purpose: Builds the incremental mesh of the shape
-
-    IsModified (me)
-        returns Boolean from Standard
-        is static;
-
-    Update (me : mutable;
-            E  : Edge from TopoDS)
-        is static private;
-    ---Purpose: Locate a correct discretisation if it exists
-    --          Set no one otherwise
-
-    Update (me : mutable;
-            F  : Face from TopoDS)
-        is static private;
-    ---Purpose: If the face is  not correctly triangulated, or
-    --          if  one  of its edges  is  to be discretisated
-    --          correctly, the triangulation  of this face  is
-    --          built.
-
-    GetStatusFlags (me)
-        returns Integer from Standard
-        is static;
-
-    SetParallel (           me : mutable;
-                 theInParallel : Boolean from Standard);
-    ---Purpose:
-    -- Request algorithm to launch in multiple threads to improve performance.
-
-    IsParallel (me)
-        returns Boolean from Standard;
-    ---Purpose:
-    -- Returns the multi-threading usage flag.
-
-    --
-    --  Plugin interface
-    --
-    Discret (myclass;
-             theShape      : Shape from TopoDS;
-             theDeflection : Real from Standard;
-             theAngle      : Real from Standard;
-             theAlgo       : out PDiscretRoot from BRepMesh)
-        returns Integer from Standard;
-    ---Purpose:
-    -- Plugin interface for the Mesh Factories.
-
-    IsParallelDefault (myclass)
-        returns Boolean from Standard;
-    ---Purpose:
-    -- Returns multi-threading usage flag set by default in
-    -- Discret() static method (thus applied only to Mesh Factories).
-
-    SetParallelDefault (myclass;
-                        theInParallel : Boolean from Standard);
-    ---Purpose:
-    -- Setup multi-threading usage flag set by default in
-    -- Discret() static method (thus applied only to Mesh Factories).
-
-fields
-    myRelative   : Boolean     from Standard is protected;
-    myInParallel : Boolean     from Standard is protected;
-    myMap        : MapOfShape  from TopTools is protected;
-    myMesh       : FastDiscret from BRepMesh is protected;
-    myModified   : Boolean     from Standard is protected;
-    mymapedge    : DataMapOfShapeReal from TopTools is protected;
-    myancestors  : IndexedDataMapOfShapeListOfShape from TopTools is protected;
-    mydtotale    : Real from Standard is protected;
-    myBox        : Box  from Bnd is protected;
-    myStatus     : Integer from Standard is protected;
-
-end IncrementalMesh;
index 194d75a..09cca19 100644 (file)
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
 
-#include <BRepMesh_IncrementalMesh.ixx>
+#include <BRepMesh_IncrementalMesh.hxx>
 
 #include <BRepMesh.hxx>
 #include <BRepMesh_Edge.hxx>
 #include <BRepMesh_Triangle.hxx>
+#include <BRepMesh_FastDiscret.hxx>
 #include <BRepMesh_FastDiscretFace.hxx>
 #include <BRepMesh_PluginMacro.hxx>
 
 #include <Bnd_Box.hxx>
 #include <BRep_Builder.hxx>
 #include <BRep_Tool.hxx>
+#include <BRepTools.hxx>
 #include <BRepLib.hxx>
 #include <BRepBndLib.hxx>
 #include <BRepAdaptor_Curve.hxx>
@@ -45,8 +47,8 @@
 #include <Poly_Triangulation.hxx>
 #include <Poly_Polygon3D.hxx>
 #include <Poly_PolygonOnTriangulation.hxx>
-
-#include <vector>
+#include <Standard_Mutex.hxx>
+#include <BRepMesh_FaceChecker.hxx>
 
 #ifdef HAVE_TBB
   // paralleling using Intel TBB
@@ -60,18 +62,47 @@ namespace
   static Standard_Boolean IS_IN_PARALLEL = Standard_False;
 };
 
+IMPLEMENT_STANDARD_HANDLE (BRepMesh_IncrementalMesh, BRepMesh_DiscretRoot)
+IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_IncrementalMesh, BRepMesh_DiscretRoot)
+
+//=======================================================================
+//function : isCorrectPolyData
+//purpose  : 
+//=======================================================================
+Standard_Boolean BRepMesh_IncrementalMesh::isCorrectPolyData()
+{
+  collectFaces();
+
+  BRepMesh_FaceChecker aFaceChecker(myInParallel);
+  if (myInParallel)
+  {
+  #ifdef HAVE_TBB
+    // check faces in parallel threads using TBB
+    tbb::parallel_for_each(myFaces.begin(), myFaces.end(), aFaceChecker);
+  #else
+    // alternative parallelization not yet available
+    for (std::vector<TopoDS_Face>::iterator it(myFaces.begin()); it != myFaces.end(); it++)
+      aFaceChecker(*it);
+  #endif
+  }
+  else
+  {
+    for (std::vector<TopoDS_Face>::iterator it(myFaces.begin()); it != myFaces.end(); it++)
+      aFaceChecker(*it);
+  }
+
+  return aFaceChecker.IsValid();
+}
+
 //=======================================================================
 //function : BRepMesh_IncrementalMesh
 //purpose  : 
 //=======================================================================
 BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh() 
 : myRelative (Standard_False),
-  myInParallel (Standard_False),
-  myModified (Standard_False),
-  myStatus (0)
+  myInParallel (Standard_False)
 {
-  mymapedge.Clear();
-  myancestors.Clear();
+  Init();
 }
 
 //=======================================================================
@@ -82,14 +113,11 @@ BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh (const TopoDS_Shape& theShape
                                                     const Standard_Real theDeflection,
                                                     const Standard_Boolean theRelative,
                                                     const Standard_Real theAngle,
-                                                                                                       const Standard_Boolean theInParallel)
+                                                    const Standard_Boolean theInParallel)
 : myRelative (theRelative),
-  myInParallel (theInParallel),
-  myModified (Standard_False),
-  myStatus (0)
+  myInParallel (theInParallel)
 {
-  mymapedge.Clear();
-  myancestors.Clear();
+  Init();
   myDeflection = theDeflection;
   myAngle = theAngle;
   myShape = theShape;
@@ -130,9 +158,11 @@ Standard_Boolean BRepMesh_IncrementalMesh::IsParallel() const
 //=======================================================================
 void BRepMesh_IncrementalMesh::Init() 
 {
-  myModified=Standard_False;
+  myStatus = 0;
+  myModified = Standard_False;
   mymapedge.Clear();
   myancestors.Clear();
+  myFaces.clear();
 }
 
 //=======================================================================
@@ -141,7 +171,7 @@ void BRepMesh_IncrementalMesh::Init()
 //=======================================================================
 void BRepMesh_IncrementalMesh::SetRelative(const Standard_Boolean theFlag)
 {
-  myRelative=theFlag;
+  myRelative = theFlag;
 }
 
 //=======================================================================
@@ -168,12 +198,15 @@ Standard_Boolean BRepMesh_IncrementalMesh::IsModified() const
 //=======================================================================
 void BRepMesh_IncrementalMesh::Perform()
 {
+  Init(); 
+
+  if (!isCorrectPolyData())
+    BRepTools::Clean(myShape);
+
   Bnd_Box aBox;
   //
   SetDone();
   //
-  Init(); 
-  //
   BRepBndLib::Add(myShape, aBox);
   myBox = aBox;
   //
@@ -202,6 +235,37 @@ Standard_Integer BRepMesh_IncrementalMesh::GetStatusFlags() const
 }
 
 //=======================================================================
+//function : collectFaces
+//purpose  : 
+//=======================================================================
+void BRepMesh_IncrementalMesh::collectFaces()
+{
+  TopTools_ListOfShape aFaceList;
+  BRepLib::ReverseSortFaces(myShape, aFaceList);
+  TopTools_MapOfShape aFaceMap;
+  myFaces.reserve(aFaceList.Extent());
+
+  // make array of faces suitable for processing (excluding faces without surface)
+  TopLoc_Location aDummyLoc;
+  const TopLoc_Location aEmptyLoc;
+  TopTools_ListIteratorOfListOfShape aFaceIter(aFaceList);
+  for (; aFaceIter.More(); aFaceIter.Next())
+  {
+    TopoDS_Shape aFaceNoLoc = aFaceIter.Value();
+    aFaceNoLoc.Location(aEmptyLoc);
+    if (!aFaceMap.Add (aFaceNoLoc))
+      continue; // already processed
+
+    TopoDS_Face aFace = TopoDS::Face(aFaceIter.Value());
+    const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(aFace, aDummyLoc);
+    if (aSurf.IsNull())
+      continue;
+
+    myFaces.push_back(aFace);
+  }
+}
+
+//=======================================================================
 //function : Update(shape)
 //purpose  : Builds the incremental mesh of the shape
 //=======================================================================
@@ -225,49 +289,26 @@ void BRepMesh_IncrementalMesh::Update(const TopoDS_Shape& S)
   }
 
   // get list of faces
-  std::vector<TopoDS_Face> aFaces;
-  {
-    TopTools_ListOfShape aFaceList;
-    BRepLib::ReverseSortFaces (S, aFaceList);
-    TopTools_MapOfShape aFaceMap;
-    aFaces.reserve (aFaceList.Extent());
-
-    // make array of faces suitable for processing (excluding faces without surface)
-    TopLoc_Location aDummyLoc;
-    const TopLoc_Location anEmptyLoc;
-    for (TopTools_ListIteratorOfListOfShape aFaceIter (aFaceList); aFaceIter.More(); aFaceIter.Next())
-    {
-      TopoDS_Shape aFaceNoLoc = aFaceIter.Value();
-      aFaceNoLoc.Location (anEmptyLoc);
-      if (!aFaceMap.Add (aFaceNoLoc))
-        continue; // already processed
-
-      TopoDS_Face aFace = TopoDS::Face (aFaceIter.Value());
-      const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface (aFace, aDummyLoc);
-      if (aSurf.IsNull())
-        continue;
-
-      Update (aFace);
-      aFaces.push_back (aFace);
-    }
-  }
+  std::vector<TopoDS_Face>::iterator aFaceIt(myFaces.begin());
+  for (; aFaceIt != myFaces.end(); aFaceIt++)
+    Update(*aFaceIt);
 
   if (myInParallel)
   {
   #ifdef HAVE_TBB
     myMesh->CreateMutexesForSubShapes(S, TopAbs_EDGE);
     // mesh faces in parallel threads using TBB
-    tbb::parallel_for_each (aFaces.begin(), aFaces.end(), *myMesh.operator->());
+    tbb::parallel_for_each (myFaces.begin(), myFaces.end(), *myMesh.operator->());
   #else
     // alternative parallelization not yet available
-    for (std::vector<TopoDS_Face>::iterator it(aFaces.begin()); it != aFaces.end(); it++)
+    for (std::vector<TopoDS_Face>::iterator it(myFaces.begin()); it != myFaces.end(); it++)
       myMesh->Process (*it);
   #endif
     myMesh->RemoveAllMutexes();
   }
   else
   {
-    for (std::vector<TopoDS_Face>::iterator it(aFaces.begin()); it != aFaces.end(); it++)
+    for (std::vector<TopoDS_Face>::iterator it(myFaces.begin()); it != myFaces.end(); it++)
       myMesh->Process (*it);
   }
 
diff --git a/src/BRepMesh/BRepMesh_IncrementalMesh.hxx b/src/BRepMesh/BRepMesh_IncrementalMesh.hxx
new file mode 100644 (file)
index 0000000..2e3212f
--- /dev/null
@@ -0,0 +1,135 @@
+// Copyright (c) 2013 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMesh_IncrementalMesh_HeaderFile
+#define _BRepMesh_IncrementalMesh_HeaderFile
+
+#include <Standard.hxx>
+#include <Standard_DefineHandle.hxx>
+
+#include <Handle_BRepMesh_FastDiscret.hxx>
+#include <TopTools_MapOfShape.hxx>
+#include <TopTools_DataMapOfShapeReal.hxx>
+#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
+#include <Bnd_Box.hxx>
+#include <BRepMesh_DiscretRoot.hxx>
+#include <BRepMesh_PDiscretRoot.hxx>
+
+#include <vector>
+
+class BRepMesh_FastDiscret;
+class TopoDS_Shape;
+class TopoDS_Edge;
+class TopoDS_Face;
+
+//! Builds the mesh of a shape with respect of their <br>
+//! correctly triangulated parts <br>
+//! <br>
+class BRepMesh_IncrementalMesh : public BRepMesh_DiscretRoot {
+
+public:
+
+  Standard_EXPORT   BRepMesh_IncrementalMesh();
+
+  Standard_EXPORT virtual ~BRepMesh_IncrementalMesh();
+
+  //! If the boolean flag <isRelative> is TRUE, the <br>
+  //! deflection used for the polygonalisation of <br>
+  //! each edge will be <theLinDeflection> * Size of Edge. <br>
+  //! the deflection used for the faces will be the maximum <br>
+  //! deflection of their edges. <br>
+  Standard_EXPORT BRepMesh_IncrementalMesh(const TopoDS_Shape&    theShape,
+                                           const Standard_Real    theLinDeflection,
+                                           const Standard_Boolean isRelative       = Standard_False,
+                                           const Standard_Real    theAngDeflection = 0.5,
+                                           const Standard_Boolean isInParallel     = Standard_False);
+  
+  Standard_EXPORT void SetRelative(const Standard_Boolean theFlag);
+  
+  Standard_EXPORT Standard_Boolean Relative() const;
+  
+  Standard_EXPORT virtual void Perform();
+
+  //! Builds the incremental mesh of the shape <br>
+  Standard_EXPORT void Update(const TopoDS_Shape& theShape);
+  
+  Standard_EXPORT Standard_Boolean IsModified() const;
+  
+  Standard_EXPORT Standard_Integer GetStatusFlags() const;
+  
+  //! Request algorithm to launch in multiple threads to improve performance. <br>
+  Standard_EXPORT void SetParallel(const Standard_Boolean isInParallel);
+  
+  //! Returns the multi-threading usage flag. <br>
+  Standard_EXPORT Standard_Boolean IsParallel() const;
+  
+  //! Plugin interface for the Mesh Factories. <br>
+  Standard_EXPORT static Standard_Integer Discret(const TopoDS_Shape&    theShape,
+                                                  const Standard_Real    theLinDeflection,
+                                                  const Standard_Real    theAngDeflection,
+                                                  BRepMesh_PDiscretRoot& theAlgo);
+  
+  //! Returns multi-threading usage flag set by default in <br>
+  //! Discret() static method (thus applied only to Mesh Factories). <br>
+  Standard_EXPORT static Standard_Boolean IsParallelDefault();
+  
+  //! Setup multi-threading usage flag set by default in <br>
+  //! Discret() static method (thus applied only to Mesh Factories). <br>
+  Standard_EXPORT static void SetParallelDefault(const Standard_Boolean isInParallel) ;
+
+
+  DEFINE_STANDARD_RTTI(BRepMesh_IncrementalMesh)
+
+protected:
+
+  Standard_EXPORT virtual void Init();
+
+  //! Collects faces suitable for meshing.
+  Standard_EXPORT void collectFaces();
+
+protected:
+
+  Standard_Boolean                          myRelative;
+  Standard_Boolean                          myInParallel;
+  TopTools_MapOfShape                       myMap;
+  Handle_BRepMesh_FastDiscret               myMesh;
+  Standard_Boolean                          myModified;
+  TopTools_DataMapOfShapeReal               mymapedge;
+  TopTools_IndexedDataMapOfShapeListOfShape myancestors;
+  Standard_Real                             mydtotale;
+  Bnd_Box                                   myBox;
+  Standard_Integer                          myStatus;
+  std::vector<TopoDS_Face>                  myFaces;
+
+private:
+  //! Checks is the shape to be meshed has correct poly data, <br>
+  //! i.e. PolygonOnTriangulation of particular edge connected <br>
+  //! to the same Triangulation data structure as stored inside <br>
+  //! a parent face. <br>
+  Standard_Boolean isCorrectPolyData();
+
+  //! Locate a correct discretisation if it exists <br>
+  //! Set no one otherwise <br>
+  void Update(const TopoDS_Edge& theEdge);
+
+  //! If the face is not correctly triangulated, or if one <br>
+  //! of its edges is to be discretisated correctly, the <br>
+  //! triangulation of this face is built. <br>
+  void Update(const TopoDS_Face& theFace);
+};
+
+DEFINE_STANDARD_HANDLE(BRepMesh_IncrementalMesh,BRepMesh_DiscretRoot)
+
+// other Inline functions and methods (like "C++: function call" methods)
+
+#endif
index 2be4e8f..9d80a5d 100755 (executable)
@@ -18,4 +18,8 @@ BRepMesh_VertexCellFilter.hxx
 BRepMesh_VertexInspector.hxx
 BRepMesh_VertexInspector.cxx
 BRepMesh_VectorOfVertex.hxx
+BRepMesh_EdgeChecker.hxx
+BRepMesh_FaceChecker.hxx
+BRepMesh_IncrementalMesh.hxx
+BRepMesh_IncrementalMesh.cxx
 EXTERNLIB
diff --git a/tests/bugs/mesh/bug23631 b/tests/bugs/mesh/bug23631
new file mode 100644 (file)
index 0000000..e80c600
--- /dev/null
@@ -0,0 +1,37 @@
+puts "========"
+puts "OCC23631"
+puts "========"
+puts ""
+###########################################
+## Infinite memory consumption in BRepMesh
+###########################################
+
+set BugNumber 23631
+
+restore [locate_data_file OCC396_f2903.brep] result
+
+incmesh result 0.01
+triangles result 
+
+set tri 0
+set nod 0
+
+set good_tri 31
+set good_nod 33
+
+set tri_info [trinfo result]
+regexp { +([-0-9.+eE]+) +triangles} $tri_info full tri
+regexp { +([-0-9.+eE]+) +nodes} $tri_info full nod
+
+if { ${tri} == ${good_tri} && ${nod} == ${good_nod} } {
+    puts "Bug ${BugNumber} shading: OK"
+} else {
+    puts "Bug ${BugNumber} shading: Faulty"
+}
+
+vinit
+vdisplay result
+vfit
+vsetdispmode 1
+set only_screen 1
+