Add GIS-friendly exports and update contributor guide

This commit is contained in:
2025-12-13 22:59:10 +01:00
parent 5cf9e86c8b
commit 83ffa457dd
2 changed files with 78 additions and 13 deletions

View File

@@ -1,6 +1,5 @@
#!/usr/bin/env python3
import glob
import math
import os
from osgeo import gdal
@@ -16,26 +15,68 @@ RESAMPLE = "bilinear"
os.makedirs("work", exist_ok=True)
os.makedirs(OUT_DIR, exist_ok=True)
# Open VRT
ds = gdal.Open(VRT_PATH)
if ds is None:
raise SystemExit(f"Could not open {VRT_PATH}. Did you run gdalbuildvrt?")
gdal.UseExceptions()
def open_dataset(path, purpose):
"""Open a dataset and fail fast with context."""
try:
ds = gdal.Open(path)
except RuntimeError as exc:
raise SystemExit(f"{purpose}: {exc}") from exc
if ds is None:
raise SystemExit(f"{purpose}: GDAL returned None for {path}")
return ds
def safe_remove(path):
"""Remove a file if present; return True when deleted."""
try:
os.remove(path)
return True
except FileNotFoundError:
return False
except OSError as exc:
print(f"Warning: could not remove {path}: {exc}")
return False
def cleanup_aux_files():
"""Clear GDAL sidecars and leftover temp files to keep the repo tidy."""
patterns = [
os.path.join("work", "*_tmp.tif"),
os.path.join("work", "*_tmp.tif.aux.xml"),
os.path.join("work", "*.aux.xml"),
os.path.join(RAW_DIR, "*.aux.xml"),
]
removed = 0
for pattern in patterns:
for path in glob.glob(pattern):
if safe_remove(path):
removed += 1
print(f"Cleanup removed {removed} temporary files/sidecars.")
ds = open_dataset(VRT_PATH, f"Could not open {VRT_PATH}. Did you run gdalbuildvrt?")
band = ds.GetRasterBand(1)
# Strategy B: compute global min/max for CURRENT downloaded AOI (full scan for stability)
gmin, gmax = band.ComputeRasterMinMax(False)
print(f"GLOBAL_MIN={gmin}, GLOBAL_MAX={gmax}")
# Export manifest for Unity placement later
manifest_path = os.path.join("export_unity", "tile_index.csv")
with open(manifest_path, "w", encoding="utf-8") as f:
f.write("tile_id,xmin,ymin,xmax,ymax,global_min,global_max,out_res\n")
skipped = 0
written = 0
for tif in sorted(glob.glob(os.path.join(RAW_DIR, "*.tif"))):
tds = gdal.Open(tif)
if tds is None:
print(f"Skipping unreadable: {tif}")
try:
tds = open_dataset(tif, f"Skipping unreadable {tif}")
except SystemExit as exc:
print(exc)
skipped += 1
continue
gt = tds.GetGeoTransform()
@@ -61,17 +102,36 @@ with open(manifest_path, "w", encoding="utf-8") as f:
srcNodata=-9999,
dstNodata=gmin, # fill nodata with global min to avoid deep pits
)
gdal.Warp(tmp_path, ds, options=warp_opts)
try:
gdal.Warp(tmp_path, ds, options=warp_opts)
except RuntimeError as exc:
print(f"Warp failed for {tile_id}: {exc}")
skipped += 1
continue
# Scale to UInt16 (0..65535) using Strategy-B global min/max
trans_opts = gdal.TranslateOptions(
outputType=gdal.GDT_UInt16,
scaleParams=[(gmin, gmax, 0, 65535)],
format="PNG",
creationOptions=["WORLDFILE=YES"], # emit .wld so GIS tools place tiles correctly
)
gdal.Translate(out_path, tmp_path, options=trans_opts)
try:
gdal.Translate(out_path, tmp_path, options=trans_opts)
except RuntimeError as exc:
print(f"Translate failed for {tile_id}: {exc}")
skipped += 1
continue
safe_remove(tmp_path)
safe_remove(f"{tmp_path}.aux.xml")
f.write(f"{tile_id},{xmin},{ymin},{xmax},{ymax},{gmin},{gmax},{OUT_RES}\n")
print(f"Wrote {out_path}")
written += 1
print(f"Manifest: {manifest_path}")
print(f"Summary: wrote {written} tiles; skipped {skipped}.")
cleanup_aux_files()
if skipped:
raise SystemExit(1)