From e72a7769bc47c8590632f7acce88715f1cbb86ab Mon Sep 17 00:00:00 2001 From: Nis Meinert Date: Mon, 11 Mar 2024 16:03:14 +0100 Subject: [PATCH 1/4] Ensure non-negative values in sqrt --- geordpy/great_circle.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geordpy/great_circle.py b/geordpy/great_circle.py index e65e2c9..efcd04f 100644 --- a/geordpy/great_circle.py +++ b/geordpy/great_circle.py @@ -34,7 +34,7 @@ def cos_distance_segment(lat, lon, *, lat1, lon1, lat2, lon2, eps=1e-5): ) n = np.cross(a, b) - cos_gamma = np.dot(a, b) + cos_gamma = np.clip(np.dot(a, b), a_min=-1.0, a_max=1.0) n /= max(np.sqrt((1.0 - cos_gamma) * (1.0 + cos_gamma)), np.nextafter(0.0, 1.0)) s = x @ n From 1583dbfebe3b7fdadd60c480810737b4a6601441 Mon Sep 17 00:00:00 2001 From: Nis Meinert Date: Mon, 11 Mar 2024 16:26:41 +0100 Subject: [PATCH 2/4] Add test case for degenerated data --- tests/rdp_test.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/rdp_test.py b/tests/rdp_test.py index 4e8e399..de677d5 100644 --- a/tests/rdp_test.py +++ b/tests/rdp_test.py @@ -66,6 +66,24 @@ def test_great_circle(): assert all(mask == [True, False, True, True, True, True, False, True]) +def test_degenerated_great_circle(): + points = [ + (0.0, 10.0), # point 0 + (0.0, 0.0), # point 1 + (0.0, 0.0), # point 2 + (0.0, 10.0), # point 3 + ] + + radius = 1000 + _filter = functools.partial(rdp_filter, radius=radius) + + mask = _filter(points, threshold=1) + assert all(mask == [True, True, False, True]) + + mask = _filter(points, threshold=10 * radius) + assert all(mask == [True, False, False, True]) + + def test_rhumb_line(): def _gd(x): return np.rad2deg(utils.gd(np.deg2rad(x))) From dd61ff0fc4426128978bb747dabddc234b602cec Mon Sep 17 00:00:00 2001 From: Nis Meinert Date: Mon, 11 Mar 2024 16:27:12 +0100 Subject: [PATCH 3/4] Make division safe against overflows --- geordpy/great_circle.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/geordpy/great_circle.py b/geordpy/great_circle.py index efcd04f..09b8bf6 100644 --- a/geordpy/great_circle.py +++ b/geordpy/great_circle.py @@ -35,7 +35,11 @@ def cos_distance_segment(lat, lon, *, lat1, lon1, lat2, lon2, eps=1e-5): n = np.cross(a, b) cos_gamma = np.clip(np.dot(a, b), a_min=-1.0, a_max=1.0) - n /= max(np.sqrt((1.0 - cos_gamma) * (1.0 + cos_gamma)), np.nextafter(0.0, 1.0)) + + # if |cos(gamma)| = 1, then |n| = 0. However, in case |n| is slightly larger due + # to numeric issues, division by 1e-100 is a decent approximation. Even smaller + # values for the denominator should be avoided as this can trigger overflows. + n /= max(np.sqrt((1.0 - cos_gamma) * (1.0 + cos_gamma)), 1e-100) s = x @ n From 6082d83a1fd371a675a6d1e35f75ad9800c6bb19 Mon Sep 17 00:00:00 2001 From: Nis Meinert Date: Mon, 11 Mar 2024 16:35:07 +0100 Subject: [PATCH 4/4] Bump version --- CITATION.cff | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CITATION.cff b/CITATION.cff index 179c343..d9c4a57 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -5,6 +5,6 @@ authors: given-names: "Nis" orcid: "https://orcid.org/0000-0002-4712-9579" title: "GeoRDPy" -version: 3.0 +version: 3.1 date-released: 2023-10-06 url: "https://github.com/avitase/geordpy"