OpenStreetMap embedded in your application

Share your advanced PureBasic knowledge/code with the community.
User avatar
Progi1984
Addict
Addict
Posts: 806
Joined: Fri Feb 25, 2005 1:01 am
Location: France > Rennes
Contact:

OpenStreetMap embedded in your application

Post by Progi1984 »

Hello, I give you a new code for embedding OSM in your application.

(If you use it, thank you for talking me... I like seeing what become my code)

Download the package : http://partage.rootslabs.net/SourceCode_OSM.zip

OR

Get the wrapper of LibCurl (files dll, lib, et the two *Inc&Res.pb)
http://code.google.com/p/rwrappers/sour ... nk/LibCurl

Code: Select all

IncludePath ""
XIncludeFile "RW_LibCurl_Inc.pb"
UsePNGImageDecoder()
UseSQLiteDatabase()
EnableExplicit
Enumeration
  #Window_0
  #Image_0
  #Image_1
  #Image_2
  #Image_3
  #Button_0
  #Button_1
  #Button_2
  #Button_3
  #Button_4
  #Button_5
  #Combo_0
  #Text_0
  #Text_1
  #Text_2
  #Text_3
  #Text_4
  #String_0
  #String_1
EndEnumeration
#_DQ_ = Chr(34)
Global gfLatitude.f   = 46.97
Global gfLongitude.f  = 2.75
Global gfxTile.f
Global gfyTile.f
Global glZoom.l       = 6
Global glLayerCur.l   = 0
Global glSQLiteDB.l
Global gsSQLiteDBPath.s
Global glGadget.l
Global glEvent.l
Global glQuit.l

Global gRWCurl_Proxy.l = #false
; #True if you use a proxy else #false
Global gRWCurl_ProxyIP.s = ""
Global gRWCurl_ProxyPort.s = ""
Global gRWCurl_ProxyAuthLogin.s = ""
Global gRWCurl_ProxyAuthPwd.s = ""

Structure S_OSM_Layers
  sName.s
  sURL.s
  lZoomMin.l
  lZoomMax.l
