diff options
| author | godosa <godosa@godosa.eu> | 2026-10-06 23:52:03 +0200 |
|---|---|---|
| committer | godosa <godosa@godosa.eu> | 2026-10-06 23:52:03 +0200 |
| commit | 346b1c5195bffc71ceaa9262453e3c189656400b (patch) | |
| tree | 01ac0d31e2724cd6abcc689a5a228e2cbea2f6cf /tests/test_sphere_noise.py | |
| download | worldgen-346b1c5195bffc71ceaa9262453e3c189656400b.tar.gz worldgen-346b1c5195bffc71ceaa9262453e3c189656400b.zip | |
worldgen: initial public history
Diffstat (limited to 'tests/test_sphere_noise.py')
| -rw-r--r-- | tests/test_sphere_noise.py | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/tests/test_sphere_noise.py b/tests/test_sphere_noise.py new file mode 100644 index 0000000..a3c325e --- /dev/null +++ b/tests/test_sphere_noise.py @@ -0,0 +1,86 @@ +import unittest + +import numpy as np + +from mapgen import noise as N +from mapgen import sphere as S + + +class SphereTest(unittest.TestCase): + def test_roundtrip(self): + lat = np.array([0.0, 45.0, -60.0, 89.0]) + lon = np.array([0.0, 120.0, -170.0, 10.0]) + la, lo = S.xyz_to_latlon(S.latlon_to_xyz(lat, lon)) + np.testing.assert_allclose(la, lat, atol=1e-9) + np.testing.assert_allclose(lo, lon, atol=1e-9) + + def test_east_north_at_pole(self): + p = S.latlon_to_xyz(np.array([90.0, -90.0, 0.0]), np.array([0.0, 0.0, 0.0])) + e, n = S.east_north(p) + self.assertTrue(np.all(np.isfinite(e)) and np.all(np.isfinite(n))) + np.testing.assert_allclose(np.linalg.norm(e, axis=1), 1.0) + np.testing.assert_allclose(np.sum(e * p, axis=1), 0.0, atol=1e-12) + # at the equator/prime meridian east = +y, north = +z + np.testing.assert_allclose(e[2], [0, 1, 0], atol=1e-12) + np.testing.assert_allclose(n[2], [0, 0, 1], atol=1e-12) + + def test_motion_velocity_matches_request(self): + R = 12742.0 + om = S.motion_to_omega(10.0, 20.0, 90.0, 5.0, R) # due east, 5 cm/yr + p = S.latlon_to_xyz(np.array([10.0]), np.array([20.0])) + v = S.velocity(p, om, R)[0] + e, n = S.east_north(p) + self.assertAlmostEqual(float(np.dot(v, e[0])), 0.05, places=6) + self.assertAlmostEqual(float(np.dot(v, n[0])), 0.0, places=6) + + def test_zero_speed_is_zero_velocity(self): + om = S.motion_to_omega(0.0, 0.0, 45.0, 0.0, 12742.0) + self.assertTrue(np.allclose(om, 0.0)) + + def test_rotate_and_azimuth(self): + p = S.latlon_to_xyz(np.array([0.0]), np.array([0.0])) + e, n = S.east_north(p) + r = S.rotate_about(p, e, np.pi / 2) # CCW seen from outside: east -> north + np.testing.assert_allclose(r, n, atol=1e-12) + q = S.latlon_to_xyz(np.array([0.0, 10.0]), np.array([10.0, 0.0])) + np.testing.assert_allclose(S.azimuth_deg(p[0], q), [90.0, 0.0], atol=1e-9) + + def test_great_circle_point(self): + p0 = S.latlon_to_xyz(np.array([0.0]), np.array([0.0]))[0] + e, _ = S.east_north(p0[None]) + R = 12742.0 + q = S.great_circle_point(p0, e[0], np.pi * R / 2, R) # quarter turn east + np.testing.assert_allclose(q, [0, 1, 0], atol=1e-12) + + +class NoiseTest(unittest.TestCase): + def test_deterministic_and_bounded(self): + rng = np.random.default_rng(0) + p = rng.normal(size=(5000, 3)) + p /= np.linalg.norm(p, axis=1, keepdims=True) + a = N.fbm(p, 42) + b = N.fbm(p, 42) + c = N.fbm(p, 43) + np.testing.assert_array_equal(a, b) + self.assertFalse(np.allclose(a, c)) + self.assertTrue(np.all(np.abs(a) <= 1.0)) + self.assertGreater(a.std(), 0.05) + r = N.ridged(p, 1) + self.assertTrue(np.all((r >= 0) & (r <= 1))) + + def test_continuity(self): + p = np.array([[0.3, 0.4, 0.5]]) + d = N.fbm(p + 1e-6, 5) - N.fbm(p, 5) + self.assertLess(abs(d[0]), 1e-3) + + +class CompiledNoiseTest(unittest.TestCase): + def test_compiled_value_noise_matches_numpy(self): + from mapgen import noise as N + if N._noise_jit is None: + self.skipTest("numba not installed") + rng = np.random.default_rng(0) + for scale in (1.0, 37.0, 1e4, 1e7): + for seed in (0, 4242, 123456789, -5, 2 ** 40): + p = rng.normal(0, scale, (2000, 3)) + self.assertTrue(np.array_equal(N.value_noise(p, seed), N._value_noise(p, seed)), (scale, seed)) |
