-
Notifications
You must be signed in to change notification settings - Fork 541
Description
Description
If a TopoDS_Face contains TopABS_Internal vertices in it's topology, mesh generated by the BRepMesh_IncrementalMesh algorithm results in uninitialized coordinates for the first N triangulation nodes, where N is the number of internal vertices from the input. This is due to myUsedNodes not being correctly populated during the initialization of the triangulation input. While registerNode() is called from initDataStructure the following call to myUsedNodes->Bind(aNodeIndex, aNodeIndex); is only present there. In method insertInternalVertex there is no corresponding call to Bind, hence all TopABS_Internal vertices from the input remain 'hanging' with some random FP values, usually resulting in garbage large values.
When such faces are meshed, there are number of invalid triangles, which are not visible, but refer to the these uninitialized output nodes.
I have reported this in the old forums while ago dev.opencascade.org _however, my suggested fix was not entirely correct. Disregard my previous comments about appending to the end of the collection, this part is obviously not part of the problem.
Option A: Moving the Bind call inside registerNode() fixes this, as internal vertices are properly registered from the beginning;
Option B: Add a call to myUsedNodes->Bind in method insertInternalVertex after the call to registerNode;
Problem is contained in BRepMesh_NodeInsertionMeshAlgo.hxx and BRepMesh_BaseMeshAlgo.cxx entirely
Expected Behavior
When internal vertices are included in the triangulation (by the corresponding flag), these should be valid fixed nodes in the output triangulation, producing valid mesh topology and geometry.
NOTE: Produced with the suggested simple fix applied (I chose 'A' as it is more atomic):
Actual Behavior
Internal vertices are present only as indices with uninitialized memory for their coordinates, resulting in both invalid mesh topology (degenerate triangles) and invalid coordinates for a range at the beginning of the node array.
OCCT 7.9.3 (same behavior since 7.8.0):
Sample Code or DRAW Tcl Script
// Helper to encapsulate the proper topological and parametric description of an internal vertex
// Force-project the input vertex using GeomAPI, and obtain it's surface parametrization
//
TopoDS_Vertex Face_AddInternalVertex(TopoDS_Face aFace, TopoDS_Vertex iVertex)
{
Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
gp_Pnt vPnt = BRep_Tool::Pnt(iVertex);
GeomAPI_ProjectPointOnSurf aProjection(vPnt, aSurf);
if (!aProjection.IsDone())
return TopoDS_Vertex();
double minDist = aProjection.LowerDistance();
BRepClass_FaceClassifier pOnFaceClassifier(aFace, vPnt, 1E-4, false);
int pState = pOnFaceClassifier.State();
if (aProjection.IsDone())
{
if (aProjection.NbPoints() > 0)
{
double u, v;
aProjection.Parameters(1, u, v);
TopoDS_Vertex V(BRepBuilderAPI_MakeVertex(aProjection.Point(1)));
V.Orientation(TopAbs_INTERNAL);
BRep_Builder().UpdateVertex(V, u, v, aFace, Precision::Confusion());
//aFace.Free(true);
BRep_Builder().Add(aFace, V);
return V;
}
else
return TopoDS_Vertex();
}
else
return TopoDS_Vertex();
}
void main()
{
printf("Creating BRep topology... ");
gp_Pln plane(gp_Pnt(0.0, 0.0, 0.0), gp::DZ());
const Standard_Real uMin = 0.0;
const Standard_Real uMax = 100.0;
const Standard_Real vMin = 0.0;
const Standard_Real vMax = 50.0;
TopoDS_Face face = BRepBuilderAPI_MakeFace(plane, uMin, uMax, vMin, vMax);
// Now add some INTERNAL vertices on the Face
Face_AddInternalVertex(face, BRepBuilderAPI_MakeVertex(gp_Pnt(40.0, 20.0, 0.0)));
Face_AddInternalVertex(face, BRepBuilderAPI_MakeVertex(gp_Pnt(60.0, 30.0, 0.0)));
Face_AddInternalVertex(face, BRepBuilderAPI_MakeVertex(gp_Pnt(77.0, 33.0, 0.0)));
printf(" OK\n");
printf("Performing Incremental Mesh using BRepMesh...");
IMeshTools_Parameters params;
params.Deflection = 1.0;
params.Angle = 0.5;
// Make sure we request TopABS_Internal vertices to be included in the mesh
params.InternalVerticesMode = true;
BRepMesh_IncrementalMesh mesher(face, params);
if (!mesher.IsDone())
{
printf(" FAILED!\n");
return;
}
// Let's see what just transpired... hm
TopLoc_Location loc;
Handle(Poly_Triangulation) tri = BRep_Tool::Triangulation(face, loc);
if (tri.IsNull())
{
printf("FAILED!\n");
return;
}
printf(" OK\n");
// BOOM GOES THE DYNAMITE (observe the first 3 entries coordinates'...)
printf("\n=== Nodes ===\n");
printf("Idx | X | Y | Z\n");
printf("-------+-----------------+-----------------+-----------------\n");
for (Standard_Integer i = 1; i <= tri->NbNodes(); ++i)
{
gp_Pnt p = tri->Node(i).Transformed(loc);
printf("%5d | %15.6f | %15.6f | %15.6f\n", i, p.X(), p.Y(), p.Z());
}
// BOOM AGAIN (degenerate triangles with duplicate vertex indices...)
printf("\n=== Triangles ===\n");
printf("Idx | N1 | N2 | N3\n");
printf("-------+--------+--------+--------\n");
for (Standard_Integer i = 1; i <= tri->NbTriangles(); ++i)
{
Standard_Integer n1, n2, n3;
tri->Triangle(i).Get(n1, n2, n3);
printf("%5d | %6d | %6d | %6d\n", i, n1, n2, n3);
}
}
Operating System
Windows
Compiler
MSVC
Bitness
64-bit
OCCT Version
latest
Additional Files
No response
Metadata
Metadata
Assignees
Labels
Type
Projects
Status