Creare da una carta topografica i file delle tessere di una mappa e utilizzarli con MapView

Da Gambas-it.org - Wikipedia.

L'oggetto MapView viene solitamente utilizzato mostrando mappe fornite da "Raster Tile Server" remoti (come Google Maps, OpenStreetMap ed altri).

Le mappe sono costituite da una serie di tessere (tile), di dimensioni 256x256 pixel, che poste l'una accanto all'altra offrono un quadro unico di visualizzazione della mappa medesima.
Tali "Raster Tile Server" remoti forniscono appunto le tessere della propria mappa del mondo proposta.

E' possibile caricare con l'oggetto MapView tessere di un'area geografica realizzate dall'utente ?

La risposta al quesito, che introduce il presente capitolo, è affermativa. L'operazione richiesta è complessa componendosi di varie fasi essenziali.

Va precisato che oltre ad una carta topografica, avente un qualunque rapporto, si potrà utilizzare con MapView anche una foto scattata dall'alto (ad esempio da un drone).

Georeferenziazione della carta geografica da utilizzare con MapView

La prima fase prevede la georeferenziazione della carta geografica da utilizzare con MapView.

Per effettuare la georeferenziazione di una carta geografica si utilizzerà un programma adatto. Qui saranno esposte le operazioni da compiere utilizzando il programma gratuito "QGIS desktop". [nota 1]

