diff --git a/PBMap.pb b/PBMap.pb index 4d258e3..d2fb5a2 100644 --- a/PBMap.pb +++ b/PBMap.pb @@ -1,15 +1,15 @@ -;******************************************************************** +; ******************************************************************** ; Program: PBMap ; Description: Permits the use of tiled maps like ; OpenStreetMap in a handy PureBASIC module ; Author: Thyphoon, djes And Idle ; Date: March, 2017 ; License: PBMap : Free, unrestricted, credit -; appreciated but not required. -; OSM : see http://www.openstreetmap.org/copyright +; appreciated but not required. +; OSM : see http://www.openstreetmap.org/copyright ; Note: Please share improvement ! ; Thanks: Progi1984, yves86 -;******************************************************************** +; ******************************************************************** CompilerIf #PB_Compiler_Thread = #False MessageRequester("Warning !", "You must enable ThreadSafe support in compiler options", #PB_MessageRequester_Ok ) @@ -78,9 +78,9 @@ DeclareModule PBMap Declare SetZoom(Zoom.i, mode.i = #PB_Relative) Declare SetZoomToArea(MinY.d, MaxY.d, MinX.d, MaxX.d) Declare SetZoomToTracks(*Tracks) - Declare NominatimGeoLocationQuery(Address.s, *ReturnPosition = 0) ;Send back the position *ptr.GeographicCoordinates - Declare.i LoadGpxFile(FileName.s) ; - Declare.i SaveGpxFile(FileName.s, *Track) ; + Declare NominatimGeoLocationQuery(Address.s, *ReturnPosition = 0) ; Send back the position *ptr.GeographicCoordinates + Declare.i LoadGpxFile(FileName.s) ; + Declare.i SaveGpxFile(FileName.s, *Track) ; Declare ClearTracks() Declare DeleteTrack(*Ptr) Declare DeleteSelectedTracks() @@ -125,6 +125,7 @@ Module PBMap CacheFile.s GetImageThread.i Download.i + Time.i EndStructure Structure BoundingBox @@ -198,18 +199,19 @@ Module PBMap TimerInterval.i MaxMemCache.i ; in MiB MaxThreads.i ; Maximum simultaneous web loading threads + MaxDownloadSlots.i ; Maximum simultaneous download slots TileLifetime.i Verbose.i ; Maximum debug informations Warning.i ; Warning requesters ShowMarkersNb.i ShowMarkersLegend.i - ;Drawing stuff + ; Drawing stuff StrokeWidthTrackDefault.i - ;Colours + ; Colours ColourFocus.i ColourSelected.i ColourTrackDefault.i - ;HERE specific + ; HERE specific appid.s appcode.s EndStructure @@ -223,7 +225,7 @@ Module PBMap Enabled.i Alpha.d ; 1 : opaque ; 0 : transparent format.s - ;> HERE specific params + ; > HERE specific params APP_ID.s APP_CODE.s ressource.s @@ -232,10 +234,10 @@ Module PBMap scheme.s lg.s lg2.s - ;< - ;> GeoServer specific params + ; < + ; > GeoServer specific params ServerLayerName.s - ;< + ; < EndStructure Structure Box @@ -288,8 +290,11 @@ Module PBMap Redraw.i Dragging.i Dirty.i ; To signal that drawing need a refresh - MemoryCacheManagement.i ; To pause web loading threads + MemoryCacheManagement.i ; To pause web loading threads + DownloadSlots.i ; Actual nb of used download slots + DownloadSlotsMutex.i ; To be sure that only one thread at a time can access to the DownloadSlots var + List TracksList.Tracks() ; To display a GPX track List Markers.Marker() ; To diplay marker EditMarker.l @@ -318,7 +323,7 @@ Module PBMap ;- *** GetText - Translation purpose - ;TODO use this for all text + ; TODO use this for all text IncludeFile "gettext.pbi" ;-*** Misc tools @@ -333,7 +338,7 @@ Module PBMap ;-Error management - ;Shows an error msg and terminates the program + ; Shows an error msg and terminates the program Procedure FatalError(msg.s) If PBMap\Options\Warning MessageRequester("PBMap", msg, #PB_MessageRequester_Ok) @@ -341,31 +346,31 @@ Module PBMap End EndProcedure - ;Shows an error msg + ; Shows an error msg Procedure Error(msg.s) If PBMap\Options\Warning MessageRequester("PBMap", msg, #PB_MessageRequester_Ok) EndIf EndProcedure - ;Send debug infos to stdout (allowing mixed debug infos with curl or other libs) + ; Send debug infos to stdout (allowing mixed debug infos with curl or other libs) Procedure MyDebug(msg.s, DbgLevel = 0) If PBMap\Options\Verbose And DbgLevel >= MyDebugLevel PrintN(msg) - ;Debug msg + ; Debug msg EndIf EndProcedure - ;Creates a full tree - ;by Thomas (ts-soft) Schulz - ;http://www.purebasic.fr/english/viewtopic.php?f=12&t=58657&hilit=createdirectory&view=unread#unread + ; Creates a full tree + ; by Thomas (ts-soft) Schulz + ; http://www.purebasic.fr/english/viewtopic.php?f=12&t=58657&hilit=createdirectory&view=unread#unread CompilerSelect #PB_Compiler_OS CompilerCase #PB_OS_Windows - #FILE_ATTRIBUTE_DEVICE = 64 ;(0x40) - #FILE_ATTRIBUTE_INTEGRITY_STREAM = 32768 ;(0x8000) - #FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 8192;(0x2000) - #FILE_ATTRIBUTE_NO_SCRUB_DATA = 131072;(0x20000) - #FILE_ATTRIBUTE_VIRTUAL = 65536;(0x10000) + #FILE_ATTRIBUTE_DEVICE = 64 ; (0x40) + #FILE_ATTRIBUTE_INTEGRITY_STREAM = 32768 ; (0x8000) + #FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 8192; (0x2000) + #FILE_ATTRIBUTE_NO_SCRUB_DATA = 131072; (0x20000) + #FILE_ATTRIBUTE_VIRTUAL = 65536; (0x10000) #FILE_ATTRIBUTE_DONTSETFLAGS = ~(#FILE_ATTRIBUTE_DIRECTORY| #FILE_ATTRIBUTE_SPARSE_FILE| #FILE_ATTRIBUTE_OFFLINE| @@ -403,7 +408,7 @@ Module PBMap EndProcedure Procedure TechnicalImagesCreation() - ;"Loading" image + ; "Loading" image Protected LoadingText$ = "Loading" Protected NothingText$ = "Nothing" PBmap\ImgLoading = CreateImage(#PB_Any, 256, 256) @@ -421,20 +426,20 @@ Module PBMap EndVectorLayer() StopVectorDrawing() EndIf - ;"Nothing" tile + ; "Nothing" tile PBmap\ImgNothing = CreateImage(#PB_Any, 256, 256) If PBmap\ImgNothing StartVectorDrawing(ImageVectorOutput(PBMap\ImgNothing)) - ;BeginVectorLayer() + ; BeginVectorLayer() VectorSourceColor(RGBA(220, 230, 255, 255)) AddPathBox(0, 0, 256, 256) FillPath() - ;MovePathCursor(0, 0) - ;VectorFont(FontID(PBMap\Font), 256 / 20) - ;VectorSourceColor(RGBA(150, 150, 150, 255)) - ;MovePathCursor(0 + (256 - VectorTextWidth(NothingText$)) / 2, 0 + (256 - VectorTextHeight(NothingText$)) / 2) - ;DrawVectorText(NothingText$) - ;EndVectorLayer() + ; MovePathCursor(0, 0) + ; VectorFont(FontID(PBMap\Font), 256 / 20) + ; VectorSourceColor(RGBA(150, 150, 150, 255)) + ; MovePathCursor(0 + (256 - VectorTextWidth(NothingText$)) / 2, 0 + (256 - VectorTextHeight(NothingText$)) / 2) + ; DrawVectorText(NothingText$) + ; EndVectorLayer() StopVectorDrawing() EndIf EndProcedure @@ -445,22 +450,22 @@ Module PBMap ProcedureReturn Result EndProcedure - ;*** Converts coords to tile.decimal - ;Warning, structures used in parameters are not tested + ; *** Converts coords to tile.decimal + ; Warning, structures used in parameters are not tested Procedure LatLon2TileXY(*Location.GeographicCoordinates, *Coords.Coordinates, Zoom) Protected n.d = Pow(2.0, Zoom) Protected LatRad.d = Radian(*Location\Latitude) *Coords\x = n * (Mod( *Location\Longitude + 180.0, 360) / 360.0 ) *Coords\y = n * ( 1.0 - Log(Tan(LatRad) + (1.0/Cos(LatRad))) / #PI ) / 2.0 MyDebug("Latitude : " + StrD(*Location\Latitude) + " ; Longitude : " + StrD(*Location\Longitude), 5) - MyDebug("Coords X : " + Str(*Coords\x) + " ; Y : " + Str(*Coords\y), 5) + MyDebug("Coords X : " + Str(*Coords\x) + " ; Y : " + Str(*Coords\y), 5) EndProcedure - ;*** Converts tile.decimal to coords - ;Warning, structures used in parameters are not tested + ; *** Converts tile.decimal to coords + ; Warning, structures used in parameters are not tested Procedure TileXY2LatLon(*Coords.Coordinates, *Location.GeographicCoordinates, Zoom) Protected n.d = Pow(2.0, Zoom) - ;Ensures the longitude to be in the range [-180;180[ + ; 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 @@ -473,7 +478,7 @@ Module PBMap Procedure Pixel2LatLon(*Coords.PixelCoordinates, *Location.GeographicCoordinates, Zoom) Protected n.d = PBMap\TileSize * Pow(2.0, Zoom) - ;Ensures the longitude to be in the range [-180;180[ + ; 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 @@ -484,12 +489,12 @@ Module PBMap 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) ProcedureReturn Mod(Mod(Longitude + 180, 360.0) + 360.0, 360.0) - 180 EndProcedure - ;Lat Lon coordinates 2 pixel absolute [0 to 2^Zoom * TileSize [ + ; Lat Lon coordinates 2 pixel absolute [0 to 2^Zoom * TileSize [ Procedure LatLon2Pixel(*Location.GeographicCoordinates, *Pixel.PixelCoordinates, Zoom) Protected tilemax = Pow(2.0, Zoom) * PBMap\TileSize Protected LatRad.d = Radian(*Location\Latitude) @@ -497,7 +502,7 @@ Module PBMap *Pixel\y = tilemax * ( 1.0 - Log(Tan(LatRad) + (1.0/Cos(LatRad))) / #PI ) / 2.0 EndProcedure - ;Lat Lon coordinates 2 pixel relative to the center of view + ; Lat Lon coordinates 2 pixel relative to the center of view Procedure LatLon2PixelRel(*Location.GeographicCoordinates, *Pixel.PixelCoordinates, Zoom) Protected tilemax = Pow(2.0, Zoom) * PBMap\TileSize Protected cx.d = PBMap\Drawing\RadiusX @@ -505,18 +510,18 @@ Module PBMap Protected LatRad.d = Radian(*Location\Latitude) Protected px.d = tilemax * (Mod( *Location\Longitude + 180.0, 360) / 360.0 ) Protected py.d = tilemax * ( 1.0 - Log(Tan(LatRad) + (1.0/Cos(LatRad))) / #PI ) / 2.0 - ;check the x boundaries of the map to adjust the position (coz of the longitude wrapping) + ; check the x boundaries of the map to adjust the position (coz of the longitude wrapping) If dpx - px >= tilemax / 2 - ;Debug "c1" + ; Debug "c1" *Pixel\x = cx + (px - dpx + tilemax) ElseIf px - dpx > tilemax / 2 - ;Debug "c2" + ; Debug "c2" *Pixel\x = cx + (px - dpx - tilemax) ElseIf px - dpx < 0 - ;Debug "c3" + ; Debug "c3" *Pixel\x = cx - (dpx - px) Else - ;Debug "c0" + ; Debug "c0" *Pixel\x = cx + (px - dpx) EndIf *Pixel\y = PBMap\Drawing\RadiusY + (py - PBMap\PixelCoordinates\y) @@ -525,7 +530,7 @@ Module PBMap Procedure.d Pixel2Lon(x) Protected NewX.d = (PBMap\PixelCoordinates\x - PBMap\Drawing\RadiusX + x) / PBMap\TileSize 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(NewX / n * 360.0, 360.0) + 360.0, 360.0) - 180 EndProcedure @@ -538,19 +543,19 @@ Module PBMap ; HaversineAlgorithm ; http://andrew.hedges.name/experiments/haversine/ Procedure.d HaversineInKM(*posA.GeographicCoordinates, *posB.GeographicCoordinates) - Protected eQuatorialEarthRadius.d = 6378.1370;6372.795477598; - Protected dlong.d = (*posB\Longitude - *posA\Longitude); - Protected dlat.d = (*posB\Latitude - *posA\Latitude) ; + Protected eQuatorialEarthRadius.d = 6378.1370; 6372.795477598; + Protected dlong.d = (*posB\Longitude - *posA\Longitude); + Protected dlat.d = (*posB\Latitude - *posA\Latitude) ; Protected alpha.d=dlat/2 Protected beta.d=dlong/2 Protected a.d = Sin(Radian(alpha)) * Sin(Radian(alpha)) + Cos(Radian(*posA\Latitude)) * Cos(Radian(*posB\Latitude)) * Sin(Radian(beta)) * Sin(Radian(beta)) - Protected c.d = ASin(Min(1,Sqr(a))); + Protected c.d = ASin(Min(1,Sqr(a))); Protected distance.d = 2*eQuatorialEarthRadius * c - ProcedureReturn distance ; + ProcedureReturn distance ; EndProcedure Procedure.d HaversineInM(*posA.GeographicCoordinates, *posB.GeographicCoordinates) - ProcedureReturn (1000 * HaversineInKM(@*posA,@*posB)); + ProcedureReturn (1000 * HaversineInKM(@*posA,@*posB)); EndProcedure ; No more used, see LatLon2PixelRel @@ -560,15 +565,15 @@ Module PBMap Protected x1.l,y1.l x1 = (*Location\Longitude+180)*(mapWidth/360) ; convert from degrees To radians - Protected latRad.d = *Location\Latitude*#PI/180; - Protected mercN.d = Log(Tan((#PI/4)+(latRad/2))); - y1 = (mapHeight/2)-(mapWidth*mercN/(2*#PI)) ; + Protected latRad.d = *Location\Latitude*#PI/180; + Protected mercN.d = Log(Tan((#PI/4)+(latRad/2))); + y1 = (mapHeight/2)-(mapWidth*mercN/(2*#PI)) ; Protected x2.l, y2.l x2 = (PBMap\GeographicCoordinates\Longitude+180)*(mapWidth/360) ; convert from degrees To radians - latRad = PBMap\GeographicCoordinates\Latitude*#PI/180; + latRad = PBMap\GeographicCoordinates\Latitude*#PI/180; mercN = Log(Tan((#PI/4)+(latRad/2))) - y2 = (mapHeight/2)-(mapWidth*mercN/(2*#PI)); + y2 = (mapHeight/2)-(mapWidth*mercN/(2*#PI)); *Pixel\x=PBMap\Drawing\RadiusX - (x2-x1) *Pixel\y=PBMap\Drawing\RadiusY - (y2-y1) EndProcedure @@ -610,24 +615,24 @@ Module PBMap EndIf EndProcedure - ;TODO : best cleaning of the string from bad behaviour + ; TODO : best cleaning of the string from bad behaviour Procedure.s StringCheck(String.s) ProcedureReturn Trim(RemoveString(RemoveString(RemoveString(RemoveString(RemoveString(RemoveString(RemoveString(RemoveString(RemoveString(RemoveString(String, Chr(0)), Chr(32)), Chr(39)), Chr(33)), Chr(34)), "@"), "/"), "\"), "$"), "%")) EndProcedure Procedure.i ColourString2Value(Value.s) - ;TODO : better string check + ; TODO : better string check Protected Col.s = RemoveString(Value, " ") If Left(Col, 1) = "$" Protected r.i, g.i, b.i, a.i = 255 Select Len(Col) - Case 4 ;RGB (eg : "$9BC" + Case 4 ; RGB (eg : "$9BC" r = Val("$"+Mid(Col, 2, 1)) : g = Val("$"+Mid(Col, 3, 1)) : b = Val("$"+Mid(Col, 4, 1)) - Case 5 ;RGBA (eg : "$9BC5") + Case 5 ; RGBA (eg : "$9BC5") r = Val("$"+Mid(Col, 2, 1)) : g = Val("$"+Mid(Col, 3, 1)) : b = Val("$"+Mid(Col, 4, 1)) : a = Val("$"+Mid(Col, 5, 1)) - Case 7 ;RRGGBB (eg : "$95B4C2") + Case 7 ; RRGGBB (eg : "$95B4C2") r = Val("$"+Mid(Col, 2, 2)) : g = Val("$"+Mid(Col, 4, 2)) : b = Val("$"+Mid(Col, 6, 2)) - Case 9 ;RRGGBBAA (eg : "$95B4C249") + Case 9 ; RRGGBBAA (eg : "$95B4C249") r = Val("$"+Mid(Col, 2, 2)) : g = Val("$"+Mid(Col, 4, 2)) : b = Val("$"+Mid(Col, 6, 2)) : a = Val("$"+Mid(Col, 8, 2)) EndSelect ProcedureReturn RGBA(r, g, b, a) @@ -651,7 +656,7 @@ Module PBMap OpenConsole() EndIf CreateDirectoryEx(\HDDCachePath) - If \DefaultOSMServer <> "" And IsLayer("OSM") = #False ;First time creation of the basis OSM layer + If \DefaultOSMServer <> "" And IsLayer("OSM") = #False ; First time creation of the basis OSM layer AddOSMServerLayer("OSM", 1, \DefaultOSMServer) EndIf EndWith @@ -687,6 +692,8 @@ Module PBMap PBMap\Options\MaxMemCache = Val(Value) Case "maxthreads" PBMap\Options\MaxThreads = Val(Value) + Case "maxdownloadslots" + PBMap\Options\MaxDownloadSlots = Val(Value) Case "tilelifetime" PBMap\Options\TileLifetime = Val(Value) Case "verbose" @@ -756,6 +763,8 @@ Module PBMap ProcedureReturn StrU(\MaxMemCache) Case "maxthreads" ProcedureReturn StrU(\MaxThreads) + Case "maxdownloadslots" + ProcedureReturn StrU(\MaxDownloadSlots) Case "tilelifetime" ProcedureReturn StrU(\TileLifetime) Case "verbose" @@ -794,7 +803,7 @@ Module PBMap EndWith EndProcedure - ;By default, save options in the user's home directory + ; By default, save options in the user's home directory Procedure SaveOptions(PreferencesFile.s = "PBMap.prefs") If PreferencesFile = "PBMap.prefs" CreatePreferences(GetHomeDirectory() + "PBMap.prefs") @@ -818,6 +827,7 @@ Module PBMap WritePreferenceInteger("WheelMouseRelative", \WheelMouseRelative) WritePreferenceInteger("MaxMemCache", \MaxMemCache) WritePreferenceInteger("MaxThreads", \MaxThreads) + WritePreferenceInteger("MaxDownloadSlots", \MaxDownloadSlots) WritePreferenceInteger("TileLifetime", \TileLifetime) WritePreferenceInteger("Verbose", \Verbose) WritePreferenceInteger("Warning", \Warning) @@ -832,7 +842,7 @@ Module PBMap WritePreferenceInteger("ShowMarkersLegend", \ShowMarkersLegend) PreferenceGroup("DRAWING") WritePreferenceInteger("StrokeWidthTrackDefault", \StrokeWidthTrackDefault) - ;Colours; + ; Colours; WritePreferenceInteger("ColourFocus", \ColourFocus) WritePreferenceInteger("ColourSelected", \ColourSelected) WritePreferenceInteger("ColourTrackDefault", \ColourTrackDefault) @@ -846,22 +856,22 @@ Module PBMap Else OpenPreferences(PreferencesFile) EndIf - ;Use this to create and customize your preferences file for the first time - ; CreatePreferences(GetHomeDirectory() + "PBMap.prefs") - ; ;Or this to modify - ; ;OpenPreferences(GetHomeDirectory() + "PBMap.prefs") - ; ;Or this - ; ;RunProgram("notepad.exe", GetHomeDirectory() + "PBMap.prefs", GetHomeDirectory()) - ; PreferenceGroup("PROXY") - ; WritePreferenceInteger("Proxy", #True) - ; WritePreferenceString("ProxyURL", "myproxy.fr") - ; WritePreferenceString("ProxyPort", "myproxyport") - ; WritePreferenceString("ProxyUser", "myproxyname") - ; WritePreferenceString("ProxyPass", "myproxypass") ;TODO !Warning! !not encoded! - ; PreferenceGroup("HERE") - ; WritePreferenceString("APP_ID", "myhereid") ;TODO !Warning! !not encoded! - ; WritePreferenceString("APP_CODE", "myherecode") ;TODO !Warning! !not encoded! - ; ClosePreferences() + ; Use this to create and customize your preferences file for the first time + ; CreatePreferences(GetHomeDirectory() + "PBMap.prefs") + ; ; Or this to modify + ; ; OpenPreferences(GetHomeDirectory() + "PBMap.prefs") + ; ; Or this + ; ; RunProgram("notepad.exe", GetHomeDirectory() + "PBMap.prefs", GetHomeDirectory()) + ; PreferenceGroup("PROXY") + ; WritePreferenceInteger("Proxy", #True) + ; WritePreferenceString("ProxyURL", "myproxy.fr") + ; WritePreferenceString("ProxyPort", "myproxyport") + ; WritePreferenceString("ProxyUser", "myproxyname") + ; WritePreferenceString("ProxyPass", "myproxypass") ; TODO !Warning! !not encoded! + ; PreferenceGroup("HERE") + ; WritePreferenceString("APP_ID", "myhereid") ; TODO !Warning! !not encoded! + ; WritePreferenceString("APP_CODE", "myherecode") ; TODO !Warning! !not encoded! + ; ClosePreferences() With PBMap\Options PreferenceGroup("PROXY") \Proxy = ReadPreferenceInteger("Proxy", #False) @@ -869,11 +879,11 @@ Module PBMap \ProxyURL = ReadPreferenceString("ProxyURL", "") ; = InputRequester("ProxyServer", "Do you use a Proxy Server? Then enter the full url:", "") \ProxyPort = ReadPreferenceString("ProxyPort", "") ; = InputRequester("ProxyPort" , "Do you use a specific port? Then enter it", "") \ProxyUser = ReadPreferenceString("ProxyUser", "") ; = InputRequester("ProxyUser" , "Do you use a user name? Then enter it", "") - \ProxyPassword = ReadPreferenceString("ProxyPass", "") ; = InputRequester("ProxyPass", "Do you use a password ? Then enter it", "") ;TODO + \ProxyPassword = ReadPreferenceString("ProxyPass", "") ; = InputRequester("ProxyPass", "Do you use a password ? Then enter it", "") ; TODO EndIf PreferenceGroup("HERE") - \appid = ReadPreferenceString("APP_ID", "") ; = InputRequester("Here App ID", "Do you use HERE ? Enter app ID", "") ;TODO - \appcode = ReadPreferenceString("APP_CODE", "") ; = InputRequester("Here App Code", "Do you use HERE ? Enter app Code", "") ;TODO + \appid = ReadPreferenceString("APP_ID", "") ; = InputRequester("Here App ID", "Do you use HERE ? Enter app ID", "") ; TODO + \appcode = ReadPreferenceString("APP_CODE", "") ; = InputRequester("Here App Code", "Do you use HERE ? Enter app Code", "") ; TODO PreferenceGroup("URL") \DefaultOSMServer = ReadPreferenceString("DefaultOSMServer", "http://tile.openstreetmap.org/") @@ -881,9 +891,10 @@ Module PBMap \HDDCachePath = ReadPreferenceString("TilesCachePath", GetTemporaryDirectory() + "PBMap" + slash) PreferenceGroup("OPTIONS") \WheelMouseRelative = ReadPreferenceInteger("WheelMouseRelative", #True) - \MaxMemCache = ReadPreferenceInteger("MaxMemCache", 20480) ;20 MiB, about 80 tiles in memory - \MaxThreads = ReadPreferenceInteger("MaxThreads", 10) - \TileLifetime = ReadPreferenceInteger("TileLifetime", 1209600) ;about 2 weeks ; -1 = unlimited + \MaxMemCache = ReadPreferenceInteger("MaxMemCache", 20480) ; 20 MiB, about 80 tiles in memory + \MaxThreads = ReadPreferenceInteger("MaxThreads", 40) + \MaxDownloadSlots = ReadPreferenceInteger("MaxDownloadSlots", 2) + \TileLifetime = ReadPreferenceInteger("TileLifetime", 1209600) ; about 2 weeks ;-1 = unlimited \Verbose = ReadPreferenceInteger("Verbose", #False) \Warning = ReadPreferenceInteger("Warning", #False) \ShowDegrees = ReadPreferenceInteger("ShowDegrees", #False) @@ -909,7 +920,7 @@ Module PBMap ;-*** Layers - ;Add a layer to a list (to get things ordered) and to a map (to access things easily) + ; Add a layer to a list (to get things ordered) and to a map (to access things easily) Procedure.i AddLayer(Name.s, Order.i, Alpha.d) Protected *Ptr = 0 *Ptr = AddMapElement(PBMap\Layers(), Name) @@ -943,13 +954,13 @@ Module PBMap EndProcedure ; "Here" layer - ;see there for parameters : https://developer.here.com/rest-apis/documentation/enterprise-map-tile/topics/resource-base-maptile.html - ;you could use base.maps.api.here.com or aerial.maps.api.here.com or traffic.maps.api.here.com or pano.maps.api.here.com. - ;use *.cit.map.api.com For Customer Integration Testing (see https://developer.here.com/rest-apis/documentation/enterprise-Map-tile/common/request-cit-environment-rest.html) + ; see there for parameters : https://developer.here.com/rest-apis/documentation/enterprise-map-tile/topics/resource-base-maptile.html + ; you could use base.maps.api.here.com or aerial.maps.api.here.com or traffic.maps.api.here.com or pano.maps.api.here.com. + ; use *.cit.map.api.com For Customer Integration Testing (see https://developer.here.com/rest-apis/documentation/enterprise-Map-tile/common/request-cit-environment-rest.html) Procedure.i AddHereServerLayer(LayerName.s, Order.i, APP_ID.s = "", APP_CODE.s = "", ServerURL.s = "aerial.maps.api.here.com", path.s = "/maptile/2.1/", ressource.s = "maptile", id.s = "newest", scheme.s = "satellite.day", format.s = "jpg", lg.s = "eng", lg2.s = "eng", param.s = "") Protected *Ptr.Layer = AddLayer(LayerName, Order, 1) If *Ptr - With *Ptr ;PBMap\Layers() + With *Ptr ; PBMap\Layers() \ServerURL = ServerURL \path = path \ressource = ressource @@ -977,12 +988,12 @@ Module PBMap EndIf EndProcedure - ;GeoServer / geowebcache - google maps service - ;template 'http://localhost:8080/geowebcache/service/gmaps?layers=layer-name&zoom={Z}&x={X}&y={Y}&format=image/png' + ; GeoServer / geowebcache - google maps service + ; template 'http://localhost:8080/geowebcache/service/gmaps?layers=layer-name&zoom={Z}&x={X}&y={Y}&format=image/png' Procedure.i AddGeoServerLayer(LayerName.s, Order.i, ServerLayerName.s, ServerURL.s = "http://localhost:8080/", path.s = "geowebcache/service/gmaps", format.s = "image/png") Protected *Ptr.Layer = AddLayer(LayerName, Order, 1) If *Ptr - With *Ptr ;PBMap\Layers() + With *Ptr ; PBMap\Layers() \ServerURL = ServerURL \path = path \LayerType = 2 ; GeoServer @@ -1004,10 +1015,10 @@ Module PBMap Procedure DeleteLayer(Name.s) FindMapElement(PBMap\Layers(), Name) Protected *Ptr = PBMap\Layers() - ;Free the list element + ; Free the list element ChangeCurrentElement(PBMap\LayersList(), *Ptr) DeleteElement(PBMap\LayersList()) - ;Free the map element + ; Free the map element DeleteMapElement(PBMap\Layers()) PBMap\Redraw = #True EndProcedure @@ -1031,6 +1042,8 @@ Module PBMap ProcedureReturn PBMap\Layers(Name)\Alpha EndProcedure + ;-*** + Procedure MemoryCacheManagement() ; If cache size exceeds limit, try to delete the oldest tiles used (first in the time stack) Protected CacheSize = MapSize(PBMap\MemCache\Images()) * Pow(PBMap\TileSize, 2) * 5 ; Size of a tile = TileSize * TileSize * 4 bytes (RGBA) @@ -1075,17 +1088,17 @@ Module PBMap Procedure.i GetTileFromHDD(CacheFile.s) MaxLifeTime.i = PBMap\Options\TileLifetime - If FileSize(CacheFile) > 0 ;<> -1 + If FileSize(CacheFile) > 0 ; <> -1 ; Manage tile file lifetime If MaxLifeTime <> -1 - LifeTime = Date() - GetFileDate(CacheFile, #PB_Date_Modified) ;There's a bug with #PB_Date_Created + LifeTime = Date() - GetFileDate(CacheFile, #PB_Date_Modified) ; There's a bug with #PB_Date_Created If LifeTime > MaxLifeTime MyDebug(" Deleting too old (" + StrU(LifeTime) + " secs) " + CacheFile, 3) DeleteFile(CacheFile) ProcedureReturn 0 EndIf EndIf - ;Everything is OK, loads the file + ; Everything is OK, loads the file nImage = LoadImage(#PB_Any, CacheFile) If nImage And IsImage(nImage) MyDebug(" Success loading " + CacheFile + " as nImage " + Str(nImage), 3) @@ -1107,32 +1120,46 @@ Module PBMap ; **** OLD IMPORTANT NOTICE (please not remove) ; This original catchimage/saveimage method is a double operation (uncompress/recompress PNG) ; and is modifying the original PNG image which could lead to PNG error (Idle has spent hours debunking the 1 bit PNG bug) - ;Protected *Buffer - ;Protected nImage.i = -1 - ;Protected timg - ; *Buffer = ReceiveHTTPMemory(TileURL) ;TODO to thread by using #PB_HTTP_Asynchronous - ; If *Buffer - ; nImage = CatchImage(#PB_Any, *Buffer, MemorySize(*Buffer)) - ; If IsImage(nImage) - ; If SaveImage(nImage, CacheFile, #PB_ImagePlugin_PNG, 0, 32) ;The 32 is needed !!!! - ; MyDebug("Loaded from web " + TileURL + " as CacheFile " + CacheFile, 3) - ; Else - ; MyDebug("Loaded from web " + TileURL + " but cannot save to CacheFile " + CacheFile, 3) - ; EndIf - ; FreeMemory(*Buffer) - ; Else - ; MyDebug("Can't catch image loaded from web " + TileURL, 3) - ; nImage = -1 - ; EndIf - ; Else - ; MyDebug(" Problem loading from web " + TileURL, 3) - ; EndIf + ; Protected *Buffer + ; Protected nImage.i = -1 + ; Protected timg + ; *Buffer = ReceiveHTTPMemory(TileURL) ; TODO to thread by using #PB_HTTP_Asynchronous + ; If *Buffer + ; nImage = CatchImage(#PB_Any, *Buffer, MemorySize(*Buffer)) + ; If IsImage(nImage) + ; If SaveImage(nImage, CacheFile, #PB_ImagePlugin_PNG, 0, 32) ; The 32 is needed !!!! + ; MyDebug("Loaded from web " + TileURL + " as CacheFile " + CacheFile, 3) + ; Else + ; MyDebug("Loaded from web " + TileURL + " but cannot save to CacheFile " + CacheFile, 3) + ; EndIf + ; FreeMemory(*Buffer) + ; Else + ; MyDebug("Can't catch image loaded from web " + TileURL, 3) + ; nImage = -1 + ; EndIf + ; Else + ; MyDebug(" Problem loading from web " + TileURL, 3) + ; EndIf ; **** Threaded Progress = 0, Size = 0 Procedure GetImageThread(*Tile.Tile) MyDebug("Thread starting for image " + *Tile\CacheFile + "(" + *Tile\key + ")", 5) + ; Waits for a free download slot + LockMutex(PBMap\DownloadSlotsMutex) + While PBMap\DownloadSlots >= PBMap\Options\MaxDownloadSlots + UnlockMutex(PBMap\DownloadSlotsMutex) + If ElapsedMilliseconds() - *Tile\Time > 10000 + MyDebug(" Thread for image " + *Tile\CacheFile + " canceled after 10 seconds waiting for a slot.", 5) + PostEvent(#PB_Event_Gadget, PBMap\Window, PBmap\Gadget, #PB_MAP_TILE_CLEANUP, *Tile) ; To free memory outside the thread + ProcedureReturn #False + EndIf + Delay(500) + LockMutex(PBMap\DownloadSlotsMutex) + Wend + PBMap\DownloadSlots + 1 + UnlockMutex(PBMap\DownloadSlotsMutex) *Tile\Download = ReceiveHTTPFile(*Tile\URL, *Tile\CacheFile, #PB_HTTP_Asynchronous) If *Tile\Download Repeat @@ -1142,23 +1169,24 @@ Module PBMap Case #PB_Http_Success Size = FinishHTTP(*Tile\Download) MyDebug(" Thread for image " + *Tile\CacheFile + " finished. Size : " + Str(Size), 5) - PostEvent(#PB_Event_Gadget, PBMap\Window, PBmap\Gadget, #PB_MAP_TILE_CLEANUP, *Tile) ;To free memory outside the thread - *Tile\Download = 0 + PostEvent(#PB_Event_Gadget, PBMap\Window, PBmap\Gadget, #PB_MAP_TILE_CLEANUP, *Tile) ; To free memory outside the thread ProcedureReturn #True Case #PB_Http_Failed FinishHTTP(*Tile\Download) MyDebug(" Thread for image " + *Tile\CacheFile + " failed.", 5) - PostEvent(#PB_Event_Gadget, PBMap\Window, PBmap\Gadget, #PB_MAP_TILE_CLEANUP, *Tile) ;To free memory outside the thread - *Tile\Download = 0 + PostEvent(#PB_Event_Gadget, PBMap\Window, PBmap\Gadget, #PB_MAP_TILE_CLEANUP, *Tile) ; To free memory outside the thread ProcedureReturn #False Case #PB_Http_Aborted FinishHTTP(*Tile\Download) MyDebug(" Thread for image " + *Tile\CacheFile + " aborted.", 5) - PostEvent(#PB_Event_Gadget, PBMap\Window, PBmap\Gadget, #PB_MAP_TILE_CLEANUP, *Tile) ;To free memory outside the thread - *Tile\Download = 0 + PostEvent(#PB_Event_Gadget, PBMap\Window, PBmap\Gadget, #PB_MAP_TILE_CLEANUP, *Tile) ; To free memory outside the thread ProcedureReturn #False Default MyDebug(" Thread for image " + *Tile\CacheFile + " downloading " + Str(Progress) + " bytes", 5) + If ElapsedMilliseconds() - *Tile\Time > 60000 + MyDebug(" Thread for image " + *Tile\CacheFile + " canceled after 60 seconds.", 5) + AbortHTTP(*Tile\Download) + EndIf EndSelect EndIf Delay(500) ; Frees CPU @@ -1175,12 +1203,12 @@ Module PBMap MyDebug("Key : " + key + " found in memory cache", 5) If *timg\nImage MyDebug(" as image " + *timg\nImage, 5) - ;*** Cache management + ; *** Cache management ; Retrieves the image in the time stack, push it to the end (to say it's the lastly used) ChangeCurrentElement(PBMap\MemCache\ImagesTimeStack(), *timg\TimeStackPtr) MoveElement(PBMap\MemCache\ImagesTimeStack(), #PB_List_Last) - ;*timg\TimeStackPtr = LastElement(PBMap\MemCache\ImagesTimeStack()) - ;*** + ; *timg\TimeStackPtr = LastElement(PBMap\MemCache\ImagesTimeStack()) + ; *** ProcedureReturn *timg Else MyDebug(" but not the image.", 5) @@ -1204,7 +1232,7 @@ Module PBMap ; Associates the time stack element to the cache element PBMap\MemCache\ImagesTimeStack()\MapKey = MapKey(PBMap\MemCache\Images()) MyDebug("Key : " + key + " added in memory cache", 5) - ;*** + ; *** EndIf If *timg\Tile = 0 ; Checks if a loading thread is not already running ; Is the file image on HDD ? @@ -1221,12 +1249,13 @@ Module PBMap With *NewTile *timg\Tile = *NewTile ; There's now a loading thread *timg\Alpha = 0 - ;*timg\nImage = -1 - ;New tile parameters + ; *timg\nImage = -1 + ; New tile parameters \key = key \URL = URL \CacheFile = CacheFile - \nImage = 0 + \nImage = 0 + \Time = ElapsedMilliseconds() \GetImageThread = CreateThread(@GetImageThread(), *NewTile) If \GetImageThread MyDebug(" Creating get image thread nb " + Str(\GetImageThread) + " to get " + CacheFile, 3) @@ -1248,14 +1277,14 @@ Module PBMap Procedure DrawTiles(*Drawing.DrawingParameters, LayerName.s) Protected x.i, y.i,kq.q - Protected tx = Int(*Drawing\TileCoordinates\x) ;Don't forget the Int() ! + Protected tx = Int(*Drawing\TileCoordinates\x) ; Don't forget the Int() ! Protected ty = Int(*Drawing\TileCoordinates\y) - Protected nx = *Drawing\RadiusX / PBMap\TileSize ;How many tiles around the point + Protected nx = *Drawing\RadiusX / PBMap\TileSize ; How many tiles around the point Protected ny = *Drawing\RadiusY / PBMap\TileSize Protected px, py, *timg.ImgMemCach, tilex, tiley, key.s Protected URL.s, CacheFile.s Protected tilemax = 1< 0 BeginVectorLayer() ForEach PBMap\TracksList() If ListSize(\Track()) > 0 - ;Check visibility + ; Check visibility \Visible = #False ForEach \Track() If IsInDrawingPixelBoundaries(*Drawing, @PBMap\TracksList()\Track()) @@ -1523,7 +1552,7 @@ Module PBMap EndIf Next If \Visible - ;Draw tracks + ; Draw tracks ForEach \Track() LatLon2PixelRel(@PBMap\TracksList()\Track(), @Pixel, PBMap\Zoom) If ListIndex(\Track()) = 0 @@ -1532,10 +1561,10 @@ Module PBMap AddPathLine(Pixel\x, Pixel\y) EndIf Next - ; \BoundingBox\x = PathBoundsX() - ; \BoundingBox\y = PathBoundsY() - ; \BoundingBox\w = PathBoundsWidth() - ; \BoundingBox\h = PathBoundsHeight() + ; \BoundingBox\x = PathBoundsX() + ; \BoundingBox\y = PathBoundsY() + ; \BoundingBox\w = PathBoundsWidth() + ; \BoundingBox\h = PathBoundsHeight() If \Focus VectorSourceColor(PBMap\Options\ColourFocus) ElseIf \Selected @@ -1548,14 +1577,14 @@ Module PBMap EndIf Next EndVectorLayer() - ;Draw distances + ; Draw distances If PBMap\Options\ShowTrackKms And PBMap\Zoom > 10 BeginVectorLayer() ForEach PBMap\TracksList() If \Visible km = 0 : memKm = -1 ForEach PBMap\TracksList()\Track() - ;Test Distance + ; Test Distance If ListIndex(\Track()) = 0 Location\Latitude = \Track()\Latitude Location\Longitude = \Track()\Longitude @@ -1704,7 +1733,7 @@ Module PBMap EndProcedure Procedure MarkerEdit(*Marker.Marker) - If *Marker\EditWindow = 0 ;Check that this marker has no already opened window + If *Marker\EditWindow = 0 ; Check that this marker has no already opened window Protected WindowMarkerEdit = OpenWindow(#PB_Any, WindowX(PBMap\Window) + WindowWidth(PBMap\Window) / 2 - 150, WindowY(PBMap\Window)+ WindowHeight(PBMap\Window) / 2 + 50, 300, 100, "Marker Edit", #PB_Window_SystemMenu | #PB_Window_TitleBar) StickyWindow(WindowMarkerEdit, #True) TextGadget(#PB_Any, 2, 2, 80, 25, gettext("Identifier")) @@ -1727,8 +1756,8 @@ Module PBMap AddPathLine(-8, -16, #PB_Path_Relative) AddPathCircle(8, 0, 8, 180, 0, #PB_Path_Relative) AddPathLine(-8, 16, #PB_Path_Relative) - ;FillPath(#PB_Path_Preserve) - ;ClipPath(#PB_Path_Preserve) + ; FillPath(#PB_Path_Preserve) + ; ClipPath(#PB_Path_Preserve) AddPathCircle(0, -16, 5, 0, 360, #PB_Path_Relative) VectorSourceColor(*Marker\Color) FillPath(#PB_Path_Preserve) @@ -1755,7 +1784,7 @@ Module PBMap EndIf If PBMap\Options\ShowMarkersLegend And *Marker\Legend <> "" VectorFont(FontID(PBMap\Font), 13) - ;dessin d'un cadre avec fond transparent + ; dessin d'un cadre avec fond transparent Protected Height = VectorParagraphHeight(*Marker\Legend, 100, 100) Protected Width.l If Height < 20 ; une ligne @@ -1832,7 +1861,7 @@ Module PBMap Protected NW.Coordinates, SE.Coordinates PBMap\Dirty = #False PBMap\Redraw = #False - ;*** Precalc some values + ; *** Precalc some values *Drawing\RadiusX = GadgetWidth(PBMap\Gadget) / 2 *Drawing\RadiusY = GadgetHeight(PBMap\Gadget) / 2 *Drawing\GeographicCoordinates\Latitude = PBMap\GeographicCoordinates\Latitude @@ -1842,10 +1871,10 @@ Module PBMap ; Pixel shift, aka position in the tile Px = *Drawing\TileCoordinates\x Py = *Drawing\TileCoordinates\y - *Drawing\DeltaX = Px * ts - (Int(Px) * ts) ;Don't forget the Int() ! + *Drawing\DeltaX = Px * ts - (Int(Px) * ts) ; Don't forget the Int() ! *Drawing\DeltaY = Py * ts - (Int(Py) * ts) - ;Drawing boundaries - nx = *Drawing\RadiusX / ts ;How many tiles around the point + ; Drawing boundaries + nx = *Drawing\RadiusX / ts ; How many tiles around the point ny = *Drawing\RadiusY / ts NW\x = Px - nx - 1 NW\y = Py - ny - 1 @@ -1853,17 +1882,17 @@ Module PBMap SE\y = Py + ny + 2 TileXY2LatLon(@NW, *Drawing\Bounds\NorthWest, PBMap\Zoom) TileXY2LatLon(@SE, *Drawing\Bounds\SouthEast, PBMap\Zoom) - ;*Drawing\Width = (SE\x / Pow(2, PBMap\Zoom) * 360.0) - (NW\x / Pow(2, PBMap\Zoom) * 360.0) ;Calculus without clipping - ;*Drawing\Height = *Drawing\Bounds\NorthWest\Latitude - *Drawing\Bounds\SouthEast\Latitude - ;*** + ; *Drawing\Width = (SE\x / Pow(2, PBMap\Zoom) * 360.0) - (NW\x / Pow(2, PBMap\Zoom) * 360.0) ; Calculus without clipping + ; *Drawing\Height = *Drawing\Bounds\NorthWest\Latitude - *Drawing\Bounds\SouthEast\Latitude + ; *** ; Main drawing stuff StartVectorDrawing(CanvasVectorOutput(PBMap\Gadget)) - ;Clearscreen + ; Clearscreen VectorSourceColor(RGBA(150, 150, 150, 255)) FillVectorOutput() - ;TODO add in layers of tiles ;this way we can cache them as 0 base 1.n layers + ; TODO add in layers of tiles ; this way we can cache them as 0 base 1.n layers ; such as for openseamap tiles which are overlaid. not that efficent from here though. - ;Draws layers based on their number + ; Draws layers based on their number ForEach PBMap\LayersList() If PBMap\LayersList()\Enabled DrawTiles(*Drawing, PBMap\LayersList()\Name) @@ -1893,7 +1922,7 @@ Module PBMap Procedure Refresh() PBMap\Redraw = #True - ;Drawing() + ; Drawing() EndProcedure ;-*** Misc functions @@ -1901,7 +1930,7 @@ Module PBMap Procedure.d GetMouseLongitude() Protected MouseX.d = (PBMap\PixelCoordinates\x - PBMap\Drawing\RadiusX + GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_MouseX)) / PBMap\TileSize 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 EndProcedure @@ -1946,26 +1975,26 @@ Module PBMap EndProcedure Procedure SetZoomToArea(MinY.d, MaxY.d, MinX.d, MaxX.d) - ;Source => http://gis.stackexchange.com/questions/19632/how-to-calculate-the-optimal-zoom-level-to-display-two-or-more-points-on-a-map - ;bounding box in long/lat coords (x=long, y=lat) - Protected DeltaX.d = MaxX - MinX ;assumption ! In original code DeltaX have no source + ; Source => http://gis.stackexchange.com/questions/19632/how-to-calculate-the-optimal-zoom-level-to-display-two-or-more-points-on-a-map + ; bounding box in long/lat coords (x=long, y=lat) + Protected DeltaX.d = MaxX - MinX ; assumption ! In original code DeltaX have no source Protected centerX.d = MinX + DeltaX / 2 ; assumption ! In original code CenterX have no source - Protected paddingFactor.f= 1.2 ;paddingFactor: this can be used to get the "120%" effect ThomM refers to. Value of 1.2 would get you the 120%. + Protected paddingFactor.f= 1.2 ; paddingFactor: this can be used to get the "120%" effect ThomM refers to. Value of 1.2 would get you the 120%. Protected ry1.d = Log((Sin(Radian(MinY)) + 1) / Cos(Radian(MinY))) Protected ry2.d = Log((Sin(Radian(MaxY)) + 1) / Cos(Radian(MaxY))) Protected ryc.d = (ry1 + ry2) / 2 Protected centerY.d = Degree(ATan(SinH(ryc))) Protected resolutionHorizontal.d = DeltaX / (PBMap\Drawing\RadiusX * 2) - Protected vy0.d = Log(Tan(#PI*(0.25 + centerY/360))); - Protected vy1.d = Log(Tan(#PI*(0.25 + MaxY/360))) ; - Protected viewHeightHalf.d = PBMap\Drawing\RadiusY ; + Protected vy0.d = Log(Tan(#PI*(0.25 + centerY/360))); + Protected vy1.d = Log(Tan(#PI*(0.25 + MaxY/360))) ; + Protected viewHeightHalf.d = PBMap\Drawing\RadiusY ; Protected zoomFactorPowered.d = viewHeightHalf / (40.7436654315252*(vy1 - vy0)) Protected resolutionVertical.d = 360.0 / (zoomFactorPowered * PBMap\TileSize) If resolutionHorizontal<>0 And resolutionVertical<>0 Protected resolution.d = Max(resolutionHorizontal, resolutionVertical)* paddingFactor Protected zoom.d = Log(360 / (resolution * PBMap\TileSize))/Log(2) - Protected lon.d = centerX; - Protected lat.d = centerY; + Protected lon.d = centerX; + Protected lat.d = centerY; SetLocation(lat, lon, Round(zoom,#PB_Round_Down)) Else SetLocation(PBMap\GeographicCoordinates\Latitude, PBMap\GeographicCoordinates\Longitude, 15) @@ -2038,7 +2067,7 @@ Module PBMap Procedure SetMapScaleUnit(ScaleUnit.i = PBMAP::#SCALE_KM) PBMap\Options\ScaleUnit = ScaleUnit PBMap\Redraw = #True - ;Drawing() + ; Drawing() EndProcedure ; User mode @@ -2054,9 +2083,9 @@ Module PBMap ProcedureReturn PBMap\Mode EndProcedure - ;Zoom on x, y pixel position from the center + ; Zoom on x, y pixel position from the center Procedure SetZoomOnPixel(x, y, zoom) - ;*** First : Zoom + ; *** First : Zoom PBMap\Zoom + zoom If PBMap\Zoom > PBMap\ZoomMax : PBMap\Zoom = PBMap\ZoomMax : ProcedureReturn : EndIf If PBMap\Zoom < PBMap\ZoomMin : PBMap\Zoom = PBMap\ZoomMin : ProcedureReturn : EndIf @@ -2077,12 +2106,12 @@ Module PBMap EndIf EndProcedure - ;Zoom on x, y position relative to the canvas gadget + ; Zoom on x, y position relative to the canvas gadget Procedure SetZoomOnPixelRel(x, y, zoom) SetZoomOnPixel(x - PBMap\Drawing\RadiusX, y - PBMap\Drawing\RadiusY, zoom) EndProcedure - ;Go to x, y position relative to the canvas gadget left up + ; Go to x, y position relative to the canvas gadget left up Procedure GotoPixelRel(x, y) LatLon2Pixel(@PBMap\GeographicCoordinates, @PBMap\PixelCoordinates, PBMap\Zoom) PBMap\PixelCoordinates\x + x - PBMap\Drawing\RadiusX @@ -2096,7 +2125,7 @@ Module PBMap EndIf EndProcedure - ;Go to x, y position relative to the canvas gadget + ; Go to x, y position relative to the canvas gadget Procedure GotoPixel(x, y) PBMap\PixelCoordinates\x = x PBMap\PixelCoordinates\y = y @@ -2131,16 +2160,16 @@ Module PBMap URLEncoder(Address) + "?format=json&addressdetails=0&polygon=0&limit=1" Protected JSONFileName.s = PBMap\Options\HDDCachePath + "nominatimresponse.json" - ; Protected *Buffer = CurlReceiveHTTPToMemory("http://nominatim.openstreetmap.org/search/Unter%20den%20Linden%201%20Berlin?format=json&addressdetails=1&limit=1&polygon_svg=1", PBMap\Options\ProxyURL, PBMap\Options\ProxyPort, PBMap\Options\ProxyUser, PBMap\Options\ProxyPassword) - ; Debug *Buffer - ; Debug MemorySize(*Buffer) - ; Protected JSon.s = PeekS(*Buffer, MemorySize(*Buffer), #PB_UTF8) + ; Protected *Buffer = CurlReceiveHTTPToMemory("http://nominatim.openstreetmap.org/search/Unter%20den%20Linden%201%20Berlin?format=json&addressdetails=1&limit=1&polygon_svg=1", PBMap\Options\ProxyURL, PBMap\Options\ProxyPort, PBMap\Options\ProxyUser, PBMap\Options\ProxyPassword) + ; Debug *Buffer + ; Debug MemorySize(*Buffer) + ; Protected JSon.s = PeekS(*Buffer, MemorySize(*Buffer), #PB_UTF8) If PBMap\Options\Proxy HTTPProxy(PBMap\Options\ProxyURL + ":" + PBMap\Options\ProxyPort, PBMap\Options\ProxyUser, PBMap\Options\ProxyPassword) EndIf Size = ReceiveHTTPFile(Query, JSONFileName) If LoadJSON(0, JSONFileName) = 0 - ;Demivec's code + ; Demivec's code MyDebug( JSONErrorMessage() + " at position " + JSONErrorPosition() + " in line " + JSONErrorLine() + " of JSON web Data", 1) @@ -2160,7 +2189,7 @@ Module PBMap EndIf If lat <> "" And lon <> "" SetZoomToArea(bbox\SouthEast\Latitude, bbox\NorthWest\Latitude, bbox\NorthWest\Longitude, bbox\SouthEast\Longitude) - ;SetLocation(Position\Latitude, Position\Longitude) + ; SetLocation(Position\Latitude, Position\Longitude) EndIf EndIf EndProcedure @@ -2193,11 +2222,11 @@ Module PBMap CanvasMouseX = GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_MouseX) - PBMap\Drawing\RadiusX CanvasMouseY = GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_MouseY) - PBMap\Drawing\RadiusY ; rotation wip - ; StartVectorDrawing(CanvasVectorOutput(PBMap\Gadget)) - ; RotateCoordinates(0, 0, PBMap\Angle) - ; CanvasMouseX = ConvertCoordinateX(MouseX, MouseY, #PB_Coordinate_Device, #PB_Coordinate_User) - ; CanvasMouseY = ConvertCoordinateY(MouseX, MouseY, #PB_Coordinate_Device, #PB_Coordinate_User) - ; StopVectorDrawing() + ; StartVectorDrawing(CanvasVectorOutput(PBMap\Gadget)) + ; RotateCoordinates(0, 0, PBMap\Angle) + ; CanvasMouseX = ConvertCoordinateX(MouseX, MouseY, #PB_Coordinate_Device, #PB_Coordinate_User) + ; CanvasMouseY = ConvertCoordinateY(MouseX, MouseY, #PB_Coordinate_Device, #PB_Coordinate_User) + ; StopVectorDrawing() Select EventType() Case #PB_EventType_Focus PBMap\Drawing\RadiusX = GadgetWidth(PBMap\Gadget) / 2 @@ -2249,19 +2278,19 @@ Module PBMap LatLon2Pixel(@PBMap\GeographicCoordinates, @PBMap\PixelCoordinates, PBMap\Zoom) MouseX = PBMap\PixelCoordinates\x + CanvasMouseX MouseY = PBMap\PixelCoordinates\y + CanvasMouseY - ;Clip MouseX to the map range (in X, the map is infinite) + ; Clip MouseX to the map range (in X, the map is infinite) MouseX = Mod(Mod(MouseX, MapWidth) + MapWidth, MapWidth) Touch = #False - ;Check if the mouse touch a marker + ; Check if the mouse touch a marker ForEach PBMap\Markers() LatLon2Pixel(@PBMap\Markers()\GeographicCoordinates, @MarkerCoords, PBMap\Zoom) If Distance(MarkerCoords\x, MarkerCoords\y, MouseX, MouseY) < 8 If PBMap\Mode = #MODE_DEFAULT Or PBMap\Mode = #MODE_SELECT - ;Jump to the marker + ; Jump to the marker Touch = #True SetLocation(PBMap\Markers()\GeographicCoordinates\Latitude, PBMap\Markers()\GeographicCoordinates\Longitude) ElseIf PBMap\Mode = #MODE_EDIT - ;Edit the legend + ; Edit the legend MarkerEdit(@PBMap\Markers()) EndIf Break @@ -2272,37 +2301,37 @@ Module PBMap EndIf Case #PB_EventType_MouseWheel If PBMap\Options\WheelMouseRelative - ;Relative zoom (centered on the mouse) + ; Relative zoom (centered on the mouse) SetZoomOnPixel(CanvasMouseX, CanvasMouseY, GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_WheelDelta)) Else - ;Absolute zoom (centered on the center of the map) + ; Absolute zoom (centered on the center of the map) SetZoom(GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_WheelDelta), #PB_Relative) EndIf Case #PB_EventType_LeftButtonDown - ;LatLon2Pixel(@PBMap\GeographicCoordinates, @PBMap\PixelCoordinates, PBMap\Zoom) + ; LatLon2Pixel(@PBMap\GeographicCoordinates, @PBMap\PixelCoordinates, PBMap\Zoom) PBMap\Dragging = #True - ;Mem cursor Coord + ; Memorize cursor Coord PBMap\MoveStartingPoint\x = CanvasMouseX PBMap\MoveStartingPoint\y = CanvasMouseY - ;Clip MouseX to the map range (in X, the map is infinite) + ; Clip MouseX to the map range (in X, the map is infinite) PBMap\MoveStartingPoint\x = Mod(Mod(PBMap\MoveStartingPoint\x, MapWidth) + MapWidth, MapWidth) If PBMap\Mode = #MODE_DEFAULT Or PBMap\Mode = #MODE_SELECT PBMap\EditMarker = #False - ;Check if we select marker(s) + ; Check if we select marker(s) ForEach PBMap\Markers() If CtrlKey = #False - PBMap\Markers()\Selected = #False ;If no CTRL key, deselect everything and select only the focused marker + PBMap\Markers()\Selected = #False ; If no CTRL key, deselect everything and select only the focused marker EndIf If PBMap\Markers()\Focus PBMap\Markers()\Selected = #True - PBMap\EditMarker = #True;ListIndex(PBMap\Markers()) + PBMap\EditMarker = #True; ListIndex(PBMap\Markers()) PBMap\Markers()\Focus = #False EndIf Next - ;Check if we select track(s) + ; Check if we select track(s) ForEach PBMap\TracksList() If CtrlKey = #False - PBMap\TracksList()\Selected = #False ;If no CTRL key, deselect everything and select only the focused track + PBMap\TracksList()\Selected = #False ; If no CTRL key, deselect everything and select only the focused track EndIf If PBMap\TracksList()\Focus PBMap\TracksList()\Selected = #True @@ -2313,12 +2342,12 @@ Module PBMap Case #PB_EventType_MouseMove ; Drag If PBMap\Dragging - ; If PBMap\MoveStartingPoint\x <> - 1 + ; If PBMap\MoveStartingPoint\x <> - 1 MouseX = CanvasMouseX - PBMap\MoveStartingPoint\x MouseY = CanvasMouseY - PBMap\MoveStartingPoint\y PBMap\MoveStartingPoint\x = CanvasMouseX PBMap\MoveStartingPoint\y = CanvasMouseY - ;Move selected markers + ; Move selected markers If PBMap\EditMarker And (PBMap\Mode = #MODE_DEFAULT Or PBMap\Mode = #MODE_SELECT) ForEach PBMap\Markers() If PBMap\Markers()\Selected @@ -2329,14 +2358,14 @@ Module PBMap EndIf Next ElseIf PBMap\Mode = #MODE_DEFAULT Or PBMap\Mode = #MODE_HAND - ;Move map only - LatLon2Pixel(@PBMap\GeographicCoordinates, @PBMap\PixelCoordinates, PBMap\Zoom) ;This line could be removed as the coordinates don't have to change but I want to be sure we rely only on geographic coordinates + ; Move map only + LatLon2Pixel(@PBMap\GeographicCoordinates, @PBMap\PixelCoordinates, PBMap\Zoom) ; This line could be removed as the coordinates don't have to change but I want to be sure we rely only on geographic coordinates PBMap\PixelCoordinates\x - MouseX - ;Ensures that pixel position stay in the range [0..2^Zoom*PBMap\TileSize[ coz of the wrapping of the map + ; Ensures that pixel position stay in the range [0..2^Zoom*PBMap\TileSize[ coz of the wrapping of the map PBMap\PixelCoordinates\x = Mod(Mod(PBMap\PixelCoordinates\x, MapWidth) + MapWidth, MapWidth) PBMap\PixelCoordinates\y - MouseY Pixel2LatLon(@PBMap\PixelCoordinates, @PBMap\GeographicCoordinates, PBMap\Zoom) - ;If CallBackLocation send Location to function + ; If CallBackLocation send Location to function If PBMap\CallBackLocation > 0 CallFunctionFast(PBMap\CallBackLocation, @PBMap\GeographicCoordinates) EndIf @@ -2347,30 +2376,30 @@ Module PBMap LatLon2Pixel(@PBMap\GeographicCoordinates, @PBMap\PixelCoordinates, PBMap\Zoom) MouseX = PBMap\PixelCoordinates\x + CanvasMouseX MouseY = PBMap\PixelCoordinates\y + CanvasMouseY - ;Clip MouseX to the map range (in X, the map is infinite) + ; Clip MouseX to the map range (in X, the map is infinite) MouseX = Mod(Mod(MouseX, MapWidth) + MapWidth, MapWidth) If PBMap\Mode = #MODE_DEFAULT Or PBMap\Mode = #MODE_SELECT Or PBMap\Mode = #MODE_EDIT - ;Check if mouse touch markers + ; Check if mouse touch markers ForEach PBMap\Markers() LatLon2Pixel(@PBMap\Markers()\GeographicCoordinates, @MarkerCoords, PBMap\Zoom) If Distance(MarkerCoords\x, MarkerCoords\y, MouseX, MouseY) < 8 PBMap\Markers()\Focus = #True PBMap\Redraw = #True ElseIf PBMap\Markers()\Focus - ;If CtrlKey = #False + ; If CtrlKey = #False PBMap\Markers()\Focus = #False PBMap\Redraw = #True EndIf Next - ;Check if mouse touch tracks + ; Check if mouse touch tracks With PBMap\TracksList() - ;Trace Track + ; Trace Track If ListSize(PBMap\TracksList()) > 0 ForEach PBMap\TracksList() If ListSize(\Track()) > 0 If \Visible StartVectorDrawing(CanvasVectorOutput(PBMap\Gadget)) - ;Simulates track drawing + ; Simulates track drawing ForEach \Track() LatLon2Pixel(@PBMap\TracksList()\Track(), @Pixel, PBMap\Zoom) If ListIndex(\Track()) = 0 @@ -2395,7 +2424,7 @@ Module PBMap EndIf EndIf Case #PB_EventType_LeftButtonUp - ; PBMap\MoveStartingPoint\x = - 1 + ; PBMap\MoveStartingPoint\x = - 1 PBMap\Dragging = #False PBMap\Redraw = #True Case #PB_MAP_REDRAW @@ -2408,7 +2437,11 @@ Module PBMap *Tile = EventData() key = *Tile\key ; After a Web tile loading thread, clean the tile structure memory and set the image nb in the cache - ; avoid to have threads accessing vars (and avoid mutex), see GetImageThread() + ; avoid to have threads accessing vars (and avoid some mutex), see GetImageThread() + *Tile\Download = 0 + LockMutex(PBMap\DownloadSlotsMutex) + PBMap\DownloadSlots - 1 + UnlockMutex(PBMap\DownloadSlotsMutex) Protected timg = PBMap\MemCache\Images(key)\Tile\nImage ; Get this new tile image nb PBMap\MemCache\Images(key)\nImage = timg ; Stores it in the cache using the key FreeMemory(PBMap\MemCache\Images(key)\Tile) ; Frees the data needed for the thread @@ -2421,7 +2454,7 @@ Module PBMap ; Redraws at regular intervals Procedure TimerEvents() If EventTimer() = PBMap\Timer And (PBMap\Redraw Or PBMap\Dirty) - MemoryCacheManagement() + ; MemoryCacheManagement() Drawing() EndIf EndProcedure @@ -2439,7 +2472,7 @@ Module PBMap ; Creates a canvas and attach our map Procedure MapGadget(Gadget.i, X.i, Y.i, Width.i, Height.i) If Gadget = #PB_Any - PBMap\Gadget = CanvasGadget(PBMap\Gadget, X, Y, Width, Height, #PB_Canvas_Keyboard) ;#PB_Canvas_Keyboard has to be set for mousewheel to work on windows + PBMap\Gadget = CanvasGadget(PBMap\Gadget, X, Y, Width, Height, #PB_Canvas_Keyboard) ; #PB_Canvas_Keyboard has to be set for mousewheel to work on windows Else PBMap\Gadget = Gadget CanvasGadget(PBMap\Gadget, X, Y, Width, Height, #PB_Canvas_Keyboard) @@ -2450,14 +2483,14 @@ Module PBMap Procedure Quit() PBMap\Drawing\End = #True PBMap\MemoryCacheManagement = #True ; Tells web loading threads to pause - ;Wait for loading threads to finish nicely. Passed 2 seconds, kills them. + ; Wait for loading threads to finish nicely. Passed 2 seconds, kills them. Protected TimeCounter = ElapsedMilliseconds() Repeat ForEach PBMap\MemCache\Images() If PBMap\MemCache\Images()\Tile <> 0 If IsThread(PBMap\MemCache\Images()\Tile\GetImageThread) If ElapsedMilliseconds() - TimeCounter > 2000 - ;Should not occur + ; Should not occur KillThread(PBMap\MemCache\Images()\Tile\GetImageThread) EndIf Else @@ -2484,6 +2517,11 @@ Module PBMap PBMap\Window = Window PBMap\Timer = 1 PBMap\Mode = #MODE_DEFAULT + PBMap\DownloadSlotsMutex = CreateMutex() + If PBMap\DownloadSlotsMutex = #False + MyDebug("Cannot create a mutex", 0) + End + EndIf LoadOptions() TechnicalImagesCreation() SetLocation(0, 0) @@ -2491,11 +2529,11 @@ Module PBMap EndModule -;**************************************************************** -; +; **************************************************************** +; ;- Example of application -; -;**************************************************************** +; +; **************************************************************** CompilerIf #PB_Compiler_IsMainFile InitNetwork() @@ -2507,8 +2545,8 @@ CompilerIf #PB_Compiler_IsMainFile #Gdt_Right #Gdt_Up #Gdt_Down - ;#Gdt_RotateLeft - ;#Gdt_RotateRight + ; #Gdt_RotateLeft + ; #Gdt_RotateRight #Button_4 #Button_5 #Combo_0 @@ -2532,7 +2570,7 @@ CompilerIf #PB_Compiler_IsMainFile #StringGeoLocationQuery EndEnumeration - ;Menu events + ; Menu events Enumeration #MenuEventLonLatStringEnter #MenuEventGeoLocationStringEnter @@ -2549,7 +2587,7 @@ CompilerIf #PB_Compiler_IsMainFile ProcedureReturn 0 EndProcedure - ;This callback demonstration procedure will receive relative coords from canvas + ; This callback demonstration procedure will receive relative coords from canvas Procedure MyMarker(x.i, y.i, Focus = #False, Selected = #False) Protected color = RGBA(0, 255, 0, 255) MovePathCursor(x, y) @@ -2580,8 +2618,8 @@ CompilerIf #PB_Compiler_IsMainFile ResizeGadget(#Text_1,WindowWidth(#Window_0)-170,#PB_Ignore,#PB_Ignore,#PB_Ignore) ResizeGadget(#Gdt_Left, WindowWidth(#Window_0) - 150 ,#PB_Ignore,#PB_Ignore,#PB_Ignore) ResizeGadget(#Gdt_Right,WindowWidth(#Window_0) - 90 ,#PB_Ignore,#PB_Ignore,#PB_Ignore) - ;ResizeGadget(#Gdt_RotateLeft, WindowWidth(#Window_0) - 150 ,#PB_Ignore,#PB_Ignore,#PB_Ignore) - ;ResizeGadget(#Gdt_RotateRight,WindowWidth(#Window_0) - 90 ,#PB_Ignore,#PB_Ignore,#PB_Ignore) + ; ResizeGadget(#Gdt_RotateLeft, WindowWidth(#Window_0) - 150 ,#PB_Ignore,#PB_Ignore,#PB_Ignore) + ; ResizeGadget(#Gdt_RotateRight,WindowWidth(#Window_0) - 90 ,#PB_Ignore,#PB_Ignore,#PB_Ignore) ResizeGadget(#Gdt_Up, WindowWidth(#Window_0) - 120 ,#PB_Ignore,#PB_Ignore,#PB_Ignore) ResizeGadget(#Gdt_Down, WindowWidth(#Window_0) - 120 ,#PB_Ignore,#PB_Ignore,#PB_Ignore) ResizeGadget(#Text_2,WindowWidth(#Window_0)-170,#PB_Ignore,#PB_Ignore,#PB_Ignore) @@ -2613,8 +2651,8 @@ CompilerIf #PB_Compiler_IsMainFile LoadFont(2, "Arial", 8) TextGadget(#Text_1, 530, 10, 60, 15, "Movements") - ;ButtonGadget(#Gdt_RotateLeft, 550, 070, 30, 30, "LRot") : SetGadgetFont(#Gdt_RotateLeft, FontID(2)) - ;ButtonGadget(#Gdt_RotateRight, 610, 070, 30, 30, "RRot") : SetGadgetFont(#Gdt_RotateRight, FontID(2)) + ; ButtonGadget(#Gdt_RotateLeft, 550, 070, 30, 30, "LRot") : SetGadgetFont(#Gdt_RotateLeft, FontID(2)) + ; ButtonGadget(#Gdt_RotateRight, 610, 070, 30, 30, "RRot") : SetGadgetFont(#Gdt_RotateRight, FontID(2)) ButtonGadget(#Gdt_Left, 550, 60, 30, 30, Chr($25C4)) : SetGadgetFont(#Gdt_Left, FontID(0)) ButtonGadget(#Gdt_Right, 610, 60, 30, 30, Chr($25BA)) : SetGadgetFont(#Gdt_Right, FontID(0)) ButtonGadget(#Gdt_Up, 580, 030, 30, 30, Chr($25B2)) : SetGadgetFont(#Gdt_Up, FontID(0)) @@ -2639,20 +2677,20 @@ CompilerIf #PB_Compiler_IsMainFile StringGadget(#StringGeoLocationQuery, 530, 530, 150, 20, "") SetActiveGadget(#StringGeoLocationQuery) AddKeyboardShortcut(#Window_0, #PB_Shortcut_Return, #MenuEventGeoLocationStringEnter) - ;*** TODO : code to remove when the SetActiveGadget(-1) will be fixed + ; *** TODO : code to remove when the SetActiveGadget(-1) will be fixed CompilerIf #PB_Compiler_OS = #PB_OS_Linux Define Dummy = ButtonGadget(#PB_Any, 0, 0, 1, 1, "Dummy") HideGadget(Dummy, 1) CompilerElse Define Dummy = -1 CompilerEndIf - ;*** + ; *** Define Event.i, Gadget.i, Quit.b = #False Define pfValue.d Define Degrees = 1 Define *Track - ;Our main gadget + ; Our main gadget PBMap::InitPBMap(#Window_0) PBMap::SetOption("ShowDegrees", "1") : Degrees = 0 PBMap::SetOption("ShowDebugInfos", "1") @@ -2673,7 +2711,7 @@ CompilerIf #PB_Compiler_IsMainFile Event = WaitWindowEvent() Select Event Case #PB_Event_CloseWindow : Quit = 1 - Case #PB_Event_Gadget ;{ + Case #PB_Event_Gadget ; { Gadget = EventGadget() Select Gadget Case #Gdt_Up @@ -2684,12 +2722,12 @@ CompilerIf #PB_Compiler_IsMainFile PBMap::SetLocation(0, 10* -360 / Pow(2, PBMap::GetZoom() + 8), 0, #PB_Relative) Case #Gdt_Right PBMap::SetLocation(0, 10* 360 / Pow(2, PBMap::GetZoom() + 8), 0, #PB_Relative) - ;Case #Gdt_RotateLeft - ; PBMAP::SetAngle(-5,#PB_Relative) - ; PBMap::Refresh() - ;Case #Gdt_RotateRight - ; PBMAP::SetAngle(5,#PB_Relative) - ; PBMap::Refresh() + ; Case #Gdt_RotateLeft + ; PBMAP::SetAngle(-5,#PB_Relative) + ; PBMap::Refresh() + ; Case #Gdt_RotateRight + ; PBMAP::SetAngle(5,#PB_Relative) + ; PBMap::Refresh() Case #Button_4 PBMap::SetZoom(1) Case #Button_5 @@ -2776,16 +2814,16 @@ CompilerIf #PB_Compiler_IsMainFile Case #PB_Event_SizeWindow ResizeAll() Case #PB_Event_Menu - ;Receive "enter" key events + ; Receive "enter" key events Select EventMenu() Case #MenuEventGeoLocationStringEnter If GetGadgetText(#StringGeoLocationQuery) <> "" PBMap::NominatimGeoLocationQuery(GetGadgetText(#StringGeoLocationQuery)) PBMap::Refresh() EndIf - ;*** TODO : code to change when the SetActiveGadget(-1) will be fixed + ; *** TODO : code to change when the SetActiveGadget(-1) will be fixed SetActiveGadget(Dummy) - ;*** + ; *** Case #MenuEventLonLatStringEnter PBMap::SetLocation(ValD(GetGadgetText(#StringLatitude)), ValD(GetGadgetText(#StringLongitude))) ; Change the PBMap coordinates PBMap::Refresh() @@ -2799,8 +2837,8 @@ CompilerIf #PB_Compiler_IsMainFile CompilerEndIf ; IDE Options = PureBasic 5.60 (Windows - x64) -; CursorPosition = 893 -; FirstLine = 894 +; CursorPosition = 1162 +; FirstLine = 1143 ; Folding = ------------------- ; EnableThread ; EnableXP