diff options
Diffstat (limited to 'tests/test_plateaus.py')
| -rw-r--r-- | tests/test_plateaus.py | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/tests/test_plateaus.py b/tests/test_plateaus.py new file mode 100644 index 0000000..00da0ed --- /dev/null +++ b/tests/test_plateaus.py @@ -0,0 +1,78 @@ +# map/tests/test_plateaus.py +import json +import unittest + +import numpy as np + +from mapgen import plateaus as PL +from mapgen.sphere import east_north, great_circle_point, latlon_to_xyz +from tests.helpers import small_grid + +R = 12742.0 +P1 = {"name": "east-flank", "center": [-39.9, -18.0], "area_km2": 3.0e6, "elongation": 1.9, "azimuth_deg": 30.0, + "top_m": [1500.0, 3000.0]} +P2 = {"name": "plateau-02", "center": [-0.4, 176.6], "area_km2": 1.0e6, "top_m": [1000.0, 1500.0], "islands": True} + + +def at(lat, lon): + return latlon_to_xyz(lat, lon)[None] + + +class PlateauGeometryTest(unittest.TestCase): + def test_centre_inside_and_area_close_to_config(self): + g = small_grid(4) + for p in (P1, P2): + self.assertLess(PL.rho(at(*p["center"]), p, 1296, R)[0], 1e-6) + area = g.area_km2[PL.rho(g.xyz, p, 1296, R) < 1.0].sum() + self.assertAlmostEqual(area / p["area_km2"], 1.0, delta=0.2, msg=p["name"]) + + def test_long_axis_follows_the_azimuth(self): + a, b = PL.semi_axes(P1) + self.assertAlmostEqual(a / b, 1.9) + self.assertAlmostEqual(np.pi * a * b, P1["area_km2"], delta=1.0) + c = latlon_to_xyz(*P1["center"]) + e, n = east_north(c[None]) + az = np.radians(30.0) + along = np.sin(az) * e[0] + np.cos(az) * n[0] + across = np.cos(az) * e[0] - np.sin(az) * n[0] + self.assertLess(PL.rho(great_circle_point(c, along, 0.8 * a, R)[None], P1, 1296, R)[0], 1.0) + self.assertGreater(PL.rho(great_circle_point(c, across, 0.8 * a, R)[None], P1, 1296, R)[0], 1.0) + + def test_features_are_deterministic_inside_and_json_ready(self): + f = PL.features(P2, 1296, R) + self.assertEqual(f, PL.features(P2, 1296, R)) + json.dumps(f) + self.assertTrue(6 <= len(f["cones"]) <= 20) + self.assertTrue(1 <= len(f["calderas"]) <= 3) + self.assertTrue(3 <= sum(c["island"] for c in f["cones"]) <= 6) + for c in f["cones"] + f["calderas"]: + self.assertLess(PL.rho(at(c["lat"], c["lon"]), P2, 1296, R)[0], 0.86) + self.assertFalse(any(c["island"] for c in PL.features(P1, 1296, R)["cones"])) + self.assertEqual(PL.features({**P1, "vent": 0.0}, 1296, R)["cones"], []) + + def test_surface_depth_follows_top_m(self): + g = small_grid(4) + inner = g.xyz[PL.rho(g.xyz, P1, 1296, R) < 0.5] + z = PL.surface(inner, P1, {"cones": [], "calderas": []}, 1296, R, np.full(len(inner), -5900.0)) + self.assertTrue(np.all(z <= -P1["top_m"][0] + PL.RELIEF_M + 1e-6)) + self.assertTrue(np.all(z >= -P1["top_m"][1] - PL.RELIEF_M - 1e-6)) + + def test_apply_hidden_clamp_islands_and_nothing_else(self): + g = small_grid(4) + plats = [P1, P2] + ids = PL.cell_ids(g.xyz, plats, 1296, R) + self.assertGreater((ids == 0).sum(), 100) + z = PL.apply(g, np.full(g.n, -6000.0), plats, ids, 1296) + self.assertLessEqual(z[ids == 0].max(), PL.HIDDEN_MAX_M) + self.assertGreater(z.max(), 0.0, "island plateau: small volcanic islands") + changed_outside = (ids < 0) & (z != -6000.0) + self.assertLessEqual(changed_outside.sum(), 6, "only islands' nearest cells may lie outside the outline") + + def test_outline_across_the_antimeridian_and_near_the_pole(self): + p = {"name": "plateau-11", "center": [77.0, 179.0], "area_km2": 0.9e6, "top_m": [1000.0, 1500.0]} + self.assertLess(PL.rho(at(77.0, 179.8), p, 1296, R)[0], 0.3) + self.assertLess(PL.rho(at(77.0, -179.8), p, 1296, R)[0], 0.3) + q = {"name": "polar", "center": [88.0, 0.0], "area_km2": 1.0e6, "top_m": [1000.0, 1500.0]} + self.assertLess(PL.rho(at(89.9, 90.0), q, 1296, R)[0], 1.0) + self.assertLess(PL.rho(at(89.9, -90.0), q, 1296, R)[0], 1.0) + self.assertTrue(np.all(np.isfinite(PL.rho(small_grid(3).xyz, q, 1296, R)))) |
