Verificare le tessere dei livelli delle Map tiles

Da Gambas-it.org - Wikipedia.

Le "Map tiles", che si usano tutte insieme sul web per offrire la rappresentazione corrente della mappa, sono formate per ciascun livello di zoom da molteplici tessere (tile), ciascuna solitamente avente dimensione 256 pixel x 256 pixel.

La descrizione delle "Coordinate delle tessere", che formano l'intera mappa georeferziata, è riportata nella seguente pagina:

https://developers-dot-devsite-v2-prod.appspot.com/maps/documentation/javascript/coordinates?hl=it#tile-coordinates

e qui una esposizione pratica della griglia delle tessere e delle loro coordinate x, y sulla mappa del mondo:

http://tools.geofabrik.de/map/#2/29.1466/31.9609&type=Geofabrik_Standard&grid=1

Di seguito saranno mostrati alcuni esempi per visualizzare tali tessere, costituenti la mappa fornita da "Google Maps", e di conoscerne i relativi parametri "x" (Longitudine), "y" (Latitudine) e "z" (Zoom). Al riguardo va detto che il numero del parametro "x" (Longitudine) delle tessere aumenta procedendo verso Est; mentre il valore del parametro "y" (Latitudine) aumenta procedendo verso SUD.

Visualizzare le tessere di una mappa e i relativi parametri "x", "y" e "z" mediante le risorse del Componente "gb.map"

Mostriamo un primo semplice esempio pratico usando il Metodo "MapPointToTile()" della Classe statica "Geo" del Componente "gb.map".
Questo Metodo fornisce i parametri della "x" e della "y" della tessera individuata:

Public Sub Form_Open()
 
 Dim mp As New MapPoint(41.8902142, 12.4900422)
 
 MapView1.Map.AddTile("OpenTopo", "https://a.tile.opentopomap.org/{z}/{x}/{y}.png")
 
 Print Geo.MapPointToTile(mp, 13)
 
End


In quest'altro esempio si visualizzeranno sulla mappa le tessere e i relativi parametri "x", "y" e "z".
Cliccando con il tasto destro su un punto della mappa, saranno visualizzati i contorni di un quadrato di dimensioni - come già detto - di 256 pixel x 256 pixel a riprodurre la tessera corrispondente al punto, nonché i suoi predetti tre parametri.
Ruotando la rotellina del mouse, per cambiare zoom, i contorni delle tessere precedentemente visualizzati saranno cancellati.

Private MapView1 As MapView
Private mmpp As MapPoint[]
Private tl As Point
Private z As Byte = 14


Public Sub Form_Open()
 
 With Me
   .W = Screen.AvailableWidth
   .H = Screen.AvailableHeight
 End With

 With MapView1 = New MapView(Me) As "MapView1"
   .X = 0
   .Y = 0
   .W = Me.W
   .H = Me.H
   .Map.AddTile("GoogleMap", "http://mt0.google.com/vt/lyrs=s&hl=&x={x}&y={y}&z={z}")
   .Map.Center = MapPoint(41.8902142, 12.4900422)
   .Map.Zoom = z
 End With
 
End

Public Sub MapView1_MouseWheel()
 
' Mostra il livello di zoom della mappa ad ogni rotazione della rotellina del mouse:
 Me.Text = "Zoom: " & CStr(MapView1.Map.Zoom)
 
 EliminaContornoTessera()
  
End

Public Sub MapView1_MouseDown()
 
 Dim pt As New Point(Mouse.X, Mouse.Y)
 Dim mb As MapBounds
 
' Mostra la latitudine e la longitudine del punto ove si è cliccato:
 Me.Text = "Lat. " & Format(MapView1.Map.PixelToMapPointRel(pt).Lat, "0.000000") &
           "  -  Lon. " & Format(MapView1.Map.PixelToMapPointRel(pt).Lon, "0.000000")
 
 If z <> MapView1.Map.Zoom Then EliminaContornoTessera()
 z = MapView1.Map.Zoom
 
 If Not Mouse.Right Then Return 
   tl = Geo.MapPointToTile(MapView1.Map.PixelToMapPointRel(pt), MapView1.Map.Zoom)
   mb = Geo.TileBounds(tl.X, tl.Y, MapView1.Map.Zoom)
' Crea un vettore di Oggetti "MapPoint" contenenti i 4 vertici della tessera:
   With mmpp = New MapPoint[]
     .Push(MapPoint(mb.North, mb.Est))
     .Push(MapPoint(mb.North, mb.West))
     .Push(MapPoint(mb.South, mb.West))
     .Push(MapPoint(mb.South, mb.Est)) 
     .Push(MapPoint(mb.North, mb.Est))
  End With 
 
  MapView1.Map.Center = MapPoint.GetCenter(mmpp)
 
