Page 3 sur 16

Re: OpenStreetMap dans un Canvas

Publié : ven. 08/juil./2016 11:45
par djes
Je ne sais pas pourquoi il y avait un zoom + 1, ce qui m'a causé bien des tracas. Cela ne servait à rien, il n'y a pas d'histoire de 512, les tuiles font bien 256 pixels, et elles sont servies sur ce principe. Maintenant, il faut travailler sur le centrage de la carte sur les coordonnées du point voulu, et pas sur le coin de la tuile. Je suis dessus, voici le code pour l'instant

Code : Tout sélectionner

InitNetwork()

DeclareModule OSM
  Declare InitOSM()
  Declare OSMGadget(Gadget.i, X.i, Y.i, Width.i, Height.i)
  Declare Event(Event.l)
  Declare SetLocation(latitude.d, longitude.d, zoom = 15)
  Declare GetSquareTile()
  Declare DrawMap()
  Declare SetZoom(Zoom.i, mode.i = #PB_Relative)
EndDeclareModule

Module OSM
  #USEPROXY = #False
  UsePNGImageDecoder()
  UsePNGImageEncoder()
  
  CompilerIf #USEPROXY = #True
    IncludeFile("C : \Users\lebrun_y_413\Documents\Developpement\Purebasic\includes Share\http.pbi")
  CompilerEndIf
  
  Structure Location
    Longitude.d
    Latitude.d
  EndStructure
  
  Structure Tile
    X.i
    Y.i
  EndStructure
  
  Structure Pixel
    X.i
    Y.i
  EndStructure
  
  Structure OSM
    Gadget.i
    TargetLocation.Location
    TargetTile.tile
    
    ServerURL.s
    ZoomMin.i
    ZoomMax.i
    Zoom.i
    
    CachePath.S
    
    StartCursor.Pixel
    DeltaCursor.Pixel
    
    Shift.Pixel
  EndStructure
  
  Global OSM.OSM
  
  Procedure InitOSM()
    OSM\CachePath = GetTemporaryDirectory()
    OSM\ServerURL = "http://tile.openstreetmap.org/"
    OSM\ZoomMin = 0
    OSM\ZoomMax = 18
    OSM\StartCursor\X = - 1
  EndProcedure
  
  Procedure OSMGadget(Gadget.i, X.i, Y.i, Width.i, Height.i)
    If Gadget = #PB_Any
      OSM\Gadget = CanvasGadget(OSM\Gadget, X, Y, Width, Height)
    Else
      OSM\Gadget = Gadget
      CanvasGadget(OSM\Gadget, X, Y, Width, Height)
    EndIf 
  EndProcedure
  
  Procedure LatLon2XY(*Location.Location, *Tile.Tile)
    Protected n.d = Pow(2.0, OSM\Zoom)
    Protected LatRad.d = Radian(*Location\Latitude)
    *Tile\X = n * ( (*Location\Longitude + 180.0) / 360.0)
    *Tile\Y = n * ( 1.0 - Log(Tan(LatRad) + 1.0/Cos(LatRad)) / #PI ) / 2.0
    Debug "Latitude : " + StrD(*Location\Latitude) + " ; Longitude : " + StrD(*Location\Longitude)
    Debug "Tile X : " + Str(*Tile\X) + " ; Tile Y : " + Str(*Tile\Y)
  EndProcedure
  
  Procedure XY2LatLon(*Tile.Tile, *Location.Location)
    Protected n.d = Pow(2.0, OSM\Zoom)
    Protected LatitudeRad.d
    *Location\Longitude  = *Tile\X / n * 360.0 - 180.0
    LatitudeRad = ATan(SinH(#PI * (1.0 - 2.0 * *Tile\Y / n)))
    *Location\Latitude = Degree(LatitudeRad)
  EndProcedure
  
  Procedure LoadMapTile(Image.i, Zoom.i, XTile.i, YTile.i)
    Protected *Buffer
    Protected TileURL.s = OSM\ServerURL + Str(Zoom) + "/" + Str(XTile) + "/" + Str(YTile) + ".png"
    ; Test if in cache else download it
    Protected CacheFile.s = "OSM_" + Str(Zoom) + "_" + Str(XTile) + "_" + Str(YTile) + ".png"
    If FileSize(osm\cachePath + cacheFile) > 0
      Debug "Use Cache : " + cacheFile
      LoadImage(Image, OSM\CachePath + CacheFile)
    Else 
      ;Debug "DOWNLOAD : " + psURL
      CompilerIf #USEPROXY = #True
        Protected http.HTTP_Query
        HTTP_proxy(@http, "spxy.bpi.fr", 3128)
        HTTP_DownloadToMem(@http, TileURL)
        If IsImage(Image)
          FreeImage(Image)
        EndIf
        If CatchImage(Image, http\data, MemorySize(http\data))
          SaveImage(Image, OSM\CachePath + CacheFile, #PB_ImagePlugin_PNG)
        EndIf
      CompilerElse
        *Buffer = ReceiveHTTPMemory(TileURL)  ;TODO to thread by using #PB_HTTP_Asynchronous
        If IsImage(Image)
          FreeImage(Image)
        EndIf
        If *Buffer
          If CatchImage(Image, *Buffer, MemorySize(*Buffer))
            Debug "Loaded :" + TileURL
            SaveImage(image, OSM\CachePath + CacheFile, #PB_ImagePlugin_PNG)
            FreeMemory(*Buffer)
          Else
            Debug "Can't catch image :" + TileURL
          EndIf
        Else
          Debug "Problem loading :" + TileURL
        EndIf
      CompilerEndIf
      
    EndIf
    
  EndProcedure
  
  Procedure GetSquareTile()
    Protected x.i, y.i, nx.i, ny.i, n.i = 0, tx.i, ty.i
    mx = GadgetWidth(OSM\Gadget)
    my = GadgetHeight(OSM\Gadget)
    nx = mx/256 ;How many tiles
    ny = my/256
    mx/2 : my/2 ;Gadget center
    tx = OSM\TargetTile\X
    ty = OSM\TargetTile\Y
    For y = ty - ny To ty + ny + ny - 1
      For x = tx - nx To tx + nx + nx - 1
        LoadMapTile(n, OSM\Zoom, x, y)
        n = n + 1
      Next
    Next
    Debug Str(n) + " Images Chargées";
  EndProcedure
  
  Procedure DrawMap()
    Protected x.i, y.i, nx.i, ny.i, mx.i, my.i, n.i = 0
    Protected deltaX.i, deltaY.i

    ;Protected tx.i, ty.i
    Protected x2.i, y2.i
    ;deltaX = 512*(OSM\TargetTile\X - Int(OSM\TargetTile\X)) - 256 ;TODO Why - 256 ?????
    ;deltaY = 512*(OSM\TargetTile\Y - Int(OSM\TargetTile\Y)) - 512 ;TODO Why - 512 ?????
    ;tx = 2 * OSM\TargetTile\X
    ;ty = 2 * OSM\TargetTile\Y
        
    mx = GadgetWidth(OSM\Gadget)
    my = GadgetHeight(OSM\Gadget)
    nx = mx/256 ;How many tiles
    ny = my/256
    mx/2 : my/2 ;Gadget center
    
    StartDrawing(CanvasOutput(OSM\Gadget))
    Box(0, 0, GadgetWidth(OSM\Gadget), GadgetHeight(OSM\Gadget), RGB(255, 255, 255))
    
    For y = - ny To ny + ny - 1
      For x = - nx To nx + nx - 1
        x2 = x*256 + OSM\DeltaCursor\X
        y2 = y*256 + OSM\DeltaCursor\Y
        If IsImage(n) And (x2 + 256) > 0 And (y2 + 256) > 0 And x2 < GadgetWidth(OSM\Gadget) And y2 < GadgetHeight(OSM\Gadget)
          DrawImage(ImageID(n), mx + x2 - 128, my + y2 - 128, 254, 254)
          DrawText( x2, y2, Str(x) + ", " + Str(y))
        EndIf        
        n = n + 1
      Next
    Next
    
    Circle(GadgetWidth(OSM\Gadget)/2, GadgetHeight(OSM\Gadget)/2, 5, #Red)
    ;DrawText(0, 0, "DeltaCursorX : " + Str(OSM\DeltaCursor\X) + " deltaX : " + Str(deltaX) + " Tile X : " + StrD(OSM\TargetTile\X))
    DrawText(0, 16, Str(OSM\TargetTile\X + OSM\DeltaCursor\X) + " " + Str(OSM\TargetTile\Y + OSM\DeltaCursor\Y))
    StopDrawing()
  EndProcedure
  
  Procedure SetLocation(latitude.d, longitude.d, zoom = 15)
    If zoom > OSM\ZoomMax : zoom = OSM\ZoomMax : EndIf
    If zoom < OSM\ZoomMin : zoom = OSM\ZoomMin : EndIf
    OSM\Zoom = zoom
    OSM\TargetLocation\Latitude = latitude
    OSM\TargetLocation\Longitude = longitude
    LatLon2XY(@OSM\TargetLocation, @OSM\TargetTile)
  EndProcedure
  
  Procedure TileTranslate(*Tile.Tile, tx.d, ty.d)
    Debug " - move - "
    
    Protected pfValue.d
    If tx <> 0
      pfValue = *Tile\X - tx
      If pfValue > Pow(2, OSM\Zoom) - 1
        *Tile\X = Pow(2, OSM\Zoom) - 2
      ElseIf pfValue < 0 
        *Tile\X = Pow(2, OSM\Zoom) - 2
      Else
        *Tile\X = pfValue
        
      EndIf
    EndIf
    
    If ty <> 0
      pfValue = *Tile\Y - ty
      If pfValue > Pow(2, OSM\Zoom) - 1
        *Tile\Y = Pow(2, OSM\Zoom) - 2
      ElseIf pfValue < 0 
        *Tile\Y = Pow(2, OSM\Zoom) - 2
      Else
        *Tile\Y = pfValue
        
      EndIf
    EndIf
  EndProcedure
  
  Procedure SetZoom(Zoom.i, mode.i = #PB_Relative)
    Select mode
      Case #PB_Relative
        OSM\Zoom = OSM\Zoom + zoom
      Case #PB_Absolute
        OSM\Zoom = zoom
    EndSelect
    If OSM\Zoom > OSM\ZoomMax : OSM\Zoom = OSM\ZoomMax : EndIf
    If OSM\Zoom < OSM\ZoomMin : OSM\Zoom = OSM\ZoomMin : EndIf
    LatLon2XY(@OSM\TargetLocation, @OSM\TargetTile)
    GetSquareTile()
    DrawMap()
  EndProcedure
  
  Procedure Event(Event.l)
    Protected Gadget.i
    Protected tx.i, ty.i
    If IsGadget(OSM\Gadget) And GadgetType(OSM\Gadget) = #PB_GadgetType_Canvas 
      Select Event
        Case #PB_Event_Gadget ;{
          Gadget = EventGadget()
          Select Gadget
            Case OSM\Gadget
              Select EventType()
                Case #PB_EventType_LeftButtonDown
                  ;Mem cursor Coord
                  OSM\StartCursor\X = GetGadgetAttribute(OSM\Gadget, #PB_Canvas_MouseX) 
                  OSM\StartCursor\Y = GetGadgetAttribute(OSM\Gadget, #PB_Canvas_MouseY) 
                Case #PB_EventType_MouseMove 
                  If OSM\StartCursor\X <> - 1
                    tx = GetGadgetAttribute(OSM\Gadget, #PB_Canvas_MouseX) - OSM\StartCursor\X + OSM\Shift\X
                    ty = GetGadgetAttribute(OSM\Gadget, #PB_Canvas_MouseY) - OSM\StartCursor\Y + OSM\Shift\Y
                    ;TileTranslate(@OSM\TargetTile, tx/256, ty/256)
                    OSM\DeltaCursor\X = tx%256
                    OSM\DeltaCursor\Y = ty%256
                    If tx/256 <> 0 Or ty/256 <> 0
                      OSM\TargetTile\X - tx/256
                      OSM\TargetTile\Y - ty/256
                      OSM\Shift\X = OSM\DeltaCursor\X                     
                      OSM\Shift\Y = OSM\DeltaCursor\Y
                      OSM\StartCursor\X = GetGadgetAttribute(OSM\Gadget, #PB_Canvas_MouseX) 
                      OSM\StartCursor\Y = GetGadgetAttribute(OSM\Gadget, #PB_Canvas_MouseY) 
                      XY2LatLon(@OSM\TargetTile, @OSM\TargetLocation)
                      ;SetLocation(OSM\TargetLocation\Latitude, OSM\TargetLocation\Longitude, OSM\Zoom)
                      GetSquareTile()
                    EndIf
                    DrawMap()
                  EndIf 
                Case #PB_EventType_LeftButtonUp
                  OSM\Shift\X = OSM\DeltaCursor\X
                  OSM\Shift\Y = OSM\DeltaCursor\Y
                  OSM\DeltaCursor\X = 0
                  OSM\DeltaCursor\Y = 0
                  OSM\StartCursor\X = - 1
                  ;move(tx, ty)
                  ;SetGadgetText(#String_1, StrD(OSM\TargetLocation\Latitude))
                  ;SetGadgetText(#String_0, StrD(OSM\TargetLocation\Longitude))
              EndSelect
          EndSelect
      EndSelect
    Else
      MessageRequester("Module OSM", "You must use OSMGadget before", #PB_MessageRequester_Ok )
      End
    EndIf  
  EndProcedure
EndModule

Enumeration
  #Window_0
  #Map
  #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

;- Main
If OpenWindow(#Window_0, 260, 225, 700, 571, "OpenStreetMap",  #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_TitleBar | #PB_Window_ScreenCentered )
  
  OSM::InitOSM()
  LoadFont(0, "Wingdings", 12)
  LoadFont(1, "Arial", 12, #PB_Font_Bold)
  
  OSM::OSMGadget(#Map, 10, 10, 512, 512)
  
  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, 90, 20, "")
  TextGadget(#Text_4, 530, 250, 60, 15, "Longitude : ")
  StringGadget(#String_1, 600, 250, 90, 20, "")
  
  Define Event.i, Gadget.i, Quit.b = #False
  Define pfValue.d
  OSM::SetLocation(49.04599, 2.03347, 15)
  OSM::GetSquareTile()
  OSM::DrawMap()
  ;OSM::SetLocation(49.0361165, 2.0456982)
  
  Repeat
    Event = WaitWindowEvent()
    
    OSM::Event(Event)
    Select Event
      Case #PB_Event_CloseWindow : Quit = 1
      Case #PB_Event_Gadget ;{
        Gadget = EventGadget()
        Select Gadget
          Case #Button_4
            OSM::SetZoom(1)
          Case #Button_5
            OSM::SetZoom( - 1)
        EndSelect
    EndSelect
  Until Quit = #True
EndIf

Re: OpenStreetMap dans un Canvas

Publié : sam. 09/juil./2016 6:33
par Thyphoon
vraiment un super boulot ! Je suis admiratif ! :D

oui le zoom+1 venait du code de progi1984 je ne le comprenais pas mais je lui faisait confiance :lol:
par-contre j'ai vu que tu avais modifier la structure Tile pour la passer en integer plutôt qu'en double.
hors on a besoin du chiffre après la virgule pour centrer l'image. je l'ai repassé en double et ça n' interfére pas sur ce que tu as fais.
ensuite je calcul le centrage de l'image

Code : Tout sélectionner

 deltaX = 256*(OSM\TargetTile\X - Int(OSM\TargetTile\X))
 deltaY = 256*(OSM\TargetTile\Y - Int(OSM\TargetTile\Y))
et j'ai juste modifier la routine d'affichage. de façon a ce que le calcul de x2 et y2 soit avant le teste pour savoir si il on dessine ou pas le Tile

Code : Tout sélectionner

 For y = - ny To ny + ny - 1
      For x = - nx To nx + nx - 1
        x2 = x*256 + OSM\DeltaCursor\X   + mx -deltaX
        y2 = y*256 + OSM\DeltaCursor\Y   + my - deltaY
        If IsImage(n) And (x2 + 256) > 0 And (y2 + 256) > 0 And x2 < GadgetWidth(OSM\Gadget) And y2 < GadgetHeight(OSM\Gadget)
          DrawImage(ImageID(n), x2,y2, 254, 254)
          DrawText( x2, y2, Str(x) + ", " + Str(y))
        EndIf        
        n = n + 1
      Next
    Next
Du coup on est bien centré en X mais on est 2 Tiles en dessous en Y
et lorsqu'on change le zoom ça finit part ne plus rester centré sur le même point :cry:
voilà ce que ça donne. Mais je fais peut être toujours la même erreur depuis le début et tu avais peut être une autre façon de faire en tête.

Code : Tout sélectionner

InitNetwork()

DeclareModule OSM
  Declare InitOSM()
  Declare OSMGadget(Gadget.i, X.i, Y.i, Width.i, Height.i)
  Declare Event(Event.l)
  Declare SetLocation(latitude.d, longitude.d, zoom = 15)
  Declare GetSquareTile()
  Declare DrawMap()
  Declare SetZoom(Zoom.i, mode.i = #PB_Relative)
EndDeclareModule

Module OSM
  #USEPROXY = #False
  UsePNGImageDecoder()
  UsePNGImageEncoder()
  
  CompilerIf #USEPROXY = #True
    IncludeFile("C : \Users\lebrun_y_413\Documents\Developpement\Purebasic\includes Share\http.pbi")
  CompilerEndIf
  
  Structure Location
    Longitude.d
    Latitude.d
  EndStructure
  
  Structure Tile
    X.d
    Y.d
  EndStructure
  
  Structure Pixel
    X.i
    Y.i
  EndStructure
  
  Structure OSM
    Gadget.i
    TargetLocation.Location
    TargetTile.tile
    
    ServerURL.s
    ZoomMin.i
    ZoomMax.i
    Zoom.i
    
    CachePath.S
    
    StartCursor.Pixel
    DeltaCursor.Pixel
    
    Shift.Pixel
  EndStructure
  
  Global OSM.OSM
  
  Procedure InitOSM()
    OSM\CachePath = GetTemporaryDirectory()
    OSM\ServerURL = "http://tile.openstreetmap.org/"
    OSM\ZoomMin = 0
    OSM\ZoomMax = 18
    OSM\StartCursor\X = - 1
  EndProcedure
  
  Procedure OSMGadget(Gadget.i, X.i, Y.i, Width.i, Height.i)
    If Gadget = #PB_Any
      OSM\Gadget = CanvasGadget(OSM\Gadget, X, Y, Width, Height)
    Else
      OSM\Gadget = Gadget
      CanvasGadget(OSM\Gadget, X, Y, Width, Height)
    EndIf 
  EndProcedure
  
  Procedure LatLon2XY(*Location.Location, *Tile.Tile)
    Protected n.d = Pow(2.0, OSM\Zoom)
    Protected LatRad.d = Radian(*Location\Latitude)
    *Tile\X = n * ( (*Location\Longitude + 180.0) / 360.0)
    *Tile\Y = n * ( 1.0 - Log(Tan(LatRad) + 1.0/Cos(LatRad)) / #PI ) / 2.0
    Debug "Latitude : " + StrD(*Location\Latitude) + " ; Longitude : " + StrD(*Location\Longitude)
    Debug "Tile X : " + Str(*Tile\X) + " ; Tile Y : " + Str(*Tile\Y)
  EndProcedure
  
  Procedure XY2LatLon(*Tile.Tile, *Location.Location)
    Protected n.d = Pow(2.0, OSM\Zoom)
    Protected LatitudeRad.d
    *Location\Longitude  = *Tile\X / n * 360.0 - 180.0
    LatitudeRad = ATan(SinH(#PI * (1.0 - 2.0 * *Tile\Y / n)))
    *Location\Latitude = Degree(LatitudeRad)
  EndProcedure
  
  Procedure LoadMapTile(Image.i, Zoom.i, XTile.i, YTile.i)
    Protected *Buffer
    Protected TileURL.s = OSM\ServerURL + Str(Zoom) + "/" + Str(XTile) + "/" + Str(YTile) + ".png"
    ; Test if in cache else download it
    Protected CacheFile.s = "OSM_" + Str(Zoom) + "_" + Str(XTile) + "_" + Str(YTile) + ".png"
    If FileSize(osm\cachePath + cacheFile) > 0
      Debug "Use Cache : " + cacheFile
      LoadImage(Image, OSM\CachePath + CacheFile)
    Else 
      ;Debug "DOWNLOAD : " + psURL
      CompilerIf #USEPROXY = #True
        Protected http.HTTP_Query
        HTTP_proxy(@http, "spxy.bpi.fr", 3128)
        HTTP_DownloadToMem(@http, TileURL)
        If IsImage(Image)
          FreeImage(Image)
        EndIf
        If CatchImage(Image, http\data, MemorySize(http\data))
          SaveImage(Image, OSM\CachePath + CacheFile, #PB_ImagePlugin_PNG)
        EndIf
      CompilerElse
        *Buffer = ReceiveHTTPMemory(TileURL)  ;TODO to thread by using #PB_HTTP_Asynchronous
        If IsImage(Image)
          FreeImage(Image)
        EndIf
        If *Buffer
          If CatchImage(Image, *Buffer, MemorySize(*Buffer))
            Debug "Loaded :" + TileURL
            SaveImage(image, OSM\CachePath + CacheFile, #PB_ImagePlugin_PNG)
            FreeMemory(*Buffer)
          Else
            Debug "Can't catch image :" + TileURL
          EndIf
        Else
          Debug "Problem loading :" + TileURL
        EndIf
      CompilerEndIf
      
    EndIf
    
  EndProcedure
  
  Procedure GetSquareTile()
    Protected x.i, y.i, nx.i, ny.i, n.i = 0, tx.i, ty.i
    mx = GadgetWidth(OSM\Gadget)
    my = GadgetHeight(OSM\Gadget)
    nx = mx/256 ;How many tiles
    ny = my/256
    mx/2 : my/2 ;Gadget center
    tx = OSM\TargetTile\X
    ty = OSM\TargetTile\Y
    For y = ty - ny To ty + ny + ny - 1
      For x = tx - nx To tx + nx + nx - 1
        LoadMapTile(n, OSM\Zoom, x, y)
        n = n + 1
      Next
    Next
    Debug Str(n) + " Images Chargées";
  EndProcedure
  
  Procedure DrawMap()
    Protected x.i, y.i, nx.i, ny.i, mx.i, my.i, n.i = 0
    Protected deltaX.i, deltaY.i

    ;Protected tx.i, ty.i
    Protected x2.i, y2.i
    deltaX = 512*(OSM\TargetTile\X - Int(OSM\TargetTile\X))
    deltaY = 512*(OSM\TargetTile\Y - Int(OSM\TargetTile\Y))
    ;tx = 2 * OSM\TargetTile\X
    ;ty = 2 * OSM\TargetTile\Y
        
    mx = GadgetWidth(OSM\Gadget)
    my = GadgetHeight(OSM\Gadget)
    nx = mx/256 ;How many tiles
    ny = my/256
    mx/2 : my/2 ;Gadget center
    
    StartDrawing(CanvasOutput(OSM\Gadget))
    Box(0, 0, GadgetWidth(OSM\Gadget), GadgetHeight(OSM\Gadget), RGB(255, 255, 255))
    
    For y = - ny To ny + ny - 1
      For x = - nx To nx + nx - 1
        x2 = x*256 + OSM\DeltaCursor\X   + mx -deltaX
        y2 = y*256 + OSM\DeltaCursor\Y   + my - deltaY
        If IsImage(n) And (x2 + 256) > 0 And (y2 + 256) > 0 And x2 < GadgetWidth(OSM\Gadget) And y2 < GadgetHeight(OSM\Gadget)
          DrawImage(ImageID(n), x2,y2, 254, 254)
          DrawText( x2, y2, Str(x) + ", " + Str(y))
        EndIf        
        n = n + 1
      Next
    Next
    
    Circle(GadgetWidth(OSM\Gadget)/2, GadgetHeight(OSM\Gadget)/2, 5, #Red)
    ;DrawText(0, 0, "DeltaCursorX : " + Str(OSM\DeltaCursor\X) + " deltaX : " + Str(deltaX) + " Tile X : " + StrD(OSM\TargetTile\X))
    DrawText(0, 16, Str(OSM\TargetTile\X + OSM\DeltaCursor\X) + " " + Str(OSM\TargetTile\Y + OSM\DeltaCursor\Y))
    StopDrawing()
  EndProcedure
  
  Procedure SetLocation(latitude.d, longitude.d, zoom = 15)
    If zoom > OSM\ZoomMax : zoom = OSM\ZoomMax : EndIf
    If zoom < OSM\ZoomMin : zoom = OSM\ZoomMin : EndIf
    OSM\Zoom = zoom
    OSM\TargetLocation\Latitude = latitude
    OSM\TargetLocation\Longitude = longitude
    LatLon2XY(@OSM\TargetLocation, @OSM\TargetTile)
  EndProcedure
  
  Procedure TileTranslate(*Tile.Tile, tx.d, ty.d)
    Debug " - move - "
    
    Protected pfValue.d
    If tx <> 0
      pfValue = *Tile\X - tx
      If pfValue > Pow(2, OSM\Zoom) - 1
        *Tile\X = Pow(2, OSM\Zoom) - 2
      ElseIf pfValue < 0 
        *Tile\X = Pow(2, OSM\Zoom) - 2
      Else
        *Tile\X = pfValue
        
      EndIf
    EndIf
    
    If ty <> 0
      pfValue = *Tile\Y - ty
      If pfValue > Pow(2, OSM\Zoom) - 1
        *Tile\Y = Pow(2, OSM\Zoom) - 2
      ElseIf pfValue < 0 
        *Tile\Y = Pow(2, OSM\Zoom) - 2
      Else
        *Tile\Y = pfValue
        
      EndIf
    EndIf
  EndProcedure
  
  Procedure SetZoom(Zoom.i, mode.i = #PB_Relative)
    Select mode
      Case #PB_Relative
        OSM\Zoom = OSM\Zoom + zoom
      Case #PB_Absolute
        OSM\Zoom = zoom
    EndSelect
    If OSM\Zoom > OSM\ZoomMax : OSM\Zoom = OSM\ZoomMax : EndIf
    If OSM\Zoom < OSM\ZoomMin : OSM\Zoom = OSM\ZoomMin : EndIf
    LatLon2XY(@OSM\TargetLocation, @OSM\TargetTile)
    GetSquareTile()
    DrawMap()
  EndProcedure
  
  Procedure Event(Event.l)
    Protected Gadget.i
    Protected tx.i, ty.i
    If IsGadget(OSM\Gadget) And GadgetType(OSM\Gadget) = #PB_GadgetType_Canvas 
      Select Event
        Case #PB_Event_Gadget ;{
          Gadget = EventGadget()
          Select Gadget
            Case OSM\Gadget
              Select EventType()
                Case #PB_EventType_LeftButtonDown
                  ;Mem cursor Coord
                  OSM\StartCursor\X = GetGadgetAttribute(OSM\Gadget, #PB_Canvas_MouseX) 
                  OSM\StartCursor\Y = GetGadgetAttribute(OSM\Gadget, #PB_Canvas_MouseY) 
                Case #PB_EventType_MouseMove 
                  If OSM\StartCursor\X <> - 1
                    tx = GetGadgetAttribute(OSM\Gadget, #PB_Canvas_MouseX) - OSM\StartCursor\X + OSM\Shift\X
                    ty = GetGadgetAttribute(OSM\Gadget, #PB_Canvas_MouseY) - OSM\StartCursor\Y + OSM\Shift\Y
                    ;TileTranslate(@OSM\TargetTile, tx/256, ty/256)
                    OSM\DeltaCursor\X = tx%256
                    OSM\DeltaCursor\Y = ty%256
                    If tx/256 <> 0 Or ty/256 <> 0
                      OSM\TargetTile\X - tx/256
                      OSM\TargetTile\Y - ty/256
                      OSM\Shift\X = OSM\DeltaCursor\X                     
                      OSM\Shift\Y = OSM\DeltaCursor\Y
                      OSM\StartCursor\X = GetGadgetAttribute(OSM\Gadget, #PB_Canvas_MouseX) 
                      OSM\StartCursor\Y = GetGadgetAttribute(OSM\Gadget, #PB_Canvas_MouseY) 
                      XY2LatLon(@OSM\TargetTile, @OSM\TargetLocation)
                      ;SetLocation(OSM\TargetLocation\Latitude, OSM\TargetLocation\Longitude, OSM\Zoom)
                      GetSquareTile()
                    EndIf
                    DrawMap()
                  EndIf 
                Case #PB_EventType_LeftButtonUp
                  OSM\Shift\X = OSM\DeltaCursor\X
                  OSM\Shift\Y = OSM\DeltaCursor\Y
                  OSM\DeltaCursor\X = 0
                  OSM\DeltaCursor\Y = 0
                  OSM\StartCursor\X = - 1
                  ;move(tx, ty)
                  ;SetGadgetText(#String_1, StrD(OSM\TargetLocation\Latitude))
                  ;SetGadgetText(#String_0, StrD(OSM\TargetLocation\Longitude))
              EndSelect
          EndSelect
      EndSelect
    Else
      MessageRequester("Module OSM", "You must use OSMGadget before", #PB_MessageRequester_Ok )
      End
    EndIf  
  EndProcedure
EndModule

Enumeration
  #Window_0
  #Map
  #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

;- Main
If OpenWindow(#Window_0, 260, 225, 700, 571, "OpenStreetMap",  #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_TitleBar | #PB_Window_ScreenCentered )
  
  OSM::InitOSM()
  LoadFont(0, "Wingdings", 12)
  LoadFont(1, "Arial", 12, #PB_Font_Bold)
  
  OSM::OSMGadget(#Map, 10, 10, 512, 512)
  
  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, 90, 20, "")
  TextGadget(#Text_4, 530, 250, 60, 15, "Longitude : ")
  StringGadget(#String_1, 600, 250, 90, 20, "")
  
  Define Event.i, Gadget.i, Quit.b = #False
  Define pfValue.d
  OSM::SetLocation(49.04599, 2.03347, 15)
  OSM::GetSquareTile()
  OSM::DrawMap()
  ;OSM::SetLocation(49.0361165, 2.0456982)
  
  Repeat
    Event = WaitWindowEvent()
    
    OSM::Event(Event)
    Select Event
      Case #PB_Event_CloseWindow : Quit = 1
      Case #PB_Event_Gadget ;{
        Gadget = EventGadget()
        Select Gadget
          Case #Button_4
            OSM::SetZoom(1)
          Case #Button_5
            OSM::SetZoom( - 1)
        EndSelect
    EndSelect
  Until Quit = #True
EndIf

Re: OpenStreetMap dans un Canvas

Publié : sam. 09/juil./2016 8:20
par djes
Super, on avance ! Tu as raison pour le .d du tile, la partie flottante est la position sur la tuile. Maintenant, je pense qu'il faut s'attaquer à la boucle de déplacement, parce qu'on n'arrivera pas à s'en sortir avec toutes ces conversions partout. Le mieux serait de se caler sur le point "réel", et de faire l'affichage et les conversions finales en fonction de lui (avec une procédure qui renvoie le numéro de la tuile, une autre le décalage...). Là il y a trop de surcouches d'optims, du coup on s'y perd. On les refera plus tard.

Re: OpenStreetMap dans un Canvas

Publié : sam. 09/juil./2016 20:08
par Thyphoon
cet après midi j'ai essayer de me focaliser sur le point "réel" et de faire l'affichage et les conversions finales en fonction de lui et j'ai fait une découverte...
Avec un Zoom de 17 le point est bien placé ... alors qu'avec les autres valeurs du zoom non ... je commence a me demander si il n'y a pas un souci sur le calcul du tile en fonction du zoom

je te fais grace de tout ce que j'ai essayé mais voici un code qui n'affiche qu'un tile avec un zoom de 17.
Pour toi on doit faire les calculs a partir du Tile ou du Quadrant ?

Code : Tout sélectionner

InitNetwork()

DeclareModule OSM
  Declare InitOSM()
  Declare OSMGadget(Gadget.i, X.i, Y.i, Width.i, Height.i)
  Declare Event(Event.l)
  Declare SetLocation(latitude.d, longitude.d, zoom = 15)
  Declare GetSquareTile()
  Declare DrawMap()
  Declare SetZoom(Zoom.i, mode.i = #PB_Relative)
EndDeclareModule

Module OSM
  #USEPROXY = #False
  UsePNGImageDecoder()
  UsePNGImageEncoder()
  
  CompilerIf #USEPROXY = #True
    IncludeFile("C : \Users\lebrun_y_413\Documents\Developpement\Purebasic\includes Share\http.pbi")
  CompilerEndIf
  
  Structure Location
    Longitude.d
    Latitude.d
  EndStructure
  
  Structure Tile
    X.d
    Y.d
  EndStructure
  
  Structure Pixel
    X.i
    Y.i
  EndStructure
  
  Structure OSM
    Gadget.i
    TargetLocation.Location
    TargetTile.tile
    
    ServerURL.s
    ZoomMin.i
    ZoomMax.i
    Zoom.i
    
    CachePath.S
    
    StartCursor.Pixel
    DeltaCursor.Pixel
    
    Shift.Pixel
  EndStructure
  
  Global OSM.OSM
  
  Procedure InitOSM()
    OSM\CachePath = GetTemporaryDirectory()
    OSM\ServerURL = "http://tile.openstreetmap.org/"
    OSM\ZoomMin = 0
    OSM\ZoomMax = 18
    OSM\StartCursor\X = - 1
  EndProcedure
  
  Procedure OSMGadget(Gadget.i, X.i, Y.i, Width.i, Height.i)
    If Gadget = #PB_Any
      OSM\Gadget = CanvasGadget(OSM\Gadget, X, Y, Width, Height)
    Else
      OSM\Gadget = Gadget
      CanvasGadget(OSM\Gadget, X, Y, Width, Height)
    EndIf 
  EndProcedure
  
  Procedure LatLon2XY(*Location.Location, *Tile.Tile)
    Protected n.d = Pow(2.0, OSM\Zoom)
    Protected LatRad.d = Radian(*Location\Latitude)
    *Tile\X = n * ( (*Location\Longitude + 180.0) / 360.0)
    *Tile\Y = n * ( 1.0 - Log(Tan(LatRad) + 1.0/Cos(LatRad)) / #PI ) / 2.0
    Debug "Latitude : " + StrD(*Location\Latitude) + " ; Longitude : " + StrD(*Location\Longitude)
    Debug "Tile X : " + Str(*Tile\X) + " ; Tile Y : " + Str(*Tile\Y)
  EndProcedure
  
  Procedure XY2LatLon(*Tile.Tile, *Location.Location)
    Protected n.d = Pow(2.0, OSM\Zoom)
    Protected LatitudeRad.d
    *Location\Longitude  = *Tile\X / n * 360.0 - 180.0
    LatitudeRad = ATan(SinH(#PI * (1.0 - 2.0 * *Tile\Y / n)))
    *Location\Latitude = Degree(LatitudeRad)
  EndProcedure
  
  Procedure LoadMapTile(Image.i, Zoom.i, XTile.i, YTile.i)
    Protected *Buffer
    Protected TileURL.s = OSM\ServerURL + Str(Zoom) + "/" + Str(XTile) + "/" + Str(YTile) + ".png"
    ; Test if in cache else download it
    Protected CacheFile.s = "OSM_" + Str(Zoom) + "_" + Str(XTile) + "_" + Str(YTile) + ".png"
    If FileSize(osm\cachePath + cacheFile) > 0
      Debug "Use Cache : " + cacheFile
      LoadImage(Image, OSM\CachePath + CacheFile)
    Else 
      ;Debug "DOWNLOAD : " + psURL
      CompilerIf #USEPROXY = #True
        Protected http.HTTP_Query
        HTTP_proxy(@http, "spxy.bpi.fr", 3128)
        HTTP_DownloadToMem(@http, TileURL)
        If IsImage(Image)
          FreeImage(Image)
        EndIf
        If CatchImage(Image, http\data, MemorySize(http\data))
          SaveImage(Image, OSM\CachePath + CacheFile, #PB_ImagePlugin_PNG)
        EndIf
      CompilerElse
        *Buffer = ReceiveHTTPMemory(TileURL)  ;TODO to thread by using #PB_HTTP_Asynchronous
        If IsImage(Image)
          FreeImage(Image)
        EndIf
        If *Buffer
          If CatchImage(Image, *Buffer, MemorySize(*Buffer))
            Debug "Loaded :" + TileURL
            SaveImage(image, OSM\CachePath + CacheFile, #PB_ImagePlugin_PNG)
            FreeMemory(*Buffer)
          Else
            Debug "Can't catch image :" + TileURL
          EndIf
        Else
          Debug "Problem loading :" + TileURL
        EndIf
      CompilerEndIf
      
    EndIf
    
  EndProcedure
  
  Procedure GetSquareTile()
    Protected x.i, y.i, nx.i, ny.i, n.i = 0, tx.i, ty.i
    mx = GadgetWidth(OSM\Gadget)
    my = GadgetHeight(OSM\Gadget)
    nx = mx/256 ;How many tiles
    ny = my/256
    mx/2 : my/2 ;Gadget center
    tx = OSM\TargetTile\X
    ty = OSM\TargetTile\Y

        LoadMapTile(1, OSM\Zoom, tx, ty)
    
  EndProcedure
  
 
  Procedure DrawMap()
    Protected x.i, y.i, nx.i, ny.i, mx.i, my.i, n.i = 0
    Protected deltaX.i, deltaY.i
    Protected x2.i, y2.i
    deltaX = 256*(OSM\TargetTile\X - Int(OSM\TargetTile\X))
    deltaY = 256*(OSM\TargetTile\Y - Int(OSM\TargetTile\Y))

    mx = GadgetWidth(OSM\Gadget)/2
    my = GadgetHeight(OSM\Gadget)/2

    
    StartDrawing(CanvasOutput(OSM\Gadget))
    Box(0, 0, GadgetWidth(OSM\Gadget), GadgetHeight(OSM\Gadget), RGB(255, 255, 255))
  
        x2 = x*256 + OSM\DeltaCursor\X   + mx -deltaX
        y2 = y*256 + OSM\DeltaCursor\Y   + my - deltaY
        If IsImage(1)
          DrawImage(ImageID(1), mx-deltaX,my-deltaY, 256, 256)
        EndIf        
    
    Circle(mx, my, 5, #Red)
    StopDrawing()
  EndProcedure
  
  Procedure SetLocation(latitude.d, longitude.d, zoom = 15)
    If zoom > OSM\ZoomMax : zoom = OSM\ZoomMax : EndIf
    If zoom < OSM\ZoomMin : zoom = OSM\ZoomMin : EndIf
    OSM\Zoom = zoom
    OSM\TargetLocation\Latitude = latitude
    OSM\TargetLocation\Longitude = longitude
    LatLon2XY(@OSM\TargetLocation, @OSM\TargetTile)
  EndProcedure
  
  Procedure TileTranslate(*Tile.Tile, tx.d, ty.d)
    Debug " - move - "
    
    Protected pfValue.d
    If tx <> 0
      pfValue = *Tile\X - tx
      If pfValue > Pow(2, OSM\Zoom) - 1
        *Tile\X = Pow(2, OSM\Zoom) - 2
      ElseIf pfValue < 0 
        *Tile\X = Pow(2, OSM\Zoom) - 2
      Else
        *Tile\X = pfValue
        
      EndIf
    EndIf
    
    If ty <> 0
      pfValue = *Tile\Y - ty
      If pfValue > Pow(2, OSM\Zoom) - 1
        *Tile\Y = Pow(2, OSM\Zoom) - 2
      ElseIf pfValue < 0 
        *Tile\Y = Pow(2, OSM\Zoom) - 2
      Else
        *Tile\Y = pfValue
        
      EndIf
    EndIf
  EndProcedure
  
  Procedure SetZoom(Zoom.i, mode.i = #PB_Relative)
    Select mode
      Case #PB_Relative
        OSM\Zoom = OSM\Zoom + zoom
      Case #PB_Absolute
        OSM\Zoom = zoom
    EndSelect
    If OSM\Zoom > OSM\ZoomMax : OSM\Zoom = OSM\ZoomMax : EndIf
    If OSM\Zoom < OSM\ZoomMin : OSM\Zoom = OSM\ZoomMin : EndIf
    LatLon2XY(@OSM\TargetLocation, @OSM\TargetTile)
    GetSquareTile()
    DrawMap()
  EndProcedure
  
  Procedure Event(Event.l)
    Protected Gadget.i
    Protected tx.i, ty.i
    If IsGadget(OSM\Gadget) And GadgetType(OSM\Gadget) = #PB_GadgetType_Canvas 
      Select Event
        Case #PB_Event_Gadget ;{
          Gadget = EventGadget()
          Select Gadget
            Case OSM\Gadget
              Select EventType()
                Case #PB_EventType_LeftButtonDown
                  ;Mem cursor Coord
                  OSM\StartCursor\X = GetGadgetAttribute(OSM\Gadget, #PB_Canvas_MouseX) 
                  OSM\StartCursor\Y = GetGadgetAttribute(OSM\Gadget, #PB_Canvas_MouseY) 
                Case #PB_EventType_MouseMove 
                  If OSM\StartCursor\X <> - 1
                    tx = GetGadgetAttribute(OSM\Gadget, #PB_Canvas_MouseX) - OSM\StartCursor\X + OSM\Shift\X
                    ty = GetGadgetAttribute(OSM\Gadget, #PB_Canvas_MouseY) - OSM\StartCursor\Y + OSM\Shift\Y
                    ;TileTranslate(@OSM\TargetTile, tx/256, ty/256)
                    OSM\DeltaCursor\X = tx%256
                    OSM\DeltaCursor\Y = ty%256
                    If tx/256 <> 0 Or ty/256 <> 0
                      OSM\TargetTile\X - tx/256
                      OSM\TargetTile\Y - ty/256
                      OSM\Shift\X = OSM\DeltaCursor\X                     
                      OSM\Shift\Y = OSM\DeltaCursor\Y
                      OSM\StartCursor\X = GetGadgetAttribute(OSM\Gadget, #PB_Canvas_MouseX) 
                      OSM\StartCursor\Y = GetGadgetAttribute(OSM\Gadget, #PB_Canvas_MouseY) 
                      XY2LatLon(@OSM\TargetTile, @OSM\TargetLocation)
                      ;SetLocation(OSM\TargetLocation\Latitude, OSM\TargetLocation\Longitude, OSM\Zoom)
                      GetSquareTile()
                    EndIf
                    DrawMap()
                  EndIf 
                Case #PB_EventType_LeftButtonUp
                  OSM\Shift\X = OSM\DeltaCursor\X
                  OSM\Shift\Y = OSM\DeltaCursor\Y
                  OSM\DeltaCursor\X = 0
                  OSM\DeltaCursor\Y = 0
                  OSM\StartCursor\X = - 1
                  ;move(tx, ty)
                  ;SetGadgetText(#String_1, StrD(OSM\TargetLocation\Latitude))
                  ;SetGadgetText(#String_0, StrD(OSM\TargetLocation\Longitude))
              EndSelect
          EndSelect
      EndSelect
    Else
      MessageRequester("Module OSM", "You must use OSMGadget before", #PB_MessageRequester_Ok )
      End
    EndIf  
  EndProcedure
EndModule

Enumeration
  #Window_0
  #Map
  #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

;- Main
If OpenWindow(#Window_0, 260, 225, 700, 571, "OpenStreetMap",  #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_TitleBar | #PB_Window_ScreenCentered )
  
  OSM::InitOSM()
  LoadFont(0, "Wingdings", 12)
  LoadFont(1, "Arial", 12, #PB_Font_Bold)
  
  OSM::OSMGadget(#Map, 10, 10, 512, 512)
  
  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, 90, 20, "")
  TextGadget(#Text_4, 530, 250, 60, 15, "Longitude : ")
  StringGadget(#String_1, 600, 250, 90, 20, "")
  
  Define Event.i, Gadget.i, Quit.b = #False
  Define pfValue.d
  OSM::SetLocation(49.04599, 2.03347, 17)
  OSM::GetSquareTile()
  OSM::DrawMap()
  ;OSM::SetLocation(49.0361165, 2.0456982)
  
  Repeat
    Event = WaitWindowEvent()
    
    OSM::Event(Event)
    Select Event
      Case #PB_Event_CloseWindow : Quit = 1
      Case #PB_Event_Gadget ;{
        Gadget = EventGadget()
        Select Gadget
          Case #Button_4
            OSM::SetZoom(1)
          Case #Button_5
            OSM::SetZoom( - 1)
        EndSelect
    EndSelect
  Until Quit = #True
EndIf 

Re: OpenStreetMap dans un Canvas

Publié : sam. 09/juil./2016 23:29
par MetalOS
Je n'est pas regarder vos code mais je me demandais si vous utilisez un système de projection comme mercator ou lambert ?

Re: OpenStreetMap dans un Canvas

Publié : dim. 10/juil./2016 0:11
par djes
Là c'est du Mercator adapté à la sauce web. Tu peux aller voir là pour plus d'infos http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames

Re: OpenStreetMap dans un Canvas

Publié : dim. 10/juil./2016 10:54
par djes
Thyphoon> On comprend mieux comme ça ! J'ai corrigé une vilaine erreur d'arrondi, mais il y a encore un peu d'imprécision. On s'approche !

Code : Tout sélectionner

InitNetwork()

DeclareModule OSM
  Declare InitOSM()
  Declare OSMGadget(Gadget.i, X.i, Y.i, Width.i, Height.i)
  Declare Event(Event.l)
  Declare SetLocation(latitude.d, longitude.d, zoom = 15)
  Declare GetSquareTile()
  Declare DrawMap()
  Declare SetZoom(Zoom.i, mode.i = #PB_Relative)
EndDeclareModule

Module OSM
  #USEPROXY = #False
  UsePNGImageDecoder()
  UsePNGImageEncoder()
  
  CompilerIf #USEPROXY = #True
    IncludeFile("C : \Users\lebrun_y_413\Documents\Developpement\Purebasic\includes Share\http.pbi")
  CompilerEndIf
  
  Structure Location
    Longitude.d
    Latitude.d
  EndStructure
  
  Structure Tile
    X.d
    Y.d
  EndStructure
  
  Structure Pixel
    X.i
    Y.i
  EndStructure
  
  Structure OSM
    Gadget.i
    TargetLocation.Location
    TargetTile.tile
    
    Position.Pixel
    
    ServerURL.s
    ZoomMin.i
    ZoomMax.i
    Zoom.i
    
    TileSize.i
    
    CachePath.S
    
    StartCursor.Pixel
    DeltaCursor.Pixel
    
    Shift.Pixel
  EndStructure
  
  Global OSM.OSM
  
  Procedure InitOSM()
    OSM\CachePath = GetTemporaryDirectory()
    OSM\ServerURL = "http://tile.openstreetmap.org/"
    OSM\ZoomMin = 0
    OSM\ZoomMax = 18
    OSM\StartCursor\X = - 1
    OSM\TileSize = 256
  EndProcedure
  
  Procedure OSMGadget(Gadget.i, X.i, Y.i, Width.i, Height.i)
    If Gadget = #PB_Any
      OSM\Gadget = CanvasGadget(OSM\Gadget, X, Y, Width, Height)
    Else
      OSM\Gadget = Gadget
      CanvasGadget(OSM\Gadget, X, Y, Width, Height)
    EndIf 
  EndProcedure
  
  Procedure LatLon2XY(*Location.Location, *Tile.Tile)
    Protected n.d = Pow(2.0, OSM\Zoom)
    Protected LatRad.d = Radian(*Location\Latitude)
    *Tile\X = n * ( (*Location\Longitude + 180.0) / 360.0)
    *Tile\Y = n * ( 1.0 - Log(Tan(LatRad) + 1.0/Cos(LatRad)) / #PI ) / 2.0
    Debug "Latitude : " + StrD(*Location\Latitude) + " ; Longitude : " + StrD(*Location\Longitude)
    Debug "Tile X : " + Str(*Tile\X) + " ; Tile Y : " + Str(*Tile\Y)
  EndProcedure
  
  Procedure XY2LatLon(*Tile.Tile, *Location.Location)
    Protected n.d = Pow(2.0, OSM\Zoom)
    Protected LatitudeRad.d
    *Location\Longitude  = *Tile\X / n * 360.0 - 180.0
    LatitudeRad = ATan(SinH(#PI * (1.0 - 2.0 * *Tile\Y / n)))
    *Location\Latitude = Degree(LatitudeRad)
  EndProcedure
  
  Procedure LoadMapTile(Image.i, Zoom.i, XTile.i, YTile.i)
    Protected *Buffer
    Protected TileURL.s = OSM\ServerURL + Str(Zoom) + "/" + Str(XTile) + "/" + Str(YTile) + ".png"
    ; Test if in cache else download it
    Protected CacheFile.s = "OSM_" + Str(Zoom) + "_" + Str(XTile) + "_" + Str(YTile) + ".png"
    If FileSize(osm\cachePath + cacheFile) > 0
      Debug "Use Cache : " + cacheFile
      LoadImage(Image, OSM\CachePath + CacheFile)
    Else 
      ;Debug "DOWNLOAD : " + psURL
      CompilerIf #USEPROXY = #True
        Protected http.HTTP_Query
        HTTP_proxy(@http, "spxy.bpi.fr", 3128)
        HTTP_DownloadToMem(@http, TileURL)
        If IsImage(Image)
          FreeImage(Image)
        EndIf
        If CatchImage(Image, http\data, MemorySize(http\data))
          SaveImage(Image, OSM\CachePath + CacheFile, #PB_ImagePlugin_PNG)
        EndIf
      CompilerElse
        *Buffer = ReceiveHTTPMemory(TileURL)  ;TODO to thread by using #PB_HTTP_Asynchronous
        If IsImage(Image)
          FreeImage(Image)
        EndIf
        If *Buffer
          If CatchImage(Image, *Buffer, MemorySize(*Buffer))
            Debug "Loaded :" + TileURL
            SaveImage(image, OSM\CachePath + CacheFile, #PB_ImagePlugin_PNG)
            FreeMemory(*Buffer)
          Else
            Debug "Can't catch image :" + TileURL
          EndIf
        Else
          Debug "Problem loading :" + TileURL
        EndIf
      CompilerEndIf
      
    EndIf
    
  EndProcedure
  
  Procedure GetSquareTile()
    Protected x.i, y.i, nx.i, ny.i, n.i = 0, tx.i, ty.i
    mx = GadgetWidth(OSM\Gadget)
    my = GadgetHeight(OSM\Gadget)
    nx = mx / OSM\TileSize ;How many tiles
    ny = my / OSM\TileSize
    mx/2 : my/2 ;Gadget center
    tx = Int(OSM\TargetTile\X)  ;Don't forget the Int() !
    ty = Int(OSM\TargetTile\Y)
    LoadMapTile(1, OSM\Zoom, tx, ty)
    
  EndProcedure
  
  
  Procedure DrawMap()
    Protected x.i, y.i, nx.i, ny.i, mx.i, my.i, n.i = 0
    Protected deltaX.i, deltaY.i
    Protected x2.i, y2.i
    deltaX = OSM\Position\X - Int(OSM\TargetTile\X)*256
    deltaY = OSM\Position\Y - Int(OSM\TargetTile\Y)*256
    Debug Str(deltaX) + " " + Str(deltaY)
    
    mx = GadgetWidth(OSM\Gadget)/2
    my = GadgetHeight(OSM\Gadget)/2
    
    StartDrawing(CanvasOutput(OSM\Gadget))
    Box(0, 0, GadgetWidth(OSM\Gadget), GadgetHeight(OSM\Gadget), RGB(255, 255, 255))
    
    If IsImage(1)
      DrawImage(ImageID(1), mx-deltaX,my-deltaY, 256, 256)
    EndIf        
    
    Circle(mx, my, 5, #Red)
    StopDrawing()
  EndProcedure
  
  Procedure SetLocation(latitude.d, longitude.d, zoom = 15)
    If zoom > OSM\ZoomMax : zoom = OSM\ZoomMax : EndIf
    If zoom < OSM\ZoomMin : zoom = OSM\ZoomMin : EndIf
    OSM\Zoom = zoom
    OSM\TargetLocation\Latitude = latitude
    OSM\TargetLocation\Longitude = longitude
    LatLon2XY(@OSM\TargetLocation, @OSM\TargetTile)
    OSM\Position\X = OSM\TargetTile\X * OSM\TileSize ;Convert X, Y in tile.decimal into real pixels
    OSM\Position\Y = OSM\TargetTile\Y * OSM\TileSize 
  EndProcedure
  
  Procedure TileTranslate(*Tile.Tile, tx.d, ty.d)
    Debug " - move - "
    
    Protected pfValue.d
    If tx <> 0
      pfValue = *Tile\X - tx
      If pfValue > Pow(2, OSM\Zoom) - 1
        *Tile\X = Pow(2, OSM\Zoom) - 2
      ElseIf pfValue < 0 
        *Tile\X = Pow(2, OSM\Zoom) - 2
      Else
        *Tile\X = pfValue
        
      EndIf
    EndIf
    
    If ty <> 0
      pfValue = *Tile\Y - ty
      If pfValue > Pow(2, OSM\Zoom) - 1
        *Tile\Y = Pow(2, OSM\Zoom) - 2
      ElseIf pfValue < 0 
        *Tile\Y = Pow(2, OSM\Zoom) - 2
      Else
        *Tile\Y = pfValue
        
      EndIf
    EndIf
  EndProcedure
  
  Procedure SetZoom(Zoom.i, mode.i = #PB_Relative)
    Select mode
      Case #PB_Relative
        OSM\Zoom = OSM\Zoom + zoom
      Case #PB_Absolute
        OSM\Zoom = zoom
    EndSelect
    If OSM\Zoom > OSM\ZoomMax : OSM\Zoom = OSM\ZoomMax : EndIf
    If OSM\Zoom < OSM\ZoomMin : OSM\Zoom = OSM\ZoomMin : EndIf
    LatLon2XY(@OSM\TargetLocation, @OSM\TargetTile)
    OSM\Position\X = OSM\TargetTile\X * OSM\TileSize ;Convert X, Y in tile.decimal into real pixels
    OSM\Position\Y = OSM\TargetTile\Y * OSM\TileSize 
    GetSquareTile()
    DrawMap()
  EndProcedure
  
  Procedure Event(Event.l)
    Protected Gadget.i
    Protected tx.i, ty.i
    Protected OldX.i, OldY.i
    If IsGadget(OSM\Gadget) And GadgetType(OSM\Gadget) = #PB_GadgetType_Canvas 
      Select Event
        Case #PB_Event_Gadget ;{
          Gadget = EventGadget()
          Select Gadget
            Case OSM\Gadget
              Select EventType()
                Case #PB_EventType_LeftButtonDown
                  ;Mem cursor Coord
                  OSM\StartCursor\X = GetGadgetAttribute(OSM\Gadget, #PB_Canvas_MouseX) 
                  OSM\StartCursor\Y = GetGadgetAttribute(OSM\Gadget, #PB_Canvas_MouseY) 
                Case #PB_EventType_MouseMove 
                  If OSM\StartCursor\X <> - 1
                    tx = GetGadgetAttribute(OSM\Gadget, #PB_Canvas_MouseX) - OSM\StartCursor\X
                    ty = GetGadgetAttribute(OSM\Gadget, #PB_Canvas_MouseY) - OSM\StartCursor\Y
                    OldX = OSM\Position\X : OldY = OSM\Position\Y
                    OSM\Position\X - tx
                    OSM\Position\Y - ty
                    If (OSM\Position\X / OSM\TileSize) <> (OldX / OSM\TileSize) Or (OSM\Position\Y / OSM\TileSize) <> (OldY / OSM\TileSize) ;shift from more than 256 ?
                      Debug "Tiles loading"
                      OSM\TargetTile\X = OSM\Position\X / OSM\TileSize
                      OSM\TargetTile\Y = OSM\Position\Y / OSM\TileSize
                      Debug "OSM\Position\X " + Str(OSM\Position\X) + " ; OSM\Position\Y " + Str(OSM\Position\Y) 
                      XY2LatLon(@OSM\TargetTile, @OSM\TargetLocation)
                      Debug "OSM\TargetTile\X " + StrD(OSM\TargetTile\X) + " ; OSM\TargetTile\Y "  + StrD(OSM\TargetTile\Y) 
                      GetSquareTile()
                    EndIf
                    DrawMap()
                    OSM\StartCursor\X = GetGadgetAttribute(OSM\Gadget, #PB_Canvas_MouseX) 
                    OSM\StartCursor\Y = GetGadgetAttribute(OSM\Gadget, #PB_Canvas_MouseY)                   
                  EndIf 
                Case #PB_EventType_LeftButtonUp
                  OSM\StartCursor\X = - 1
                  OSM\TargetTile\X = OSM\Position\X / OSM\TileSize
                  OSM\TargetTile\Y = OSM\Position\Y / OSM\TileSize
                  Debug "OSM\Position\X " + Str(OSM\Position\X) + " ; OSM\Position\Y " + Str(OSM\Position\Y) 
                  XY2LatLon(@OSM\TargetTile, @OSM\TargetLocation)
                  Debug "OSM\TargetTile\X " + StrD(OSM\TargetTile\X) + " ; OSM\TargetTile\Y "  + StrD(OSM\TargetTile\Y) 
                  ;move(tx, ty)
                  ;SetGadgetText(#String_1, StrD(OSM\TargetLocation\Latitude))
                  ;SetGadgetText(#String_0, StrD(OSM\TargetLocation\Longitude))
              EndSelect
          EndSelect
      EndSelect
    Else
      MessageRequester("Module OSM", "You must use OSMGadget before", #PB_MessageRequester_Ok )
      End
    EndIf  
  EndProcedure
EndModule

Enumeration
  #Window_0
  #Map
  #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

;- Main
If OpenWindow(#Window_0, 260, 225, 700, 571, "OpenStreetMap",  #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_TitleBar | #PB_Window_ScreenCentered )
  
  OSM::InitOSM()
  LoadFont(0, "Wingdings", 12)
  LoadFont(1, "Arial", 12, #PB_Font_Bold)
  
  OSM::OSMGadget(#Map, 10, 10, 512, 512)
  
  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, 90, 20, "")
  TextGadget(#Text_4, 530, 250, 60, 15, "Longitude : ")
  StringGadget(#String_1, 600, 250, 90, 20, "")
  
  Define Event.i, Gadget.i, Quit.b = #False
  Define pfValue.d
  OSM::SetLocation(49.04599, 2.03347, 17)
  OSM::GetSquareTile()
  OSM::DrawMap()
  ;OSM::SetLocation(49.0361165, 2.0456982)
  
  Repeat
    Event = WaitWindowEvent()
    
    OSM::Event(Event)
    Select Event
      Case #PB_Event_CloseWindow : Quit = 1
      Case #PB_Event_Gadget ;{
        Gadget = EventGadget()
        Select Gadget
          Case #Button_4
            OSM::SetZoom(1)
          Case #Button_5
            OSM::SetZoom( - 1)
        EndSelect
    EndSelect
  Until Quit = #True
EndIf
 
 

Re: OpenStreetMap dans un Canvas

Publié : dim. 10/juil./2016 11:43
par Thyphoon
rhaaaaaaaaaa tu es trop fort ! je t'embrasse pas mais le coeur y est. Sans toi je pense que je n'y serais jamais arrivé.
Depuis ce matin je cherchais et j'en étais a comparer avec d'autre code trouver sur le web pour trouver ou était l'erreur.

Si on arrive au bout je te dois tout :mrgreen:

Re: OpenStreetMap dans un Canvas

Publié : dim. 10/juil./2016 12:35
par djes
Thyphoon a écrit :rhaaaaaaaaaa tu es trop fort ! je t'embrasse pas mais le coeur y est. Sans toi je pense que je n'y serais jamais arrivé.
Depuis ce matin je cherchais et j'en étais a comparer avec d'autre code trouver sur le web pour trouver ou était l'erreur.

Si on arrive au bout je te dois tout :mrgreen:
Lol ! Merci, tout le plaisir est pour moi... Je n'ai plus beaucoup de raison de programmer, alors, si ça peut aider un ami... C'est à moi que ça profite aussi. De toutes façons il y a encore du boulot, la gestion du cache mémoire/disque ne va pas être si facile !

Re: OpenStreetMap dans un Canvas

Publié : dim. 10/juil./2016 13:08
par Thyphoon
histoire d'avoir l'impression d'aider :P
J'ai mi un système en place de chargement des images dans un thread.
Pour l'instant les images se chargent en mémoire indéfiniment.Faut juste que je fasse une fonctionne qui libère les images qui ne sont pas affiché depuis un certain temp, ou qui sont trop eloigné...j'ai une idée je vais tester ça :) Puis il reste le déplacement de la carte qui n'est pas encore au point

Code : Tout sélectionner

EDIT : TOO MANY BUGS  :P 

Re: OpenStreetMap dans un Canvas

Publié : dim. 10/juil./2016 15:25
par Thyphoon
Voilà ! Dit moi si ça marche chez toi ! lorsque je zoom et je dezoom j'ai parfois une pb de chargement je cherche pourquoi.

Code : Tout sélectionner

InitNetwork()

DeclareModule OSM
  Declare InitOSM()
  Declare OSMGadget(Gadget.i, X.i, Y.i, Width.i, Height.i)
  Declare Event(Event.l)
  Declare SetLocation(latitude.d, longitude.d, zoom = 15)
  Declare GetSquareTile()
  Declare DrawMap()
  Declare SetZoom(Zoom.i, mode.i = #PB_Relative)
EndDeclareModule

Module OSM
  #USEPROXY = #False
  UsePNGImageDecoder()
  UsePNGImageEncoder()
  
  CompilerIf #USEPROXY = #True
    IncludeFile("C : \Users\lebrun_y_413\Documents\Developpement\Purebasic\includes Share\http.pbi")
  CompilerEndIf
  
  Structure Location
    Longitude.d
    Latitude.d
  EndStructure
  
  Structure Tile
    X.d
    Y.d
  EndStructure
  
  Structure Pixel
    X.i
    Y.i
  EndStructure
  
  Structure OSM
    Gadget.i
    TargetLocation.Location
    TargetTile.tile
    
    Position.Pixel
    
    ServerURL.s
    ZoomMin.i
    ZoomMax.i
    Zoom.i
    
    TileSize.i
    
    CachePath.S
    
    StartCursor.Pixel
    DeltaCursor.Pixel
    
    Shift.Pixel
  EndStructure
  
  Global OSM.OSM
  
 
  Procedure OSMGadget(Gadget.i, X.i, Y.i, Width.i, Height.i)
    If Gadget = #PB_Any
      OSM\Gadget = CanvasGadget(OSM\Gadget, X, Y, Width, Height)
    Else
      OSM\Gadget = Gadget
      CanvasGadget(OSM\Gadget, X, Y, Width, Height)
    EndIf 
  EndProcedure
  
  Procedure LatLon2XY(*Location.Location, *Tile.Tile)
    Protected n.d = Pow(2.0, OSM\Zoom)
    Protected LatRad.d = Radian(*Location\Latitude)
    *Tile\X = n * ( (*Location\Longitude + 180.0) / 360.0)
    *Tile\Y = n * ( 1.0 - Log(Tan(LatRad) + 1.0/Cos(LatRad)) / #PI ) / 2.0
    Debug "Latitude : " + StrD(*Location\Latitude) + " ; Longitude : " + StrD(*Location\Longitude)
    Debug "Tile X : " + Str(*Tile\X) + " ; Tile Y : " + Str(*Tile\Y)
  EndProcedure
  
  Procedure XY2LatLon(*Tile.Tile, *Location.Location)
    Protected n.d = Pow(2.0, OSM\Zoom)
    Protected LatitudeRad.d
    *Location\Longitude  = *Tile\X / n * 360.0 - 180.0
    LatitudeRad = ATan(SinH(#PI * (1.0 - 2.0 * *Tile\Y / n)))
    *Location\Latitude = Degree(LatitudeRad)
  EndProcedure
  
  
  
  Procedure LoadMapTile(Zoom.i, XTile.i, YTile.i)
    Protected *Buffer
    Protected nImage.i
    Protected TileURL.s = OSM\ServerURL + Str(Zoom) + "/" + Str(XTile) + "/" + Str(YTile) + ".png"
    ; Test if in cache else download it
    Protected CacheFile.s = "OSM_" + Str(Zoom) + "_" + Str(XTile) + "_" + Str(YTile) + ".png"
    If FileSize(osm\cachePath + cacheFile) > 0
      
      nImage=LoadImage(#PB_Any, OSM\CachePath + CacheFile)
      If nImage>0
         Debug "Load From HDD Tile X : " + Str(XTile) + " ; Tile Y : " + Str(YTile)
      EndIf 
    Else 
      ;Debug "DOWNLOAD : " + psURL
      CompilerIf #USEPROXY = #True
        Protected http.HTTP_Query
        HTTP_proxy(@http, "spxy.bpi.fr", 3128)
        HTTP_DownloadToMem(@http, TileURL)
        nImage=CatchImage(#PB_Any, http\data, MemorySize(http\data))
        If nImage<>0
          SaveImage(nImage, OSM\CachePath + CacheFile, #PB_ImagePlugin_PNG)
          Debug "Load From WEB Tile X : " + Str(XTile) + " ; Tile Y : " + Str(YTile)
        EndIf
      CompilerElse
        *Buffer = ReceiveHTTPMemory(TileURL)
       If *Buffer
         nImage=CatchImage(#PB_Any, *Buffer, MemorySize(*Buffer))
         If nImage<>0
            Debug "Loaded :" + TileURL
            SaveImage(nImage, OSM\CachePath + CacheFile, #PB_ImagePlugin_PNG)
            Debug "Load From WEB Tile X : " + Str(XTile) + " ; Tile Y : " + Str(YTile)
            FreeMemory(*Buffer)
          Else
            Debug "Can't catch image :" + TileURL
          EndIf
        Else
          Debug "Problem loading :" + TileURL
        EndIf
      CompilerEndIf
      
    EndIf
    ProcedureReturn nImage
  EndProcedure
  
  Structure TileImage
    nImage.i
    Zoom.i
    XTile.i
    YTile.i
  EndStructure
  
  Structure MemoryTile
    List TileImage.TileImage()
    Mutex.i
    Semaphore.i
    
    List MapImage.i()
  EndStructure
  
  Global MemoryTile.MemoryTile
  
  Procedure GetImageFromIndex(index)
    Protected nImage.i
    LockMutex(MemoryTile\Mutex)
    SelectElement(MemoryTile\TileImage(),Index)
    nImage=MemoryTile\TileImage()\nImage
    If nImage=0
        Debug "Index :"+Str(index)+" Image not ready"
    EndIf 
    UnlockMutex(MemoryTile\Mutex)
    ProcedureReturn nImage
  EndProcedure
      
  Procedure LoadTileImage(Index.i)
    Protected Zoom.i, XTile.i, YTile.i,nImage.i
    LockMutex(MemoryTile\Mutex)
    SelectElement(MemoryTile\TileImage(),Index)
    Zoom = MemoryTile\TileImage()\Zoom
    XTile= MemoryTile\TileImage()\XTile
    YTile= MemoryTile\TileImage()\YTile
    UnlockMutex(MemoryTile\Mutex)
    nImage=LoadMapTile(Zoom.i, XTile.i, YTile.i)
    LockMutex(MemoryTile\Mutex)
    SelectElement(MemoryTile\TileImage(),Index)
    MemoryTile\TileImage()\nImage=nImage  
    UnlockMutex(MemoryTile\Mutex)
  EndProcedure
  
  Procedure LoadMapTileToMemory(Zoom.i, XTile.i, YTile.i)
    Protected Index.i
    LockMutex(MemoryTile\Mutex)
    ;Check if we have this Image in Memory
    ForEach MemoryTile\TileImage()
      If Zoom=MemoryTile\TileImage()\Zoom And MemoryTile\TileImage()\XTile=XTile And MemoryTile\TileImage()\YTile=YTile
        Debug "Load From MEM Tile X : " + Str(XTile) + " ; Tile Y : " + Str(YTile)
        SignalSemaphore(MemoryTile\Semaphore)
        ProcedureReturn ListIndex(MemoryTile\TileImage())
      ElseIf Zoom<>MemoryTile\TileImage()\Zoom
        DeleteElement(MemoryTile\TileImage())
      EndIf 
    Next 
    ;If Not, We add to the list and load it
    AddElement(MemoryTile\TileImage())
      Index=ListIndex(MemoryTile\TileImage())
      MemoryTile\TileImage()\XTile=XTile
      MemoryTile\TileImage()\YTile=YTile
      MemoryTile\TileImage()\Zoom=Zoom
      UnlockMutex(MemoryTile\Mutex)
      SignalSemaphore(MemoryTile\Semaphore)
      ProcedureReturn Index
  EndProcedure
  Procedure threadLoadImage(n.l)
    Protected Index.l
    LockMutex(MemoryTile\Mutex)
    n=ListSize(MemoryTile\TileImage())
    UnlockMutex(MemoryTile\Mutex)
    For Index=0 To n-1
      Debug "LOAD THREAD :"+Str(Index)
      WaitSemaphore(MemoryTile\Semaphore)
      CreateThread(@LoadTileImage(),Index)
    Next
  EndProcedure
Procedure GetSquareTile()
    Protected x.i, y.i, nx.i, ny.i, n.i = 0, tx.i, ty.i
    mx = GadgetWidth(OSM\Gadget)
    my = GadgetHeight(OSM\Gadget)
    nx = mx/256 ;How many tiles
    ny = my/256
    mx/2 : my/2 ;Gadget center
    tx = Int(OSM\TargetTile\X)
    ty = Int(OSM\TargetTile\Y)
    ClearList(MemoryTile\MapImage())
    For y = ty - ny To ty + ny + ny - 1
      For x = tx - nx To tx + nx + nx - 1
        AddElement(MemoryTile\MapImage())
        MemoryTile\MapImage()=LoadMapTileToMemory(OSM\Zoom, x, y)
        n = n + 1
      Next
    Next
    CreateThread(@threadLoadImage(),0)
    Debug Str(n) + " Images Chargées";
  EndProcedure
  
  
Procedure DrawMap()
    Protected x.i, y.i, nx.i, ny.i, mx.i, my.i, n.i = 0
    Protected deltaX.i, deltaY.i

    Protected nImage.i
    Protected x2.i, y2.i
    deltaX = 256*(OSM\TargetTile\X - Int(OSM\TargetTile\X))
    deltaY = 256*(OSM\TargetTile\Y - Int(OSM\TargetTile\Y))

    mx = GadgetWidth(OSM\Gadget)/2
    my = GadgetHeight(OSM\Gadget)/2
    
    nx = GadgetWidth(OSM\Gadget)/256 ;How many tiles
    ny = GadgetWidth(OSM\Gadget)/256
   
    
    StartDrawing(CanvasOutput(OSM\Gadget))
    Box(0, 0, GadgetWidth(OSM\Gadget), GadgetHeight(OSM\Gadget), RGB(255, 255, 255))
    ResetList(MemoryTile\MapImage())
    For y = - ny To ny + ny - 1
      For x = - nx To nx + nx - 1
        If NextElement(MemoryTile\MapImage())
        
        x2 = x*256 + OSM\DeltaCursor\X   + mx -deltaX
        y2 = y*256 + OSM\DeltaCursor\Y   + my - deltaY
        nImage=GetImageFromIndex(MemoryTile\MapImage())
        If IsImage(nImage) And (x2 + 256) > 0 And (y2 + 256) > 0 And x2 < GadgetWidth(OSM\Gadget) And y2 < GadgetHeight(OSM\Gadget)
          DrawImage(ImageID(nImage), x2,y2, 254, 254)
          DrawText( x2, y2, Str(x) + ", " + Str(y))
        EndIf        
        n = n + 1
      Else
        Break 2
       EndIf 
      Next
    Next
    
    Circle(GadgetWidth(OSM\Gadget)/2, GadgetHeight(OSM\Gadget)/2, 5, #Red)
    ;DrawText(0, 0, "DeltaCursorX : " + Str(OSM\DeltaCursor\X) + " deltaX : " + Str(deltaX) + " Tile X : " + StrD(OSM\TargetTile\X))
    DrawText(0, 16, Str(OSM\TargetTile\X + OSM\DeltaCursor\X) + " " + Str(OSM\TargetTile\Y + OSM\DeltaCursor\Y))
    StopDrawing()
  EndProcedure
  
  Procedure SetLocation(latitude.d, longitude.d, zoom = 15)
    If zoom > OSM\ZoomMax : zoom = OSM\ZoomMax : EndIf
    If zoom < OSM\ZoomMin : zoom = OSM\ZoomMin : EndIf
    OSM\Zoom = zoom
    OSM\TargetLocation\Latitude = latitude
    OSM\TargetLocation\Longitude = longitude
    LatLon2XY(@OSM\TargetLocation, @OSM\TargetTile)
    OSM\Position\X = OSM\TargetTile\X * OSM\TileSize ;Convert X, Y in tile.decimal into real pixels
    OSM\Position\Y = OSM\TargetTile\Y * OSM\TileSize 
  EndProcedure
  
  Procedure TileTranslate(*Tile.Tile, tx.d, ty.d)
    Debug " - move - "
    
    Protected pfValue.d
    If tx <> 0
      pfValue = *Tile\X - tx
      If pfValue > Pow(2, OSM\Zoom) - 1
        *Tile\X = Pow(2, OSM\Zoom) - 2
      ElseIf pfValue < 0 
        *Tile\X = Pow(2, OSM\Zoom) - 2
      Else
        *Tile\X = pfValue
        
      EndIf
    EndIf
    
    If ty <> 0
      pfValue = *Tile\Y - ty
      If pfValue > Pow(2, OSM\Zoom) - 1
        *Tile\Y = Pow(2, OSM\Zoom) - 2
      ElseIf pfValue < 0 
        *Tile\Y = Pow(2, OSM\Zoom) - 2
      Else
        *Tile\Y = pfValue
        
      EndIf
    EndIf
  EndProcedure
  
  Procedure SetZoom(Zoom.i, mode.i = #PB_Relative)
    Select mode
      Case #PB_Relative
        OSM\Zoom = OSM\Zoom + zoom
      Case #PB_Absolute
        OSM\Zoom = zoom
    EndSelect
    If OSM\Zoom > OSM\ZoomMax : OSM\Zoom = OSM\ZoomMax : EndIf
    If OSM\Zoom < OSM\ZoomMin : OSM\Zoom = OSM\ZoomMin : EndIf
    LatLon2XY(@OSM\TargetLocation, @OSM\TargetTile)
    ;OSM\Position\X = OSM\TargetTile\X * OSM\TileSize ;Convert X, Y in tile.decimal into real pixels
    ;OSM\Position\Y = OSM\TargetTile\Y * OSM\TileSize 
    GetSquareTile()
    DrawMap()
  EndProcedure
  
  Procedure InitOSM()
    Debug GetTemporaryDirectory()
    OSM\CachePath = GetTemporaryDirectory()
    OSM\ServerURL = "http://tile.openstreetmap.org/"
    OSM\ZoomMin = 0
    OSM\ZoomMax = 18
    OSM\StartCursor\X = - 1
    OSM\TileSize = 256
    MemoryTile\Mutex=CreateMutex()
    MemoryTile\Semaphore=CreateSemaphore(1)
  EndProcedure
  
  Procedure Event(Event.l)
    Protected Gadget.i
    Protected tx.d, ty.d
    Protected OldX.i, OldY.i
    If IsGadget(OSM\Gadget) And GadgetType(OSM\Gadget) = #PB_GadgetType_Canvas 
      Select Event
        Case #PB_Event_Gadget ;{
          Gadget = EventGadget()
          Select Gadget
            Case OSM\Gadget
              Select EventType()
                Case #PB_EventType_LeftButtonDown
                  ;Mem cursor Coord
                  OSM\StartCursor\X = GetGadgetAttribute(OSM\Gadget, #PB_Canvas_MouseX) 
                  OSM\StartCursor\Y = GetGadgetAttribute(OSM\Gadget, #PB_Canvas_MouseY) 
                Case #PB_EventType_MouseMove 
                  If OSM\StartCursor\X<>-1
                    OSM\DeltaCursor\X=GetGadgetAttribute(OSM\Gadget, #PB_Canvas_MouseX)-OSM\StartCursor\X
                    OSM\DeltaCursor\Y=GetGadgetAttribute(OSM\Gadget, #PB_Canvas_MouseY)-OSM\StartCursor\Y
                  EndIf 
                Case #PB_EventType_LeftButtonUp
                  tx=(OSM\DeltaCursor\X/256)
                  ty=(OSM\DeltaCursor\Y/256)
                  OSM\DeltaCursor\X=0
                  OSM\DeltaCursor\Y=0
                  OSM\StartCursor\X=-1
                  TileTranslate(@OSM\TargetTile,tx,ty)
                  XY2LatLon(@OSM\TargetTile,@OSM\TargetLocation)
                  GetSquareTile()
              EndSelect
          EndSelect
          DrawMap()
      EndSelect
    Else
      MessageRequester("Module OSM", "You must use OSMGadget before", #PB_MessageRequester_Ok )
      End
    EndIf  
  EndProcedure
EndModule

Enumeration
  #Window_0
  #Map
  #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

;- Main
If OpenWindow(#Window_0, 260, 225, 700, 571, "OpenStreetMap",  #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_TitleBar | #PB_Window_ScreenCentered )
  
  OSM::InitOSM()
  LoadFont(0, "Wingdings", 12)
  LoadFont(1, "Arial", 12, #PB_Font_Bold)
  
  OSM::OSMGadget(#Map, 10, 10, 512, 512)
  
  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, 90, 20, "")
  TextGadget(#Text_4, 530, 250, 60, 15, "Longitude : ")
  StringGadget(#String_1, 600, 250, 90, 20, "")
  
  Define Event.i, Gadget.i, Quit.b = #False
  Define pfValue.d
  OSM::SetLocation(49.04599, 2.03347, 17)
  OSM::GetSquareTile()
  OSM::DrawMap()
  ;OSM::SetLocation(49.0361165, 2.0456982)
  
  Repeat
    Event = WaitWindowEvent()
    
    OSM::Event(Event)
    Select Event
      Case #PB_Event_CloseWindow : Quit = 1
      Case #PB_Event_Gadget ;{
        Gadget = EventGadget()
        Select Gadget
          Case #Button_4
            OSM::SetZoom(1)
          Case #Button_5
            OSM::SetZoom( - 1)
        EndSelect
    EndSelect
  Until Quit = #True
EndIf
  
  

Re: OpenStreetMap dans un Canvas

Publié : lun. 11/juil./2016 12:39
par djes
Pour l'instant, le zoom ne me donne pas de bons résultats. En plus le code pour le proxy ne fonctionne pas... A ce sujet j'ai complété le code d'infratec avec curl : http://www.purebasic.fr/english/viewtop ... 51#p491051

Re: OpenStreetMap dans un Canvas

Publié : lun. 11/juil./2016 12:58
par Thyphoon
djes a écrit :Pour l'instant, le zoom ne me donne pas de bons résultats. En plus le code pour le proxy ne fonctionne pas... A ce sujet j'ai complété le code d'infratec avec curl : http://www.purebasic.fr/english/viewtop ... 51#p491051
je sais pas pourquoi le zoom se comporte comme ça (Oui je sais il y a beaucoup de chose que je sais pas au final :mrgreen: ). Une bonne idée le code d'infratec j'étais passé a côté. de mon côté j'essaye d'avancer mais rien de probant pour l'instant. mais je continue :P

Re: OpenStreetMap dans un Canvas

Publié : lun. 11/juil./2016 17:52
par Thyphoon
Bon Le chargement des images via un Thread fonctionne enfin correctement ... :mrgreen:
VOilà le code brut .. je vais faire un peu de nettoyage et mettre au propre déjà tout ça...

Code : Tout sélectionner

InitNetwork()

DeclareModule OSM
  Declare InitOSM()
  Declare OSMGadget(Gadget.i, X.i, Y.i, Width.i, Height.i)
  Declare Event(Event.l)
  Declare SetLocation(latitude.d, longitude.d, zoom = 15)
  Declare SetZoom(Zoom.i, mode.i = #PB_Relative)
  Declare GetMapTiles()
  Declare DrawMap()
EndDeclareModule

Module OSM
  #USEPROXY = #False
  UsePNGImageDecoder()
  UsePNGImageEncoder()
  
  CompilerIf #USEPROXY = #True
    IncludeFile("C : \Users\lebrun_y_413\Documents\Developpement\Purebasic\includes Share\http.pbi")
  CompilerEndIf
  
  Structure Location
    Longitude.d
    Latitude.d
  EndStructure
  
  Structure Tile
    X.d
    Y.d
  EndStructure
  
  Structure Pixel
    X.i
    Y.i
  EndStructure
  
  Structure OSM
    Gadget.i
    TargetLocation.Location
    TargetTile.tile
    
    Position.Pixel
    
    ServerURL.s
    ZoomMin.i
    ZoomMax.i
    Zoom.i
    
    TileSize.i
    
    CachePath.S
    
    StartCursor.Pixel
    DeltaCursor.Pixel
    
    Shift.Pixel
  EndStructure
  
  Global OSM.OSM
  
  
  Procedure OSMGadget(Gadget.i, X.i, Y.i, Width.i, Height.i)
    If Gadget = #PB_Any
      OSM\Gadget = CanvasGadget(OSM\Gadget, X, Y, Width, Height)
    Else
      OSM\Gadget = Gadget
      CanvasGadget(OSM\Gadget, X, Y, Width, Height)
    EndIf 
  EndProcedure
  
  Procedure LatLon2XY(*Location.Location, *Tile.Tile)
    Protected n.d = Pow(2.0, OSM\Zoom)
    Protected LatRad.d = Radian(*Location\Latitude)
    *Tile\X = n * ( (*Location\Longitude + 180.0) / 360.0)
    *Tile\Y = n * ( 1.0 - Log(Tan(LatRad) + 1.0/Cos(LatRad)) / #PI ) / 2.0
    Debug "Latitude : " + StrD(*Location\Latitude) + " ; Longitude : " + StrD(*Location\Longitude)
    Debug "Tile X : " + Str(*Tile\X) + " ; Tile Y : " + Str(*Tile\Y)
  EndProcedure
  
  Procedure XY2LatLon(*Tile.Tile, *Location.Location)
    Protected n.d = Pow(2.0, OSM\Zoom)
    Protected LatitudeRad.d
    *Location\Longitude  = *Tile\X / n * 360.0 - 180.0
    LatitudeRad = ATan(SinH(#PI * (1.0 - 2.0 * *Tile\Y / n)))
    *Location\Latitude = Degree(LatitudeRad)
  EndProcedure
  
  Structure trace
    Location.Location
  EndStructure
  
  Global NewList trace.trace()
  #XML=0
  
    Procedure LoadGpxFile(file.s)
    If LoadXML(#XML, file.s)
      Protected Message.s
      If XMLStatus(#XML) <> #PB_XML_Success
        Message = "Error in the XML file:" + Chr(13)
        Message + "Message: " + XMLError(#XML) + Chr(13)
        Message + "Line: " + Str(XMLErrorLine(#XML)) + "   Character: " + Str(XMLErrorPosition(#XML))
        MessageRequester("Error", Message)
      EndIf
      Protected *MainNode,*subNode,*child,child.l
      *MainNode=MainXMLNode(#XML)
      *MainNode=XMLNodeFromPath(*MainNode,"/gpx/trk/trkseg")
      Debug *MainNode
      For child = 1 To XMLChildCount(*MainNode)
        *child = ChildXMLNode(*MainNode, child)
        AddElement(trace())
        If ExamineXMLAttributes(*child)
          While NextXMLAttribute(*child)
            Select XMLAttributeName(*child)
              Case "lat"
                trace()\Location\Latitude=ValD(XMLAttributeValue(*child))
              Case "lon"
                trace()\Location\Longitude=ValD(XMLAttributeValue(*child))
            EndSelect
          Wend
        EndIf
      Next 
    EndIf
  EndProcedure
  
  
  Procedure LoadMapTile(Zoom.i, XTile.i, YTile.i)
    Debug "LoadMapTile"
    Protected *Buffer
    Protected nImage.i
    Protected TileURL.s = OSM\ServerURL + Str(Zoom) + "/" + Str(XTile) + "/" + Str(YTile) + ".png"
    ; Test if in cache else download it
    Protected CacheFile.s = "OSM_" + Str(Zoom) + "_" + Str(XTile) + "_" + Str(YTile) + ".png"
    If FileSize(osm\cachePath + cacheFile) > 0
      
      nImage=LoadImage(#PB_Any, OSM\CachePath + CacheFile)
      If nImage>0
        Debug "Load From HDD Tile X : " + Str(XTile) + " ; Tile Y : " + Str(YTile)
      EndIf 
    Else 
      ;Debug "DOWNLOAD : " + psURL
      CompilerIf #USEPROXY = #True
        Protected http.HTTP_Query
        HTTP_proxy(@http, "spxy.bpi.fr", 3128)
        HTTP_DownloadToMem(@http, TileURL)
        nImage=CatchImage(#PB_Any, http\data, MemorySize(http\data))
        If nImage<>0
          SaveImage(nImage, OSM\CachePath + CacheFile, #PB_ImagePlugin_PNG)
          Debug "Load From WEB Tile X : " + Str(XTile) + " ; Tile Y : " + Str(YTile)
        EndIf
      CompilerElse
        *Buffer = ReceiveHTTPMemory(TileURL)
        If *Buffer
          nImage=CatchImage(#PB_Any, *Buffer, MemorySize(*Buffer))
          If nImage<>0
            Debug "Loaded :" + TileURL
            SaveImage(nImage, OSM\CachePath + CacheFile, #PB_ImagePlugin_PNG)
            Debug "Load From WEB Tile X : " + Str(XTile) + " ; Tile Y : " + Str(YTile)
            FreeMemory(*Buffer)
          Else
            Debug "Can't catch image :" + TileURL
          EndIf
        Else
          Debug "Problem loading :" + TileURL
        EndIf
      CompilerEndIf
      
    EndIf
    ProcedureReturn nImage
  EndProcedure
  
  Structure TileImage
    nImage.i
    Zoom.i
    XTile.i
    YTile.i
    Thread.i
    Load.b
  EndStructure
  
  Structure MemoryTile
    List TileImage.TileImage()
    Mutex.i
    Semaphore.i
    
    List MapImage.i()
  EndStructure
  
  Global MemoryTile.MemoryTile
  

  
  Procedure LoadTileImage(Index.i)
    Protected Zoom.i, XTile.i, YTile.i,nImage.i
    LockMutex(MemoryTile\Mutex)
    SelectElement(MemoryTile\TileImage(),Index)
    Zoom = MemoryTile\TileImage()\Zoom
    XTile= MemoryTile\TileImage()\XTile
    YTile= MemoryTile\TileImage()\YTile
    UnlockMutex(MemoryTile\Mutex)
    nImage=LoadMapTile(Zoom.i, XTile.i, YTile.i)
    LockMutex(MemoryTile\Mutex)
    SelectElement(MemoryTile\TileImage(),Index)
    MemoryTile\TileImage()\nImage=nImage 
    If IsImage(nImage)
      MemoryTile\TileImage()\Load=#True
    Else
      MemoryTile\TileImage()\Load=#False
      Debug "ERROR TO LOAD"
    EndIf 
    UnlockMutex(MemoryTile\Mutex)
    SignalSemaphore(MemoryTile\Semaphore)
  EndProcedure
  
  Procedure isTileExist(Zoom.i, XTile.i, YTile.i)
    LockMutex(MemoryTile\Mutex)
    ;Check if we have this Image in Memory
    ForEach MemoryTile\TileImage()
      If Zoom=MemoryTile\TileImage()\Zoom And MemoryTile\TileImage()\XTile=XTile And MemoryTile\TileImage()\YTile=YTile
        Debug "Load From MEM Tile X : " + Str(XTile) + " ; Tile Y : " + Str(YTile)
        UnlockMutex(MemoryTile\Mutex)
        ProcedureReturn ListIndex(MemoryTile\TileImage())
      ElseIf Zoom<>MemoryTile\TileImage()\Zoom
        DeleteElement(MemoryTile\TileImage())
      EndIf 
    Next 
    UnlockMutex(MemoryTile\Mutex)
    ProcedureReturn -1
  EndProcedure
  
  Procedure AddTileToLoadList(Zoom.i, XTile.i, YTile.i)
    Protected Index.i
    LockMutex(MemoryTile\Mutex)
    ;We add To the List And load it
    FirstElement(MemoryTile\TileImage())
    AddElement(MemoryTile\TileImage())
    Index=ListIndex(MemoryTile\TileImage())
    MemoryTile\TileImage()\XTile=XTile
    MemoryTile\TileImage()\YTile=YTile
    MemoryTile\TileImage()\Zoom=Zoom
    UnlockMutex(MemoryTile\Mutex)
    ProcedureReturn Index
  EndProcedure
  
  Procedure threadLoadImage(n.l)
    Protected Index.l
    LockMutex(MemoryTile\Mutex)
    n=ListSize(MemoryTile\TileImage())
    UnlockMutex(MemoryTile\Mutex)
    For Index=0 To n-1
      Debug "LOAD THREAD :"+Str(Index)
      WaitSemaphore(MemoryTile\Semaphore)
      LockMutex(MemoryTile\Mutex)
      SelectElement(MemoryTile\TileImage(),Index)
      MemoryTile\TileImage()\Thread=CreateThread(@LoadTileImage(),Index)
      If MemoryTile\TileImage()\Thread=0
        Debug "Error to Init Thread "+Str(Index)
      EndIf
      UnlockMutex(MemoryTile\Mutex)
    Next
  EndProcedure
  
  Procedure GetMapTiles()
    Protected x.i, y.i, nx.i, ny.i, n.i = 0, tx.i, ty.i
    mx = GadgetWidth(OSM\Gadget)
    my = GadgetHeight(OSM\Gadget)
    nx = mx/256 ;How many tiles
    ny = my/256
    mx/2 : my/2 ;Gadget center
    tx = Int(OSM\TargetTile\X)
    ty = Int(OSM\TargetTile\Y)
    ClearList(MemoryTile\MapImage())
    For y = ty - ny To ty + ny + ny - 1
      For x = tx - nx To tx + nx + nx - 1
        AddElement(MemoryTile\MapImage())
        MemoryTile\MapImage()=isTileExist(OSM\Zoom, x, y);check if Tile is in memory
        If MemoryTile\MapImage()=-1
          MemoryTile\MapImage()=AddTileToLoadList(OSM\Zoom, x, y)
        EndIf
        n = n + 1
      Next
    Next
    
    CreateThread(@threadLoadImage(),0)
    Debug Str(n) + " Images Chargées";
  EndProcedure
  
    Procedure GetImageFromIndex(index)
    Protected nImage.i
    LockMutex(MemoryTile\Mutex)
    SelectElement(MemoryTile\TileImage(),Index)
    nImage=MemoryTile\TileImage()\nImage
    If nImage=0
      Debug "Index :"+Str(index)+"Not L"+Str(MemoryTile\TileImage()\Load)+"X"+Str(MemoryTile\TileImage()\XTile)+" Y"+Str(MemoryTile\TileImage()\YTile)+" Z"+Str(MemoryTile\TileImage()\Zoom)+" T"+Str(IsThread(MemoryTile\TileImage()\Thread))
    EndIf 
    UnlockMutex(MemoryTile\Mutex)
    ProcedureReturn nImage
  EndProcedure
  
  Procedure DrawMap()
    Protected x.i, y.i, nx.i, ny.i, mx.i, my.i, n.i = 0
    Protected deltaX.i, deltaY.i
    
    Protected nImage.i
    Protected x2.i, y2.i
    deltaX = 256*(OSM\TargetTile\X - Int(OSM\TargetTile\X))
    deltaY = 256*(OSM\TargetTile\Y - Int(OSM\TargetTile\Y))
    
    mx = GadgetWidth(OSM\Gadget)/2
    my = GadgetHeight(OSM\Gadget)/2
    
    nx = GadgetWidth(OSM\Gadget)/256 ;How many tiles
    ny = GadgetWidth(OSM\Gadget)/256
    
    
    StartDrawing(CanvasOutput(OSM\Gadget))
    Box(0, 0, GadgetWidth(OSM\Gadget), GadgetHeight(OSM\Gadget), RGB(255, 255, 255))
    ResetList(MemoryTile\MapImage())
    For y = - ny To ny + ny - 1
      For x = - nx To nx + nx - 1
        If NextElement(MemoryTile\MapImage())
          
          x2 = x*256 + OSM\DeltaCursor\X   + mx -deltaX
          y2 = y*256 + OSM\DeltaCursor\Y   + my - deltaY
          nImage=GetImageFromIndex(MemoryTile\MapImage())
          If IsImage(nImage) And (x2 + 256) > 0 And (y2 + 256) > 0 And x2 < GadgetWidth(OSM\Gadget) And y2 < GadgetHeight(OSM\Gadget)
            DrawImage(ImageID(nImage), x2,y2, 254, 254)
            DrawText( x2, y2, Str(x) + ", " + Str(y))
          EndIf        
          n = n + 1
        Else
          Break 2
        EndIf 
      Next
    Next
    
    Circle(GadgetWidth(OSM\Gadget)/2, GadgetHeight(OSM\Gadget)/2, 5, #Red)
    ;DrawText(0, 0, "DeltaCursorX : " + Str(OSM\DeltaCursor\X) + " deltaX : " + Str(deltaX) + " Tile X : " + StrD(OSM\TargetTile\X))
    DrawText(0, 16, Str(OSM\TargetTile\X + OSM\DeltaCursor\X) + " " + Str(OSM\TargetTile\Y + OSM\DeltaCursor\Y))
    StopDrawing()
  EndProcedure
  
  Procedure SetLocation(latitude.d, longitude.d, zoom = 15)
    If zoom > OSM\ZoomMax : zoom = OSM\ZoomMax : EndIf
    If zoom < OSM\ZoomMin : zoom = OSM\ZoomMin : EndIf
    OSM\Zoom = zoom
    OSM\TargetLocation\Latitude = latitude
    OSM\TargetLocation\Longitude = longitude
    LatLon2XY(@OSM\TargetLocation, @OSM\TargetTile)
    OSM\Position\X = OSM\TargetTile\X * OSM\TileSize ;Convert X, Y in tile.decimal into real pixels
    OSM\Position\Y = OSM\TargetTile\Y * OSM\TileSize 
  EndProcedure
  
  Procedure TileTranslate(*Tile.Tile, tx.d, ty.d)
    Debug " - move - "
    
    Protected pfValue.d
    If tx <> 0
      pfValue = *Tile\X - tx
      If pfValue > Pow(2, OSM\Zoom) - 1
        *Tile\X = Pow(2, OSM\Zoom) - 2
      ElseIf pfValue < 0 
        *Tile\X = Pow(2, OSM\Zoom) - 2
      Else
        *Tile\X = pfValue
        
      EndIf
    EndIf
    
    If ty <> 0
      pfValue = *Tile\Y - ty
      If pfValue > Pow(2, OSM\Zoom) - 1
        *Tile\Y = Pow(2, OSM\Zoom) - 2
      ElseIf pfValue < 0 
        *Tile\Y = Pow(2, OSM\Zoom) - 2
      Else
        *Tile\Y = pfValue
        
      EndIf
    EndIf
  EndProcedure
  
  Procedure SetZoom(Zoom.i, mode.i = #PB_Relative)
    Select mode
      Case #PB_Relative
        OSM\Zoom = OSM\Zoom + zoom
      Case #PB_Absolute
        OSM\Zoom = zoom
    EndSelect
    If OSM\Zoom > OSM\ZoomMax : OSM\Zoom = OSM\ZoomMax : EndIf
    If OSM\Zoom < OSM\ZoomMin : OSM\Zoom = OSM\ZoomMin : EndIf
    LatLon2XY(@OSM\TargetLocation, @OSM\TargetTile)
    ;OSM\Position\X = OSM\TargetTile\X * OSM\TileSize ;Convert X, Y in tile.decimal into real pixels
    ;OSM\Position\Y = OSM\TargetTile\Y * OSM\TileSize 
    GetMapTiles()
    DrawMap()
  EndProcedure
  
  Procedure InitOSM()
    Debug GetTemporaryDirectory()
    OSM\CachePath = GetTemporaryDirectory()
    OSM\ServerURL = "http://tile.openstreetmap.org/"
    OSM\ZoomMin = 0
    OSM\ZoomMax = 18
    OSM\StartCursor\X = - 1
    OSM\TileSize = 256
    MemoryTile\Mutex=CreateMutex()
    MemoryTile\Semaphore=CreateSemaphore(1)
  EndProcedure
  
  Procedure Event(Event.l)
    Protected Gadget.i
    Protected tx.d, ty.d
    Protected OldX.i, OldY.i
    If IsGadget(OSM\Gadget) And GadgetType(OSM\Gadget) = #PB_GadgetType_Canvas 
      Select Event
        Case #PB_Event_Gadget ;{
          Gadget = EventGadget()
          Select Gadget
            Case OSM\Gadget
              Select EventType()
                Case #PB_EventType_LeftButtonDown
                  ;Mem cursor Coord
                  OSM\StartCursor\X = GetGadgetAttribute(OSM\Gadget, #PB_Canvas_MouseX) 
                  OSM\StartCursor\Y = GetGadgetAttribute(OSM\Gadget, #PB_Canvas_MouseY) 
                Case #PB_EventType_MouseMove 
                  If OSM\StartCursor\X<>-1
                    OSM\DeltaCursor\X=GetGadgetAttribute(OSM\Gadget, #PB_Canvas_MouseX)-OSM\StartCursor\X
                    OSM\DeltaCursor\Y=GetGadgetAttribute(OSM\Gadget, #PB_Canvas_MouseY)-OSM\StartCursor\Y
                  EndIf 
                Case #PB_EventType_LeftButtonUp
                  tx=(OSM\DeltaCursor\X/256)
                  ty=(OSM\DeltaCursor\Y/256)
                  OSM\DeltaCursor\X=0
                  OSM\DeltaCursor\Y=0
                  OSM\StartCursor\X=-1
                  TileTranslate(@OSM\TargetTile,tx,ty)
                  XY2LatLon(@OSM\TargetTile,@OSM\TargetLocation)
                  GetMapTiles()
              EndSelect
          EndSelect
          DrawMap()
      EndSelect
    Else
      MessageRequester("Module OSM", "You must use OSMGadget before", #PB_MessageRequester_Ok )
      End
    EndIf  
  EndProcedure
EndModule

Enumeration
  #Window_0
  #Map
  #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

;- Main
If OpenWindow(#Window_0, 260, 225, 700, 571, "OpenStreetMap",  #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_TitleBar | #PB_Window_ScreenCentered )
  
  OSM::InitOSM()
  LoadFont(0, "Wingdings", 12)
  LoadFont(1, "Arial", 12, #PB_Font_Bold)
  
  OSM::OSMGadget(#Map, 10, 10, 512, 512)
  
  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, 90, 20, "")
  TextGadget(#Text_4, 530, 250, 60, 15, "Longitude : ")
  StringGadget(#String_1, 600, 250, 90, 20, "")
  
  Define Event.i, Gadget.i, Quit.b = #False
  Define pfValue.d
  OSM::SetLocation(49.04599, 2.03347, 17)
  OSM::GetMapTiles()
  OSM::DrawMap()
  ;OSM::SetLocation(49.0361165, 2.0456982)
  
  Repeat
    Event = WaitWindowEvent()
    
    OSM::Event(Event)
    Select Event
      Case #PB_Event_CloseWindow : Quit = 1
      Case #PB_Event_Gadget ;{
        Gadget = EventGadget()
        Select Gadget
          Case #Button_4
            OSM::SetZoom(1)
          Case #Button_5
            OSM::SetZoom( - 1)
        EndSelect
    EndSelect
  Until Quit = #True
EndIf



Re: OpenStreetMap dans un Canvas

Publié : mar. 12/juil./2016 10:10
par djes
Le chargement ne fonctionne pas trop mal, c'est sympa, ça fluidifie bien :)
Par contre j'ai toujours des problèmes de calcul avec le zoom et le proxy. Je te laisse mettre au propre la partie chargement et je ferai un mix après si tu veux.