Skip to content

Internal vertices not bound in output triangulation from BrepMesh #929

@ttaneff

Description

@ttaneff

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):

Image

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):

Image

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

No one assigned

    Labels

    0. NewThe issue was created, but not updated by maintainer. Waiting for updates labels and categories2. BugSomething isn't working

    Type

    No type

    Projects

    Status

    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions