QB64 Phoenix Edition
GEO map 'library' - Printable Version

+- QB64 Phoenix Edition (https://qb64phoenix.com/forum)
+-- Forum: QB64 Rising (https://qb64phoenix.com/forum/forumdisplay.php?fid=1)
+--- Forum: Code and Stuff (https://qb64phoenix.com/forum/forumdisplay.php?fid=3)
+---- Forum: Programs (https://qb64phoenix.com/forum/forumdisplay.php?fid=7)
+---- Thread: GEO map 'library' (/showthread.php?tid=3025)



GEO map 'library' - mdijkens - 09-12-2024

Since we are into globes/spheres and maps, I thought I'd post my 'library' that I use to show a map in my programs and being able to draw on it in Lat/Lon values. The hard work is in the conversion from lat/lon to x/y and vice versa.

Maybe someone can use it or parts of it.

Only the 5 GEO.* functions are needed, the rest is samplecode to use it.
Prereqs:
- Create your own API KEY at geoapify.com and enter in line 32
- have wget utility sourceforge.net on your system and optionally set path to wget in line 33

Code: (Select All)

samplecode: ' How to use
Screen _NewImage(_DesktopWidth, _DesktopHeight, 32): Do: _Delay .01: Loop Until _ScreenExists
_FullScreen _Stretch , _Smooth

mheight% = .9 * _Height: mwidth% = .85 * mheight%
xoffset% = (_Width - mwidth%) / 2: yoffset% = (_Height - mheight%) / 2
mlat0! = 50.6: mlon0! = 5
mlat1! = 53.8: mlon1! = 5.3

h& = GEO.Map(mlat0!, mlon0!, mlat1!, mlon1!, mwidth%, mheight%)
If h& <> 0 Then _PutImage (xoffset%, yoffset%), h&: _FreeImage h&
Do
  _Limit 100
  Do While _MouseInput
    mlon! = GEO.x2lon(_MouseX - xoffset%, 0, mwidth% - 1, mlon0!, mlon1!)
    mlat! = GEO.y2lat(_MouseY - yoffset%, 0, mheight% - 1, mlat0!, mlat1!)
    mb% = _MouseButton(1)
  Loop
  If mb% Then
    Circle (xoffset% + GEO.lon2x(mlon!, mlon0!, mlon1!, 0, mwidth% - 1), yoffset% + GEO.lat2y(mlat!, mlat0!, mlat1!, 0, mheight% - 1)), 5, &HFFFF0000
    mb% = 0
  End If
  If mlat! >= mlat0! And mlat! <= mlat1! And mlon! >= mlon0 And mlon! <= mlon1! Then
    Locate 1, 1, 0: Print Using "###.######  ###.######"; mlat!; mlon!;
  End If
  _Display
Loop Until InKey$ = Chr$(27)
System

Function GEO.Map& (mlat0!, mlon0!, mlat1!, mlon1!, mwidth%, mheight%)
  Const APIKEY = "get yours at https://apidocs.geoapify.com/"
  Const WGET = "wget" ' include path if needed
  'https://apidocs.geoapify.com/playground/static-maps/
  'https://apidocs.geoapify.com/docs/maps/static/#post-requests
  'https://maps.geoapify.com/v1/staticmap?style=osm-bright&width=1920&height=1080&area=rect:5,52,5,53&apiKey=APIKEY
  If mwidth% > 4096 Then mwidth% = 4096 Else If mwidth% < 100 Then mwidth% = 100
  If mheight% > 4096 Then mheight% = 4096 Else If mheight% < 100 Then mheight% = 100
  If mlat0! <= -90 Then mlat0! = -89.99999 Else If mlat0! >= 90 Then mlat0! = 90
  If mlat1! <= -90 Then mlat1! = -89.99999 Else If mlat1! >= 90 Then mlat1! = 90
  If mlat0! <> 0 And Abs(mlat0! < 1) Then lat0$ = Right$("-0", 2 - Sgn(Sgn(mlat0!) + 1)) + _Trim$(Str$(Abs(mlat0!))) Else lat0$ = _Trim$(Str$(mlat0!))
  If mlon0! <> 0 And Abs(mlon0! < 1) Then lon0$ = Right$("-0", 2 - Sgn(Sgn(mlon0!) + 1)) + _Trim$(Str$(Abs(mlon0!))) Else lon0$ = _Trim$(Str$(mlon0!))
  If mlat1! <> 0 And Abs(mlat1! < 1) Then lat1$ = Right$("-0", 2 - Sgn(Sgn(mlat1!) + 1)) + _Trim$(Str$(Abs(mlat1!))) Else lat1$ = _Trim$(Str$(mlat1!))
  If mlon1! <> 0 And Abs(mlon1! < 1) Then lon1$ = Right$("-0", 2 - Sgn(Sgn(mlon1!) + 1)) + _Trim$(Str$(Abs(mlon1!))) Else lon1$ = _Trim$(Str$(mlon1!))
  url$= "maps.geoapify.com/v1/staticmap?style=osm-bright&width=" + _Trim$(Str$(mwidth%)) + "&height=" + _Trim$(Str$(mheight%)) + _
    "&area=rect:" + lon0$ + "," + lat0$ + "," + lon1$ + "," + lat1$ + "&apiKey=" + APIKEY
  tfile$ = "~wget.jpg"
  cmd$ = WGET + " -q --secure-protocol=TLSv1 --no-check-certificate --output-document=" + tfile$ + " " + Chr$(34) + url$ + Chr$(34)
  Shell _Hide cmd$
  gmap$ = _ReadFile$(tfile$)
  Kill tfile$
  If Len(gmap$) < 10000 Then GMap& = 0: Exit Function
  lons! = mlon1! - mlon0!: lats! = mlat1! - mlat0!
  midLat! = (mlat0! + mlat1!) / 2: cosLat! = Cos(midLat! * _Pi / 180)
  cosLons! = (mwidth% / mheight%) * lats! / cosLat!
  If cosLons! >= lons! Then
    midLon! = (mlon0! + mlon1!) / 2: mlon0! = midLon! - cosLons! / 2: mlon1! = midLon! + cosLons! / 2
  Else
    cosLats! = (mheight% / mwidth%) * lons! * cosLat!
    mlat0! = midLat! - cosLats! / 2: mlat1! = midLat! + cosLats! / 2
  End If
  GEO.Map = _LoadImage(gmap$, 32, "memory")
End Function

Function GEO.x2lon! (x!, x0!, x1!, mlon0!, mlon1!)
  GEO.x2lon! = mlon0! + ((x! - x0!) / (x1! - x0!)) * (mlon1! - mlon0!)
End Function

Function GEO.y2lat! (y!, y0!, y1!, mlat0!, mlat1!)
  Const PI2 = _Pi / 2, PI180 = -180 / _Pi, PI4 = _Pi / 4, PI360 = _Pi / 360
  tlat0! = Log(Tan(PI4 + mlat0! * PI360)): tlat1! = Log(Tan(PI4 + mlat1! * PI360))
  GEO.y2lat! = PI180 * (PI2 - 2 * Atn(Exp(tlat1! - ((y! - y0!) / (y1! - y0!)) * (tlat1! - tlat0!))))
End Function

Function GEO.lon2x! (lat!, mlat0!, mlat1!, y0!, y1!)
  GEO.lon2x! = x0! + ((lat! - mlat0!) / (mlat1! - mlat0!)) * (y1! - y0!)
End Function

Function GEO.lat2y! (lat!, mlat0!, mlat1!, y0!, y1!)
  Const PI4 = _Pi / 4, PI360 = _Pi / 360
  tlat0! = Log(Tan(PI4 + mlat0! * PI360)): tlat1! = Log(Tan(PI4 + mlat1! * PI360))
  GEO.lat2y! = y1! - ((Log(Tan(PI4 + lat! * PI360)) - tlat0!) / (tlat1! - tlat0!)) * (y1! - y0!)
End Function