aboutsummaryrefslogtreecommitdiffziptar.gz
path: root/mapgen/zones.py
diff options
context:
space:
mode:
authorgodosa <godosa@godosa.eu>2026-10-06 23:52:03 +0200
committergodosa <godosa@godosa.eu>2026-10-06 23:52:03 +0200
commit346b1c5195bffc71ceaa9262453e3c189656400b (patch)
tree01ac0d31e2724cd6abcc689a5a228e2cbea2f6cf /mapgen/zones.py
downloadworldgen-346b1c5195bffc71ceaa9262453e3c189656400b.tar.gz
worldgen-346b1c5195bffc71ceaa9262453e3c189656400b.zip
worldgen: initial public history
Diffstat (limited to 'mapgen/zones.py')
-rw-r--r--mapgen/zones.py38
1 files changed, 38 insertions, 0 deletions
diff --git a/mapgen/zones.py b/mapgen/zones.py
new file mode 100644
index 0000000..46386f7
--- /dev/null
+++ b/mapgen/zones.py
@@ -0,0 +1,38 @@
+"""Config O₂ / low-gravity zones: smooth, noise-warped discs in mask units
+(O₂ ×(1 + 0.5 v), gravity ×(1 + 0.7 v)), added to the painted masks in the `sketch` stage. Very gradual: at most
+≈ 1.9 · |effect| / radius per km (≤ 0.23 O₂ points and ≤ 0.014 g per 30 km for the configured zones)."""
+from __future__ import annotations
+
+import numpy as np
+
+from .noise import fbm, name_seed
+from .sphere import gc_dist_km, latlon_to_xyz
+
+WARP = 0.2 # outline wobble: distances stretched or shrunk by up to 20 % (low-frequency noise)
+WARP_FREQ = 1.0
+
+
+def smootherstep(t):
+ t = np.clip(t, 0.0, 1.0)
+ return t * t * t * (t * (6.0 * t - 15.0) + 10.0)
+
+
+def contribution(xyz, zone: dict, seed: int, radius_km: float):
+ """v · (1 − smootherstep(d′ / r)), d′ = d · (1 + WARP · warp): v at the centre, 0 beyond r / (1 − WARP)."""
+ xyz = np.asarray(xyz, dtype=np.float64)
+ d = gc_dist_km(xyz, latlon_to_xyz(*zone["center"]), radius_km)
+ r = float(zone["radius_km"])
+ out = np.zeros(len(xyz))
+ near = d < r / (1.0 - WARP)
+ if near.any():
+ w = np.clip(2.0 * fbm(xyz[near], name_seed(seed, zone["name"]), 3, WARP_FREQ), -1.0, 1.0)
+ out[near] = zone["v"] * (1.0 - smootherstep(d[near] * (1.0 + WARP * w) / r))
+ return out
+
+
+def masks(xyz, zones: list, seed: int, radius_km: float):
+ """(m_o2, m_gravity): the config zones summed (the caller adds the painted masks and clips to [−1, 1])."""
+ m = {"o2": np.zeros(len(xyz)), "gravity": np.zeros(len(xyz))}
+ for z in zones:
+ m[z["field"]] += contribution(xyz, z, seed, radius_km)
+ return m["o2"], m["gravity"]