1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-04 18:06:22 +03:00

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).
This commit is contained in:
emv 2020-03-23 14:52:01 +03:00 committed by bugmaster
parent 21095f2dc2
commit 128654b60b
12 changed files with 141 additions and 24 deletions

View File

@ -206,6 +206,17 @@ Handle(Geom_Curve) BRep_Tool::Curve(const TopoDS_Edge& E,
return C;
}
//=======================================================================
//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

View 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);

View 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;
}

View 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)
};

View 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)
{

View 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));

View 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);
}
}
//=======================================================================

View 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

View 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

View 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;
}

View 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++]);

17
tests/bugs/mesh/bug31461 Normal file
View File

@ -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