PBMap - Cartes OSM, Here, Geoserver dans un Canvas

Programmation d'applications complexes
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: OpenStreetMap dans un Canvas

Message par djes »

Il va falloir revoir le mode de chargement pour qu'il se fasse dès un déplacement. C'est plus compliqué que prévu :)
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Re: OpenStreetMap dans un Canvas

Message par Thyphoon »

djes a écrit :Il va falloir revoir le mode de chargement pour qu'il se fasse dès un déplacement. C'est plus compliqué que prévu :)
J'avais prévu de charger les Tiles avec un Thread je commence a bien maîtriser les Mutexs et les sémaphores :P mais je voulais déjà avoir un affichage correcte.
j'ai fais des testes ce matin encore mais j'arrive toujours sur la même problématique.
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: OpenStreetMap dans un Canvas

Message par djes »

Le problème vient du calcul de déplacement inverse, c'est à dire retrouver les coordonnées de la tuile "actuelle", et lui rajouter le décalage précédent (ce qui n'est pas fait), plus le déplacement en cours. Bref, il faudrait vraiment que ce soit dynamique pour être toujours centré sur la bonne tuile.
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Re: OpenStreetMap dans un Canvas

Message par Thyphoon »

djes a écrit :Le problème vient du calcul de déplacement inverse, c'est à dire retrouver les coordonnées de la tuile "actuelle", et lui rajouter le décalage précédent (ce qui n'est pas fait), plus le déplacement en cours. Bref, il faudrait vraiment que ce soit dynamique pour être toujours centré sur la bonne tuile.
pourtant dans mon code je lorsqu'on bouge la map effectivement tant que tu es appuyer ça ne fait qu'un déclage en pixel de l'image... mais des que tu relaches le bouton de la souris je recalcule les coordonées du Tile

Code : Tout sélectionner

tx=(OSM\DeltaCursor\X/512)
ty=(OSM\DeltaCursor\Y/512)
 TileTranslate(@OSM\TargetTile,tx.d,ty.d)
[/code]
puis je converti tout de suite en Latitude Longitude

Code : Tout sélectionner

 XY2LatLon(@OSM\TargetTile,@OSM\TargetLocation)
Le code d'origine pour bouger la carte

Code : Tout sélectionner