Aperto QGIS si caricherà il file immagine della carta topografica (o della foto dall'alto) da georeferenziare, come descritto appresso:
1) Cliccare sul Menu in alto: "Raster-->Georefereziatore-->Georeferenziatore".
2) Nella finestra, che si apre, scegliere dal Menu: "File-->Apri raster..." (oppure cliccare sulla corrispondente icona nella barra appena sottostante).
3) Nella consueta finestra di dialogo scegliere il file immagine della carta topografica da georeferenziare. Al centro della finestra del georeferenziatore apparirà l'immagine della carta topografica scelta.
La fase che segue è la più delicata, poiché bisognerà individuare 3 punti a rappresentare i vertici di un triangolo (anche approssimativamente), oppure preferibilmente individuare 4 punti scelti a formare (anche approssimativamente) un quadrato o un rettangolo.
I punti di riferimento devono essere scelti in modo tale da essere facilmente rintracciabili sulla mappa (da Google Maps, OpenStreetMap o altro), che sarà aperta a parte nel web browser, come elementi presenti nella realtà - se si è aperta col web browser una mappa satellitare - oppure comunque presenti anche nell'altro tipo mappa.
Individuato il primo punto, si procederà dalla mappa aperta con il web browser a ricavare le coordinate (latitudine e longitudine) in formato decimale.
Quindi in QGIS si sceglierà dal menu in alto: "Modifica-->Aggiunge un nuovo punto" (oppure cliccando sulla corrispondente icona nella sottostante barra). L'aspetto di puntatore del mouse cambia in forma di croce e si cliccherà sul corrispondente elemento (già individuato nella mappa del web browser) presente sulla carta topografica mostrata nella finestra del georefereziatore.
Dopo aver cliccato sul punto, che farà da riferimento per la georeferenziazione, si apre una finestra, nella quale in basso sono presenti due caselle: in quella di sinistra andrà copiato il valore della longitudine dell'elemento, rilevata nella mappa richiamata con il web browser. Nella casella di destra andrà inserito il valore decimale della longitudine dell'elemento. Si cliccherà sul tasto virtuale "OK" per fissare il primo punto di riferimento della georeferenziazione della carta topografica caricata.
Si procederà in modo analogo per i restanti punti da fissare.
Dal menu su cliccherà su: "Preferenze-->Impostazione di trasformazione" (oppure cliccando sulla corrispondente icona nella sottostante barra).
Nella finestra che appare si dovranno impostare alcuni parametri:
* alla voce "Trasformation type" si potrà impostare su "Lineare" o (tauni lo consigliano "Polynomiale";
* alla voce "Metodo di ricampionamento" si potrà impostare su "Lineare";
* alla voce "SR di destinazione" si sceglierà una delle opzioni possibili.
Nel successivo gruppo "Output settings" si imposterà il percorso per il file finale georeferenziato nella casella denominata "raster in uscita".
Infine è preferibile anche spuntare l'opzione in basso "Carica in QGIS una volta eseguito".
Si cliccherà quindi sul tsto virtuale "OK".
Per concludere la georeferenziazione, si cliccherà nel menu: "File-->Avvia georeferenziazione" (oppure cliccando sulla corrispondente icona nella sottostante barra).

Se tutto è andato bene, QGIS lo renderà noto con un avviso su una barra rettangolare aperta in alto.
Va precisato che, affinché la georeferenziazione sia davvero andata a buon fine, in prossimità dei punti prescelti come riferimento (che appaiono in rosso) non devono apparire delle lineette rosse (aventi origine proprio dai punti fissati).
Una verifica empirica può essere effettuata anche tornando nella finestra principale di QGIS, dove - se era stata attivata l'opzione "Carica in QGIS una volta eseguito" - verrà mostrata la carta topografica georeferenziata. Quindi si sceglierà un Map Server dal menu in alto: "Web-->QuickMapServices". La mappa georeferenziata apparirà ora al di sopra della mappa scelta dal web; e diminuendo l'opacità della mappa georeferenziata dell'utente agendo sullo slider nella finestra che si apre cliccando dal menu su: "Layer-->Proprietà...", si potrà verificare la giusta sovrapposizione spaziale degli elementi presenti nella mappa georeferenziata dell'utente con i corrispondenti elementi presenti nella mappa scelta dal web.

Creazione delle tessere della mappa da caricare con MapView

Come già detto, affinché la mappa, così georeferenziata, possa essere effettivamente caricata e utilizzata proficuamente dall'oggetto MapView, deve essere suddivisa in molteplici tessere in numero variabile a seconda del livello di zoom prescelto.
La realizzazione delle tessere avverrà mediante un adatto programma. qui si continuerà a utilizzare il programma QGIS.
In particolare si utilizzerà il plugin "QTiles", aprendolo - dopo averlo installato da QGIS medesimo - dal menu: "Plugins-->QTiles-->QTiles".
Nella finestra che appare, dovranno essere impostati alcuni parametri.
In particolare nel gruppo di opzioni "Output" si sceglierà l'opzione "Directory" e si imposterà il percorso ove sarà creata la cartella che conterrà i file creati delle tessere. Nella casella "Tileset name" si potrà impostare il nome della cartella che conterrà effettivamente le tessere che saranno in fine realizzate. Se questa casella di testo sarà lasciata vuota, il programma imposterà aytomaticamente un nome alla cartella contenente le i file delle tessere create.
Nel gruppo "Extent" si sceglierà l'opzione ritenuta più opportuna.
Nel gruppo "Zoom" si dovrà scegliere i livelli di zoom che saranno coperti dalle tessere. In sostanza saranno generate le tessere per usare nella MapView i livelli di mappa stabiliti in questo gruppo delle opzioni. Così, se ad esempio si sceglierà come zoom minimo il valore 12 e come zoom massimo il valore 16, saranno generate le tessere della mappa utilizzabili successivamente nella MapView con i soli livelli 12, 13, 14, 15 e 16.
Nel successivo gruppo "Parametri" i più solitamente attivano le opzioni: "Make lines appear less jagged at the expence of some drawing performance", "Render tiles outside of layers extents (whitin combines extent)" e "Write Leaflet-based viewer".
Quindi si cliccherà sul tasto virtuale "Run".
Al termine dell'operazione si provvederà a chiudere la finestra: le tessere sono state realizzate.

Percorso assegnato ai file salvati delle tessere della mappa

Andando a verificare nel percorso e nella cartella principale i file creati delle tessere, si noterà che essi sono contenuti in distinte cartelle aventi come denominazione il numero dello zoom corrispondente al livello del gruppo di tessere create per quel livello. Così, insomma, i file delle tessere, che saranno utilizzate per mostrare il livello 12 di zoom, saranno contenuti nella sub-cartella chiamata "12" e così via per le altre tessere appartenenti ai restanti livelli.
Aprendo una sub-cartella avente la denominazione di un livello di zoom previsto, si avranno una o più cartelle aventi come denominazione un numero.
Tale numero corrisponde alla coordinata "x" del reticolo in cui sono idealmente disposte le tessere per coprire l'intero pianeta terra. [nota 2] [nota 3]

Aprendo una di queste sub-cartelle appariranno finalmente i file delle tessere. La loro denominazione porta un numero e solitamente l'estensione .png.
In particolare il numero si riferisce alla coordinata "y" del reticolo in cui sono idealmente disposte le tessere per coprire l'intero pianeta terra. [nota 2] [nota 3]

Ridefinizione del nome di ciascun file delle tessere della mappa

Poiché i file delle tessere utilizzati dai Raster Tiles Server remoti, e quindi anche dall'oggetto MapView, posseggono una denominazione formata dai rispettivi valori dei seguenti elementi: zoom-y-x-1.png, si rende necessario modificare i nomi dei file delle tessere dal plugin "QTiles", in modo tale che riportino quella struttura di valori.
In sé il compito è semplice, poiché di ciascun file, come salvato dopo l'operazione del plugin QTiles:
* il valore dello "zoom" è quello della sub-cartella, nella quale è contenuta la sub-cartella che effettivamente contiene detti file;
* il valore della coordinata "x" è quello della sub-cartella che effettivamente contiene detti file;
* il valore della coordinata "y" è quello presente nella denominazione del file .png della tessera.

Questa modifica potrebbe essere fatta manualmente, ma potrebbero essere presenti anche qualche migliaio di file, soprattutto se si è voluto creare tessere per molti livelli alti di zoom.
Per facilitare questa operazione di modifica della denominazione di ciascun file in base allo zoom, alla coordinata "y" e alla coordinata "x", si potrà adottare il seguente codice:

Public Sub Main()
 
 Dim cartella_nuovi_file, tileset_name, z, x, y, bn As String
 
' Viene creata la cartella ove saranno salvati i file .png con il proprio nome modificato per l'uso nella "mapView":
 cartella_nuovi_file = "/percorso/della/cartella"  ' (vedi didascalia qui sopra)
 Mkdir cartella_nuovi_file
 
' Il percorso comprensivo del nome della cartella principale ove sono attualmente contenente le sub-cartelle con i valori dello zoom, della sub-cartella della coordinata "x" contenente i file .png delle tessere della mappa:
 tileset_name = "/percorso/della/cartella/principale"  ' (vedi didascalia qui sopra)
 
' La variabile "z" rappresenta una sub-cartella corrispondente ad un valore di zoom:
 For Each z In Dir(tileset_name, Null, gb.Directory)
' La variabile "x" rappresenta una sub-cartella corrispondente ad un valore di una coordinata "x":
   For Each x In Dir(tileset_name &/ z, Null, gb.Directory)
' La variavbile "y" rappresenta un file corrispondente ad una tessera della mappa e avente nel nome il valore della rispettiva coordinata "y":
     For Each y In Dir(tileset_name &/ z &/ x, "*.png", gb.File)
       bn = File.BaseName(tileset_name &/ z &/ x &/ y)
' Si provvede a salvare i file .png delle tessere con i nomi ora così modificati:
       Copy tileset_name &/ z &/ x &/ y To cartella_nuovi_file &/ z & "-" & bn & "-" & x & "-" & "1.png"
     Next
   Next
 Next
 
End

Uso finale con l'Oggetto MapView delle tessere create dall'utente

Dopo aver modificato adeguatamente il nome dei file corrispondenti alle tessere, questi possono essere utilizzati per mostrare in un oggetto MapView la mappa rappresentata dalla carta topografica georeferenziata dall'utente.
Tali file potranno essere utilizzati con o senza collegamento internet.
Il collegamento internet permetterà - volendo - di avere a disposizione due o più livelli, strati di tessere, quindi due o più mappe, quelle di "Raster Tiles Server" remoti e quella dell'utente. Tali mappe, potranno essere sovrapposte in modo comunque visibile usando per ciascuna di esse sapientemente la proprietà "MapView1.Map.GetTile().Opacity".

Uso senza collegamento a internet dei file creati delle tessere della mappa dell'utente

Riprendendo l'esempio esposto al paragrafo precedente, fingiamo che i file .png con i nomi opportunamente modificati siano stati salvati nella seguente cartella: "/tmp/tessere", e mostriamo di seguito un esempio di uso senza collegamento a internet [nota 4] di tali tessere della carta topografica georeferenziata dell'utente:

Public Sub _New()

 MapView1.Map.DefaultCache = "/tmp"
 MapView1.Map.AddTile("esempio", Null, Null, "tessere")
 
End


Public Sub Form_Open()
 
 Dim mp As New MapPoint
 
' Imposta il centro della mappa mostrata, avendo cura di specificare le coordinate geografiche di un punto presente nella carta topografica dell'utente. Le coordinate sono impostate qui in valori decimali.
 mp.Lat = latitudine
 mp.Lon = longitudine
 
 With MapView1.Map
   .Center = mp
' Imposta un valore dello zoom purché valido per le tessere create dalla carta topografica dell'utente:
   .Zoom = zoom
' Imposta e mostra anche un punto marcatore delle coordinate:
   .AddShape("figura").AddPoint("punto", mp, Color.Default, Null)
 End With
  
End


Public Sub MapView1_MouseUp()

 Dim pt As New Point(Mouse.X, Mouse.Y)
 Dim mp As New MapPoint
 
 With MapView1
' Ottiene le coordinate geografiche del punto ove si è cliccato sulla "MapView":
   mp = .Map.PixelToMapPointRel(pt)
' Elimina la figura (shape) precedentemente impostata.
' Va specificata la sua chiave gerarchicamente sovraordinata identificativa, quale "Shape" generico.
   If .Map.GetShape("figura") Then .Map.Remove("figura")
' Aggiunge una nuova figura (shape) alle coordinate ricavate dal puntatore:
   .Map.AddShape("figura").AddPoint("punto", mp, Color.Default, Null)
   Print "Lat. "; Format(mp.Lat, "##.00000000"), "Long. "; Format(mp.Lon, "##.00000000")
   .Refresh()
   .Map.Refresh()
 End With
    
End

Uso con collegamento a internet dei file creati delle tessere della mappa dell'utente

Mostriamo ora un esempio di uso con collegamento a internet di tali tessere della carta topografica georeferenziata dell'utente. Si utilizzerà contestualmente anche la mappa di un "Raster Tiles Server" remoto.

Public Sub Form_Open()
 
 Dim mp As New MapPoint
 
' Imposta un "Raster Tiles Server" remoto:
 MapView1.Map.AddTile("opentopo", "https://a.tile.opentopomap.org/{z}/{x}/{y}.png")
 
' Contemporaneamente si utilizzeranno le tessere della mappa realizzata dall'utente:
 With MapView1
   .Map.DefaultCache = "/tmp"
   .Map.AddTile("utente", Null, Null, "tessere")
' Modifica l'opacità della mappa dell'utente, per rendere visibile al di sotto anche la mappa del "Raster Tiles Server" remoto:
   .Map.GetTile("utente").Opacity = 0.6
 End With

' Imposta il centro della mappa mostrata, avendo cura di specificare le coordinate geografiche di un punto presente nella carta topografica dell'utente. Le coordinate sono impostate qui in valori decimali.
 mp.Lat = latitudine
 mp.Lon = longitudine
 
 With MapView1
' Imposta un valore dello zoom purché valido per le tessere create dalla carta topografica dell'utente:
   .Map.Zoom = zoom
   .Map.Center = mp
 End With
  
End


Public Sub MapView1_MouseUp()

 Dim pt As New Point(Mouse.X, Mouse.Y)
 Dim mp As New MapPoint
 
 With MapView1
' Ottiene le coordinate geografiche del punto ove si è cliccato sulla "MapView":
   mp = .Map.PixelToMapPointRel(pt)
' Elimina la figura (shape) precedentemente impostata.
' Va specificata la sua chiave gerarchicamente sovraordinata identificativa, quale "Shape" generico.
   If .Map.GetShape("figura") Then .Map.Remove("figura")
' Aggiunge una nuova figura (shape) alle coordinate ricavate dal puntatore:
   .Map.AddShape("figura").AddPoint("punto", mp, Color.Default, Null)
   Print "Lat. "; Format(mp.Lat, "##.00000000"), "Long. "; Format(mp.Lon, "##.00000000")
   .Refresh()
   .Map.Refresh()
 End With
    
End


Note

[1] E' utililissimo seguire anche i seguenti video su youtube:
* https://www.youtube.com/watch?v=m6Ot76P219c
* https://www.youtube.com/watch?v=k8WoVxTXlKQ

[2] Per la griglia delle tessere e le loro coordinate x, y sulla mappa del mondo vedere qui:
http://tools.geofabrik.de/map/#2/29.1466/31.9609&type=Geofabrik_Standard&grid=1

[3] Ovviamente più è alto il valore dello zoom, più tessere saranno necessarie per coprire il pianeta (e quindi un'area prescelta), dato che le tessere hanno sempre la medesima dimensione (256x256 pixel), a nulla rilevando sulla loro dimensione il valore di zoom.

[4] Al riguardo vedere anche la seguente pagina della Wiki: Utilizzare le tessere di una mappa senza connessione a internet


Riferimenti