EndStructure
#OSM_Layers_Num = 5
Global Dim OSM_Layers_Dim.S_OSM_Layers(#OSM_Layers_Num)
OSM_Layers_Dim(0)\sName     = "OSM Mapnik"
OSM_Layers_Dim(0)\sURL      = "http://tile.openstreetmap.org/"
OSM_Layers_Dim(0)\lZoomMin  = 0
OSM_Layers_Dim(0)\lZoomMax  = 18
OSM_Layers_Dim(1)\sName     = "OSM Osmarender/Tiles@Home"
OSM_Layers_Dim(1)\sURL      = "http://tah.openstreetmap.org/Tiles/tile/"
OSM_Layers_Dim(1)\lZoomMin  = 0
OSM_Layers_Dim(1)\lZoomMax  = 17
OSM_Layers_Dim(2)\sName     = "OSM Cycle Map"
OSM_Layers_Dim(2)\sURL      = "http://andy.sandbox.cloudmade.com/tiles/cycle/"
OSM_Layers_Dim(2)\lZoomMin  = 0
OSM_Layers_Dim(2)\lZoomMax  = 18
OSM_Layers_Dim(3)\sName     = "OSM Maplint"
OSM_Layers_Dim(3)\sURL      = "http://tah.openstreetmap.org/Tiles/maplint/"
OSM_Layers_Dim(3)\lZoomMin  = 12
OSM_Layers_Dim(3)\lZoomMax  = 16
OSM_Layers_Dim(4)\sName     = "NPE out-of-copyright map "
OSM_Layers_Dim(4)\sURL      = "http://richard.dev.openstreetmap.org/npe/"
OSM_Layers_Dim(4)\lZoomMin  = 13
OSM_Layers_Dim(4)\lZoomMax  = 15


Define.f pfValue

;@author : Guimauve
;@url : http://www.purebasic.fr/french/viewtopic.php?t=2322
Procedure.f SinH(Angle.f)
  #e = 2.7182818
  ProcedureReturn (Pow(#e, angle) - Pow(#e, -angle)) / 2
EndProcedure
;@desc Open the main window
;@author Progi1984
Procedure WindowMain_Open()
  If OpenWindow(#Window_0, 260, 225, 700, 571, "OpenStreetMap",  #PB_Window_SystemMenu | #PB_Window_TitleBar | #PB_Window_ScreenCentered )
    LoadFont(0,"Wingdings",12)
    LoadFont(1,"Arial",12,#PB_Font_Bold)
 
    ImageGadget(#Image_0, 10, 10, 256, 256, 0)
    ImageGadget(#Image_1, 266, 10, 256, 256, 0)
    ImageGadget(#Image_2, 10, 266, 256, 256, 0)
    ImageGadget(#Image_3, 266, 266, 256, 256, 0)
   
    TextGadget(#Text_0, 530, 10, 60, 15, "Layers :")
    ComboBoxGadget(#Combo_0, 550, 30, 130, 20)
      AddGadgetItem(#Combo_0, 0, OSM_Layers_Dim(0)\sName)
      AddGadgetItem(#Combo_0, 1, OSM_Layers_Dim(1)\sName)
      AddGadgetItem(#Combo_0, 2, OSM_Layers_Dim(2)\sName)
      AddGadgetItem(#Combo_0, 3, OSM_Layers_Dim(3)\sName)
      AddGadgetItem(#Combo_0, 4, OSM_Layers_Dim(4)\sName)
      SetGadgetState(#Combo_0, 0)
    TextGadget(#Text_1, 530, 50, 60, 15, "Movements :")
    ButtonGadget(#Button_0, 550, 100, 30, 30, Chr($E7))  : SetGadgetFont(#Button_0, FontID(0))
    ButtonGadget(#Button_1, 610, 100, 30, 30, Chr($E8))  : SetGadgetFont(#Button_1, FontID(0))
    ButtonGadget(#Button_2, 580, 070, 30, 30, Chr($E9))  : SetGadgetFont(#Button_2, FontID(0))
    ButtonGadget(#Button_3, 580, 130, 30, 30, Chr($EA))  : SetGadgetFont(#Button_3, FontID(0))
    TextGadget(#Text_2, 530, 160, 60, 15, "Zoom :")
    ButtonGadget(#Button_4, 550, 180, 50, 30, "+")      : SetGadgetFont(#Button_4, FontID(1))
    ButtonGadget(#Button_5, 600, 180, 50, 30, "-")      : SetGadgetFont(#Button_5, FontID(1))
    TextGadget(#Text_3, 530, 230, 60, 15, "Latitude :")
    StringGadget(#String_0, 600, 230, 50, 20, "46.97",#PB_String_ReadOnly|#PB_String_BorderLess)
    TextGadget(#Text_4, 530, 250, 60, 15, "Longitude :")
    StringGadget(#String_1, 600, 250, 50, 20, "2.75",#PB_String_ReadOnly|#PB_String_BorderLess)
  EndIf
EndProcedure
;@desc Permits to translate XY Coordinates to Lon/Lat Coordinates
;@author Progi1984
Procedure OSM_LatLon2XY()
  Protected n.l = Pow(2, glZoom)
  gfxTile = Int(((gfLongitude + 180) / 360) * n)
  gfyTile = Int((1-(Log(Tan(gfLatitude * #PI / 180)+(1/Cos(gfLatitude*#PI/180)))/#PI))/2*n)
EndProcedure
;@desc Permits to translate Lon/Lat Coordinates to XY Coordinates
;@author Progi1984
Procedure OSM_XY2LatLon()
  Protected n.l = Pow(2, glZoom)
  Protected pfLatitudeRad.f
  gfLongitude   = gfxTile / n * 360.0 - 180.0
  pfLatitudeRad = ATan(SinH(#PI * (1 - 2 * gfyTile / n)))
  gfLatitude    = pfLatitudeRad * 180.0 / #PI
EndProcedure
;@desc Draws 4 subtiles for the XY Coordinates
;@author Progi1984
Macro OSM_GetSquareTile()
  Debug "======"
  OSM_GetImage(0, glZoom+1,2*gfxTile  ,2*gfyTile)
  OSM_GetImage(1, glZoom+1,2*gfxTile+1,2*gfyTile)
  OSM_GetImage(2, glZoom+1,2*gfxTile  ,2*gfyTile+1)
  OSM_GetImage(3, glZoom+1,2*gfxTile+1,2*gfyTile+1)
  Debug "======"
EndMacro
Macro OSM_TestXYCoordinates(_CoordTile_, _Inc_, _Test_)
  pfValue = _CoordTile_ _Inc_ 0.5
  If pfValue _Test_
    _CoordTile_ = Pow(2, glZoom) - 2
  Else
    _CoordTile_ = pfValue
  EndIf
EndMacro
Procedure OSM_GetImage(Image.l, Zoom.l, XTile.l, YTile.l)
  Protected psProxyURL.s    = gRWCurl_ProxyIP+":"+gRWCurl_ProxyPort
  Protected psProxyAuth.s   = gRWCurl_ProxyAuthLogin+":"+gRWCurl_ProxyAuthPwd
  Protected plMemory.l
  Protected psURL.s = OSM_Layers_Dim(glLayerCur)\sURL+Str(Zoom)+"/"+Str(XTile)+"/"+Str(YTile)+".png"
  Protected gPWRCurl = curl_easy_init()
  Protected plImageSize.l
  Protected plImageMem.l
  Protected psSQLRequest.s
  Protected pbImageOK.b
  Protected plRes.l
  ; Test if in cache else download it
  DatabaseQuery(glSQLiteDB, "SELECT * FROM cache WHERE cache_layer="+#_DQ_+Str(glLayerCur)+#_DQ_+" AND cache_zoom="+#_DQ_+Str(Zoom)+#_DQ_+" AND cache_x="+#_DQ_+Str(XTile)+#_DQ_+" AND cache_y="+#_DQ_+Str(YTile)+#_DQ_+"")
  If FirstDatabaseRow(glSQLiteDB)
    Debug "CACHE : "+Str(glLayerCur)+"\"+Str(Zoom)+"\"+Str(XTile)+"\"+Str(Ytile)
    plImageSize = GetDatabaseLong(glSQLiteDB,6)
    If plImageSize
      plImageMem = AllocateMemory(plImageSize)
      GetDatabaseBlob(glSQLiteDB, 5, plImageMem, plImageSize)
      FinishDatabaseQuery(glSQLiteDB)
      If CatchImage(0, plImageMem)
        SetGadgetState(#Image_0+Image, ImageID(0))
        FreeImage(0)
        FreeMemory(plImageMem)
      EndIf
      pbImageOK = #True
    EndIf
  Else
    Debug DatabaseError()
  EndIf
  If pbImageOK = #False
    Debug "DOWNLOAD : "+Str(glLayerCur)+"\"+Str(Zoom)+"\"+Str(XTile)+"\"+Str(Ytile)
    RW_LibCurl_InitData()
    If gRWCurl_Proxy = #True
      curl_easy_setopt(gPWRCurl, #CURLOPT_HTTPPROXYTUNNEL, #True)
      curl_easy_setopt(gPWRCurl, #CURLOPT_PROXY, @psProxyURL)
      If psProxyAuth <> ""
        curl_easy_setopt(gPWRCurl, #CURLOPT_PROXYUSERPWD, @psProxyAuth)
      EndIf
    EndIf
    curl_easy_setopt(gPWRCurl, #CURLOPT_URL, @psURL)
    curl_easy_setopt(gPWRCurl, #CURLOPT_WRITEFUNCTION, @RW_LibCurl_WriteDataFunction())
    curl_easy_perform(gPWRCurl)
    curl_easy_cleanup(gPWRCurl)
    plMemory = RW_LibCurl_GetData()
    If plMemory
      psSQLRequest = "INSERT INTO cache(cache_layer, cache_zoom, cache_x, cache_y, cache_image, cache_imagesize) VALUES ("
      psSQLRequest + Str(glLayerCur)+","
      psSQLRequest + Str(Zoom)+","
      psSQLRequest + Str(XTile)+","
      psSQLRequest + Str(YTile)+","
      psSQLRequest + "?,"
      psSQLRequest + Str(MemorySize(plMemory))+")"
      SetDatabaseBlob(glSQLiteDB, 0, plMemory, MemorySize(plMemory))
      plRes = DatabaseUpdate(glSQLiteDB, psSQLRequest)
      If plRes = 0
        Debug psSQLRequest
        Debug DatabaseError()
      EndIf
      If CatchImage(0, plMemory, MemorySize(plMemory))
        SetGadgetState(#Image_0+Image, ImageID(0))
        FreeImage(0)
        FreeMemory(plMemory)
      EndIf
    EndIf
  EndIf
EndProcedure
Procedure OSM_CacheInit()
  Protected psSQLRequest.s
  If gsSQLiteDBPath = ""
    gsSQLiteDBPath = GetCurrentDirectory()+"OSMCache.sqlite"
  EndIf
  If FileSize(gsSQLiteDBPath) <= 0
    If CreateFile(0, gsSQLiteDBPath)
      CloseFile(0)
    EndIf
    glSQLiteDB = OpenDatabase(#PB_Any, gsSQLiteDBPath, "", "")
    If glSQLiteDB
      psSQLRequest = "CREATE  TABLE "+#_DQ_+"main"+#_DQ_+"."+#_DQ_+"cache"+#_DQ_+" ("
      psSQLRequest + #_DQ_+"id_cache"+#_DQ_+" INTEGER PRIMARY KEY  AUTOINCREMENT  Not NULL , "
      psSQLRequest + #_DQ_+"cache_layer"+#_DQ_+" INTEGER Not NULL  Default 0, "
      psSQLRequest + #_DQ_+"cache_zoom"+#_DQ_+" INTEGER Not NULL , "
      psSQLRequest + #_DQ_+"cache_x"+#_DQ_+" INTEGER Not NULL , "
      psSQLRequest + #_DQ_+"cache_y"+#_DQ_+"  INTEGER Not NULL , "
      psSQLRequest + #_DQ_+"cache_image"+#_DQ_+" BLOB, "
      psSQLRequest + #_DQ_+"cache_imagesize"+#_DQ_+"  INTEGER Not NULL"
      psSQLRequest + ")"
      DatabaseUpdate(glSQLiteDB, psSQLRequest)
    EndIf
  Else
    glSQLiteDB = OpenDatabase(#PB_Any, gsSQLiteDBPath, "", "")
  EndIf 
EndProcedure

  WindowMain_Open()
  ; Init DB
  OSM_CacheInit()
  ; Init Map
  OSM_LatLon2XY()
  OSM_GetSquareTile()
 
 
  Repeat
    glEvent = WaitWindowEvent()
    Select glEvent
      Case #PB_Event_CloseWindow : glQuit = 1
      Case #PB_Event_Gadget ;{
        glGadget = EventGadget()
        Select glGadget
          Case #Button_0 ;{ To left
            OSM_TestXYCoordinates(gfxTile, -, < 0)
            OSM_GetSquareTile()
            OSM_XY2LatLon()
            SetGadgetText(#String_1, StrF(gfLongitude))
          ;}
          Case #Button_1 ;{ To Right
            OSM_TestXYCoordinates(gfxTile, +,> Pow(2, glZoom) - 1)
            OSM_GetSquareTile()
            OSM_XY2LatLon()
            SetGadgetText(#String_1, StrF(gfLongitude))
          ;}
          Case #Button_2 ;{ To Top
            OSM_TestXYCoordinates(gfyTile, -, < 0)
            OSM_GetSquareTile()
            OSM_XY2LatLon()
            SetGadgetText(#String_0, StrF(gfLatitude))
          ;}
          Case #Button_3 ;{ To Bottom
            OSM_TestXYCoordinates(gfyTile, +, > Pow(2, glZoom) - 1)
            OSM_GetSquareTile()
            OSM_XY2LatLon()
            SetGadgetText(#String_0, StrF(gfLatitude))
          ;}
          Case #Button_4 ;{ Zoom +
            If glZoom < OSM_Layers_Dim(glLayerCur)\lZoomMax
              glZoom + 1
              OSM_LatLon2XY()
              OSM_GetSquareTile()
            EndIf
          ;}
          Case #Button_5 ;{ Zoom -
            If glZoom > OSM_Layers_Dim(glLayerCur)\lZoomMin
              glZoom - 1
              OSM_LatLon2XY()
              OSM_GetSquareTile()
            EndIf
          ;}
          Case #Combo_0  ;{ Layers
            pfValue = GetGadgetState(#Combo_0)
            If pfValue >= 0 And pfValue < #OSM_Layers_Num And pfValue <> glLayerCur
              ; Current Layer
              glLayerCur = pfValue
              ; Zoom
              If glZoom < OSM_Layers_Dim(glLayerCur)\lZoomMin
                glZoom = OSM_Layers_Dim(glLayerCur)\lZoomMin +1
              EndIf
              If glZoom > OSM_Layers_Dim(glLayerCur)\lZoomMax
                glZoom = OSM_Layers_Dim(glLayerCur)\lZoomMax
              EndIf
              OSM_LatLon2XY()
              OSM_GetSquareTile()
            EndIf
          ;}
        EndSelect
      ;}
    EndSelect
  Until glQuit = 1 
Last edited by Progi1984 on Mon Aug 24, 2009 2:28 pm, edited 2 times in total.
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Post by ts-soft »

Please, can you make a package with all required files. I have many
problems to load the files from svn.

Greetings
Thomas
PureBasic 5.73 | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.
Image
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

Very neat. I like the idea.

I agree with ts-soft, it would be nice to have a single package download with all required files.

Thank You
akj
Enthusiast
Enthusiast
Posts: 668
Joined: Mon Jun 09, 2003 10:08 pm
Location: Nottingham

Post by akj »

I have downloaded all the LibCurl files, but when I run LibCurl.pb under PB4.40B2 on my Windows XP platform, I always get the error shown below. Have you any idea what is wrong?

The size of my downloaded LibCurl.lib file is 13694 bytes. Is this correct?

---------------------------
PureBasic_Compilation0.exe - Application Error
---------------------------
The application failed to initialize properly (0xc0150002). Click on OK to terminate the application.
---------------------------
Anthony Jordan
User avatar
Progi1984
Addict
Addict
Posts: 806
Joined: Fri Feb 25, 2005 1:01 am
Location: France > Rennes
Contact:

Post by Progi1984 »

SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

Very nice, thank you for the complete package download Progi1984 :)
Num3
PureBasic Expert
PureBasic Expert
Posts: 2812
Joined: Fri Apr 25, 2003 4:51 pm
Location: Portugal, Lisbon
Contact:

Post by Num3 »

Nice!

I'm working on a project that uses google maps, and GPS locations.

Image
User avatar
Progi1984
Addict
Addict
Posts: 806
Joined: Fri Feb 25, 2005 1:01 am
Location: France > Rennes
Contact:

Post by Progi1984 »

@SFSxOI : No problem :)

@Num3 : With this source code, you will be able to offer two solutions, and one based on an open source and collaborative version.
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Post by ts-soft »

Thx for the complete paket and thx for sharing this great stuff :D
PureBasic 5.73 | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.
Image
Num3
PureBasic Expert
PureBasic Expert
Posts: 2812
Joined: Fri Apr 25, 2003 4:51 pm
Location: Portugal, Lisbon
Contact:

Post by Num3 »

Progi1984 wrote:@Num3 : With this source code, you will be able to offer two solutions, and one based on an open source and collaborative version.
Yes, i might modify my source to use this...

I didn't even know about open maps!!!
User avatar
Progi1984
Addict
Addict
Posts: 806
Joined: Fri Feb 25, 2005 1:01 am
Location: France > Rennes
Contact:

Post by Progi1984 »

@Num3 : As you can see, there are some maps systems :
http://stable.toolserver.org/geohack/ge ... 2_19.59_E_
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Great work Progi - works very well here. Thanks.
I may look like a mule, but I'm not a complete ass.
User avatar
Rook Zimbabwe
Addict
Addict
Posts: 4322
Joined: Tue Jan 02, 2007 8:16 pm
Location: Cypress TX
Contact:

Post by Rook Zimbabwe »

Fantastic stuff Progi!!! I have a use for this in mind and I didn't want to use google! (though I like them too!)
Binarily speaking... it takes 10 to Tango!!!

Image
http://www.bluemesapc.com/
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

I dl'd the complete package and tried to run it but I get an error message saying "The application failed to initialize properly (Oxc0150002). What's wrong? (pb 4.4 b2 win xp)
BERESHEIT
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

Wait, is this for PB 4.4 beta?

I can't run the beta, prohibited from running betas of any software on these computers (except MS betas), can only run finished releases. Guess i'm out of luck until PB 4.4 is released. Waited all day to get home to try this, didn't know it was for the beta. My fault though as i should have seen the odd functions :(
Post Reply