From 4a913f21025f47f9ee63d60e447f1710ab5c1b29 Mon Sep 17 00:00:00 2001 From: msv Date: Fri, 28 Nov 2014 13:03:57 +0300 Subject: [PATCH] 0025503: BRepMesh - IncrementalMesh always re-meshes the shape even if existing triangulation satisfies the given deflection Test case for issue CR25503 Correction of test cases for issue CR25503 --- src/BRepMesh/BRepMesh.hxx | 4 +- src/BRepMesh/BRepMesh_EdgeChecker.hxx | 82 -------------- src/BRepMesh/BRepMesh_FaceChecker.hxx | 98 ---------------- src/BRepMesh/BRepMesh_IncrementalMesh.cxx | 132 +++++++++------------- src/BRepMesh/BRepMesh_IncrementalMesh.hxx | 25 ++-- src/BRepMesh/FILES | 2 - tests/bugs/mesh/bug25503_1 | 19 ++++ tests/bugs/mesh/bug25503_2 | 23 ++++ tests/mesh/data/standard/M1 | 3 +- 9 files changed, 108 insertions(+), 280 deletions(-) delete mode 100644 src/BRepMesh/BRepMesh_EdgeChecker.hxx delete mode 100644 src/BRepMesh/BRepMesh_FaceChecker.hxx create mode 100644 tests/bugs/mesh/bug25503_1 create mode 100755 tests/bugs/mesh/bug25503_2 diff --git a/src/BRepMesh/BRepMesh.hxx b/src/BRepMesh/BRepMesh.hxx index 121abdd1c6..139e3804b0 100644 --- a/src/BRepMesh/BRepMesh.hxx +++ b/src/BRepMesh/BRepMesh.hxx @@ -94,7 +94,7 @@ namespace BRepMesh //! Maps typedef NCollection_Map MapOfInteger; - typedef NCollection_Map MapOfTriangulation; + typedef NCollection_DataMap DMapOfTriangulationBool; typedef NCollection_Map MapOfShape; typedef NCollection_DataMap MapOfIntegerInteger; @@ -104,7 +104,7 @@ namespace BRepMesh typedef NCollection_DataMap DMapOfIntegerPnt; typedef NCollection_DataMap DMapOfIntegerListOfXY; typedef NCollection_DataMap DMapOfIntegerListOfInteger; - typedef NCollection_DataMap DMapOfEdgeListOfTriangulation; + typedef NCollection_DataMap DMapOfEdgeListOfTriangulationBool; typedef NCollection_IndexedMap IMapOfInteger; typedef NCollection_IndexedMap IMapOfReal; diff --git a/src/BRepMesh/BRepMesh_EdgeChecker.hxx b/src/BRepMesh/BRepMesh_EdgeChecker.hxx deleted file mode 100644 index f5587088cf..0000000000 --- a/src/BRepMesh/BRepMesh_EdgeChecker.hxx +++ /dev/null @@ -1,82 +0,0 @@ -// 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 deleted file mode 100644 index 350e3453ca..0000000000 --- a/src/BRepMesh/BRepMesh_FaceChecker.hxx +++ /dev/null @@ -1,98 +0,0 @@ -// 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 - -#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); -#ifdef HAVE_TBB - if (myIsInParallel) - { - // check faces in parallel threads using TBB - tbb::parallel_for_each(aEdges.begin(), aEdges.end(), aEdgeChecker); - } - else - { -#endif - for (std::vector::iterator it(aEdges.begin()); it != aEdges.end(); it++) - aEdgeChecker(*it); -#ifdef HAVE_TBB - } -#endif - } - - //! 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.cxx b/src/BRepMesh/BRepMesh_IncrementalMesh.cxx index 9c614e9fb4..358a44b56a 100644 --- a/src/BRepMesh/BRepMesh_IncrementalMesh.cxx +++ b/src/BRepMesh/BRepMesh_IncrementalMesh.cxx @@ -19,7 +19,6 @@ #include #include -#include #include #include #include @@ -112,7 +111,7 @@ BRepMesh_IncrementalMesh::~BRepMesh_IncrementalMesh() //======================================================================= void BRepMesh_IncrementalMesh::clear() { - myEmptyEdges.Clear(); + myEdges.Clear(); myEdgeDeflection.Clear(); myFaces.Clear(); myMesh.Nullify(); @@ -130,8 +129,7 @@ void BRepMesh_IncrementalMesh::init() setDone(); clear(); - if (!isCorrectPolyData()) - BRepTools::Clean(myShape); + collectFaces(); Bnd_Box aBox; BRepBndLib::Add(myShape, aBox, Standard_False); @@ -150,35 +148,6 @@ void BRepMesh_IncrementalMesh::init() myMesh->InitSharedFaces(myShape); } -//======================================================================= -//function : isCorrectPolyData -//purpose : -//======================================================================= -Standard_Boolean BRepMesh_IncrementalMesh::isCorrectPolyData() -{ - collectFaces(); - - BRepMesh_FaceChecker aFaceChecker(myInParallel); - -#ifdef HAVE_TBB - if (myInParallel) - { - // check faces in parallel threads using TBB - tbb::parallel_for_each(myFaces.begin(), myFaces.end(), aFaceChecker); - } - else - { -#endif - NCollection_Vector::Iterator aFaceIt(myFaces); - for (; aFaceIt.More(); aFaceIt.Next()) - aFaceChecker(aFaceIt.Value()); -#ifdef HAVE_TBB - } -#endif - - return aFaceChecker.IsValid(); -} - //======================================================================= //function : collectFaces //purpose : @@ -357,59 +326,46 @@ Standard_Real BRepMesh_IncrementalMesh::faceDeflection( //======================================================================= void BRepMesh_IncrementalMesh::update(const TopoDS_Edge& theEdge) { - Standard_Integer aPolyIndex = 1; + if (!myEdges.IsBound(theEdge)) + myEdges.Bind(theEdge, BRepMesh::DMapOfTriangulationBool()); + Standard_Real aEdgeDeflection = edgeDeflection(theEdge); - Handle(Poly_PolygonOnTriangulation) aPolygon; - do + // Check that triangulation relies to face of the given shape. + const TopTools_IndexedDataMapOfShapeListOfShape& aMapOfSharedFaces = + myMesh->SharedFaces(); + + const TopTools_ListOfShape& aSharedFaces = + aMapOfSharedFaces.FindFromKey(theEdge); + + TopTools_ListIteratorOfListOfShape aSharedFaceIt(aSharedFaces); + for (; aSharedFaceIt.More(); aSharedFaceIt.Next()) { TopLoc_Location aLoc; - Handle(Poly_Triangulation) aTriangulation; - BRep_Tool::PolygonOnTriangulation(theEdge, aPolygon, - aTriangulation, aLoc, aPolyIndex++); - - if (!aTriangulation.IsNull() && !aPolygon.IsNull()) - { - if (aPolygon->Deflection() < 1.1 * aEdgeDeflection && - aPolygon->HasParameters()) - { - continue; - } - else - { - // Check that triangulation relies to face of the given shape. - const TopTools_IndexedDataMapOfShapeListOfShape& aMapOfSharedFaces = - myMesh->SharedFaces(); + const TopoDS_Face& aFace = TopoDS::Face(aSharedFaceIt.Value()); + const Handle(Poly_Triangulation)& aFaceTriangulation = + BRep_Tool::Triangulation(aFace, aLoc); - const TopTools_ListOfShape& aSharedFaces = - aMapOfSharedFaces.FindFromKey(theEdge); + if (aFaceTriangulation.IsNull()) + continue; - Standard_Boolean isCurrentShape = Standard_False; - TopTools_ListIteratorOfListOfShape aSharedFaceIt(aSharedFaces); - for (; aSharedFaceIt.More() && !isCurrentShape; aSharedFaceIt.Next()) - { - TopLoc_Location aLoc; - const TopoDS_Face& aFace = TopoDS::Face(aSharedFaceIt.Value()); - Handle(Poly_Triangulation) aFaceTriangulation = - BRep_Tool::Triangulation(aFace, aLoc); + Standard_Boolean isConsistent = Standard_False; + const Handle(Poly_PolygonOnTriangulation)& aPolygon = + BRep_Tool::PolygonOnTriangulation(theEdge, aFaceTriangulation, aLoc); - isCurrentShape = (aFaceTriangulation == aTriangulation); - } + if (!aPolygon.IsNull()) + { + isConsistent = aPolygon->Deflection() < 1.1 * aEdgeDeflection && + aPolygon->HasParameters(); - if (!isCurrentShape) - continue; + if (!isConsistent) + { + myModified = Standard_True; + BRepMesh_ShapeTool::NullifyEdge(theEdge, aFaceTriangulation, aLoc); } - - myModified = Standard_True; - BRepMesh_ShapeTool::NullifyEdge(theEdge, aTriangulation, aLoc); } - if (!myEmptyEdges.IsBound(theEdge)) - myEmptyEdges.Bind(theEdge, BRepMesh::MapOfTriangulation()); - - if (!aTriangulation.IsNull()) - myEmptyEdges(theEdge).Add(aTriangulation); + myEdges(theEdge).Bind(aFaceTriangulation, isConsistent); } - while (!aPolygon.IsNull()); } //======================================================================= @@ -437,15 +393,33 @@ Standard_Boolean BRepMesh_IncrementalMesh::toBeMeshed( for (; aEdgeIt.More() && isEdgesConsistent; aEdgeIt.Next()) { const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Current()); - if (!myEmptyEdges.IsBound(aEdge)) + if (!myEdges.IsBound(aEdge)) continue; - BRepMesh::MapOfTriangulation& aTriMap = myEmptyEdges(aEdge); - isEdgesConsistent &= !aTriMap.IsEmpty() && !aTriMap.Contains(aTriangulation); + BRepMesh::DMapOfTriangulationBool& aTriMap = myEdges(aEdge); + isEdgesConsistent &= aTriMap.IsBound(aTriangulation) && + aTriMap(aTriangulation); } if (isEdgesConsistent) - return Standard_False; + { + // #25080: check that indices of links forming triangles are in range. + Standard_Boolean isTriangulationConsistent = Standard_True; + const Standard_Integer aNodesNb = aTriangulation->NbNodes(); + const Poly_Array1OfTriangle& aTriangles = aTriangulation->Triangles(); + Standard_Integer i = aTriangles.Lower(); + for (; i <= aTriangles.Upper() && isTriangulationConsistent; ++i) + { + const Poly_Triangle& aTriangle = aTriangles(i); + Standard_Integer n[3]; + aTriangle.Get(n[0], n[1], n[2]); + for (Standard_Integer j = 0; j < 3 && isTriangulationConsistent; ++j) + isTriangulationConsistent = (n[j] >= 1 && n[j] <= aNodesNb); + } + + if (isTriangulationConsistent) + return Standard_False; + } } } diff --git a/src/BRepMesh/BRepMesh_IncrementalMesh.hxx b/src/BRepMesh/BRepMesh_IncrementalMesh.hxx index dc0f3c1e26..879b9b8cf2 100644 --- a/src/BRepMesh/BRepMesh_IncrementalMesh.hxx +++ b/src/BRepMesh/BRepMesh_IncrementalMesh.hxx @@ -132,13 +132,6 @@ protected: 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. - //! @return TRUE on success, FALSE in case of inconsistencies. - Standard_Boolean isCorrectPolyData(); - //! Builds the incremental mesh for the shape. void update(); @@ -191,15 +184,15 @@ private: protected: - Standard_Boolean myRelative; - Standard_Boolean myInParallel; - BRepMesh::DMapOfEdgeListOfTriangulation myEmptyEdges; - Handle(BRepMesh_FastDiscret) myMesh; - Standard_Boolean myModified; - TopTools_DataMapOfShapeReal myEdgeDeflection; - Standard_Real myMaxShapeSize; - Standard_Integer myStatus; - NCollection_Vector myFaces; + Standard_Boolean myRelative; + Standard_Boolean myInParallel; + BRepMesh::DMapOfEdgeListOfTriangulationBool myEdges; + Handle(BRepMesh_FastDiscret) myMesh; + Standard_Boolean myModified; + TopTools_DataMapOfShapeReal myEdgeDeflection; + Standard_Real myMaxShapeSize; + Standard_Integer myStatus; + NCollection_Vector myFaces; }; DEFINE_STANDARD_HANDLE(BRepMesh_IncrementalMesh,BRepMesh_DiscretRoot) diff --git a/src/BRepMesh/FILES b/src/BRepMesh/FILES index 683eed9766..a0476779a0 100755 --- a/src/BRepMesh/FILES +++ b/src/BRepMesh/FILES @@ -33,8 +33,6 @@ BRepMesh_PairOfIndex.hxx BRepMesh_Status.hxx BRepMesh_CMPLRS.edl BRepMesh_VertexInspector.hxx -BRepMesh_EdgeChecker.hxx -BRepMesh_FaceChecker.hxx BRepMesh_SelectorOfDataStructureOfDelaun.hxx BRepMesh_SelectorOfDataStructureOfDelaun.cxx BRepMesh_EdgeParameterProvider.hxx diff --git a/tests/bugs/mesh/bug25503_1 b/tests/bugs/mesh/bug25503_1 new file mode 100644 index 0000000000..744889d3d3 --- /dev/null +++ b/tests/bugs/mesh/bug25503_1 @@ -0,0 +1,19 @@ +puts "============" +puts "CR25503" +puts "============" +puts "" +################################################################################### +# BRepMesh - IncrementalMesh always re-meshes the shape even if existing triangulation satisfies the given deflection +################################################################################### + +puts "===> meshing segment of sphere" +psphere a 100 -45 45 180 +puts "" +puts "incmesh first time" +set t1 [expr [lindex [time {incmesh a 0.003}] 0]/1000000] +puts "spent $t1 sec" +puts "" +puts "incmesh second time" +set t2 [expr [lindex [time {incmesh a 0.003}] 0]/1000000] +puts "spent $t2 sec" +if {$t2 != 0} {puts "Error: second time must be quicker"} diff --git a/tests/bugs/mesh/bug25503_2 b/tests/bugs/mesh/bug25503_2 new file mode 100755 index 0000000000..b04b5217e3 --- /dev/null +++ b/tests/bugs/mesh/bug25503_2 @@ -0,0 +1,23 @@ +puts "TODO CR25469 ALL: Error: second time must be quicker" + +puts "============" +puts "CR25503" +puts "============" +puts "" +################################################################################### +# BRepMesh - IncrementalMesh always re-meshes the shape even if existing triangulation satisfies the given deflection +################################################################################### + +puts "" +puts "===> meshing full sphere" +psphere a 100 +puts "" +puts "incmesh first time" +set t3 [expr [lindex [time {incmesh a 0.015}] 0]/1000000] +puts "spent $t3 sec" +puts "" +puts "incmesh second time" +set t4 [expr [lindex [time {incmesh a 0.015}] 0]/1000000] +puts "spent $t4 sec" +if {$t4 != 0} {puts "Error: second time must be quicker"} +puts "" diff --git a/tests/mesh/data/standard/M1 b/tests/mesh/data/standard/M1 index d78592a4aa..a1ed0ff67e 100755 --- a/tests/mesh/data/standard/M1 +++ b/tests/mesh/data/standard/M1 @@ -1,6 +1,7 @@ set TheFileName shading_109.brep if { [string compare ${command} "shading"] == 0 && [string compare ${group} "standard"] == 0} { - # + set bug_cross "OCC25503" + set nbcross(All) 2 } else { set bug_cross "OCC22687" set nbcross(All) 4 -- 2.20.1