"""This module asserts correct runtime behaviour of the :mod:`pyrate.plan.geometry.helpers` functions for calculating distances. """ # Python standard library from datetime import timedelta from math import radians # Testing from unittest import TestCase # Hypothesis testing from hypothesis import given from hypothesis import settings import hypothesis.strategies as st # Scientific (testing) import numpy.testing # Module under test from pyrate.plan.geometry.helpers import fast_distance_geo from pyrate.plan.geometry.helpers import haversine_numpy # Own geometry from pyrate.plan.geometry.geospatial import MEAN_EARTH_CIRCUMFERENCE from pyrate.plan.geometry import PolarLocation # Test helpers from pyrate.common.testing.strategies.geometry import geo_bearings from pyrate.common.testing.strategies.geometry import polar_locations class TestDistanceCalculation(TestCase): """Tests the geographic helper methods.""" @given(polar_locations(), polar_locations()) def test_haversine_formula(self, location_1: PolarLocation, location_2: PolarLocation) -> None: """Test the correctness of the haversine formula.""" dist = haversine_numpy( radians(location_1.latitude), radians(location_1.longitude), radians(location_2.latitude), radians(location_2.longitude), ) self.assertLessEqual(dist, MEAN_EARTH_CIRCUMFERENCE / 2) numpy.testing.assert_allclose(location_1.distance(location_2), dist, atol=5.0, rtol=0.01) @given(polar_locations(), geo_bearings(), st.floats(min_value=0.0, max_value=250_000.0)) @settings(deadline=timedelta(seconds=1.0)) # pylint: disable=no-self-use def test_fast_distance_geo(self, center: PolarLocation, direction: float, distance: float) -> None: """Test the correctness of the fast great-circle approximation.""" other, _ = center.translate(direction, distance) distance_calculated = fast_distance_geo( radians(other.latitude), radians(other.longitude), radians(center.latitude), radians(center.longitude), ) numpy.testing.assert_allclose(distance, distance_calculated, atol=0.5, rtol=0.05)