Closed oboes closed 3 years ago
Hello @oboes for your detailed message.
I have made some experiments to try dealing with degenerate faces, and avoid manipulating NANs inside the code. I managed to avoid them but the infinite loop is still there.
For now I think that we should add a precondition that the input mesh should not have degenerate faces, and maybe refer to the mesh repair functions available in PMP. Maybe later we can think of an extension of the intrinsic triangulation that deals with degenerate faces, or implement the recent paper you mentioned.
@sloriot @afabri do you agree or have suggestions?
+1
+1
I also fully agree. I had missed that the degenerate triangle was in the input, and had thought that the intrinsification had produced one. We still could ask Keenan Crane if he sees a trivial fix.
Good. I'm preparing a PR for that and contacting Keenan Crane.
Today I read the mentioned paper N. Sharp & K. Crane 2020 and in fact the bulk of the article is about handling non-manifold input meshes by building some kind of double cover of the mesh (the "tufted cover") and then computing the Laplacian on it. Since the Surface_mesh
class implements a half-edge data structure which anyway can't handle non-manifold edges (i.e. edges with at least 3 incident faces), we don't really need this tufted cover construction here.
If we only want to handle degeneracies then it is enough to implement the "mollification step" described in section 4.5 of the article, which is much less work, so I submitted the alternative PR #5037 to solve this issue. However it might require more tests to be sure that in meshes with no degeneracies, the end result is really the same with and without the mollification step.
Issue Details
Using the
Heat_method_3
package inIntrinsic_Delaunay
mode with a mesh containing degenerate triangles will cause the algorithm to get stuck in an infinite loop.The responsible loop can be found in internal/Intrinsic_Delaunay_triangulation_3.h:293. When flipping edges to build the Delaunay triangulation, the algorithm will try to add/remove the same cycle of edges to the stack indefinitely. (On the line just above there is also a
int a = 0;
declaration which serves no purpose).This infinite loop is in turn caused by a division by zero when computing cotangents in internal/Intrinsic_Delaunay_triangulation_3.h:226. When encountering a degenerate triangle of the "needle" kind (having two vertices with identical positions), a
NaN
value will be produced, causing theis_edge_locally_delaunay
function to returnfalse
, and finally theloop_over_edges
to goes on forever.(If the algorithm instead encounters a degenerate triangle of the "cap" kind, with 3 collinear but distinct points, then an
inf
value will be produced, the loop will terminate, and you will get aEigen Decomposition in cotan failed
assertion exception later on in the linear solver.)The
Heat_method_3
package make some common assumptions on the input mesh (such as it being a triangle mesh, etc) so it might be expected that it will fail if you feed it a mesh containing degeneracies, but as there is no assertions checking for that the software will just silently freeze at some point. I believe that degeneracies might also be created during the edge flipping phase due to floating-point rounding errors (this package only works withdouble
data type so we can't use exact arithmetic there).See the original paper describing the heat method for additional details on this algorithm.
Source Code
Minimal example :
Suggestions
I didn't submit a pull request for this issue because I am not sure of the preferred way to fix it. Below are some suggestions.
NaN
values and replace them by something sane which will produce the expected behaviour from the algorithm (if that's possible).remove_degenerate_faces
function (but see also this related issue).Heat_method_3
package by implementing the method described in this recent paper by the same author which I believe could solve this and other issues related to non-manifold meshes (but that would require much more work).Environment