From 128654b60b3e87ba03daa93811dd24744252f704 Mon Sep 17 00:00:00 2001 From: emv Date: Mon, 23 Mar 2020 14:52:01 +0300 Subject: [PATCH] 0031461: Mesh - Add possibility to force the meshing of the shape BRepMesh: Add new mesh parameter *AllowQualityDecrease* which affects the criteria used for checking of the consistency of the existing mesh to new meshing parameters. So if set to true it will force the meshing of the shape if current deflection strongly vary from the new one, no matter in which side. BRepTools::Clean: Keep triangulation on non-geometric shapes (faces with no surface or edges with no curves). --- src/BRep/BRep_Tool.cxx | 11 +++++ src/BRep/BRep_Tool.hxx | 3 ++ src/BRepMesh/BRepMesh_Deflection.cxx | 17 +++++++ src/BRepMesh/BRepMesh_Deflection.hxx | 14 ++++++ src/BRepMesh/BRepMesh_EdgeDiscret.cxx | 12 +++-- src/BRepMesh/BRepMesh_ModelPreProcessor.cxx | 16 +++++-- src/BRepTools/BRepTools.cxx | 50 +++++++++++++++++---- src/BRepTools/BRepTools.hxx | 8 ++-- src/IMeshTools/IMeshTools_Parameters.hxx | 7 ++- src/IMeshTools/IMeshTools_ShapeExplorer.cxx | 4 +- src/MeshTest/MeshTest.cxx | 6 ++- tests/bugs/mesh/bug31461 | 17 +++++++ 12 files changed, 141 insertions(+), 24 deletions(-) create mode 100644 tests/bugs/mesh/bug31461 diff --git a/src/BRep/BRep_Tool.cxx b/src/BRep/BRep_Tool.cxx index 37c4f2213e..8fb6ef8638 100644 --- a/src/BRep/BRep_Tool.cxx +++ b/src/BRep/BRep_Tool.cxx @@ -206,6 +206,17 @@ Handle(Geom_Curve) BRep_Tool::Curve(const TopoDS_Edge& E, return C; } +//======================================================================= +//function : IsGeometric +//purpose : Returns True if has a surface. +//======================================================================= +Standard_Boolean BRep_Tool::IsGeometric (const TopoDS_Face& F) +{ + const BRep_TFace* TF = static_cast(F.TShape().get()); + const Handle(Geom_Surface)& S = TF->Surface(); + return !S.IsNull(); +} + //======================================================================= //function : IsGeometric //purpose : Returns True if is a 3d curve or a curve on diff --git a/src/BRep/BRep_Tool.hxx b/src/BRep/BRep_Tool.hxx index 6fdc110c06..e81eceab23 100644 --- a/src/BRep/BRep_Tool.hxx +++ b/src/BRep/BRep_Tool.hxx @@ -74,6 +74,9 @@ public: //! Returns the NaturalRestriction flag of the face. Standard_EXPORT static Standard_Boolean NaturalRestriction (const TopoDS_Face& F); + //! Returns True if has a surface, false otherwise. + Standard_EXPORT static Standard_Boolean IsGeometric (const TopoDS_Face& F); + //! Returns True if is a 3d curve or a curve on //! surface. Standard_EXPORT static Standard_Boolean IsGeometric (const TopoDS_Edge& E); diff --git a/src/BRepMesh/BRepMesh_Deflection.cxx b/src/BRepMesh/BRepMesh_Deflection.cxx index 776c7235bb..f6e37b2b48 100644 --- a/src/BRepMesh/BRepMesh_Deflection.cxx +++ b/src/BRepMesh/BRepMesh_Deflection.cxx @@ -164,3 +164,20 @@ void BRepMesh_Deflection::ComputeDeflection ( theDFace->SetDeflection (aFaceDeflection); } + +//======================================================================= +// Function: IsConsistent +// Purpose : +//======================================================================= +Standard_Boolean BRepMesh_Deflection::IsConsistent ( + const Standard_Real theCurrent, + const Standard_Real theRequired, + const Standard_Boolean theAllowDecrease, + const Standard_Real theRatio) +{ + // Check if the deflection of existing polygonal representation + // fits the required deflection. + Standard_Boolean isConsistent = theCurrent < (1. + theRatio) * theRequired + && (!theAllowDecrease || theCurrent > (1. - theRatio) * theRequired); + return isConsistent; +} diff --git a/src/BRepMesh/BRepMesh_Deflection.hxx b/src/BRepMesh/BRepMesh_Deflection.hxx index 35998a839b..d8c7caf472 100644 --- a/src/BRepMesh/BRepMesh_Deflection.hxx +++ b/src/BRepMesh/BRepMesh_Deflection.hxx @@ -58,6 +58,20 @@ public: const IMeshData::IFaceHandle& theDFace, const IMeshTools_Parameters& theParameters); + //! Checks if the deflection of current polygonal representation + //! is consistent with the required deflection. + //! @param theCurrent [in] Current deflection. + //! @param theRequired [in] Required deflection. + //! @param theAllowDecrease [in] Flag controlling the check. If decrease is allowed, + //! to be consistent the current and required deflections should be approximately the same. + //! If not allowed, the current deflection should be less than required. + //! @param theRatio [in] The ratio for comparison of the deflections (value from 0 to 1). + Standard_EXPORT static Standard_Boolean IsConsistent ( + const Standard_Real theCurrent, + const Standard_Real theRequired, + const Standard_Boolean theAllowDecrease, + const Standard_Real theRatio = 0.1); + DEFINE_STANDARD_RTTI_INLINE(BRepMesh_Deflection, Standard_Transient) }; diff --git a/src/BRepMesh/BRepMesh_EdgeDiscret.cxx b/src/BRepMesh/BRepMesh_EdgeDiscret.cxx index d9e575af43..4a305440d4 100644 --- a/src/BRepMesh/BRepMesh_EdgeDiscret.cxx +++ b/src/BRepMesh/BRepMesh_EdgeDiscret.cxx @@ -155,8 +155,10 @@ void BRepMesh_EdgeDiscret::process (const Standard_Integer theEdgeIndex) const const Handle (Poly_Polygon3D)& aPoly3D = BRep_Tool::Polygon3D (aDEdge->GetEdge (), aLoc); if (!aPoly3D.IsNull ()) { - if (aPoly3D->HasParameters () && - aPoly3D->Deflection () < 1.1 * aDEdge->GetDeflection ()) + if (aPoly3D->HasParameters() && + BRepMesh_Deflection::IsConsistent (aPoly3D->Deflection(), + aDEdge->GetDeflection(), + myParameters.AllowQualityDecrease)) { // Edge already has suitable 3d polygon. aDEdge->SetStatus(IMeshData_Reused); @@ -209,8 +211,10 @@ Standard_Real BRepMesh_EdgeDiscret::checkExistingPolygonAndUpdateStatus( if (!aPolygon.IsNull ()) { - Standard_Boolean isConsistent = aPolygon->HasParameters () && - aPolygon->Deflection () < 1.1 * theDEdge->GetDeflection (); + Standard_Boolean isConsistent = aPolygon->HasParameters() && + BRepMesh_Deflection::IsConsistent (aPolygon->Deflection(), + theDEdge->GetDeflection(), + myParameters.AllowQualityDecrease); if (!isConsistent) { diff --git a/src/BRepMesh/BRepMesh_ModelPreProcessor.cxx b/src/BRepMesh/BRepMesh_ModelPreProcessor.cxx index c9d02d486b..df9d9e48d9 100644 --- a/src/BRepMesh/BRepMesh_ModelPreProcessor.cxx +++ b/src/BRepMesh/BRepMesh_ModelPreProcessor.cxx @@ -14,6 +14,7 @@ // commercial license or contractual agreement. #include +#include #include #include #include @@ -30,8 +31,10 @@ namespace { public: //! Constructor - TriangulationConsistency(const Handle(IMeshData_Model)& theModel) + TriangulationConsistency(const Handle(IMeshData_Model)& theModel, + const Standard_Boolean theAllowQualityDecrease) : myModel (theModel) + , myAllowQualityDecrease (theAllowQualityDecrease) { } @@ -51,7 +54,9 @@ namespace if (!aTriangulation.IsNull()) { Standard_Boolean isTriangulationConsistent = - aTriangulation->Deflection() < 1.1 * aDFace->GetDeflection(); + BRepMesh_Deflection::IsConsistent (aTriangulation->Deflection(), + aDFace->GetDeflection(), + myAllowQualityDecrease); if (isTriangulationConsistent) { @@ -88,6 +93,7 @@ namespace private: Handle(IMeshData_Model) myModel; + Standard_Boolean myAllowQualityDecrease; //!< Flag used for consistency check }; //! Adds additional points to seam edges on specific surfaces. @@ -251,8 +257,10 @@ Standard_Boolean BRepMesh_ModelPreProcessor::performInternal( return Standard_False; } - OSD_Parallel::For(0, theModel->FacesNb(), SeamEdgeAmplifier(theModel, theParameters), !theParameters.InParallel); - OSD_Parallel::For(0, theModel->FacesNb(), TriangulationConsistency(theModel), !theParameters.InParallel); + const Standard_Integer aFacesNb = theModel->FacesNb(); + const Standard_Boolean isOneThread = !theParameters.InParallel; + OSD_Parallel::For(0, aFacesNb, SeamEdgeAmplifier (theModel, theParameters), isOneThread); + OSD_Parallel::For(0, aFacesNb, TriangulationConsistency (theModel, theParameters.AllowQualityDecrease), isOneThread); // Clean edges and faces from outdated polygons. Handle(NCollection_IncAllocator) aTmpAlloc(new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE)); diff --git a/src/BRepTools/BRepTools.cxx b/src/BRepTools/BRepTools.cxx index 327fa12a60..cc38b3a2e5 100644 --- a/src/BRepTools/BRepTools.cxx +++ b/src/BRepTools/BRepTools.cxx @@ -760,19 +760,36 @@ Standard_Boolean BRepTools::Read(TopoDS_Shape& Sh, //purpose : //======================================================================= -void BRepTools::Clean(const TopoDS_Shape& theShape) +void BRepTools::Clean (const TopoDS_Shape& theShape) { + if (theShape.IsNull()) + return; + BRep_Builder aBuilder; Handle(Poly_Triangulation) aNullTriangulation; Handle(Poly_PolygonOnTriangulation) aNullPoly; - if (theShape.IsNull()) - return; + TopTools_MapOfShape aShapeMap; + const TopLoc_Location anEmptyLoc; TopExp_Explorer aFaceIt(theShape, TopAbs_FACE); for (; aFaceIt.More(); aFaceIt.Next()) { - const TopoDS_Face& aFace = TopoDS::Face(aFaceIt.Current()); + TopoDS_Shape aFaceNoLoc = aFaceIt.Value(); + aFaceNoLoc.Location (anEmptyLoc); + if (!aShapeMap.Add (aFaceNoLoc)) + { + // the face has already been processed + continue; + } + + const TopoDS_Face& aFace = TopoDS::Face (aFaceIt.Current()); + if (!BRep_Tool::IsGeometric (aFace)) + { + // Do not remove triangulation as there is no surface to recompute it. + continue; + } + TopLoc_Location aLoc; const Handle(Poly_Triangulation)& aTriangulation = @@ -782,6 +799,10 @@ void BRepTools::Clean(const TopoDS_Shape& theShape) continue; // Nullify edges + // Theoretically, the edges on the face (with surface) may have no geometry + // (no curve 3d or 2d or both). Such faces should be considered as invalid and + // are not supported by current implementation. So, both triangulation of the face + // and polygon on triangulation of the edges are removed unconditionally. TopExp_Explorer aEdgeIt(aFace, TopAbs_EDGE); for (; aEdgeIt.More(); aEdgeIt.Next()) { @@ -797,14 +818,27 @@ void BRepTools::Clean(const TopoDS_Shape& theShape) TopExp_Explorer aEdgeIt (theShape, TopAbs_EDGE); for (; aEdgeIt.More (); aEdgeIt.Next ()) { - const TopoDS_Edge& aEdge = TopoDS::Edge (aEdgeIt.Current ()); + TopoDS_Edge anEdgeNoLoc = TopoDS::Edge (aEdgeIt.Value()); + anEdgeNoLoc.Location (anEmptyLoc); + + if (!aShapeMap.Add (anEdgeNoLoc)) + { + // the edge has already been processed + continue; + } + + if (!BRep_Tool::IsGeometric (TopoDS::Edge (anEdgeNoLoc))) + { + // Do not remove polygon 3d as there is no curve to recompute it. + continue; + } TopLoc_Location aLoc; - Handle (Poly_Polygon3D) aPoly3d = BRep_Tool::Polygon3D (aEdge, aLoc); - if (aPoly3d.IsNull ()) + Handle (Poly_Polygon3D) aPoly3d = BRep_Tool::Polygon3D (anEdgeNoLoc, aLoc); + if (aPoly3d.IsNull()) continue; - aBuilder.UpdateEdge (aEdge, aNullPoly3d); + aBuilder.UpdateEdge (anEdgeNoLoc, aNullPoly3d); } } //======================================================================= diff --git a/src/BRepTools/BRepTools.hxx b/src/BRepTools/BRepTools.hxx index 5cfc5f7259..1e1b916ddb 100644 --- a/src/BRepTools/BRepTools.hxx +++ b/src/BRepTools/BRepTools.hxx @@ -150,9 +150,11 @@ public: //! edge on the face. Standard_EXPORT static void UpdateFaceUVPoints (const TopoDS_Face& theF); - //! Removes all the triangulations of the faces of - //! and removes all polygons on triangulations of the - //! edges. + //! Removes all cashed polygonal representation of the shape, + //! i.e. the triangulations of the faces of and polygons on + //! triangulations and polygons 3d of the edges. + //! In case polygonal representation is the only available representation + //! for the shape (shape does not have geometry) it is not removed. Standard_EXPORT static void Clean (const TopoDS_Shape& S); //! Removes geometry (curves and surfaces) from all edges and faces of the shape diff --git a/src/IMeshTools/IMeshTools_Parameters.hxx b/src/IMeshTools/IMeshTools_Parameters.hxx index c0526becdb..17c3591113 100644 --- a/src/IMeshTools/IMeshTools_Parameters.hxx +++ b/src/IMeshTools/IMeshTools_Parameters.hxx @@ -35,7 +35,8 @@ struct IMeshTools_Parameters { ControlSurfaceDeflection (Standard_True), CleanModel (Standard_True), AdjustMinSize (Standard_False), - ForceFaceDeflection (Standard_False) + ForceFaceDeflection (Standard_False), + AllowQualityDecrease (Standard_False) { } @@ -89,6 +90,10 @@ struct IMeshTools_Parameters { //! Enables/disables usage of shape tolerances for computing face deflection. //! Disabled by default. Standard_Boolean ForceFaceDeflection; + + //! Allows/forbids the decrease of the quality of the generated mesh + //! over the existing one. + Standard_Boolean AllowQualityDecrease; }; #endif diff --git a/src/IMeshTools/IMeshTools_ShapeExplorer.cxx b/src/IMeshTools/IMeshTools_ShapeExplorer.cxx index bc690a40df..a6214ee700 100644 --- a/src/IMeshTools/IMeshTools_ShapeExplorer.cxx +++ b/src/IMeshTools/IMeshTools_ShapeExplorer.cxx @@ -88,7 +88,6 @@ void IMeshTools_ShapeExplorer::Accept ( BRepLib::ReverseSortFaces (GetShape (), aFaceList); TopTools_MapOfShape aFaceMap; - TopLoc_Location aDummyLoc; const TopLoc_Location aEmptyLoc; TopTools_ListIteratorOfListOfShape aFaceIter (aFaceList); for (; aFaceIter.More (); aFaceIter.Next ()) @@ -101,8 +100,7 @@ void IMeshTools_ShapeExplorer::Accept ( } const TopoDS_Face& aFace = TopoDS::Face (aFaceIter.Value ()); - const Handle (Geom_Surface)& aSurf = BRep_Tool::Surface (aFace, aDummyLoc); - if (aSurf.IsNull()) + if (!BRep_Tool::IsGeometric (aFace)) { continue; } diff --git a/src/MeshTest/MeshTest.cxx b/src/MeshTest/MeshTest.cxx index 9882f52266..3624575271 100644 --- a/src/MeshTest/MeshTest.cxx +++ b/src/MeshTest/MeshTest.cxx @@ -89,7 +89,9 @@ options:\n\ surface (enabled by default)\n\ -parallel enables parallel execution (switched off by default)\n\ -adjust_min enables local adjustment of min size depending on edge size (switched off by default)\n\ - -force_face_def disables usage of shape tolerances for computing face deflection (switched off by default). \n"; + -force_face_def disables usage of shape tolerances for computing face deflection (switched off by default)\n\ + -decrease enforces the meshing of the shape even if current mesh satisfies the new criteria\ + (switched off by default).\n"; return 0; } @@ -126,6 +128,8 @@ options:\n\ aMeshParams.AdjustMinSize = Standard_True; else if (aOpt == "-force_face_def") aMeshParams.ForceFaceDeflection = Standard_True; + else if (aOpt == "-decrease") + aMeshParams.AllowQualityDecrease = Standard_True; else if (i < nbarg) { Standard_Real aVal = Draw::Atof(argv[i++]); diff --git a/tests/bugs/mesh/bug31461 b/tests/bugs/mesh/bug31461 new file mode 100644 index 0000000000..bd1c569c53 --- /dev/null +++ b/tests/bugs/mesh/bug31461 @@ -0,0 +1,17 @@ +puts "=======" +puts "0031461: Mesh - Add possibility to force the meshing of the shape" +puts "=======" +puts "" + +psphere s 10 + +incmesh s 0.01 +checktrinfo s -tri 10108 -nod 5106 + +incmesh s 0.1 -decrease +checktrinfo s -tri 978 -nod 507 + +tclean -geom s +incmesh s 0.01 +tclean s +checktrinfo s -tri 978 -nod 507