diff --git a/src/BRepMesh/BRepMesh.cdl b/src/BRepMesh/BRepMesh.cdl index dcca4c266a..52fe7b3b61 100644 --- a/src/BRepMesh/BRepMesh.cdl +++ b/src/BRepMesh/BRepMesh.cdl @@ -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 index 0000000000..8cc3a53b0b --- /dev/null +++ b/src/BRepMesh/BRepMesh_EdgeChecker.hxx @@ -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 +#include +#include +#include +#include +#include +#include + +//! 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 index 0000000000..613ceb13c2 --- /dev/null +++ b/src/BRepMesh/BRepMesh_FaceChecker.hxx @@ -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 +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef HAVE_TBB + // paralleling using Intel TBB + #include +#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 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::iterator it(aEdges.begin()); it != aEdges.end(); it++) + aEdgeChecker(*it); + #endif + } + else + { + for (std::vector::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 index 218a812b90..0000000000 --- a/src/BRepMesh/BRepMesh_IncrementalMesh.cdl +++ /dev/null @@ -1,139 +0,0 @@ --- Created on: 1995-06-20 --- Created by: Stagiaire Alain JOURDAIN --- 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 is True, the - -- deflection used for the polygonalisation of - -- each edge will be * 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; diff --git a/src/BRepMesh/BRepMesh_IncrementalMesh.cxx b/src/BRepMesh/BRepMesh_IncrementalMesh.cxx index 194d75a4bf..09cca193d7 100644 --- a/src/BRepMesh/BRepMesh_IncrementalMesh.cxx +++ b/src/BRepMesh/BRepMesh_IncrementalMesh.cxx @@ -14,17 +14,19 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. -#include +#include #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -45,8 +47,8 @@ #include #include #include - -#include +#include +#include #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::iterator it(myFaces.begin()); it != myFaces.end(); it++) + aFaceChecker(*it); + #endif + } + else + { + for (std::vector::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; // @@ -201,6 +234,37 @@ Standard_Integer BRepMesh_IncrementalMesh::GetStatusFlags() const return myStatus; } +//======================================================================= +//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 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::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::iterator it(aFaces.begin()); it != aFaces.end(); it++) + for (std::vector::iterator it(myFaces.begin()); it != myFaces.end(); it++) myMesh->Process (*it); #endif myMesh->RemoveAllMutexes(); } else { - for (std::vector::iterator it(aFaces.begin()); it != aFaces.end(); it++) + for (std::vector::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 index 0000000000..2e3212fa4a --- /dev/null +++ b/src/BRepMesh/BRepMesh_IncrementalMesh.hxx @@ -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 +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +class BRepMesh_FastDiscret; +class TopoDS_Shape; +class TopoDS_Edge; +class TopoDS_Face; + +//! Builds the mesh of a shape with respect of their
+//! correctly triangulated parts
+//!
+class BRepMesh_IncrementalMesh : public BRepMesh_DiscretRoot { + +public: + + Standard_EXPORT BRepMesh_IncrementalMesh(); + + Standard_EXPORT virtual ~BRepMesh_IncrementalMesh(); + + //! If the boolean flag is TRUE, the
+ //! deflection used for the polygonalisation of
+ //! each edge will be * Size of Edge.
+ //! the deflection used for the faces will be the maximum
+ //! deflection of their edges.
+ 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
+ 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.
+ Standard_EXPORT void SetParallel(const Standard_Boolean isInParallel); + + //! Returns the multi-threading usage flag.
+ Standard_EXPORT Standard_Boolean IsParallel() const; + + //! Plugin interface for the Mesh Factories.
+ 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
+ //! Discret() static method (thus applied only to Mesh Factories).
+ Standard_EXPORT static Standard_Boolean IsParallelDefault(); + + //! Setup multi-threading usage flag set by default in
+ //! Discret() static method (thus applied only to Mesh Factories).
+ 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 myFaces; + +private: + //! Checks 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.
+ Standard_Boolean isCorrectPolyData(); + + //! Locate a correct discretisation if it exists
+ //! Set no one otherwise
+ void Update(const TopoDS_Edge& theEdge); + + //! 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.
+ void Update(const TopoDS_Face& theFace); +}; + +DEFINE_STANDARD_HANDLE(BRepMesh_IncrementalMesh,BRepMesh_DiscretRoot) + +// other Inline functions and methods (like "C++: function call" methods) + +#endif diff --git a/src/BRepMesh/FILES b/src/BRepMesh/FILES index 2be4e8f617..9d80a5dfab 100755 --- a/src/BRepMesh/FILES +++ b/src/BRepMesh/FILES @@ -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 index 0000000000..e80c600b9d --- /dev/null +++ b/tests/bugs/mesh/bug23631 @@ -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 +