96 lines
3.7 KiB
Python
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()
|