diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9a024d7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +PBMap.pb.bak \ No newline at end of file diff --git a/PBMap.pb b/PBMap.pb index 113588d..2f9aaa1 100644 --- a/PBMap.pb +++ b/PBMap.pb @@ -27,33 +27,47 @@ UsePNGImageEncoder() DeclareModule PBMap #Red = 255 + ;-Show debug infos Global Verbose = 0 Global MyDebugLevel = 5 - ;-Proxy ON/OFF - Global Proxy = #False #SCALE_NAUTICAL = 1 #SCALE_KM = 0 + #MODE_DEFAULT = 0 + #MODE_HAND = 1 + #MODE_SELECT = 2 + #MODE_EDIT = 3 + + ;-Declarations Declare InitPBMap(window) + Declare SetOption(Option.s, Value.s) + Declare LoadOptions(PreferencesFile.s = "PBMap.prefs") + 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 MapGadget(Gadget.i, X.i, Y.i, Width.i, Height.i) - Declare SetLocation(latitude.d, longitude.d, zoom = 15, mode.i = #PB_Absolute) + Declare SetLocation(latitude.d, longitude.d, Zoom = -1, mode.i = #PB_Absolute) Declare Drawing() Declare SetZoom(Zoom.i, mode.i = #PB_Relative) - Declare ZoomToArea() + 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 AddMarker(Latitude.d,Longitude.d,color.l=-1, CallBackPointer.i = -1) + Declare.i AddMarker(Latitude.d, Longitude.d, Legend.s = "", color.l=-1, CallBackPointer.i = -1) + Declare ClearMarkers() + Declare DeleteMarker(*Ptr) + Declare DeleteSelectedMarkers() Declare Quit() Declare Error(msg.s) Declare Refresh() Declare.d GetLatitude() Declare.d GetLongitude() + Declare.d MouseLatitude() + Declare.d MouseLongitude() Declare.i GetZoom() EndDeclareModule @@ -99,8 +113,6 @@ Module PBMap TileCoordinates.Coordinates Bounds.TileBounds Canvas.i - PBMapTileX.i - PBMapTileY.i PBMapZoom.i GeographicCoordinates.GeographicCoordinates CenterX.i @@ -111,31 +123,51 @@ Module PBMap End.i EndStructure - Structure TileThread - *Tile.Tile - GetImageThread.i - EndStructure - Structure ImgMemCach nImage.i - *Tile.Tile - ;Location.Location - ;Mutex.i + *Tile.Tile + TimeStackPosition.i + EndStructure + + Structure ImgMemCachKey + MapKey.s EndStructure Structure TileMemCach Map Images.ImgMemCach(4096) + List ImagesTimeStack.ImgMemCachKey() ; Usage of the tile (first = older) EndStructure Structure Marker GeographicCoordinates.GeographicCoordinates ; Marker latitude and longitude - color.l ; Marker color + 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) EndStructure Structure Option + HDDCachePath.s ; Path where to load and save tiles downloaded from server + DefaultOSMServer.s ; Base layer OSM server WheelMouseRelative.i - ScaleUnit.i ; Scale unit to use for measurements + ScaleUnit.i ; Scale unit to use for measurements + Proxy.i ; Proxy ON/OFF + ProxyURL.s + ProxyPort.s + ProxyUser.s + ProxyPassword.s + ShowDegrees.i + ShowDebugInfos.i + ShowScale.i + ShowTrack.i + ShowMarkers.i + ShowPointer.i + TimerInterval.i + MaxMemCache.i ; in MiB + TrackShowKms.i + ShowMarkersNb.i + ShowMarkersLegend.i EndStructure Structure Layer @@ -143,46 +175,49 @@ Module PBMap Name.s ServerURL.s ; Web URL ex: http://tile.openstreetmap.org/ EndStructure - + + Structure Tracks + List Track.GeographicCoordinates() + EndStructure ;-PBMap Structure Structure PBMap Window.i ; Parent Window Gadget.i ; Canvas Gadget Id Font.i ; Font to uses when write on the map - Timer.i + Timer.i ; Redraw/update timer + GeographicCoordinates.GeographicCoordinates ; Latitude and Longitude from focus point Drawing.DrawingParameters ; Drawing parameters based on focus point - ; + CallBackLocation.i ; @Procedure(latitude.d,lontitude.d) CallBackMainPointer.i ; @Procedure(X.i, Y.i) to DrawPointer (you must use VectorDrawing lib) - ; + PixelCoordinates.PixelCoordinates ; Actual focus point coords in pixels (global) MoveStartingPoint.PixelCoordinates ; Start mouse position coords when dragging the map - ; - List Layers.Layer() + + List Layers.Layer() ; ZoomMin.i ; Min Zoom supported by server ZoomMax.i ; Max Zoom supported by server Zoom.i ; Current zoom TileSize.i ; Tile size downloaded on the server ex : 256 - ; - HDDCachePath.S ; Path where to load and save tiles downloaded from server + MemCache.TileMemCach ; Images in memory cache - ; + + Mode.i ; User mode : 0 (default)->hand (moving map) and select markers, 1->hand, 2->select only (moving objects), 3->drawing (todo) Redraw.i Moving.i Dirty.i ; To signal that drawing need a refresh - ; - MainDrawingThread.i - TileThreadMutex.i; ;Mutex to protect resources - List track.GeographicCoordinates() ; To display a GPX track - List Marker.Marker() ; To diplay marker - EditMarkerIndex.l - ImgLoading.i ;Image Loading Tile - ImgNothing.i ;Image Nothing Tile + List TracksList.Tracks() ; To display a GPX track + List Markers.Marker() ; To diplay marker + EditMarker.l + + ImgLoading.i ; Image Loading Tile + ImgNothing.i ; Image Nothing Tile + + Options.option ; Options - Options.option ; EndStructure #PB_MAP_REDRAW = #PB_EventType_FirstCustomValue + 1 @@ -194,7 +229,7 @@ Module PBMap ;Shows an error msg and terminates the program Procedure Error(msg.s) - MessageRequester("MapGadget", msg, #PB_MessageRequester_Ok) + MessageRequester("PBMap", msg, #PB_MessageRequester_Ok) End EndProcedure @@ -206,7 +241,7 @@ Module PBMap EndIf EndProcedure - ;- *** CURL specific *** + ;- *** CURL specific ; (program has To be compiled in console format for curl debug infos) IncludeFile "libcurl.pbi" ; https://github.com/deseven/pbsamples/tree/master/crossplatform/libcurl @@ -268,7 +303,8 @@ Module PBMap Procedure TechnicalImagesCreation() ;"Loading" image - Protected Text$ = "Loading" + Protected LoadingText$ = "Loading" + Protected NothingText$ = "Nothing" PBmap\ImgLoading = CreateImage(#PB_Any, 256, 256) If PBmap\ImgLoading StartVectorDrawing(ImageVectorOutput(PBMap\Imgloading)) @@ -279,41 +315,118 @@ Module PBMap MovePathCursor(0, 0) VectorFont(FontID(PBMap\Font), 256 / 20) VectorSourceColor(RGBA(150, 150, 150, 255)) - MovePathCursor(0 + (256 - VectorTextWidth(Text$)) / 2, 0 + (256 - VectorTextHeight(Text$)) / 2) - DrawVectorText(Text$) + MovePathCursor(0 + (256 - VectorTextWidth(LoadingText$)) / 2, 0 + (256 - VectorTextHeight(LoadingText$)) / 2) + DrawVectorText(LoadingText$) EndVectorLayer() StopVectorDrawing() EndIf ;"Nothing" tile PBmap\ImgNothing = CreateImage(#PB_Any, 256, 256) If PBmap\ImgNothing - StartVectorDrawing(ImageVectorOutput(PBMap\Imgloading)) - VectorSourceColor(RGBA(255, 255, 255, 128)) + StartVectorDrawing(ImageVectorOutput(PBMap\ImgNothing)) + ;BeginVectorLayer() + VectorSourceColor(RGBA(220, 230, 255, 255)) AddPathBox(0, 0, 256, 256) FillPath() + ;MovePathCursor(0, 0) + ;VectorFont(FontID(PBMap\Font), 256 / 20) + ;VectorSourceColor(RGBA(150, 150, 150, 255)) + ;MovePathCursor(0 + (256 - VectorTextWidth(NothingText$)) / 2, 0 + (256 - VectorTextHeight(NothingText$)) / 2) + ;DrawVectorText(NothingText$) + ;EndVectorLayer() StopVectorDrawing() EndIf EndProcedure - Procedure InitPBMap(Window) - Protected Result.i - If Verbose - OpenConsole() + ;TODO : best cleaning of the string from bad behaviour + Procedure.s StringCheck(String.s) + ProcedureReturn Trim(RemoveString(RemoveString(RemoveString(RemoveString(RemoveString(RemoveString(RemoveString(RemoveString(RemoveString(RemoveString(String, Chr(0)), Chr(32)), Chr(39)), Chr(33)), Chr(34)), "@"), "/"), "\"), "$"), "%")) + EndProcedure + + Macro SelBool(Name) + Select UCase(Value) + Case "0", "FALSE", "DISABLE" + PBMap\Options\Name = #False + Default + PBMap\Options\Name = #True + EndSelect + EndMacro + + Procedure SetOption(Option.s, Value.s) + Option = StringCheck(Option) + Select LCase(Option) + Case "proxy" + SelBool(Proxy) + Case "proxyurl" + PBMap\Options\ProxyURL = Value + Case "proxyport" + PBMap\Options\ProxyPort = Value + Case "proxyuser" + PBMap\Options\ProxyUser = Value + Case "tilescachepath" + PBMap\Options\HDDCachePath = Value + Case "maxmemcache" + PBMap\Options\MaxMemCache = Val(Value) + Case "wheelmouserelative" + SelBool(WheelMouseRelative) + Case "showdegrees" + SelBool(ShowDegrees) + Case "showdebuginfos" + SelBool(ShowDebugInfos) + Case "showscale" + SelBool(ShowScale) + Case "showmarkers" + SelBool(ShowMarkers) + Case "showpointer" + SelBool(ShowPointer) + Case "showtrack" + SelBool(ShowTrack) + Case "showmarkersnb" + SelBool(ShowMarkersNb) + Case "showmarkerslegend" + SelBool(ShowMarkersLegend) + Case "trackshowkms" + SelBool(TrackShowKms) + EndSelect + EndProcedure + + ;By default, save options in the user's home directory + Procedure SaveOptions(PreferencesFile.s = "PBMap.prefs") + If PreferencesFile = "PBMap.prefs" + CreatePreferences(GetHomeDirectory() + "PBMap.prefs") + 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() + EndProcedure + + Procedure LoadOptions(PreferencesFile.s = "PBMap.prefs") + If PreferencesFile = "PBMap.prefs" + OpenPreferences(GetHomeDirectory() + "PBMap.prefs") + Else + OpenPreferences(PreferencesFile) EndIf - PBMap\HDDCachePath = GetTemporaryDirectory() - PBMap\ZoomMin = 0 - PBMap\ZoomMax = 18 - PBMap\MoveStartingPoint\x = - 1 - PBMap\TileSize = 256 - PBMap\Dirty = #False - PBMap\TileThreadMutex = CreateMutex() - PBMap\EditMarkerIndex = -1 ;Initialised with "no marker selected" - PBMap\Font = LoadFont(#PB_Any, "Arial", 20, #PB_Font_Bold) - PBMap\Window = Window - PBMap\Timer = 1 - PBMap\Options\WheelMouseRelative = #True - AddMapServerLayer("OSM", 1, "http://tile.openstreetmap.org/") - ;-Preferences ;Use this to create and customize your preferences file for the first time ; CreatePreferences(GetHomeDirectory() + "PBMap.prefs") ; ;Or this to modify @@ -327,22 +440,69 @@ Module PBMap ; WritePreferenceString("ProxyUser", "myproxyname") ; WritePreferenceString("ProxyPass", "myproxypass") ;TODO !Warning! !not encoded! ; ClosePreferences() - OpenPreferences(GetHomeDirectory() + "PBMap.prefs") PreferenceGroup("PROXY") - Proxy = ReadPreferenceInteger("Proxy", #False) - If Proxy - Global ProxyURL$ = ReadPreferenceString("ProxyURL", "") ;InputRequester("ProxyServer", "Do you use a Proxy Server? Then enter the full url:", "") - Global ProxyPort$ = ReadPreferenceString("ProxyPort", "") ;InputRequester("ProxyPort" , "Do you use a specific port? Then enter it", "") - Global ProxyUser$ = ReadPreferenceString("ProxyUser", "") ;InputRequester("ProxyUser" , "Do you use a user name? Then enter it", "") - Global ProxyPassword$ = InputRequester("ProxyPass", "Do you use a password ? Then enter it", "") ;TODO + 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 curl_global_init(#CURL_GLOBAL_WIN32) TechnicalImagesCreation() + SetLocation(0, 0) 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 cache directory : " + DirName) + Else + MyDebug(DirName + " successfully created", 4) + EndIf + EndIf If *Ptr PBMap\Layers()\Name = LayerName PBMap\Layers()\Order = Order @@ -428,6 +588,11 @@ Module PBMap *Location\Latitude = Degree(ATan(SinH(#PI * (1.0 - 2.0 * *Coords\y / n)))) 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 @@ -460,7 +625,7 @@ Module PBMap EndIf *Pixel\y = PBMap\Drawing\CenterY + (py - PBMap\PixelCoordinates\y) EndProcedure - + ; HaversineAlgorithm ; http://andrew.hedges.name/experiments/haversine/ Procedure.d HaversineInKM(*posA.GeographicCoordinates, *posB.GeographicCoordinates) @@ -510,36 +675,35 @@ Module PBMap Protected *MainNode,*subNode,*child,child.l *MainNode=MainXMLNode(0) *MainNode=XMLNodeFromPath(*MainNode,"/gpx/trk/trkseg") - ClearList(PBMap\track()) + Protected *NewTrack.Tracks = AddElement(PBMap\TracksList()) For child = 1 To XMLChildCount(*MainNode) *child = ChildXMLNode(*MainNode, child) - AddElement(PBMap\track()) + AddElement(*NewTrack\Track()) If ExamineXMLAttributes(*child) While NextXMLAttribute(*child) Select XMLAttributeName(*child) Case "lat" - PBMap\track()\Latitude=ValD(XMLAttributeValue(*child)) + *NewTrack\Track()\Latitude=ValD(XMLAttributeValue(*child)) Case "lon" - PBMap\track()\Longitude=ValD(XMLAttributeValue(*child)) + *NewTrack\Track()\Longitude=ValD(XMLAttributeValue(*child)) EndSelect Wend EndIf Next + ZoomToTracks(LastElement(PBMap\TracksList())) ; <-To center the view, and zoom on the tracks EndIf EndProcedure - + + ;-*** These are threaded Procedure.i GetTileFromHDD(CacheFile.s) Protected nImage.i If FileSize(CacheFile) > 0 - ; OnErrorCall(@LoadErrorHandler()) nImage = LoadImage(#PB_Any, CacheFile) - ; OnErrorDefault() If IsImage(nImage) MyDebug("Success loading " + CacheFile + " as nImage " + Str(nImage), 3) ProcedureReturn nImage Else MyDebug("Failed loading " + CacheFile + " as nImage " + Str(nImage) + " -> not an image !", 3) - MyDebug("Failed loading " + CacheFile + " as nImage " + Str(nImage) + " -> not an image !", 3) EndIf Else MyDebug("Failed loading " + CacheFile + " -> Size <= 0", 3) @@ -551,35 +715,35 @@ Module PBMap Protected *Buffer Protected nImage.i = -1 Protected FileSize.i, timg - If Proxy - FileSize = CurlReceiveHTTPToFile(TileURL, CacheFile, ProxyURL$, ProxyPort$, ProxyUser$, ProxyPassword$) - If FileSize > 0 - MyDebug("Loaded from web " + TileURL + " as CacheFile " + CacheFile, 3) - nImage = GetTileFromHDD(CacheFile) - Else - MyDebug("Problem loading from web " + TileURL, 3) - EndIf + FileSize = CurlReceiveHTTPToFile(TileURL, CacheFile, PBMap\Options\ProxyURL, PBMap\Options\ProxyPort, PBMap\Options\ProxyUser, PBMap\Options\ProxyPassword) + If FileSize > 0 + MyDebug("Loaded from web " + TileURL + " as CacheFile " + CacheFile, 3) + nImage = GetTileFromHDD(CacheFile) Else - *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) - 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) - ; EndIf - Else - MyDebug("Can't catch image loaded from web " + TileURL, 3) - nImage = -1 - ;ShowMemoryViewer(*Buffer, MemorySize(*Buffer)) - EndIf - Else - MyDebug(" Problem loading from web " + TileURL, 3) - EndIf + 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) + ; 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 + ; **** ProcedureReturn nImage EndProcedure @@ -601,27 +765,57 @@ Module PBMap *Tile\RetryNb = -2 ;End of the thread PostEvent(#PB_Event_Gadget, PBMap\Window, PBmap\Gadget, #PB_MAP_TILE_CLEANUP, *Tile) ;To free memory outside the thread EndProcedure + ;-*** Procedure.i GetTile(key.s, CacheFile.s, px.i, py.i, tilex.i, tiley.i, ServerURL.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) MyDebug("Key : " + key + " found in memory cache!", 3) timg = PBMap\MemCache\Images()\nImage - If timg <> -1 + If timg <> -1 MyDebug("Image : " + timg + " 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) + MoveElement(PBMap\MemCache\ImagesTimeStack(), #PB_List_Last) + ;*** ProcedureReturn timg EndIf Else AddMapElement(PBMap\MemCache\Images(), key) + PushMapPosition(PBMap\MemCache\Images()) + ;*** Cache management + ; if cache size exceeds limit, try to delete the oldest tile used + 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) + ResetList(PBMap\MemCache\ImagesTimeStack()) + While NextElement(PBMap\MemCache\ImagesTimeStack()) And CacheSize > CacheLimit + Protected CacheMapKey.s = PBMap\MemCache\ImagesTimeStack()\MapKey + Protected Image = PBMap\MemCache\Images(CacheMapKey)\nImage + If IsImage(Image) ; Check if the image is valid (is a loading thread running ?) + FreeImage(Image) + MyDebug("Delete " + CacheMapKey + " As image nb " + Str(Image), 4) + DeleteMapElement(PBMap\MemCache\Images(), CacheMapKey) + DeleteElement(PBMap\MemCache\ImagesTimeStack()) + 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()) + AddElement(PBMap\MemCache\ImagesTimeStack()) + PBMap\MemCache\ImagesTimeStack()\MapKey = MapKey(PBMap\MemCache\Images()) + ;*** MyDebug("Key : " + key + " added in memory cache!", 3) PBMap\MemCache\Images()\nImage = -1 EndIf - If PBMap\MemCache\Images()\Tile = 0 ;Check if a loading thread is not running + If PBMap\MemCache\Images()\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 MyDebug("Key : " + key + " found on HDD", 3) - PBMap\MemCache\Images()\nImage = timg + PBMap\MemCache\Images()\nImage = timg ProcedureReturn timg EndIf MyDebug("Key : " + key + " not found on HDD", 3) @@ -640,7 +834,7 @@ Module PBMap \CacheFile = CacheFile \ServerURL = ServerURL \RetryNb = 5 - \nImage = -1 + \nImage = -1 MyDebug(" Creating get image thread nb " + Str(\GetImageThread) + " to get " + CacheFile, 3) \GetImageThread = CreateThread(@GetImageThread(), *NewTile) EndWith @@ -652,11 +846,10 @@ Module PBMap EndProcedure Procedure DrawTiles(*Drawing.DrawingParameters, Layer, alpha.i=255) - ;DisableDebugger 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 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 tilemax = 1<= 0 And tiley < tilemax - kq = (PBMap\zoom << 8) | (tilex << 16) | (tiley << 36) + kq = (PBMap\Zoom << 8) | (tilex << 16) | (tiley << 36) key = PBMap\Layers()\Name + Str(kq) - CacheFile = PBMap\HDDCachePath + key + ".png" + ; Creates the cache tree based on the OSM tree+Layer : layer/zoom/x/y.png + ; Creates the sub-directory based on the zoom + Protected DirName.s = PBMap\Options\HDDCachePath + PBMap\Layers()\Name + "\" + Str(PBMap\Zoom) + If FileSize(DirName) <> -2 + If CreateDirectory(DirName) = #False + Error("Can't create the following cache directory : " + DirName) + EndIf + EndIf + ; Creates the sub-directory based on x + DirName.s + "\" + Str(tilex) + If FileSize(DirName) <> -2 + If CreateDirectory(DirName) = #False + Error("Can't create the following cache directory : " + DirName) + 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 MovePathCursor(px, py) @@ -684,41 +893,23 @@ Module PBMap DrawVectorImage(ImageID(PBMap\ImgLoading), alpha) EndIf Else - If PBMap\Layers()\Name = "" - MovePathCursor(px, py) - DrawVectorImage(ImageID(PBMap\ImgNothing)) - EndIf + ;If PBMap\Layers()\Name = "" + MovePathCursor(px, py) + DrawVectorImage(ImageID(PBMap\ImgNothing)) + ;EndIf + EndIf + If PBMap\Options\ShowDebugInfos + VectorFont(FontID(PBMap\Font), 16) + VectorSourceColor(RGBA(0, 0, 0, 80)) + MovePathCursor(px, py) + DrawVectorText("x:" + Str(tilex)) + MovePathCursor(px, py + 16) + DrawVectorText("y:" + Str(tiley)) EndIf Next Next EndProcedure - ; ;-**** Clean Mem Cache - ; ;TODO in development, by now there's many cache problem as the loading thread could be perturbed - ; ;GadgetWidth(PBMap\Gadget)/PBMap\TileSize - ; Protected MaxNbTile.l - ; If GadgetWidth(PBMap\Gadget)>GadgetHeight(PBMap\Gadget) - ; MaxNbTile=GadgetWidth(PBMap\Gadget)/PBMap\TileSize - ; Else - ; MaxNbTile=GadgetHeight(PBMap\Gadget)/PBMap\TileSize - ; EndIf - ; Protected Scale.d= 40075*Cos(Radian(PBMap\GeographicCoordinates\Latitude))/Pow(2,PBMap\Zoom) - ; Protected Limit.d=Scale*(MaxNbTile)*1.5 - ; Debug "Cache cleaning" - ; ForEach PBMap\MemCache\Images() - ; Protected Distance.d = HaversineInKM(@PBMap\MemCache\Images()\Location, @PBMap\GeographicCoordinates) - ; Debug "Limit:"+StrD(Limit)+" Distance:"+StrD(Distance) - ; If Distance>Limit And IsImage(PBMap\MemCache\Images()\nImage) - ; LockMutex(PBMap\MemCache\Images()\Mutex) - ; Debug "delete" - ; Debug PBMap\MemCache\Images() - ; FreeImage(PBMap\MemCache\Images()\nImage) - ; UnlockMutex(PBMap\MemCache\Images()\Mutex) - ; FreeMutex(PBMap\MemCache\Images()\Mutex) - ; DeleteMapElement(PBMap\MemCache\Images()) - ; EndIf - ; Next - Procedure DrawPointer(*Drawing.DrawingParameters) If PBMap\CallBackMainPointer > 0 ; @Procedure(X.i, Y.i) to DrawPointer (you must use VectorDrawing lib) @@ -729,8 +920,6 @@ Module PBMap AddPathLine(-8, -16, #PB_Path_Relative) AddPathCircle(8, 0, 8, 180, 0, #PB_Path_Relative) AddPathLine(-8, 16, #PB_Path_Relative) - ;FillPath(#PB_Path_Preserve) - ;ClipPath(#PB_Path_Preserve) AddPathCircle(0, -16, 5, 0, 360, #PB_Path_Relative) VectorSourceColor(RGBA($FF, 0, 0, $FF)) FillPath(#PB_Path_Preserve):VectorSourceColor(RGBA($FF, 0, 0, $FF));RGBA(0, 0, 0, 255)) @@ -811,7 +1000,7 @@ Module PBMap StrokePath(1) EndProcedure - Procedure TrackPointer(x.i, y.i,dist.l) + Procedure TrackPointer(x.i, y.i, dist.l) Protected color.l color=RGBA(0, 0, 0, 255) MovePathCursor(x,y) @@ -830,51 +1019,60 @@ Module PBMap DrawVectorText(Str(dist)) EndProcedure - Procedure DrawTrack(*Drawing.DrawingParameters) + Procedure DrawTracks(*Drawing.DrawingParameters) Protected Pixel.PixelCoordinates Protected Location.GeographicCoordinates Protected km.f, memKm.i - If ListSize(PBMap\track())>0 - ;Trace Track - ForEach PBMap\track() - If *Drawing\GeographicCoordinates\Latitude<>0 And *Drawing\GeographicCoordinates\Longitude<>0 - ;GetPixelCoordFromLocation(@PBMap\track(),@Pixel) - LatLon2PixelRel(@PBMap\track(), @Pixel, PBMap\Zoom) - If ListIndex(PBMap\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) - ;Draw Distance - ForEach PBMap\track() - ;-Test Distance - If ListIndex(PBMap\track())=0 - Location\Latitude=PBMap\track()\Latitude - Location\Longitude=PBMap\track()\Longitude - Else - km=km+HaversineInKM(@Location,@PBMap\track()) ;<- display Distance - Location\Latitude=PBMap\track()\Latitude - Location\Longitude=PBMap\track()\Longitude - EndIf - ;GetPixelCoordFromLocation(@PBMap\track(),@Pixel) - LatLon2PixelRel(@PBMap\track(),@Pixel, PBMap\Zoom) - If Int(km)<>memKm - memKm=Int(km) - If PBMap\Zoom>10 - BeginVectorLayer() - TrackPointer(Pixel\X , Pixel\Y,Int(km)) - EndVectorLayer() - EndIf + ;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 + EndIf + Next + Next + EndVectorLayer() EndIf EndProcedure - Procedure DrawMarker(x.i, y.i, color.l = 0) + 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) @@ -883,66 +1081,85 @@ Module PBMap ;FillPath(#PB_Path_Preserve) ;ClipPath(#PB_Path_Preserve) AddPathCircle(0, -16, 5, 0, 360, #PB_Path_Relative) - VectorSourceColor(color) - FillPath(#PB_Path_Preserve):VectorSourceColor(color);RGBA(0, 0, 0, 255)) - StrokePath(1) + 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 - ; Add a Marker To the Map - Procedure AddMarker(Latitude.d, Longitude.d, color.l=-1, CallBackPointer.i = -1) - AddElement(PBMap\Marker()) - PBMap\Marker()\GeographicCoordinates\Latitude = Latitude - PBMap\Marker()\GeographicCoordinates\Longitude = Mod(Mod(Longitude, 360) + 360, 360) - PBMap\Marker()\color = color - PBMap\Marker()\CallBackPointer = CallBackPointer - PBMap\Redraw = #True + Procedure ClearMarkers() + ClearList(PBMap\Markers()) EndProcedure - ; Draw all markers on the screen ! - Procedure DrawMarkers(*Drawing.DrawingParameters) + Procedure DeleteMarker(*Ptr) + ChangeCurrentElement(PBMap\Markers(), *Ptr) + DeleteElement(PBMap\Markers()) + EndProcedure + + Procedure DeleteSelectedMarkers() + ForEach PBMap\Markers() + If PBMap\Markers()\Selected + DeleteElement(PBMap\Markers()) + PBMap\Redraw = #True + EndIf + Next + EndProcedure + + Procedure.i AddMarker(Latitude.d, Longitude.d, 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()\Legend = Legend + PBMap\Markers()\Color = Color + PBMap\Markers()\CallBackPointer = CallBackPointer + PBMap\Redraw = #True + ProcedureReturn *Ptr + EndIf + EndProcedure + + ; Draw all markers + Procedure DrawMarkers() Protected Pixel.PixelCoordinates - ForEach PBMap\Marker() - If PBMap\Marker()\GeographicCoordinates\Latitude <> 0 And PBMap\Marker()\GeographicCoordinates\Longitude <> 0 - ;GetPixelCoordFromLocation(PBMap\Marker()\GeographicCoordinates, @Pixel) - LatLon2PixelRel(PBMap\Marker()\GeographicCoordinates, @Pixel, PBMap\Zoom) + 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\Marker()\CallBackPointer > 0 - CallFunctionFast(PBMap\Marker()\CallBackPointer, Pixel\X, Pixel\Y) + 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, PBMap\Marker()\color) + DrawMarker(Pixel\X, Pixel\Y, ListIndex(PBMap\Markers()), PBMap\Markers()\Color, PBMap\Markers()\Legend, PBMap\Markers()\Focus, PBMap\Markers()\Selected) EndIf EndIf EndIf Next EndProcedure - ;-*** Main drawing - Procedure Drawing() - Protected *Drawing.DrawingParameters = @PBMap\Drawing - Protected Px.d, Py.d,a, ts = PBMap\TileSize - PBMap\Dirty = #False - PBMap\Redraw = #False - ;Precalc some values - *Drawing\CenterX = GadgetWidth(PBMap\Gadget) / 2 - *Drawing\CenterY = GadgetHeight(PBMap\Gadget) / 2 - *Drawing\GeographicCoordinates\Latitude = PBMap\GeographicCoordinates\Latitude - *Drawing\GeographicCoordinates\Longitude = PBMap\GeographicCoordinates\Longitude - LatLon2TileXY(*Drawing\GeographicCoordinates, *Drawing\TileCoordinates, PBMap\Zoom) - ;Pixel shift, aka position in the tile - Px = *Drawing\TileCoordinates\x : Py = *Drawing\TileCoordinates\y - *Drawing\DeltaX = Px * ts - (Int(Px) * ts) ;Don't forget the Int() ! - *Drawing\DeltaY = Py * ts - (Int(Py) * ts) - ;Main drawing stuff - StartVectorDrawing(CanvasVectorOutput(PBMap\Gadget)) - ;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() - DrawTiles(*Drawing, ListIndex(PBMap\Layers())) - Next - DrawTrack(*Drawing) - DrawMarkers(*Drawing) - DrawPointer(*Drawing) - ;- Display how many images in cache + Procedure DrawDebugInfos() + ; Display how many images in cache VectorFont(FontID(PBMap\Font), 30) VectorSourceColor(RGBA(0, 0, 0, 80)) MovePathCursor(50,50) @@ -957,10 +1174,51 @@ Module PBMap EndIf Next DrawVectorText(Str(ThreadCounter)) - DrawDegrees(*Drawing, 192) - ;If PBMap\Options\ShowScale - DrawScale(*Drawing,10,GadgetHeight(PBMAP\Gadget)-20,192) - ;EndIf + MovePathCursor(50,110) + DrawVectorText(Str(PBMap\Zoom)) + EndProcedure + + ;-*** Main drawing + Procedure Drawing() + Protected *Drawing.DrawingParameters = @PBMap\Drawing + Protected Px.d, Py.d,a, ts = PBMap\TileSize + PBMap\Dirty = #False + PBMap\Redraw = #False + ; Precalc some values + *Drawing\CenterX = GadgetWidth(PBMap\Gadget) / 2 + *Drawing\CenterY = GadgetHeight(PBMap\Gadget) / 2 + *Drawing\GeographicCoordinates\Latitude = PBMap\GeographicCoordinates\Latitude + *Drawing\GeographicCoordinates\Longitude = PBMap\GeographicCoordinates\Longitude + LatLon2TileXY(*Drawing\GeographicCoordinates, *Drawing\TileCoordinates, PBMap\Zoom) + ; Pixel shift, aka position in the tile + Px = *Drawing\TileCoordinates\x : Py = *Drawing\TileCoordinates\y + *Drawing\DeltaX = Px * ts - (Int(Px) * ts) ;Don't forget the Int() ! + *Drawing\DeltaY = Py * ts - (Int(Py) * ts) + ; Main drawing stuff + StartVectorDrawing(CanvasVectorOutput(PBMap\Gadget)) + ;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() + DrawTiles(*Drawing, ListIndex(PBMap\Layers())) + Next + If PBMap\Options\ShowTrack + DrawTracks(*Drawing) + EndIf + If PBMap\Options\ShowMarkers + DrawMarkers() + EndIf + If PBMap\Options\ShowPointer + DrawPointer(*Drawing) + EndIf + If PBMap\Options\ShowDebugInfos + DrawDebugInfos() + EndIf + If PBMap\Options\ShowDegrees + DrawDegrees(*Drawing, 192) + EndIf + If PBMap\Options\ShowScale + DrawScale(*Drawing, 10, GadgetHeight(PBMAP\Gadget) - 20, 192) + EndIf StopVectorDrawing() EndProcedure @@ -972,7 +1230,7 @@ Module PBMap Procedure.d Pixel2Lon(x) Protected NewX.d = (PBMap\PixelCoordinates\x - GadgetWidth(PBMap\Gadget) / 2 + x) / PBMap\TileSize Protected n.d = Pow(2.0, PBMap\Zoom) - ;double mod is to ensure the longitude to be in the range [-180;180[ + ; double mod is to ensure the longitude to be in the range [-180;180[ ProcedureReturn Mod(Mod(NewX / n * 360.0, 360.0) + 360.0, 360.0) - 180 EndProcedure @@ -985,7 +1243,7 @@ Module PBMap Procedure.d MouseLongitude() Protected MouseX.d = (PBMap\PixelCoordinates\x - GadgetWidth(PBMap\Gadget) / 2 + GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_MouseX)) / PBMap\TileSize Protected n.d = Pow(2.0, PBMap\Zoom) - ;double mod is to ensure the longitude to be in the range [-180;180[ + ; double mod is to ensure the longitude to be in the range [-180;180[ ProcedureReturn Mod(Mod(MouseX / n * 360.0, 360.0) + 360.0, 360.0) - 180 EndProcedure @@ -995,48 +1253,36 @@ Module PBMap ProcedureReturn Degree(ATan(SinH(#PI * (1.0 - 2.0 * MouseY / n)))) EndProcedure - Procedure SetLocation(latitude.d, longitude.d, zoom = 15, Mode.i = #PB_Absolute) + Procedure SetLocation(latitude.d, longitude.d, Zoom = -1, Mode.i = #PB_Absolute) Select Mode Case #PB_Absolute PBMap\GeographicCoordinates\Latitude = latitude PBMap\GeographicCoordinates\Longitude = longitude - PBMap\Zoom = zoom + If Zoom <> -1 + PBMap\Zoom = Zoom + EndIf Case #PB_Relative PBMap\GeographicCoordinates\Latitude + latitude PBMap\GeographicCoordinates\Longitude + longitude - PBMap\Zoom + zoom + If Zoom <> -1 + PBMap\Zoom + Zoom + EndIf EndSelect 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 + ; 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 - ;Drawing() If PBMap\CallBackLocation > 0 CallFunctionFast(PBMap\CallBackLocation, @PBMap\GeographicCoordinates) EndIf EndProcedure - Procedure ZoomToArea() + 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 MinY.d,MaxY.d,MinX.d,MaxX.d - ForEach PBMap\track() - If ListIndex(PBMap\track())=0 Or PBMap\track()\LongitudeMaxX - MaxX=PBMap\track()\Longitude - EndIf - If ListIndex(PBMap\track())=0 Or PBMap\track()\LatitudeMaxY - MaxY=PBMap\track()\Latitude - EndIf - Next 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%. @@ -1055,12 +1301,36 @@ Module PBMap 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(lat, lon, Round(zoom,#PB_Round_Down)) Else SetLocation(PBMap\GeographicCoordinates\Latitude, PBMap\GeographicCoordinates\Longitude, 15) EndIf EndProcedure + Procedure ZoomToTracks(*Tracks.Tracks) + Protected MinY.d, MaxY.d, MinX.d, MaxX.d + If ListSize(*Tracks\Track()) > 0 + With *Tracks\Track() + FirstElement(*Tracks\Track()) + MinX = \Longitude : MaxX = MinX : MinY = \Latitude : MaxY = MinY + ForEach *Tracks\Track() + If \Longitude < MinX + MinX = \Longitude + EndIf + If \Longitude > MaxX + MaxX = \Longitude + EndIf + If \Latitude < MinY + MinY = \Latitude + EndIf + If \Latitude > MaxY + MaxY = \Latitude + EndIf + Next + ZoomToArea(MinY.d, MaxY.d, MinX.d, MaxX.d) + EndWith + EndIf + EndProcedure Procedure SetZoom(Zoom.i, mode.i = #PB_Relative) Select mode Case #PB_Relative @@ -1068,15 +1338,14 @@ Module PBMap Case #PB_Absolute PBMap\Zoom = zoom EndSelect - If PBMap\Zoom > PBMap\ZoomMax : PBMap\Zoom = PBMap\ZoomMax : EndIf - If PBMap\Zoom < PBMap\ZoomMin : PBMap\Zoom = PBMap\ZoomMin : EndIf + 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 + ; 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 - ;First drawing + ; First drawing PBMap\Redraw = #True - ;Drawing() If PBMap\CallBackLocation > 0 CallFunctionFast(PBMap\CallBackLocation, @PBMap\GeographicCoordinates) EndIf @@ -1096,6 +1365,15 @@ Module PBMap ;Drawing() EndProcedure + ; User mode + ; #MODE_DEFAULT = 0 -> "Hand" (move map) and move objects + ; #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 + ;Zoom on x, y position relative to the canvas gadget Procedure SetZoomOnPosition(x, y, zoom) Protected MouseX.d, MouseY.d @@ -1106,8 +1384,8 @@ Module PBMap y - CenterY ;*** First : Zoom PBMap\Zoom + zoom - If PBMap\Zoom > PBMap\ZoomMax : PBMap\Zoom = PBMap\ZoomMax : EndIf - If PBMap\Zoom < PBMap\ZoomMin : PBMap\Zoom = PBMap\ZoomMin : EndIf + 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) If Zoom = 1 PBMap\PixelCoordinates\x + x @@ -1117,9 +1395,9 @@ Module PBMap PBMap\PixelCoordinates\y - y/2 EndIf Pixel2LatLon(@PBMap\PixelCoordinates, @PBMap\GeographicCoordinates, PBMap\Zoom) - ;Start drawing + ; Start drawing PBMap\Redraw = #True - ;If CallBackLocation send Location to function + ; If CallBackLocation send Location To function If PBMap\CallBackLocation > 0 CallFunctionFast(PBMap\CallBackLocation, @PBMap\GeographicCoordinates) EndIf @@ -1135,21 +1413,19 @@ Module PBMap PBMap\PixelCoordinates\x + x PBMap\PixelCoordinates\y + y Pixel2LatLon(@PBMap\PixelCoordinates, @PBMap\GeographicCoordinates, PBMap\Zoom) - ;Start drawing + ; Start drawing PBMap\Redraw = #True - ;If CallBackLocation send Location to function + ; If CallBackLocation send Location to function If PBMap\CallBackLocation > 0 CallFunctionFast(PBMap\CallBackLocation, @PBMap\GeographicCoordinates) EndIf EndProcedure Procedure.d GetLatitude() - ; ProcedureReturn 0-(90-Mod((PBMap\GeographicCoordinates\Latitude+90),180)) ProcedureReturn PBMap\GeographicCoordinates\Latitude EndProcedure Procedure.d GetLongitude() - ; ProcedureReturn 0-(180-Mod((PBMap\GeographicCoordinates\Longitude+180),360)) ProcedureReturn PBMap\GeographicCoordinates\Longitude EndProcedure @@ -1161,11 +1437,74 @@ Module PBMap Procedure CanvasEvents() Protected MouseX.i, MouseY.i - Protected MarkerCoords.Coordinates, *Tile.Tile, MapWidth = Pow(2, PBMap\Zoom) * PBMap\TileSize + Protected MarkerCoords.PixelCoordinates, *Tile.Tile, MapWidth = Pow(2, PBMap\Zoom) * PBMap\TileSize + Protected key.s, Touch.i + Static CtrlKey PBMap\Moving = #False - Select EventType() + Select EventType() + Case #PB_EventType_KeyUp + Select GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_Key) + Case #PB_Shortcut_Delete + DeleteSelectedMarkers() + EndSelect + 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) + 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 - GotoPixelRel(GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_MouseX), GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_MouseY)) + 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 + Touch = #True + SetLocation(PBMap\Markers()\GeographicCoordinates\Latitude, PBMap\Markers()\GeographicCoordinates\Longitude) + Break + EndIf + Next + EndIf + If Not Touch + GotoPixelRel(GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_MouseX), GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_MouseY)) + EndIf Case #PB_EventType_MouseWheel If PBMap\Options\WheelMouseRelative ;Relative zoom (centered on the mouse) @@ -1180,17 +1519,20 @@ Module PBMap 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) - ;Check if we select a marker - ForEach PBMap\Marker() - LatLon2TileXY(@PBMap\Marker()\GeographicCoordinates, @MarkerCoords, 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 - MarkerCoords\x * PBMap\TileSize - MarkerCoords\y * PBMap\TileSize - ;Debug "Pos : " + StrD(Marker\x) + " ; Drawing pos : " + StrD(PBMap\Drawing\TileCoordinates\x) - If Distance(MarkerCoords\x, MarkerCoords\y, MouseX, MouseY) < 8 - PBMap\EditMarkerIndex = ListIndex(PBMap\Marker()) - Break - EndIf - Next + If PBMap\Mode = #MODE_DEFAULT Or PBMap\Mode = #MODE_SELECT + PBMap\EditMarker = #False + ;Check if we select marker(s) + ForEach PBMap\Markers() + If CtrlKey = #False + PBMap\Markers()\Selected = #False ;If no CTRL key, deselect everything and select only the focused marker + EndIf + If PBMap\Markers()\Focus + PBMap\Markers()\Selected = #True + PBMap\EditMarker = #True;ListIndex(PBMap\Markers()) + PBMap\Markers()\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) @@ -1199,18 +1541,21 @@ Module PBMap 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 - ;Move marker - If PBMap\EditMarkerIndex > -1 - SelectElement(PBMap\Marker(), PBMap\EditMarkerIndex) - LatLon2TileXY(@PBMap\Marker()\GeographicCoordinates, @MarkerCoords, PBMap\Zoom) - MarkerCoords\x + MouseX / PBMap\TileSize - MarkerCoords\y + MouseY / PBMap\TileSize - TileXY2LatLon(@MarkerCoords, @PBMap\Marker()\GeographicCoordinates, PBMap\Zoom) - Else - ;New move values + ;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) + MarkerCoords\x + MouseX + MarkerCoords\y + MouseY + Pixel2LatLon(@MarkerCoords, @PBMap\Markers()\GeographicCoordinates, PBMap\Zoom) + EndIf + Next + ElseIf PBMap\Mode = #MODE_DEFAULT Or PBMap\Mode = #MODE_HAND + ;Move map only LatLon2Pixel(@PBMap\GeographicCoordinates, @PBMap\PixelCoordinates, PBMap\Zoom) ;This line could be removed as the coordinates don't have to change but I want to be sure we rely only on geographic coordinates - ;Ensures that pixel position stay in the range [0..2^Zoom*PBMap\TileSize[ coz of the wrapping of the map 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) @@ -1222,18 +1567,30 @@ Module PBMap PBMap\Redraw = #True PBMap\MoveStartingPoint\x = GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_MouseX) PBMap\MoveStartingPoint\y = GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_MouseY) - EndIf - Case #PB_EventType_LeftButtonUp - PBMap\MoveStartingPoint\x = - 1 - If PBMap\EditMarkerIndex > -1 - PBMap\EditMarkerIndex = -1 - Else ;Move Map - ; PBMap\Drawing\TileCoordinates\x = PBMap\PixelCoordinates\x / PBMap\TileSize - ; PBMap\Drawing\TileCoordinates\y = PBMap\PixelCoordinates\y / PBMap\TileSize - ; MyDebug("PBMap\Drawing\TileCoordinates\x " + Str(PBMap\Drawing\TileCoordinates\x) + " ; PBMap\Drawing\TileCoordinates\y " + Str(PBMap\Drawing\TileCoordinates\y) ) - ; TileXY2LatLon(@PBMap\Drawing\TileCoordinates, @PBMap\GeographicCoordinates, PBMap\Zoom) + Else + 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) + ;Check if mouse touch markers + If PBMap\Mode = #MODE_DEFAULT Or PBMap\Mode = #MODE_SELECT + ForEach PBMap\Markers() + LatLon2Pixel(@PBMap\Markers()\GeographicCoordinates, @MarkerCoords, PBMap\Zoom) + If Distance(MarkerCoords\x, MarkerCoords\y, MouseX, MouseY) < 8 + PBMap\Markers()\Focus = #True + Else + ;If CtrlKey = #False + PBMap\Markers()\Focus = #False + ;EndIf + EndIf + Next + EndIf PBMap\Redraw = #True EndIf + Case #PB_EventType_LeftButtonUp + PBMap\MoveStartingPoint\x = - 1 + PBMap\Redraw = #True Case #PB_MAP_REDRAW Debug "Redraw" PBMap\Redraw = #True @@ -1241,13 +1598,14 @@ Module PBMap Debug "Reload" PBMap\Redraw = #True Case #PB_MAP_TILE_CLEANUP - *Tile = EventData() + *Tile = EventData() + key = *Tile\key ;After a Web tile loading thread, clean the tile structure memory and set the image nb in the cache ;avoid to have threads accessing vars (and avoid mutex), see GetImageThread() - Protected timg = PBMap\MemCache\Images(*Tile\key)\Tile\nImage - PBMap\MemCache\Images(*Tile\key)\nImage = timg - FreeMemory(PBMap\MemCache\Images(*Tile\key)\Tile) - PBMap\MemCache\Images(*Tile\key)\Tile = 0 + Protected timg = PBMap\MemCache\Images(key)\Tile\nImage ;Get this new tile image nb + PBMap\MemCache\Images(key)\nImage = timg ;store it in the cache using the key + FreeMemory(PBMap\MemCache\Images(key)\Tile) ;free the data needed for the thread + PBMap\MemCache\Images(key)\Tile = 0 ;clear the data ptr PBMap\Redraw = #True EndSelect EndProcedure @@ -1267,13 +1625,14 @@ Module PBMap CanvasGadget(PBMap\Gadget, X, Y, Width, Height, #PB_Canvas_Keyboard) EndIf BindGadgetEvent(PBMap\Gadget, @CanvasEvents()) - AddWindowTimer(PBMap\Window, PBMap\Timer, 20) + AddWindowTimer(PBMap\Window, PBMap\Timer, PBMap\Options\TimerInterval) BindEvent(#PB_Event_Timer, @TimerEvents()) + ;AddKeyboardShortcut(#PB_Shortcut_Delete EndProcedure EndModule -;-Example +;-**** Example of application **** CompilerIf #PB_Compiler_IsMainFile InitNetwork() @@ -1292,11 +1651,12 @@ CompilerIf #PB_Compiler_IsMainFile #Text_2 #Text_3 #Text_4 - #String_0 - #String_1 + #StringLatitude + #StringLongitude #Gdt_LoadGpx #Gdt_AddMarker #Gdt_AddOpenseaMap + #Gdt_Degrees EndEnumeration Structure Location @@ -1305,21 +1665,30 @@ CompilerIf #PB_Compiler_IsMainFile EndStructure Procedure UpdateLocation(*Location.Location) - SetGadgetText(#String_0, StrD(*Location\Latitude)) - SetGadgetText(#String_1, StrD(*Location\Longitude)) + SetGadgetText(#StringLatitude, StrD(*Location\Latitude)) + SetGadgetText(#StringLongitude, StrD(*Location\Longitude)) ProcedureReturn 0 EndProcedure - Procedure MyMarker(x.i, y.i) - Protected color.l - color=RGBA(0, 255, 0, 255) - VectorSourceColor(color) + ;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):VectorSourceColor(RGBA(0, 0, 0, 255)):StrokePath(1) + 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 MainPointer(x.i, y.i) @@ -1338,12 +1707,13 @@ CompilerIf #PB_Compiler_IsMainFile 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(#String_0,WindowWidth(#Window_0)-100,#PB_Ignore,#PB_Ignore,#PB_Ignore) - ResizeGadget(#String_1,WindowWidth(#Window_0)-100,#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(#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) PBMap::Refresh() EndProcedure @@ -1359,29 +1729,34 @@ CompilerIf #PB_Compiler_IsMainFile ButtonGadget(#Gdt_Up, 580, 070, 30, 30, Chr($25B2)) : SetGadgetFont(#Gdt_Up, FontID(0)) ButtonGadget(#Gdt_Down, 580, 130, 30, 30, Chr($25BC)) : SetGadgetFont(#Gdt_Down, FontID(0)) 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)) + 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(#String_0, 600, 230, 90, 20, "") + StringGadget(#StringLatitude, 600, 230, 90, 20, "") TextGadget(#Text_4, 530, 250, 60, 15, "Longitude : ") - StringGadget(#String_1, 600, 250, 90, 20, "") + StringGadget(#StringLongitude, 600, 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") Define Event.i, Gadget.i, Quit.b = #False Define pfValue.d - Define OpenSeaMap = 0 + Define OpenSeaMap = 0, Degrees = 1 ;Our main gadget PBMap::InitPBMap(#Window_0) + PBMap::SetOption("ShowDegrees", "1") + PBMap::SetOption("ShowDebugInfos", "0") + PBMap::SetOption("ShowScale", "1") + PBMap::SetOption("ShowMarkersLegend", "1") + PBMap::SetOption("TrackShowKms", "1") PBMap::MapGadget(#Map, 10, 10, 512, 512) - PBMap::SetCallBackMainPointer(@MainPointer()) ;To change the Main Pointer - PBMap::SetCallBackLocation(@UpdateLocation()) - PBMap::SetLocation(-36.81148, 175.08634,12) - ;PBMap::SetLocation(0, 0) - PBMAP::SetMapScaleUnit(PBMAP::#SCALE_NAUTICAL) - PBMap::AddMarker(49.0446828398, 2.0349812508, -1, @MyMarker()) + 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 Repeat Event = WaitWindowEvent() @@ -1403,18 +1778,27 @@ CompilerIf #PB_Compiler_IsMainFile Case #Button_5 PBMap::SetZoom( - 1) Case #Gdt_LoadGpx - PBMap::LoadGpxFile(OpenFileRequester("Choose a file to load", "", "*.gpx", 0)) - PBMap::ZoomToArea() ; <-To center the view, and zoom on the tracks + PBMap::LoadGpxFile(OpenFileRequester("Choose a file to load", "", "Gpx|*.gpx", 0)) + Case #StringLatitude, #StringLongitude + Select EventType() + Case #PB_EventType_LostFocus + PBMap::SetLocation(ValD(GetGadgetText(#StringLatitude)), ValD(GetGadgetText(#StringLongitude))) ; Change the PBMap coordinates + PBMAP::Refresh() + EndSelect Case #Gdt_AddMarker - PBMap::AddMarker(ValD(GetGadgetText(#String_0)), ValD(GetGadgetText(#String_1)), RGBA(Random(255), Random(255), Random(255), 255), @MyMarker()) + 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 + OpenSeaMap = PBMap::AddMapServerLayer("OpenSeaMap", 2, "http://t1.openseamap.org/seamark/") ; Add a special osm overlay map on layer nb 2 Else PBMap::DeleteLayer(OpenSeaMap) OpenSeaMap = 0 EndIf PBMAP::Refresh() + Case #Gdt_Degrees + Degrees = 1 - Degrees + PBMap::SetOption("ShowDegrees", Str(Degrees)) + PBMap::Refresh() EndSelect Case #PB_Event_SizeWindow ResizeAll() @@ -1426,8 +1810,9 @@ CompilerIf #PB_Compiler_IsMainFile CompilerEndIf ; IDE Options = PureBasic 5.50 (Windows - x64) -; CursorPosition = 1411 -; Folding = ----------- +; CursorPosition = 11 +; Folding = ------------- ; EnableThread ; EnableXP +; DisableDebugger ; EnableUnicode \ No newline at end of file