3

I have a CGAL surface_mesh of triangles with some self-intersecting triangles which I'm trying to remove to create a continuous 2-manifold shell, ultimately for printing.

I've attempted to use remove_self_intersection() and autorefine_and_remove_self_intersections() from this answer. The first only removes a few self-intersections while the second completely removes my mesh.

So, I'm trying my own approach - I'm finding the self-intersections and then attempting to delete them. I've tried using the low level remove_face but the borders are not detectable afterwards so I'm unable to fill the resulting holes. This answer refers to using the higher level Euler remove_face but this method, and make_hole seem to discard my mesh entirely.

Here is an extract (I'm using break to see if I can get at least one triangle removed, and I'm just trying with the first of the pair):

    vector<pair<face_descriptor, face_descriptor> > intersected_tris;
PMP::self_intersections(mesh, back_inserter(intersected_tris));
for (pair<face_descriptor, face_descriptor> &p : intersected_tris) {
    CGAL::Euler::remove_face(mesh.halfedge(get<0>(p)), mesh);
    break;
}
James
  • 339
  • 3
  • 16
  • 1
    These functions are not documented because as you noticed they are not yet able to handle all possible nasty cases. If you can share your input mesh this would help us improving those functions. About your code, you should pay attention to the fact that a face might be involved in more than one self-intersection and a call to `remove_face()` should be done only once per face. – sloriot Oct 10 '18 at 07:07
  • Thank you very much @sloriot and I very much appreciate the unbelievable amount of work that must have gone into creating these libraries. – James Oct 10 '18 at 23:12

1 Answers1

5

My approach to removing self-intersecting triangles is to aggressively delete the intersecting faces, along with nearby faces and fill the resulting holes. Thanks to @sloriot 's comment I realised that the Euler::remove_face function was failing due to duplicate faces in the set returned from both the self_intersections and expand_face_selection functions.

A quick way to remove duplicate faces from the vector result of those two functions is:

std::set<face_descriptor> s(selected_faces.begin(), selected_faces.end());
selected_faces.assign(s.begin(), s.end());

This code converts the vector of faces into a set (sets contain no duplicates) and then converting the set back again.

Once the duplicates were removed, the Euler::remove_face function worked correctly, including updating the borders so that the triangulate_hole function could be used on the result producing a final surface with no self-intersections.

James
  • 339
  • 3
  • 16