Skip to content

Commit f4f297f

Browse files
authored
Add fast tests for UTM conversions (#537)
1 parent 01f9668 commit f4f297f

2 files changed

Lines changed: 126 additions & 0 deletions

File tree

.github/workflows/ubuntu.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ jobs:
5050
pip install --user .
5151
- name: Test import
5252
run: python -c "import samgeo; print('samgeo import successful')"
53+
- name: Fast unit tests
54+
run: python -m unittest tests.test_utmconv
5355
# - name: PKG-TEST
5456
# run: |
5557
# python -m unittest discover tests/

tests/test_utmconv.py

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
"""Tests for the dependency-free UTM conversion helpers."""
2+
3+
import importlib.util
4+
import math
5+
from pathlib import Path
6+
import unittest
7+
8+
9+
def _load_utmconv():
10+
module_path = Path(__file__).resolve().parents[1] / "samgeo" / "utmconv.py"
11+
spec = importlib.util.spec_from_file_location("utmconv", module_path)
12+
module = importlib.util.module_from_spec(spec)
13+
spec.loader.exec_module(module)
14+
return module
15+
16+
17+
utmconv = _load_utmconv()
18+
19+
20+
class TestUtmconv(unittest.TestCase):
21+
"""Tests for samgeo/utmconv.py."""
22+
23+
def assert_close(self, actual, expected, tolerance):
24+
self.assertLessEqual(abs(actual - expected), tolerance)
25+
26+
def test_degree_radian_conversions_round_trip(self):
27+
for degrees in [-180.0, -45.5, 0.0, 37.25, 180.0]:
28+
radians = utmconv.deg2rad(degrees)
29+
self.assert_close(radians, math.radians(degrees), 1e-12)
30+
self.assert_close(utmconv.rad2deg(radians), degrees, 1e-12)
31+
32+
def test_utm_central_meridian_for_edge_zones(self):
33+
expected_degrees = {
34+
1: -177.0,
35+
30: -3.0,
36+
31: 3.0,
37+
60: 177.0,
38+
}
39+
40+
for zone, central_meridian in expected_degrees.items():
41+
self.assert_close(
42+
utmconv.rad2deg(utmconv.utm_central_meridian(zone)),
43+
central_meridian,
44+
1e-12,
45+
)
46+
47+
def test_latlon_to_utm_known_equator_point(self):
48+
easting, northing = utmconv.latlon2utmxy(
49+
utmconv.deg2rad(0.0),
50+
utmconv.deg2rad(0.0),
51+
31,
52+
)
53+
54+
self.assert_close(easting, 166021.443096, 1e-6)
55+
self.assert_close(northing, 0.0, 1e-9)
56+
57+
def test_latlon_to_utm_known_central_meridian_point(self):
58+
easting, northing = utmconv.latlon2utmxy(
59+
utmconv.deg2rad(-75.0),
60+
utmconv.deg2rad(40.0),
61+
18,
62+
)
63+
64+
self.assert_close(easting, 500000.0, 1e-6)
65+
self.assert_close(northing, 4427757.218472, 1e-6)
66+
67+
def test_latlon_utm_round_trip_for_northern_and_southern_points(self):
68+
cases = [
69+
(-75.0, 40.0, 18, False),
70+
(151.0, -33.0, 56, True),
71+
(179.9, 0.1, 60, False),
72+
(-177.0, -79.9, 1, True),
73+
]
74+
75+
for longitude, latitude, zone, is_south_hemi in cases:
76+
with self.subTest(
77+
longitude=longitude,
78+
latitude=latitude,
79+
zone=zone,
80+
is_south_hemi=is_south_hemi,
81+
):
82+
easting, northing = utmconv.latlon2utmxy(
83+
utmconv.deg2rad(longitude),
84+
utmconv.deg2rad(latitude),
85+
zone,
86+
)
87+
round_trip_longitude, round_trip_latitude = utmconv.utmxy2latlon(
88+
easting,
89+
northing,
90+
zone,
91+
is_south_hemi,
92+
)
93+
94+
self.assert_close(
95+
utmconv.rad2deg(round_trip_longitude), longitude, 1e-6
96+
)
97+
self.assert_close(utmconv.rad2deg(round_trip_latitude), latitude, 2e-5)
98+
99+
def test_southern_hemisphere_false_northing_is_reversible(self):
100+
longitude = 151.0
101+
latitude = -33.0
102+
zone = 56
103+
104+
easting, northing = utmconv.latlon2utmxy(
105+
utmconv.deg2rad(longitude),
106+
utmconv.deg2rad(latitude),
107+
zone,
108+
)
109+
110+
self.assertGreater(northing, 0.0)
111+
112+
round_trip_longitude, round_trip_latitude = utmconv.utmxy2latlon(
113+
easting,
114+
northing,
115+
zone,
116+
True,
117+
)
118+
119+
self.assert_close(utmconv.rad2deg(round_trip_longitude), longitude, 1e-6)
120+
self.assert_close(utmconv.rad2deg(round_trip_latitude), latitude, 2e-5)
121+
122+
123+
if __name__ == "__main__":
124+
unittest.main()

0 commit comments

Comments
 (0)