Best Practices Cartografia
Linee guida operative per sviluppatori che integrano dati geografici in applicazioni AI, RAG e GIS.
Dichiarare sempre il datum e il CRS
Pratica: In qualsiasi sistema che gestisce coordinate geografiche, il datum (WGS84, ETRS89, Roma40) e il CRS (EPSG code) devono essere esplicitati e salvati con i dati. Non assumere mai che "le coordinate siano in WGS84" senza verifica.
Do: Salvare il CRS nel file (gpkg_spatial_ref_sys in GeoPackage, file .prj in Shapefile, metadati GeoTIFF), documentarlo nel README del dataset, verificarlo con ogrinfo -al -so file.gpkg o gdalinfo file.tif.
Don't: Distribuire file con CRS "sconosciuto" o assunto implicito. Un dataset senza CRS dichiarato richiede un'indagine forense per determinarlo: confronto con fonti note, analisi dell'estensione, contatto con il fornitore.
Usare GeoPackage al posto di Shapefile per nuovi progetti
Pratica: Shapefile ha limitazioni che causano errori silenti: nomi di campo troncati a 10 caratteri, file da 2 GB massimo, encoding ambiguo, un solo tipo di geometria per file. GeoPackage (.gpkg) è il formato OGC moderno che risolve tutte queste limitazioni.
Do: Usare ogr2ogr -f GPKG output.gpkg input.shp per convertire Shapefile esistenti. Preferire GeoPackage per tutti i nuovi dataset vettoriali.
Don't: Creare nuovi Shapefile quando GeoPackage è disponibile. Non ignorare il troncamento silente dei nomi di campo: un campo "district_name" diventa "district_na" senza avviso.
Separare il CRS di storage dal CRS di visualizzazione
Pratica: I dati possono essere archiviati in ETRS89/UTM (coordinate metriche, adatte per analisi spaziali) e visualizzati in Web Mercator (EPSG:3857, adatto per tile web). La conversione al volo è gestita dalle librerie GIS (pyproj, PROJ, PostGIS ST_Transform).
Do: Archiviare i dati nel CRS appropriato all'analisi (UTM per misurazioni metriche, ETRS89 per conformità INSPIRE); convertire al volo per la visualizzazione web.
Don't: Archiviare dati in Web Mercator (EPSG:3857): questa proiezione Mercatore sferica distorce le aree e le distanze, è adatta solo alla visualizzazione raster su web.
Citare sempre la fonte delle coordinate, mai generarle
Pratica: In qualsiasi contenuto cartografico (documentazione, FAQ, esempi di dataset), le coordinate geografiche devono essere citate da fonti autorevoli (IGM, OpenStreetMap, EPSG Registry, dati SRTM), mai generate approssimativamente o calcolate senza fonte.
Do: Citare esplicitamente la fonte ("coordinate EPSG:4326 da OpenStreetMap Nominatim per Firenze: latitudine 43,7696°N, longitudine 11,2558°E, accessed 2024"). Usare servizi di geocoding verificati (Nominatim OSM, GeocodeAPI, HERE Geocoder) per coordinate di esempio.
Don't: Generare o inventare coordinate "plausibili" per esempi o documentazione. Un errore di coordinate in un pack cartografico è il failure mode principale: chi usa il pack per riferimento GIS rileverà subito l'inesattezza.
Gestire correttamente l'ordine latitudine-longitudine
Pratica: L'ordine latitudine-longitudine vs longitudine-latitudine è una fonte perenne di bug. Le specifiche OGC usano lat-lon; GeoJSON (RFC 7946) usa lon-lat; Leaflet usa lat-lon; Mapbox GL JS usa lon-lat. Documentare sempre l'ordine usato nelle API.
Do: Usare tipi espliciti ({lat: number, lng: number} invece di array [number, number]), commentare l'ordine, aggiungere test di sanità-check (verificare che la latitudine sia nel range [-90, 90]).
Don't: Usare array di coordinate senza documentazione dell'ordine. Non assumere che tutte le librerie usino lo stesso ordine.
Usare il tipo geography di PostGIS per distanze geodetiche
Pratica: PostGIS ha due tipi per le geometrie geografiche: geometry (piano cartesiano, calcoli euclidei) e geography (sferoide WGS84, calcoli geodetici). Per distanze e aree accurate su dati WGS84, usare il tipo geography.
Do: SELECT ST_Distance(a.geom::geography, b.geom::geography) FROM ... per distanze in metri su sferoide. Indicizzare con CREATE INDEX ON table USING GIST(geom::geography).
Don't: Calcolare distanze in gradi con il tipo geometry in WGS84: ST_Distance(p1, p2) restituisce la differenza in gradi, non in metri. Moltiplicare per 111.319 km/grado è un'approssimazione grossolana non adatta a distanze superiori a pochi km.
Validare le geometrie prima dell'inserimento nel database
Pratica: Le geometrie non valide (auto-intersections in poligoni, ring non chiusi, geometrie vuote) causano errori nelle query spaziali e nei calcoli topologici. Validare prima di inserire.
Do: SELECT ST_IsValid(geom), ST_IsValidReason(geom) FROM ... per diagnosticare; UPDATE table SET geom = ST_MakeValid(geom) WHERE NOT ST_IsValid(geom) per correzione automatica. In QGIS: Vector → Geometry Tools → Fix Geometries.
Don't: Inserire geometrie senza validazione: una geometria non valida può bloccare query ST_Intersection, ST_Union e funzioni di analisi topologica con errori GEOS oscuri.
Usare indici spaziali per le query geografiche
Pratica: Le query spaziali senza indice (full scan) sono ordini di grandezza più lente su grandi dataset. Gli indici GiST (PostGIS) e gli indici R-Tree (SQLite/GeoPackage) sono essenziali per performance accettabili.
Do: CREATE INDEX ON table USING GIST(geom); in PostGIS dopo il caricamento. SELECT CreateSpatialIndex('table', 'geom'); in GeoPackage. Verificare l'uso dell'indice con EXPLAIN ANALYZE in PostgreSQL.
Don't: Eseguire join spaziali o ST_Contains / ST_Within su milioni di geometrie senza indice. Il query planner PostgreSQL usa l'indice automaticamente se presente.
Scelta della proiezione in base all'uso
Pratica: Non esiste una proiezione universalmente corretta. La scelta deve essere guidata dall'uso: UTM per misurazioni lineari in un'area limitata, Equal Area per statistiche di area, Robinson o Mollweide per mappe globali di visualizzazione, Web Mercator per tile web.
Do: Per analisi in Italia: UTM zona 32N o 33N (EPSG:32632 o 32633) per misurazioni metriche. Per conformità INSPIRE: ETRS89 / LAEA Europe (EPSG:3035) per mappe statistiche. Per tile web: Web Mercator (EPSG:3857).
Don't: Usare Web Mercator (EPSG:3857) per calcoli di area o distanza. Questa proiezione distorce le aree: la Groenlandia appare grande quanto l'Africa nella proiezione Mercatore, ma è in realtà 14 volte più piccola.
Documentare la risoluzione e l'accuratezza dei dati
Pratica: La risoluzione spaziale di un raster (es. 25 m/pixel per SRTM3) e l'accuratezza planimetrica di un dataset vettoriale (es. ±5 m per dati CTR 1:10.000) determinano l'applicabilità dei dati all'uso previsto. Documentarle nei metadati.
Do: Specificare nel README o nei metadati ISO 19115: risoluzione spaziale (per raster), accuratezza planimetrica e verticale (per dati topografici), data di acquisizione, ente produttore, licenza.
Don't: Presentare dati SRTM (30 m di risoluzione, accuratezza verticale ~10 m RMSE) come DEM ad alta risoluzione per applicazioni che richiedono precisione centimetrica. La differenza tra SRTM e LiDAR è di 2-3 ordini di grandezza in risoluzione.
Gestire i fusi orari nelle timestamp geografiche
Pratica: I dati di tracciamento GPS e i log di acquisizione contengono timestamp. Usare sempre UTC come timezone per i timestamp nei dataset geografici. La conversione a ora locale è un'operazione di presentazione, non di archiviazione.
Do: Archiviare i timestamp come UTC con timezone esplicita (ISO 8601 con suffisso Z). Documentare la timezone nel metadato.
Don't: Archiviare timestamp senza timezone o in ora locale: durante i cambi di ora legale o nelle analisi cross-timezone, i timestamp ambigui causano errori di ordinamento e calcolo della durata.
Usare il formato HGT/SRTM con attenzione ai valori no-data
Pratica: I file HGT (formato SRTM) usano il valore -32768 come indicatore di dato mancante (no-data). Se non gestito, questo valore appare come una quota di -32.768 m, causando errori gravi nell'analisi del terreno.
Do: Verificare e impostare il valore no-data: gdal_translate -a_nodata -32768 input.hgt output.tif. Usare gdalinfo per verificare il valore no-data corrente. Filtrare i pixel no-data nelle analisi con GDAL/numpy.
Don't: Usare dati SRTM per analisi di quota senza filtrare i no-data: l'interpolazione di isoipse o il calcolo di profili altimetrici con valori -32768 produce risultati completamente errati.