diff --git a/src/pymap3d/tests/test_vincenty_vreckon.py b/src/pymap3d/tests/test_vincenty_vreckon.py index 8ee945c..314f40a 100644 --- a/src/pymap3d/tests/test_vincenty_vreckon.py +++ b/src/pymap3d/tests/test_vincenty_vreckon.py @@ -23,11 +23,11 @@ [ (0, 0, 0, 0, 0, 0), (0, 0, 1.001875e7, 90, 0, 90), - (0, 0, 1.001875e7, 270, 0, 270), - (0, 0, 1.001875e7, -90, 0, 270), + (0, 0, 1.001875e7, 270, 0, -90), + (0, 0, 1.001875e7, -90, 0, -90), (0, 0, 2.00375e7, 90, 0, 180), - (0, 0, 2.00375e7, 270, 0, 180), - (0, 0, 2.00375e7, -90, 0, 180), + (0, 0, 2.00375e7, 270, 0, -180), + (0, 0, 2.00375e7, -90, 0, -180), ], ) def test_vreckon_unit(deg, lat, lon, srange, az, lato, lono): @@ -43,6 +43,15 @@ def test_vreckon_unit(deg, lat, lon, srange, az, lato, lono): assert isinstance(lon1, float) +def test_negative_lon_stays_negative(): + """Regression test for issue #88: vreckon with negative start longitude + must return a negative (or near-zero) destination longitude, not 358+.""" + lat2, lon2 = vincenty.vreckon(52.22610277777778, -1.2696583333333333, 839.63, 63.02) + assert lat2 == approx(52.22952562862266, rel=1e-6) + assert -180 <= lon2 <= 0, f"lon2={lon2} should be negative for a point west of prime meridian" + assert lon2 == approx(-1.258707, abs=1e-3) + + def test_az_vector(): np = pytest.importorskip("numpy") az = np.array(az1) diff --git a/src/pymap3d/vincenty.py b/src/pymap3d/vincenty.py index d975633..3ed0679 100644 --- a/src/pymap3d/vincenty.py +++ b/src/pymap3d/vincenty.py @@ -433,7 +433,7 @@ def vreckon( # lon2 = pi*((absolute(lon2)/pi) - # 2*ceil(((absolute(lon2)/pi)-1)/2)) * sign(lon2) - lon2 %= tau # follow [0, 360) convention + lon2 = (lon2 + pi) % tau - pi # normalize to [-180, 180) convention if deg: lat2 = degrees(lat2)