139 lines
5.2 KiB
Bash
Executable file
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"
|