From b95c60fc9fe671eb42a6811e137ab48167657db2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 27 Apr 2021 22:40:22 +0200 Subject: [PATCH] Avoid needless orientation checks / distance computations If we are right of the edge, the distance is minimum over the edge... ...and that's it. Computing the distance to a segment is about as expensive as the orientation check, so no point pinpointing to check if the min is at a vertex. --- .../CGAL/Distance_3/Point_3_Triangle_3.h | 32 +++++++++++++------ 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/Distance_3/include/CGAL/Distance_3/Point_3_Triangle_3.h b/Distance_3/include/CGAL/Distance_3/Point_3_Triangle_3.h index 7f1c4d5acdd..4231977b22d 100644 --- a/Distance_3/include/CGAL/Distance_3/Point_3_Triangle_3.h +++ b/Distance_3/include/CGAL/Distance_3/Point_3_Triangle_3.h @@ -64,26 +64,38 @@ squared_distance_to_triangle(const typename K::Point_3& pt, const Vector_3 oe3 = vector(t0, t2); const Vector_3 normal = wcross(e1, oe3, k); - if(normal != NULL_VECTOR && - on_left_of_triangle_edge(pt, normal, t0, t1, k) && - on_left_of_triangle_edge(pt, normal, t1, t2, k) && - on_left_of_triangle_edge(pt, normal, t2, t0, k)) - { - // the projection of pt is inside the triangle - inside = true; - return squared_distance_to_plane(normal, vector(t0, pt), k); - } - else + if(normal == NULL_VECTOR) { // The case normal == NULL_VECTOR covers the case when the triangle // is colinear, or even more degenerate. In that case, we can // simply take also the distance to the three segments. + // + // Note that in the degenerate case, at most 2 edges cover the full triangle, + // and only two distances could be used, but leaving 3 for the case of + // inexact constructions as it might improve the accuracy. + typename K::FT d1 = internal::squared_distance(pt, segment(t2, t0), k); typename K::FT d2 = internal::squared_distance(pt, segment(t1, t2), k); typename K::FT d3 = internal::squared_distance(pt, segment(t0, t1), k); return (std::min)( (std::min)(d1, d2), d3); } + + const bool b01 = on_left_of_triangle_edge(pt, normal, t0, t1, k); + if(!b01) + return internal::squared_distance(pt, segment(t0, t1), k); + + const bool b12 = on_left_of_triangle_edge(pt, normal, t1, t2, k); + if(!b12) + return internal::squared_distance(pt, segment(t1, t2), k); + + const bool b20 = on_left_of_triangle_edge(pt, normal, t2, t0, k); + if(!b20) + return internal::squared_distance(pt, segment(t2, t0), k); + + // The projection of pt is inside the triangle + inside = true; + return squared_distance_to_plane(normal, vector(t0, pt), k); } template