feat(client): render province boundaries on planetary map (#927, D-205)

Export pre-computed drainage basin boundaries from atlas_province_boundaries
into markers.json during generate_atlas. AtlasMarkerOverlay draws province
polylines with semi-transparent fill under the political_zones overlay.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-03 16:12:59 +02:00
co-authored by Claude Opus 4.6
parent d869435eee
commit 13259dbfd5
2 changed files with 80 additions and 2 deletions
+45
View File
@@ -1162,6 +1162,7 @@ def load_markers(body_dir: Path) -> dict:
"cities": [],
"railroads": [],
"pois": [],
"provinces": [],
}
@@ -1310,6 +1311,38 @@ def process_body(
return {"status": "generated", "markers": markers}
def query_province_boundaries(conn: sqlite3.Connection, body_id: str) -> list[dict]:
"""Read pre-computed province boundaries for a body from atlas_province_boundaries."""
rows = conn.execute(
"SELECT basin_id, path, area_pct FROM atlas_province_boundaries WHERE body_id = ? ORDER BY basin_id",
(body_id,),
).fetchall()
provinces = []
for row in rows:
provinces.append({
"basin_id": row[0],
"path": json.loads(row[1]),
"area_pct": row[2],
})
return provinces
def inject_provinces_into_markers(conn: sqlite3.Connection, body_id: str, body_dir: Path) -> bool:
"""Add provinces array to an existing markers.json. Returns True if written."""
markers_path = body_dir / "markers.json"
if not markers_path.exists():
return False
provinces = query_province_boundaries(conn, body_id)
if not provinces:
return False
with open(markers_path) as f:
markers = json.load(f)
markers["provinces"] = provinces
with open(markers_path, "w") as f:
json.dump(markers, f, indent=2)
return True
def main():
parser = argparse.ArgumentParser(
description="Atlas generation — terrain-aware city placement and infrastructure (#832)"
@@ -1406,6 +1439,18 @@ def main():
n_errors += 1
print(f" [{i+1}/{len(bodies)}] {body_id:20s} ERROR: {result.get('message', '')}")
# Inject province boundaries into markers.json for bodies that have them
if not args.dry_run:
n_provinces = 0
for body_info in bodies:
body_id = body_info["body_id"]
terrain_ref = body_info["terrain_reference"]
body_dir = REPO_ROOT / Path(terrain_ref).parent
if inject_provinces_into_markers(conn, body_id, body_dir):
n_provinces += 1
if n_provinces > 0:
print(f"\n Province boundaries injected into {n_provinces} markers.json files.")
if not args.dry_run:
# Stamp generator metadata (#855, #856) together with the atlas data
# in a single commit — atlas data + stamp land atomically, and the