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

139 lines
5.2 KiB
Bash
Executable file

#!/usr/bin/env bash
set -euo pipefail
# --------------------------------------------------------------------
# Imposta metadati essenziali in un file .mbtiles (schema XYZ)
# - Calcola bounds (ovest,sud,est,nord) dal raster sorgente (GeoTIFF/COG)
# - Calcola center (lon,lat,zoom)
# - Legge min/max zoom dalla tabella 'tiles' e li scrive nella 'metadata'
# - Imposta name/format/type/attribution
#
# Requisiti: gdalinfo (GDAL), jq, sqlite3
# --------------------------------------------------------------------
# USO:
# ./mbtiles_set_metadata.sh \
# --mbtiles aa.mbtiles \
# --raster aa_rgb.tif \
# [--name "Terrain RGB Adamello"] \
# [--type overlay|baselayer] \
# [--format png|jpg] \
# [--zoom <Zcenter>] \
# [--attribution " Copernicus DEM (GLO-30), ESA"]
#
# NOTE:
# - 'bounds' e 'center' sono calcolati in EPSG:4326 (lon/lat).
# - Se il raster non riassume esattamente lestensione delle tile,
# passa un raster "clip" coerente con larea tilata.
# - Lo script usa REPLACE INTO per compatibilit con SQLite < 3.24.
# --------------------------------------------------------------------
# ---------- parsing argomenti ----------
MBTILES=""
RASTER=""
LAYER_NAME=""
LAYER_TYPE="overlay"
FORMAT="png"
CENTER_Z=""
ATTRIBUTION=""
while [[ $# -gt 0 ]]; do
case "$1" in
--mbtiles) MBTILES="$2"; shift 2;;
--raster) RASTER="$2"; shift 2;;
--name) LAYER_NAME="$2"; shift 2;;
--type) LAYER_TYPE="$2"; shift 2;;
--format) FORMAT="$2"; shift 2;;
--zoom) CENTER_Z="$2"; shift 2;;
--attribution) ATTRIBUTION="$2"; shift 2;;
-h|--help)
sed -n '1,80p' "$0"; exit 0;;
*)
echo "Argomento sconosciuto: $1" >&2; exit 1;;
esac
done
if [[ -z "$MBTILES" || -z "$RASTER" ]]; then
echo "Uso: $0 --mbtiles <file.mbtiles> --raster <raster.tif> [opzioni]" >&2
exit 1
fi
if [[ ! -f "$MBTILES" ]]; then
echo "File MBTiles non trovato: $MBTILES" >&2; exit 1
fi
if [[ ! -f "$RASTER" ]]; then
echo "Raster non trovato: $RASTER" >&2; exit 1
fi
command -v gdalinfo >/dev/null || { echo "gdalinfo non trovato"; exit 1; }
command -v jq >/dev/null || { echo "jq non trovato"; exit 1; }
command -v sqlite3 >/dev/null || { echo "sqlite3 non trovato"; exit 1; }
# ---------- step 1: calcolo bounds dal raster (EPSG:4326) ----------
# Usiamo wgs84Extent se presente, altrimenti cornerCoordinates.
# gdalinfo -json fornisce geometrie e corner coords in lon/lat.
export LC_ALL=C
export LANG=C
GDAL_JSON="$(gdalinfo -json "$RASTER")"
has_wgs84=$(echo "$GDAL_JSON" | jq 'has("wgs84Extent")')
if [[ "$has_wgs84" == "true" ]]; then
# Polygon ring: [ [minLon,minLat], [maxLon,minLat], [maxLon,maxLat], [minLon,maxLat], ... ]
read -r MINLON MINLAT MAXLON MAXLAT <<<"$(echo "$GDAL_JSON" \
| jq -r '.wgs84Extent.coordinates[0] |
[.[0][0], .[0][1], .[2][0], .[2][1]] | @tsv')"
else
# cornerCoordinates: upperLeft, lowerLeft, upperRight, lowerRight (lon,lat)
read -r MINLON MINLAT MAXLON MAXLAT <<<"$(echo "$GDAL_JSON" \
| jq -r '.cornerCoordinates as $c |
[$c.lowerLeft[0], $c.lowerLeft[1], $c.upperRight[0], $c.upperRight[1]] | @tsv')"
fi
# Arrotonda a 6 decimali per compattare la stringa
printf -v BOUNDS "%.6f,%.6f,%.6f,%.6f" "$MINLON" "$MINLAT" "$MAXLON" "$MAXLAT"
# ---------- step 2: calcolo center (lon,lat,zoom) ----------
# lon,lat = met dei bounds; zoom: se non fornito, media tra min e max zoom presenti nelle tile
CTR_LON=$(awk -v a="$MINLON" -v b="$MAXLON" 'BEGIN{printf "%.6f",(a+b)/2.0}')
CTR_LAT=$(awk -v a="$MINLAT" -v b="$MAXLAT" 'BEGIN{printf "%.6f",(a+b)/2.0}')
# Leggi min/max zoom dalla tabella 'tiles'
read -r TMIN TMAX <<<"$(sqlite3 "$MBTILES" "SELECT MIN(zoom_level), MAX(zoom_level) FROM tiles;")"
if [[ -z "$TMIN" || -z "$TMAX" ]]; then
echo "Attenzione: tabella 'tiles' vuota o mancante in $MBTILES" >&2
TMIN=0; TMAX=0
fi
if [[ -z "${CENTER_Z}" ]]; then
CENTER_Z=$(( (TMIN + TMAX) / 2 ))
fi
CENTER="${CTR_LON},${CTR_LAT},${CENTER_Z}"
# ---------- step 3: definisci name/format/type/attribution ----------
if [[ -z "$LAYER_NAME" ]]; then
# Usa il nome file come default
base="$(basename "$MBTILES")"
LAYER_NAME="${base%.*}"
fi
# ---------- step 4: crea tabella metadata (se non esiste) e scrivi i metadati ----------
sqlite3 "$MBTILES" <<SQL
CREATE TABLE IF NOT EXISTS metadata (name TEXT PRIMARY KEY, value TEXT);
REPLACE INTO metadata(name,value) VALUES('name', '$LAYER_NAME');
REPLACE INTO metadata(name,value) VALUES('format', '$FORMAT');
REPLACE INTO metadata(name,value) VALUES('type', '$LAYER_TYPE');
REPLACE INTO metadata(name,value) VALUES('minzoom', '$TMIN');
REPLACE INTO metadata(name,value) VALUES('maxzoom', '$TMAX');
REPLACE INTO metadata(name,value) VALUES('bounds', '$BOUNDS');
REPLACE INTO metadata(name,value) VALUES('center', '$CENTER');
$( [[ -n "$ATTRIBUTION" ]] && echo "REPLACE INTO metadata(name,value) VALUES('attribution','$ATTRIBUTION');" )
SQL
# ---------- step 5: stampa riepilogo ----------
echo "==> METADATA scritti in: $MBTILES"
sqlite3 "$MBTILES" "SELECT name,value FROM metadata ORDER BY name;"
echo
echo "Zoom effettivi nelle tile: $(sqlite3 "$MBTILES" "SELECT MIN(zoom_level)||'..'||MAX(zoom_level) FROM tiles;")"
echo "Bounds: $BOUNDS"
echo "Center: $CENTER"