End

Private Procedure EliminaContornoTessera()

 If Not Object.IsValid(MapView1.Map.GetShape("polyline")) Then Return
  
' Compie un ciclo pari al numero di item validi inseriti:
 Repeat
   With MapView1
     .Map.Remove("polyline")
     .Map.Remove("testo")
     .Refresh()
   End With 
' Compie un ciclo fino a che l'oggetto "_MapShape" è valido, ossia fino a che sono ancora presenti gli item precedentemente inseriti:
 Until Not Object.IsValid(MapView1.Map.GetShape("polyline"))

End

Public Sub MapView1_MouseUp()
 
 Dim im As Image

 If Not Mouse.Right Then Return 
 
' Crea un Oggetto "Image", per scriverci i tre parametri della tessera e passarlo quindi al Metodo ".AddShape()":
 im = New Image(256, 256, Color.Transparent, Image.Standard)
 With Paint
   .Begin(im)
   .Brush = .Color(Color.SoftOrange)
   .DrawText("x = " & CStr(tl.X) & "\ny = " & CStr(tl.Y) & "\nz = " & Format(MapView1.Map.Zoom, "######"), 0, 0, im.W, im.H, Align.Center)
   .End
 End With
  
 With MapView1
   .Map.AddShape("polyline").AddPolyLine("polyline", mmpp, Color.Yellow, 2, Line.DashDot)
   .Map.AddShape("testo").AddPoint("testo", MapPoint.GetCenter(mmpp), Color.Default, im)
   .Refresh()
 End With
 
End


Visualizzare le tessere di una mappa e i relativi parametri "x", "y" e "z" mediante il Controllo "WebView"

Il seguente codice fa uso della Classe "WebView", e pertanto bisognerà attivare il relativo Componente (come ad esempio gb.qt5.webkit). Quindi non è necessario attivare il Componente gb.map .
Il programma mostra nel riquadro del Controllo "WebView" una sola tessera per volta (la tessera di partenza mostra la foce del fiume Tevere ad un livello di zoom = 12). Sulla destra sono mostrati anche i tre parametri relativi alla corrente tessera mostrata.
Per vedere le tessere contigue a quella corrente visibile (quindi per spostarsi sul territorio), è necessario modificare i valori dei parametri x (Longitudine) e y (Latitudine) delle tile, che potranno essere variati cliccando sulle parti visibili di colore arancione del "Panel" di contorno al "WebView", come segue: se si clicca sulla parte sinistra, sarà mostrata la tessera contigua a sinistra della tessera corrente; se si clicca sulla parte superiore, sarà mostrata la tessera contigua al di sopra della tessera corrente; e così via per le restanti due parti del Panel arancione. Per modificare lo zoom della mappa, ruotare la rotellina del mouse al di sopra dell'oggetto "WebView".
Va ricordato che il numero del parametro "x" (Longitudine) delle tessere aumenta procedendo verso Est; mentre il valore del parametro "y" (Latitudine) aumenta procedendo verso SUD.

Private WebView1 As WebView
Private Panel1 As Panel
Private Label1 As Label
Private Label2 As Label
Private Label3 As Label
Private x As Integer     ' Indica lo spostamento in Longitudine (Ovest-Est)
Private y As Integer     ' Indica lo spostamento in Latitudine (Nord-Sud)
Private z As Byte        ' Indica lo Zoom della mappa


Public Sub _new()
 
 With Me
   .Center
   .W = 580
   .H = 500
 End With
 With Panel1 = New Panel(Me) As "Panel1"
   .X = 100
   .Y = 50
   .W = 350
   .H = 350
   .Background = Color.Orange
 End With
 With Label1 = New Label(Me)
   .X = Me.W * 0.82
   .Y = Me.H * 0.3
   .Alignment = Align.Right
   .W = .Font.TextWidth(.Text)
   .H = 20
 End With
 With Label2 = New Label(Me)
   .X = Me.W * 0.82
   .Y = Label1.Y + Label1.H + 10
   .Alignment = Align.Right
   .W = .Font.TextWidth(.Text)
   .H = 20
 End With
 With Label3 = New Label(Me)
   .X = Me.W * 0.82
   .Y = Label2.Y + Label2.H + 10
   .Alignment = Align.Right
   .W = .Font.TextWidth(.Text)
   .H = 20
 End With
 
End 

Public Sub Form_Open()
 
 x = 2187
 y = 1524
 z = 12
 AggiornaLabel()
 
 Ricarica()
 
End


Public Sub WebView1_MouseWheel()
 
 Select Case Mouse.Delta
   Case 1
     If z == 22 Then Return 
     x *= 2
     y *= 2
     z += 1
   Case -1
     If z == 0 Then Return 
     x \= 2
     y \= 2
     z -= 1
 End Select
 
 AggiornaLabel()
 
 Ricarica()
 
