worldgen

git clone https://git.godosa.eu/worldgen

master

raw · 2945 bytes

# map/tests/test_zones.py
import tempfile
import unittest
from pathlib import Path

import numpy as np
from PIL import Image

from mapgen import sketch as SK, zones as ZN
from mapgen.sphere import east_north, great_circle_point, latlon_to_xyz
from tests.helpers import make_ctx

R = 12742.0
R1 = {"name": "R1", "field": "o2", "center": [-5.6, -118.8], "radius_km": 3200.0, "v": 1.0}
L1 = {"name": "L1", "field": "gravity", "center": [-26.3, -133.7], "radius_km": 2200.0, "v": -0.6}


def ray(zone, az_deg, step_km=5.0):
    p0 = latlon_to_xyz(*zone["center"])
    e, n = east_north(p0[None])
    a = np.radians(az_deg)
    t = np.sin(a) * e[0] + np.cos(a) * n[0]
    s = np.arange(0.0, 1.4 * zone["radius_km"], step_km)
    return s, np.array([great_circle_point(p0, t, si, R) for si in s])


class ZoneProfileTest(unittest.TestCase):
    def test_peak_at_the_centre_and_nothing_beyond_the_warped_radius(self):
        for z in (R1, L1):
            s, pts = ray(z, 40.0)
            f = ZN.contribution(pts, z, 1296, R)
            self.assertAlmostEqual(f[0], z["v"])
            self.assertTrue(np.all(f[s > z["radius_km"] / (1 - ZN.WARP) + 1] == 0.0))

    def test_steepest_change_is_hard_to_notice_over_a_days_walk(self):
        """≤ 0.23 O₂ points and ≤ 0.014 g per 30 km, for the strongest O₂ and low-gravity zones."""
        for z, per_unit, limit in ((R1, 0.21 * 0.5 * 100.0, 0.23), (L1, 1.05 * 0.7, 0.014)):
            worst = 0.0
            for az in range(0, 360, 5):
                _, pts = ray(z, az)
                f = ZN.contribution(pts, z, 1296, R) * per_unit
                worst = max(worst, float(np.max(np.abs(np.diff(f)))) / 5.0 * 30.0)
            self.assertLessEqual(worst, limit, z["name"])

    def test_outline_is_not_a_circle(self):
        at = [ZN.contribution(ray(R1, az)[1][[400]], R1, 1296, R)[0] for az in range(0, 360, 30)]   # 2,000 km out
        self.assertGreater(max(at) - min(at), 0.02)


class SketchZonesTest(unittest.TestCase):
    def test_config_zones_add_to_painted_masks_and_clip(self):
        root = Path(tempfile.mkdtemp())
        (root / "sketch").mkdir()
        (root / "masks").mkdir()
        for n in SK.SKETCH:
            Image.fromarray(np.zeros((10, 20), np.uint8), "L").save(root / "sketch" / f"{n}.png")
        Image.fromarray(np.full((10, 20), 191, np.uint8), "L").save(root / "masks" / "o2_zones.png")   # ≈ +0.5
        zones = [{**R1, "center": [0.0, 0.0]}, {**L1, "center": [0.0, 0.0]}]
        ctx = make_ctx(2, tect={"plate": [], "zone": zones}, root=root)
        out = SK.run(ctx)
        g = ctx.grid
        c, far = g.cell_index(0.0, 0.0), g.cell_index(0.0, 180.0)
        self.assertEqual(out["m_o2_zones"][c], 1.0, "mask + zone, clipped")
        self.assertAlmostEqual(out["m_o2_zones"][far], 0.498, places=2)
        self.assertAlmostEqual(out["m_gravity_zones"][c], -0.6, delta=0.05)
        self.assertEqual(out["m_gravity_zones"][far], 0.0)