278
PBMap.pb
278
PBMap.pb
@@ -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
|
|
||||||
|
20
README.md
20
README.md
@@ -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
|
||||||
|
Reference in New Issue
Block a user