import json import math import tempfile import unittest from pathlib import Path import numpy as np from PIL import Image import export as EX import serve import tiles as T from mapgen import config as C from tests.test_serve import built_world def _spot(): """A river mouth on the test world: land, sea and a river in one small square.""" a = np.load(built_world() / "out" / "r2" / "cells.npz") mouths = np.where(a["river"].astype(bool) & a["ocean"][a["recv"]].astype(bool))[0] i = int(mouths[np.argmax(a["discharge_km3_yr"][mouths])]) t = np.linspace(0, 1, 101)[:, None] # from the mouth toward its sea cell … p = a["g_xyz"][i] * (1 - t) + a["g_xyz"][a["recv"][i]] * t p /= np.linalg.norm(p, axis=1, keepdims=True) lat, lon = np.degrees(np.arcsin(p[:, 2])), np.degrees(np.arctan2(p[:, 1], p[:, 0])) src = T.TileSource(serve.World(built_world(), 2), seed=int(C.load(built_world())[0]["build"]["seed"]), cache_dir=Path(tempfile.mkdtemp()), regions_dir=Path(tempfile.mkdtemp())) wet = src.surface_at(lat, lon, 1.0)[1] k = int(np.argmax(wet)) if wet.any() else 50 # … to where the map shows the sea: the coast return float(lat[k]), float(lon[k]) class ExportTest(unittest.TestCase): @classmethod def setUpClass(cls): cls.root = built_world() cls.lat, cls.lon = _spot() cls.pins = Path(tempfile.mkdtemp()) / "pins.json" cls.pins.write_text(json.dumps({"pins": [{"id": "pin-1", "name": "Here", "lat": cls.lat, "lon": cls.lon, "lore": "somewhere", "note": "", "epoch": None}, {"id": "pin-2", "name": "Far", "lat": -cls.lat, "lon": cls.lon + 90}]})) cls.out = Path(tempfile.mkdtemp()) cls.d = EX.export(cls.root, 2, cls.lat, cls.lon, size_km=200, res_m=2000, out_dir=cls.out, name="t", pins_path=cls.pins, regions_dir=Path(tempfile.mkdtemp())) cls.meta = json.loads((cls.d / "meta.json").read_text()) cls.n = cls.meta["samples"] cls.h = np.fromfile(cls.d / "height.f32", dtype="