From 825be77b4e13e947287f9db833ad98033086dac1 Mon Sep 17 00:00:00 2001 From: djes Date: Wed, 1 Mar 2017 16:12:58 +0100 Subject: [PATCH] To correct sync problem --- PBMap.pb | 1596 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 1105 insertions(+), 491 deletions(-) diff --git a/PBMap.pb b/PBMap.pb index 4f2ea3c..950d7f9 100644 --- a/PBMap.pb +++ b/PBMap.pb @@ -1,18 +1,15 @@ -;************************************************************** +;******************************************************************** ; Program: PBMap ; Description: Permits the use of tiled maps like ; OpenStreetMap in a handy PureBASIC module -; Author: Thyphoon, Djes And Idle -; Date: Februry 21, 2017 -; License: Free, unrestricted, credit appreciated -; but not required. +; Author: Thyphoon, djes And Idle +; Date: March, 2017 +; License: PBMap : Free, unrestricted, credit +; appreciated but not required. +; OSM : see http://www.openstreetmap.org/copyright ; Note: Please share improvement ! -; Thanks: Progi1984 -; Usage: Change the Proxy global variables if needed -; (see also Proxy Details) -;************************************************************** - -;#Red = 255 +; Thanks: Progi1984, yves86 +;******************************************************************** CompilerIf #PB_Compiler_Thread = #False MessageRequester("Warning !!","You must enable ThreadSafe support in compiler options",#PB_MessageRequester_Ok ) @@ -25,12 +22,22 @@ InitNetwork() UsePNGImageDecoder() UsePNGImageEncoder() -DeclareModule PBMap - #Red = 255 +DeclareModule PBMap + ;-Show debug infos + Global MyDebugLevel = 0 - ;-Show debug infos - Global Verbose = 0 - Global MyDebugLevel = 5 + CompilerIf #PB_Compiler_OS = #PB_OS_Linux + #Red = 255 + CompilerEndIf + + Global slash.s + + CompilerSelect #PB_Compiler_OS + CompilerCase #PB_OS_Windows + slash = "\" + CompilerDefault + slash = "/" + CompilerEndSelect #SCALE_NAUTICAL = 1 #SCALE_KM = 0 @@ -40,6 +47,8 @@ DeclareModule PBMap #MODE_SELECT = 2 #MODE_EDIT = 3 + #MARKER_EDIT_EVENT = #PB_Event_FirstCustomValue + ;-Declarations Declare InitPBMap(window) Declare SetOption(Option.s, Value.s) @@ -47,17 +56,23 @@ DeclareModule PBMap Declare SaveOptions(PreferencesFile.s = "PBMap.prefs") Declare.i AddMapServerLayer(LayerName.s, Order.i, ServerURL.s = "http://tile.openstreetmap.org/", TileSize = 256, ZoomMin = 0, ZoomMax = 18) Declare DeleteLayer(Nb.i) + Declare BindMapGadget(Gadget.i) Declare MapGadget(Gadget.i, X.i, Y.i, Width.i, Height.i) Declare SetLocation(latitude.d, longitude.d, Zoom = -1, mode.i = #PB_Absolute) Declare Drawing() + Declare SetAngle(Angle.d, Mode = #PB_Absolute) Declare SetZoom(Zoom.i, mode.i = #PB_Relative) Declare ZoomToArea(MinY.d, MaxY.d, MinX.d, MaxX.d) Declare ZoomToTracks(*Tracks) Declare SetCallBackLocation(*CallBackLocation) Declare SetCallBackMainPointer(CallBackMainPointer.i) Declare SetMapScaleUnit(ScaleUnit=PBMAP::#SCALE_KM) - Declare LoadGpxFile(file.s); - Declare.i AddMarker(Latitude.d, Longitude.d, Legend.s = "", color.l=-1, CallBackPointer.i = -1) + Declare.i LoadGpxFile(file.s); + 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() @@ -68,7 +83,12 @@ DeclareModule PBMap Declare.d GetLongitude() Declare.d MouseLatitude() Declare.d MouseLongitude() + Declare.d GetAngle() Declare.i GetZoom() + Declare.i GetMode() + Declare SetMode(Mode.i = #MODE_DEFAULT) + Declare NominatimGeoLocationQuery(Address.s, *ReturnPosition= 0) ;Send back the position *ptr.GeographicCoordinates + Declare.i ClearDiskCache() EndDeclareModule Module PBMap @@ -81,8 +101,8 @@ Module PBMap EndStructure Structure PixelCoordinates - x.i - y.i + x.d + y.d EndStructure Structure Coordinates @@ -92,32 +112,32 @@ Module PBMap ;- Tile Structure Structure Tile - Position.Coordinates - PBMapTileX.i - PBMapTileY.i - PBMapZoom.i nImage.i key.s + URL.s CacheFile.s GetImageThread.i RetryNb.i - ServerURL.s EndStructure - Structure TileBounds - NorthWest.Coordinates - SouthEast.Coordinates + Structure BoundingBox + NorthWest.GeographicCoordinates + SouthEast.GeographicCoordinates + BottomRight.PixelCoordinates + TopLeft.PixelCoordinates EndStructure Structure DrawingParameters - TileCoordinates.Coordinates - Bounds.TileBounds Canvas.i + RadiusX.d ; Canvas radius, or center in pixels + RadiusY.d + GeographicCoordinates.GeographicCoordinates ; Real center in lat/lon + TileCoordinates.Coordinates ; Center coordinates in tile.decimal + Bounds.BoundingBox ; Drawing boundaries in lat/lon + Width.d ; Drawing width in degrees + Height.d ; Drawing height in degrees PBMapZoom.i - GeographicCoordinates.GeographicCoordinates - CenterX.i - CenterY.i - DeltaX.i + DeltaX.i ; Screen relative pixels tile shift DeltaY.i Dirty.i End.i @@ -127,6 +147,7 @@ Module PBMap nImage.i *Tile.Tile TimeStackPosition.i + Alpha.i EndStructure Structure ImgMemCachKey @@ -140,13 +161,16 @@ Module PBMap Structure Marker GeographicCoordinates.GeographicCoordinates ; Marker latitude and longitude + Identifier.s Legend.s Color.l ; Marker color Focus.i Selected.i ; Is the marker selected ? CallBackPointer.i ; @Procedure(X.i, Y.i) to DrawPointer (you must use VectorDrawing lib) + EditWindow.i EndStructure + ;-Options Structure Option HDDCachePath.s ; Path where to load and save tiles downloaded from server DefaultOSMServer.s ; Base layer OSM server @@ -161,13 +185,21 @@ Module PBMap ShowDebugInfos.i ShowScale.i ShowTrack.i + ShowTrackKms.i ShowMarkers.i ShowPointer.i TimerInterval.i MaxMemCache.i ; in MiB - TrackShowKms.i + Verbose.i ; Maximum debug informations + Warning.i ; Warning requesters ShowMarkersNb.i ShowMarkersLegend.i + ;Drawing stuff + StrokeWidthTrackDefault.i + ;Colours + ColourFocus.i + ColourSelected.i + ColourTrackDefault.i EndStructure Structure Layer @@ -176,9 +208,23 @@ Module PBMap ServerURL.s ; Web URL ex: http://tile.openstreetmap.org/ EndStructure + Structure Box + x1.i + y1.i + x2.i + y2.i + EndStructure + Structure Tracks - List Track.GeographicCoordinates() + List Track.GeographicCoordinates() ; To display a GPX track + BoundingBox.Box + Visible.i + Focus.i + Selected.i + Colour.i + StrokeWidth.i EndStructure + ;-PBMap Structure Structure PBMap Window.i ; Parent Window @@ -197,6 +243,7 @@ Module PBMap List Layers.Layer() ; + Angle.d ZoomMin.i ; Min Zoom supported by server ZoomMax.i ; Max Zoom supported by server Zoom.i ; Current zoom @@ -235,12 +282,16 @@ Module PBMap ;Send debug infos to stdout (allowing mixed debug infos with curl or other libs) Procedure MyDebug(msg.s, DbgLevel = 0) - If Verbose And MyDebugLevel >= DbgLevel + If PBMap\Options\Verbose And DbgLevel >= MyDebugLevel PrintN(msg) ;Debug msg EndIf EndProcedure - + + ;- *** GetText - Translation purpose + ;TODO use this for all text + IncludeFile "gettext.pbi" + Procedure TechnicalImagesCreation() ;"Loading" image Protected LoadingText$ = "Loading" @@ -292,6 +343,27 @@ Module PBMap EndSelect EndMacro + Procedure.i ColourString2Value(Value.s) + ;TODO : better string check + Protected Col.s = RemoveString(Value, " ") + If Left(Col, 1) = "$" + Protected r.i, g.i, b.i, a.i = 255 + Select Len(Col) + Case 4 ;RGB (eg : "$9BC" + r = Val("$"+Mid(Col, 2, 1)) : g = Val("$"+Mid(Col, 3, 1)) : b = Val("$"+Mid(Col, 4, 1)) + Case 5 ;RGBA (eg : "$9BC5") + r = Val("$"+Mid(Col, 2, 1)) : g = Val("$"+Mid(Col, 3, 1)) : b = Val("$"+Mid(Col, 4, 1)) : a = Val("$"+Mid(Col, 5, 1)) + Case 7 ;RRGGBB (eg : "$95B4C2") + r = Val("$"+Mid(Col, 2, 2)) : g = Val("$"+Mid(Col, 4, 2)) : b = Val("$"+Mid(Col, 6, 2)) + Case 9 ;RRGGBBAA (eg : "$95B4C249") + r = Val("$"+Mid(Col, 2, 2)) : g = Val("$"+Mid(Col, 4, 2)) : b = Val("$"+Mid(Col, 6, 2)) : a = Val("$"+Mid(Col, 8, 2)) + EndSelect + ProcedureReturn RGBA(r, g, b, a) + Else + ProcedureReturn Val(Value) + EndIf + EndProcedure + Procedure SetOption(Option.s, Value.s) Option = StringCheck(Option) Select LCase(Option) @@ -307,9 +379,10 @@ Module PBMap PBMap\Options\HDDCachePath = Value Case "maxmemcache" PBMap\Options\MaxMemCache = Val(Value) - Case "cleancache" - DeleteDirectory(PBMap\Options\HDDCachePath, "",#PB_FileSystem_Recursive) - MyDebug("Cache : "+PBMap\Options\HDDCachePath+" cleaned" + Case "verbose" + SelBool(Verbose) + Case "warning" + SelBool(Warning) Case "wheelmouserelative" SelBool(WheelMouseRelative) Case "showdegrees" @@ -328,9 +401,16 @@ Module PBMap SelBool(ShowMarkersNb) Case "showmarkerslegend" SelBool(ShowMarkersLegend) - Case "trackshowkms" - SelBool(TrackShowKms) - + Case "showtrackkms" + SelBool(ShowTrackKms) + Case "strokewidthtrackdefault" + SelBool(StrokeWidthTrackDefault) + Case "colourfocus" + PBMap\Options\ColourFocus = ColourString2Value(Value) + Case "colourselected" + PBMap\Options\ColourSelected = ColourString2Value(Value) + Case "colourtrackdefault" + PBMap\Options\ColourTrackDefault = ColourString2Value(Value) EndSelect EndProcedure @@ -341,28 +421,38 @@ Module PBMap Else CreatePreferences(PreferencesFile) EndIf - PreferenceGroup("PROXY") - WritePreferenceInteger("Proxy", PBMap\Options\Proxy) - WritePreferenceString("ProxyURL", PBMap\Options\ProxyURL) - WritePreferenceString("ProxyPort", PBMap\Options\ProxyPort) - WritePreferenceString("ProxyUser", PBMap\Options\ProxyUser) - PreferenceGroup("URL") - WritePreferenceString("DefaultOSMServer", PBMap\Options\DefaultOSMServer) - PreferenceGroup("PATHS") - WritePreferenceString("TilesCachePath", PBMap\Options\HDDCachePath) - PreferenceGroup("OPTIONS") - WritePreferenceInteger("WheelMouseRelative", PBMap\Options\WheelMouseRelative) - WritePreferenceInteger("MaxMemCache", PBMap\Options\MaxMemCache) - WritePreferenceInteger("ShowDegrees", PBMap\Options\ShowDegrees) - WritePreferenceInteger("ShowDebugInfos", PBMap\Options\ShowDebugInfos) - WritePreferenceInteger("ShowScale", PBMap\Options\ShowScale) - WritePreferenceInteger("ShowMarkers", PBMap\Options\ShowMarkers) - WritePreferenceInteger("ShowPointer", PBMap\Options\ShowPointer) - WritePreferenceInteger("ShowTrack", PBMap\Options\ShowTrack) - WritePreferenceInteger("ShowMarkersNb", PBMap\Options\ShowMarkersNb) - WritePreferenceInteger("ShowMarkersLegend", PBMap\Options\ShowMarkersLegend) - WritePreferenceInteger("TrackShowKms", PBMap\Options\TrackShowKms) - ClosePreferences() + With PBMap\Options + PreferenceGroup("PROXY") + WritePreferenceInteger("Proxy", \Proxy) + WritePreferenceString("ProxyURL", \ProxyURL) + WritePreferenceString("ProxyPort", \ProxyPort) + WritePreferenceString("ProxyUser", \ProxyUser) + PreferenceGroup("URL") + WritePreferenceString("DefaultOSMServer", \DefaultOSMServer) + PreferenceGroup("PATHS") + WritePreferenceString("TilesCachePath", \HDDCachePath) + PreferenceGroup("OPTIONS") + WritePreferenceInteger("WheelMouseRelative", \WheelMouseRelative) + WritePreferenceInteger("MaxMemCache", \MaxMemCache) + WritePreferenceInteger("Verbose", \Verbose) + WritePreferenceInteger("Warning", \Warning) + WritePreferenceInteger("ShowDegrees", \ShowDegrees) + WritePreferenceInteger("ShowDebugInfos", \ShowDebugInfos) + WritePreferenceInteger("ShowScale", \ShowScale) + WritePreferenceInteger("ShowMarkers", \ShowMarkers) + WritePreferenceInteger("ShowPointer", \ShowPointer) + WritePreferenceInteger("ShowTrack", \ShowTrack) + WritePreferenceInteger("ShowTrackKms", \ShowTrackKms) + WritePreferenceInteger("ShowMarkersNb", \ShowMarkersNb) + WritePreferenceInteger("ShowMarkersLegend", \ShowMarkersLegend) + PreferenceGroup("DRAWING") + WritePreferenceInteger("StrokeWidthTrackDefault", \StrokeWidthTrackDefault) + ;Colours; + WritePreferenceInteger("ColourFocus", \ColourFocus) + WritePreferenceInteger("ColourSelected", \ColourSelected) + WritePreferenceInteger("ColourTrackDefault", \ColourTrackDefault) + ClosePreferences() + EndWith EndProcedure Procedure LoadOptions(PreferencesFile.s = "PBMap.prefs") @@ -384,68 +474,47 @@ Module PBMap ; WritePreferenceString("ProxyUser", "myproxyname") ; WritePreferenceString("ProxyPass", "myproxypass") ;TODO !Warning! !not encoded! ; ClosePreferences() - PreferenceGroup("PROXY") - PBMap\Options\Proxy = ReadPreferenceInteger("Proxy", #False) - If PBMap\Options\Proxy - PBMap\Options\ProxyURL = ReadPreferenceString("ProxyURL", "") ;InputRequester("ProxyServer", "Do you use a Proxy Server? Then enter the full url:", "") - PBMap\Options\ProxyPort = ReadPreferenceString("ProxyPort", "") ;InputRequester("ProxyPort" , "Do you use a specific port? Then enter it", "") - PBMap\Options\ProxyUser = ReadPreferenceString("ProxyUser", "") ;InputRequester("ProxyUser" , "Do you use a user name? Then enter it", "") - PBMap\Options\ProxyPassword = InputRequester("ProxyPass", "Do you use a password ? Then enter it", "") ;TODO - EndIf - PreferenceGroup("URL") - PBMap\Options\DefaultOSMServer = ReadPreferenceString("DefaultOSMServer", "http://tile.openstreetmap.org/") - - PreferenceGroup("PATHS") - PBMap\Options\HDDCachePath = ReadPreferenceString("TilesCachePath", GetTemporaryDirectory()) - PreferenceGroup("OPTIONS") - PBMap\Options\WheelMouseRelative = ReadPreferenceInteger("WheelMouseRelative", #True) - PBMap\Options\MaxMemCache = ReadPreferenceInteger("MaxMemCache", 20480) ;20 MiB, about 80 tiles in memory - PBMap\Options\ShowDegrees = ReadPreferenceInteger("ShowDegrees", #False) - PBMap\Options\ShowDebugInfos = ReadPreferenceInteger("ShowDebugInfos", #False) - PBMap\Options\ShowScale = ReadPreferenceInteger("ShowScale", #False) - PBMap\Options\ShowMarkers = ReadPreferenceInteger("ShowMarkers", #True) - PBMap\Options\ShowPointer = ReadPreferenceInteger("ShowPointer", #True) - PBMap\Options\ShowTrack = ReadPreferenceInteger("ShowTrack", #True) - PBMap\Options\ShowMarkersNb = ReadPreferenceInteger("ShowMarkersNb", #True) - PBMap\Options\ShowMarkersLegend = ReadPreferenceInteger("ShowMarkersLegend", #False) - PBMap\Options\TrackShowKms = ReadPreferenceInteger("TrackShowKms", #False) - PBMap\Options\TimerInterval = 20 - ClosePreferences() - EndProcedure - - Procedure InitPBMap(Window) - Protected Result.i - If Verbose - OpenConsole() - EndIf - PBMap\ZoomMin = 0 - PBMap\ZoomMax = 18 - PBMap\MoveStartingPoint\x = - 1 - PBMap\TileSize = 256 - PBMap\Dirty = #False - PBMap\EditMarker = #False - PBMap\Font = LoadFont(#PB_Any, "Arial", 20, #PB_Font_Bold) - PBMap\Window = Window - PBMap\Timer = 1 - PBMap\Mode = #MODE_DEFAULT - LoadOptions() - If PBMap\Options\DefaultOSMServer <> "" - AddMapServerLayer("OSM", 1, PBMap\Options\DefaultOSMServer) - EndIf - TechnicalImagesCreation() - SetLocation(0, 0) + 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", "") + \ProxyPassword = InputRequester("ProxyPass", "Do you use a password ? Then enter it", "") ;TODO + EndIf + PreferenceGroup("URL") + \DefaultOSMServer = ReadPreferenceString("DefaultOSMServer", "http://tile.openstreetmap.org/") + + PreferenceGroup("PATHS") + \HDDCachePath = ReadPreferenceString("TilesCachePath", GetTemporaryDirectory() + "PBMap" + slash) + PreferenceGroup("OPTIONS") + \WheelMouseRelative = ReadPreferenceInteger("WheelMouseRelative", #True) + \MaxMemCache = ReadPreferenceInteger("MaxMemCache", 20480) ;20 MiB, about 80 tiles in memory + \Verbose = ReadPreferenceInteger("Verbose", #True) + \Warning = ReadPreferenceInteger("Warning", #False) + \ShowDegrees = ReadPreferenceInteger("ShowDegrees", #False) + \ShowDebugInfos = ReadPreferenceInteger("ShowDebugInfos", #False) + \ShowScale = ReadPreferenceInteger("ShowScale", #False) + \ShowMarkers = ReadPreferenceInteger("ShowMarkers", #True) + \ShowPointer = ReadPreferenceInteger("ShowPointer", #True) + \ShowTrack = ReadPreferenceInteger("ShowTrack", #True) + \ShowTrackKms = ReadPreferenceInteger("ShowTrackKms", #False) + \ShowMarkersNb = ReadPreferenceInteger("ShowMarkersNb", #True) + \ShowMarkersLegend = ReadPreferenceInteger("ShowMarkersLegend", #False) + PreferenceGroup("DRAWING") + \StrokeWidthTrackDefault = ReadPreferenceInteger("StrokeWidthTrackDefault", 10) + PreferenceGroup("COLOURS") + \ColourFocus = ReadPreferenceInteger("ColourFocus", RGBA(255, 255, 0, 255)) + \ColourSelected = ReadPreferenceInteger("ColourSelected", RGBA(225, 225, 0, 255)) + \ColourTrackDefault = ReadPreferenceInteger("ColourTrackDefault", RGBA(0, 255, 0, 150)) + \TimerInterval = 20 + ClosePreferences() + EndWith EndProcedure Procedure.i AddMapServerLayer(LayerName.s, Order.i, ServerURL.s = "http://tile.openstreetmap.org/", TileSize = 256, ZoomMin = 0, ZoomMax = 18) Protected *Ptr = AddElement(PBMap\Layers()) - 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 cache directory : " + DirName) - Else - MyDebug(DirName + " successfully created", 4) - EndIf - EndIf If *Ptr PBMap\Layers()\Name = LayerName PBMap\Layers()\Order = Order @@ -486,7 +555,7 @@ Module PBMap EndIf Next Delay(10) - Until MapSize(PBMap\MemCache\Images()) = 0 + Until MapSize(PBMap\MemCache\Images()) = 0 EndProcedure Macro Min(a,b) @@ -521,6 +590,12 @@ Module PBMap ;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 Procedure Pixel2LatLon(*Coords.PixelCoordinates, *Location.GeographicCoordinates, Zoom) @@ -528,6 +603,12 @@ Module PBMap ;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[ @@ -546,11 +627,11 @@ Module PBMap ;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\CenterX + Protected cx.d = PBMap\Drawing\RadiusX Protected dpx.d = PBMap\PixelCoordinates\x Protected LatRad.d = Radian(*Location\Latitude) - Protected px = tilemax * (Mod( *Location\Longitude + 180.0, 360) / 360.0 ) - Protected py = tilemax * ( 1.0 - Log(Tan(LatRad) + (1.0/Cos(LatRad))) / #PI ) / 2.0 + Protected px.d = tilemax * (Mod( *Location\Longitude + 180.0, 360) / 360.0 ) + Protected py.d = tilemax * ( 1.0 - Log(Tan(LatRad) + (1.0/Cos(LatRad))) / #PI ) / 2.0 ;check the x boundaries of the map to adjust the position (coz of the longitude wrapping) If dpx - px >= tilemax / 2 ;Debug "c1" @@ -565,7 +646,7 @@ Module PBMap ;Debug "c0" *Pixel\x = cx + (px - dpx) EndIf - *Pixel\y = PBMap\Drawing\CenterY + (py - PBMap\PixelCoordinates\y) + *Pixel\y = PBMap\Drawing\RadiusY + (py - PBMap\PixelCoordinates\y) EndProcedure ; HaversineAlgorithm @@ -586,6 +667,7 @@ Module PBMap ProcedureReturn (1000 * HaversineInKM(@*posA,@*posB)); EndProcedure + ; No more used, see LatLon2PixelRel Procedure GetPixelCoordFromLocation(*Location.GeographicCoordinates, *Pixel.PixelCoordinates, Zoom) ; TODO to Optimize Protected mapWidth.l = Pow(2, Zoom + 8) Protected mapHeight.l = Pow(2, Zoom + 8) @@ -601,41 +683,47 @@ Module PBMap latRad = PBMap\GeographicCoordinates\Latitude*#PI/180; mercN = Log(Tan((#PI/4)+(latRad/2))) y2 = (mapHeight/2)-(mapWidth*mercN/(2*#PI)); - *Pixel\x=GadgetWidth(PBMap\Gadget)/2 - (x2-x1) - *Pixel\y=GadgetHeight(PBMap\Gadget)/2 - (y2-y1) + *Pixel\x=PBMap\Drawing\RadiusX - (x2-x1) + *Pixel\y=PBMap\Drawing\RadiusY - (y2-y1) EndProcedure - Procedure LoadGpxFile(file.s) - If LoadXML(0, file.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)) - MessageRequester("Error", Message) - EndIf - Protected *MainNode,*subNode,*child,child.l - *MainNode=MainXMLNode(0) - *MainNode=XMLNodeFromPath(*MainNode,"/gpx/trk/trkseg") - Protected *NewTrack.Tracks = AddElement(PBMap\TracksList()) - For child = 1 To XMLChildCount(*MainNode) - *child = ChildXMLNode(*MainNode, child) - AddElement(*NewTrack\Track()) - If ExamineXMLAttributes(*child) - While NextXMLAttribute(*child) - Select XMLAttributeName(*child) - Case "lat" - *NewTrack\Track()\Latitude=ValD(XMLAttributeValue(*child)) - Case "lon" - *NewTrack\Track()\Longitude=ValD(XMLAttributeValue(*child)) - EndSelect - Wend - EndIf - Next - ZoomToTracks(LastElement(PBMap\TracksList())) ; <-To center the view, and zoom on the tracks + Procedure IsInDrawingPixelBoundaries(*Drawing.DrawingParameters, *Position.GeographicCoordinates) + Protected Pixel.PixelCoordinates + LatLon2PixelRel(*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 + ProcedureReturn #False EndIf EndProcedure + Procedure IsInDrawingBoundaries(*Drawing.DrawingParameters, *Position.GeographicCoordinates) + Protected Lat.d = *Position\Latitude, Lon.d = *Position\Longitude + Protected LatNW.d = *Drawing\Bounds\NorthWest\Latitude, LonNW.d = *Drawing\Bounds\NorthWest\Longitude + Protected LatSE.d = *Drawing\Bounds\SouthEast\Latitude, LonSE.d = *Drawing\Bounds\SouthEast\Longitude + If Lat >= LatSE And Lat <= LatNW + If *Drawing\Width >= 360 + ProcedureReturn #True + Else + If LonNW < LonSE + If Lon >= LonNW And Lon <= LonSE + ProcedureReturn #True + Else + ProcedureReturn #False + EndIf + Else + If (Lon >= -180 And Lon <= LonSE) Or (Lon >= LonNW And Lon <= 180) + ProcedureReturn #True + Else + ProcedureReturn #False + EndIf + EndIf + EndIf + Else + ProcedureReturn #False + EndIf + EndProcedure + ;-*** These are threaded Procedure.i GetTileFromHDD(CacheFile.s) Protected nImage.i @@ -656,51 +744,50 @@ Module PBMap Procedure.i GetTileFromWeb(TileURL.s, CacheFile.s) Protected *Buffer Protected nImage.i = -1 - Protected FileSize.i, timg - HTTPProxy(PBMap\Options\ProxyURL+":"+PBMap\Options\ProxyPort, PBMap\Options\ProxyUser, PBMap\Options\ProxyPassword) - ;FileSize= ReceiveHTTPFile(TileURL,CacheFile) - ;If FileSize > 0 - ; MyDebug("Loaded from web " + TileURL + " as CacheFile " + CacheFile, 3) - ; nImage = GetTileFromHDD(CacheFile) - ;Else - ; MyDebug("Problem loading from web " + TileURL, 3) - ;EndIf - ; **** IMPORTANT NOTICE - ; I'm (djes) now using Curl only, as this original catchimage/saveimage method is a double operation (uncompress/recompress PNG) + Protected FileSize.i, timg + HTTPProxy(PBMap\Options\ProxyURL + ":" + PBMap\Options\ProxyPort, PBMap\Options\ProxyUser, PBMap\Options\ProxyPassword) + FileSize = ReceiveHTTPFile(TileURL, CacheFile) + If FileSize > 0 + MyDebug("Loaded from web " + TileURL + " as CacheFile " + CacheFile, 3) + nImage = GetTileFromHDD(CacheFile) + Else + MyDebug("Problem loading from web " + TileURL, 3) + EndIf + ; **** IMPORTANT NOTICE (please not remove) + ; I'm (djes) now using Curl (actually, just normal pb) only, as this original catchimage/saveimage method is a double operation (uncompress/recompress PNG) ; and is modifying the original PNG image which could lead to PNG error (Idle has spent hours debunking the 1 bit PNG bug) ; More than that, the original Purebasic Receive library is still not Proxy enabled. - *Buffer = ReceiveHTTPMemory(TileURL) ;TODO to thread by using #PB_HTTP_Asynchronous - If *Buffer - nImage = CatchImage(#PB_Any, *Buffer, MemorySize(*Buffer)) - If IsImage(nImage) - If SaveImage(nImage, CacheFile, #PB_ImagePlugin_PNG, 0, 32) ;The 32 is needed !!!! - MyDebug("Loaded from web " + TileURL + " as CacheFile " + CacheFile, 3) - Else - MyDebug("Loaded from web " + TileURL + " but cannot save to CacheFile " + CacheFile, 3) - EndIf - FreeMemory(*Buffer) - Else - MyDebug("Can't catch image loaded from web " + TileURL, 3) - nImage = -1 - EndIf - Else - MyDebug(" Problem loading from web " + TileURL, 3) - EndIf + ; *Buffer = ReceiveHTTPMemory(TileURL) ;TODO to thread by using #PB_HTTP_Asynchronous + ; If *Buffer + ; nImage = CatchImage(#PB_Any, *Buffer, MemorySize(*Buffer)) + ; If IsImage(nImage) + ; If SaveImage(nImage, CacheFile, #PB_ImagePlugin_PNG, 0, 32) ;The 32 is needed !!!! + ; MyDebug("Loaded from web " + TileURL + " as CacheFile " + CacheFile, 3) + ; Else + ; MyDebug("Loaded from web " + TileURL + " but cannot save to CacheFile " + CacheFile, 3) + ; EndIf + ; FreeMemory(*Buffer) + ; Else + ; MyDebug("Can't catch image loaded from web " + TileURL, 3) + ; nImage = -1 + ; EndIf + ; Else + ; MyDebug(" Problem loading from web " + TileURL, 3) + ; EndIf ; **** ProcedureReturn nImage EndProcedure Procedure GetImageThread(*Tile.Tile) Protected nImage.i = -1 - Protected TileURL.s = *Tile\ServerURL + Str(*Tile\PBMapZoom) + "/" + Str(*Tile\PBMapTileX) + "/" + Str(*Tile\PBMapTileY) + ".png" Repeat - nImage = GetTileFromWeb(TileURL, *Tile\CacheFile) + nImage = GetTileFromWeb(*Tile\URL, *Tile\CacheFile) If nImage <> -1 MyDebug("Image key : " + *Tile\key + " web image loaded", 3) *Tile\RetryNb = 0 Else MyDebug("Image key : " + *Tile\key + " web image not correctly loaded", 3) - Delay(1000) + Delay(2000) *Tile\RetryNb - 1 EndIf Until *Tile\RetryNb <= 0 @@ -710,27 +797,27 @@ Module PBMap EndProcedure ;-*** - Procedure.i GetTile(key.s, CacheFile.s, px.i, py.i, tilex.i, tiley.i, ServerURL.s) + Procedure.i GetTile(key.s, URL.s, CacheFile.s) ; Try to find the tile in memory cache. If not found, add it, try To load it from the ; HDD, or launch a loading thread, and try again on the next drawing loop. - Protected timg = -1 - If FindMapElement(PBMap\MemCache\Images(), key) + Protected img.i = -1 + Protected *timg.ImgMemCach = FindMapElement(PBMap\MemCache\Images(), key) + If *timg MyDebug("Key : " + key + " found in memory cache!", 3) - timg = PBMap\MemCache\Images()\nImage - If timg <> -1 - MyDebug("Image : " + timg + " found in memory cache!", 3) + img = *timg\nImage + If img <> -1 + MyDebug("Image : " + img + " found in memory cache!", 3) ;*** Cache management ; Move the newly used element to the last position of the time stack - SelectElement(PBMap\MemCache\ImagesTimeStack(), PBMap\MemCache\Images()\TimeStackPosition) + SelectElement(PBMap\MemCache\ImagesTimeStack(), *timg\TimeStackPosition) MoveElement(PBMap\MemCache\ImagesTimeStack(), #PB_List_Last) ;*** - ProcedureReturn timg + ProcedureReturn *timg EndIf Else - AddMapElement(PBMap\MemCache\Images(), key) - PushMapPosition(PBMap\MemCache\Images()) + ;PushMapPosition(PBMap\MemCache\Images()) ;*** Cache management - ; if cache size exceeds limit, try to delete the oldest tile used + ; if cache size exceeds limit, try to delete the oldest tile used (first in the list) 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), 4) @@ -746,36 +833,38 @@ Module PBMap CacheSize = MapSize(PBMap\MemCache\Images()) * Pow(PBMap\TileSize, 2) * 4 ; Size of a tile = TileSize * TileSize * 4 bytes (RGBA) EndIf Wend - PopMapPosition(PBMap\MemCache\Images()) + LastElement(PBMap\MemCache\ImagesTimeStack()) + ;PopMapPosition(PBMap\MemCache\Images()) + AddMapElement(PBMap\MemCache\Images(), key) AddElement(PBMap\MemCache\ImagesTimeStack()) + ;MoveElement(PBMap\MemCache\ImagesTimeStack(), #PB_List_Last) PBMap\MemCache\ImagesTimeStack()\MapKey = MapKey(PBMap\MemCache\Images()) ;*** MyDebug("Key : " + key + " added in memory cache!", 3) - PBMap\MemCache\Images()\nImage = -1 + *timg = PBMap\MemCache\Images() + *timg\nImage = -1 EndIf - If PBMap\MemCache\Images()\Tile = 0 ; Check if a loading thread is not running + If *timg\Tile = 0 ; Check if a loading thread is not running MyDebug("Trying to load from HDD " + CacheFile, 3) - timg = GetTileFromHDD(CacheFile.s) - If timg <> -1 + img = GetTileFromHDD(CacheFile.s) + If img <> -1 MyDebug("Key : " + key + " found on HDD", 3) - PBMap\MemCache\Images()\nImage = timg - ProcedureReturn timg + *timg\nImage = img + *timg\Alpha = 256 + ProcedureReturn *timg EndIf MyDebug("Key : " + key + " not found on HDD", 3) ;Launch a new thread Protected *NewTile.Tile = AllocateMemory(SizeOf(Tile)) If *NewTile With *NewTile - PBMap\MemCache\Images()\Tile = *NewTile + *timg\Tile = *NewTile + *timg\Alpha = 0 + ;*timg\nImage = -1 ;New tile parameters - \Position\x = px - \Position\y = py - \PBMapTileX = tilex - \PBMapTileY = tiley - \PBMapZoom = PBMap\Zoom \key = key + \URL = URL \CacheFile = CacheFile - \ServerURL = ServerURL \RetryNb = 5 \nImage = -1 MyDebug(" Creating get image thread nb " + Str(\GetImageThread) + " to get " + CacheFile, 3) @@ -785,23 +874,24 @@ Module PBMap MyDebug(" Error, can't create a new tile loading thread", 3) EndIf EndIf - ProcedureReturn timg + ProcedureReturn *timg EndProcedure - Procedure DrawTiles(*Drawing.DrawingParameters, Layer, alpha.i=255) + Procedure DrawTiles(*Drawing.DrawingParameters, Layer) 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\CenterX / PBMap\TileSize ;How many tiles around the point - Protected ny = *Drawing\CenterY / PBMap\TileSize - Protected px, py, img, tilex,tiley, key.s, CacheFile.s + Protected nx = *Drawing\RadiusX / PBMap\TileSize ;How many tiles around the point + Protected ny = *Drawing\RadiusY / PBMap\TileSize + Protected px, py, *timg.ImgMemCach, tilex, tiley, key.s + Protected URL.s, CacheFile.s Protected tilemax = 1< -2 - If CreateDirectory(DirName) = #False - Error("Can't create the following Layer cache directory : " + DirName) + If CreateDirectory(DirName) = #False ; Creates a directory based on the layer name + Error("Can't create the following layer directory : " + DirName) + Else + MyDebug(DirName + " successfully created", 4) EndIf - EndIf - DirName.s = PBMap\Options\HDDCachePath + PBMap\Layers()\Name + "\" + Str(PBMap\Zoom) + EndIf + ; Creates the sub-directory based on the zoom + DirName + slash + Str(PBMap\Zoom) If FileSize(DirName) <> -2 If CreateDirectory(DirName) = #False - Error("Can't create the following cache directory : " + DirName) + Error("Can't create the following zoom directory : " + DirName) + Else + MyDebug(DirName + " successfully created", 4) EndIf EndIf ; Creates the sub-directory based on x - DirName.s + "\" + Str(tilex) + DirName.s + slash + Str(tilex) If FileSize(DirName) <> -2 If CreateDirectory(DirName) = #False - Error("Can't create the following cache directory : " + DirName) + Error("Can't create the following x directory : " + DirName) + Else + MyDebug(DirName + " successfully created", 4) EndIf EndIf ; Tile cache name based on y - CacheFile = DirName + "\" + Str(tiley) + ".png" - img = GetTile(key, CacheFile, px, py, tilex, tiley, PBMap\Layers()\ServerURL) - If img <> -1 + URL = PBMap\Layers()\ServerURL + Str(PBMap\Zoom) + "/" + Str(tilex) + "/" + Str(tiley) + ".png" + CacheFile = DirName + slash + Str(tiley) + ".png" + *timg = GetTile(key, URL, CacheFile) + If *timg\nImage <> -1 MovePathCursor(px, py) - DrawVectorImage(ImageID(img), alpha) + If *timg\Alpha <= 224 + DrawVectorImage(ImageID(*timg\nImage), *timg\Alpha) + *timg\Alpha + 32 + PBMap\Redraw = #True + Else + DrawVectorImage(ImageID(*timg\nImage), 255) + *timg\Alpha = 256 + EndIf Else MovePathCursor(px, py) - DrawVectorImage(ImageID(PBMap\ImgLoading), alpha) + DrawVectorImage(ImageID(PBMap\ImgLoading), 255) EndIf Else ;If PBMap\Layers()\Name = "" MovePathCursor(px, py) - DrawVectorImage(ImageID(PBMap\ImgNothing)) + DrawVectorImage(ImageID(PBMap\ImgNothing), 255) ;EndIf EndIf If PBMap\Options\ShowDebugInfos @@ -863,10 +966,10 @@ Module PBMap Procedure DrawPointer(*Drawing.DrawingParameters) If PBMap\CallBackMainPointer > 0 ; @Procedure(X.i, Y.i) to DrawPointer (you must use VectorDrawing lib) - CallFunctionFast(PBMap\CallBackMainPointer, *Drawing\CenterX, *Drawing\CenterY) + CallFunctionFast(PBMap\CallBackMainPointer, *Drawing\RadiusX, *Drawing\RadiusY) Else VectorSourceColor(RGBA($FF, 0, 0, $FF)) - MovePathCursor(*Drawing\CenterX, *Drawing\CenterY) + MovePathCursor(*Drawing\RadiusX, *Drawing\RadiusY) AddPathLine(-8, -16, #PB_Path_Relative) AddPathCircle(8, 0, 8, 180, 0, #PB_Path_Relative) AddPathLine(-8, 16, #PB_Path_Relative) @@ -888,7 +991,7 @@ Module PBMap sunit = " Km" EndSelect VectorFont(FontID(PBMap\Font), 10) - VectorSourceColor(RGBA(0, 0, 0,alpha)) + VectorSourceColor(RGBA(0, 0, 0, alpha)) MovePathCursor(x,y) DrawVectorText(StrD(Scale,3)+sunit) MovePathCursor(x,y+12) @@ -900,17 +1003,27 @@ Module PBMap Protected tx, ty, nx,ny,nx1,ny1,x,y,n,cx,dperpixel.d Protected pos1.PixelCoordinates,pos2.PixelCoordinates,Degrees1.GeographicCoordinates,degrees2.GeographicCoordinates Protected realx - tx = Int(*Drawing\TileCoordinates\x) - ty = Int(*Drawing\TileCoordinates\y) - nx = *Drawing\CenterX / PBMap\TileSize ;How many tiles around the point - ny = *Drawing\CenterY / PBMap\TileSize - *Drawing\Bounds\NorthWest\x = tx-nx-1 - *Drawing\Bounds\NorthWest\y = ty-ny-1 - *Drawing\Bounds\SouthEast\x = tx+nx+2 - *Drawing\Bounds\SouthEast\y = ty+ny+2 - ; Debug "------------------" - TileXY2LatLon(*Drawing\Bounds\NorthWest, @Degrees1, PBMap\Zoom) - TileXY2LatLon(*Drawing\Bounds\SouthEast, @Degrees2, PBMap\Zoom) + + ;TODO to find why it doesn't work + CopyStructure(*Drawing\Bounds\NorthWest, @Degrees1, GeographicCoordinates) + Debug "----" + Debug Degrees1\Longitude-1 + CopyStructure(*Drawing\Bounds\SouthEast, @Degrees2, GeographicCoordinates) + ;tx = Int(*Drawing\TileCoordinates\x) + ;ty = Int(*Drawing\TileCoordinates\y) + tx = *Drawing\TileCoordinates\x + ty = *Drawing\TileCoordinates\y + nx = *Drawing\RadiusX / PBMap\TileSize ;How many tiles around the point + ny = *Drawing\RadiusY / PBMap\TileSize + *Drawing\Bounds\TopLeft\x = tx-nx-1 + *Drawing\Bounds\TopLeft\y = ty-ny-1 + *Drawing\Bounds\BottomRight\x = tx+nx+2 + *Drawing\Bounds\BottomRight\y = ty+ny+2 + TileXY2LatLon(*Drawing\Bounds\TopLeft, @Degrees1, PBMap\Zoom) + TileXY2LatLon(*Drawing\Bounds\BottomRight, @Degrees2, PBMap\Zoom) + Debug Degrees1\Longitude + ;*** + ;ensure we stay positive for the drawing nx = Mod(Mod(Round(Degrees1\Longitude, #PB_Round_Down)-1, 360) + 360, 360) ny = Round(Degrees1\Latitude, #PB_Round_Up) +1 @@ -950,7 +1063,7 @@ Module PBMap StrokePath(1) EndProcedure - Procedure TrackPointer(x.i, y.i, dist.l) + Procedure DrawTrackPointer(x.d, y.d, dist.l) Protected color.l color=RGBA(0, 0, 0, 255) MovePathCursor(x,y) @@ -969,103 +1082,178 @@ Module PBMap DrawVectorText(Str(dist)) EndProcedure + Procedure DrawTrackPointerFirst(x.d, y.d, dist.l) + Protected color.l + color=RGBA(0, 0, 0, 255) + MovePathCursor(x,y) + AddPathLine(-9,-17,#PB_Path_Relative) + AddPathLine(17,0,#PB_Path_Relative) + AddPathLine(-9,17,#PB_Path_Relative) + VectorSourceColor(color) + AddPathCircle(x,y-24,16) + FillPath() + VectorSourceColor(RGBA(255, 0, 0, 255)) + AddPathCircle(x,y-24,14) + FillPath() + VectorFont(FontID(PBMap\Font), 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) + If *Ptr + ChangeCurrentElement(PBMap\TracksList(), *Ptr) + DeleteElement(PBMap\TracksList()) + EndIf + EndProcedure + + Procedure DeleteSelectedTracks() + ForEach PBMap\TracksList() + If PBMap\TracksList()\Selected + DeleteElement(PBMap\TracksList()) + PBMap\Redraw = #True + EndIf + Next + EndProcedure + + Procedure ClearTracks() + ClearList(PBMap\TracksList()) + PBMap\Redraw = #True + EndProcedure + + Procedure SetTrackColour(*Ptr, Colour.i) + If *Ptr + ChangeCurrentElement(PBMap\TracksList(), *Ptr) + PBMap\TracksList()\Colour = Colour + PBMap\Redraw = #True + EndIf + EndProcedure + Procedure DrawTracks(*Drawing.DrawingParameters) Protected Pixel.PixelCoordinates Protected Location.GeographicCoordinates Protected km.f, memKm.i - ;Trace Track - If ListSize(PBMap\TracksList()) > 0 - BeginVectorLayer() - ForEach PBMap\TracksList() - If ListSize(PBMap\TracksList()\Track()) > 0 - ForEach PBMap\TracksList()\Track() - ;If *Drawing\GeographicCoordinates\Latitude<>0 And *Drawing\GeographicCoordinates\Longitude<>0 - LatLon2PixelRel(@PBMap\TracksList()\Track(), @Pixel, PBMap\Zoom) - If ListIndex(PBMap\TracksList()\Track()) = 0 - MovePathCursor(Pixel\X, Pixel\Y) - Else - AddPathLine(Pixel\X, Pixel\Y) - EndIf - ;EndIf - Next - VectorSourceColor(RGBA(0, 255, 0, 150)) - StrokePath(10, #PB_Path_RoundEnd|#PB_Path_RoundCorner) - EndIf - Next - EndVectorLayer() - EndIf - ;Draw Distance - If PBMap\Options\TrackShowKms And ListSize(PBMap\TracksList()) > 0 - BeginVectorLayer() - ForEach PBMap\TracksList() - km = 0 : memKm = -1 - ForEach PBMap\TracksList()\Track() - ;Test Distance - If ListIndex(PBMap\TracksList()\Track()) = 0 - Location\Latitude = PBMap\TracksList()\Track()\Latitude - Location\Longitude = PBMap\TracksList()\Track()\Longitude - Else - km = km + HaversineInKM(@Location, @PBMap\TracksList()\Track()) - Location\Latitude = PBMap\TracksList()\Track()\Latitude - Location\Longitude = PBMap\TracksList()\Track()\Longitude - EndIf - LatLon2PixelRel(@PBMap\TracksList()\Track(), @Pixel, PBMap\Zoom) - If Int(km) <> memKm - memKm = Int(km) - If PBMap\Zoom > 10 - TrackPointer(Pixel\X , Pixel\Y, Int(km)) - EndIf + With PBMap\TracksList() + ;Trace Track + If ListSize(PBMap\TracksList()) > 0 + BeginVectorLayer() + ForEach PBMap\TracksList() + If ListSize(\Track()) > 0 + ;Check visibility + \Visible = #False + ForEach \Track() + If IsInDrawingPixelBoundaries(*Drawing, @PBMap\TracksList()\Track()) + \Visible = #True + Break + EndIf + Next + If \Visible + ;Draw tracks + ForEach \Track() + LatLon2PixelRel(@PBMap\TracksList()\Track(), @Pixel, PBMap\Zoom) + If ListIndex(\Track()) = 0 + MovePathCursor(Pixel\x, Pixel\y) + Else + AddPathLine(Pixel\x, Pixel\y) + EndIf + Next + ; \BoundingBox\x = PathBoundsX() + ; \BoundingBox\y = PathBoundsY() + ; \BoundingBox\w = PathBoundsWidth() + ; \BoundingBox\h = PathBoundsHeight() + If \Focus + VectorSourceColor(PBMap\Options\ColourFocus) + ElseIf \Selected + VectorSourceColor(PBMap\Options\ColourSelected) + Else + VectorSourceColor(\Colour) + EndIf + StrokePath(\StrokeWidth, #PB_Path_RoundEnd|#PB_Path_RoundCorner) + EndIf EndIf Next - Next - EndVectorLayer() + EndVectorLayer() + ;Draw distances + If PBMap\Options\ShowTrackKms And PBMap\Zoom > 10 + BeginVectorLayer() + ForEach PBMap\TracksList() + If \Visible + km = 0 : memKm = -1 + ForEach PBMap\TracksList()\Track() + ;Test Distance + If ListIndex(\Track()) = 0 + Location\Latitude = \Track()\Latitude + Location\Longitude = \Track()\Longitude + Else + km = km + HaversineInKM(@Location, @PBMap\TracksList()\Track()) + Location\Latitude = \Track()\Latitude + Location\Longitude = \Track()\Longitude + EndIf + LatLon2PixelRel(@PBMap\TracksList()\Track(), @Pixel, PBMap\Zoom) + If Int(km) <> memKm + memKm = Int(km) + If Int(km) = 0 + DrawTrackPointerFirst(Pixel\x , Pixel\y, Int(km)) + Else + DrawTrackPointer(Pixel\x , Pixel\y, Int(km)) + EndIf + EndIf + Next + EndIf + Next + EndVectorLayer() + EndIf + EndIf + EndWith + EndProcedure + + Procedure.i LoadGpxFile(file.s) + If LoadXML(0, file.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)) + MessageRequester("Error", 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 + For child = 1 To XMLChildCount(*MainNode) + *child = ChildXMLNode(*MainNode, child) + AddElement(*NewTrack\Track()) + If ExamineXMLAttributes(*child) + While NextXMLAttribute(*child) + Select XMLAttributeName(*child) + Case "lat" + *NewTrack\Track()\Latitude=ValD(XMLAttributeValue(*child)) + Case "lon" + *NewTrack\Track()\Longitude=ValD(XMLAttributeValue(*child)) + EndSelect + Wend + EndIf + Next + ZoomToTracks(LastElement(PBMap\TracksList())) ; <-To center the view, and zoom on the tracks + ProcedureReturn *NewTrack EndIf EndProcedure - Procedure DrawMarker(x.i, y.i, Nb, Color.l, Legend.s, Focus.i, Selected.i) - VectorSourceColor(color) - MovePathCursor(x, y) - AddPathLine(-8, -16, #PB_Path_Relative) - AddPathCircle(8, 0, 8, 180, 0, #PB_Path_Relative) - AddPathLine(-8, 16, #PB_Path_Relative) - ;FillPath(#PB_Path_Preserve) - ;ClipPath(#PB_Path_Preserve) - AddPathCircle(0, -16, 5, 0, 360, #PB_Path_Relative) - VectorSourceColor(Color) - FillPath(#PB_Path_Preserve) - If Focus - VectorSourceColor(RGBA(255, 255, 0, 255)) - StrokePath(3) - ElseIf Selected - VectorSourceColor(RGBA(255, 255, 0, 255)) - StrokePath(4) - Else - VectorSourceColor(Color) - StrokePath(1) - EndIf - If PBMap\Options\ShowMarkersNb - Protected Text.s = Str(Nb) - VectorFont(FontID(PBMap\Font), 13) - MovePathCursor(x - 10, y) - VectorSourceColor(RGBA(0, 0, 0, 255)) - DrawVectorParagraph(Text, 20, 20, #PB_VectorParagraph_Center) - EndIf - If PBMap\Options\ShowMarkersLegend - VectorFont(FontID(PBMap\Font), 13) - Protected Height = VectorParagraphHeight(Legend, 100, 13) - MovePathCursor(x - 50, y - 30 - Height) - VectorSourceColor(RGBA(0, 0, 0, 255)) - DrawVectorParagraph(Legend, 100, Height, #PB_VectorParagraph_Center) - EndIf - EndProcedure Procedure ClearMarkers() ClearList(PBMap\Markers()) + PBMap\Redraw = #True EndProcedure Procedure DeleteMarker(*Ptr) - ChangeCurrentElement(PBMap\Markers(), *Ptr) - DeleteElement(PBMap\Markers()) + If *Ptr + ChangeCurrentElement(PBMap\Markers(), *Ptr) + DeleteElement(PBMap\Markers()) + PBMap\Redraw = #True + EndIf EndProcedure Procedure DeleteSelectedMarkers() @@ -1077,11 +1265,12 @@ Module PBMap Next EndProcedure - Procedure.i AddMarker(Latitude.d, Longitude.d, Legend.s = "", Color.l=-1, CallBackPointer.i = -1) + Procedure.i AddMarker(Latitude.d, Longitude.d, Identifier.s = "", Legend.s = "", Color.l=-1, CallBackPointer.i = -1) Protected *Ptr = AddElement(PBMap\Markers()) If *Ptr PBMap\Markers()\GeographicCoordinates\Latitude = Latitude - PBMap\Markers()\GeographicCoordinates\Longitude = Mod(Mod(Longitude, 360) + 360, 360) + PBMap\Markers()\GeographicCoordinates\Longitude = ClipLongitude(Longitude) + PBMap\Markers()\Identifier = Identifier PBMap\Markers()\Legend = Legend PBMap\Markers()\Color = Color PBMap\Markers()\CallBackPointer = CallBackPointer @@ -1090,31 +1279,122 @@ Module PBMap EndIf EndProcedure - ; Draw all markers - Procedure DrawMarkers() - Protected Pixel.PixelCoordinates + ;-*** Marker Edit + Procedure MarkerIdentifierChange() + Protected *Marker.Marker = GetGadgetData(EventGadget()) + If GetGadgetText(EventGadget()) <> *Marker\Identifier + *Marker\Identifier = GetGadgetText(EventGadget()) + EndIf + EndProcedure + Procedure MarkerLegendChange() + Protected *Marker.Marker = GetGadgetData(EventGadget()) + If GetGadgetText(EventGadget()) <> *Marker\Legend + *Marker\Legend = GetGadgetText(EventGadget()) + EndIf + EndProcedure + Procedure MarkerEditCloseWindow() ForEach PBMap\Markers() - If PBMap\Markers()\GeographicCoordinates\Latitude <> 0 And PBMap\Markers()\GeographicCoordinates\Longitude <> 0 - ;GetPixelCoordFromLocation(PBMap\Markers()\GeographicCoordinates, @Pixel) - LatLon2PixelRel(PBMap\Markers()\GeographicCoordinates, @Pixel, PBMap\Zoom) - If Pixel\X >= 0 And Pixel\Y >= 0 And Pixel\X < GadgetWidth(PBMap\Gadget) And Pixel\Y < GadgetHeight(PBMap\Gadget) ; Only if visible ^_^ - 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()\Color, PBMap\Markers()\Legend, PBMap\Markers()\Focus, PBMap\Markers()\Selected) - EndIf - EndIf - EndIf + If PBMap\Markers()\EditWindow = EventWindow() + PBMap\Markers()\EditWindow = 0 + EndIf Next + CloseWindow(EventWindow()) + EndProcedure + Procedure MarkerEdit(*Marker.Marker) + If *Marker\EditWindow = 0 ;Check that this marker has no already opened window + Protected WindowMarkerEdit = OpenWindow(#PB_Any, WindowX(PBMap\Window) + WindowWidth(PBMap\Window) / 2 - 150, WindowY(PBMap\Window)+ WindowHeight(PBMap\Window) / 2 + 50, 300, 100, "Marker Edit", #PB_Window_SystemMenu | #PB_Window_TitleBar) + StickyWindow(WindowMarkerEdit, #True) + TextGadget(#PB_Any, 2, 2, 80, 25, gettext("Identifier")) + TextGadget(#PB_Any, 2, 27, 80, 25, gettext("Legend")) + Protected StringIdentifier = StringGadget(#PB_Any, 84, 2, 120, 25, *Marker\Identifier) : SetGadgetData(StringIdentifier, *Marker) + Protected EditorLegend = EditorGadget(#PB_Any, 84, 27, 210, 70) : SetGadgetText(EditorLegend, *Marker\Legend) : SetGadgetData(EditorLegend, *Marker) + *Marker\EditWindow = WindowMarkerEdit + BindGadgetEvent(StringIdentifier, @MarkerIdentifierChange(), #PB_EventType_Change) + BindGadgetEvent(EditorLegend, @MarkerLegendChange(), #PB_EventType_Change) + BindEvent(#PB_Event_CloseWindow, @MarkerEditCloseWindow(), WindowMarkerEdit) + Else + SetActiveWindow(*Marker\EditWindow) + EndIf + EndProcedure + ;-*** + + Procedure DrawMarker(x.i, y.i, Nb.i, *Marker.Marker) + Protected Text.s + VectorSourceColor(*Marker\Color) + MovePathCursor(x, y) + AddPathLine(-8, -16, #PB_Path_Relative) + AddPathCircle(8, 0, 8, 180, 0, #PB_Path_Relative) + AddPathLine(-8, 16, #PB_Path_Relative) + ;FillPath(#PB_Path_Preserve) + ;ClipPath(#PB_Path_Preserve) + AddPathCircle(0, -16, 5, 0, 360, #PB_Path_Relative) + VectorSourceColor(*Marker\Color) + FillPath(#PB_Path_Preserve) + If *Marker\Focus + VectorSourceColor(PBMap\Options\ColourFocus) + StrokePath(3) + ElseIf *Marker\Selected + VectorSourceColor(PBMap\Options\ColourSelected) + StrokePath(4) + Else + VectorSourceColor(*Marker\Color) + StrokePath(1) + EndIf + If PBMap\Options\ShowMarkersNb + If *Marker\Identifier = "" + Text.s = Str(Nb) + Else + Text.s = *Marker\Identifier + EndIf + VectorFont(FontID(PBMap\Font), 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\Font), 13) + ;dessin d'un cadre avec fond transparent + Protected Height = VectorParagraphHeight(*Marker\Legend, 100, 100) + Protected Width.l + If Height < 20 ; une ligne + Width = VectorTextWidth(*Marker\Legend) + Else + Width = 100 + EndIf + AddPathBox(x - (Width / 2), y - 30 - Height, Width, Height) + VectorSourceColor(RGBA(168, 255, 255, 100)) + FillPath() + AddPathBox(x - (Width / 2), y - 30 - Height, Width, Height) + VectorSourceColor(RGBA(36, 36, 255, 100)) + StrokePath(2) + MovePathCursor(x - 50, y - 30 - Height) + VectorSourceColor(RGBA(0, 0, 0, 255)) + DrawVectorParagraph(*Marker\Legend, 100, Height, #PB_VectorParagraph_Center) + EndIf EndProcedure - Procedure DrawDebugInfos() + ; Draw all markers + Procedure DrawMarkers(*Drawing.DrawingParameters) + 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) + Else + DrawMarker(Pixel\x, Pixel\y, ListIndex(PBMap\Markers()), @PBMap\Markers()) + EndIf + EndIf + Next + EndProcedure + + Procedure DrawDebugInfos(*Drawing.DrawingParameters) ; Display how many images in cache - VectorFont(FontID(PBMap\Font), 30) + VectorFont(FontID(PBMap\Font), 16) VectorSourceColor(RGBA(0, 0, 0, 80)) - MovePathCursor(50,50) + MovePathCursor(50, 50) DrawVectorText(Str(MapSize(PBMap\MemCache\Images()))) - MovePathCursor(50,80) + MovePathCursor(50, 70) Protected ThreadCounter = 0 ForEach PBMap\MemCache\Images() If PBMap\MemCache\Images()\Tile <> 0 @@ -1123,29 +1403,60 @@ Module PBMap EndIf EndIf Next - DrawVectorText(Str(ThreadCounter)) - MovePathCursor(50,110) + DrawVectorText(Str(ThreadCounter)) + MovePathCursor(50, 90) DrawVectorText(Str(PBMap\Zoom)) + MovePathCursor(50, 110) + DrawVectorText(StrD(*Drawing\Bounds\NorthWest\Latitude) + "," + StrD(*Drawing\Bounds\NorthWest\Longitude)) + MovePathCursor(50, 130) + DrawVectorText(StrD(*Drawing\Bounds\SouthEast\Latitude) + "," + StrD(*Drawing\Bounds\SouthEast\Longitude)) + EndProcedure + + Procedure DrawOSMCopyright(*Drawing.DrawingParameters) + Protected Text.s = "© OpenStreetMap contributors" + VectorFont(FontID(PBMap\Font), 12) + VectorSourceColor(RGBA(0, 0, 0, 80)) + MovePathCursor(GadgetWidth(PBMAP\Gadget) - VectorTextWidth(Text), GadgetHeight(PBMAP\Gadget) - 20) + DrawVectorText(Text) EndProcedure ;-*** Main drawing Procedure Drawing() Protected *Drawing.DrawingParameters = @PBMap\Drawing - Protected Px.d, Py.d,a, ts = PBMap\TileSize + Protected PixelCenter.PixelCoordinates + Protected Px.d, Py.d,a, ts = PBMap\TileSize, nx, ny + Protected NW.Coordinates, SE.Coordinates PBMap\Dirty = #False PBMap\Redraw = #False - ; Precalc some values - *Drawing\CenterX = GadgetWidth(PBMap\Gadget) / 2 - *Drawing\CenterY = GadgetHeight(PBMap\Gadget) / 2 + ;*** 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) ; Pixel shift, aka position in the tile - Px = *Drawing\TileCoordinates\x : Py = *Drawing\TileCoordinates\y + Px = *Drawing\TileCoordinates\x + Py = *Drawing\TileCoordinates\y *Drawing\DeltaX = Px * ts - (Int(Px) * ts) ;Don't forget the Int() ! *Drawing\DeltaY = Py * ts - (Int(Py) * ts) + ;Drawing boundaries + nx = *Drawing\RadiusX / ts ;How many tiles around the point + ny = *Drawing\RadiusY / ts + NW\x = Px - nx - 1 + 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 + ;*Drawing\Height = *Drawing\Bounds\NorthWest\Latitude - *Drawing\Bounds\SouthEast\Latitude + ;*** ; Main drawing stuff 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. ForEach PBMap\Layers() @@ -1155,20 +1466,21 @@ Module PBMap DrawTracks(*Drawing) EndIf If PBMap\Options\ShowMarkers - DrawMarkers() + DrawMarkers(*Drawing) EndIf + If PBMap\Options\ShowDegrees And PBMap\Zoom > 2 + DrawDegrees(*Drawing, 192) + EndIf If PBMap\Options\ShowPointer DrawPointer(*Drawing) EndIf If PBMap\Options\ShowDebugInfos - DrawDebugInfos() - EndIf - If PBMap\Options\ShowDegrees - DrawDegrees(*Drawing, 192) + DrawDebugInfos(*Drawing) EndIf If PBMap\Options\ShowScale DrawScale(*Drawing, 10, GadgetHeight(PBMAP\Gadget) - 20, 192) - EndIf + EndIf + DrawOSMCopyright(*Drawing) StopVectorDrawing() EndProcedure @@ -1178,27 +1490,27 @@ Module PBMap EndProcedure Procedure.d Pixel2Lon(x) - Protected NewX.d = (PBMap\PixelCoordinates\x - GadgetWidth(PBMap\Gadget) / 2 + x) / PBMap\TileSize + 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 EndProcedure Procedure.d Pixel2Lat(y) - Protected NewY.d = (PBMap\PixelCoordinates\y - GadgetHeight(PBMap\Gadget) / 2 + y) / PBMap\TileSize + 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)))) EndProcedure Procedure.d MouseLongitude() - Protected MouseX.d = (PBMap\PixelCoordinates\x - GadgetWidth(PBMap\Gadget) / 2 + GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_MouseX)) / PBMap\TileSize + Protected MouseX.d = (PBMap\PixelCoordinates\x - PBMap\Drawing\RadiusX + GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_MouseX)) / PBMap\TileSize Protected n.d = Pow(2.0, PBMap\Zoom) ; double mod is to ensure the longitude to be in the range [-180;180[ ProcedureReturn Mod(Mod(MouseX / n * 360.0, 360.0) + 360.0, 360.0) - 180 EndProcedure Procedure.d MouseLatitude() - Protected MouseY.d = (PBMap\PixelCoordinates\y - GadgetHeight(PBMap\Gadget) / 2 + GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_MouseY)) / PBMap\TileSize + 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) ProcedureReturn Degree(ATan(SinH(#PI * (1.0 - 2.0 * MouseY / n)))) EndProcedure @@ -1218,6 +1530,13 @@ Module PBMap PBMap\Zoom + Zoom EndIf EndSelect + 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 + 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) @@ -1233,17 +1552,17 @@ Module PBMap Procedure ZoomToArea(MinY.d, MaxY.d, MinX.d, MaxX.d) ;Source => http://gis.stackexchange.com/questions/19632/how-to-calculate-the-optimal-zoom-level-to-display-two-or-more-points-on-a-map ;bounding box in long/lat coords (x=long, y=lat) - Protected DeltaX.d=MaxX-MinX ;assumption ! In original code DeltaX have no source - Protected centerX.d=MinX+DeltaX/2 ; assumption ! In original code CenterX have no source - Protected paddingFactor.f= 1.2 ;paddingFactor: this can be used to get the "120%" effect ThomM refers to. Value of 1.2 would get you the 120%. + Protected DeltaX.d = MaxX - MinX ;assumption ! In original code DeltaX have no source + Protected centerX.d = MinX + DeltaX / 2 ; assumption ! In original code CenterX have no source + Protected paddingFactor.f= 1.2 ;paddingFactor: this can be used to get the "120%" effect ThomM refers to. Value of 1.2 would get you the 120%. Protected ry1.d = Log((Sin(Radian(MinY)) + 1) / Cos(Radian(MinY))) Protected ry2.d = Log((Sin(Radian(MaxY)) + 1) / Cos(Radian(MaxY))) Protected ryc.d = (ry1 + ry2) / 2 Protected centerY.d = Degree(ATan(SinH(ryc))) - Protected resolutionHorizontal.d = DeltaX / GadgetWidth(PBMap\Gadget) + 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 = GadgetHeight(PBMap\Gadget)/2; + Protected viewHeightHalf.d = PBMap\Drawing\RadiusY ; Protected zoomFactorPowered.d = viewHeightHalf / (40.7436654315252*(vy1 - vy0)) Protected resolutionVertical.d = 360.0 / (zoomFactorPowered * PBMap\TileSize) If resolutionHorizontal<>0 And resolutionVertical<>0 @@ -1281,6 +1600,7 @@ Module PBMap EndWith EndIf EndProcedure + Procedure SetZoom(Zoom.i, mode.i = #PB_Relative) Select mode Case #PB_Relative @@ -1301,6 +1621,16 @@ Module PBMap EndIf EndProcedure + Procedure SetAngle(Angle.d, Mode = #PB_Absolute) + If Mode = #PB_Absolute + PBmap\Angle = Angle + Else + PBMap\Angle + Angle + PBMap\Angle = Mod(PBMap\Angle,360) + EndIf + PBMap\Redraw = #True + EndProcedure + Procedure SetCallBackLocation(CallBackLocation.i) PBMap\CallBackLocation = CallBackLocation EndProcedure @@ -1320,18 +1650,16 @@ Module PBMap ; #MODE_HAND = 1 -> Hand only ; #MODE_SELECT = 2 -> Move objects only ; #MODE_EDIT = 3 -> Create objects - Procedure SetMode(Mode = #MODE_DEFAULT) - PBMap\Mode = Mode - EndProcedure + Procedure SetMode(Mode.i = #MODE_DEFAULT) + PBMap\Mode = Mode + EndProcedure - ;Zoom on x, y position relative to the canvas gadget - Procedure SetZoomOnPosition(x, y, zoom) - Protected MouseX.d, MouseY.d - Protected OldPx.d, OldPy.d, OldMx.d, OldMy.d, Px.d, Py.d - Protected CenterX = GadgetWidth(PBMap\Gadget) / 2 - Protected CenterY = GadgetHeight(PBMap\Gadget) / 2 - x - CenterX - y - CenterY + Procedure.i GetMode() + ProcedureReturn PBMap\Mode + EndProcedure + + ;Zoom on x, y pixel position from the center + Procedure ZoomOnPixel(x, y, zoom) ;*** First : Zoom PBMap\Zoom + zoom If PBMap\Zoom > PBMap\ZoomMax : PBMap\Zoom = PBMap\ZoomMax : ProcedureReturn : EndIf @@ -1353,15 +1681,29 @@ Module PBMap EndIf EndProcedure - ;Go to x, y position relative to the canvas gadget + ;Zoom on x, y position relative to the canvas gadget + Procedure ZoomOnPixelRel(x, y, zoom) + ZoomOnPixel(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) - Protected CenterX = GadgetWidth(PBMap\Gadget) / 2 - Protected CenterY = GadgetHeight(PBMap\Gadget) / 2 - x - CenterX - y - CenterY LatLon2Pixel(@PBMap\GeographicCoordinates, @PBMap\PixelCoordinates, PBMap\Zoom) - PBMap\PixelCoordinates\x + x - PBMap\PixelCoordinates\y + y + PBMap\PixelCoordinates\x + x - PBMap\Drawing\RadiusX + PBMap\PixelCoordinates\y + y - PBMap\Drawing\RadiusY + Pixel2LatLon(@PBMap\PixelCoordinates, @PBMap\GeographicCoordinates, PBMap\Zoom) + ; Start drawing + PBMap\Redraw = #True + ; If CallBackLocation send Location to function + 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) ; Start drawing PBMap\Redraw = #True @@ -1380,22 +1722,136 @@ Module PBMap EndProcedure Procedure.i GetZoom() - Protected Value.d - Value = PBMap\Zoom - ProcedureReturn Value + ProcedureReturn PBMap\Zoom + EndProcedure + + Procedure.d GetAngle() + ProcedureReturn PBMap\Angle + EndProcedure + + Procedure NominatimGeoLocationQuery(Address.s, *ReturnPosition.GeographicCoordinates = 0) + 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) + ; Debug *Buffer + ; Debug MemorySize(*Buffer) + ; Protected JSon.s = PeekS(*Buffer, MemorySize(*Buffer), #PB_UTF8) + HTTPProxy(PBMap\Options\ProxyURL + ":" + PBMap\Options\ProxyPort, PBMap\Options\ProxyUser, PBMap\Options\ProxyPassword) + Size = ReceiveHTTPFile(Query, JSONFileName) + If LoadJSON(0, JSONFileName) = 0 + ;Demivec's code + MyDebug( JSONErrorMessage() + " at position " + + JSONErrorPosition() + " in line " + + JSONErrorLine() + " of JSON web Data", 1) + ElseIf JSONArraySize(JSONValue(0)) > 0 + Protected object_val = GetJSONElement(JSONValue(0), 0) + Protected object_box = GetJSONMember(object_val, "boundingbox") + Protected bbox.BoundingBox + bbox\SouthEast\Latitude = ValD(GetJSONString(GetJSONElement(object_box, 0))) + bbox\NorthWest\Latitude = ValD(GetJSONString(GetJSONElement(object_box, 1))) + bbox\NorthWest\Longitude = ValD(GetJSONString(GetJSONElement(object_box, 2))) + bbox\SouthEast\Longitude = ValD(GetJSONString(GetJSONElement(object_box, 3))) + Protected lat.s = GetJSONString(GetJSONMember(object_val, "lat")) + Protected lon.s = GetJSONString(GetJSONMember(object_val, "lon")) + If *ReturnPosition <> 0 + *ReturnPosition\Latitude = ValD(lat) + *ReturnPosition\Longitude = ValD(lon) + EndIf + If lat<> "" And lon <> "" + ZoomToArea(bbox\SouthEast\Latitude, bbox\NorthWest\Latitude, bbox\NorthWest\Longitude, bbox\SouthEast\Longitude) + ;SetLocation(Position\Latitude, Position\Longitude) + EndIf + EndIf + EndProcedure + + ;(c) ts-soft http://www.purebasic.fr/english/viewtopic.php?f=12&t=58657&hilit=createdirectory&view=unread#unread + CompilerSelect #PB_Compiler_OS + CompilerCase #PB_OS_Windows + #FILE_ATTRIBUTE_DEVICE = 64 ;(0x40) + #FILE_ATTRIBUTE_INTEGRITY_STREAM = 32768 ;(0x8000) + #FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 8192;(0x2000) + #FILE_ATTRIBUTE_NO_SCRUB_DATA = 131072;(0x20000) + #FILE_ATTRIBUTE_VIRTUAL = 65536;(0x10000) + #FILE_ATTRIBUTE_DONTSETFLAGS = ~(#FILE_ATTRIBUTE_DIRECTORY| + #FILE_ATTRIBUTE_SPARSE_FILE| + #FILE_ATTRIBUTE_OFFLINE| + #FILE_ATTRIBUTE_NOT_CONTENT_INDEXED| + #FILE_ATTRIBUTE_VIRTUAL| + 0) + Macro SetFileAttributesEx(Name, Attribs) + SetFileAttributes(Name, Attribs & #FILE_ATTRIBUTE_DONTSETFLAGS) + EndMacro + CompilerDefault + Macro SetFileAttributesEx(Name, Attribs) + SetFileAttributes(Name, Attribs) + EndMacro + CompilerEndSelect + + Procedure CreateDirectoryEx(DirectoryName.s, FileAttribute = #PB_Default) + Protected i, c, tmp.s + If Right(DirectoryName, 1) = slash + DirectoryName = Left(DirectoryName, Len(DirectoryName) -1) + EndIf + c = CountString(DirectoryName, slash) + 1 + For i = 1 To c + tmp + StringField(DirectoryName, i, slash) + If FileSize(tmp) <> -2 + CreateDirectory(tmp) + EndIf + tmp + slash + Next + If FileAttribute <> #PB_Default + SetFileAttributesEx(DirectoryName, FileAttribute) + EndIf + If FileSize(DirectoryName) = -2 + ProcedureReturn #True + 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) + 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") + CreateDirectoryEx(PBMap\Options\HDDCachePath) + ProcedureReturn #True + Else + MyDebug("Can't clear cache in " + PBMap\Options\HDDCachePath) + ProcedureReturn #False + EndIf EndProcedure Procedure CanvasEvents() - Protected MouseX.i, MouseY.i + Protected CanvasMouseX.d, CanvasMouseY.d, MouseX.d, MouseY.d Protected MarkerCoords.PixelCoordinates, *Tile.Tile, MapWidth = Pow(2, PBMap\Zoom) * PBMap\TileSize Protected key.s, Touch.i + Protected Pixel.PixelCoordinates Static CtrlKey PBMap\Moving = #False + CanvasMouseX = GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_MouseX) - PBMap\Drawing\RadiusX + CanvasMouseY = GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_MouseY) - PBMap\Drawing\RadiusY + ; rotation wip + ; StartVectorDrawing(CanvasVectorOutput(PBMap\Gadget)) + ; RotateCoordinates(0, 0, PBMap\Angle) + ; CanvasMouseX = ConvertCoordinateX(MouseX, MouseY, #PB_Coordinate_Device, #PB_Coordinate_User) + ; CanvasMouseY = ConvertCoordinateY(MouseX, MouseY, #PB_Coordinate_Device, #PB_Coordinate_User) + ; StopVectorDrawing() Select EventType() + Case #PB_EventType_Focus + PBMap\Drawing\RadiusX = GadgetWidth(PBMap\Gadget) / 2 + PBMap\Drawing\RadiusY = GadgetHeight(PBMap\Gadget) / 2 Case #PB_EventType_KeyUp Select GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_Key) Case #PB_Shortcut_Delete DeleteSelectedMarkers() + DeleteSelectedTracks() EndSelect PBMap\Redraw = #True If GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_Modifiers)&#PB_Canvas_Control = 0 @@ -1403,72 +1859,77 @@ Module PBMap EndIf Case #PB_EventType_KeyDown With PBMap\Markers() - Select GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_Key) - Case #PB_Shortcut_Left - ForEach PBMap\Markers() - If \Selected - \GeographicCoordinates\Longitude = ClipLongitude( \GeographicCoordinates\Longitude - 10* 360 / Pow(2, PBMap\Zoom + 8)) - EndIf - Next - Case #PB_Shortcut_Up - ForEach PBMap\Markers() - If \Selected - \GeographicCoordinates\Latitude + 10* 360 / Pow(2, PBMap\Zoom + 8) - EndIf - Next - Case #PB_Shortcut_Right - ForEach PBMap\Markers() - If \Selected - \GeographicCoordinates\Longitude = ClipLongitude( \GeographicCoordinates\Longitude + 10* 360 / Pow(2, PBMap\Zoom + 8)) - EndIf - Next - Case #PB_Shortcut_Down - ForEach PBMap\Markers() - If \Selected - \GeographicCoordinates\Latitude - 10* 360 / Pow(2, PBMap\Zoom + 8) - EndIf - Next - EndSelect + Select GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_Key) + Case #PB_Shortcut_Left + ForEach PBMap\Markers() + If \Selected + \GeographicCoordinates\Longitude = ClipLongitude( \GeographicCoordinates\Longitude - 10* 360 / Pow(2, PBMap\Zoom + 8)) + EndIf + Next + Case #PB_Shortcut_Up + ForEach PBMap\Markers() + If \Selected + \GeographicCoordinates\Latitude + 10* 360 / Pow(2, PBMap\Zoom + 8) + EndIf + Next + Case #PB_Shortcut_Right + ForEach PBMap\Markers() + If \Selected + \GeographicCoordinates\Longitude = ClipLongitude( \GeographicCoordinates\Longitude + 10* 360 / Pow(2, PBMap\Zoom + 8)) + EndIf + Next + Case #PB_Shortcut_Down + ForEach PBMap\Markers() + If \Selected + \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 CtrlKey = #True EndIf Case #PB_EventType_LeftDoubleClick - If PBMap\Mode = #MODE_DEFAULT Or PBMap\Mode = #MODE_SELECT - ;Check if the mouse touch a marker, if so, jump to it - LatLon2Pixel(@PBMap\GeographicCoordinates, @PBMap\PixelCoordinates, PBMap\Zoom) - MouseX = PBMap\PixelCoordinates\x - GadgetWidth(PBMap\Gadget) / 2 + GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_MouseX) - MouseY = PBMap\PixelCoordinates\y - GadgetHeight(PBMap\Gadget) / 2 + GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_MouseY) - ;Clip MouseX to the map range (in X, the map is infinite) - MouseX = Mod(Mod(MouseX, MapWidth) + MapWidth, MapWidth) - Touch = #False - ForEach PBMap\Markers() - LatLon2Pixel(@PBMap\Markers()\GeographicCoordinates, @MarkerCoords, PBMap\Zoom) - If Distance(MarkerCoords\x, MarkerCoords\y, MouseX, MouseY) < 8 + LatLon2Pixel(@PBMap\GeographicCoordinates, @PBMap\PixelCoordinates, PBMap\Zoom) + MouseX = PBMap\PixelCoordinates\x + CanvasMouseX + MouseY = PBMap\PixelCoordinates\y + CanvasMouseY + ;Clip MouseX to the map range (in X, the map is infinite) + 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) + If Distance(MarkerCoords\x, MarkerCoords\y, MouseX, MouseY) < 8 + 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) - Break + ElseIf PBMap\Mode = #MODE_EDIT + ;Edit the legend + MarkerEdit(@PBMap\Markers()) EndIf - Next - EndIf + Break + EndIf + Next If Not Touch - GotoPixelRel(GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_MouseX), GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_MouseY)) + GotoPixel(MouseX, MouseY) EndIf Case #PB_EventType_MouseWheel If PBMap\Options\WheelMouseRelative ;Relative zoom (centered on the mouse) - SetZoomOnPosition(GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_MouseX), GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_MouseY), GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_WheelDelta)) + ZoomOnPixel(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 Case #PB_EventType_LeftButtonDown - LatLon2Pixel(@PBMap\GeographicCoordinates, @PBMap\PixelCoordinates, PBMap\Zoom) - MouseX = PBMap\PixelCoordinates\x - GadgetWidth(PBMap\Gadget) / 2 + GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_MouseX) - MouseY = PBMap\PixelCoordinates\y - GadgetHeight(PBMap\Gadget) / 2 + GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_MouseY) + ;LatLon2Pixel(@PBMap\GeographicCoordinates, @PBMap\PixelCoordinates, PBMap\Zoom) + ;Mem cursor Coord + PBMap\MoveStartingPoint\x = CanvasMouseX + PBMap\MoveStartingPoint\y = CanvasMouseY ;Clip MouseX to the map range (in X, the map is infinite) - MouseX = Mod(Mod(MouseX, MapWidth) + MapWidth, MapWidth) + 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) @@ -1482,15 +1943,25 @@ Module PBMap PBMap\Markers()\Focus = #False EndIf Next + ;Check if we select track(s) + ForEach PBMap\TracksList() + If CtrlKey = #False + PBMap\TracksList()\Selected = #False ;If no CTRL key, deselect everything and select only the focused track + EndIf + If PBMap\TracksList()\Focus + PBMap\TracksList()\Selected = #True + PBMap\TracksList()\Focus = #False + EndIf + Next EndIf - ;Mem cursor Coord - PBMap\MoveStartingPoint\x = GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_MouseX) - PBMap\MoveStartingPoint\y = GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_MouseY) Case #PB_EventType_MouseMove PBMap\Moving = #True + ; Drag If PBMap\MoveStartingPoint\x <> - 1 - MouseX = GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_MouseX) - PBMap\MoveStartingPoint\x - MouseY = GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_MouseY) - PBMap\MoveStartingPoint\y + 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() @@ -1515,28 +1986,57 @@ Module PBMap EndIf EndIf PBMap\Redraw = #True - PBMap\MoveStartingPoint\x = GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_MouseX) - PBMap\MoveStartingPoint\y = GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_MouseY) Else + ; Touch test LatLon2Pixel(@PBMap\GeographicCoordinates, @PBMap\PixelCoordinates, PBMap\Zoom) - MouseX = PBMap\PixelCoordinates\x - GadgetWidth(PBMap\Gadget) / 2 + GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_MouseX) - MouseY = PBMap\PixelCoordinates\y - GadgetHeight(PBMap\Gadget) / 2 + GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_MouseY) + 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) - ;Check if mouse touch markers - If PBMap\Mode = #MODE_DEFAULT Or PBMap\Mode = #MODE_SELECT + 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) If Distance(MarkerCoords\x, MarkerCoords\y, MouseX, MouseY) < 8 PBMap\Markers()\Focus = #True - Else + PBMap\Redraw = #True + ElseIf PBMap\Markers()\Focus ;If CtrlKey = #False PBMap\Markers()\Focus = #False - ;EndIf + PBMap\Redraw = #True EndIf Next + ;Check if mouse touch tracks + With PBMap\TracksList() + ;Trace Track + If ListSize(PBMap\TracksList()) > 0 + ForEach PBMap\TracksList() + If ListSize(\Track()) > 0 + If \Visible + StartVectorDrawing(CanvasVectorOutput(PBMap\Gadget)) + ;Simulate tracks 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) + 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 EndIf - PBMap\Redraw = #True EndIf Case #PB_EventType_LeftButtonUp PBMap\MoveStartingPoint\x = - 1 @@ -1560,29 +2060,66 @@ Module PBMap EndSelect EndProcedure + ; Redraws at regular intervals Procedure TimerEvents() - ;Redraw at regular intervals If EventTimer() = PBMap\Timer And (PBMap\Redraw Or PBMap\Dirty) Drawing() EndIf 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) - EndIf - BindGadgetEvent(PBMap\Gadget, @CanvasEvents()) - AddWindowTimer(PBMap\Window, PBMap\Timer, PBMap\Options\TimerInterval) - BindEvent(#PB_Event_Timer, @TimerEvents()) - ;AddKeyboardShortcut(#PB_Shortcut_Delete + EndIf + BindMapGadget(PBMap\Gadget) + EndProcedure + + Procedure InitPBMap(Window) + Protected Result.i + PBMap\ZoomMin = 0 + PBMap\ZoomMax = 18 + PBMap\MoveStartingPoint\x = - 1 + PBMap\TileSize = 256 + PBMap\Dirty = #False + PBMap\EditMarker = #False + PBMap\Font = LoadFont(#PB_Any, "Arial", 20, #PB_Font_Bold) + PBMap\Window = Window + PBMap\Timer = 1 + PBMap\Mode = #MODE_DEFAULT + LoadOptions() + If PBMap\Options\Verbose + OpenConsole() + EndIf + CreateDirectoryEx(PBMap\Options\HDDCachePath) + If PBMap\Options\DefaultOSMServer <> "" + AddMapServerLayer("OSM", 1, PBMap\Options\DefaultOSMServer) + EndIf + TechnicalImagesCreation() + SetLocation(0, 0) EndProcedure EndModule -;-**** Example of application **** +;**************************************************************** +; +;- Example of application +; +;**************************************************************** + CompilerIf #PB_Compiler_IsMainFile InitNetwork() @@ -1593,6 +2130,8 @@ CompilerIf #PB_Compiler_IsMainFile #Gdt_Right #Gdt_Up #Gdt_Down + ;#Gdt_RotateLeft + ;#Gdt_RotateRight #Button_4 #Button_5 #Combo_0 @@ -1607,6 +2146,16 @@ CompilerIf #PB_Compiler_IsMainFile #Gdt_AddMarker #Gdt_AddOpenseaMap #Gdt_Degrees + #Gdt_EditMode + #Gdt_ClearDiskCache + #TextGeoLocationQuery + #StringGeoLocationQuery + EndEnumeration + + ;Menu events + Enumeration + #MenuEventLonLatStringEnter + #MenuEventGeoLocationStringEnter EndEnumeration Structure Location @@ -1651,19 +2200,25 @@ CompilerIf #PB_Compiler_IsMainFile ResizeGadget(#Text_1,WindowWidth(#Window_0)-170,#PB_Ignore,#PB_Ignore,#PB_Ignore) ResizeGadget(#Gdt_Left, WindowWidth(#Window_0) - 150 ,#PB_Ignore,#PB_Ignore,#PB_Ignore) ResizeGadget(#Gdt_Right,WindowWidth(#Window_0) - 90 ,#PB_Ignore,#PB_Ignore,#PB_Ignore) + ;ResizeGadget(#Gdt_RotateLeft, WindowWidth(#Window_0) - 150 ,#PB_Ignore,#PB_Ignore,#PB_Ignore) + ;ResizeGadget(#Gdt_RotateRight,WindowWidth(#Window_0) - 90 ,#PB_Ignore,#PB_Ignore,#PB_Ignore) ResizeGadget(#Gdt_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)-100,#PB_Ignore,#PB_Ignore,#PB_Ignore) - ResizeGadget(#StringLongitude,WindowWidth(#Window_0)-100,#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_AddOpenseaMap,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 @@ -1672,8 +2227,11 @@ CompilerIf #PB_Compiler_IsMainFile LoadFont(0, "Arial", 12) LoadFont(1, "Arial", 12, #PB_Font_Bold) + LoadFont(2, "Arial", 8) TextGadget(#Text_1, 530, 50, 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, 100, 30, 30, Chr($25C4)) : SetGadgetFont(#Gdt_Left, FontID(0)) ButtonGadget(#Gdt_Right, 610, 100, 30, 30, Chr($25BA)) : SetGadgetFont(#Gdt_Right, FontID(0)) ButtonGadget(#Gdt_Up, 580, 070, 30, 30, Chr($25B2)) : SetGadgetFont(#Gdt_Up, FontID(0)) @@ -1681,36 +2239,48 @@ CompilerIf #PB_Compiler_IsMainFile TextGadget(#Text_2, 530, 160, 60, 15, "Zoom") ButtonGadget(#Button_4, 550, 180, 50, 30, " + ") : SetGadgetFont(#Button_4, FontID(1)) ButtonGadget(#Button_5, 600, 180, 50, 30, " - ") : SetGadgetFont(#Button_5, FontID(1)) - TextGadget(#Text_3, 530, 230, 60, 15, "Latitude : ") - StringGadget(#StringLatitude, 600, 230, 90, 20, "") - TextGadget(#Text_4, 530, 250, 60, 15, "Longitude : ") - StringGadget(#StringLongitude, 600, 250, 90, 20, "") + TextGadget(#Text_3, 530, 230, 50, 15, "Latitude ") + StringGadget(#StringLatitude, 580, 230, 90, 20, "") + TextGadget(#Text_4, 530, 250, 50, 15, "Longitude ") + StringGadget(#StringLongitude, 580, 250, 90, 20, "") ButtonGadget(#Gdt_AddMarker, 530, 280, 150, 30, "Add Marker") ButtonGadget(#Gdt_LoadGpx, 530, 310, 150, 30, "Load GPX") - ButtonGadget(#Gdt_AddOpenseaMap, 530, 340, 150, 30, "OpenSeaMap") - ButtonGadget(#Gdt_Degrees, 530, 370, 150, 30, "Show/Hide Degrees") - + ButtonGadget(#Gdt_AddOpenseaMap, 530, 340, 150, 30, "Show/Hide OpenSeaMap", #PB_Button_Toggle) + ButtonGadget(#Gdt_Degrees, 530, 370, 150, 30, "Show/Hide Degrees", #PB_Button_Toggle) + ButtonGadget(#Gdt_EditMode, 530, 400, 150, 30, "Edit mode ON/OFF", #PB_Button_Toggle) + ButtonGadget(#Gdt_ClearDiskCache, 530, 430, 150, 30, "Clear disk cache", #PB_Button_Toggle) + TextGadget(#TextGeoLocationQuery, 530, 465, 150, 15, "Enter an address") + StringGadget(#StringGeoLocationQuery, 530, 480, 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 OpenSeaMap = 0, Degrees = 1 + Define *Track ;Our main gadget PBMap::InitPBMap(#Window_0) - ;PBMap::SetOption("Proxy", "1") - ;PBMap::SetOption("ProxyUrl", "myproxy") - ;PBMap::SetOption("proxyport","3128") - PBMap::SetOption("CleanCache","1") ;Delete all files in HDD cache Directory - PBMap::SetOption("ShowDegrees", "1") + PBMap::SetOption("ShowDegrees", "0") : Degrees = 0 PBMap::SetOption("ShowDebugInfos", "0") - PBMap::SetOption("ShowScale", "1") + PBMap::SetOption("ShowScale", "1") + PBMap::SetOption("Warning", "1") PBMap::SetOption("ShowMarkersLegend", "1") - PBMap::SetOption("TrackShowKms", "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(49.0446828398, 2.0349812508,12) ; Change the PBMap 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::AddMarker(49.0446828398, 2.0349812508, "", "", -1, @MyMarker()) ; To add a marker with a customised GFX Repeat Event = WaitWindowEvent() @@ -1727,35 +2297,78 @@ CompilerIf #PB_Compiler_IsMainFile PBMap::SetLocation(0, 10* -360 / Pow(2, PBMap::GetZoom() + 8), 0, #PB_Relative) Case #Gdt_Right PBMap::SetLocation(0, 10* 360 / Pow(2, PBMap::GetZoom() + 8), 0, #PB_Relative) + ;Case #Gdt_RotateLeft + ; PBMAP::SetAngle(-5,#PB_Relative) + ; PBMap::Refresh() + ;Case #Gdt_RotateRight + ; PBMAP::SetAngle(5,#PB_Relative) + ; PBMap::Refresh() Case #Button_4 PBMap::SetZoom(1) Case #Button_5 PBMap::SetZoom( - 1) Case #Gdt_LoadGpx - PBMap::LoadGpxFile(OpenFileRequester("Choose a file to load", "", "Gpx|*.gpx", 0)) + *Track = PBMap::LoadGpxFile(OpenFileRequester("Choose a file to load", "", "Gpx|*.gpx", 0)) + PBMap::SetTrackColour(*Track, RGBA(Random(255), Random(255), Random(255), 128)) Case #StringLatitude, #StringLongitude Select EventType() + Case #PB_EventType_Focus + AddKeyboardShortcut(#Window_0, #PB_Shortcut_Return, #MenuEventLonLatStringEnter) Case #PB_EventType_LostFocus - PBMap::SetLocation(ValD(GetGadgetText(#StringLatitude)), ValD(GetGadgetText(#StringLongitude))) ; Change the PBMap coordinates - PBMAP::Refresh() + 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)) + PBMap::AddMarker(ValD(GetGadgetText(#StringLatitude)), ValD(GetGadgetText(#StringLongitude)), "", "Test", RGBA(Random(255), Random(255), Random(255), 255)) Case #Gdt_AddOpenseaMap If OpenSeaMap = 0 OpenSeaMap = PBMap::AddMapServerLayer("OpenSeaMap", 2, "http://t1.openseamap.org/seamark/") ; Add a special osm overlay map on layer nb 2 + SetGadgetState(#Gdt_AddOpenseaMap, 1) Else PBMap::DeleteLayer(OpenSeaMap) OpenSeaMap = 0 + SetGadgetState(#Gdt_AddOpenseaMap, 0) 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 @@ -1763,10 +2376,11 @@ CompilerIf #PB_Compiler_IsMainFile EndIf CompilerEndIf -; IDE Options = PureBasic 5.60 beta 7 (Windows - x86) -; CursorPosition = 1699 -; FirstLine = 1683 -; Folding = ------------- + + +; IDE Options = PureBasic 5.60 beta 7 (Windows - x64) +; CursorPosition = 33 +; Folding = ----------------- ; EnableThread ; EnableXP ; EnableUnicode \ No newline at end of file