From 346b1c5195bffc71ceaa9262453e3c189656400b Mon Sep 17 00:00:00 2001 From: godosa Date: Tue, 6 Oct 2026 23:52:03 +0200 Subject: worldgen: initial public history --- tests/test_grid.py | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 tests/test_grid.py (limited to 'tests/test_grid.py') diff --git a/tests/test_grid.py b/tests/test_grid.py new file mode 100644 index 0000000..a6b0848 --- /dev/null +++ b/tests/test_grid.py @@ -0,0 +1,83 @@ +import unittest + +import numpy as np + +from mapgen.grid import Grid +from tests.helpers import small_grid + + +class GridTest(unittest.TestCase): + def test_counts_and_pentagons(self): + g = small_grid(2) + self.assertEqual(g.n, 5882) + self.assertTrue(np.all(np.diff(g.ids.astype(np.int64)) > 0)) + self.assertEqual(int(np.sum(g.counts == 5)), 12) + self.assertEqual(int(np.sum(g.counts == 6)), g.n - 12) + + def test_neighbours_symmetric(self): + g = small_grid(2) + pairs = set(zip(g.src.tolist(), g.dst.tolist())) + self.assertTrue(all((b, a) in pairs for a, b in pairs)) + + def test_area_sums_to_sphere(self): + g = small_grid(2) + self.assertAlmostEqual(g.area_km2.sum() / (4 * np.pi * 12742.0**2), 1.0, places=6) + + def test_spacing_and_tangents(self): + g = small_grid(2) + self.assertTrue(500 < g.spacing_km < 800) # res 2 ≈ 632 km + np.testing.assert_allclose(np.linalg.norm(g.edge_tangents, axis=1), 1.0) + np.testing.assert_allclose(np.sum(g.edge_tangents * g.xyz[g.src], axis=1), 0.0, atol=1e-12) + + def test_roundtrip_arrays_and_lookup(self): + g = small_grid(2) + h = Grid.from_arrays(g.to_arrays(), g.res, g.radius_km) + np.testing.assert_array_equal(h.nbr_idx, g.nbr_idx) + i = g.cell_index(10.0, 20.0) + self.assertLess(abs(g.lat[i] - 10.0), 5.0) + + +class CellParentsTest(unittest.TestCase): + def test_same_as_h3_cell_to_parent(self): + import h3.api.basic_int as h3 + import numpy as np + from mapgen.grid import cell_parents + rng = np.random.default_rng(5) + for res in (1, 3, 6, 9): + cells = [h3.latlng_to_cell(float(la), float(lo), res + int(k)) + for la, lo, k in zip(rng.uniform(-90, 90, 300), rng.uniform(-180, 180, 300), rng.integers(0, 4, 300))] + pent = h3.get_pentagons(max(res - 2, 0))[:2] + [h3.latlng_to_cell(10.0, 20.0, max(res - 2, 0))] + cells += [c for p in pent for c in h3.cell_to_children(p, res)] # incl. pentagons + for pr in range(0, res + 1): + want = np.array([h3.cell_to_parent(c, pr) for c in cells], np.uint64) + self.assertTrue(np.array_equal(cell_parents(cells, pr), want), (res, pr)) + with self.assertRaises(ValueError): + cell_parents([h3.latlng_to_cell(0.0, 0.0, 2)], 3) + + +class EdgeBlocksTest(unittest.TestCase): + def test_blocked_edge_fields_same_as_whole(self): + from unittest import mock + from mapgen import grid as GR + from mapgen import plates as PL + from mapgen.sphere import tangent_dir + g = small_grid(3) + xyz, src, dst = g.xyz, g.src, g.dst + want_t = tangent_dir(xyz[src], xyz[dst]) # the whole-array formulas, written out + want_km = g.radius_km * np.arccos(np.clip(np.sum(xyz[src] * xyz[dst], axis=1), -1.0, 1.0)) + vel = np.random.default_rng(2).normal(size=(g.n, 3)) + rel = vel[dst] - vel[src] + along = np.sum(rel * want_t, axis=1) + want_tang = np.linalg.norm(rel - along[:, None] * want_t, axis=1) + with mock.patch.object(GR, "EDGE_BLOCK", 997): # many uneven blocks + g2 = small_grid(3) + self.assertTrue(np.array_equal(g2.edge_tangents, want_t)) + self.assertTrue(np.array_equal(g2.edge_km, want_km)) + conv, tang = PL.edge_convergence(g2, vel) + self.assertTrue(np.array_equal(conv, -along)) + self.assertTrue(np.array_equal(tang, want_tang)) + self.assertGreater(len(GR.edge_blocks(len(dst), 997)), 3) + with mock.patch.object(GR, "EDGE_BLOCK", 997): + for idx in (src, dst): + self.assertTrue(np.array_equal(GR.rowdot_at(vel, idx, want_t), np.sum(vel[idx] * want_t, axis=1))) + self.assertTrue(np.array_equal(GR.rowdot_at(vel, idx, want_t), np.sum(want_t * vel[idx], axis=1))) -- cgit