From b108b8b3859c9f1bf201b2b6fe05d0cfce4db105 Mon Sep 17 00:00:00 2001 From: thyphoonfr Date: Sun, 22 Aug 2021 14:48:55 +0200 Subject: [PATCH] DPI Aware Add compatible with DPI Scaling (4k screen) --- PBMap.pb | 2217 ++++++++++++++++++++++++++---------------------------- 1 file changed, 1067 insertions(+), 1150 deletions(-) diff --git a/PBMap.pb b/PBMap.pb index 987c1fd..4a4eff9 100644 --- a/PBMap.pb +++ b/PBMap.pb @@ -1,18 +1,41 @@ -; ******************************************************************** +; ******************************************************************** ; Program: PBMap ; Description: Permits the use of tiled maps like ; OpenStreetMap in a handy PureBASIC module ; Author: Thyphoon, djes, Idle, yves86 -; Date: July, 2017 +; Date: Jan, 2021 ; License: PBMap : Free, unrestricted, credit ; appreciated but not required. ; OSM : see http://www.openstreetmap.org/copyright ; Note: Please share improvement ! -; Thanks: Progi1984 +; Thanks: Progi1984, falsam +; HowToRun: Include this code +; ******************************************************************** +; +; 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 - 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 CompilerEndIf @@ -28,6 +51,10 @@ UseJPEGImageEncoder() DeclareModule PBMap + #PBMAPNAME = "PBMap" + #PBMAPVERSION = "0.91" + #USERAGENT = #PBMAPNAME + "/" + #PBMAPVERSION + " (https://github.com/djes/PBMap)" + CompilerIf #PB_Compiler_OS = #PB_OS_Linux #Red = 255 CompilerEndIf @@ -53,10 +80,10 @@ DeclareModule PBMap EndStructure Structure Marker - GeographicCoordinates.GeographicCoordinates ; Marker latitude and longitude + GeographicCoordinates.GeographicCoordinates ; Marker's latitude and longitude Identifier.s Legend.s - Color.l ; Marker color + Color.l ; Marker's color Focus.i Selected.i ; Is the marker selected ? CallBackPointer.i ; @Procedure(X.i, Y.i) to DrawPointer (you must use VectorDrawing lib) @@ -64,58 +91,60 @@ DeclareModule PBMap EndStructure ;*** - Declare InitPBMap(window) - Declare SetDebugLevel(level.i) - Declare SetOption(Option.s, Value.s) - Declare.s GetOption(Option.s) - Declare LoadOptions(PreferencesFile.s = "PBMap.prefs") - Declare SaveOptions(PreferencesFile.s = "PBMap.prefs") - Declare.i AddOSMServerLayer(LayerName.s, Order.i, ServerURL.s = "http://tile.openstreetmap.org/") - Declare.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 = "") - Declare.i AddGeoServerLayer(LayerName.s, Order.i, ServerLayerName.s, ServerURL.s = "http://localhost:8080/", path.s = "geowebcache/service/gmaps", format.s = "image/png") - Declare IsLayer(Name.s) - Declare DeleteLayer(Name.s) - Declare EnableLayer(Name.s) - Declare DisableLayer(Name.s) - Declare SetLayerAlpha(Name.s, Alpha.d) - Declare.d GetLayerAlpha(Name.s) - Declare BindMapGadget(Gadget.i) - Declare SetCallBackLocation(*CallBackLocation) - Declare SetCallBackMainPointer(CallBackMainPointer.i) - Declare MapGadget(Gadget.i, X.i, Y.i, Width.i, Height.i) - Declare.d GetLatitude() - Declare.d GetLongitude() - Declare.d GetMouseLatitude() - Declare.d GetMouseLongitude() - Declare.d GetAngle() - Declare.i GetZoom() - Declare.i GetMode() - Declare SetMode(Mode.i = #MODE_DEFAULT) - Declare SetMapScaleUnit(ScaleUnit=PBMAP::#SCALE_KM) - Declare SetLocation(latitude.d, longitude.d, Zoom = -1, mode.i = #PB_Absolute) - Declare SetAngle(Angle.d, Mode = #PB_Absolute) - 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 ClearTracks() - Declare DeleteTrack(*Ptr) - Declare DeleteSelectedTracks() - Declare SetTrackColour(*Ptr, Colour.i) - Declare.i AddMarker(Latitude.d, Longitude.d, Identifier.s = "", Legend.s = "", color.l=-1, CallBackPointer.i = -1) - Declare ClearMarkers() - Declare DeleteMarker(*Ptr) - Declare DeleteSelectedMarkers() - Declare Drawing() - Declare Quit() - Declare FatalError(msg.s) - Declare Error(msg.s) - Declare Refresh() - Declare.i ClearDiskCache() - Declare SetCallBackMarker(*CallBackLocation) - Declare SetCallBackLeftClic(*CallBackLocation) + ;Declare SelectPBMap(Gadget.i) ; Could be used to have multiple PBMaps in one window + Declare SetDebugLevel(Level.i) + Declare SetOption(MapGadget.i, Option.s, Value.s) + Declare.s GetOption(MapGadget.i, Option.s) + Declare LoadOptions(MapGadget.i, PreferencesFile.s = "PBMap.prefs") + Declare SaveOptions(MapGadget.i, PreferencesFile.s = "PBMap.prefs") + Declare.i AddOSMServerLayer(MapGadget.i, LayerName.s, Order.i, ServerURL.s = "http://tile.openstreetmap.org/") + Declare.i AddHereServerLayer(MapGadget.i, 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 = "") + Declare.i AddGeoServerLayer(MapGadget.i, LayerName.s, Order.i, ServerLayerName.s, ServerURL.s = "http://localhost:8080/", path.s = "geowebcache/service/gmaps", format.s = "image/png") + Declare IsLayer(MapGadget.i, Name.s) + Declare DeleteLayer(MapGadget.i, Name.s) + Declare EnableLayer(MapGadget.i, Name.s) + Declare DisableLayer(MapGadget.i, Name.s) + Declare SetLayerAlpha(MapGadget.i, Name.s, Alpha.d) + Declare.d GetLayerAlpha(MapGadget.i, Name.s) + Declare BindMapGadget(MapGadget.i, TimerNB = 1, Window = -1) + Declare SetCallBackLocation(MapGadget.i, *CallBackLocation) + Declare SetCallBackMainPointer(MapGadget.i, CallBackMainPointer.i) + Declare SetCallBackDrawTile(MapGadget.i, *CallBackLocation) + Declare SetCallBackMarker(MapGadget.i, *CallBackLocation) + Declare SetCallBackLeftClic(MapGadget.i, *CallBackLocation) + Declare SetCallBackModifyTileFile(MapGadget.i, *CallBackLocation) + Declare.i MapGadget(MapGadget.i, X.i, Y.i, Width.i, Height.i, TimerNB = 1, Window = -1) ; Returns Gadget NB if #PB_Any is used for gadget + Declare FreeMapGadget(MapGadget.i) + Declare.d GetLatitude(MapGadget.i) + Declare.d GetLongitude(MapGadget.i) + Declare.d GetMouseLatitude(MapGadget.i) + Declare.d GetMouseLongitude(MapGadget.i) + Declare.d GetAngle(MapGadget.i) + Declare.i GetZoom(MapGadget.i) + Declare.i GetMode(MapGadget.i) + Declare SetMode(MapGadget.i, Mode.i = #MODE_DEFAULT) + Declare SetMapScaleUnit(MapGadget.i, ScaleUnit=PBMAP::#SCALE_KM) + Declare SetLocation(MapGadget.i, Latitude.d, Longitude.d, Zoom = -1, Mode.i = #PB_Absolute) + Declare SetAngle(MapGadget.i, Angle.d, Mode = #PB_Absolute) + Declare SetZoom(MapGadget.i, Zoom.i, Mode.i = #PB_Relative) + Declare SetZoomToArea(MapGadget.i, MinY.d, MaxY.d, MinX.d, MaxX.d) + Declare SetZoomToTracks(MapGadget.i, *Tracks) + Declare NominatimGeoLocationQuery(MapGadget.i, Address.s, *ReturnPosition = 0) ; Send back the position *ptr.GeographicCoordinates + Declare.i LoadGpxFile(MapGadget.i, FileName.s) ; + Declare.i SaveGpxFile(MapGadget.i, FileName.s, *Track) ; + Declare ClearTracks(MapGadget.i) + Declare DeleteTrack(MapGadget.i, *Ptr) + Declare DeleteSelectedTracks(MapGadget.i) + Declare SetTrackColour(MapGadget.i, *Ptr, Colour.i) + Declare.i AddMarker(MapGadget.i, Latitude.d, Longitude.d, Identifier.s = "", Legend.s = "", color.l=-1, CallBackPointer.i = -1) + Declare ClearMarkers(MapGadget.i) + Declare DeleteMarker(MapGadget.i, *Ptr) + Declare DeleteSelectedMarkers(MapGadget.i) + Declare Drawing(MapGadget.i) + Declare FatalError(MapGadget.i, msg.s) + Declare Error(MapGadget.i, msg.s) + Declare Refresh(MapGadget.i) + Declare.i ClearDiskCache(MapGadget.i) EndDeclareModule @@ -123,6 +152,11 @@ Module PBMap EnableExplicit + ;-*** Prototypes + + Prototype.i ProtoDrawTile(x.i, y.i, image.i, alpha.d = 1) + Prototype.s ProtoModifyTileFile(Filename.s, OriginalURL.s) + ;-*** Internal Structures Structure PixelCoordinates @@ -144,6 +178,8 @@ Module PBMap Download.i Time.i Size.i + Window.i ; Parent Window + Gadget.i EndStructure Structure BoundingBox @@ -278,10 +314,12 @@ Module PBMap GeographicCoordinates.GeographicCoordinates ; Latitude and Longitude from focus point Drawing.DrawingParameters ; Drawing parameters based on focus point - CallBackLocation.i ; @Procedure(latitude.d,lontitude.d) + CallBackLocation.i ; @Procedure(latitude.d, longitude.d) CallBackMainPointer.i ; @Procedure(X.i, Y.i) to DrawPointer (you must use VectorDrawing lib) - CallBackMarker.i ; @Procedure (latitude.d,lontitude.d) pour connaitre la nouvelle position du marqueur (YA) - CallBackLeftClic.i ; @Procdeure (latitude.d,lontitude.d) pour connaitre la position lors du clic gauche (YA) + CallBackMarker.i ; @Procedure (latitude.d, longitude.d) to know the marker position (YA) + CallBackLeftClic.i ; @Procedure (latitude.d, longitude.d) to know the position on left click (YA) + CallBackDrawTile.ProtoDrawTile ; @Procedure (x.i, y.i, nImage.i) to customise tile drawing + CallBackModifyTileFile.ProtoModifyTileFile ; @Procedure (Filename.s, Original URL) to customise image file => New Filename PixelCoordinates.PixelCoordinates ; Actual focus point coords in pixels (global) MoveStartingPoint.PixelCoordinates ; Start mouse position coords when dragging the map @@ -304,7 +342,7 @@ Module PBMap Dragging.i Dirty.i ; To signal that drawing need a refresh - MemoryCacheAccessMutex.i ; Memorycache access variable mutual exclusion + MemoryCacheAccessMutex.i ; Memorycache access variable mutual exclusion DownloadSlots.i ; Actual nb of used download slots List TracksList.Tracks() ; To display a GPX track @@ -323,7 +361,7 @@ Module PBMap ;-Show debug infos Global MyDebugLevel = 5 - Global PBMap.PBMap, Null.i, NullPtrMem.i, *NullPtr = @NullPtrMem + Global NewMap PBMaps() Global slash.s CompilerSelect #PB_Compiler_OS @@ -351,16 +389,18 @@ Module PBMap ;-Error management ; Shows an error msg and terminates the program - Procedure FatalError(msg.s) - If PBMap\Options\Warning + Procedure FatalError(MapGadget, msg.s) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + If *PBMap\Options\Warning MessageRequester("PBMap", msg, #PB_MessageRequester_Ok) EndIf End EndProcedure ; Shows an error msg - Procedure Error(msg.s) - If PBMap\Options\Warning + Procedure Error(MapGadget, msg.s) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + If *PBMap\Options\Warning MessageRequester("PBMap", msg, #PB_MessageRequester_Ok) EndIf EndProcedure @@ -371,8 +411,8 @@ Module PBMap EndProcedure ; 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 + Procedure MyDebug(*PBMap.PBMap, msg.s, DbgLevel = 0) ;Directly pass the PBMap structure (faster) + If *PBMap\Options\Verbose And DbgLevel <= MyDebugLevel PrintN(msg) ; Debug msg EndIf @@ -424,19 +464,20 @@ Module PBMap EndIf EndProcedure - Procedure TechnicalImagesCreation() + Procedure TechnicalImagesCreation(MapGadget.i) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) ; "Loading" image Protected LoadingText$ = "Loading" Protected NothingText$ = "Nothing" - PBmap\ImgLoading = CreateImage(#PB_Any, 256, 256) - If PBmap\ImgLoading - StartVectorDrawing(ImageVectorOutput(PBMap\Imgloading)) + *PBMap\ImgLoading = CreateImage(#PB_Any, 256, 256) + If *PBMap\ImgLoading + StartVectorDrawing(ImageVectorOutput(*PBMap\Imgloading)) BeginVectorLayer() VectorSourceColor(RGBA(255, 255, 255, 128)) AddPathBox(0, 0, 256, 256) FillPath() MovePathCursor(0, 0) - VectorFont(FontID(PBMap\StandardFont), 256 / 20) + VectorFont(FontID(*PBMap\StandardFont), 256 / 20) VectorSourceColor(RGBA(150, 150, 150, 255)) MovePathCursor(0 + (256 - VectorTextWidth(LoadingText$)) / 2, 0 + (256 - VectorTextHeight(LoadingText$)) / 2) DrawVectorText(LoadingText$) @@ -444,15 +485,15 @@ Module PBMap StopVectorDrawing() EndIf ; "Nothing" tile - PBmap\ImgNothing = CreateImage(#PB_Any, 256, 256) - If PBmap\ImgNothing - StartVectorDrawing(ImageVectorOutput(PBMap\ImgNothing)) + *PBMap\ImgNothing = CreateImage(#PB_Any, 256, 256) + If *PBMap\ImgNothing + StartVectorDrawing(ImageVectorOutput(*PBMap\ImgNothing)) ; BeginVectorLayer() VectorSourceColor(RGBA(220, 230, 255, 255)) AddPathBox(0, 0, 256, 256) FillPath() ; MovePathCursor(0, 0) - ; VectorFont(FontID(PBMap\StandardFont), 256 / 20) + ; VectorFont(FontID(*PBMap\StandardFont), 256 / 20) ; VectorSourceColor(RGBA(150, 150, 150, 255)) ; MovePathCursor(0 + (256 - VectorTextWidth(NothingText$)) / 2, 0 + (256 - VectorTextHeight(NothingText$)) / 2) ; DrawVectorText(NothingText$) @@ -474,8 +515,8 @@ Module PBMap 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(*PBMap, "Latitude : " + StrD(*Location\Latitude) + " ; Longitude : " + StrD(*Location\Longitude), 5) + ;MyDebug(*PBMap, "Coords X : " + Str(*Coords\x) + " ; Y : " + Str(*Coords\y), 5) EndProcedure ; *** Converts tile.decimal to coords @@ -493,37 +534,26 @@ Module PBMap EndIf EndProcedure - 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[ - *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[ 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 [ - Procedure LatLon2Pixel(*Location.GeographicCoordinates, *Pixel.PixelCoordinates, Zoom) - Protected tilemax = Pow(2.0, Zoom) * PBMap\TileSize + Procedure LatLon2Pixel(MapGadget.i, *Location.GeographicCoordinates, *Pixel.PixelCoordinates, Zoom) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + Protected tilemax = Pow(2.0, Zoom) * *PBMap\TileSize Protected LatRad.d = Radian(*Location\Latitude) *Pixel\x = tilemax * (Mod( *Location\Longitude + 180.0, 360) / 360.0 ) *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 - Procedure LatLon2PixelRel(*Location.GeographicCoordinates, *Pixel.PixelCoordinates, Zoom) - Protected tilemax = Pow(2.0, Zoom) * PBMap\TileSize - Protected cx.d = PBMap\Drawing\RadiusX - Protected dpx.d = PBMap\PixelCoordinates\x + Procedure LatLon2PixelRel(MapGadget.i, *Location.GeographicCoordinates, *Pixel.PixelCoordinates, Zoom) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + Protected tilemax = Pow(2.0, Zoom) * *PBMap\TileSize + Protected cx.d = *PBMap\Drawing\RadiusX + Protected dpx.d = *PBMap\PixelCoordinates\x 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 @@ -541,20 +571,40 @@ Module PBMap ; Debug "c0" *Pixel\x = cx + (px - dpx) EndIf - *Pixel\y = PBMap\Drawing\RadiusY + (py - PBMap\PixelCoordinates\y) + *Pixel\y = *PBMap\Drawing\RadiusY + (py - *PBMap\PixelCoordinates\y) EndProcedure - 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[ - ProcedureReturn Mod(Mod(NewX / n * 360.0, 360.0) + 360.0, 360.0) - 180 + 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 Pixel2Lat(y) - Protected NewY.d = (PBMap\PixelCoordinates\y - PBMap\Drawing\RadiusY + y) / PBMap\TileSize - Protected n.d = Pow(2.0, PBMap\Zoom) - ProcedureReturn Degree(ATan(SinH(#PI * (1.0 - 2.0 * NewY / n)))) + Procedure.d Pixel2Lon(MapGadget.i, x) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + Protected n.d = *PBMap\TileSize * Pow(2.0, *PBMap\Zoom) + ProcedureReturn Mod((1 + x / n) * 360.0, 360.0) - 180 + EndProcedure + + Procedure.d Pixel2Lat(MapGadget.i, y) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + Protected n.d = *PBMap\TileSize * Pow(2.0, *PBMap\Zoom) + Protected latitude.d = Degree(ATan(SinH(#PI * (1.0 - 2.0 * y / n)))) + If latitude <= -89 + latitude = -89 + EndIf + If latitude >= 89 + latitude = 89 + EndIf + ProcedureReturn latitude EndProcedure ; HaversineAlgorithm @@ -572,11 +622,12 @@ Module PBMap EndProcedure Procedure.d HaversineInM(*posA.GeographicCoordinates, *posB.GeographicCoordinates) - ProcedureReturn (1000 * HaversineInKM(@*posA,@*posB)); + ProcedureReturn (1000 * HaversineInKM(@*posA, @*posB)); EndProcedure ; No more used, see LatLon2PixelRel - Procedure GetPixelCoordFromLocation(*Location.GeographicCoordinates, *Pixel.PixelCoordinates, Zoom) ; TODO to Optimize + Procedure GetPixelCoordFromLocation(MapGadget.i, *Location.GeographicCoordinates, *Pixel.PixelCoordinates, Zoom) ; TODO to Optimize + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) Protected mapWidth.l = Pow(2, Zoom + 8) Protected mapHeight.l = Pow(2, Zoom + 8) Protected x1.l,y1.l @@ -586,18 +637,19 @@ Module PBMap 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) + 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)); - *Pixel\x=PBMap\Drawing\RadiusX - (x2-x1) - *Pixel\y=PBMap\Drawing\RadiusY - (y2-y1) + *Pixel\x=*PBMap\Drawing\RadiusX - (x2-x1) + *Pixel\y=*PBMap\Drawing\RadiusY - (y2-y1) EndProcedure - Procedure IsInDrawingPixelBoundaries(*Drawing.DrawingParameters, *Position.GeographicCoordinates) + Procedure IsInDrawingPixelBoundaries(MapGadget.i, *Drawing.DrawingParameters, *Position.GeographicCoordinates) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) Protected Pixel.PixelCoordinates - LatLon2PixelRel(*Position, @Pixel, PBMap\Zoom) + LatLon2PixelRel(MapGadget, *Position, @Pixel, *PBMap\Zoom) If Pixel\x >= 0 And Pixel\y >= 0 And Pixel\x < *Drawing\RadiusX * 2 And Pixel\y < *Drawing\RadiusY * 2 ProcedureReturn #True Else @@ -664,17 +716,18 @@ Module PBMap ;-*** Options - Procedure SetOptions() - With PBMap\Options + Procedure SetOptions(MapGadget.i) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + With *PBMap\Options If \Proxy - HTTPProxy(PBMap\Options\ProxyURL + ":" + PBMap\Options\ProxyPort, PBMap\Options\ProxyUser, PBMap\Options\ProxyPassword) + HTTPProxy(*PBMap\Options\ProxyURL + ":" + *PBMap\Options\ProxyPort, *PBMap\Options\ProxyUser, *PBMap\Options\ProxyPassword) EndIf If \Verbose OpenConsole() EndIf CreateDirectoryEx(\HDDCachePath) - If \DefaultOSMServer <> "" And IsLayer("OSM") = #False ; First time creation of the basis OSM layer - AddOSMServerLayer("OSM", 1, \DefaultOSMServer) + If \DefaultOSMServer <> "" And IsLayer(MapGadget, "OSM") = #False ; First time creation of the basis OSM layer + AddOSMServerLayer(MapGadget, "OSM", 1, \DefaultOSMServer) EndIf EndWith EndProcedure @@ -682,37 +735,38 @@ Module PBMap Macro SelBool(Name) Select UCase(Value) Case "0", "FALSE", "DISABLE" - PBMap\Options\Name = #False + *PBMap\Options\Name = #False Default - PBMap\Options\Name = #True + *PBMap\Options\Name = #True EndSelect EndMacro - Procedure SetOption(Option.s, Value.s) + Procedure SetOption(MapGadget.i, Option.s, Value.s) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) Option = StringCheck(Option) Select LCase(Option) Case "proxy" SelBool(Proxy) Case "proxyurl" - PBMap\Options\ProxyURL = Value + *PBMap\Options\ProxyURL = Value Case "proxyport" - PBMap\Options\ProxyPort = Value + *PBMap\Options\ProxyPort = Value Case "proxyuser" - PBMap\Options\ProxyUser = Value + *PBMap\Options\ProxyUser = Value Case "appid" - PBMap\Options\appid = Value + *PBMap\Options\appid = Value Case "appcode" - PBMap\Options\appcode = Value + *PBMap\Options\appcode = Value Case "tilescachepath" - PBMap\Options\HDDCachePath = Value + *PBMap\Options\HDDCachePath = Value Case "maxmemcache" - PBMap\Options\MaxMemCache = Val(Value) + *PBMap\Options\MaxMemCache = Val(Value) Case "maxthreads" - PBMap\Options\MaxThreads = Val(Value) + *PBMap\Options\MaxThreads = Val(Value) Case "maxdownloadslots" - PBMap\Options\MaxDownloadSlots = Val(Value) + *PBMap\Options\MaxDownloadSlots = Val(Value) Case "tilelifetime" - PBMap\Options\TileLifetime = Val(Value) + *PBMap\Options\TileLifetime = Val(Value) Case "verbose" SelBool(Verbose) Case "warning" @@ -744,13 +798,13 @@ Module PBMap Case "strokewidthtrackdefault" SelBool(StrokeWidthTrackDefault) Case "colourfocus" - PBMap\Options\ColourFocus = ColourString2Value(Value) + *PBMap\Options\ColourFocus = ColourString2Value(Value) Case "colourselected" - PBMap\Options\ColourSelected = ColourString2Value(Value) + *PBMap\Options\ColourSelected = ColourString2Value(Value) Case "colourtrackdefault" - PBMap\Options\ColourTrackDefault = ColourString2Value(Value) + *PBMap\Options\ColourTrackDefault = ColourString2Value(Value) EndSelect - SetOptions() + SetOptions(MapGadget) EndProcedure Procedure.s GetBoolString(Value.i) @@ -762,9 +816,10 @@ Module PBMap EndSelect EndProcedure - Procedure.s GetOption(Option.s) + Procedure.s GetOption(MapGadget.i, Option.s) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) Option = StringCheck(Option) - With PBMap\Options + With *PBMap\Options Select LCase(Option) Case "proxy" ProcedureReturn GetBoolString(\Proxy) @@ -829,13 +884,14 @@ Module PBMap EndProcedure ; By default, save options in the user's home directory - Procedure SaveOptions(PreferencesFile.s = "PBMap.prefs") + Procedure SaveOptions(MapGadget.i, PreferencesFile.s = "PBMap.prefs") + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) If PreferencesFile = "PBMap.prefs" CreatePreferences(GetHomeDirectory() + "PBMap.prefs") Else CreatePreferences(PreferencesFile) EndIf - With PBMap\Options + With *PBMap\Options PreferenceGroup("PROXY") WritePreferenceInteger("Proxy", \Proxy) WritePreferenceString("ProxyURL", \ProxyURL) @@ -877,7 +933,8 @@ Module PBMap EndWith EndProcedure - Procedure LoadOptions(PreferencesFile.s = "PBMap.prefs") + Procedure LoadOptions(MapGadget.i, PreferencesFile.s = "PBMap.prefs") + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) If PreferencesFile = "PBMap.prefs" OpenPreferences(GetHomeDirectory() + "PBMap.prefs") Else @@ -899,13 +956,13 @@ Module PBMap ; WritePreferenceString("APP_ID", "myhereid") ; TODO !Warning! !not encoded! ; WritePreferenceString("APP_CODE", "myherecode") ; TODO !Warning! !not encoded! ; ClosePreferences() - With PBMap\Options + With *PBMap\Options PreferenceGroup("PROXY") \Proxy = ReadPreferenceInteger("Proxy", #False) If \Proxy \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", "") + \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 EndIf PreferenceGroup("HERE") @@ -944,22 +1001,23 @@ Module PBMap \TimerInterval = 12 ClosePreferences() EndWith - SetOptions() + SetOptions(MapGadget) EndProcedure ;-*** Layers ; 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) + Procedure.i AddLayer(MapGadget.i, Name.s, Order.i, Alpha.d) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) Protected *Ptr = 0 - *Ptr = AddMapElement(PBMap\Layers(), Name) + *Ptr = AddMapElement(*PBMap\Layers(), Name) If *Ptr - PBMap\Layers() = AddElement(PBMap\LayersList()) ; This map element is a ptr to a linked list element - If PBMap\Layers() - PBMap\LayersList()\Name = Name - PBMap\LayersList()\Order = Order - PBMap\LayersList()\Alpha = Alpha - SortStructuredList(PBMap\LayersList(), #PB_Sort_Ascending, OffsetOf(Layer\Order), TypeOf(Layer\Order)) - ProcedureReturn PBMap\Layers() + *PBMap\Layers() = AddElement(*PBMap\LayersList()) ; This map element is a ptr to a linked list element + If *PBMap\Layers() + *PBMap\LayersList()\Name = Name + *PBMap\LayersList()\Order = Order + *PBMap\LayersList()\Alpha = Alpha + SortStructuredList(*PBMap\LayersList(), #PB_Sort_Ascending, OffsetOf(Layer\Order), TypeOf(Layer\Order)) + ProcedureReturn *PBMap\Layers() Else *Ptr = 0 EndIf @@ -968,13 +1026,14 @@ Module PBMap EndProcedure ; "OpenStreetMap" layer - Procedure.i AddOSMServerLayer(LayerName.s, Order.i, ServerURL.s = "http://tile.openstreetmap.org/") - Protected *Ptr.Layer = AddLayer(LayerName, Order, 1) + Procedure.i AddOSMServerLayer(MapGadget.i, LayerName.s, Order.i, ServerURL.s = "http://tile.openstreetmap.org/") + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + Protected *Ptr.Layer = AddLayer(MapGadget, LayerName, Order, 1) If *Ptr *Ptr\ServerURL = ServerURL *Ptr\LayerType = 0 ; OSM *Ptr\Enabled = #True - PBMap\Redraw = #True + *PBMap\Redraw = #True ProcedureReturn *Ptr Else ProcedureReturn #False @@ -985,20 +1044,21 @@ Module PBMap ; 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) + Procedure.i AddHereServerLayer(MapGadget.i, 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 *PBMap.PBMap = PBMaps(Str(MapGadget)) + Protected *Ptr.Layer = AddLayer(MapGadget, LayerName, Order, 1) If *Ptr - With *Ptr ; PBMap\Layers() + With *Ptr ; *PBMap\Layers() \ServerURL = ServerURL \path = path \ressource = ressource \LayerType = 1 ; HERE \Enabled = #True If APP_ID = "" - APP_ID = PBMap\Options\appid + APP_ID = *PBMap\Options\appid EndIf If APP_CODE = "" - APP_CODE = PBMap\Options\appcode + APP_CODE = *PBMap\Options\appcode EndIf \APP_CODE = APP_CODE \APP_ID = APP_ID @@ -1009,7 +1069,7 @@ Module PBMap \param = param \scheme = scheme EndWith - PBMap\Redraw = #True + *PBMap\Redraw = #True ProcedureReturn *Ptr Else ProcedureReturn #False @@ -1018,10 +1078,11 @@ Module PBMap ; 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) + Procedure.i AddGeoServerLayer(MapGadget.i, LayerName.s, Order.i, ServerLayerName.s, ServerURL.s = "http://localhost:8080/", path.s = "geowebcache/service/gmaps", format.s = "image/png") + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + Protected *Ptr.Layer = AddLayer(MapGadget, LayerName, Order, 1) If *Ptr - With *Ptr ; PBMap\Layers() + With *Ptr ; *PBMap\Layers() \ServerURL = ServerURL \path = path \LayerType = 2 ; GeoServer @@ -1029,103 +1090,130 @@ Module PBMap \Enabled = #True \ServerLayerName = ServerLayerName EndWith - PBMap\Redraw = #True + *PBMap\Redraw = #True ProcedureReturn *Ptr Else ProcedureReturn #False EndIf EndProcedure - Procedure.i IsLayer(Name.s) - ProcedureReturn FindMapElement(PBMap\Layers(), Name) + Procedure.i IsLayer(MapGadget.i, Name.s) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + ProcedureReturn FindMapElement(*PBMap\Layers(), Name) EndProcedure - Procedure DeleteLayer(Name.s) - FindMapElement(PBMap\Layers(), Name) - Protected *Ptr = PBMap\Layers() + Procedure DeleteLayer(MapGadget.i, Name.s) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + FindMapElement(*PBMap\Layers(), Name) + Protected *Ptr = *PBMap\Layers() ; Free the list element - ChangeCurrentElement(PBMap\LayersList(), *Ptr) - DeleteElement(PBMap\LayersList()) + ChangeCurrentElement(*PBMap\LayersList(), *Ptr) + DeleteElement(*PBMap\LayersList()) ; Free the map element - DeleteMapElement(PBMap\Layers()) - PBMap\Redraw = #True + DeleteMapElement(*PBMap\Layers()) + *PBMap\Redraw = #True EndProcedure - Procedure EnableLayer(Name.s) - PBMap\Layers(Name)\Enabled = #True - PBMap\Redraw = #True + Procedure EnableLayer(MapGadget.i, Name.s) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + *PBMap\Layers(Name)\Enabled = #True + *PBMap\Redraw = #True EndProcedure - Procedure DisableLayer(Name.s) - PBMap\Layers(Name)\Enabled = #False - PBMap\Redraw = #True + Procedure DisableLayer(MapGadget.i, Name.s) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + *PBMap\Layers(Name)\Enabled = #False + *PBMap\Redraw = #True EndProcedure - Procedure SetLayerAlpha(Name.s, Alpha.d) - PBMap\Layers(Name)\Alpha = Alpha - PBMap\Redraw = #True + Procedure SetLayerAlpha(MapGadget.i, Name.s, Alpha.d) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + *PBMap\Layers(Name)\Alpha = Alpha + *PBMap\Redraw = #True EndProcedure - Procedure.d GetLayerAlpha(Name.s) - ProcedureReturn PBMap\Layers(Name)\Alpha + Procedure.d GetLayerAlpha(MapGadget.i, Name.s) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + ProcedureReturn *PBMap\Layers(Name)\Alpha EndProcedure ;-*** ; If cache size exceeds limit, try to delete the oldest tiles used (first in the time stack) - Procedure MemoryCacheManagement() - LockMutex(PBMap\MemoryCacheAccessMutex) ; Prevents thread 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 CacheLimit = PBMap\Options\MaxMemCache * 1024 - MyDebug("Cache size : " + Str(CacheSize/1024) + " / CacheLimit : " + Str(CacheLimit/1024), 5) + Procedure MemoryCacheManagement(MapGadget.i) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + 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 CacheLimit = *PBMap\Options\MaxMemCache * 1024 + MyDebug(*PBMap, "Cache size : " + Str(CacheSize/1024) + " / CacheLimit : " + Str(CacheLimit/1024), 5) If CacheSize > CacheLimit - MyDebug(" Cache full. Trying cache cleaning", 5) - ResetList(PBMap\MemCache\ImagesTimeStack()) + MyDebug(*PBMap, " Cache full. Trying cache cleaning", 5) + ResetList(*PBMap\MemCache\ImagesTimeStack()) ; Try to free half the cache memory (one pass) - While NextElement(PBMap\MemCache\ImagesTimeStack()) And CacheSize > (CacheLimit / 2) ; /2 = half - Protected CacheMapKey.s = PBMap\MemCache\ImagesTimeStack()\MapKey + While NextElement(*PBMap\MemCache\ImagesTimeStack()) And CacheSize > (CacheLimit / 2) ; /2 = half + Protected CacheMapKey.s = *PBMap\MemCache\ImagesTimeStack()\MapKey ; Is the loading over - If PBMap\MemCache\Images(CacheMapKey)\Tile <= 0 ;TODO Should not verify this var directly - MyDebug(" Delete " + CacheMapKey, 5) - If PBMap\MemCache\Images(CacheMapKey)\nImage;IsImage(PBMap\MemCache\Images(CacheMapKey)\nImage) - FreeImage(PBMap\MemCache\Images(CacheMapKey)\nImage) - MyDebug(" and free image nb " + Str(PBMap\MemCache\Images(CacheMapKey)\nImage), 5) - PBMap\MemCache\Images(CacheMapKey)\nImage = 0 + If *PBMap\MemCache\Images(CacheMapKey)\Tile <= 0 ;TODO Should not verify this var directly + MyDebug(*PBMap, " Delete " + CacheMapKey, 5) + If *PBMap\MemCache\Images(CacheMapKey)\nImage;IsImage(*PBMap\MemCache\Images(CacheMapKey)\nImage) + FreeImage(*PBMap\MemCache\Images(CacheMapKey)\nImage) + MyDebug(*PBMap, " and free image nb " + Str(*PBMap\MemCache\Images(CacheMapKey)\nImage), 5) + *PBMap\MemCache\Images(CacheMapKey)\nImage = 0 EndIf - DeleteMapElement(PBMap\MemCache\Images(), CacheMapKey) - DeleteElement(PBMap\MemCache\ImagesTimeStack(), 1) - ; ElseIf PBMap\MemCache\Images(CacheMapKey)\Tile = 0 - ; MyDebug(" Delete " + CacheMapKey, 5) - ; DeleteMapElement(PBMap\MemCache\Images(), CacheMapKey) - ; DeleteElement(PBMap\MemCache\ImagesTimeStack(), 1) - ; ElseIf PBMap\MemCache\Images(CacheMapKey)\Tile > 0 + DeleteMapElement(*PBMap\MemCache\Images(), CacheMapKey) + DeleteElement(*PBMap\MemCache\ImagesTimeStack(), 1) + ; ElseIf *PBMap\MemCache\Images(CacheMapKey)\Tile = 0 + ; MyDebug(*PBMap, " Delete " + CacheMapKey, 5) + ; DeleteMapElement(*PBMap\MemCache\Images(), CacheMapKey) + ; DeleteElement(*PBMap\MemCache\ImagesTimeStack(), 1) + ; ElseIf *PBMap\MemCache\Images(CacheMapKey)\Tile > 0 ; ; If the thread is running, try to abort the download - ; If PBMap\MemCache\Images(CacheMapKey)\Tile\Download - ; AbortHTTP(PBMap\MemCache\Images(CacheMapKey)\Tile\Download) ; Could lead to error + ; If *PBMap\MemCache\Images(CacheMapKey)\Tile\Download + ; AbortHTTP(*PBMap\MemCache\Images(CacheMapKey)\Tile\Download) ; Could lead to error ; EndIf EndIf - CacheSize = MapSize(PBMap\MemCache\Images()) * Pow(PBMap\TileSize, 2) * 4 ; Size of a tile = TileSize * TileSize * 4 bytes (RGBA) + CacheSize = MapSize(*PBMap\MemCache\Images()) * Pow(*PBMap\TileSize, 2) * 4 ; Size of a tile = TileSize * TileSize * 4 bytes (RGBA) Wend - MyDebug(" New cache size : " + Str(CacheSize/1024) + " / CacheLimit : " + Str(CacheLimit/1024), 5) + MyDebug(*PBMap, " New cache size : " + Str(CacheSize/1024) + " / CacheLimit : " + Str(CacheLimit/1024), 5) If CacheSize > CacheLimit - MyDebug(" Cache cleaning unsuccessfull, can't add new tiles.", 5) + MyDebug(*PBMap, " Cache cleaning unsuccessfull, can't add new tiles.", 5) EndIf EndIf - UnlockMutex(PBMap\MemoryCacheAccessMutex) + UnlockMutex(*PBMap\MemoryCacheAccessMutex) EndProcedure - Procedure.i GetTileFromHDD(CacheFile.s) + ;- 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) Protected nImage.i, LifeTime.i, MaxLifeTime.i ; Everything is OK, loads the file - nImage = LoadImage(#PB_Any, CacheFile) + nImage = _LoadImage(#PB_Any, CacheFile) If nImage - MyDebug(" Success loading " + CacheFile + " as nImage " + Str(nImage), 3) + MyDebug(*PBMap, " Success loading " + CacheFile + " as nImage " + Str(nImage), 3) ProcedureReturn nImage Else - MyDebug(" Failed loading " + CacheFile + " as nImage " + Str(nImage) + " -> not an image !", 3) + MyDebug(*PBMap, " Failed loading " + CacheFile + " as nImage " + Str(nImage) + " -> not an image !", 3) If DeleteFile(CacheFile) - MyDebug(" Deleting faulty image file " + CacheFile, 3) + MyDebug(*PBMap, " Deleting faulty image file " + CacheFile, 3) Else - MyDebug(" Can't delete faulty image file " + CacheFile, 3) + MyDebug(*PBMap, " Can't delete faulty image file " + CacheFile, 3) EndIf EndIf ProcedureReturn #False @@ -1142,17 +1230,17 @@ Module PBMap ; 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) + ; MyDebug(*PBMap, "Loaded from web " + TileURL + " as CacheFile " + CacheFile, 3) ; Else - ; MyDebug("Loaded from web " + TileURL + " but cannot save to CacheFile " + CacheFile, 3) + ; MyDebug(*PBMap, "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) + ; MyDebug(*PBMap, "Can't catch image loaded from web " + TileURL, 3) ; nImage = -1 ; EndIf ; Else - ; MyDebug(" Problem loading from web " + TileURL, 3) + ; MyDebug(*PBMap, " Problem loading from web " + TileURL, 3) ; EndIf ; **** @@ -1160,43 +1248,44 @@ Module PBMap Threaded Progress = 0, Quit = #False - Procedure GetImageThread(*Tile.Tile) - LockMutex(PBMap\MemoryCacheAccessMutex) - MyDebug("Thread nb " + Str(*Tile\GetImageThread) + " " + *Tile\key + " starting for image " + *Tile\CacheFile, 5) + Procedure GetImageThread(*Tile.Tile) + ;LockMutex(*PBMap\MemoryCacheAccessMutex) + ;MyDebug(*PBMap, "Thread nb " + Str(*Tile\GetImageThread) + " " + *Tile\key + " starting for image " + *Tile\CacheFile, 5) ; If MemoryCache is currently being cleaned, abort -; If PBMap\MemoryCacheAccessNB = -1 -; MyDebug(" Thread nb " + Str(*Tile\GetImageThread) + " " + *Tile\key + " for image " + *Tile\CacheFile + " canceled because of cleaning.", 5) +; If *PBMap\MemoryCacheAccessNB = -1 +; MyDebug(*PBMap, " Thread nb " + Str(*Tile\GetImageThread) + " " + *Tile\key + " for image " + *Tile\CacheFile + " canceled because of cleaning.", 5) ; *Tile\Size = 0 ; \Size = 0 signals that the download has failed -; PostEvent(#PB_Event_Gadget, PBMap\Window, PBmap\Gadget, #PB_MAP_TILE_CLEANUP, *Tile) ; To free memory outside the thread -; UnlockMutex(PBMap\MemoryCacheAccessMutex) +; PostEvent(#PB_Event_Gadget, *PBMap\Window, *PBMap\Gadget, #PB_MAP_TILE_CLEANUP, *Tile) ; To free memory outside the thread +; UnlockMutex(*PBMap\MemoryCacheAccessMutex) ; ProcedureReturn ; EndIf ; We're accessing MemoryCache - UnlockMutex(PBMap\MemoryCacheAccessMutex) + ;UnlockMutex(*PBMap\MemoryCacheAccessMutex) *Tile\Size = 0 - *Tile\Download = ReceiveHTTPFile(*Tile\URL, *Tile\CacheFile, #PB_HTTP_Asynchronous) + *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 Repeat Progress = HTTPProgress(*Tile\Download) Select Progress - Case #PB_Http_Success + Case #PB_HTTP_Success *Tile\Size = FinishHTTP(*Tile\Download) ; \Size signals that the download is OK - MyDebug(" 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 - Case #PB_Http_Failed + Case #PB_HTTP_Failed FinishHTTP(*Tile\Download) *Tile\Size = 0 ; \Size = 0 signals that the download has failed - MyDebug(" 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 - Case #PB_Http_Aborted + Case #PB_HTTP_Aborted FinishHTTP(*Tile\Download) *Tile\Size = 0 ; \Size = 0 signals that the download has failed - MyDebug(" 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) Quit = #True Default - MyDebug(" Thread nb " + Str(*Tile\GetImageThread) + " " + *Tile\key + " for image " + *Tile\CacheFile + " downloading " + Str(Progress) + " bytes", 5) + ;MyDebug(*PBMap, " Thread nb " + Str(*Tile\GetImageThread) + " " + *Tile\key + " for image " + *Tile\CacheFile + " downloading " + Str(Progress) + " bytes", 5) If ElapsedMilliseconds() - *Tile\Time > 10000 - MyDebug(" Thread nb " + Str(*Tile\GetImageThread) + " " + *Tile\key + " for image " + *Tile\CacheFile + " canceled after 10 seconds.", 5) + ;MyDebug(*PBMap, " Thread nb " + Str(*Tile\GetImageThread) + " " + *Tile\key + " for image " + *Tile\CacheFile + " canceled after 10 seconds.", 5) AbortHTTP(*Tile\Download) EndIf EndSelect @@ -1204,192 +1293,195 @@ Module PBMap Until Quit EndIf ; End of the memory cache access - LockMutex(PBMap\MemoryCacheAccessMutex) - PostEvent(#PB_Event_Gadget, PBMap\Window, PBmap\Gadget, #PB_MAP_TILE_CLEANUP, *Tile) ; To free memory outside the thread - UnlockMutex(PBMap\MemoryCacheAccessMutex) + ;LockMutex(*PBMap\MemoryCacheAccessMutex) + ; 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) EndProcedure ;-*** - Procedure.i GetTile(key.s, URL.s, CacheFile.s) + Procedure.i GetTile(MapGadget.i, key.s, URL.s, CacheFile.s) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) ; MemoryCache access management - LockMutex(PBMap\MemoryCacheAccessMutex) + LockMutex(*PBMap\MemoryCacheAccessMutex) ; Try to find the tile in memory cache - Protected *timg.ImgMemCach = FindMapElement(PBMap\MemCache\Images(), key) + Protected *timg.ImgMemCach = FindMapElement(*PBMap\MemCache\Images(), key) If *timg - MyDebug("Key : " + key + " found in memory cache", 4) - ; Is the associated image already been loaded in memory ? + MyDebug(*PBMap, "Key : " + key + " found in memory cache", 4) + ; Is the associated image already loaded in memory ? If *timg\nImage ; Yes, returns the image's nb - MyDebug(" as image " + *timg\nImage, 4) + MyDebug(*PBMap, " as image " + *timg\nImage, 4) ; *** 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()) + ChangeCurrentElement(*PBMap\MemCache\ImagesTimeStack(), *timg\TimeStackPtr) + MoveElement(*PBMap\MemCache\ImagesTimeStack(), #PB_List_Last) + ; *timg\TimeStackPtr = LastElement(*PBMap\MemCache\ImagesTimeStack()) ; *** - UnlockMutex(PBMap\MemoryCacheAccessMutex) + UnlockMutex(*PBMap\MemoryCacheAccessMutex) ProcedureReturn *timg Else ; No, try to load it from HD (see below) - MyDebug(" but not the image.", 4) + MyDebug(*PBMap, " but not the image.", 4) EndIf Else ; The tile has not been found in the cache, so creates a new cache element - *timg = AddMapElement(PBMap\MemCache\Images(), key) + *timg = AddMapElement(*PBMap\MemCache\Images(), key) If *timg = 0 - MyDebug(" Can't add a new cache element.", 4) - UnlockMutex(PBMap\MemoryCacheAccessMutex) + MyDebug(*PBMap, " Can't add a new cache element.", 4) + UnlockMutex(*PBMap\MemoryCacheAccessMutex) ProcedureReturn #False EndIf ; add a new time stack element at the End - LastElement(PBMap\MemCache\ImagesTimeStack()) + LastElement(*PBMap\MemCache\ImagesTimeStack()) ; Stores the time stack ptr - *timg\TimeStackPtr = AddElement(PBMap\MemCache\ImagesTimeStack()) + *timg\TimeStackPtr = AddElement(*PBMap\MemCache\ImagesTimeStack()) If *timg\TimeStackPtr = 0 - MyDebug(" Can't add a new time stack element.", 4) - DeleteMapElement(PBMap\MemCache\Images()) - UnlockMutex(PBMap\MemoryCacheAccessMutex) + MyDebug(*PBMap, " Can't add a new time stack element.", 4) + DeleteMapElement(*PBMap\MemCache\Images()) + UnlockMutex(*PBMap\MemoryCacheAccessMutex) ProcedureReturn #False EndIf ; Associates the time stack element to the cache element - PBMap\MemCache\ImagesTimeStack()\MapKey = MapKey(PBMap\MemCache\Images()) - MyDebug("Key : " + key + " added in memory cache", 4) + *PBMap\MemCache\ImagesTimeStack()\MapKey = MapKey(*PBMap\MemCache\Images()) + MyDebug(*PBMap, "Key : " + key + " added in memory cache", 4) EndIf - ; If there's no active download thread for this tile - If *timg\Tile <= 0 + ; If there's no active downloading thread for this image + If *timg\Tile <= 0 *timg\nImage = 0 - *timg\Size = FileSize(CacheFile) - ; Manage tile file lifetime, delete if too old, or if size = 0 - If PBMap\Options\TileLifetime <> -1 - If *timg\Size >= 0 ; Does the file exists ? - 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 + *timg\Size = FileSize(CacheFile) + ; Does a valid file exists on HD ? Try to load it. + If *timg\Size >= 0 + ; 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 DeleteFile(CacheFile) - MyDebug(" Deleting image file " + CacheFile, 3) + MyDebug(*PBMap, " Deleting image file " + CacheFile, 3) *timg\Size = 0 Else - MyDebug(" Can't delete image file " + CacheFile, 3) - UnlockMutex(PBMap\MemoryCacheAccessMutex) - ProcedureReturn #False + MyDebug(*PBMap, " Can't delete image file " + CacheFile, 3) EndIf + UnlockMutex(*PBMap\MemoryCacheAccessMutex) + ProcedureReturn #False EndIf EndIf + ; Try to load tile's image from HD + *timg\nImage = GetTileFromHDD(*PBMap, CacheFile.s) + If *timg\nImage + ; Success : image found and loaded from HDD + *timg\Alpha = 0 + UnlockMutex(*PBMap\MemoryCacheAccessMutex) + ProcedureReturn *timg + EndIf EndIf - ; Try To load it from HD - If *timg\Size > 0 - *timg\nImage = GetTileFromHDD(CacheFile.s) - Else - MyDebug(" Failed loading from HDD " + CacheFile + " -> Filesize = " + FileSize(CacheFile), 3) - EndIf - If *timg\nImage - ; Image found and loaded from HDD - *timg\Alpha = 0 - UnlockMutex(PBMap\MemoryCacheAccessMutex) - ProcedureReturn *timg - Else - ; If GetTileFromHDD failed, will load it (again?) from the web - If PBMap\ThreadsNB < PBMap\Options\MaxThreads - If PBMap\DownloadSlots < PBMap\Options\MaxDownloadSlots - ; Launch a new web loading thread - PBMap\DownloadSlots + 1 - Protected *NewTile.Tile = AllocateMemory(SizeOf(Tile)) - If *NewTile - With *NewTile - ; New tile parameters - \key = key - \URL = URL - \CacheFile = CacheFile - \nImage = 0 - \Time = ElapsedMilliseconds() - \GetImageThread = CreateThread(@GetImageThread(), *NewTile) - If \GetImageThread - *timg\Tile = *NewTile ; There's now a loading thread - *timg\Alpha = 0 - MyDebug(" Creating get image thread nb " + Str(\GetImageThread) + " to get " + CacheFile + " (key = " + key, 3) - PBMap\ThreadsNB + 1 - Else - MyDebug(" Can't create get image thread to get " + CacheFile, 3) - FreeMemory(*NewTile) - EndIf - EndWith - Else - MyDebug(" Error, can't allocate memory for a new tile loading thread", 3) - EndIf - Else - MyDebug(" Thread needed " + key + " for image " + CacheFile + " canceled because no free download slot.", 5) - EndIf + ; If GetTileFromHDD failed, will try to download the image from the web in a thread + MyDebug(*PBMap, " Failed loading from HDD " + CacheFile + " -> Filesize = " + FileSize(CacheFile), 3) + If *PBMap\ThreadsNB < *PBMap\Options\MaxThreads + If *PBMap\DownloadSlots < *PBMap\Options\MaxDownloadSlots + Protected *NewTile.Tile = AllocateMemory(SizeOf(Tile)) + If *NewTile + *timg\Tile = *NewTile ; There's now a loading thread + *timg\Alpha = 0 + With *NewTile + ; New tile parameters + \key = key + \URL = URL + \CacheFile = CacheFile + \nImage = 0 + \Time = ElapsedMilliseconds() + \Window = *PBMap\Window + \Gadget = *PBMap\Gadget + \GetImageThread = CreateThread(@GetImageThread(), *NewTile) + If \GetImageThread + MyDebug(*PBMap, " Creating get image thread nb " + Str(\GetImageThread) + " to get " + CacheFile + " (key = " + key, 3) + *PBMap\ThreadsNB + 1 + *PBMap\DownloadSlots + 1 + Else + ; Thread creation failed this time + *timg\Tile = 0 + 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 - MyDebug(" Error, maximum threads nb reached", 3) + MyDebug(*PBMap, " Thread needed " + key + " for image " + CacheFile + " canceled because no free download slot.", 5) EndIf + Else + MyDebug(*PBMap, " Error, maximum threads nb reached", 3) EndIf EndIf - UnlockMutex(PBMap\MemoryCacheAccessMutex) + UnlockMutex(*PBMap\MemoryCacheAccessMutex) ProcedureReturn #False EndProcedure - 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 ty = Int(*Drawing\TileCoordinates\y) - 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 + Procedure DrawTiles(MapGadget.i, *Drawing.DrawingParameters, LayerName.s) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + Protected x.i, y.i, kq.q + Protected tx.i = Int(*Drawing\TileCoordinates\x) ; Don't forget the Int() ! + Protected ty.i = Int(*Drawing\TileCoordinates\y) + Protected nx.i = *Drawing\RadiusX / *PBMap\TileSize ; How many tiles around the point + Protected ny.i = *Drawing\RadiusY / *PBMap\TileSize + Protected px.i, py.i, *timg.ImgMemCach, tilex.i, tiley.i, key.s Protected URL.s, CacheFile.s - Protected tilemax = 1<= 0 And tiley < tilemax - kq = (PBMap\Zoom << 8) | (tilex << 16) | (tiley << 36) + kq = (*PBMap\Zoom << 8) | (tilex << 16) | (tiley << 36) key = LayerName + Str(kq) ; Creates the cache tree based on the OSM tree+Layer : layer/zoom/x/y.png - Protected DirName.s = PBMap\Options\HDDCachePath + LayerName + Protected DirName.s = *PBMap\Options\HDDCachePath + LayerName If FileSize(DirName) <> -2 If CreateDirectory(DirName) = #False ; Creates a directory based on the layer name - Error("Can't create the following layer directory : " + DirName) + Error(MapGadget, "Can't create the following layer directory : " + DirName) Else - MyDebug(DirName + " successfully created", 4) + MyDebug(*PBMap, DirName + " successfully created", 4) EndIf EndIf ; Creates the sub-directory based on the zoom - DirName + slash + Str(PBMap\Zoom) + DirName + slash + Str(*PBMap\Zoom) If FileSize(DirName) <> -2 If CreateDirectory(DirName) = #False - Error("Can't create the following zoom directory : " + DirName) + Error(MapGadget, "Can't create the following zoom directory : " + DirName) Else - MyDebug(DirName + " successfully created", 4) + MyDebug(*PBMap, DirName + " successfully created", 4) EndIf EndIf ; Creates the sub-directory based on x DirName.s + slash + Str(tilex) If FileSize(DirName) <> -2 If CreateDirectory(DirName) = #False - Error("Can't create the following x directory : " + DirName) + Error(MapGadget, "Can't create the following x directory : " + DirName) Else - MyDebug(DirName + " successfully created", 4) + MyDebug(*PBMap, DirName + " successfully created", 4) EndIf EndIf - With PBMap\Layers() + With *PBMap\Layers() Select \LayerType ;---- OSM tiles Case 0 - URL = \ServerURL + Str(PBMap\Zoom) + "/" + Str(tilex) + "/" + Str(tiley) + ".png" + URL = \ServerURL + Str(*PBMap\Zoom) + "/" + Str(tilex) + "/" + Str(tiley) + ".png" ; Tile cache name based on y CacheFile = DirName + slash + Str(tiley) + ".png" ;---- Here tiles Case 1 HereLoadBalancing = 1 + ((tiley + tilex) % 4) ; {Base URL}{Path}{resource (tile type)}/{Map id}/{scheme}/{zoom}/{column}/{row}/{size}/{format}?app_id={YOUR_APP_ID}&app_code={YOUR_APP_CODE}&{param}={value} - URL = "https://" + StrU(HereLoadBalancing, #PB_Byte) + "." + \ServerURL + \path + \ressource + "/" + \id + "/" + \scheme + "/" + Str(PBMap\Zoom) + "/" + Str(tilex) + "/" + Str(tiley) + "/256/" + \format + "?app_id=" + \APP_ID + "&app_code=" + \APP_CODE + "&lg=" + \lg + "&lg2=" + \lg2 + URL = "https://" + StrU(HereLoadBalancing, #PB_Byte) + "." + \ServerURL + \path + \ressource + "/" + \id + "/" + \scheme + "/" + Str(*PBMap\Zoom) + "/" + Str(tilex) + "/" + Str(tiley) + "/256/" + \format + "?app_id=" + \APP_ID + "&app_code=" + \APP_CODE + "&lg=" + \lg + "&lg2=" + \lg2 If \param <> "" URL + "&" + \param EndIf @@ -1398,34 +1490,40 @@ Module PBMap ;---- GeoServer / geowebcache - google maps service tiles Case 2 ; template 'http://localhost:8080/geowebcache/service/gmaps?layers=layer-name&zoom={Z}&x={X}&y={Y}&format=image/png' - URL = \ServerURL + \path + "?layers=" + \ServerLayerName + "&zoom={" + Str(PBMap\Zoom) + "}&x={" + Str(tilex) + "}&y={" + Str(tiley) + "}&format=" + \format + URL = \ServerURL + \path + "?layers=" + \ServerLayerName + "&zoom={" + Str(*PBMap\Zoom) + "}&x={" + Str(tilex) + "}&y={" + Str(tiley) + "}&format=" + \format ; Tile cache name based on y CacheFile = DirName + slash + Str(tiley) + ".png" EndSelect EndWith - *timg = GetTile(key, URL, CacheFile) + *timg = GetTile(MapGadget, key, URL, CacheFile) If *timg And *timg\nImage - MovePathCursor(px, py) - If *timg\Alpha <= 224 - DrawVectorImage(ImageID(*timg\nImage), *timg\Alpha * PBMap\Layers()\Alpha) - *timg\Alpha + 32 - PBMap\Redraw = #True + If *PBMap\CallBackDrawTile + ;CallFunctionFast(*PBMap\CallBackDrawTile, px, py, *timg\nImage) + *PBMap\CallBackDrawTile(px, py, *timg\nImage, *PBMap\Layers()\Alpha) + *PBMap\Redraw = #True Else - DrawVectorImage(ImageID(*timg\nImage), 255 * PBMap\Layers()\Alpha) - *timg\Alpha = 256 - EndIf + MovePathCursor(px, py) + If *timg\Alpha <= 224 + DrawVectorImage(ImageID(*timg\nImage), *timg\Alpha * *PBMap\Layers()\Alpha) + *timg\Alpha + 32 + *PBMap\Redraw = #True + Else + DrawVectorImage(ImageID(*timg\nImage), 255 * *PBMap\Layers()\Alpha) + *timg\Alpha = 256 + EndIf + EndIf Else MovePathCursor(px, py) - DrawVectorImage(ImageID(PBMap\ImgLoading), 255 * PBMap\Layers()\Alpha) + DrawVectorImage(ImageID(*PBMap\ImgLoading), 255 * *PBMap\Layers()\Alpha) EndIf Else - ; If PBMap\Layers()\Name = "" + ; If *PBMap\Layers()\Name = "" MovePathCursor(px, py) - DrawVectorImage(ImageID(PBMap\ImgNothing), 255 * PBMap\Layers()\Alpha) + DrawVectorImage(ImageID(*PBMap\ImgNothing), 255 * *PBMap\Layers()\Alpha) ; EndIf EndIf - If PBMap\Options\ShowDebugInfos - VectorFont(FontID(PBMap\StandardFont), 16) + If *PBMap\Options\ShowDebugInfos + VectorFont(FontID(*PBMap\StandardFont), 16) VectorSourceColor(RGBA(0, 0, 0, 80)) MovePathCursor(px, py) DrawVectorText("x:" + Str(tilex)) @@ -1436,10 +1534,11 @@ Module PBMap Next EndProcedure - Procedure DrawPointer(*Drawing.DrawingParameters) - If PBMap\CallBackMainPointer > 0 + Procedure DrawPointer(MapGadget.i, *Drawing.DrawingParameters) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + If *PBMap\CallBackMainPointer > 0 ; @Procedure(X.i, Y.i) to DrawPointer (you must use VectorDrawing lib) - CallFunctionFast(PBMap\CallBackMainPointer, *Drawing\RadiusX, *Drawing\RadiusY) + CallFunctionFast(*PBMap\CallBackMainPointer, *Drawing\RadiusX, *Drawing\RadiusY) Else VectorSourceColor(RGBA($FF, 0, 0, $FF)) MovePathCursor(*Drawing\RadiusX, *Drawing\RadiusY) @@ -1453,17 +1552,18 @@ Module PBMap EndIf EndProcedure - Procedure DrawScale(*Drawing.DrawingParameters,x,y,alpha=80) + Procedure DrawScale(MapGadget.i, *Drawing.DrawingParameters,x,y,alpha=80) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) Protected sunit.s - Protected Scale.d= 40075*Cos(Radian(PBMap\GeographicCoordinates\Latitude))/Pow(2,PBMap\Zoom) / 2 - Select PBMap\Options\ScaleUnit + Protected Scale.d= 40075*Cos(Radian(*PBMap\GeographicCoordinates\Latitude))/Pow(2,*PBMap\Zoom) / 2 + Select *PBMap\Options\ScaleUnit Case #SCALE_Nautical Scale * 0.539957 sunit = " Nm" Case #SCALE_KM; sunit = " Km" EndSelect - VectorFont(FontID(PBMap\StandardFont), 10) + VectorFont(FontID(*PBMap\StandardFont), 10) VectorSourceColor(RGBA(0, 0, 0, alpha)) MovePathCursor(x,y) DrawVectorText(StrD(Scale,3)+sunit) @@ -1472,7 +1572,8 @@ Module PBMap StrokePath(1) EndProcedure - Procedure DrawDegrees(*Drawing.DrawingParameters, alpha=192) + Procedure DrawDegrees(MapGadget.i, *Drawing.DrawingParameters, alpha=192) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) Protected nx, ny, nx1, ny1, x, y Protected pos1.PixelCoordinates, pos2.PixelCoordinates, Degrees1.GeographicCoordinates, degrees2.GeographicCoordinates CopyStructure(*Drawing\Bounds\NorthWest, @Degrees1, GeographicCoordinates) @@ -1487,15 +1588,15 @@ Module PBMap Degrees2\Longitude = nx1 Degrees2\Latitude = ny1 ; Debug "NW : " + StrD(Degrees1\Longitude) + " ; NE : " + StrD(Degrees2\Longitude) - LatLon2PixelRel(@Degrees1, @pos1, PBMap\Zoom) - LatLon2PixelRel(@Degrees2, @pos2, PBMap\Zoom) - VectorFont(FontID(PBMap\StandardFont), 10) + LatLon2PixelRel(MapGadget, @Degrees1, @pos1, *PBMap\Zoom) + LatLon2PixelRel(MapGadget, @Degrees2, @pos2, *PBMap\Zoom) + VectorFont(FontID(*PBMap\StandardFont), 10) VectorSourceColor(RGBA(0, 0, 0, alpha)) ; draw latitudes For y = ny1 To ny Degrees1\Longitude = nx Degrees1\Latitude = y - LatLon2PixelRel(@Degrees1, @pos1, PBMap\Zoom) + LatLon2PixelRel(MapGadget, @Degrees1, @pos1, *PBMap\Zoom) MovePathCursor(pos1\x, pos1\y) AddPathLine( pos2\x, pos1\y) MovePathCursor(10, pos1\y) @@ -1506,7 +1607,7 @@ Module PBMap Repeat Degrees1\Longitude = x Degrees1\Latitude = ny - LatLon2PixelRel(@Degrees1, @pos1, PBMap\Zoom) + LatLon2PixelRel(MapGadget, @Degrees1, @pos1, *PBMap\Zoom) MovePathCursor(pos1\x, pos1\y) AddPathLine( pos1\x, pos2\y) MovePathCursor(pos1\x,10) @@ -1516,15 +1617,17 @@ Module PBMap StrokePath(1) EndProcedure - Procedure DrawZoom(x.i, y.i) - VectorFont(FontID(PBMap\StandardFont), 20) + Procedure DrawZoom(MapGadget.i, x.i, y.i) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + VectorFont(FontID(*PBMap\StandardFont), 20) VectorSourceColor(RGBA(0, 0, 0,150)) MovePathCursor(x,y) - DrawVectorText(Str(GetZoom())) + DrawVectorText(Str(GetZoom(MapGadget))) EndProcedure ;-*** Tracks - Procedure DrawTrackPointer(x.d, y.d, dist.l) + Procedure DrawTrackPointer(MapGadget.i, x.d, y.d, dist.l) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) Protected color.l color=RGBA(0, 0, 0, 255) MovePathCursor(x,y) @@ -1537,13 +1640,14 @@ Module PBMap VectorSourceColor(RGBA(255, 255, 255, 255)) AddPathCircle(x,y-20,12) FillPath() - VectorFont(FontID(PBMap\StandardFont), 13) + VectorFont(FontID(*PBMap\StandardFont), 13) MovePathCursor(x-VectorTextWidth(Str(dist))/2, y-20-VectorTextHeight(Str(dist))/2) VectorSourceColor(RGBA(0, 0, 0, 255)) DrawVectorText(Str(dist)) EndProcedure - Procedure DrawTrackPointerFirst(x.d, y.d, dist.l) + Procedure DrawTrackPointerFirst(MapGadget.i, x.d, y.d, dist.l) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) Protected color.l color=RGBA(0, 0, 0, 255) MovePathCursor(x,y) @@ -1556,55 +1660,60 @@ Module PBMap VectorSourceColor(RGBA(255, 0, 0, 255)) AddPathCircle(x,y-24,14) FillPath() - VectorFont(FontID(PBMap\StandardFont), 14) + VectorFont(FontID(*PBMap\StandardFont), 14) MovePathCursor(x-VectorTextWidth(Str(dist))/2, y-24-VectorTextHeight(Str(dist))/2) VectorSourceColor(RGBA(0, 0, 0, 255)) DrawVectorText(Str(dist)) EndProcedure - Procedure DeleteTrack(*Ptr) + Procedure DeleteTrack(MapGadget.i, *Ptr) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) If *Ptr - ChangeCurrentElement(PBMap\TracksList(), *Ptr) - DeleteElement(PBMap\TracksList()) + ChangeCurrentElement(*PBMap\TracksList(), *Ptr) + DeleteElement(*PBMap\TracksList()) EndIf EndProcedure - Procedure DeleteSelectedTracks() - ForEach PBMap\TracksList() - If PBMap\TracksList()\Selected - DeleteElement(PBMap\TracksList()) - PBMap\Redraw = #True + Procedure DeleteSelectedTracks(MapGadget.i) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + ForEach *PBMap\TracksList() + If *PBMap\TracksList()\Selected + DeleteElement(*PBMap\TracksList()) + *PBMap\Redraw = #True EndIf Next EndProcedure - Procedure ClearTracks() - ClearList(PBMap\TracksList()) - PBMap\Redraw = #True + Procedure ClearTracks(MapGadget.i) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + ClearList(*PBMap\TracksList()) + *PBMap\Redraw = #True EndProcedure - Procedure SetTrackColour(*Ptr, Colour.i) + Procedure SetTrackColour(MapGadget.i, *Ptr, Colour.i) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) If *Ptr - ChangeCurrentElement(PBMap\TracksList(), *Ptr) - PBMap\TracksList()\Colour = Colour - PBMap\Redraw = #True + ChangeCurrentElement(*PBMap\TracksList(), *Ptr) + *PBMap\TracksList()\Colour = Colour + *PBMap\Redraw = #True EndIf EndProcedure - Procedure DrawTracks(*Drawing.DrawingParameters) + Procedure DrawTracks(MapGadget.i, *Drawing.DrawingParameters) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) Protected Pixel.PixelCoordinates Protected Location.GeographicCoordinates Protected km.f, memKm.i - With PBMap\TracksList() + With *PBMap\TracksList() ; Trace Track - If ListSize(PBMap\TracksList()) > 0 + If ListSize(*PBMap\TracksList()) > 0 BeginVectorLayer() - ForEach PBMap\TracksList() + ForEach *PBMap\TracksList() If ListSize(\Track()) > 0 ; Check visibility \Visible = #False ForEach \Track() - If IsInDrawingPixelBoundaries(*Drawing, @PBMap\TracksList()\Track()) + If IsInDrawingPixelBoundaries(MapGadget, *Drawing, @*PBMap\TracksList()\Track()) \Visible = #True Break EndIf @@ -1612,7 +1721,7 @@ Module PBMap If \Visible ; Draw tracks ForEach \Track() - LatLon2PixelRel(@PBMap\TracksList()\Track(), @Pixel, PBMap\Zoom) + LatLon2PixelRel(MapGadget, @*PBMap\TracksList()\Track(), @Pixel, *PBMap\Zoom) If ListIndex(\Track()) = 0 MovePathCursor(Pixel\x, Pixel\y) Else @@ -1624,9 +1733,9 @@ Module PBMap ; \BoundingBox\w = PathBoundsWidth() ; \BoundingBox\h = PathBoundsHeight() If \Focus - VectorSourceColor(PBMap\Options\ColourFocus) + VectorSourceColor(*PBMap\Options\ColourFocus) ElseIf \Selected - VectorSourceColor(PBMap\Options\ColourSelected) + VectorSourceColor(*PBMap\Options\ColourSelected) Else VectorSourceColor(\Colour) EndIf @@ -1634,7 +1743,7 @@ Module PBMap ; YA pour marquer chaque point d'un rond ForEach \Track() - LatLon2PixelRel(@PBMap\TracksList()\Track(), @Pixel, PBMap\Zoom) + LatLon2PixelRel(MapGadget, @*PBMap\TracksList()\Track(), @Pixel, *PBMap\Zoom) AddPathCircle(Pixel\x,Pixel\y,(\StrokeWidth / 4)) Next VectorSourceColor(RGBA(255, 255, 0, 255)) @@ -1645,28 +1754,28 @@ Module PBMap Next EndVectorLayer() ;Draw distances - If PBMap\Options\ShowTrackKms And PBMap\Zoom > 10 + If *PBMap\Options\ShowTrackKms And *PBMap\Zoom > 10 BeginVectorLayer() - ForEach PBMap\TracksList() + ForEach *PBMap\TracksList() If \Visible km = 0 : memKm = -1 - ForEach PBMap\TracksList()\Track() + ForEach *PBMap\TracksList()\Track() ; Test Distance If ListIndex(\Track()) = 0 Location\Latitude = \Track()\Latitude Location\Longitude = \Track()\Longitude Else - km = km + HaversineInKM(@Location, @PBMap\TracksList()\Track()) + km = km + HaversineInKM(@Location, @*PBMap\TracksList()\Track()) Location\Latitude = \Track()\Latitude Location\Longitude = \Track()\Longitude EndIf - LatLon2PixelRel(@PBMap\TracksList()\Track(), @Pixel, PBMap\Zoom) + LatLon2PixelRel(MapGadget, @*PBMap\TracksList()\Track(), @Pixel, *PBMap\Zoom) If Int(km) <> memKm memKm = Int(km) If Int(km) = 0 - DrawTrackPointerFirst(Pixel\x , Pixel\y, Int(km)) + DrawTrackPointerFirst(MapGadget, Pixel\x , Pixel\y, Int(km)) Else - DrawTrackPointer(Pixel\x , Pixel\y, Int(km)) + DrawTrackPointer(MapGadget, Pixel\x , Pixel\y, Int(km)) EndIf EndIf Next @@ -1678,21 +1787,22 @@ Module PBMap EndWith EndProcedure - Procedure.i LoadGpxFile(FileName.s) + Procedure.i LoadGpxFile(MapGadget.i, FileName.s) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) If LoadXML(0, FileName.s) Protected Message.s If XMLStatus(0) <> #PB_XML_Success Message = "Error in the XML file:" + Chr(13) Message + "Message: " + XMLError(0) + Chr(13) Message + "Line: " + Str(XMLErrorLine(0)) + " Character: " + Str(XMLErrorPosition(0)) - Error(Message) + Error(MapGadget, Message) EndIf Protected *MainNode,*subNode,*child,child.l *MainNode = MainXMLNode(0) *MainNode = XMLNodeFromPath(*MainNode, "/gpx/trk/trkseg") - Protected *NewTrack.Tracks = AddElement(PBMap\TracksList()) - PBMap\TracksList()\StrokeWidth = PBMap\Options\StrokeWidthTrackDefault - PBMap\TracksList()\Colour = PBMap\Options\ColourTrackDefault + Protected *NewTrack.Tracks = AddElement(*PBMap\TracksList()) + *PBMap\TracksList()\StrokeWidth = *PBMap\Options\StrokeWidthTrackDefault + *PBMap\TracksList()\Colour = *PBMap\Options\ColourTrackDefault For child = 1 To XMLChildCount(*MainNode) *child = ChildXMLNode(*MainNode, child) AddElement(*NewTrack\Track()) @@ -1707,12 +1817,13 @@ Module PBMap Wend EndIf Next - SetZoomToTracks(LastElement(PBMap\TracksList())) ; <-To center the view, and zoom on the tracks + SetZoomToTracks(MapGadget, LastElement(*PBMap\TracksList())) ; <-To center the view, and zoom on the tracks ProcedureReturn *NewTrack EndIf EndProcedure - Procedure.i SaveGpxFile(FileName.s, *Track.Tracks) + Procedure.i SaveGpxFile(MapGadget.i, FileName.s, *Track.Tracks) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) Protected Message.s If CreateXML(0) Protected *MainNode, *subNode, *child @@ -1729,7 +1840,7 @@ Module PBMap Message = "Error in the XML file:" + Chr(13) Message + "Message: " + XMLError(0) + Chr(13) Message + "Line: " + Str(XMLErrorLine(0)) + " Character: " + Str(XMLErrorPosition(0)) - Error(Message) + Error(MapGadget, Message) ProcedureReturn #False EndIf ProcedureReturn #True @@ -1740,38 +1851,42 @@ Module PBMap ;-*** Markers - Procedure ClearMarkers() - ClearList(PBMap\Markers()) - PBMap\Redraw = #True + Procedure ClearMarkers(MapGadget.i) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + ClearList(*PBMap\Markers()) + *PBMap\Redraw = #True EndProcedure - Procedure DeleteMarker(*Ptr) + Procedure DeleteMarker(MapGadget.i, *Ptr) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) If *Ptr - ChangeCurrentElement(PBMap\Markers(), *Ptr) - DeleteElement(PBMap\Markers()) - PBMap\Redraw = #True + ChangeCurrentElement(*PBMap\Markers(), *Ptr) + DeleteElement(*PBMap\Markers()) + *PBMap\Redraw = #True EndIf EndProcedure - Procedure DeleteSelectedMarkers() - ForEach PBMap\Markers() - If PBMap\Markers()\Selected - DeleteElement(PBMap\Markers()) - PBMap\Redraw = #True + Procedure DeleteSelectedMarkers(MapGadget.i) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + ForEach *PBMap\Markers() + If *PBMap\Markers()\Selected + DeleteElement(*PBMap\Markers()) + *PBMap\Redraw = #True EndIf Next EndProcedure - Procedure.i AddMarker(Latitude.d, Longitude.d, Identifier.s = "", Legend.s = "", Color.l=-1, CallBackPointer.i = -1) - Protected *Ptr = AddElement(PBMap\Markers()) + Procedure.i AddMarker(MapGadget.i, Latitude.d, Longitude.d, Identifier.s = "", Legend.s = "", Color.l=-1, CallBackPointer.i = -1) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + Protected *Ptr = AddElement(*PBMap\Markers()) If *Ptr - PBMap\Markers()\GeographicCoordinates\Latitude = Latitude - PBMap\Markers()\GeographicCoordinates\Longitude = ClipLongitude(Longitude) - PBMap\Markers()\Identifier = Identifier - PBMap\Markers()\Legend = Legend - PBMap\Markers()\Color = Color - PBMap\Markers()\CallBackPointer = CallBackPointer - PBMap\Redraw = #True + *PBMap\Markers()\GeographicCoordinates\Latitude = Latitude + *PBMap\Markers()\GeographicCoordinates\Longitude = ClipLongitude(Longitude) + *PBMap\Markers()\Identifier = Identifier + *PBMap\Markers()\Legend = Legend + *PBMap\Markers()\Color = Color + *PBMap\Markers()\CallBackPointer = CallBackPointer + *PBMap\Redraw = #True ProcedureReturn *Ptr EndIf EndProcedure @@ -1790,18 +1905,20 @@ Module PBMap EndIf EndProcedure - Procedure MarkerEditCloseWindow() - ForEach PBMap\Markers() - If PBMap\Markers()\EditWindow = EventWindow() - PBMap\Markers()\EditWindow = 0 + Procedure MarkerEditCloseWindow(MapGadget.i) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + ForEach *PBMap\Markers() + If *PBMap\Markers()\EditWindow = EventWindow() + *PBMap\Markers()\EditWindow = 0 EndIf Next CloseWindow(EventWindow()) EndProcedure - Procedure MarkerEdit(*Marker.Marker) + Procedure MarkerEdit(MapGadget.i, *Marker.Marker) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) 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) + 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")) TextGadget(#PB_Any, 2, 27, 80, 25, gettext("Legend")) @@ -1816,7 +1933,8 @@ Module PBMap EndIf EndProcedure - Procedure DrawMarker(x.i, y.i, Nb.i, *Marker.Marker) + Procedure DrawMarker(MapGadget.i, x.i, y.i, Nb.i, *Marker.Marker) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) Protected Text.s VectorSourceColor(*Marker\Color) MovePathCursor(x, y) @@ -1829,28 +1947,28 @@ Module PBMap VectorSourceColor(*Marker\Color) FillPath(#PB_Path_Preserve) If *Marker\Focus - VectorSourceColor(PBMap\Options\ColourFocus) + VectorSourceColor(*PBMap\Options\ColourFocus) StrokePath(3) ElseIf *Marker\Selected - VectorSourceColor(PBMap\Options\ColourSelected) + VectorSourceColor(*PBMap\Options\ColourSelected) StrokePath(4) Else VectorSourceColor(*Marker\Color) StrokePath(1) EndIf - If PBMap\Options\ShowMarkersNb + If *PBMap\Options\ShowMarkersNb If *Marker\Identifier = "" Text.s = Str(Nb) Else Text.s = *Marker\Identifier EndIf - VectorFont(FontID(PBMap\StandardFont), 13) + VectorFont(FontID(*PBMap\StandardFont), 13) MovePathCursor(x - VectorTextWidth(Text) / 2, y) VectorSourceColor(RGBA(0, 0, 0, 255)) DrawVectorText(Text) EndIf - If PBMap\Options\ShowMarkersLegend And *Marker\Legend <> "" - VectorFont(FontID(PBMap\StandardFont), 13) + If *PBMap\Options\ShowMarkersLegend And *Marker\Legend <> "" + VectorFont(FontID(*PBMap\StandardFont), 13) ; dessin d'un cadre avec fond transparent Protected Height = VectorParagraphHeight(*Marker\Legend, 100, 100) Protected Width.l @@ -1872,15 +1990,16 @@ Module PBMap EndProcedure ; Draw all markers - Procedure DrawMarkers(*Drawing.DrawingParameters) + Procedure DrawMarkers(MapGadget.i, *Drawing.DrawingParameters) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) Protected Pixel.PixelCoordinates - ForEach PBMap\Markers() - If IsInDrawingPixelBoundaries(*Drawing, @PBMap\Markers()\GeographicCoordinates) - LatLon2PixelRel(@PBMap\Markers()\GeographicCoordinates, @Pixel, PBMap\Zoom) - If PBMap\Markers()\CallBackPointer > 0 - CallFunctionFast(PBMap\Markers()\CallBackPointer, Pixel\x, Pixel\y, PBMap\Markers()\Focus, PBMap\Markers()\Selected) + ForEach *PBMap\Markers() + If IsInDrawingPixelBoundaries(MapGadget, *Drawing, @*PBMap\Markers()\GeographicCoordinates) + LatLon2PixelRel(MapGadget, @*PBMap\Markers()\GeographicCoordinates, @Pixel, *PBMap\Zoom) + If *PBMap\Markers()\CallBackPointer > 0 + CallFunctionFast(*PBMap\Markers()\CallBackPointer, Pixel\x, Pixel\y, *PBMap\Markers()\Focus, *PBMap\Markers()\Selected) Else - DrawMarker(Pixel\x, Pixel\y, ListIndex(PBMap\Markers()), @PBMap\Markers()) + DrawMarker(MapGadget, Pixel\x, Pixel\y, ListIndex(*PBMap\Markers()), @*PBMap\Markers()) EndIf EndIf Next @@ -1888,54 +2007,57 @@ Module PBMap ;-*** Main drawing stuff - Procedure DrawDebugInfos(*Drawing.DrawingParameters) + Procedure DrawDebugInfos(MapGadget.i, *Drawing.DrawingParameters) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) ; Display how many images in cache - VectorFont(FontID(PBMap\StandardFont), 16) + VectorFont(FontID(*PBMap\StandardFont), 16) VectorSourceColor(RGBA(0, 0, 0, 80)) MovePathCursor(50, 50) - DrawVectorText("Images in cache : " + Str(MapSize(PBMap\MemCache\Images()))) + DrawVectorText("Images in cache : " + Str(MapSize(*PBMap\MemCache\Images()))) MovePathCursor(50, 70) Protected ThreadCounter = 0 - ForEach PBMap\MemCache\Images() - If PBMap\MemCache\Images()\Tile > 0 - If IsThread(PBMap\MemCache\Images()\Tile\GetImageThread) + ForEach *PBMap\MemCache\Images() + If *PBMap\MemCache\Images()\Tile > 0 + If IsThread(*PBMap\MemCache\Images()\Tile\GetImageThread) ThreadCounter + 1 EndIf EndIf Next DrawVectorText("Threads nb : " + Str(ThreadCounter)) MovePathCursor(50, 90) - DrawVectorText("Zoom : " + Str(PBMap\Zoom)) + DrawVectorText("Zoom : " + Str(*PBMap\Zoom)) MovePathCursor(50, 110) DrawVectorText("Lat-Lon 1 : " + StrD(*Drawing\Bounds\NorthWest\Latitude) + "," + StrD(*Drawing\Bounds\NorthWest\Longitude)) MovePathCursor(50, 130) DrawVectorText("Lat-Lon 2 : " + StrD(*Drawing\Bounds\SouthEast\Latitude) + "," + StrD(*Drawing\Bounds\SouthEast\Longitude)) EndProcedure - Procedure DrawOSMCopyright(*Drawing.DrawingParameters) - Protected Text.s = "© OpenStreetMap contributors" - VectorFont(FontID(PBMap\StandardFont), 12) + Procedure DrawOSMCopyright(MapGadget.i, *Drawing.DrawingParameters) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + Protected Text.s = "© OpenStreetMap contributors" + VectorFont(FontID(*PBMap\StandardFont), 12) VectorSourceColor(RGBA(0, 0, 0, 80)) - MovePathCursor(GadgetWidth(PBMAP\Gadget) - VectorTextWidth(Text), GadgetHeight(PBMAP\Gadget) - 20) + MovePathCursor(DesktopScaledX(GadgetWidth(*PBMap\Gadget)) - VectorTextWidth(Text), GadgetHeight(*PBMap\Gadget) - 20) DrawVectorText(Text) EndProcedure - Procedure Drawing() - Protected *Drawing.DrawingParameters = @PBMap\Drawing + Procedure Drawing(MapGadget.i) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + Protected *Drawing.DrawingParameters = @*PBMap\Drawing Protected PixelCenter.PixelCoordinates - Protected Px.d, Py.d,a, ts = PBMap\TileSize, nx, ny + Protected Px.d, Py.d,a, ts = *PBMap\TileSize, nx, ny Protected LayerOrder.i = 0 Protected NW.Coordinates, SE.Coordinates Protected OSMCopyright.i = #False - PBMap\Dirty = #False - PBMap\Redraw = #False + *PBMap\Dirty = #False + *PBMap\Redraw = #False ; *** Precalc some values - *Drawing\RadiusX = GadgetWidth(PBMap\Gadget) / 2 - *Drawing\RadiusY = GadgetHeight(PBMap\Gadget) / 2 - *Drawing\GeographicCoordinates\Latitude = PBMap\GeographicCoordinates\Latitude - *Drawing\GeographicCoordinates\Longitude = PBMap\GeographicCoordinates\Longitude - LatLon2TileXY(*Drawing\GeographicCoordinates, *Drawing\TileCoordinates, PBMap\Zoom) - LatLon2Pixel(*Drawing\GeographicCoordinates, @PixelCenter, PBMap\Zoom) + *Drawing\RadiusX = DesktopScaledX(GadgetWidth(*PBMap\Gadget)) / 2 + *Drawing\RadiusY = DesktopScaledY(GadgetHeight(*PBMap\Gadget)) / 2 + *Drawing\GeographicCoordinates\Latitude = *PBMap\GeographicCoordinates\Latitude + *Drawing\GeographicCoordinates\Longitude = *PBMap\GeographicCoordinates\Longitude + LatLon2TileXY(*Drawing\GeographicCoordinates, *Drawing\TileCoordinates, *PBMap\Zoom) + LatLon2Pixel(MapGadget, *Drawing\GeographicCoordinates, @PixelCenter, *PBMap\Zoom) ; Pixel shift, aka position in the tile Px = *Drawing\TileCoordinates\x Py = *Drawing\TileCoordinates\y @@ -1948,109 +2070,124 @@ Module PBMap NW\y = Py - ny - 1 SE\x = Px + nx + 2 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 + 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 ; *** ; Main drawing stuff - StartVectorDrawing(CanvasVectorOutput(PBMap\Gadget)) + StartVectorDrawing(CanvasVectorOutput(*PBMap\Gadget)) ; 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 ; such as for openseamap tiles which are overlaid. not that efficent from here though. ; Draws layers based on their number - ForEach PBMap\LayersList() - If PBMap\LayersList()\Enabled - DrawTiles(*Drawing, PBMap\LayersList()\Name) + ForEach *PBMap\LayersList() + If *PBMap\LayersList()\Enabled + DrawTiles(MapGadget, *Drawing, *PBMap\LayersList()\Name) EndIf - If PBMap\LayersList()\LayerType = 0 ; OSM + If *PBMap\LayersList()\LayerType = 0 ; OSM OSMCopyright = #True EndIf Next - If PBMap\Options\ShowTrack - DrawTracks(*Drawing) + If *PBMap\Options\ShowTrack + DrawTracks(MapGadget, *Drawing) EndIf - If PBMap\Options\ShowMarkers - DrawMarkers(*Drawing) + If *PBMap\Options\ShowMarkers + DrawMarkers(MapGadget, *Drawing) EndIf - If PBMap\Options\ShowDegrees And PBMap\Zoom > 2 - DrawDegrees(*Drawing, 192) + If *PBMap\Options\ShowDegrees And *PBMap\Zoom > 2 + DrawDegrees(MapGadget, *Drawing, 192) EndIf - If PBMap\Options\ShowPointer - DrawPointer(*Drawing) + If *PBMap\Options\ShowPointer + DrawPointer(MapGadget, *Drawing) EndIf - If PBMap\Options\ShowDebugInfos - DrawDebugInfos(*Drawing) + If *PBMap\Options\ShowDebugInfos + DrawDebugInfos(MapGadget, *Drawing) EndIf - If PBMap\Options\ShowScale - DrawScale(*Drawing, 10, GadgetHeight(PBMAP\Gadget) - 20, 192) + If *PBMap\Options\ShowScale + DrawScale(MapGadget, *Drawing, 10, DesktopScaledY(GadgetHeight(*PBMap\Gadget)) - 20, 192) EndIf - If PBMap\Options\ShowZoom - DrawZoom(GadgetWidth(PBMap\Gadget) - 30, 5) ; ajout YA - affiche le niveau de zoom + If *PBMap\Options\ShowZoom + DrawZoom(MapGadget, DesktopScaledX(GadgetWidth(*PBMap\Gadget)) - 30, 5) ; ajout YA - affiche le niveau de zoom EndIf If OSMCopyright - DrawOSMCopyright(*Drawing) + DrawOSMCopyright(MapGadget, *Drawing) EndIf StopVectorDrawing() EndProcedure - Procedure Refresh() - PBMap\Redraw = #True + Procedure Refresh(MapGadget.i) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + *PBMap\Redraw = #True ; Drawing() EndProcedure ;-*** Misc functions - 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) + Procedure.d GetCanvasPixelLon(MapGadget.i, x) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + Protected MouseX.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[ ProcedureReturn Mod(Mod(MouseX / n * 360.0, 360.0) + 360.0, 360.0) - 180 EndProcedure - Procedure.d GetMouseLatitude() - Protected MouseY.d = (PBMap\PixelCoordinates\y - PBMap\Drawing\RadiusY + GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_MouseY)) / PBMap\TileSize - Protected n.d = Pow(2.0, PBMap\Zoom) + Procedure.d GetCanvasPixelLat(MapGadget.i, y) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + Protected MouseY.d = (*PBMap\PixelCoordinates\y - *PBMap\Drawing\RadiusY + y) / *PBMap\TileSize + Protected n.d = Pow(2.0, *PBMap\Zoom) ProcedureReturn Degree(ATan(SinH(#PI * (1.0 - 2.0 * MouseY / n)))) EndProcedure + + Procedure.d GetMouseLongitude(MapGadget.i) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + ProcedureReturn GetCanvasPixelLon(MapGadget.i, GetGadgetAttribute(*PBMap\Gadget, #PB_Canvas_MouseX)) + EndProcedure - Procedure SetLocation(latitude.d, longitude.d, Zoom = -1, Mode.i = #PB_Absolute) + 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) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) Select Mode Case #PB_Absolute - PBMap\GeographicCoordinates\Latitude = latitude - PBMap\GeographicCoordinates\Longitude = longitude + *PBMap\GeographicCoordinates\Latitude = latitude + *PBMap\GeographicCoordinates\Longitude = longitude If Zoom <> -1 - PBMap\Zoom = Zoom + *PBMap\Zoom = Zoom EndIf Case #PB_Relative - PBMap\GeographicCoordinates\Latitude + latitude - PBMap\GeographicCoordinates\Longitude + longitude + *PBMap\GeographicCoordinates\Latitude + latitude + *PBMap\GeographicCoordinates\Longitude + longitude If Zoom <> -1 - PBMap\Zoom + Zoom + *PBMap\Zoom + Zoom EndIf EndSelect - PBMap\GeographicCoordinates\Longitude = ClipLongitude(PBMap\GeographicCoordinates\Longitude) - If PBMap\GeographicCoordinates\Latitude < -89 - PBMap\GeographicCoordinates\Latitude = -89 + *PBMap\GeographicCoordinates\Longitude = ClipLongitude(*PBMap\GeographicCoordinates\Longitude) + If *PBMap\GeographicCoordinates\Latitude < -89 + *PBMap\GeographicCoordinates\Latitude = -89 EndIf - If PBMap\GeographicCoordinates\Latitude > 89 - PBMap\GeographicCoordinates\Latitude = 89 + If *PBMap\GeographicCoordinates\Latitude > 89 + *PBMap\GeographicCoordinates\Latitude = 89 EndIf - If PBMap\Zoom > PBMap\ZoomMax : PBMap\Zoom = PBMap\ZoomMax : EndIf - If PBMap\Zoom < PBMap\ZoomMin : PBMap\Zoom = PBMap\ZoomMin : EndIf - LatLon2TileXY(@PBMap\GeographicCoordinates, @PBMap\Drawing\TileCoordinates, PBMap\Zoom) + If *PBMap\Zoom > *PBMap\ZoomMax : *PBMap\Zoom = *PBMap\ZoomMax : EndIf + If *PBMap\Zoom < *PBMap\ZoomMin : *PBMap\Zoom = *PBMap\ZoomMin : EndIf + LatLon2TileXY(@*PBMap\GeographicCoordinates, @*PBMap\Drawing\TileCoordinates, *PBMap\Zoom) ; Convert X, Y in tile.decimal into real pixels - PBMap\PixelCoordinates\x = PBMap\Drawing\TileCoordinates\x * PBMap\TileSize - PBMap\PixelCoordinates\y = PBMap\Drawing\TileCoordinates\y * PBMap\TileSize - PBMap\Redraw = #True - If PBMap\CallBackLocation > 0 - CallFunctionFast(PBMap\CallBackLocation, @PBMap\GeographicCoordinates) + *PBMap\PixelCoordinates\x = *PBMap\Drawing\TileCoordinates\x * *PBMap\TileSize + *PBMap\PixelCoordinates\y = *PBMap\Drawing\TileCoordinates\y * *PBMap\TileSize + *PBMap\Redraw = #True + If *PBMap\CallBackLocation > 0 + CallFunctionFast(*PBMap\CallBackLocation, @*PBMap\GeographicCoordinates) EndIf EndProcedure - Procedure SetZoomToArea(MinY.d, MaxY.d, MinX.d, MaxX.d) + Procedure SetZoomToArea(MapGadget.i, MinY.d, MaxY.d, MinX.d, MaxX.d) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) ; 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 @@ -2060,24 +2197,25 @@ Module PBMap 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 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 viewHeightHalf.d = *PBMap\Drawing\RadiusY ; Protected zoomFactorPowered.d = viewHeightHalf / (40.7436654315252*(vy1 - vy0)) - Protected resolutionVertical.d = 360.0 / (zoomFactorPowered * PBMap\TileSize) + 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 zoom.d = Log(360 / (resolution * *PBMap\TileSize))/Log(2) Protected lon.d = centerX; Protected lat.d = centerY; - SetLocation(lat, lon, Round(zoom,#PB_Round_Down)) + SetLocation(MapGadget, lat, lon, Round(zoom,#PB_Round_Down)) Else - SetLocation(PBMap\GeographicCoordinates\Latitude, PBMap\GeographicCoordinates\Longitude, 15) + SetLocation(MapGadget, *PBMap\GeographicCoordinates\Latitude, *PBMap\GeographicCoordinates\Longitude, 15) EndIf EndProcedure - Procedure SetZoomToTracks(*Tracks.Tracks) + Procedure SetZoomToTracks(MapGadget.i, *Tracks.Tracks) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) Protected MinY.d, MaxY.d, MinX.d, MaxX.d If ListSize(*Tracks\Track()) > 0 With *Tracks\Track() @@ -2097,60 +2235,81 @@ Module PBMap MaxY = \Latitude EndIf Next - SetZoomToArea(MinY.d, MaxY.d, MinX.d, MaxX.d) + SetZoomToArea(MapGadget, MinY.d, MaxY.d, MinX.d, MaxX.d) EndWith EndIf EndProcedure - Procedure SetZoom(Zoom.i, mode.i = #PB_Relative) + Procedure SetZoom(MapGadget.i, Zoom.i, mode.i = #PB_Relative) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) Select mode Case #PB_Relative - PBMap\Zoom = PBMap\Zoom + zoom + *PBMap\Zoom = *PBMap\Zoom + zoom Case #PB_Absolute - PBMap\Zoom = zoom + *PBMap\Zoom = zoom EndSelect - If PBMap\Zoom > PBMap\ZoomMax : PBMap\Zoom = PBMap\ZoomMax : ProcedureReturn : EndIf - If PBMap\Zoom < PBMap\ZoomMin : PBMap\Zoom = PBMap\ZoomMin : ProcedureReturn : EndIf - LatLon2TileXY(@PBMap\GeographicCoordinates, @PBMap\Drawing\TileCoordinates, PBMap\Zoom) + If *PBMap\Zoom > *PBMap\ZoomMax : *PBMap\Zoom = *PBMap\ZoomMax : ProcedureReturn : EndIf + If *PBMap\Zoom < *PBMap\ZoomMin : *PBMap\Zoom = *PBMap\ZoomMin : ProcedureReturn : EndIf + LatLon2TileXY(@*PBMap\GeographicCoordinates, @*PBMap\Drawing\TileCoordinates, *PBMap\Zoom) ; Convert X, Y in tile.decimal into real pixels - PBMap\PixelCoordinates\X = PBMap\Drawing\TileCoordinates\x * PBMap\TileSize - PBMap\PixelCoordinates\Y = PBMap\Drawing\TileCoordinates\y * PBMap\TileSize + *PBMap\PixelCoordinates\X = *PBMap\Drawing\TileCoordinates\x * *PBMap\TileSize + *PBMap\PixelCoordinates\Y = *PBMap\Drawing\TileCoordinates\y * *PBMap\TileSize ; First drawing - PBMap\Redraw = #True - If PBMap\CallBackLocation > 0 - CallFunctionFast(PBMap\CallBackLocation, @PBMap\GeographicCoordinates) + *PBMap\Redraw = #True + If *PBMap\CallBackLocation > 0 + CallFunctionFast(*PBMap\CallBackLocation, @*PBMap\GeographicCoordinates) EndIf EndProcedure - Procedure SetAngle(Angle.d, Mode = #PB_Absolute) + Procedure SetAngle(MapGadget.i, Angle.d, Mode = #PB_Absolute) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) If Mode = #PB_Absolute - PBmap\Angle = Angle + *PBMap\Angle = Angle Else - PBMap\Angle + Angle - PBMap\Angle = Mod(PBMap\Angle,360) + *PBMap\Angle + Angle + *PBMap\Angle = Mod(*PBMap\Angle,360) EndIf - PBMap\Redraw = #True + *PBMap\Redraw = #True EndProcedure - Procedure SetCallBackLocation(CallBackLocation.i) - PBMap\CallBackLocation = CallBackLocation + ;-*** Callbacks + + Procedure SetCallBackLocation(MapGadget.i, CallBackLocation.i) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + *PBMap\CallBackLocation = CallBackLocation EndProcedure - Procedure SetCallBackMainPointer(CallBackMainPointer.i) - PBMap\CallBackMainPointer = CallBackMainPointer + Procedure SetCallBackMainPointer(MapGadget.i, CallBackMainPointer.i) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + *PBMap\CallBackMainPointer = CallBackMainPointer EndProcedure - Procedure SetCallBackMarker(CallBackLocation.i) - PBMap\CallBackMarker = CallBackLocation + Procedure SetCallBackMarker(MapGadget.i, CallBackLocation.i) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + *PBMap\CallBackMarker = CallBackLocation EndProcedure - Procedure SetCallBackLeftClic(CallBackLocation.i) - PBMap\CallBackLeftClic = CallBackLocation + Procedure SetCallBackLeftClic(MapGadget.i, CallBackLocation.i) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + *PBMap\CallBackLeftClic = CallBackLocation EndProcedure - Procedure SetMapScaleUnit(ScaleUnit.i = PBMAP::#SCALE_KM) - PBMap\Options\ScaleUnit = ScaleUnit - PBMap\Redraw = #True + Procedure SetCallBackDrawTile(MapGadget.i, CallBackLocation.i) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + *PBMap\CallBackDrawTile = CallBackLocation + EndProcedure + + Procedure SetCallBackModifyTileFile(MapGadget.i, CallBackLocation.i) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + *PBMap\CallBackModifyTileFile = CallBackLocation + EndProcedure + + ;*** + + Procedure SetMapScaleUnit(MapGadget.i, ScaleUnit.i = PBMAP::#SCALE_KM) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + *PBMap\Options\ScaleUnit = ScaleUnit + *PBMap\Redraw = #True ; Drawing() EndProcedure @@ -2159,102 +2318,113 @@ Module PBMap ; #MODE_HAND = 1 -> Hand only ; #MODE_SELECT = 2 -> Move objects only ; #MODE_EDIT = 3 -> Create objects - Procedure SetMode(Mode.i = #MODE_DEFAULT) - PBMap\Mode = Mode + Procedure SetMode(MapGadget.i, Mode.i = #MODE_DEFAULT) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + *PBMap\Mode = Mode EndProcedure - Procedure.i GetMode() - ProcedureReturn PBMap\Mode + Procedure.i GetMode(MapGadget.i) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + ProcedureReturn *PBMap\Mode EndProcedure ; Zoom on x, y pixel position from the center - Procedure SetZoomOnPixel(x, y, zoom) + Procedure SetZoomOnPixel(MapGadget.i, x, y, zoom) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) ; *** 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 - LatLon2Pixel(@PBMap\GeographicCoordinates, @PBMap\PixelCoordinates, PBMap\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 + LatLon2Pixel(MapGadget, @*PBMap\GeographicCoordinates, @*PBMap\PixelCoordinates, *PBMap\Zoom) If Zoom = 1 - PBMap\PixelCoordinates\x + x - PBMap\PixelCoordinates\y + y + *PBMap\PixelCoordinates\x + x + *PBMap\PixelCoordinates\y + y ElseIf zoom = -1 - PBMap\PixelCoordinates\x - x/2 - PBMap\PixelCoordinates\y - y/2 + *PBMap\PixelCoordinates\x - x/2 + *PBMap\PixelCoordinates\y - y/2 EndIf - Pixel2LatLon(@PBMap\PixelCoordinates, @PBMap\GeographicCoordinates, PBMap\Zoom) + Pixel2LatLon(MapGadget, @*PBMap\PixelCoordinates, @*PBMap\GeographicCoordinates, *PBMap\Zoom) ; Start drawing - PBMap\Redraw = #True + *PBMap\Redraw = #True ; If CallBackLocation send Location To function - If PBMap\CallBackLocation > 0 - CallFunctionFast(PBMap\CallBackLocation, @PBMap\GeographicCoordinates) + If *PBMap\CallBackLocation > 0 + CallFunctionFast(*PBMap\CallBackLocation, @*PBMap\GeographicCoordinates) EndIf EndProcedure ; 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) + Procedure SetZoomOnPixelRel(MapGadget.i, x, y, zoom) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + SetZoomOnPixel(MapGadget, x - *PBMap\Drawing\RadiusX, y - *PBMap\Drawing\RadiusY, zoom) EndProcedure ; 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 - PBMap\PixelCoordinates\y + y - PBMap\Drawing\RadiusY - Pixel2LatLon(@PBMap\PixelCoordinates, @PBMap\GeographicCoordinates, PBMap\Zoom) + Procedure GotoPixelRel(MapGadget.i, x, y) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + LatLon2Pixel(MapGadget, @*PBMap\GeographicCoordinates, @*PBMap\PixelCoordinates, *PBMap\Zoom) + *PBMap\PixelCoordinates\x + x - *PBMap\Drawing\RadiusX + *PBMap\PixelCoordinates\y + y - *PBMap\Drawing\RadiusY + Pixel2LatLon(MapGadget, @*PBMap\PixelCoordinates, @*PBMap\GeographicCoordinates, *PBMap\Zoom) ; Start drawing - PBMap\Redraw = #True + *PBMap\Redraw = #True ; If CallBackLocation send Location to function - If PBMap\CallBackLocation > 0 - CallFunctionFast(PBMap\CallBackLocation, @PBMap\GeographicCoordinates) + If *PBMap\CallBackLocation > 0 + CallFunctionFast(*PBMap\CallBackLocation, @*PBMap\GeographicCoordinates) EndIf EndProcedure ; Go to x, y position relative to the canvas gadget - Procedure GotoPixel(x, y) - PBMap\PixelCoordinates\x = x - PBMap\PixelCoordinates\y = y - Pixel2LatLon(@PBMap\PixelCoordinates, @PBMap\GeographicCoordinates, PBMap\Zoom) + Procedure GotoPixel(MapGadget.i, x, y) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + *PBMap\PixelCoordinates\x = x + *PBMap\PixelCoordinates\y = y + Pixel2LatLon(MapGadget, @*PBMap\PixelCoordinates, @*PBMap\GeographicCoordinates, *PBMap\Zoom) ; Start drawing - PBMap\Redraw = #True + *PBMap\Redraw = #True ; If CallBackLocation send Location to function - If PBMap\CallBackLocation > 0 - CallFunctionFast(PBMap\CallBackLocation, @PBMap\GeographicCoordinates) + If *PBMap\CallBackLocation > 0 + CallFunctionFast(*PBMap\CallBackLocation, @*PBMap\GeographicCoordinates) EndIf EndProcedure - Procedure.d GetLatitude() - ProcedureReturn PBMap\GeographicCoordinates\Latitude + Procedure.d GetLatitude(MapGadget.i) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + ProcedureReturn *PBMap\GeographicCoordinates\Latitude EndProcedure - Procedure.d GetLongitude() - ProcedureReturn PBMap\GeographicCoordinates\Longitude + Procedure.d GetLongitude(MapGadget.i) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + ProcedureReturn *PBMap\GeographicCoordinates\Longitude EndProcedure - Procedure.i GetZoom() - ProcedureReturn PBMap\Zoom + Procedure.i GetZoom(MapGadget.i) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + ProcedureReturn *PBMap\Zoom EndProcedure - Procedure.d GetAngle() - ProcedureReturn PBMap\Angle + Procedure.d GetAngle(MapGadget.i) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + ProcedureReturn *PBMap\Angle EndProcedure - Procedure NominatimGeoLocationQuery(Address.s, *ReturnPosition.GeographicCoordinates = 0) + Procedure NominatimGeoLocationQuery(MapGadget.i, Address.s, *ReturnPosition.GeographicCoordinates = 0) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) Protected Size.i Protected Query.s = "http://nominatim.openstreetmap.org/search/" + 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) + 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) - If PBMap\Options\Proxy - HTTPProxy(PBMap\Options\ProxyURL + ":" + PBMap\Options\ProxyPort, PBMap\Options\ProxyUser, PBMap\Options\ProxyPassword) + 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 - MyDebug( JSONErrorMessage() + " at position " + + MyDebug(*PBMap, JSONErrorMessage() + " at position " + JSONErrorPosition() + " in line " + JSONErrorLine() + " of JSON web Data", 1) ElseIf JSONArraySize(JSONValue(0)) > 0 @@ -2272,25 +2442,26 @@ Module PBMap *ReturnPosition\Longitude = ValD(lon) EndIf If lat <> "" And lon <> "" - SetZoomToArea(bbox\SouthEast\Latitude, bbox\NorthWest\Latitude, bbox\NorthWest\Longitude, bbox\SouthEast\Longitude) + SetZoomToArea(MapGadget, bbox\SouthEast\Latitude, bbox\NorthWest\Latitude, bbox\NorthWest\Longitude, bbox\SouthEast\Longitude) ; SetLocation(Position\Latitude, Position\Longitude) EndIf EndIf EndProcedure - Procedure.i ClearDiskCache() - If PBMap\Options\Warning - Protected Result.i = MessageRequester("Warning", "You will clear all cache content in " + PBMap\Options\HDDCachePath + ". Are you sure ?",#PB_MessageRequester_YesNo) + Procedure.i ClearDiskCache(MapGadget.i) + Protected *PBMap.PBMap = PBMaps(Str(MapGadget)) + If *PBMap\Options\Warning + Protected Result.i = MessageRequester("Warning", "You will clear all cache content in " + *PBMap\Options\HDDCachePath + ". Are you sure ?",#PB_MessageRequester_YesNo) If Result = #PB_MessageRequester_No ; Quit if "no" selected ProcedureReturn #False EndIf EndIf - If DeleteDirectory(PBMap\Options\HDDCachePath, "", #PB_FileSystem_Recursive) - MyDebug("Cache in : " + PBMap\Options\HDDCachePath + " cleared", 3) - CreateDirectoryEx(PBMap\Options\HDDCachePath) + If DeleteDirectory(*PBMap\Options\HDDCachePath, "", #PB_FileSystem_Recursive) + MyDebug(*PBMap, "Cache in : " + *PBMap\Options\HDDCachePath + " cleared", 3) + CreateDirectoryEx(*PBMap\Options\HDDCachePath) ProcedureReturn #True Else - MyDebug("Can't clear cache in " + PBMap\Options\HDDCachePath, 3) + MyDebug(*PBMap, "Can't clear cache in " + *PBMap\Options\HDDCachePath, 3) ProcedureReturn #False EndIf EndProcedure @@ -2299,323 +2470,319 @@ Module PBMap Procedure CanvasEvents() Protected CanvasMouseX.d, CanvasMouseY.d, MouseX.d, MouseY.d - Protected MarkerCoords.PixelCoordinates, *Tile.Tile, MapWidth = Pow(2, PBMap\Zoom) * PBMap\TileSize + Protected MarkerCoords.PixelCoordinates, *Tile.Tile, MapWidth Protected key.s, Touch.i Protected Pixel.PixelCoordinates + Protected ImgNB.i, TileNewFilename.s Static CtrlKey Protected Location.GeographicCoordinates - CanvasMouseX = GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_MouseX) - PBMap\Drawing\RadiusX - CanvasMouseY = GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_MouseY) - PBMap\Drawing\RadiusY + Protected MapGadget.i = EventGadget() + + Protected *PBMap.PBmap = PBMaps(Str(MapGadget)) + MapWidth = Pow(2, *PBMap\Zoom) * *PBMap\TileSize + 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) + ; 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 - PBMap\Drawing\RadiusY = GadgetHeight(PBMap\Gadget) / 2 + *PBMap\Drawing\RadiusX = DesktopScaledX(GadgetWidth(*PBMap\Gadget)) / 2 + *PBMap\Drawing\RadiusY = DesktopScaledY(GadgetHeight(*PBMap\Gadget)) / 2 Case #PB_EventType_KeyUp - Select GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_Key) + Select GetGadgetAttribute(*PBMap\Gadget, #PB_Canvas_Key) Case #PB_Shortcut_Delete - DeleteSelectedMarkers() - DeleteSelectedTracks() + DeleteSelectedMarkers(MapGadget) + DeleteSelectedTracks(MapGadget) EndSelect - PBMap\Redraw = #True - If GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_Modifiers)&#PB_Canvas_Control = 0 + *PBMap\Redraw = #True + If GetGadgetAttribute(*PBMap\Gadget, #PB_Canvas_Modifiers)&#PB_Canvas_Control = 0 CtrlKey = #False EndIf Case #PB_EventType_KeyDown - With PBMap\Markers() - Select GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_Key) + With *PBMap\Markers() + Select GetGadgetAttribute(*PBMap\Gadget, #PB_Canvas_Key) Case #PB_Shortcut_Left - ForEach PBMap\Markers() + ForEach *PBMap\Markers() If \Selected - \GeographicCoordinates\Longitude = ClipLongitude( \GeographicCoordinates\Longitude - 10* 360 / Pow(2, PBMap\Zoom + 8)) + \GeographicCoordinates\Longitude = ClipLongitude( \GeographicCoordinates\Longitude - 10* 360 / Pow(2, *PBMap\Zoom + 8)) EndIf Next Case #PB_Shortcut_Up - ForEach PBMap\Markers() + ForEach *PBMap\Markers() If \Selected - \GeographicCoordinates\Latitude + 10* 360 / Pow(2, PBMap\Zoom + 8) + \GeographicCoordinates\Latitude + 10* 360 / Pow(2, *PBMap\Zoom + 8) EndIf Next Case #PB_Shortcut_Right - ForEach PBMap\Markers() + ForEach *PBMap\Markers() If \Selected - \GeographicCoordinates\Longitude = ClipLongitude( \GeographicCoordinates\Longitude + 10* 360 / Pow(2, PBMap\Zoom + 8)) + \GeographicCoordinates\Longitude = ClipLongitude( \GeographicCoordinates\Longitude + 10* 360 / Pow(2, *PBMap\Zoom + 8)) EndIf Next Case #PB_Shortcut_Down - ForEach PBMap\Markers() + ForEach *PBMap\Markers() If \Selected - \GeographicCoordinates\Latitude - 10* 360 / Pow(2, PBMap\Zoom + 8) + \GeographicCoordinates\Latitude - 10* 360 / Pow(2, *PBMap\Zoom + 8) EndIf Next EndSelect EndWith - PBMap\Redraw = #True - If GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_Modifiers)&#PB_Canvas_Control <> 0 + *PBMap\Redraw = #True + If GetGadgetAttribute(*PBMap\Gadget, #PB_Canvas_Modifiers)&#PB_Canvas_Control <> 0 CtrlKey = #True EndIf Case #PB_EventType_LeftDoubleClick - LatLon2Pixel(@PBMap\GeographicCoordinates, @PBMap\PixelCoordinates, PBMap\Zoom) - MouseX = PBMap\PixelCoordinates\x + CanvasMouseX - MouseY = PBMap\PixelCoordinates\y + CanvasMouseY + LatLon2Pixel(MapGadget, @*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) MouseX = Mod(Mod(MouseX, MapWidth) + MapWidth, MapWidth) Touch = #False ; Check if the mouse touch a marker - ForEach PBMap\Markers() - LatLon2Pixel(@PBMap\Markers()\GeographicCoordinates, @MarkerCoords, PBMap\Zoom) + ForEach *PBMap\Markers() + LatLon2Pixel(MapGadget, @*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 + If *PBMap\Mode = #MODE_DEFAULT Or *PBMap\Mode = #MODE_SELECT ; Jump to the marker Touch = #True - SetLocation(PBMap\Markers()\GeographicCoordinates\Latitude, PBMap\Markers()\GeographicCoordinates\Longitude) - ElseIf PBMap\Mode = #MODE_EDIT + SetLocation(MapGadget, *PBMap\Markers()\GeographicCoordinates\Latitude, *PBMap\Markers()\GeographicCoordinates\Longitude) + ElseIf *PBMap\Mode = #MODE_EDIT ; Edit the legend - MarkerEdit(@PBMap\Markers()) + MarkerEdit(MapGadget, @*PBMap\Markers()) EndIf Break EndIf Next If Not Touch - GotoPixel(MouseX, MouseY) + GotoPixel(MapGadget, MouseX, MouseY) EndIf Case #PB_EventType_MouseWheel - If PBMap\Options\WheelMouseRelative + If *PBMap\Options\WheelMouseRelative ; Relative zoom (centered on the mouse) - SetZoomOnPixel(CanvasMouseX, CanvasMouseY, GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_WheelDelta)) + SetZoomOnPixel(MapGadget, CanvasMouseX, CanvasMouseY, GetGadgetAttribute(*PBMap\Gadget, #PB_Canvas_WheelDelta)) Else ; Absolute zoom (centered on the center of the map) - SetZoom(GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_WheelDelta), #PB_Relative) - EndIf + SetZoom(MapGadget, GetGadgetAttribute(*PBMap\Gadget, #PB_Canvas_WheelDelta), #PB_Relative) + 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 - ; LatLon2Pixel(@PBMap\GeographicCoordinates, @PBMap\PixelCoordinates, PBMap\Zoom) - PBMap\Dragging = #True + ; LatLon2Pixel(@*PBMap\GeographicCoordinates, @*PBMap\PixelCoordinates, *PBMap\Zoom) + *PBMap\Dragging = #True ; Memorize cursor Coord - PBMap\MoveStartingPoint\x = CanvasMouseX - PBMap\MoveStartingPoint\y = CanvasMouseY + *PBMap\MoveStartingPoint\x = CanvasMouseX + *PBMap\MoveStartingPoint\y = CanvasMouseY ; 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 + *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) - ForEach PBMap\Markers() + 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\Markers()\Focus = #False + If *PBMap\Markers()\Focus + *PBMap\Markers()\Selected = #True + *PBMap\EditMarker = #True; ListIndex(*PBMap\Markers()) + *PBMap\Markers()\Focus = #False EndIf Next ; Check if we select track(s) - ForEach PBMap\TracksList() + 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 - PBMap\TracksList()\Focus = #False + If *PBMap\TracksList()\Focus + *PBMap\TracksList()\Selected = #True + *PBMap\TracksList()\Focus = #False EndIf Next EndIf - ; YA pour sélectionner un point de la trace avec le clic gauche - If PBMap\EditMarker = #False - Location\Latitude = GetMouseLatitude() - Location\Longitude = GetMouseLongitude() - If PBMap\CallBackLeftClic > 0 - CallFunctionFast(PBMap\CallBackLeftClic, @Location) + ; YA To select a track with LMB + If *PBMap\EditMarker = #False + Location\Latitude = GetMouseLatitude(MapGadget) + Location\Longitude = GetMouseLongitude(MapGadget) + If *PBMap\CallBackLeftClic > 0 + CallFunctionFast(*PBMap\CallBackLeftClic, @Location) EndIf - ; ajout YA // change la forme du pointeur de souris pour les déplacements de la carte - SetGadgetAttribute(PBMap\Gadget, #PB_Canvas_Cursor, #PB_Cursor_Hand) + ; ajout YA // Mouse pointer when moving map + SetGadgetAttribute(*PBMap\Gadget, #PB_Canvas_Cursor, #PB_Cursor_Hand) 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 EndIf Case #PB_EventType_MouseMove ; Drag - If PBMap\Dragging - ; If PBMap\MoveStartingPoint\x <> - 1 - MouseX = CanvasMouseX - PBMap\MoveStartingPoint\x - MouseY = CanvasMouseY - PBMap\MoveStartingPoint\y - PBMap\MoveStartingPoint\x = CanvasMouseX - PBMap\MoveStartingPoint\y = CanvasMouseY + If *PBMap\Dragging + ; 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 - If PBMap\EditMarker And (PBMap\Mode = #MODE_DEFAULT Or PBMap\Mode = #MODE_SELECT) - ForEach PBMap\Markers() - If PBMap\Markers()\Selected - LatLon2Pixel(@PBMap\Markers()\GeographicCoordinates, @MarkerCoords, PBMap\Zoom) + If *PBMap\EditMarker And (*PBMap\Mode = #MODE_DEFAULT Or *PBMap\Mode = #MODE_SELECT) + ForEach *PBMap\Markers() + If *PBMap\Markers()\Selected + LatLon2Pixel(MapGadget, @*PBMap\Markers()\GeographicCoordinates, @MarkerCoords, *PBMap\Zoom) MarkerCoords\x + MouseX MarkerCoords\y + MouseY - Pixel2LatLon(@MarkerCoords, @PBMap\Markers()\GeographicCoordinates, PBMap\Zoom) + Pixel2LatLon(MapGadget, @MarkerCoords, @*PBMap\Markers()\GeographicCoordinates, *PBMap\Zoom) EndIf Next - ElseIf PBMap\Mode = #MODE_DEFAULT Or PBMap\Mode = #MODE_HAND + 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 - PBMap\PixelCoordinates\x - MouseX - ; 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) + LatLon2Pixel(MapGadget, @*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 + *PBMap\PixelCoordinates\x = Mod(Mod(*PBMap\PixelCoordinates\x, MapWidth) + MapWidth, MapWidth) + *PBMap\PixelCoordinates\y - MouseY + Pixel2LatLon(MapGadget, @*PBMap\PixelCoordinates, @*PBMap\GeographicCoordinates, *PBMap\Zoom) ; If CallBackLocation send Location to function - If PBMap\CallBackLocation > 0 - CallFunctionFast(PBMap\CallBackLocation, @PBMap\GeographicCoordinates) + If *PBMap\CallBackLocation > 0 + CallFunctionFast(*PBMap\CallBackLocation, @*PBMap\GeographicCoordinates) EndIf EndIf - PBMap\Redraw = #True + *PBMap\Redraw = #True Else ; Touch test - LatLon2Pixel(@PBMap\GeographicCoordinates, @PBMap\PixelCoordinates, PBMap\Zoom) - MouseX = PBMap\PixelCoordinates\x + CanvasMouseX - MouseY = PBMap\PixelCoordinates\y + CanvasMouseY + LatLon2Pixel(MapGadget, @*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) MouseX = Mod(Mod(MouseX, MapWidth) + MapWidth, MapWidth) - If PBMap\Mode = #MODE_DEFAULT Or PBMap\Mode = #MODE_SELECT Or PBMap\Mode = #MODE_EDIT + If *PBMap\Mode = #MODE_DEFAULT Or *PBMap\Mode = #MODE_SELECT Or *PBMap\Mode = #MODE_EDIT ; Check if mouse touch markers - ForEach PBMap\Markers() - LatLon2Pixel(@PBMap\Markers()\GeographicCoordinates, @MarkerCoords, PBMap\Zoom) + ForEach *PBMap\Markers() + LatLon2Pixel(MapGadget, @*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 + *PBMap\Markers()\Focus = #True + *PBMap\Redraw = #True + ElseIf *PBMap\Markers()\Focus ; If CtrlKey = #False - PBMap\Markers()\Focus = #False - PBMap\Redraw = #True + *PBMap\Markers()\Focus = #False + *PBMap\Redraw = #True EndIf Next ; Check if mouse touch tracks - If PBMap\Options\ShowTrackSelection ; YA ajout pour éviter la sélection de la trace - With PBMap\TracksList() - ; Trace Track - If ListSize(PBMap\TracksList()) > 0 - ForEach PBMap\TracksList() - If ListSize(\Track()) > 0 - If \Visible - StartVectorDrawing(CanvasVectorOutput(PBMap\Gadget)) - ; Simulates track drawing - ForEach \Track() - LatLon2Pixel(@PBMap\TracksList()\Track(), @Pixel, PBMap\Zoom) - If ListIndex(\Track()) = 0 - MovePathCursor(Pixel\x, Pixel\y) - Else - AddPathLine(Pixel\x, Pixel\y) + If *PBMap\Options\ShowTrackSelection ; YA to avoid selecting track + With *PBMap\TracksList() + ; Trace Track + If ListSize(*PBMap\TracksList()) > 0 + ForEach *PBMap\TracksList() + If ListSize(\Track()) > 0 + If \Visible + StartVectorDrawing(CanvasVectorOutput(*PBMap\Gadget)) + ; Simulates track drawing + ForEach \Track() + LatLon2Pixel(MapGadget, @*PBMap\TracksList()\Track(), @Pixel, *PBMap\Zoom) + If ListIndex(\Track()) = 0 + MovePathCursor(Pixel\x, Pixel\y) + Else + AddPathLine(Pixel\x, Pixel\y) + EndIf + Next + If IsInsideStroke(MouseX, MouseY, \StrokeWidth) + \Focus = #True + *PBMap\Redraw = #True + ElseIf \Focus + \Focus = #False + *PBMap\Redraw = #True EndIf - Next - If IsInsideStroke(MouseX, MouseY, \StrokeWidth) - \Focus = #True - PBMap\Redraw = #True - ElseIf \Focus - \Focus = #False - PBMap\Redraw = #True - EndIf - StopVectorDrawing() - EndIf - EndIf - Next - EndIf - EndWith + StopVectorDrawing() + EndIf + EndIf + Next + EndIf + EndWith + EndIf EndIf EndIf - EndIf Case #PB_EventType_LeftButtonUp - SetGadgetAttribute(PBMap\Gadget,#PB_Canvas_Cursor,#PB_Cursor_Default) ; ajout YA pour remettre le pointeur souris en normal - ; PBMap\MoveStartingPoint\x = - 1 - PBMap\Dragging = #False - PBMap\Redraw = #True - ;YA pour connaitre les coordonnées d'un marqueur après déplacement - ForEach PBMap\Markers() - If PBMap\Markers()\Selected = #True - If PBMap\CallBackMarker > 0 - CallFunctionFast(PBMap\CallBackMarker, @PBMap\Markers()); + SetGadgetAttribute(*PBMap\Gadget,#PB_Canvas_Cursor,#PB_Cursor_Default) ; YA normal mouse pointer + ; *PBMap\MoveStartingPoint\x = - 1 + *PBMap\Dragging = #False + *PBMap\Redraw = #True + ;YA to knows marker coordinates after moving + ForEach *PBMap\Markers() + If *PBMap\Markers()\Selected = #True + If *PBMap\CallBackMarker > 0 + CallFunctionFast(*PBMap\CallBackMarker, @*PBMap\Markers()); EndIf EndIf Next Case #PB_MAP_REDRAW - PBMap\Redraw = #True + *PBMap\Redraw = #True Case #PB_MAP_RETRY - PBMap\Redraw = #True - ;- Tile web loading thread cleanup - ; After a Web tile loading thread, clean the tile structure memory, see GetImageThread() + *PBMap\Redraw = #True + ;- *** Tile web loading thread cleanup + ; After a Web tile loading thread, cleans the tile structure memory, see GetImageThread() Case #PB_MAP_TILE_CLEANUP + LockMutex(*PBMap\MemoryCacheAccessMutex) ; Prevents threads to start or finish *Tile = EventData() key = *Tile\key *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) - PBMap\MemCache\Images(key)\Tile = *Tile\Size + ;*PBMap\MemCache\Images(key)\Tile = *Tile\Size If *Tile\Size - PBMap\MemCache\Images(key)\Tile = -1 ; Web loading thread has finished successfully + ;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 + ; Allows to post edit the tile image file with a customised code + If *PBMap\CallBackModifyTileFile + TileNewFilename = *PBMap\CallBackModifyTileFile(*Tile\CacheFile, *Tile\URL) + If TileNewFilename + ;TODO : Not used by now, a new filename is sent back + *Tile\CacheFile = TileNewFilename + EndIf + EndIf 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 - FreeMemory(*Tile) ; Frees the data needed for the thread (*tile=PBMap\MemCache\Images(key)\Tile) - PBMap\ThreadsNB - 1 - PBMap\DownloadSlots - 1 - PBMap\Redraw = #True + FreeMemory(*Tile) ; Frees the data needed for the thread (*tile=*PBMap\MemCache\Images(key)\Tile) + *PBMap\ThreadsNB - 1 + *PBMap\DownloadSlots - 1 + *PBMap\Redraw = #True + UnlockMutex(*PBMap\MemoryCacheAccessMutex) EndSelect EndProcedure - ; Redraws at regular intervals + ;-*** Main timer : Cache management and drawing Procedure TimerEvents() - If EventTimer() = PBMap\Timer And (PBMap\Redraw Or PBMap\Dirty) - MemoryCacheManagement() - Drawing() - EndIf + Protected *PBMap.PBMap + ForEach PBMaps() + *PBMap = PBMaps() + If EventTimer() = *PBMap\Timer And (*PBMap\Redraw Or *PBMap\Dirty) + MemoryCacheManagement(*PBMap\Gadget) + Drawing(*PBMap\Gadget) + EndIf + Next EndProcedure ; Could be called directly to attach our map to an existing canvas - Procedure BindMapGadget(Gadget.i) - PBMap\Gadget = Gadget - BindGadgetEvent(PBMap\Gadget, @CanvasEvents()) - AddWindowTimer(PBMap\Window, PBMap\Timer, PBMap\Options\TimerInterval) - BindEvent(#PB_Event_Timer, @TimerEvents()) - PBMap\Drawing\RadiusX = GadgetWidth(PBMap\Gadget) / 2 - PBMap\Drawing\RadiusY = GadgetHeight(PBMap\Gadget) / 2 - EndProcedure - - ; 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 - Else - PBMap\Gadget = Gadget - CanvasGadget(PBMap\Gadget, X, Y, Width, Height, #PB_Canvas_Keyboard) + Procedure BindMapGadget(MapGadget.i, TimerNB = 1, Window = -1) + Protected *PBMap.PBMap + *PBMap.PBMap = AllocateStructure(PBMap) + If *PBMap = 0 + FatalError(MapGadget, "Cannot initialize PBMap memory") EndIf - BindMapGadget(PBMap\Gadget) - EndProcedure - - Procedure Quit() - PBMap\Drawing\End = #True - ; 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 - KillThread(PBMap\MemCache\Images()\Tile\GetImageThread) - EndIf - Else - FreeMemory(PBMap\MemCache\Images()\Tile) - PBMap\MemCache\Images()\Tile = 0 - EndIf - Else - DeleteMapElement(PBMap\MemCache\Images()) - EndIf - Next - Delay(10) - Until MapSize(PBMap\MemCache\Images()) = 0 - EndProcedure - - Procedure InitPBMap(Window) - With PBMap + If Window = -1 + Window = GetActiveWindow() + EndIf + PBMaps(Str(MapGadget)) = *PBMap + With *PBMap Protected Result.i \ZoomMin = 1 \ZoomMax = 18 @@ -2626,339 +2793,89 @@ Module PBMap \StandardFont = LoadFont(#PB_Any, "Arial", 20, #PB_Font_Bold) \UnderlineFont = LoadFont(#PB_Any, "Arial", 20, #PB_Font_Underline) \Window = Window - \Timer = 1 + \Timer = TimerNB \Mode = #MODE_DEFAULT \MemoryCacheAccessMutex = CreateMutex() If \MemoryCacheAccessMutex = #False - MyDebug("Cannot create a mutex", 0) + MyDebug(*PBMap, "Cannot create a mutex", 0) End EndIf EndWith - LoadOptions() - TechnicalImagesCreation() - SetLocation(0, 0) + LoadOptions(MapGadget) + TechnicalImagesCreation(MapGadget) + SetLocation(MapGadget, 0, 0) + *PBMap\Gadget = MapGadget + BindGadgetEvent(*PBMap\Gadget, @CanvasEvents()) + AddWindowTimer(*PBMap\Window, *PBMap\Timer, *PBMap\Options\TimerInterval) + BindEvent(#PB_Event_Timer, @TimerEvents()) + *PBMap\Drawing\RadiusX = DesktopScaledX(GadgetWidth(*PBMap\Gadget)) / 2 + *PBMap\Drawing\RadiusY = DesktopScaledY(GadgetHeight(*PBMap\Gadget)) / 2 EndProcedure + ; Creates a canvas and attach our map + Procedure MapGadget(MapGadget.i, X.i, Y.i, Width.i, Height.i, TimerNB = 1, Window.i = -1) + If Window = -1 + Window = GetActiveWindow() + EndIf + If MapGadget = #PB_Any + Protected GadgetNB.i + GadgetNB = CanvasGadget(#PB_Any, X, Y, Width, Height, #PB_Canvas_Keyboard) ; #PB_Canvas_Keyboard has to be set for mousewheel to work on windows + BindMapGadget(GadgetNB, TimerNB, Window) + ProcedureReturn GadgetNB + Else + If CanvasGadget(MapGadget, X, Y, Width, Height, #PB_Canvas_Keyboard) + BindMapGadget(MapGadget, TimerNB, Window) + Else + FatalError(MapGadget, "Cannot create the map gadget") + EndIf + EndIf + EndProcedure + + Procedure Quit(*PBMap.PBMap) + *PBMap\Drawing\End = #True + ; 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 + KillThread(*PBMap\MemCache\Images()\Tile\GetImageThread) + EndIf + Else + FreeMemory(*PBMap\MemCache\Images()\Tile) + *PBMap\MemCache\Images()\Tile = 0 + EndIf + Else + DeleteMapElement(*PBMap\MemCache\Images()) + EndIf + Next + Delay(10) + Until MapSize(*PBMap\MemCache\Images()) = 0 + RemoveWindowTimer(*PBMap\Window, *PBMap\Timer) + UnbindGadgetEvent(*PBMap\Gadget, @CanvasEvents()) + FreeStructure(*PBMap) + EndProcedure + + Procedure FreeMapGadget(MapGadget.i) + Protected *PBMap.PBMap + ForEach PBMaps() + *PBMap = PBMaps() + If *PBMap\Gadget = MapGadget + Quit(*PBMap) + DeleteMapElement(PBMaps()) + EndIf + Next + EndProcedure + EndModule -; **************************************************************** -; -;- Example of application -; -; **************************************************************** + -CompilerIf #PB_Compiler_IsMainFile - InitNetwork() - - Enumeration - #Window_0 - #Map - #Gdt_Left - #Gdt_Right - #Gdt_Up - #Gdt_Down - ; #Gdt_RotateLeft - ; #Gdt_RotateRight - #Button_4 - #Button_5 - #Combo_0 - #Text_0 - #Text_1 - #Text_2 - #Text_3 - #Text_4 - #StringLatitude - #StringLongitude - #Gdt_LoadGpx - #Gdt_SaveGpx - #Gdt_AddMarker - #Gdt_AddOpenseaMap - #Gdt_AddHereMap - #Gdt_AddGeoServerMap - #Gdt_Degrees - #Gdt_EditMode - #Gdt_ClearDiskCache - #TextGeoLocationQuery - #StringGeoLocationQuery - EndEnumeration - - ; Menu events - Enumeration - #MenuEventLonLatStringEnter - #MenuEventGeoLocationStringEnter - EndEnumeration - - Structure Location - Longitude.d - Latitude.d - EndStructure - - Procedure UpdateLocation(*Location.Location) - SetGadgetText(#StringLatitude, StrD(*Location\Latitude)) - SetGadgetText(#StringLongitude, StrD(*Location\Longitude)) - ProcedureReturn 0 - EndProcedure - - ; 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) - AddPathLine(-16,-32,#PB_Path_Relative) - AddPathCircle(16,0,16,180,0,#PB_Path_Relative) - AddPathLine(-16,32,#PB_Path_Relative) - VectorSourceColor(color) - FillPath(#PB_Path_Preserve) - If Focus - VectorSourceColor(RGBA($FF, $FF, 0, $FF)) - StrokePath(2) - ElseIf Selected - VectorSourceColor(RGBA($FF, $FF, 0, $FF)) - StrokePath(3) - Else - VectorSourceColor(RGBA(0, 0, 0, 255)) - StrokePath(1) - EndIf - EndProcedure - - Procedure MarkerMoveCallBack(*Marker.PBMap::Marker) - Debug "Identifier : " + *Marker\Identifier + "(" + StrD(*Marker\GeographicCoordinates\Latitude) + ", " + StrD(*Marker\GeographicCoordinates\Longitude) + ")" - EndProcedure - - Procedure MainPointer(x.i, y.i) - VectorSourceColor(RGBA(255, 255,255, 255)) : AddPathCircle(x, y,32) : StrokePath(1) - VectorSourceColor(RGBA(0, 0, 0, 255)) : AddPathCircle(x, y, 29):StrokePath(2) - EndProcedure - - Procedure ResizeAll() - ResizeGadget(#Map,10,10,WindowWidth(#Window_0)-198,WindowHeight(#Window_0)-59) - 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_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) - ResizeGadget(#Button_4,WindowWidth(#Window_0)-150,#PB_Ignore,#PB_Ignore,#PB_Ignore) - ResizeGadget(#Button_5,WindowWidth(#Window_0)-100,#PB_Ignore,#PB_Ignore,#PB_Ignore) - ResizeGadget(#Text_3,WindowWidth(#Window_0)-170,#PB_Ignore,#PB_Ignore,#PB_Ignore) - ResizeGadget(#StringLatitude,WindowWidth(#Window_0)-120,#PB_Ignore,#PB_Ignore,#PB_Ignore) - ResizeGadget(#StringLongitude,WindowWidth(#Window_0)-120,#PB_Ignore,#PB_Ignore,#PB_Ignore) - ResizeGadget(#Text_4,WindowWidth(#Window_0)-170,#PB_Ignore,#PB_Ignore,#PB_Ignore) - ResizeGadget(#Gdt_AddMarker,WindowWidth(#Window_0)-170,#PB_Ignore,#PB_Ignore,#PB_Ignore) - ResizeGadget(#Gdt_LoadGpx,WindowWidth(#Window_0)-170,#PB_Ignore,#PB_Ignore,#PB_Ignore) - ResizeGadget(#Gdt_SaveGpx,WindowWidth(#Window_0)-170,#PB_Ignore,#PB_Ignore,#PB_Ignore) - ResizeGadget(#Gdt_AddOpenseaMap,WindowWidth(#Window_0)-170,#PB_Ignore,#PB_Ignore,#PB_Ignore) - ResizeGadget(#Gdt_AddHereMap,WindowWidth(#Window_0)-170,#PB_Ignore,#PB_Ignore,#PB_Ignore) - ResizeGadget(#Gdt_AddGeoServerMap,WindowWidth(#Window_0)-170,#PB_Ignore,#PB_Ignore,#PB_Ignore) - ResizeGadget(#Gdt_Degrees,WindowWidth(#Window_0)-170,#PB_Ignore,#PB_Ignore,#PB_Ignore) - ResizeGadget(#Gdt_EditMode,WindowWidth(#Window_0)-170,#PB_Ignore,#PB_Ignore,#PB_Ignore) - ResizeGadget(#Gdt_ClearDiskCache,WindowWidth(#Window_0)-170,#PB_Ignore,#PB_Ignore,#PB_Ignore) - ResizeGadget(#TextGeoLocationQuery,WindowWidth(#Window_0)-170,#PB_Ignore,#PB_Ignore,#PB_Ignore) - ResizeGadget(#StringGeoLocationQuery,WindowWidth(#Window_0)-170,#PB_Ignore,#PB_Ignore,#PB_Ignore) - PBMap::Refresh() - EndProcedure - - ;- MAIN TEST - If OpenWindow(#Window_0, 260, 225, 700, 571, "PBMap", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_TitleBar | #PB_Window_ScreenCentered | #PB_Window_SizeGadget) - - LoadFont(0, "Arial", 12) - LoadFont(1, "Arial", 12, #PB_Font_Bold) - 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_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)) - ButtonGadget(#Gdt_Down, 580, 90, 30, 30, Chr($25BC)) : SetGadgetFont(#Gdt_Down, FontID(0)) - TextGadget(#Text_2, 530, 120, 60, 15, "Zoom") - ButtonGadget(#Button_4, 550, 140, 50, 30, " + ") : SetGadgetFont(#Button_4, FontID(1)) - ButtonGadget(#Button_5, 600, 140, 50, 30, " - ") : SetGadgetFont(#Button_5, FontID(1)) - TextGadget(#Text_3, 530, 190, 50, 15, "Latitude ") - StringGadget(#StringLatitude, 580, 190, 90, 20, "") - TextGadget(#Text_4, 530, 210, 50, 15, "Longitude ") - StringGadget(#StringLongitude, 580, 210, 90, 20, "") - ButtonGadget(#Gdt_AddMarker, 530, 240, 150, 30, "Add Marker") - ButtonGadget(#Gdt_LoadGpx, 530, 270, 150, 30, "Load GPX") - ButtonGadget(#Gdt_SaveGpx, 530, 300, 150, 30, "Save GPX") - ButtonGadget(#Gdt_AddOpenseaMap, 530, 330, 150, 30, "Show/Hide OpenSeaMap", #PB_Button_Toggle) - ButtonGadget(#Gdt_AddHereMap, 530, 360, 150, 30, "Show/Hide HERE Aerial", #PB_Button_Toggle) - ButtonGadget(#Gdt_AddGeoServerMap, 530, 390, 150, 30, "Show/Hide Geoserver layer", #PB_Button_Toggle) - ButtonGadget(#Gdt_Degrees, 530, 420, 150, 30, "Show/Hide Degrees", #PB_Button_Toggle) - ButtonGadget(#Gdt_EditMode, 530, 450, 150, 30, "Edit mode ON/OFF", #PB_Button_Toggle) - ButtonGadget(#Gdt_ClearDiskCache, 530, 480, 150, 30, "Clear disk cache", #PB_Button_Toggle) - TextGadget(#TextGeoLocationQuery, 530, 515, 150, 15, "Enter an address") - 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 - 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 - PBMap::InitPBMap(#Window_0) - PBMap::SetOption("ShowDegrees", "1") : Degrees = 0 - PBMap::SetOption("ShowDebugInfos", "0") - PBMap::SetDebugLevel(5) - PBMap::SetOption("Verbose", "0") - PBMap::SetOption("ShowScale", "1") - PBMap::SetOption("Warning", "1") - PBMap::SetOption("ShowMarkersLegend", "1") - PBMap::SetOption("ShowTrackKms", "1") - PBMap::SetOption("ColourFocus", "$FFFF00AA") - PBMap::MapGadget(#Map, 10, 10, 512, 512) - PBMap::SetCallBackMainPointer(@MainPointer()) ; To change the main pointer (center of the view) - PBMap::SetCallBackLocation(@UpdateLocation()) ; To obtain realtime coordinates - PBMap::SetLocation(-36.81148, 175.08634,12) ; Change the PBMap coordinates - PBMAP::SetMapScaleUnit(PBMAP::#SCALE_KM) ; To change the scale unit - PBMap::AddMarker(49.0446828398, 2.0349812508, "", "", -1, @MyMarker()) ; To add a marker with a customised GFX - PBMap::SetCallBackMarker(@MarkerMoveCallBack()) - - Repeat - Event = WaitWindowEvent() - Select Event - Case #PB_Event_CloseWindow : Quit = 1 - Case #PB_Event_Gadget ; { - Gadget = EventGadget() - Select Gadget - Case #Gdt_Up - PBMap::SetLocation(10* 360 / Pow(2, PBMap::GetZoom() + 8), 0, 0, #PB_Relative) - Case #Gdt_Down - PBMap::SetLocation(10* -360 / Pow(2, PBMap::GetZoom() + 8), 0, 0, #PB_Relative) - Case #Gdt_Left - 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 #Button_4 - PBMap::SetZoom(1) - Case #Button_5 - PBMap::SetZoom( - 1) - Case #Gdt_LoadGpx - *Track = PBMap::LoadGpxFile(OpenFileRequester("Choose a file to load", "", "Gpx|*.gpx", 0)) - PBMap::SetTrackColour(*Track, RGBA(Random(255), Random(255), Random(255), 128)) - Case #Gdt_SaveGpx - If *Track - If PBMap::SaveGpxFile(SaveFileRequester("Choose a filename", "mytrack.gpx", "Gpx|*.gpx", 0), *Track) - MessageRequester("PBMap", "Saving OK !", #PB_MessageRequester_Ok) - Else - MessageRequester("PBMap", "Problem while saving.", #PB_MessageRequester_Ok) - EndIf - Else - MessageRequester("PBMap", "No track to save.", #PB_MessageRequester_Ok) - EndIf - Case #StringLatitude, #StringLongitude - Select EventType() - Case #PB_EventType_Focus - AddKeyboardShortcut(#Window_0, #PB_Shortcut_Return, #MenuEventLonLatStringEnter) - Case #PB_EventType_LostFocus - RemoveKeyboardShortcut(#Window_0, #PB_Shortcut_Return) - EndSelect - Case #Gdt_AddMarker - PBMap::AddMarker(ValD(GetGadgetText(#StringLatitude)), ValD(GetGadgetText(#StringLongitude)), "", "Test", RGBA(Random(255), Random(255), Random(255), 255)) - Case #Gdt_AddOpenseaMap - If PBMap::IsLayer("OpenSeaMap") - PBMap::DeleteLayer("OpenSeaMap") - SetGadgetState(#Gdt_AddOpenseaMap, 0) - Else - PBMap::AddOSMServerLayer("OpenSeaMap", 3, "http://t1.openseamap.org/seamark/") ; Add a special osm overlay map on layer nb 3 - SetGadgetState(#Gdt_AddOpenseaMap, 1) - EndIf - PBMap::Refresh() - Case #Gdt_AddHereMap - If PBMap::IsLayer("Here") - PBMap::DeleteLayer("Here") - SetGadgetState(#Gdt_AddHereMap, 0) - Else - If PBMap::GetOption("appid") <> "" And PBMap::GetOption("appcode") <> "" - PBMap::AddHereServerLayer("Here", 2) ; Add a "HERE" overlay map on layer nb 2 - PBMap::SetLayerAlpha("Here", 0.75) - Else - MessageRequester("Info", "Don't forget to register on HERE and change the following line or edit options file") - PBMap::AddHereServerLayer("Here", 2, "my_id", "my_code") ; Add a here overlay map on layer nb 2 - EndIf - SetGadgetState(#Gdt_AddHereMap, 1) - EndIf - PBMap::Refresh() - Case #Gdt_AddGeoServerMap - If PBMap::IsLayer("GeoServer") - PBMap::DeleteLayer("GeoServer") - SetGadgetState(#Gdt_AddGeoServerMap, 0) - Else - PBMap::AddGeoServerLayer("GeoServer", 3, "demolayer", "http://localhost:8080/", "geowebcache/service/gmaps", "image/png") ; Add a geoserver overlay map on layer nb 3 - PBMap::SetLayerAlpha("GeoServer", 0.75) - SetGadgetState(#Gdt_AddGeoServerMap, 1) - EndIf - PBMap::Refresh() - Case #Gdt_Degrees - Degrees = 1 - Degrees - PBMap::SetOption("ShowDegrees", Str(Degrees)) - PBMap::Refresh() - SetGadgetState(#Gdt_Degrees, Degrees) - Case #Gdt_EditMode - If PBMap::GetMode() <> PBMap::#MODE_EDIT - PBMap::SetMode(PBMap::#MODE_EDIT) - SetGadgetState(#Gdt_EditMode, 1) - Else - PBMap::SetMode(PBMap::#MODE_DEFAULT) - SetGadgetState(#Gdt_EditMode, 0) - EndIf - Case #Gdt_ClearDiskCache - PBMap::ClearDiskCache() - Case #StringGeoLocationQuery - Select EventType() - Case #PB_EventType_Focus - AddKeyboardShortcut(#Window_0, #PB_Shortcut_Return, #MenuEventGeoLocationStringEnter) - Case #PB_EventType_LostFocus - RemoveKeyboardShortcut(#Window_0, #PB_Shortcut_Return) - EndSelect - EndSelect - Case #PB_Event_SizeWindow - ResizeAll() - Case #PB_Event_Menu - ; 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 - SetActiveGadget(Dummy) - ; *** - Case #MenuEventLonLatStringEnter - PBMap::SetLocation(ValD(GetGadgetText(#StringLatitude)), ValD(GetGadgetText(#StringLongitude))) ; Change the PBMap coordinates - PBMap::Refresh() - EndSelect - EndSelect - Until Quit = #True - - PBMap::Quit() - EndIf - -CompilerEndIf - - -; IDE Options = PureBasic 5.60 (Windows - x64) -; CursorPosition = 2726 -; FirstLine = 2720 +; IDE Options = PureBasic 6.00 Alpha 3 (Windows - x64) +; CursorPosition = 2657 +; FirstLine = 766 ; Folding = -------------------- ; EnableThread -; EnableXP -; CompileSourceDirectory \ No newline at end of file +; EnableXP \ No newline at end of file