From 5dcbdfc944a2dfc00b07cb138254d4e479f68fe6 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 25 Jan 2022 18:00:56 +0100 Subject: [PATCH] Fix floating point accuracy issue in triangulation Close #60 --- src/kernel/topology/faces.rs | 37 +++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/src/kernel/topology/faces.rs b/src/kernel/topology/faces.rs index 0e1eeb099c..43fd422758 100644 --- a/src/kernel/topology/faces.rs +++ b/src/kernel/topology/faces.rs @@ -108,18 +108,41 @@ impl Face { let outside = aabb.maxs * 2.; triangles.retain(|triangle| { - for segment in triangle.edges() { + 'outer: for segment in triangle.edges() { let mut inverted_segment = segment; inverted_segment.swap(); - let triangle_segment_is_face_edge = face_as_polygon - .contains(&segment) - || face_as_polygon.contains(&inverted_segment); - // If the segment is an edge of the face, we don't need // to take a closer look. - if triangle_segment_is_face_edge { - continue; + // + // We can't use `contains` here, as that compares the + // segments directly, without taking floating point + // accuracy into account. + // + // This is not great. See this issue: + // https://github.com/hannobraun/Fornjot/issues/78 + for s in &face_as_polygon { + // This epsilon value is small enough to not mistake + // different vertices as equal, for common use + // cases, while still being a few orders of + // magnitude larger than the differences between + // equal vertices that I've seen so far. + let eps = 1e-12; + + let aa = (s.a - segment.a).magnitude(); + let bb = (s.b - segment.b).magnitude(); + let ab = (s.a - segment.b).magnitude(); + let ba = (s.b - segment.a).magnitude(); + + let segment_is_face_edge = aa < eps && bb < eps; + let segment_is_inverted_face_edge = + ab < eps && ba < eps; + + if segment_is_face_edge + || segment_is_inverted_face_edge + { + continue 'outer; + } } // To determine if the edge is within the polygon, we