Page 1 of 3

OpenStreetMap embedded in your application

Posted: Mon Aug 24, 2009 10:10 am
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 

Posted: Mon Aug 24, 2009 12:06 pm
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

Posted: Mon Aug 24, 2009 12:25 pm
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

Posted: Mon Aug 24, 2009 12:31 pm
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.
---------------------------

Posted: Mon Aug 24, 2009 1:01 pm
by Progi1984

Posted: Mon Aug 24, 2009 1:26 pm
by SFSxOI
Very nice, thank you for the complete package download Progi1984 :)

Posted: Mon Aug 24, 2009 1:27 pm
by Num3
Nice!

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

Image

Posted: Mon Aug 24, 2009 2:27 pm
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.

Posted: Mon Aug 24, 2009 3:03 pm
by ts-soft
Thx for the complete paket and thx for sharing this great stuff :D

Posted: Mon Aug 24, 2009 5:55 pm
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!!!

Posted: Mon Aug 24, 2009 6:43 pm
by Progi1984
@Num3 : As you can see, there are some maps systems :
http://stable.toolserver.org/geohack/ge ... 2_19.59_E_

Posted: Mon Aug 24, 2009 6:45 pm
by srod
Great work Progi - works very well here. Thanks.

Posted: Mon Aug 24, 2009 9:40 pm
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!)

Posted: Mon Aug 24, 2009 10:16 pm
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)

Posted: Mon Aug 24, 2009 11:55 pm
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 :(