Case OSM\Gadget
              Select EventType()
                Case #PB_EventType_LeftButtonDown ; Un clic gauche je mémorise la position
                  ;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 ; la souris se déplace je calcule le décalage par rapport a la position d'origine.
                  If OSM\StartCursor\X<>0 Or OSM\StartCursor\Y<>0
                    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 ; je relache je calcul les nouvelles coordonées
                  Define tx.d,ty.d
                  tx=(OSM\DeltaCursor\X/512)
                  ty=(OSM\DeltaCursor\Y/512)
                  OSM\DeltaCursor\X=0
                  OSM\DeltaCursor\Y=0
                  OSM\StartCursor\X=0
                  OSM\StartCursor\Y=0
                  TileTranslate(@OSM\TargetTile,tx.d,ty.d)
                  XY2LatLon(@OSM\TargetTile,@OSM\TargetLocation)
                  GetSquareTile()
                  ;move(tx,ty)
                  ;SetGadgetText(#String_1, StrD(osm\gfLongitude))
                  ;SetGadgetText(#String_0, StrD(osm\gfLatitude))
              EndSelect
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: OpenStreetMap dans un Canvas

Message par djes »

Oui, je suis dessus. D'abord, quand le déplacement est très grand, il n'y a plus de nouvelles tuiles sur les bords. Ensuite, le calcul se base sur la tuile de départ, jusqu'au relâchement. Or, la nouvelle tuile peut être très loin de la première, du coup le calcul n'est pas bon. Enfin, on arrive à une position qui n'est pas "juste", donc il faut une nouvelle position de départ "décalée".
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Re: OpenStreetMap dans un Canvas

Message par Thyphoon »

djes a écrit :Oui, je suis dessus. D'abord, quand le déplacement est très grand, il n'y a plus de nouvelles tuiles sur les bords. Ensuite, le calcul se base sur la tuile de départ, jusqu'au relâchement. Or, la nouvelle tuile peut être très loin de la première, du coup le calcul n'est pas bon. Enfin, on arrive à une position qui n'est pas "juste", donc il faut une nouvelle position de départ "décalée".
heu .... :oops: tu me dis si je me trompe
Un tile déplacé a l'écran de 256 pixels correspond bien a 0.5 dans les coordonnées du Tile sur la Map .. donc si on deplace de 512 pixel ça devrait décalé de 1 tile complet. c'est bine ça.. ou bien il faut prendre en référence le quadrant ? j'avoue m'y perdre :roll: ... lollll en tout cas merci de te pencher dessus :D
je vais essayer de vérifier ça
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: OpenStreetMap dans un Canvas

Message par djes »

Thyphoon a écrit :
djes a écrit :Oui, je suis dessus. D'abord, quand le déplacement est très grand, il n'y a plus de nouvelles tuiles sur les bords. Ensuite, le calcul se base sur la tuile de départ, jusqu'au relâchement. Or, la nouvelle tuile peut être très loin de la première, du coup le calcul n'est pas bon. Enfin, on arrive à une position qui n'est pas "juste", donc il faut une nouvelle position de départ "décalée".
heu .... :oops: tu me dis si je me trompe
Un tile déplacé a l'écran de 256 pixels correspond bien a 0.5 dans les coordonnées du Tile sur la Map .. donc si on deplace de 512 pixel ça devrait décalé de 1 tile complet. c'est bine ça.. ou bien il faut prendre en référence le quadrant ? j'avoue m'y perdre :roll: ... lollll en tout cas merci de te pencher dessus :D
je vais essayer de vérifier ça
Moi aussi je m'y perds :)
Voilà où j'en suis ;)

Code : Tout sélectionner

InitNetwork()

DeclareModule OSM
  Declare InitOSM()
  Declare OSMGadget(Gadget.i, X.l, Y.l, Width.l, Height.l)
  Declare Event(Event.l)
  Declare SetLocation(latitude.d, longitude.d, zoom = 15)
  Declare DrawMap()
  Declare SetZoom(Zoom.l, mode.l = #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.l
    Y.l
  EndStructure
  
  Structure OSM
    Gadget.i
    TargetLocation.Location
    TargetTile.tile
    
    ServerURL.s
    ZoomMin.l
    ZoomMax.l
    Zoom.l
    
    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.l, Y.l, Width.l, Height.l)
    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), 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
  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.l, Zoom.l, XTile.l, YTile.l)
    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))
            SaveImage(image, OSM\CachePath + CacheFile, #PB_ImagePlugin_PNG)
            FreeMemory(*Buffer)
          EndIf
        EndIf
      CompilerEndIf
      
    EndIf
    
  EndProcedure
  
  Procedure GetSquareTile()
    Protected x.l, y.l, nx.l, ny.l, n.l = 0, tx.l, ty.l
    nx = Int(GadgetWidth(OSM\Gadget)/256) 
    ny = Int(GadgetHeight(OSM\Gadget)/256) 
    tx = 2*OSM\TargetTile\X
    ty = 2*OSM\TargetTile\Y
    For y = ty - ny To ty + ny + ny - 1    
      For x = tx - nx To tx + nx + nx - 1
        Debug Str(x) + " " + Str(y)
        LoadMapTile(n, OSM\Zoom + 1, x, y)
        n = n + 1
      Next
    Next
    Debug Str(n) + " Images Chargées";
  EndProcedure
  
  Procedure DrawMap()
    Protected x.l, y.l, nx.l, ny.l, mx.l, my.l, n.l = 0
    Protected deltaX.l, deltaY.l
    ;Protected tx.l, ty.l
    Protected x2.l, y2.l
    ;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
    nx = Int(GadgetWidth(OSM\Gadget)/256)
    ny = Int(GadgetHeight(OSM\Gadget)/256)
    
    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 ;+ OSM\Shift\X
        y2 = y*256 + OSM\DeltaCursor\Y ;+ OSM\Shift\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), x2, y2, 254, 254)
          DrawText( x2, y2, Str(x - Int(nx/2)) + ", " + Str(y - Int(ny/2)))
        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))
    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)
    GetSquareTile()
    DrawMap()
  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.l, mode.l = #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
                    SetLocation(OSM\TargetLocation\Latitude, OSM\TargetLocation\Longitude, OSM\Zoom)
                  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\gfLongitude))
                  ;SetGadgetText(#String_0, StrD(osm\gfLatitude))
              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.l, Gadget.l, Quit.b = #False
  Define pfValue.d
  OSM::SetLocation(49.04599, 2.03347)
  ;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
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Re: OpenStreetMap dans un Canvas

Message par Thyphoon »

djes a écrit : Moi aussi je m'y perds :)
Voilà où j'en suis, pas loin je crois ;)
Ha oui Bravo ça prend forme :D ... faut que je regarde en détail ce que tu as fait. :lol:
On a toujours un saut currieux des qu'on se déplace de plus d'un quadrant.
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: OpenStreetMap dans un Canvas

Message par djes »

Thyphoon a écrit :
djes a écrit : Moi aussi je m'y perds :)
Voilà où j'en suis, pas loin je crois ;)
Ha oui Bravo ça prend forme :D ... faut que je regarde en détail ce que tu as fait. :lol:
On a toujours un saut currieux des qu'on se déplace de plus d'un quadrant.
Oui, il y a un problème au niveau du chargement. Là, pareil, va falloir transformer ça en dynamique pour éviter des rechargements inutiles alors qu'il y a un cache et qu'on pourrait en garder en mémoire.
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Re: OpenStreetMap dans un Canvas

Message par Thyphoon »

djes a écrit : Oui, il y a un problème au niveau du chargement. Là, pareil, va falloir transformer ça en dynamique pour éviter des rechargements inutiles alors qu'il y a un cache.
Franchement c'est quand même pas super simple leur système ... et pas super bien documenté. Ou alors c'est moi.
c'est comme on est toujours pas centré sur les coordonnées demandées.
normalement pour se positioner dans le Tile ça devrait être ça

Code : Tout sélectionner

    deltaX = 512*(OSM\TargetTile\X - Int(OSM\TargetTile\X))
    deltaY = 512*(OSM\TargetTile\Y - Int(OSM\TargetTile\Y))
Mais ça ne marche pas ... :(
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: OpenStreetMap dans un Canvas

Message par djes »

Oui, c'est pas si simple. La difficulté, c'est de jongler avec les "ardoises" et les coordonnées des bords ; d'habitude je me fais un petit papier pour savoir où je vais mais là je perds beaucoup de temps à savoir comment fonctionne ce qui a été fait et dans quel but ! En plus je n'ai pas codé depuis TRES longtemps.
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Re: OpenStreetMap dans un Canvas

Message par Thyphoon »

djes a écrit :Oui, c'est pas si simple. La difficulté, c'est de jongler avec les "ardoises" et les coordonnées des bords ; d'habitude je me fais un petit papier pour savoir où je vais mais là je perds beaucoup de temps à savoir comment fonctionne ce qui a été fait et dans quel but ! En plus je n'ai pas codé depuis TRES longtemps.
lolll désolé ça fait pas mal de temps que je tourne en rond sur ce problème j'avais d'abord essayé de me débrouiller tout seul.. et comme j'y arrivais pas, en cherchant je suis tombé sur le code de Progi1984 qui m'a pas mal inspiré. Mais voilà je tourne en rond depuis pas mal de temps et je comprends pas bien le pourquoi du comment ...
Pourtant j'en ai fait des dessins sur des bouts de papier :?
Je suis encore loin de pouvoir afficher de multiple point sur une carte et de pouvoir les déplacer en drag and drop pour leur changer leur position
En tout cas un grand merci du temps que tu passes. :D
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: OpenStreetMap dans un Canvas

Message par djes »

Bah, ça me change, entre deux autres trucs ;)
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: OpenStreetMap dans un Canvas

Message par djes »

Ca commence à fonctionner (faudra nettoyer ce sujet après ;) )

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), 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
  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))
            SaveImage(image, OSM\CachePath + CacheFile, #PB_ImagePlugin_PNG)
            FreeMemory(*Buffer)
          EndIf
        EndIf
      CompilerEndIf
      
    EndIf
    
  EndProcedure
  
  Procedure GetSquareTile()
    Protected x.i, y.i, nx.i, ny.i, n.i = 0, tx.i, ty.i
    nx = Int(GadgetWidth(OSM\Gadget)/256) 
    ny = Int(GadgetHeight(OSM\Gadget)/256) 
    tx = 2*OSM\TargetTile\X
    ty = 2*OSM\TargetTile\Y
    For y = ty - ny To ty + ny + ny - 1    
      For x = tx - nx To tx + nx + nx - 1
        Debug Str(x) + " " + Str(y)
        LoadMapTile(n, OSM\Zoom + 1, 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
        
    nx = Int(GadgetWidth(OSM\Gadget)/256)
    ny = Int(GadgetHeight(OSM\Gadget)/256)
    
    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 ;+ OSM\Shift\X
        y2 = y*256 + OSM\DeltaCursor\Y ;+ OSM\Shift\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), x2, y2, 254, 254)
          DrawText( x2, y2, Str(x - Int(nx/2)) + ", " + Str(y - Int(ny/2)))
        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))
    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%512
                    OSM\DeltaCursor\Y = ty%512
                    If tx/512 <> 0 Or ty/512 <> 0
                      Debug tx/512
                      Debug ty/512
                      OSM\TargetTile\X - tx/512
                      OSM\TargetTile\Y - ty/512
                      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)

                      Debug OSM\TargetLocation\Latitude
                      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\gfLongitude))
                  ;SetGadgetText(#String_0, StrD(osm\gfLatitude))
              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)
  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
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Re: OpenStreetMap dans un Canvas

Message par Thyphoon »

Bravo ^_^
Faut que je regarde de plus prêt comment tu as fait.
Je suis pas là durant 24h mais des Samedi que je regarde ça de plus prêt
Répondre