terrain2/bounds.py
Fabio Micheluz 9603735519 first commit
2026-02-12 17:21:04 +01:00

96 lines
3.7 KiB
Python

#!/usr/bin/env python3
import argparse, sqlite3, sys
def fetch_one(cur, sql, args=()):
row = cur.execute(sql, args).fetchone()
return row[0] if row else None
def main():
ap = argparse.ArgumentParser(
description="Normalizza bounds (W,S,E,N) e imposta center/minzoom/maxzoom in un MBTiles."
)
ap.add_argument("mbtiles", help="Percorso al file .mbtiles")
ap.add_argument("--zoom", type=int, default=None,
help="Zoom del center da impostare (default: usa center esistente o media min/max dalle tile)")
ap.add_argument("--minzoom", type=int, default=None,
help="Forza minzoom (default: dai livelli in 'tiles')")
ap.add_argument("--maxzoom", type=int, default=None,
help="Forza maxzoom (default: dai livelli in 'tiles')")
args = ap.parse_args()
conn = sqlite3.connect(args.mbtiles)
cur = conn.cursor()
# --- 1) leggi bounds correnti
b_raw = fetch_one(cur, "SELECT value FROM metadata WHERE name='bounds';")
if not b_raw:
sys.exit("ERRORE: 'bounds' mancante nella tabella metadata.")
try:
x1, y1, x2, y2 = [float(t) for t in b_raw.split(",")]
except Exception:
sys.exit(f"ERRORE: bounds non parseable: {b_raw}")
# normalizza ordine W,S,E,N (min/max su lon e lat)
W, E = sorted((x1, x2))
S, N = sorted((y1, y2))
bounds = f"{W:.6f},{S:.6f},{E:.6f},{N:.6f}"
# --- 2) min/max zoom: da tiles salvo override
minz = fetch_one(cur, "SELECT MIN(zoom_level) FROM tiles;")
maxz = fetch_one(cur, "SELECT MAX(zoom_level) FROM tiles;")
# fallback se tiles non esiste o vuota
try:
minz = int(minz) if minz is not None else None
maxz = int(maxz) if maxz is not None else None
except Exception:
minz = maxz = None
if args.minzoom is not None: minz = int(args.minzoom)
if args.maxzoom is not None: maxz = int(args.maxzoom)
# --- 3) center: lon/lat dal bbox; zoom = argomento > zoom esistente > media min/max > 0
center_existing = fetch_one(cur, "SELECT value FROM metadata WHERE name='center';")
center_z_existing = None
if center_existing:
parts = [p.strip() for p in center_existing.split(",")]
if len(parts) >= 3 and parts[2] != "":
center_z_existing = parts[2]
if args.zoom is not None:
z = int(args.zoom)
elif center_z_existing is not None:
try:
z = int(center_z_existing)
except Exception:
z = None
else:
z = int((minz + maxz) // 2) if (minz is not None and maxz is not None) else 0
ctr_lon = (W + E) / 2.0
ctr_lat = (S + N) / 2.0
center = f"{ctr_lon:.6f},{ctr_lat:.6f},{z}"
# --- 4) scrittura: crea metadata se manca, REPLACE dei valori
cur.execute("CREATE TABLE IF NOT EXISTS metadata (name TEXT PRIMARY KEY, value TEXT)")
cur.execute("REPLACE INTO metadata(name,value) VALUES(?,?)", ("bounds", bounds))
cur.execute("REPLACE INTO metadata(name,value) VALUES(?,?)", ("center", center))
if minz is not None:
cur.execute("REPLACE INTO metadata(name,value) VALUES(?,?)", ("minzoom", str(minz)))
if maxz is not None:
cur.execute("REPLACE INTO metadata(name,value) VALUES(?,?)", ("maxzoom", str(maxz)))
conn.commit()
# --- 5) stampa riepilogo
print("OK")
for k in ("bounds","center","minzoom","maxzoom"):
v = fetch_one(cur, "SELECT value FROM metadata WHERE name=?", (k,))
print(f"{k} = {v}")
zminmax = cur.execute("SELECT MIN(zoom_level), MAX(zoom_level) FROM tiles;").fetchone()
if zminmax and all(v is not None for v in zminmax):
print(f"zoom (tiles) = {zminmax[0]}..{zminmax[1]}")
conn.close()
if __name__ == "__main__":
main()