End


Public Sub Panel1_MouseUp()
 
 If Mouse.X < WebView1.X Then x -= 1
 If Mouse.X > (WebView1.X + WebView1.W) Then x += 1
 
 If Mouse.Y < WebView1.Y Then y -= 1
 If Mouse.Y > (WebView1.Y + WebView1.H) Then y += 1
 
 AggiornaLabel()
 
 Ricarica()
 
End

Private Procedure AggiornaLabel()
 
 Label1.Text = "x = " & Format(x, "########")
 Label1.W = Label1.Font.TextWidth(Label1.Text)
 Label2.Text = "y = " & Format(y, "########")
 Label2.W = Label2.Font.TextWidth(Label2.Text)
 Label3.Text = "z = " & Format(z, "########")
 Label3.W = Label3.Font.TextWidth(Label3.Text)
 
End

Private Procedure Ricarica()
 
 If Object.IsValid(WebView1) Then WebView1.Delete
 
 With WebView1 = New WebView(Panel1) As "WebView1"
   .X = 50
   .Y = 50
   .W = 256
   .H = 256
   .Url = "https://mt1.google.com/vt/lyrs=s&x=" & CStr(x) & "&y=" & CStr(y) & "&z=" & CStr(z)
 End With
 
End


Ottenere i riferimenti di una tessera attraverso appositi calcoli

Si potranno ottenere i riferimenti di una tessera anche attraverso un complesso calcolo esplicito:

Private Const DIM_TESSERA As Integer = 256


Public Sub Main()
 
 Dim lat, lon, f, wc1, wc2 As Float
 Dim zoom, scale As Integer
 
 zoom = 18
 
 scale = Shl(1, zoom)
 
 lat = latitidine_in_decimale (DD.dddddd)
 lon = longitudine_in_decimale (DD.dddddd)
 
 f = Sin(lat * Pi / 180)
 f = Min(Max(f, -0.9999), 0.9999)
 
 wc1 = DIM_TESSERA * (0.5 + lon / 360)
 wc2 = DIM_TESSERA * (0.5 - Log((1 + f) / (1 - f)) / (4 * Pi))
 
 Print "X tessera: "; Floor(wc1 * scale / DIM_TESSERA)
 Print "Y tessera: "; Floor(wc2 * scale / DIM_TESSERA)
  
End


Scaricare dal web e ri-assemblare coerentemente le tessere di una mappa

Ora con un semplice codice proviamo a scaricare dal web i file immagine di tre tessere fra loro contigue orizzontalmente, ossia il Longitudine, e successivamente a mostrarle insieme ri-assemblandole in modo coerente.
E' necessario attivare i Componenti gb.net e gb.net.curl.
Va ricordato che il numero del parametro "x" (Longitudine) delle tessere aumenta procedendo verso Est; mentre il valore del parametro "y" (Latitudine) aumenta procedendo verso SUD.

Public Sub Form_Open()
 
 Dim tp As New HttpClient
 Dim ss As New String[]
 Dim iimm As New Image[]
 Dim img, im As Image
 Dim b As Byte
 Dim PictureBox1 As PictureBox
 
' Scarica tre immagini-tessere:
 ss.Push(tp.Download("https://mt1.google.com/vt/lyrs=s&x=2187&y=1524&z=12"))
 ss.Push(tp.Download("https://mt1.google.com/vt/lyrs=s&x=2188&y=1524&z=12"))
 ss.Push(tp.Download("https://mt1.google.com/vt/lyrs=s&x=2189&y=1524&z=12"))
 tp.Close
 
 im = New Image
 For b = 0 To ss.Max
   iimm.Push(im.FromString(ss[b]))
 Next
 
 img = New Image(iimm[0].W * iimm.Count, iimm[0].H)
 
 With Me
   .Center
   .W = img.W + 50
   .H = img.H + 50
 End With
 
 For b = 0 To ss.Max
   With Paint
     .Begin(img)
     .DrawImage(iimm[b], b * iimm[0].W, 0, iimm[0].W, iimm[0].H)
     .End
   End With
 Next
 
 With PictureBox1 = New PictureBox(Me)
   .X = 20
   .Y = 20
   .W = img.W
   .H = img.H
   .Image = img
 End With
  
End

Va detto che la denominazione dei file delle tessere (tile) scaricati è formata da 4 numeri separati da un trattino, ad esempio:

15-12177-17521-1.png

- il primo numero si riferisce allo Zoom, al quale la tessra appartiene;
- il secondo numero si riferisce alla Latitudine (parametro "y");
- il terzo numero si riferisce alla Longitudine (parametro "x").


Riferimenti