0031461: Mesh - Add possibility to force the meshing of the shape
authoremv <emv@opencascade.com>
Mon, 23 Mar 2020 11:52:01 +0000 (14:52 +0300)
committerbugmaster <bugmaster@opencascade.com>
Wed, 1 Apr 2020 10:36:29 +0000 (13:36 +0300)
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).

12 files changed:
src/BRep/BRep_Tool.cxx
src/BRep/BRep_Tool.hxx
src/BRepMesh/BRepMesh_Deflection.cxx
src/BRepMesh/BRepMesh_Deflection.hxx
src/BRepMesh/BRepMesh_EdgeDiscret.cxx
src/BRepMesh/BRepMesh_ModelPreProcessor.cxx
src/BRepTools/BRepTools.cxx
src/BRepTools/BRepTools.hxx
src/IMeshTools/IMeshTools_Parameters.hxx
src/IMeshTools/IMeshTools_ShapeExplorer.cxx
src/MeshTest/MeshTest.cxx
tests/bugs/mesh/bug31461 [new file with mode: 0644]

index 37c4f22..8fb6ef8 100644 (file)
@@ -208,6 +208,17 @@ Handle(Geom_Curve)  BRep_Tool::Curve(const TopoDS_Edge& E,
 
 //=======================================================================
 //function : IsGeometric
+//purpose  : Returns True if <F> has a surface.
+//=======================================================================
+Standard_Boolean BRep_Tool::IsGeometric (const TopoDS_Face& F)
+{
+  const BRep_TFace* TF = static_cast<const BRep_TFace*>(F.TShape().get());
+  const Handle(Geom_Surface)& S = TF->Surface();
+  return !S.IsNull();
+}
+
+//=======================================================================
+//function : IsGeometric
 //purpose  : Returns True if <E> is a 3d curve or a curve on
 //           surface.
 //=======================================================================
index 6fdc110..e81ecea 100644 (file)
@@ -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 <F> has a surface, false otherwise.
+  Standard_EXPORT static Standard_Boolean IsGeometric (const TopoDS_Face& F);
+
   //! Returns True if <E> is a 3d curve or a curve on
   //! surface.
   Standard_EXPORT static Standard_Boolean IsGeometric (const TopoDS_Edge& E);
index 776c723..f6e37b2 100644 (file)
@@ -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;
+}
index 35998a8..d8c7caf 100644 (file)
@@ -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)
 };
 
index d9e575a..4a30544 100644 (file)
@@ -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)
     {
index c9d02d4..df9d9e4 100644 (file)
@@ -14,6 +14,7 @@
 // commercial license or contractual agreement.
 
 #include <BRepMesh_ModelPreProcessor.hxx>
+#include <BRepMesh_Deflection.hxx>
 #include <BRepMesh_ShapeTool.hxx>
 #include <BRep_Tool.hxx>
 #include <IMeshData_Model.hxx>
@@ -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));
index 327fa12..cc38b3a 100644 (file)
@@ -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);
   }
 }
 //=======================================================================
index 5cfc5f7..1e1b916 100644 (file)
@@ -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 <S>
-  //! 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 <S> 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
index c0526be..17c3591 100644 (file)
@@ -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
index bc690a4..a6214ee 100644 (file)
@@ -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;
     }
index 9882f52..3624575 100644 (file)
@@ -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 (file)
index 0000000..bd1c569
--- /dev/null
@@ -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