Merge pull request #18 from djes/djes

Faulty PNG tiles fixes
This commit is contained in:
djes
2019-07-19 13:46:13 +02:00
committed by GitHub
2 changed files with 195 additions and 119 deletions

278
PBMap.pb
View File

@@ -1,18 +1,41 @@
; ******************************************************************** ; ********************************************************************
; Program: PBMap ; Program: PBMap
; Description: Permits the use of tiled maps like ; Description: Permits the use of tiled maps like
; OpenStreetMap in a handy PureBASIC module ; OpenStreetMap in a handy PureBASIC module
; Author: Thyphoon, djes, Idle, yves86 ; Author: Thyphoon, djes, Idle, yves86
; Date: June, 2018 ; Date: July, 2019
; License: PBMap : Free, unrestricted, credit ; License: PBMap : Free, unrestricted, credit
; appreciated but not required. ; appreciated but not required.
; OSM : see http://www.openstreetmap.org/copyright ; OSM : see http://www.openstreetmap.org/copyright
; Note: Please share improvement ! ; Note: Please share improvement !
; Thanks: Progi1984 ; Thanks: Progi1984, falsam
; HowToRun: Just compile this code, example is included
; ********************************************************************
;
; Track bugs with the following options with debugger enabled (see in the example)
; PBMap::SetOption(#Map, "ShowDebugInfos", "1")
; PBMap::SetDebugLevel(5)
; PBMap::SetOption(#Map, "Verbose", "1")
;
; or with the OnError() PB capabilities :
;
; CompilerIf #PB_Compiler_LineNumbering = #False
; MessageRequester("Warning !", "You must enable 'OnError lines support' in compiler options", #PB_MessageRequester_Ok )
; End
; CompilerEndIf
;
; Declare ErrorHandler()
;
; OnErrorCall(@ErrorHandler())
;
; Procedure ErrorHandler()
; MessageRequester("Ooops", "The following error happened : " + ErrorMessage(ErrorCode()) + #CRLF$ +"line : " + Str(ErrorLine()))
; EndProcedure
;
; ******************************************************************** ; ********************************************************************
CompilerIf #PB_Compiler_Thread = #False CompilerIf #PB_Compiler_Thread = #False
MessageRequester("Warning !", "You must enable ThreadSafe support in compiler options", #PB_MessageRequester_Ok ) MessageRequester("Warning !", "You must enable 'Create ThreadSafe Executable' in compiler options", #PB_MessageRequester_Ok )
End End
CompilerEndIf CompilerEndIf
@@ -29,7 +52,7 @@ UseJPEGImageEncoder()
DeclareModule PBMap DeclareModule PBMap
#PBMAPNAME = "PBMap" #PBMAPNAME = "PBMap"
#PBMAPVERSION = "0.9" #PBMAPVERSION = "0.91"
#USERAGENT = #PBMAPNAME + "/" + #PBMAPVERSION + " (https://github.com/djes/PBMap)" #USERAGENT = #PBMAPNAME + "/" + #PBMAPVERSION + " (https://github.com/djes/PBMap)"
CompilerIf #PB_Compiler_OS = #PB_OS_Linux CompilerIf #PB_Compiler_OS = #PB_OS_Linux
@@ -57,10 +80,10 @@ DeclareModule PBMap
EndStructure EndStructure
Structure Marker Structure Marker
GeographicCoordinates.GeographicCoordinates ; Marker latitude and longitude GeographicCoordinates.GeographicCoordinates ; Marker's latitude and longitude
Identifier.s Identifier.s
Legend.s Legend.s
Color.l ; Marker color Color.l ; Marker's color
Focus.i Focus.i
Selected.i ; Is the marker selected ? Selected.i ; Is the marker selected ?
CallBackPointer.i ; @Procedure(X.i, Y.i) to DrawPointer (you must use VectorDrawing lib) CallBackPointer.i ; @Procedure(X.i, Y.i) to DrawPointer (you must use VectorDrawing lib)
@@ -511,20 +534,6 @@ Module PBMap
EndIf EndIf
EndProcedure EndProcedure
Procedure Pixel2LatLon(MapGadget.i, *Coords.PixelCoordinates, *Location.GeographicCoordinates, Zoom)
Protected *PBMap.PBMap = PBMaps(Str(MapGadget))
Protected n.d = *PBMap\TileSize * Pow(2.0, Zoom)
; Ensures the longitude to be in the range [-180; 180[
*Location\Longitude = Mod(Mod(*Coords\x / n * 360.0, 360.0) + 360.0, 360.0) - 180
*Location\Latitude = Degree(ATan(SinH(#PI * (1.0 - 2.0 * *Coords\y / n))))
If *Location\Latitude <= -89
*Location\Latitude = -89
EndIf
If *Location\Latitude >= 89
*Location\Latitude = 89
EndIf
EndProcedure
; Ensures the longitude to be in the range [-180; 180[ ; Ensures the longitude to be in the range [-180; 180[
Procedure.d ClipLongitude(Longitude.d) Procedure.d ClipLongitude(Longitude.d)
ProcedureReturn Mod(Mod(Longitude + 180, 360.0) + 360.0, 360.0) - 180 ProcedureReturn Mod(Mod(Longitude + 180, 360.0) + 360.0, 360.0) - 180
@@ -565,19 +574,37 @@ Module PBMap
*Pixel\y = *PBMap\Drawing\RadiusY + (py - *PBMap\PixelCoordinates\y) *Pixel\y = *PBMap\Drawing\RadiusY + (py - *PBMap\PixelCoordinates\y)
EndProcedure EndProcedure
Procedure Pixel2LatLon(MapGadget.i, *Coords.PixelCoordinates, *Location.GeographicCoordinates, Zoom)
Protected *PBMap.PBMap = PBMaps(Str(MapGadget))
Protected n.d = *PBMap\TileSize * Pow(2.0, Zoom)
; Ensures the longitude to be in the range [-180; 180[
*Location\Longitude = Mod((1 + *Coords\x / n) * 360, 360) - 180 ; Mod(Mod(*Coords\x / n * 360.0, 360.0) + 360.0, 360.0) - 180
*Location\Latitude = Degree(ATan(SinH(#PI * (1.0 - 2.0 * *Coords\y / n))))
If *Location\Latitude <= -89
*Location\Latitude = -89
EndIf
If *Location\Latitude >= 89
*Location\Latitude = 89
EndIf
EndProcedure
Procedure.d Pixel2Lon(MapGadget.i, x) Procedure.d Pixel2Lon(MapGadget.i, x)
Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) Protected *PBMap.PBMap = PBMaps(Str(MapGadget))
Protected NewX.d = (*PBMap\PixelCoordinates\x - *PBMap\Drawing\RadiusX + x) / *PBMap\TileSize Protected n.d = *PBMap\TileSize * Pow(2.0, *PBMap\Zoom)
Protected n.d = Pow(2.0, *PBMap\Zoom) ProcedureReturn Mod((1 + x / n) * 360.0, 360.0) - 180
; double mod is to ensure the longitude to be in the range [-180; 180[
ProcedureReturn Mod(Mod(NewX / n * 360.0, 360.0) + 360.0, 360.0) - 180
EndProcedure EndProcedure
Procedure.d Pixel2Lat(MapGadget.i, y) Procedure.d Pixel2Lat(MapGadget.i, y)
Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) Protected *PBMap.PBMap = PBMaps(Str(MapGadget))
Protected NewY.d = (*PBMap\PixelCoordinates\y - *PBMap\Drawing\RadiusY + y) / *PBMap\TileSize Protected n.d = *PBMap\TileSize * Pow(2.0, *PBMap\Zoom)
Protected n.d = Pow(2.0, *PBMap\Zoom) Protected latitude.d = Degree(ATan(SinH(#PI * (1.0 - 2.0 * y / n))))
ProcedureReturn Degree(ATan(SinH(#PI * (1.0 - 2.0 * NewY / n)))) If latitude <= -89
latitude = -89
EndIf
If latitude >= 89
latitude = 89
EndIf
ProcedureReturn latitude
EndProcedure EndProcedure
; HaversineAlgorithm ; HaversineAlgorithm
@@ -1114,7 +1141,7 @@ Module PBMap
; If cache size exceeds limit, try to delete the oldest tiles used (first in the time stack) ; If cache size exceeds limit, try to delete the oldest tiles used (first in the time stack)
Procedure MemoryCacheManagement(MapGadget.i) Procedure MemoryCacheManagement(MapGadget.i)
Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) Protected *PBMap.PBMap = PBMaps(Str(MapGadget))
LockMutex(*PBMap\MemoryCacheAccessMutex) ; Prevents thread to start or finish LockMutex(*PBMap\MemoryCacheAccessMutex) ; Prevents threads to start or finish
Protected CacheSize = MapSize(*PBMap\MemCache\Images()) * Pow(*PBMap\TileSize, 2) * 4 ; Size of a tile = TileSize * TileSize * 4 bytes (RGBA) Protected CacheSize = MapSize(*PBMap\MemCache\Images()) * Pow(*PBMap\TileSize, 2) * 4 ; Size of a tile = TileSize * TileSize * 4 bytes (RGBA)
Protected CacheLimit = *PBMap\Options\MaxMemCache * 1024 Protected CacheLimit = *PBMap\Options\MaxMemCache * 1024
MyDebug(*PBMap, "Cache size : " + Str(CacheSize/1024) + " / CacheLimit : " + Str(CacheLimit/1024), 5) MyDebug(*PBMap, "Cache size : " + Str(CacheSize/1024) + " / CacheLimit : " + Str(CacheLimit/1024), 5)
@@ -1154,10 +1181,30 @@ Module PBMap
UnlockMutex(*PBMap\MemoryCacheAccessMutex) UnlockMutex(*PBMap\MemoryCacheAccessMutex)
EndProcedure EndProcedure
;- LoadImage workaround
; by idle
; Check that the PNG file is valid
Procedure _LoadImage(ImageNumber, File.s)
Protected fn, pat, pos, res
If UCase(GetExtensionPart(File)) = "PNG"
pat = $444E4549
fn= ReadFile(#PB_Any, File)
If fn
pos = Lof(fn)
FileSeek(fn, pos - 8)
res = ReadLong(fn)
CloseFile(fn)
If res = pat
ProcedureReturn LoadImage(ImageNumber, File)
EndIf
EndIf
EndIf
EndProcedure
Procedure.i GetTileFromHDD(*PBMap.PBMap, CacheFile.s) ;Directly pass the PBMap structure (faster) Procedure.i GetTileFromHDD(*PBMap.PBMap, CacheFile.s) ;Directly pass the PBMap structure (faster)
Protected nImage.i, LifeTime.i, MaxLifeTime.i Protected nImage.i, LifeTime.i, MaxLifeTime.i
; Everything is OK, loads the file ; Everything is OK, loads the file
nImage = LoadImage(#PB_Any, CacheFile) nImage = _LoadImage(#PB_Any, CacheFile)
If nImage If nImage
MyDebug(*PBMap, " Success loading " + CacheFile + " as nImage " + Str(nImage), 3) MyDebug(*PBMap, " Success loading " + CacheFile + " as nImage " + Str(nImage), 3)
ProcedureReturn nImage ProcedureReturn nImage
@@ -1216,20 +1263,21 @@ Module PBMap
;UnlockMutex(*PBMap\MemoryCacheAccessMutex) ;UnlockMutex(*PBMap\MemoryCacheAccessMutex)
*Tile\Size = 0 *Tile\Size = 0
*Tile\Download = ReceiveHTTPFile(*Tile\URL, *Tile\CacheFile, #PB_HTTP_Asynchronous, #USERAGENT) *Tile\Download = ReceiveHTTPFile(*Tile\URL, *Tile\CacheFile, #PB_HTTP_Asynchronous, #USERAGENT)
;TODO : obtain original file size to compare and eventually delete truncated file
If *Tile\Download If *Tile\Download
Repeat Repeat
Progress = HTTPProgress(*Tile\Download) Progress = HTTPProgress(*Tile\Download)
Select Progress Select Progress
Case #PB_Http_Success Case #PB_HTTP_Success
*Tile\Size = FinishHTTP(*Tile\Download) ; \Size signals that the download is OK *Tile\Size = FinishHTTP(*Tile\Download) ; \Size signals that the download is OK
;MyDebug(*PBMap, " Thread nb " + Str(*Tile\GetImageThread) + " " + *Tile\key + " for image " + *Tile\CacheFile + " finished. Size : " + Str(*Tile\Size), 5) ;MyDebug(*PBMap, " Thread nb " + Str(*Tile\GetImageThread) + " " + *Tile\key + " for image " + *Tile\CacheFile + " finished. Size : " + Str(*Tile\Size), 5)
Quit = #True Quit = #True
Case #PB_Http_Failed Case #PB_HTTP_Failed
FinishHTTP(*Tile\Download) FinishHTTP(*Tile\Download)
*Tile\Size = 0 ; \Size = 0 signals that the download has failed *Tile\Size = 0 ; \Size = 0 signals that the download has failed
;MyDebug(*PBMap, " Thread nb " + Str(*Tile\GetImageThread) + " " + *Tile\key + " for image " + *Tile\CacheFile + " failed.", 5) ;MyDebug(*PBMap, " Thread nb " + Str(*Tile\GetImageThread) + " " + *Tile\key + " for image " + *Tile\CacheFile + " failed.", 5)
Quit = #True Quit = #True
Case #PB_Http_Aborted Case #PB_HTTP_Aborted
FinishHTTP(*Tile\Download) FinishHTTP(*Tile\Download)
*Tile\Size = 0 ; \Size = 0 signals that the download has failed *Tile\Size = 0 ; \Size = 0 signals that the download has failed
;MyDebug(*PBMap, " Thread nb " + Str(*Tile\GetImageThread) + " " + *Tile\key + " for image " + *Tile\CacheFile + " aborted.", 5) ;MyDebug(*PBMap, " Thread nb " + Str(*Tile\GetImageThread) + " " + *Tile\key + " for image " + *Tile\CacheFile + " aborted.", 5)
@@ -1246,7 +1294,8 @@ Module PBMap
EndIf EndIf
; End of the memory cache access ; End of the memory cache access
;LockMutex(*PBMap\MemoryCacheAccessMutex) ;LockMutex(*PBMap\MemoryCacheAccessMutex)
PostEvent(#PB_Event_Gadget, *Tile\Window, *Tile\Gadget, #PB_MAP_TILE_CLEANUP, *Tile) ; To free memory outside the thread ; To free memory and eventually delete aborted image file outside the thread
PostEvent(#PB_Event_Gadget, *Tile\Window, *Tile\Gadget, #PB_MAP_TILE_CLEANUP, *Tile)
;UnlockMutex(*PBMap\MemoryCacheAccessMutex) ;UnlockMutex(*PBMap\MemoryCacheAccessMutex)
EndProcedure EndProcedure
@@ -1260,7 +1309,7 @@ Module PBMap
Protected *timg.ImgMemCach = FindMapElement(*PBMap\MemCache\Images(), key) Protected *timg.ImgMemCach = FindMapElement(*PBMap\MemCache\Images(), key)
If *timg If *timg
MyDebug(*PBMap, "Key : " + key + " found in memory cache", 4) MyDebug(*PBMap, "Key : " + key + " found in memory cache", 4)
; Is the associated image already been loaded in memory ? ; Is the associated image already loaded in memory ?
If *timg\nImage If *timg\nImage
; Yes, returns the image's nb ; Yes, returns the image's nb
MyDebug(*PBMap, " as image " + *timg\nImage, 4) MyDebug(*PBMap, " as image " + *timg\nImage, 4)
@@ -1298,73 +1347,71 @@ Module PBMap
*PBMap\MemCache\ImagesTimeStack()\MapKey = MapKey(*PBMap\MemCache\Images()) *PBMap\MemCache\ImagesTimeStack()\MapKey = MapKey(*PBMap\MemCache\Images())
MyDebug(*PBMap, "Key : " + key + " added in memory cache", 4) MyDebug(*PBMap, "Key : " + key + " added in memory cache", 4)
EndIf EndIf
; If there's no active download thread for this tile ; If there's no active downloading thread for this image
If *timg\Tile <= 0 If *timg\Tile <= 0
*timg\nImage = 0 *timg\nImage = 0
*timg\Size = FileSize(CacheFile) *timg\Size = FileSize(CacheFile)
; Manage tile file lifetime, delete if too old, or if size = 0 ; Does a valid file exists on HD ? Try to load it.
If *PBMap\Options\TileLifetime <> -1 If *timg\Size >= 0
If *timg\Size >= 0 ; Does the file exists ? ; Manage tile file lifetime, delete if too old, or if size = 0
If *PBMap\Options\TileLifetime <> -1
If *timg\Size = 0 Or (Date() - GetFileDate(CacheFile, #PB_Date_Modified) > *PBMap\Options\TileLifetime) ; If Lifetime > MaxLifeTime ; There's a bug with #PB_Date_Created If *timg\Size = 0 Or (Date() - GetFileDate(CacheFile, #PB_Date_Modified) > *PBMap\Options\TileLifetime) ; If Lifetime > MaxLifeTime ; There's a bug with #PB_Date_Created
If DeleteFile(CacheFile) If DeleteFile(CacheFile)
MyDebug(*PBMap, " Deleting image file " + CacheFile, 3) MyDebug(*PBMap, " Deleting image file " + CacheFile, 3)
*timg\Size = 0 *timg\Size = 0
Else Else
MyDebug(*PBMap, " Can't delete image file " + CacheFile, 3) MyDebug(*PBMap, " Can't delete image file " + CacheFile, 3)
UnlockMutex(*PBMap\MemoryCacheAccessMutex)
ProcedureReturn #False
EndIf EndIf
UnlockMutex(*PBMap\MemoryCacheAccessMutex)
ProcedureReturn #False
EndIf EndIf
EndIf EndIf
EndIf ; Try to load tile's image from HD
; Try To load it from HD
If *timg\Size > 0
*timg\nImage = GetTileFromHDD(*PBMap, CacheFile.s) *timg\nImage = GetTileFromHDD(*PBMap, CacheFile.s)
Else If *timg\nImage
MyDebug(*PBMap, " Failed loading from HDD " + CacheFile + " -> Filesize = " + FileSize(CacheFile), 3) ; Success : image found and loaded from HDD
*timg\Alpha = 0
UnlockMutex(*PBMap\MemoryCacheAccessMutex)
ProcedureReturn *timg
EndIf
EndIf EndIf
If *timg\nImage ; If GetTileFromHDD failed, will try to download the image from the web in a thread
; Image found and loaded from HDD MyDebug(*PBMap, " Failed loading from HDD " + CacheFile + " -> Filesize = " + FileSize(CacheFile), 3)
*timg\Alpha = 0 If *PBMap\ThreadsNB < *PBMap\Options\MaxThreads
UnlockMutex(*PBMap\MemoryCacheAccessMutex) If *PBMap\DownloadSlots < *PBMap\Options\MaxDownloadSlots
ProcedureReturn *timg Protected *NewTile.Tile = AllocateMemory(SizeOf(Tile))
Else If *NewTile
; If GetTileFromHDD failed, will load it (again?) from the web *timg\Tile = *NewTile ; There's now a loading thread
If *PBMap\ThreadsNB < *PBMap\Options\MaxThreads *timg\Alpha = 0
If *PBMap\DownloadSlots < *PBMap\Options\MaxDownloadSlots With *NewTile
; Launch a new web loading thread ; New tile parameters
*PBMap\DownloadSlots + 1 \key = key
Protected *NewTile.Tile = AllocateMemory(SizeOf(Tile)) \URL = URL
If *NewTile \CacheFile = CacheFile
With *NewTile \nImage = 0
; New tile parameters \Time = ElapsedMilliseconds()
\key = key \Window = *PBMap\Window
\URL = URL \Gadget = *PBMap\Gadget
\CacheFile = CacheFile \GetImageThread = CreateThread(@GetImageThread(), *NewTile)
\nImage = 0 If \GetImageThread
\Time = ElapsedMilliseconds() MyDebug(*PBMap, " Creating get image thread nb " + Str(\GetImageThread) + " to get " + CacheFile + " (key = " + key, 3)
\Window = *PBMap\Window *PBMap\ThreadsNB + 1
\Gadget = *PBMap\Gadget *PBMap\DownloadSlots + 1
\GetImageThread = CreateThread(@GetImageThread(), *NewTile) Else
If \GetImageThread ; Thread creation failed this time
*timg\Tile = *NewTile ; There's now a loading thread *timg\Tile = 0
*timg\Alpha = 0 MyDebug(*PBMap, " Can't create get image thread to get " + CacheFile, 3)
MyDebug(*PBMap, " Creating get image thread nb " + Str(\GetImageThread) + " to get " + CacheFile + " (key = " + key, 3) FreeMemory(*NewTile)
*PBMap\ThreadsNB + 1 EndIf
Else EndWith
MyDebug(*PBMap, " Can't create get image thread to get " + CacheFile, 3)
FreeMemory(*NewTile)
EndIf
EndWith
Else
MyDebug(*PBMap, " Error, can't allocate memory for a new tile loading thread", 3)
EndIf
Else Else
MyDebug(*PBMap, " Thread needed " + key + " for image " + CacheFile + " canceled because no free download slot.", 5) MyDebug(*PBMap, " Error, can't allocate memory for a new tile loading thread", 3)
EndIf EndIf
Else Else
MyDebug(*PBMap, " Error, maximum threads nb reached", 3) MyDebug(*PBMap, " Thread needed " + key + " for image " + CacheFile + " canceled because no free download slot.", 5)
EndIf EndIf
Else
MyDebug(*PBMap, " Error, maximum threads nb reached", 3)
EndIf EndIf
EndIf EndIf
UnlockMutex(*PBMap\MemoryCacheAccessMutex) UnlockMutex(*PBMap\MemoryCacheAccessMutex)
@@ -2079,21 +2126,31 @@ Module PBMap
;-*** Misc functions ;-*** Misc functions
Procedure.d GetMouseLongitude(MapGadget.i) Procedure.d GetCanvasPixelLon(MapGadget.i, x)
Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) Protected *PBMap.PBMap = PBMaps(Str(MapGadget))
Protected MouseX.d = (*PBMap\PixelCoordinates\x - *PBMap\Drawing\RadiusX + GetGadgetAttribute(*PBMap\Gadget, #PB_Canvas_MouseX)) / *PBMap\TileSize Protected MouseX.d = (*PBMap\PixelCoordinates\x - *PBMap\Drawing\RadiusX + x) / *PBMap\TileSize
Protected n.d = Pow(2.0, *PBMap\Zoom) Protected n.d = Pow(2.0, *PBMap\Zoom)
; double mod is to ensure the longitude to be in the range [-180; 180[ ; double mod is to ensure the longitude to be in the range [-180; 180[
ProcedureReturn Mod(Mod(MouseX / n * 360.0, 360.0) + 360.0, 360.0) - 180 ProcedureReturn Mod(Mod(MouseX / n * 360.0, 360.0) + 360.0, 360.0) - 180
EndProcedure EndProcedure
Procedure.d GetMouseLatitude(MapGadget.i) Procedure.d GetCanvasPixelLat(MapGadget.i, y)
Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) Protected *PBMap.PBMap = PBMaps(Str(MapGadget))
Protected MouseY.d = (*PBMap\PixelCoordinates\y - *PBMap\Drawing\RadiusY + GetGadgetAttribute(*PBMap\Gadget, #PB_Canvas_MouseY)) / *PBMap\TileSize Protected MouseY.d = (*PBMap\PixelCoordinates\y - *PBMap\Drawing\RadiusY + y) / *PBMap\TileSize
Protected n.d = Pow(2.0, *PBMap\Zoom) Protected n.d = Pow(2.0, *PBMap\Zoom)
ProcedureReturn Degree(ATan(SinH(#PI * (1.0 - 2.0 * MouseY / n)))) ProcedureReturn Degree(ATan(SinH(#PI * (1.0 - 2.0 * MouseY / n))))
EndProcedure EndProcedure
Procedure.d GetMouseLongitude(MapGadget.i)
Protected *PBMap.PBMap = PBMaps(Str(MapGadget))
ProcedureReturn GetCanvasPixelLon(MapGadget.i, GetGadgetAttribute(*PBMap\Gadget, #PB_Canvas_MouseX))
EndProcedure
Procedure.d GetMouseLatitude(MapGadget.i)
Protected *PBMap.PBMap = PBMaps(Str(MapGadget))
ProcedureReturn GetCanvasPixelLat(MapGadget.i, GetGadgetAttribute(*PBMap\Gadget, #PB_Canvas_MouseY))
EndProcedure
Procedure SetLocation(MapGadget.i, latitude.d, longitude.d, Zoom = -1, Mode.i = #PB_Absolute) Procedure SetLocation(MapGadget.i, latitude.d, longitude.d, Zoom = -1, Mode.i = #PB_Absolute)
Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) Protected *PBMap.PBMap = PBMaps(Str(MapGadget))
Select Mode Select Mode
@@ -2511,6 +2568,11 @@ Module PBMap
; Absolute zoom (centered on the center of the map) ; Absolute zoom (centered on the center of the map)
SetZoom(MapGadget, GetGadgetAttribute(*PBMap\Gadget, #PB_Canvas_WheelDelta), #PB_Relative) SetZoom(MapGadget, GetGadgetAttribute(*PBMap\Gadget, #PB_Canvas_WheelDelta), #PB_Relative)
EndIf EndIf
; Case #PB_EventType_RightClick
; Debug GetMouseLongitude(MapGadget)
; Debug GetMouseLatitude(MapGadget)
; Debug GetCanvasPixelLon(MapGadget, CanvasMouseX + *PBMap\Drawing\RadiusX)
; Debug GetCanvasPixelLat(MapGadget, CanvasMouseY + *PBMap\Drawing\RadiusY)
Case #PB_EventType_LeftButtonDown Case #PB_EventType_LeftButtonDown
; LatLon2Pixel(@*PBMap\GeographicCoordinates, @*PBMap\PixelCoordinates, *PBMap\Zoom) ; LatLon2Pixel(@*PBMap\GeographicCoordinates, @*PBMap\PixelCoordinates, *PBMap\Zoom)
*PBMap\Dragging = #True *PBMap\Dragging = #True
@@ -2543,14 +2605,14 @@ Module PBMap
EndIf EndIf
Next Next
EndIf EndIf
; YA pour sélectionner un point de la trace avec le clic gauche ; YA To select a track with LMB
If *PBMap\EditMarker = #False If *PBMap\EditMarker = #False
Location\Latitude = GetMouseLatitude(MapGadget) Location\Latitude = GetMouseLatitude(MapGadget)
Location\Longitude = GetMouseLongitude(MapGadget) Location\Longitude = GetMouseLongitude(MapGadget)
If *PBMap\CallBackLeftClic > 0 If *PBMap\CallBackLeftClic > 0
CallFunctionFast(*PBMap\CallBackLeftClic, @Location) CallFunctionFast(*PBMap\CallBackLeftClic, @Location)
EndIf EndIf
; ajout YA // change la forme du pointeur de souris pour les déplacements de la carte ; ajout YA // Mouse pointer when moving map
SetGadgetAttribute(*PBMap\Gadget, #PB_Canvas_Cursor, #PB_Cursor_Hand) SetGadgetAttribute(*PBMap\Gadget, #PB_Canvas_Cursor, #PB_Cursor_Hand)
Else Else
SetGadgetAttribute(*PBMap\Gadget, #PB_Canvas_Cursor, #PB_Cursor_Default) ; ajout YA pour remettre le pointeur souris en normal SetGadgetAttribute(*PBMap\Gadget, #PB_Canvas_Cursor, #PB_Cursor_Default) ; ajout YA pour remettre le pointeur souris en normal
@@ -2608,7 +2670,7 @@ Module PBMap
EndIf EndIf
Next Next
; Check if mouse touch tracks ; Check if mouse touch tracks
If *PBMap\Options\ShowTrackSelection ; YA ajout pour éviter la sélection de la trace If *PBMap\Options\ShowTrackSelection ; YA to avoid selecting track
With *PBMap\TracksList() With *PBMap\TracksList()
; Trace Track ; Trace Track
If ListSize(*PBMap\TracksList()) > 0 If ListSize(*PBMap\TracksList()) > 0
@@ -2642,11 +2704,11 @@ Module PBMap
EndIf EndIf
EndIf EndIf
Case #PB_EventType_LeftButtonUp Case #PB_EventType_LeftButtonUp
SetGadgetAttribute(*PBMap\Gadget,#PB_Canvas_Cursor,#PB_Cursor_Default) ; ajout YA pour remettre le pointeur souris en normal SetGadgetAttribute(*PBMap\Gadget,#PB_Canvas_Cursor,#PB_Cursor_Default) ; YA normal mouse pointer
; *PBMap\MoveStartingPoint\x = - 1 ; *PBMap\MoveStartingPoint\x = - 1
*PBMap\Dragging = #False *PBMap\Dragging = #False
*PBMap\Redraw = #True *PBMap\Redraw = #True
;YA pour connaitre les coordonnées d'un marqueur après déplacement ;YA to knows marker coordinates after moving
ForEach *PBMap\Markers() ForEach *PBMap\Markers()
If *PBMap\Markers()\Selected = #True If *PBMap\Markers()\Selected = #True
If *PBMap\CallBackMarker > 0 If *PBMap\CallBackMarker > 0
@@ -2658,18 +2720,21 @@ Module PBMap
*PBMap\Redraw = #True *PBMap\Redraw = #True
Case #PB_MAP_RETRY Case #PB_MAP_RETRY
*PBMap\Redraw = #True *PBMap\Redraw = #True
;- #PB_MAP_TILE_CLEANUP : Tile web loading thread cleanup ;- *** Tile web loading thread cleanup
; After a Web tile loading thread, clean the tile structure memory, see GetImageThread() ; After a Web tile loading thread, cleans the tile structure memory, see GetImageThread()
Case #PB_MAP_TILE_CLEANUP Case #PB_MAP_TILE_CLEANUP
LockMutex(*PBMap\MemoryCacheAccessMutex) ; Prevents threads to start or finish
*Tile = EventData() *Tile = EventData()
key = *Tile\key key = *Tile\key
*Tile\Download = 0 *Tile\Download = 0
If FindMapElement(*PBMap\MemCache\Images(), key) <> 0 If FindMapElement(*PBMap\MemCache\Images(), key) <> 0
; If the map element has not been deleted during the thread lifetime (should not occur) ; If the map element has not been deleted during the thread lifetime (should not occur)
*PBMap\MemCache\Images(key)\Tile = *Tile\Size ;*PBMap\MemCache\Images(key)\Tile = *Tile\Size
If *Tile\Size If *Tile\Size
;TODO : check if file size = server file size
;and eventually use pngcheck to avoid problematic files http://www.libpng.org/pub/png/apps/pngcheck.html
*PBMap\MemCache\Images(key)\Tile = -1 ; Web loading thread has finished successfully *PBMap\MemCache\Images(key)\Tile = -1 ; Web loading thread has finished successfully
;- Allows to post edit the tile image file with a customised code ; Allows to post edit the tile image file with a customised code
If *PBMap\CallBackModifyTileFile If *PBMap\CallBackModifyTileFile
TileNewFilename = *PBMap\CallBackModifyTileFile(*Tile\CacheFile, *Tile\URL) TileNewFilename = *PBMap\CallBackModifyTileFile(*Tile\CacheFile, *Tile\URL)
If TileNewFilename If TileNewFilename
@@ -2679,16 +2744,22 @@ Module PBMap
EndIf EndIf
Else Else
*PBMap\MemCache\Images(key)\Tile = 0 *PBMap\MemCache\Images(key)\Tile = 0
If DeleteFile(*Tile\CacheFile)
MyDebug(*PBMap, " Deleting not fully loaded image file " + *Tile\CacheFile, 3)
Else
MyDebug(*PBMap, " Can't delete not fully loaded image file " + *Tile\CacheFile, 3)
EndIf
EndIf EndIf
EndIf EndIf
FreeMemory(*Tile) ; Frees the data needed for the thread (*tile=*PBMap\MemCache\Images(key)\Tile) FreeMemory(*Tile) ; Frees the data needed for the thread (*tile=*PBMap\MemCache\Images(key)\Tile)
*PBMap\ThreadsNB - 1 *PBMap\ThreadsNB - 1
*PBMap\DownloadSlots - 1 *PBMap\DownloadSlots - 1
*PBMap\Redraw = #True *PBMap\Redraw = #True
UnlockMutex(*PBMap\MemoryCacheAccessMutex)
EndSelect EndSelect
EndProcedure EndProcedure
; Redraws at regular intervals ;-*** Main timer : Cache management and drawing
Procedure TimerEvents() Procedure TimerEvents()
Protected *PBMap.PBMap Protected *PBMap.PBMap
ForEach PBMaps() ForEach PBMaps()
@@ -3140,12 +3211,9 @@ CompilerIf #PB_Compiler_IsMainFile
CompilerEndIf CompilerEndIf
; IDE Options = PureBasic 5.70 LTS (Windows - x64)
; IDE Options = PureBasic 5.61 (Windows - x64) ; CursorPosition = 1185
; CursorPosition = 2751 ; FirstLine = 1171
; FirstLine = 2744
; Folding = --------------------- ; Folding = ---------------------
; EnableThread ; EnableThread
; EnableXP ; EnableXP
; CompileSourceDirectory
; DisablePurifier = 1,1,1,1

View File

@@ -1,14 +1,17 @@
# PBMap # PBMap 0.91
Open source tiled map software. Open source tiled map software.
To develop tiled map applications in PureBasic. Module to develop tiled map applications in PureBasic, like like OpenStreetMap(c), Google Maps(c), Here(c), ...
Functional example based on OpenStreetMap(c) services
Based on OpenStreetMap services
OSM copyright : http://www.openstreetmap.org/copyright OSM copyright : http://www.openstreetmap.org/copyright
This code is free, but any use should mention the origin of this code.
Officials forums topics here : This code is free, but any user should mention the origin of this code.
Official forums topics :
http://www.purebasic.fr/english/viewtopic.php?f=27&t=66320 (english) http://www.purebasic.fr/english/viewtopic.php?f=27&t=66320 (english)
http://www.purebasic.fr/french/viewtopic.php?f=3&t=16160 (french) http://www.purebasic.fr/french/viewtopic.php?f=3&t=16160 (french)
@@ -16,6 +19,11 @@ Contributors :
Thyphoon Thyphoon
djes djes
Idle Idle
Thanks to :
Progi1984 Progi1984
yves86 yves86
Andr<EFBFBD> André
falsam
Special thanks to Fred and Fantaisie Software's team