From b99140533b766fa112340b71550b588c5df24beb Mon Sep 17 00:00:00 2001 From: Ben Torvaney Date: Thu, 4 Apr 2024 00:10:34 +0100 Subject: [PATCH] Workaround precision errors Lack of precision in represenation of numbers can cause numbers in the arc calculation to slip into undefined spaces (arcos(-1-eps)). This commit fixes this by rounding up to -1 if needed. --- NEWS.md | 3 ++- R/annotate_pitch.R | 10 +++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index 8c698fd..f18835c 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,7 @@ # ggsoccer 0.1.8 (In progress) -- Add IMPECT pitch dimensions (`pitch_impect`) +- Add IMPECT pitch dimensions (`pitch_impect`) +- Fixed precision bug in arc drawing, which could cause the pitch to fail to render # ggsoccer 0.1.7 diff --git a/R/annotate_pitch.R b/R/annotate_pitch.R index 87fd297..19f8c49 100644 --- a/R/annotate_pitch.R +++ b/R/annotate_pitch.R @@ -345,7 +345,15 @@ annotate_intersection_arc <- function(xintercept, x0, y0, r, direction, ...) { # `annotate_intersection_arc` with `xintercept = spec$penalty_spot_distance` # on top of a pitch_international pitch and comparing to the drawn arc) # but it is close enough. - angle <- acos((r^2 + r^2 - abs(pos_y - neg_y)^2)/(2*r^2)) + + # However, it's possible to get NaNs here! + # This is because of the inaccuracies in double-precision numbers. + # Consequently, if you have a perfect semi-circle (which should have an + # angle of `acos(-1) = pi`), you might try to calculate `acos(-(1 + epsilon))` + # where epsilon is some tiny value. The arccos of anything greater than -1 is + # undefined. + # To get around this, we cap the inner calculation to be -1 at the least + angle <- acos(pmax(-1, (r^2 + r^2 - abs(pos_y - neg_y)^2)/(2*r^2))) arc_proportion <- angle/(2*pi) curvature <- -arc_proportion/(arc_proportion-1)