55 Commits

Author SHA1 Message Date
7748dd7154 Improve smoothness by protecting visible tiles 2026-01-14 22:27:33 +01:00
8f046a3855 Bugs on Cluster corrected 2026-01-14 13:33:33 +01:00
9387a58080 Big Update (Bugs / Cluster 2026-01-12 18:31:37 +01:00
djes
a32fd4d093 Merge pull request #20 from djes/thyphoon
Thyphoon desktop centering fixes
2021-09-01 10:09:05 +02:00
djes
873f25d0fe Merge branch 'master' into thyphoon 2021-09-01 10:08:26 +02:00
b108b8b385 DPI Aware
Add compatible with DPI Scaling (4k screen)
2021-08-22 14:48:55 +02:00
djes
7049aa5738 Merge pull request #19 from djes/djes
Demo separated from module
2021-01-17 11:35:17 +01:00
djes
00d7cdceb7 Demo separated from module 2021-01-17 11:30:57 +01:00
djes
878c6a0408 Merge pull request #18 from djes/djes
Faulty PNG tiles fixes
2019-07-19 13:46:13 +02:00
djes
bbd1d75c02 Update PBMap.pb 2019-07-19 13:42:09 +02:00
djes
297fe00f57 PNG checking
Thanks to idle !
2019-07-19 11:15:29 +02:00
djes
10e88b685a pngcheck comment 2019-07-18 22:07:23 +02:00
djes
a909362ee2 Update PBMap.pb 2019-07-18 21:39:34 +02:00
djes
705be8f877 Incomplete image file download automatic deletion
Little update to delete incomplete (eventually malformed) image file
2019-07-18 20:56:33 +02:00
djes
741aa2afb1 Update README.md 2019-07-18 16:39:41 +02:00
djes
86acc0be60 Update README.md 2019-07-18 16:39:22 +02:00
djes
ff6a10feb4 Update README.md 2019-07-18 16:38:22 +02:00
djes
629c469a6b Code cleanup
Misc internal fixes, especially in GetImageThread()
2019-07-18 16:24:12 +02:00
djes
be8f378bbc Merge branch 'djes' of https://github.com/djes/PBMap into djes 2019-07-18 15:18:34 +02:00
djes
55930e68b1 Bug tracking
Some bugs removed and OnError() coded added (thanks to falsam)
Spotted png image library bug, reported on PB forum.
2019-07-18 15:04:43 +02:00
djes
b09559c5ee Pixel2Lon()/Pixel2Lat() correction and GetCanvasPixelLon()/Lat() functions 2018-09-03 14:46:24 +02:00
djes
7b17b7166e UTF8 2018-06-11 23:39:02 +02:00
djes
7970758114 UTF8 source 2018-06-11 23:36:47 +02:00
djes
c13ff4fc92 Merge branch 'djes' of https://github.com/djes/PBMap into djes 2018-06-11 23:24:00 +02:00
djes
864d1e33f5 Optimisation
Little optimisation by Michael Vogel, see https://www.purebasic.fr/english/viewtopic.php?p=523247#p523247
2018-06-11 23:23:48 +02:00
djes
848b817403 Merge pull request #17 from djes/djes
Major update
2018-06-11 23:07:27 +02:00
djes
28c85648ca Merge branch 'master' into djes 2018-06-11 23:06:55 +02:00
djes
55bc5c8f78 Debug mode corrected
Active Window wasn't anymore when console opened
2018-03-17 14:36:44 +01:00
djes
648c9c9a4a Multiple PBMaps WIP
PBMap is now able to handle multiple maps.

Warning : it breaks compatibility with older codes !
InitPBMap() and Quit() are no longer used, only MapGadget() and FreeMapGadget() as in standard PureBASIC gadgets.
All functions should now include the MapGadget id as first parameter.

Now included, the André Beer demo.
2018-03-03 19:26:28 +01:00
djes
1c7b161a87 Multiple PBMaps WIP 2018-03-02 21:55:38 +01:00
djes
12723fab31 Multiple MapGadget bugfix 2018-03-02 19:42:22 +01:00
djes
dfcf0e9f5e Multiple PBMap handling
The internal pbmap structure was unique and shared. Now it is dynamically allocated and returned by the InitPBMap() function. It allows to have multiple PBMap in the same window. Switch is done by the new SelectPBMap() function. Quit() function must be called for each PBMap.
2018-03-01 09:33:52 +01:00
djes
ba26af24e1 GetImageThread() not anymore mutex excluded
Andre and DarkSoul bug tracking. This mutex doesn't seem to have any real utility in this function, as the memory management is already protected by mutex outside, and the tile data has been copied to a private memory area.
2018-02-25 19:32:34 +01:00
djes
a90b44eb6b Two new callbacks to alter tile rendering, and to work on tile file after loading
Prototype.i ProtoDrawTile(x.i, y.i, image.i, alpha.d = 1)
  Prototype.s ProtoModifyTileFile(Filename.s, OriginalURL.s)
2017-07-04 16:50:18 +02:00
djes
afc271278a CallBackDrawTile + misc cleaning + useragent
Allows a customised tile drawing
2017-07-04 12:20:07 +02:00
djes
8300e02bba Merging typhoon and djes branches 2017-07-04 09:21:00 +02:00
djes
a98f658287 Merge branch 'thyphoon' into djes 2017-07-04 09:19:30 +02:00
djes
e87435c892 Cache file delete if size = 0 2017-07-04 08:52:01 +02:00
60647f4928 Change some SetCallBackMarker Fonctionnality
replace CallFunctionFast(PBMap\CallBackMarker,  @PBMap\Markers()\GeographicCoordinates) by               CallFunctionFast(PBMap\CallBackMarker,  @PBMap\Markers()) To use Marker identifier if necessary

move "Marker" and "GeographicCoordinates" from Module to DeclareModule. I need it's public to read easly data send to callback function.
2017-07-03 23:41:25 +02:00
djes
eb8e73a245 Updating from yves86 branch 2017-07-03 12:32:00 +02:00
djes
95d78f0590 Header 2017-06-15 17:21:52 +02:00
djes
596733f49b Header slight modifications 2017-06-15 17:19:59 +02:00
djes
13798f2517 Merge pull request #16 from djes/Yves86
(djes) implemented the new functions by Yves86
2017-06-15 17:13:23 +02:00
djes
0319c8b5a4 Merge pull request #15 from djes/djes
Rewrite of cache mechanism
2017-06-15 16:42:15 +02:00
djes
ff72bc8f07 Merge pull request #14 from djes/djes
Revert "Little tile loading bugfix"
2017-06-06 16:58:14 +02:00
djes
a42058d78e Merge pull request #13 from djes/djes
Layer alpha, save GPX, geoserver support, bugfixes
2017-06-02 13:47:59 +02:00
djes
74b2f52304 Merge pull request #12 from djes/djes
Tile file lifetime management
2017-03-24 17:36:25 +01:00
djes
faf21269dc Merge pull request #11 from djes/djes
Important fix on tile loading.
2017-03-20 17:42:50 +01:00
djes
825be77b4e To correct sync problem 2017-03-01 16:12:58 +01:00
djes
f75f93a46c Merge remote-tracking branch 'refs/remotes/origin/master' into thyphoon
# Conflicts:
#	README.md
2017-03-01 16:09:58 +01:00
djes
1cc8748ddc do not ignore png 2017-03-01 16:04:22 +01:00
djes
657a0f9c5f Merge remote-tracking branch 'refs/remotes/origin/master' into thyphoon
# Conflicts:
#	PBMap.pb
#	screenshot.png
2017-03-01 15:38:17 +01:00
djes
4f8ad1af73 Merge remote-tracking branch 'refs/remotes/origin/master' into thyphoon
# Conflicts:
#	PBMap.pb
2017-03-01 14:29:46 +01:00
5587e1cc11 Add "CleanCache" to SetOption
- Add "CleanCache" to SetOption
- Some minor change to proxy http download
2017-02-28 10:22:26 +01:00
cdd8ba1074 remove curl Dependencies
Use PB command only with Proxy Support
2017-02-21 15:42:29 +01:00
6 changed files with 2928 additions and 1239 deletions

1
.gitignore vendored
View File

@@ -1,2 +1,3 @@
PBMap.pb.bak
*.exe

418
Demo.pb Normal file
View File

@@ -0,0 +1,418 @@
; ********************************************************************
; Program: PBMap example
; Author: djes
; Date: Jan, 2021
; License: PBMap : Free, unrestricted, credit
; appreciated but not required.
; OSM : see http://www.openstreetmap.org/copyright
; Note: Please share improvement !
; Thanks: Progi1984, falsam
; ********************************************************************
;
; Track bugs with the following options with debugger enabled
; PBMap::SetOption(#Map, "ShowDebugInfos", "1")
; PBMap::SetDebugLevel(5)
; PBMap::SetOption(#Map, "Verbose", "1")
;
; or with the OnError() PB capabilities :
;
; CompilerIf #PB_Compiler_LineNumbering = #False
; MessageRequester("Warning !", "You must enable 'OnError lines support' in compiler options", #PB_MessageRequester_Ok )
; End
; CompilerEndIf
;
; Declare ErrorHandler()
;
; OnErrorCall(@ErrorHandler())
;
; Procedure ErrorHandler()
; MessageRequester("Ooops", "The following error happened : " + ErrorMessage(ErrorCode()) + #CRLF$ +"line : " + Str(ErrorLine()))
; EndProcedure
;
; ********************************************************************
XIncludeFile "PBMap.pb"
CompilerIf #PB_Compiler_Thread = #False
MessageRequester("Warning !", "You must enable 'Create ThreadSafe Executable' in compiler options", #PB_MessageRequester_Ok )
End
CompilerEndIf
EnableExplicit
Enumeration
#Window_0
#Map
#Gdt_Left
#Gdt_Right
#Gdt_Up
#Gdt_Down
; #Gdt_RotateLeft
; #Gdt_RotateRight
#Button_4
#Button_5
#Combo_0
#Text_0
#Text_1
#Text_2
#Text_3
#Text_4
#StringLatitude
#StringLongitude
#Gdt_LoadGpx
#Gdt_SaveGpx
#Gdt_AddMarker
#Gdt_AddOpenseaMap
#Gdt_AddHereMap
#Gdt_AddGeoServerMap
#Gdt_Degrees
#Gdt_EditMode
#Gdt_ClearDiskCache
#Gdt_TestClusters
#TextGeoLocationQuery
#StringGeoLocationQuery
EndEnumeration
; Menu events
Enumeration
#MenuEventLonLatStringEnter
#MenuEventGeoLocationStringEnter
EndEnumeration
Structure Location
Longitude.d
Latitude.d
EndStructure
; =============================================================================
; SECTION : Constantes de demo clustering
; OBJECTIF : Centraliser les coordonnees d'Eragny pour le test
; POURQUOI : Faciliter le reglage et la maintenance
; =============================================================================
#ERAGNY_LAT = 49.0176
#ERAGNY_LON = 2.0979
; =============================================================================
; SECTION : Test clustering
; OBJECTIF : Generer un nuage de marqueurs autour d'Eragny
; POURQUOI : Visualiser et valider le clustering
; COMMENT : Distribution simple autour du centre
; =============================================================================
Procedure AddClusterTestMarkers(MapGadget.i)
Protected i.i
Protected Lat.d, Lon.d
PBMap::ClearMarkers(MapGadget)
PBMap::SetOption(MapGadget, "EnableClusters", "1")
PBMap::SetOption(MapGadget, "ClusterPixelSize", "60")
PBMap::SetOption(MapGadget, "ClusterMinCount", "2")
PBMap::SetLocation(MapGadget, #ERAGNY_LAT, #ERAGNY_LON, 13)
For i = 0 To 49
Lat = #ERAGNY_LAT + (Random(100) - 50) / 10000.0
Lon = #ERAGNY_LON + (Random(100) - 50) / 10000.0
PBMap::AddMarker(MapGadget, Lat, Lon, "", "Cluster", RGBA(Random(255), Random(255), Random(255), 255))
Next
PBMap::Refresh(MapGadget)
EndProcedure
Procedure UpdateLocation(*Location.Location)
SetGadgetText(#StringLatitude, StrD(*Location\Latitude))
SetGadgetText(#StringLongitude, StrD(*Location\Longitude))
ProcedureReturn 0
EndProcedure
; This callback demonstration procedure will receive relative coords from canvas
Procedure MyMarker(x.i, y.i, Focus = #False, Selected = #False)
Protected color = RGBA(0, 255, 0, 255)
MovePathCursor(x, y)
AddPathLine(-16,-32,#PB_Path_Relative)
AddPathCircle(16,0,16,180,0,#PB_Path_Relative)
AddPathLine(-16,32,#PB_Path_Relative)
VectorSourceColor(color)
FillPath(#PB_Path_Preserve)
If Focus
VectorSourceColor(RGBA($FF, $FF, 0, $FF))
StrokePath(2)
ElseIf Selected
VectorSourceColor(RGBA($FF, $FF, 0, $FF))
StrokePath(3)
Else
VectorSourceColor(RGBA(0, 0, 0, 255))
StrokePath(1)
EndIf
EndProcedure
Procedure MarkerMoveCallBack(*Marker.PBMap::Marker)
Debug "Identifier : " + *Marker\Identifier + "(" + StrD(*Marker\GeographicCoordinates\Latitude) + ", " + StrD(*Marker\GeographicCoordinates\Longitude) + ")"
EndProcedure
; Example of a custom procedure to alter tile rendering
Procedure DrawTileCallBack(x.i, y.i, image.i, alpha.d)
MovePathCursor(x, y)
DrawVectorImage(ImageID(image), 255 * alpha)
EndProcedure
; Example of a custom procedure to alter tile file just after loading
Procedure.s ModifyTileFileCallback(CacheFile.s, OrgURL.s)
Protected ImgNB = LoadImage(#PB_Any, CacheFile)
If ImgNB
StartDrawing(ImageOutput(ImgNB))
DrawText(0, 0,"PUREBASIC", RGB(255, 255, 0))
StopDrawing()
;*** Could be used to create new files
; Cachefile = ReplaceString(Cachefile, ".png", "_PB.png")
;***
If SaveImage(ImgNB, CacheFile, #PB_ImagePlugin_PNG, 0, 32) ;Warning, the 32 is mandatory as some tiles aren't correctly rendered
; Send back the new name (not functional by now)
ProcedureReturn CacheFile
EndIf
EndIf
EndProcedure
Procedure MainPointer(x.i, y.i)
VectorSourceColor(RGBA(255, 255,255, 255)) : AddPathCircle(x, y,32) : StrokePath(1)
VectorSourceColor(RGBA(0, 0, 0, 255)) : AddPathCircle(x, y, 29):StrokePath(2)
EndProcedure
Procedure ResizeAll()
ResizeGadget(#Map, 10, 10, WindowWidth(#Window_0)-198, WindowHeight(#Window_0)-59)
ResizeGadget(#Text_1, WindowWidth(#Window_0)-170, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Gdt_Left, WindowWidth(#Window_0) - 150, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Gdt_Right, WindowWidth(#Window_0) - 90, #PB_Ignore, #PB_Ignore, #PB_Ignore)
; ResizeGadget(#Gdt_RotateLeft, WindowWidth(#Window_0) - 150, #PB_Ignore, #PB_Ignore, #PB_Ignore)
; ResizeGadget(#Gdt_RotateRight, WindowWidth(#Window_0) - 90, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Gdt_Up, WindowWidth(#Window_0) - 120, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Gdt_Down, WindowWidth(#Window_0) - 120, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Text_2, WindowWidth(#Window_0)-170, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Button_4, WindowWidth(#Window_0)-150, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Button_5, WindowWidth(#Window_0)-100, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Text_3, WindowWidth(#Window_0)-170, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#StringLatitude, WindowWidth(#Window_0)-120, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#StringLongitude, WindowWidth(#Window_0)-120, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Text_4, WindowWidth(#Window_0)-170, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Gdt_AddMarker, WindowWidth(#Window_0)-170, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Gdt_LoadGpx, WindowWidth(#Window_0)-170, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Gdt_SaveGpx, WindowWidth(#Window_0)-170, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Gdt_AddOpenseaMap, WindowWidth(#Window_0)-170, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Gdt_AddHereMap, WindowWidth(#Window_0)-170, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Gdt_AddGeoServerMap, WindowWidth(#Window_0)-170, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Gdt_Degrees, WindowWidth(#Window_0)-170, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Gdt_EditMode, WindowWidth(#Window_0)-170, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Gdt_ClearDiskCache, WindowWidth(#Window_0)-170, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Gdt_TestClusters, 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(#Map)
EndProcedure
;- MAIN TEST
If OpenWindow(#Window_0, 260, 225, 700, 571, "PBMap", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_TitleBar | #PB_Window_ScreenCentered | #PB_Window_SizeGadget)
LoadFont(0, "Arial", 12)
LoadFont(1, "Arial", 12, #PB_Font_Bold)
LoadFont(2, "Arial", 8)
TextGadget(#Text_1, 530, 10, 60, 15, "Movements")
; ButtonGadget(#Gdt_RotateLeft, 550, 070, 30, 30, "LRot") : SetGadgetFont(#Gdt_RotateLeft, FontID(2))
; ButtonGadget(#Gdt_RotateRight, 610, 070, 30, 30, "RRot") : SetGadgetFont(#Gdt_RotateRight, FontID(2))
ButtonGadget(#Gdt_Left, 550, 60, 30, 30, Chr($25C4)) : SetGadgetFont(#Gdt_Left, FontID(0))
ButtonGadget(#Gdt_Right, 610, 60, 30, 30, Chr($25BA)) : SetGadgetFont(#Gdt_Right, FontID(0))
ButtonGadget(#Gdt_Up, 580, 030, 30, 30, Chr($25B2)) : SetGadgetFont(#Gdt_Up, FontID(0))
ButtonGadget(#Gdt_Down, 580, 90, 30, 30, Chr($25BC)) : SetGadgetFont(#Gdt_Down, FontID(0))
TextGadget(#Text_2, 530, 120, 60, 15, "Zoom")
ButtonGadget(#Button_4, 550, 140, 50, 30, " + ") : SetGadgetFont(#Button_4, FontID(1))
ButtonGadget(#Button_5, 600, 140, 50, 30, " - ") : SetGadgetFont(#Button_5, FontID(1))
TextGadget(#Text_3, 530, 190, 50, 15, "Latitude ")
StringGadget(#StringLatitude, 580, 190, 90, 20, "")
TextGadget(#Text_4, 530, 210, 50, 15, "Longitude ")
StringGadget(#StringLongitude, 580, 210, 90, 20, "")
ButtonGadget(#Gdt_AddMarker, 530, 240, 150, 30, "Add Marker")
ButtonGadget(#Gdt_LoadGpx, 530, 270, 150, 30, "Load GPX")
ButtonGadget(#Gdt_SaveGpx, 530, 300, 150, 30, "Save GPX")
ButtonGadget(#Gdt_AddOpenseaMap, 530, 330, 150, 30, "Show/Hide OpenSeaMap", #PB_Button_Toggle)
ButtonGadget(#Gdt_AddHereMap, 530, 360, 150, 30, "Show/Hide HERE Aerial", #PB_Button_Toggle)
ButtonGadget(#Gdt_AddGeoServerMap, 530, 390, 150, 30, "Show/Hide Geoserver layer", #PB_Button_Toggle)
ButtonGadget(#Gdt_Degrees, 530, 420, 150, 30, "Show/Hide Degrees", #PB_Button_Toggle)
ButtonGadget(#Gdt_EditMode, 530, 450, 150, 30, "Edit mode ON/OFF", #PB_Button_Toggle)
ButtonGadget(#Gdt_ClearDiskCache, 530, 480, 150, 30, "Clear disk cache", #PB_Button_Toggle)
ButtonGadget(#Gdt_TestClusters, 530, 510, 150, 30, "Test clusters Eragny")
TextGadget(#TextGeoLocationQuery, 530, 545, 150, 15, "Enter an address")
StringGadget(#StringGeoLocationQuery, 530, 560, 150, 20, "")
SetActiveGadget(#StringGeoLocationQuery)
AddKeyboardShortcut(#Window_0, #PB_Shortcut_Return, #MenuEventGeoLocationStringEnter)
; *** TODO : code to remove when the SetActiveGadget(-1) will be fixed
CompilerIf #PB_Compiler_OS = #PB_OS_Linux
Define Dummy = ButtonGadget(#PB_Any, 0, 0, 1, 1, "Dummy")
HideGadget(Dummy, 1)
CompilerElse
Define Dummy = -1
CompilerEndIf
; ***
Define Event.i, Gadget.i, Quit.b = #False
Define pfValue.d
Define Degrees = 1
Define *Track
Define *PBMap
; Our main gadget
;*PBMap = PBMap::InitPBMap(#Window_0)
PBMap::MapGadget(#Map, 10, 10, 512, 512)
PBMap::SetOption(#Map, "ShowDegrees", "1") : Degrees = 0
PBMap::SetOption(#Map, "ShowDebugInfos", "1")
PBMap::SetDebugLevel(5)
PBMap::SetOption(#Map, "Verbose", "0")
PBMap::SetOption(#Map, "ShowScale", "1")
PBMap::SetOption(#Map, "Warning", "1")
PBMap::SetOption(#Map, "ShowMarkersLegend", "1")
PBMap::SetOption(#Map, "ShowTrackKms", "1")
PBMap::SetOption(#Map, "ColourFocus", "$FFFF00AA")
PBMap::SetCallBackMainPointer(#Map, @MainPointer()) ; To change the main pointer (center of the view)
PBMap::SetCallBackLocation(#Map, @UpdateLocation()) ; To obtain realtime coordinates
PBMap::SetLocation(#Map, -36.81148, 175.08634,12) ; Change the PBMap coordinates
PBMap::SetMapScaleUnit(#Map, PBMAP::#SCALE_KM) ; To change the scale unit
PBMap::AddMarker(#Map, 49.0446828398, 2.0349812508, "", "", -1, @MyMarker()) ; To add a marker with a customised GFX
PBMap::SetCallBackMarker(#Map, @MarkerMoveCallBack())
;PBMap::SetCallBackDrawTile(@DrawTileCallBack())
;PBMap::SetCallBackModifyTileFile(@ModifyTileFileCallback())
Repeat
Event = WaitWindowEvent()
Select Event
Case #PB_Event_CloseWindow : Quit = 1
Case #PB_Event_Gadget ; {
Gadget = EventGadget()
Select Gadget
Case #Gdt_Up
PBMap::SetLocation(#Map, 10* 360 / Pow(2, PBMap::GetZoom(#Map) + 8), 0, 0, #PB_Relative)
Case #Gdt_Down
PBMap::SetLocation(#Map, 10* -360 / Pow(2, PBMap::GetZoom(#Map) + 8), 0, 0, #PB_Relative)
Case #Gdt_Left
PBMap::SetLocation(#Map, 0, 10* -360 / Pow(2, PBMap::GetZoom(#Map) + 8), 0, #PB_Relative)
Case #Gdt_Right
PBMap::SetLocation(#Map, 0, 10* 360 / Pow(2, PBMap::GetZoom(#Map) + 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(#Map, 1)
Case #Button_5
PBMap::SetZoom(#Map, -1)
Case #Gdt_LoadGpx
*Track = PBMap::LoadGpxFile(#Map, OpenFileRequester("Choose a file to load", "", "Gpx|*.gpx", 0))
PBMap::SetTrackColour(#Map, *Track, RGBA(Random(255), Random(255), Random(255), 128))
Case #Gdt_SaveGpx
If *Track
If PBMap::SaveGpxFile(#Map, SaveFileRequester("Choose a filename", "mytrack.gpx", "Gpx|*.gpx", 0), *Track)
MessageRequester("PBMap", "Saving OK !", #PB_MessageRequester_Ok)
Else
MessageRequester("PBMap", "Problem while saving.", #PB_MessageRequester_Ok)
EndIf
Else
MessageRequester("PBMap", "No track to save.", #PB_MessageRequester_Ok)
EndIf
Case #StringLatitude, #StringLongitude
Select EventType()
Case #PB_EventType_Focus
AddKeyboardShortcut(#Window_0, #PB_Shortcut_Return, #MenuEventLonLatStringEnter)
Case #PB_EventType_LostFocus
RemoveKeyboardShortcut(#Window_0, #PB_Shortcut_Return)
EndSelect
Case #Gdt_AddMarker
PBMap::AddMarker(#Map, ValD(GetGadgetText(#StringLatitude)), ValD(GetGadgetText(#StringLongitude)), "", "Test", RGBA(Random(255), Random(255), Random(255), 255))
Case #Gdt_AddOpenseaMap
If PBMap::IsLayer(#Map, "OpenSeaMap")
PBMap::DeleteLayer(#Map, "OpenSeaMap")
SetGadgetState(#Gdt_AddOpenseaMap, 0)
Else
PBMap::AddOSMServerLayer(#Map, "OpenSeaMap", 3, "http://t1.openseamap.org/seamark/") ; Add a special osm overlay map on layer nb 3
SetGadgetState(#Gdt_AddOpenseaMap, 1)
EndIf
PBMap::Refresh(#Map)
Case #Gdt_AddHereMap
If PBMap::IsLayer(#Map, "Here")
PBMap::DeleteLayer(#Map, "Here")
SetGadgetState(#Gdt_AddHereMap, 0)
Else
If PBMap::GetOption(#Map, "appid") <> "" And PBMap::GetOption(#Map, "appcode") <> ""
PBMap::AddHereServerLayer(#Map, "Here", 2) ; Add a "HERE" overlay map on layer nb 2
PBMap::SetLayerAlpha(#Map, "Here", 0.75)
Else
MessageRequester("Info", "Don't forget to register on HERE and change the following line or edit options file")
PBMap::AddHereServerLayer(#Map, "Here", 2, "my_id", "my_code") ; Add a here overlay map on layer nb 2
EndIf
SetGadgetState(#Gdt_AddHereMap, 1)
EndIf
PBMap::Refresh(#Map)
Case #Gdt_AddGeoServerMap
If PBMap::IsLayer(#Map, "GeoServer")
PBMap::DeleteLayer(#Map, "GeoServer")
SetGadgetState(#Gdt_AddGeoServerMap, 0)
Else
PBMap::AddGeoServerLayer(#Map, "GeoServer", 3, "demolayer", "http://localhost:8080/", "geowebcache/service/gmaps", "image/png") ; Add a geoserver overlay map on layer nb 3
PBMap::SetLayerAlpha(#Map, "GeoServer", 0.75)
SetGadgetState(#Gdt_AddGeoServerMap, 1)
EndIf
PBMap::Refresh(#Map)
Case #Gdt_Degrees
Degrees = 1 - Degrees
PBMap::SetOption(#Map, "ShowDegrees", Str(Degrees))
PBMap::Refresh(#Map)
SetGadgetState(#Gdt_Degrees, Degrees)
Case #Gdt_EditMode
If PBMap::GetMode(#Map) <> PBMap::#MODE_EDIT
PBMap::SetMode(#Map, PBMap::#MODE_EDIT)
SetGadgetState(#Gdt_EditMode, 1)
Else
PBMap::SetMode(#Map, PBMap::#MODE_DEFAULT)
SetGadgetState(#Gdt_EditMode, 0)
EndIf
Case #Gdt_ClearDiskCache
PBMap::ClearDiskCache(#Map)
Case #Gdt_TestClusters
AddClusterTestMarkers(#Map)
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(#Map, GetGadgetText(#StringGeoLocationQuery))
PBMap::Refresh(#Map)
EndIf
; *** TODO : code to change when the SetActiveGadget(-1) will be fixed
SetActiveGadget(Dummy)
; ***
Case #MenuEventLonLatStringEnter
PBMap::SetLocation(#Map, ValD(GetGadgetText(#StringLatitude)), ValD(GetGadgetText(#StringLongitude))) ; Change the PBMap coordinates
PBMap::Refresh(#Map)
EndSelect
EndSelect
Until Quit = #True
PBMap::FreeMapGadget(#Map)
EndIf
; IDE Options = PureBasic 6.21 (Windows - x64)
; CursorPosition = 35
; FirstLine = 31
; Folding = --
; EnableThread
; EnableXP

375
Multiple-PBMaps-Demo.pb Normal file
View File

@@ -0,0 +1,375 @@
; Based on the orginal PBMap example (delivered with the package in Feb. 2018), this is an example with
; less functionality, but with 2 different Canvas Map gadgets placed in 2 tabs of a PanelGadget...
; (for testing purposes related to my GeoWorldEditor)
;
; Author: André Beer
; Last change: 26. Feb. 2018
; Modified by djes : 01. March 2018
; Adapted to new PBMap syntax by André: 02. March 2018
;
; ****************************************************************
;
;- Example of application
;
; ****************************************************************
XIncludeFile "PBMap.pb"
CompilerIf #PB_Compiler_Thread = #False
MessageRequester("Warning !", "You must enable 'Create ThreadSafe Executable' in compiler options", #PB_MessageRequester_Ok )
End
CompilerEndIf
EnableExplicit
InitNetwork()
Enumeration
#Window_0
#Map
#Gdt_Left
#Gdt_Right
#Gdt_Up
#Gdt_Down
#Button_4
#Button_5
#Combo_0
#Text_0
#Text_1
#Text_2
#Text_3
#Text_4
#StringLatitude
#StringLongitude
#Gdt_AddMarker
#Gdt_Degrees
#Gdt_ClearDiskCache
#TextGeoLocationQuery
#StringGeoLocationQuery
; Additions for a 2nd panel:
#PanelGadget
#Map2_Canvas
#Map2_Move
#Map2_Left
#Map2_Right
#Map2_Up
#Map2_Down
#Map2_Zoom
#Map2_ZoomIn
#Map2_ZoomOut
#Map2_LatitudeText
#Map2_StringLatitude
#Map2_LongitudeText
#Map2_StringLongitude
EndEnumeration
; Menu events
Enumeration
#MenuEventLonLatStringEnter
#MenuEventGeoLocationStringEnter
EndEnumeration
Structure Location
Longitude.d
Latitude.d
EndStructure
Procedure UpdateLocation(*Location.Location)
SetGadgetText(#StringLatitude, StrD(*Location\Latitude))
SetGadgetText(#StringLongitude, StrD(*Location\Longitude))
ProcedureReturn 0
EndProcedure
; This callback demonstration procedure will receive relative coords from canvas
Procedure MyMarker(x.i, y.i, Focus = #False, Selected = #False)
Protected color = RGBA(0, 255, 0, 255)
MovePathCursor(x, y)
AddPathLine(-16,-32,#PB_Path_Relative)
AddPathCircle(16,0,16,180,0,#PB_Path_Relative)
AddPathLine(-16,32,#PB_Path_Relative)
VectorSourceColor(color)
FillPath(#PB_Path_Preserve)
If Focus
VectorSourceColor(RGBA($FF, $FF, 0, $FF))
StrokePath(2)
ElseIf Selected
VectorSourceColor(RGBA($FF, $FF, 0, $FF))
StrokePath(3)
Else
VectorSourceColor(RGBA(0, 0, 0, 255))
StrokePath(1)
EndIf
EndProcedure
Procedure MarkerMoveCallBack(*Marker.PBMap::Marker)
Debug "Identifier : " + *Marker\Identifier + "(" + StrD(*Marker\GeographicCoordinates\Latitude) + ", " + StrD(*Marker\GeographicCoordinates\Longitude) + ")"
EndProcedure
; Example of a custom procedure to alter tile rendering
Procedure DrawTileCallBack(x.i, y.i, image.i, alpha.d)
MovePathCursor(x, y)
DrawVectorImage(ImageID(image), 255 * alpha)
EndProcedure
; Example of a custom procedure to alter tile file just after loading
Procedure.s ModifyTileFileCallback(CacheFile.s, OrgURL.s)
Protected ImgNB = LoadImage(#PB_Any, CacheFile)
If ImgNB
StartDrawing(ImageOutput(ImgNB))
DrawText(0, 0,"PUREBASIC", RGB(255, 255, 0))
StopDrawing()
;*** Could be used to create new files
; Cachefile = ReplaceString(Cachefile, ".png", "_PB.png")
;***
If SaveImage(ImgNB, CacheFile, #PB_ImagePlugin_PNG, 0, 32) ;Warning, the 32 is mandatory as some tiles aren't correctly rendered
; Send back the new name (not functional by now)
ProcedureReturn CacheFile
EndIf
EndIf
EndProcedure
Procedure MainPointer(x.i, y.i)
VectorSourceColor(RGBA(255, 255,255, 255)) : AddPathCircle(x, y,32) : StrokePath(1)
VectorSourceColor(RGBA(0, 0, 0, 255)) : AddPathCircle(x, y, 29):StrokePath(2)
EndProcedure
Procedure ResizeAll()
Protected PanelTabHeight = GetGadgetAttribute(#PanelGadget, #PB_Panel_TabHeight)
ResizeGadget(#PanelGadget, #PB_Ignore, #PB_Ignore, WindowWidth(#Window_0), WindowHeight(#Window_0)-PanelTabHeight)
Protected PanelItemWidth = GetGadgetAttribute(#PanelGadget, #PB_Panel_ItemWidth)
Protected PanelItemHeight = GetGadgetAttribute(#PanelGadget, #PB_Panel_ItemHeight)
; First tab:
ResizeGadget(#Map, 10, 10, PanelItemWidth-198, PanelItemHeight-59)
ResizeGadget(#Text_1, PanelItemWidth-170, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Gdt_Left, PanelItemWidth-150, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Gdt_Right, PanelItemWidth-90, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Gdt_Up, PanelItemWidth-120, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Gdt_Down, PanelItemWidth-120, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Text_2, PanelItemWidth-170, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Button_4, PanelItemWidth-150, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Button_5, PanelItemWidth-100, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Text_3, PanelItemWidth-170, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#StringLatitude, PanelItemWidth-120, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#StringLongitude, PanelItemWidth-120, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Text_4, PanelItemWidth-170, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Gdt_AddMarker, PanelItemWidth-170, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Gdt_Degrees, PanelItemWidth-170, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Gdt_ClearDiskCache, PanelItemWidth-170, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#TextGeoLocationQuery, PanelItemWidth-170, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#StringGeoLocationQuery, PanelItemWidth-170, #PB_Ignore, #PB_Ignore, #PB_Ignore)
; Second tab:
ResizeGadget(#Map2_Canvas, 10, 10, PanelItemWidth-198, PanelItemHeight-59)
ResizeGadget(#Map2_Move, PanelItemWidth-170, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Map2_Left, PanelItemWidth-150, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Map2_Right, PanelItemWidth-90, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Map2_Up, PanelItemWidth-120, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Map2_Down, PanelItemWidth-120, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Map2_Zoom, PanelItemWidth-170, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Map2_ZoomIn, PanelItemWidth-150, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Map2_ZoomOut, PanelItemWidth-100, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Map2_LatitudeText, PanelItemWidth-170, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Map2_StringLatitude, PanelItemWidth-120, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Map2_LongitudeText, PanelItemWidth-170, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ResizeGadget(#Map2_StringLongitude, PanelItemWidth-120, #PB_Ignore, #PB_Ignore, #PB_Ignore)
; Refresh the PBMap:
PBMap::Refresh(#Map)
PBMap::Refresh(#Map2_Canvas)
EndProcedure
;- MAIN TEST
If OpenWindow(#Window_0, 260, 225, 720, 595, "PBMap", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_TitleBar | #PB_Window_ScreenCentered | #PB_Window_SizeGadget)
; ***
Define Event.i, Gadget.i, Quit.b = #False
Define pfValue.d
Define Degrees = 1
Define *Track
Define a, ActivePanel
LoadFont(0, "Arial", 12)
LoadFont(1, "Arial", 12, #PB_Font_Bold)
LoadFont(2, "Arial", 8)
PanelGadget(#PanelGadget, 0, 0, 720, 595)
AddGadgetItem(#PanelGadget, 0, "Map 1")
TextGadget(#Text_1, 530, 10, 60, 15, "Movements")
ButtonGadget(#Gdt_Left, 550, 60, 30, 30, Chr($25C4)) : SetGadgetFont(#Gdt_Left, FontID(0))
ButtonGadget(#Gdt_Right, 610, 60, 30, 30, Chr($25BA)) : SetGadgetFont(#Gdt_Right, FontID(0))
ButtonGadget(#Gdt_Up, 580, 030, 30, 30, Chr($25B2)) : SetGadgetFont(#Gdt_Up, FontID(0))
ButtonGadget(#Gdt_Down, 580, 90, 30, 30, Chr($25BC)) : SetGadgetFont(#Gdt_Down, FontID(0))
TextGadget(#Text_2, 530, 120, 60, 15, "Zoom")
ButtonGadget(#Button_4, 550, 140, 50, 30, " + ") : SetGadgetFont(#Button_4, FontID(1))
ButtonGadget(#Button_5, 600, 140, 50, 30, " - ") : SetGadgetFont(#Button_5, FontID(1))
TextGadget(#Text_3, 530, 190, 50, 15, "Latitude ")
StringGadget(#StringLatitude, 580, 190, 90, 20, "")
TextGadget(#Text_4, 530, 210, 50, 15, "Longitude ")
StringGadget(#StringLongitude, 580, 210, 90, 20, "")
ButtonGadget(#Gdt_AddMarker, 530, 240, 150, 30, "Add Marker")
ButtonGadget(#Gdt_Degrees, 530, 420, 150, 30, "Show/Hide Degrees", #PB_Button_Toggle)
ButtonGadget(#Gdt_ClearDiskCache, 530, 480, 150, 30, "Clear disk cache", #PB_Button_Toggle)
TextGadget(#TextGeoLocationQuery, 530, 515, 150, 15, "Enter an address")
StringGadget(#StringGeoLocationQuery, 530, 530, 150, 20, "")
SetActiveGadget(#StringGeoLocationQuery)
; Our main gadget
PBMap::MapGadget(#Map, 10, 10, 512, 512, 1, #Window_0)
PBMap::SetOption(#Map, "ShowDegrees", "1") : Degrees = 0
PBMap::SetOption(#Map, "ShowDebugInfos", "1")
PBMap::SetDebugLevel(5)
PBMap::SetOption(#Map, "Verbose", "1")
PBMap::SetOption(#Map, "ShowScale", "1")
PBMap::SetOption(#Map, "Warning", "1")
PBMap::SetOption(#Map, "ShowMarkersLegend", "1")
PBMap::SetOption(#Map, "ShowTrackKms", "1")
PBMap::SetOption(#Map, "ColourFocus", "$FFFF00AA")
PBMap::SetCallBackMainPointer(#Map, @MainPointer()) ; To change the main pointer (center of the view)
PBMap::SetCallBackLocation(#Map, @UpdateLocation()) ; To obtain realtime coordinates
PBMap::SetLocation(#Map, -36.81148, 175.08634,12) ; Change the PBMap coordinates
PBMAP::SetMapScaleUnit(#Map, PBMAP::#SCALE_KM) ; To change the scale unit
PBMap::AddMarker(#Map, 49.0446828398, 2.0349812508, "", "", -1, @MyMarker()) ; To add a marker with a customised GFX
PBMap::SetCallBackMarker(#Map, @MarkerMoveCallBack())
PBMap::SetCallBackDrawTile(#Map, @DrawTileCallBack())
PBMap::SetCallBackModifyTileFile(#Map, @ModifyTileFileCallback())
AddGadgetItem(#PanelGadget, 1, "Map 2")
TextGadget(#Map2_Move, 530, 10, 60, 15, "Movements")
ButtonGadget(#Map2_Left, 550, 60, 30, 30, Chr($25C4)) : SetGadgetFont(#Gdt_Left, FontID(0))
ButtonGadget(#Map2_Right, 610, 60, 30, 30, Chr($25BA)) : SetGadgetFont(#Gdt_Right, FontID(0))
ButtonGadget(#Map2_Up, 580, 030, 30, 30, Chr($25B2)) : SetGadgetFont(#Gdt_Up, FontID(0))
ButtonGadget(#Map2_Down, 580, 90, 30, 30, Chr($25BC)) : SetGadgetFont(#Gdt_Down, FontID(0))
TextGadget(#Map2_Zoom, 530, 120, 60, 15, "Zoom")
ButtonGadget(#Map2_ZoomIn, 550, 140, 50, 30, " + ") : SetGadgetFont(#Button_4, FontID(1))
ButtonGadget(#Map2_ZoomOut, 600, 140, 50, 30, " - ") : SetGadgetFont(#Button_5, FontID(1))
TextGadget(#Map2_LatitudeText, 530, 190, 50, 15, "Latitude ")
StringGadget(#Map2_StringLatitude, 580, 190, 90, 20, "")
TextGadget(#Map2_LongitudeText, 530, 210, 50, 15, "Longitude ")
StringGadget(#Map2_StringLongitude, 580, 210, 90, 20, "")
; Our second map:
PBMap::MapGadget(#Map2_Canvas, 10, 10, 512, 512, 1, #Window_0)
PBMap::SetOption(#Map2_Canvas, "ShowDegrees", "1") : Degrees = 0
PBMap::SetOption(#Map2_Canvas, "ShowDebugInfos", "1")
PBMap::SetDebugLevel(5)
PBMap::SetOption(#Map2_Canvas, "Verbose", "1")
PBMap::SetOption(#Map2_Canvas, "ShowScale", "1")
PBMap::SetOption(#Map2_Canvas, "Warning", "1")
PBMap::SetOption(#Map2_Canvas, "ShowMarkersLegend", "1")
PBMap::SetOption(#Map2_Canvas, "ShowTrackKms", "1")
PBMap::SetOption(#Map2_Canvas, "ColourFocus", "$FFFF00AA")
PBMap::SetCallBackMainPointer(#Map2_Canvas, @MainPointer()) ; To change the main pointer (center of the view)
PBMap::SetCallBackLocation(#Map2_Canvas, @UpdateLocation()) ; To obtain realtime coordinates
PBMap::SetLocation(#Map2_Canvas, 6.81148, 15.08634,12) ; Change the PBMap coordinates
PBMAP::SetMapScaleUnit(#Map2_Canvas, PBMAP::#SCALE_KM) ; To change the scale unit
PBMap::AddMarker(#Map2_Canvas, 49.0446828398, 2.0349812508)
CloseGadgetList()
ActivePanel = 2 ; Set the current active panel (1 = Map1, 2 = Map2)
SetGadgetState(#PanelGadget, 1)
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
Repeat
Event = WaitWindowEvent()
Select Event
Case #PB_Event_CloseWindow : Quit = 1
Case #PB_Event_Gadget ; {
Gadget = EventGadget()
Select Gadget
Case #PanelGadget
Select EventType()
Case #PB_EventType_Change
a = GetGadgetState(#PanelGadget)
If a <> ActivePanel
ActivePanel = a
If ActivePanel = 0
; ....
Else
; ....
EndIf
EndIf
EndSelect
Case #Gdt_Up
PBMap::SetLocation(#Map, 10* 360 / Pow(2, PBMap::GetZoom(#Map) + 8), 0, 0, #PB_Relative)
Case #Map2_Up
PBMap::SetLocation(#Map2_Canvas, 10* 360 / Pow(2, PBMap::GetZoom(#Map2_Canvas) + 8), 0, 0, #PB_Relative)
Case #Gdt_Down
PBMap::SetLocation(#Map, 10* -360 / Pow(2, PBMap::GetZoom(#Map) + 8), 0, 0, #PB_Relative)
Case #Map2_Down
PBMap::SetLocation(#Map2_Canvas, 10* -360 / Pow(2, PBMap::GetZoom(#Map2_Canvas) + 8), 0, 0, #PB_Relative)
Case #Gdt_Left
PBMap::SetLocation(#Map, 0, 10* -360 / Pow(2, PBMap::GetZoom(#Map) + 8), 0, #PB_Relative)
Case #Map2_Left
PBMap::SetLocation(#Map2_Canvas, 0, 10* -360 / Pow(2, PBMap::GetZoom(#Map2_Canvas) + 8), 0, #PB_Relative)
Case #Gdt_Right
PBMap::SetLocation(#Map, 0, 10* 360 / Pow(2, PBMap::GetZoom(#Map) + 8), 0, #PB_Relative)
Case #Map2_Right
PBMap::SetLocation(#Map2_Canvas, 0, 10* 360 / Pow(2, PBMap::GetZoom(#Map2_Canvas) + 8), 0, #PB_Relative)
Case #Button_4
PBMap::SetZoom(#Map, 1)
Case #Map2_ZoomIn
PBMap::SetZoom(#Map2_Canvas, 1)
Case #Button_5
PBMap::SetZoom(#Map, - 1)
Case #Map2_ZoomOut
PBMap::SetZoom(#Map2_Canvas, - 1)
Case #StringLatitude, #StringLongitude, #Map2_StringLatitude, #Map2_StringLongitude
Select EventType()
Case #PB_EventType_Focus
AddKeyboardShortcut(#Window_0, #PB_Shortcut_Return, #MenuEventLonLatStringEnter)
Case #PB_EventType_LostFocus
RemoveKeyboardShortcut(#Window_0, #PB_Shortcut_Return)
EndSelect
Case #Gdt_AddMarker
PBMap::AddMarker(#Map, ValD(GetGadgetText(#StringLatitude)), ValD(GetGadgetText(#StringLongitude)), "", "Test", RGBA(Random(255), Random(255), Random(255), 255))
Case #Gdt_Degrees
Degrees = 1 - Degrees
PBMap::SetOption(#Map, "ShowDegrees", Str(Degrees))
PBMap::Refresh(#Map)
SetGadgetState(#Gdt_Degrees, Degrees)
Case #Gdt_ClearDiskCache
PBMap::ClearDiskCache(#Map)
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(#Map, GetGadgetText(#StringGeoLocationQuery))
PBMap::Refresh(#Map)
EndIf
; *** TODO : code to change when the SetActiveGadget(-1) will be fixed
SetActiveGadget(Dummy)
; ***
Case #MenuEventLonLatStringEnter
PBMap::SetLocation(#Map, ValD(GetGadgetText(#StringLatitude)), ValD(GetGadgetText(#StringLongitude))) ; Change the PBMap coordinates
PBMap::Refresh(#Map)
EndSelect
EndSelect
Until Quit = #True
PBMap::FreeMapGadget(#Map)
PBMap::FreeMapGadget(#Map2_Canvas)
EndIf
; IDE Options = PureBasic 5.73 LTS (Windows - x64)
; CursorPosition = 21
; Folding = --
; EnableThread
; EnableXP
; CompileSourceDirectory

2885
PBMap.pb

File diff suppressed because it is too large Load Diff

461
PBMap_doc_fr.md Normal file
View File

@@ -0,0 +1,461 @@
# PBMap - Documentation FR (usage simple et complet)
Ce document explique comment utiliser `pbmap/PBMap.pb` facilement, avec un demarrage rapide, des exemples et le detail de chaque procedure publique.
## Demarrage rapide
Objectif: afficher une carte, ajouter un marqueur et deplacer la vue.
```purebasic
IncludeFile "pbmap/PBMap.pb"
EnableExplicit
InitNetwork()
UseModule PBMap
Enumeration
#Win
#Map
EndEnumeration
If OpenWindow(#Win, 100, 100, 900, 600, "PBMap demo", #PB_Window_SystemMenu)
#Map = MapGadget(#PB_Any, 0, 0, 900, 600, 1, #Win)
; Options utiles
SetOption(#Map, "ShowScale", "1")
SetOption(#Map, "ShowZoom", "1")
SetOption(#Map, "ShowMarkersLegend", "1")
; Position de depart
SetLocation(#Map, 48.8566, 2.3522, 12)
; Ajout d'un marqueur
AddMarker(#Map, 48.8566, 2.3522, "1", "Paris", RGBA(255, 80, 80, 255))
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
Break
EndSelect
ForEver
EndIf
```
Notes importantes:
- Activez "Create ThreadSafe Executable" dans les options du compilateur.
- Appelez `InitNetwork()` avant les telechargements HTTP.
- Les tuiles sont telechargees automatiquement via HTTP/HTTPS.
## Ce que PBMap permet de faire
- Afficher une carte (tuiles OSM/HERE/GeoServer).
- Gerer des marqueurs (ajout, selection, edition).
- Gerer des traces GPX (chargement, affichage, suppression).
- Changer la vue (zoom, angle, centrage).
- Configurer le cache disque et memoire.
- Ajouter des callbacks pour reagir aux mouvements et aux clics.
- Utiliser un clustering de marqueurs pour une meilleure lisibilite.
## Configuration rapide des options utiles
```purebasic
PBMap::SetOption(#Map, "Verbose", "1")
PBMap::SetOption(#Map, "ShowMarkersLegend", "1")
PBMap::SetOption(#Map, "TileLifetime", "1209600") ; 2 semaines
PBMap::SetOption(#Map, "EnableClusters", "1")
PBMap::SetOption(#Map, "ClusterPixelSize", "60")
PBMap::SetOption(#Map, "ClusterMinCount", "2")
```
## API publique - procedures et exemples
Les exemples supposent l'existence d'une carte `#Map`.
### SetDebugLevel(Level.i)
Definit le niveau de debug (0..5).
```purebasic
PBMap::SetDebugLevel(3)
```
### SetOption(MapGadget.i, Option.s, Value.s)
Change une option via une cle texte.
```purebasic
PBMap::SetOption(#Map, "ShowZoom", "1")
```
### GetOption(MapGadget.i, Option.s)
Lit une option sous forme de chaine.
```purebasic
Debug PBMap::GetOption(#Map, "ShowZoom")
```
### LoadOptions(MapGadget.i, PreferencesFile.s = "PBMap.prefs")
Charge les options depuis un fichier.
```purebasic
PBMap::LoadOptions(#Map, "PBMap.prefs")
```
### SaveOptions(MapGadget.i, PreferencesFile.s = "PBMap.prefs")
Sauvegarde les options.
```purebasic
PBMap::SaveOptions(#Map, "PBMap.prefs")
```
### AddOSMServerLayer(MapGadget.i, LayerName.s, Order.i, ServerURL.s)
Ajoute une couche OSM.
```purebasic
PBMap::AddOSMServerLayer(#Map, "OSM", 1, "https://tile.openstreetmap.org/")
```
### AddHereServerLayer(...)
Ajoute une couche HERE (necessite AppId/AppCode).
```purebasic
PBMap::AddHereServerLayer(#Map, "HERE", 2, "APP_ID", "APP_CODE")
```
### AddGeoServerLayer(...)
Ajoute une couche GeoServer.
```purebasic
PBMap::AddGeoServerLayer(#Map, "WMS", 3, "layer-name", "http://localhost:8080/")
```
### IsLayer(MapGadget.i, Name.s)
Teste si une couche existe.
```purebasic
If PBMap::IsLayer(#Map, "OSM")
Debug "Layer OSM ok"
EndIf
```
### DeleteLayer(MapGadget.i, Name.s)
Supprime une couche.
```purebasic
PBMap::DeleteLayer(#Map, "WMS")
```
### EnableLayer(MapGadget.i, Name.s)
Active une couche.
```purebasic
PBMap::EnableLayer(#Map, "OSM")
```
### DisableLayer(MapGadget.i, Name.s)
Desactive une couche.
```purebasic
PBMap::DisableLayer(#Map, "HERE")
```
### SetLayerAlpha(MapGadget.i, Name.s, Alpha.d)
Change la transparence d'une couche (0..1).
```purebasic
PBMap::SetLayerAlpha(#Map, "WMS", 0.5)
```
### GetLayerAlpha(MapGadget.i, Name.s)
Lit la transparence d'une couche.
```purebasic
Debug PBMap::GetLayerAlpha(#Map, "WMS")
```
### BindMapGadget(MapGadget.i, TimerNB = 1, Window = -1)
Attache PBMap a un Canvas existant.
```purebasic
PBMap::BindMapGadget(#MyCanvas, 1, #Win)
```
### SetCallBackLocation(MapGadget.i, *CallBackLocation)
Callback: appel lors d'un changement de position (lat/lon).
```purebasic
Procedure OnMove(*Pos.PBMap::GeographicCoordinates)
Debug StrD(*Pos\Latitude) + ", " + StrD(*Pos\Longitude)
EndProcedure
PBMap::SetCallBackLocation(#Map, @OnMove())
```
### SetCallBackMainPointer(MapGadget.i, CallBackMainPointer.i)
Callback pour dessiner le pointeur principal.
```purebasic
Procedure DrawPointer(x.i, y.i)
; custom drawing
EndProcedure
PBMap::SetCallBackMainPointer(#Map, @DrawPointer())
```
### SetCallBackDrawTile(MapGadget.i, *CallBackLocation)
Callback pour personnaliser le dessin d'une tuile.
```purebasic
Procedure DrawTile(x.i, y.i, image.i, alpha.d)
; custom drawing
EndProcedure
PBMap::SetCallBackDrawTile(#Map, @DrawTile())
```
### SetCallBackMarker(MapGadget.i, *CallBackLocation)
Callback appele quand un marqueur a ete deplace (selection).
```purebasic
Procedure OnMarkerChange(*Marker.PBMap::Marker)
Debug *Marker\Identifier
EndProcedure
PBMap::SetCallBackMarker(#Map, @OnMarkerChange())
```
### SetCallBackLeftClic(MapGadget.i, *CallBackLocation)
Callback lors d'un clic gauche sur la carte.
```purebasic
Procedure OnLeftClick(*Pos.PBMap::GeographicCoordinates)
Debug StrD(*Pos\Latitude)
EndProcedure
PBMap::SetCallBackLeftClic(#Map, @OnLeftClick())
```
### SetCallBackModifyTileFile(MapGadget.i, *CallBackLocation)
Callback pour modifier un fichier de tuile apres telechargement.
```purebasic
Procedure.s OnTileFile(FileName.s, Url.s)
ProcedureReturn FileName
EndProcedure
PBMap::SetCallBackModifyTileFile(#Map, @OnTileFile())
```
### MapGadget(MapGadget.i, X.i, Y.i, Width.i, Height.i, TimerNB = 1, Window = -1)
Cree un canvas + PBMap.
```purebasic
#Map = PBMap::MapGadget(#PB_Any, 0, 0, 800, 600, 1, #Win)
```
### FreeMapGadget(MapGadget.i)
Libere une carte.
```purebasic
PBMap::FreeMapGadget(#Map)
```
### GetLatitude(MapGadget.i)
Latitude courante.
```purebasic
Debug StrD(PBMap::GetLatitude(#Map))
```
### GetLongitude(MapGadget.i)
Longitude courante.
```purebasic
Debug StrD(PBMap::GetLongitude(#Map))
```
### GetMouseLatitude(MapGadget.i)
Latitude sous la souris.
```purebasic
Debug StrD(PBMap::GetMouseLatitude(#Map))
```
### GetMouseLongitude(MapGadget.i)
Longitude sous la souris.
```purebasic
Debug StrD(PBMap::GetMouseLongitude(#Map))
```
### GetAngle(MapGadget.i)
Angle actuel.
```purebasic
Debug StrD(PBMap::GetAngle(#Map))
```
### GetZoom(MapGadget.i)
Zoom actuel.
```purebasic
Debug PBMap::GetZoom(#Map)
```
### GetMode(MapGadget.i)
Mode utilisateur courant.
```purebasic
Debug PBMap::GetMode(#Map)
```
### SetMode(MapGadget.i, Mode.i = #MODE_DEFAULT)
Definit le mode.
```purebasic
PBMap::SetMode(#Map, PBMap::#MODE_HAND)
```
### SetMapScaleUnit(MapGadget.i, ScaleUnit = PBMap::#SCALE_KM)
Definit l'unite d'echelle.
```purebasic
PBMap::SetMapScaleUnit(#Map, PBMap::#SCALE_NAUTICAL)
```
### SetLocation(MapGadget.i, Latitude.d, Longitude.d, Zoom = -1, Mode.i = #PB_Absolute)
Centre la carte.
```purebasic
PBMap::SetLocation(#Map, 48.8566, 2.3522, 12)
```
### SetAngle(MapGadget.i, Angle.d, Mode = #PB_Absolute)
Change l'angle.
```purebasic
PBMap::SetAngle(#Map, 15.0, #PB_Absolute)
```
### SetZoom(MapGadget.i, Zoom.i, Mode.i = #PB_Relative)
Change le zoom.
```purebasic
PBMap::SetZoom(#Map, 1, #PB_Relative)
```
### SetZoomToArea(MapGadget.i, MinY.d, MaxY.d, MinX.d, MaxX.d)
Zoom sur une zone.
```purebasic
PBMap::SetZoomToArea(#Map, 48.80, 48.90, 2.30, 2.40)
```
### SetZoomToTracks(MapGadget.i, *Tracks)
Zoom automatique sur une trace.
```purebasic
PBMap::SetZoomToTracks(#Map, *Track)
```
### NominatimGeoLocationQuery(MapGadget.i, Address.s, *ReturnPosition = 0)
Geocodage d'une adresse via Nominatim.
```purebasic
Define Pos.PBMap::GeographicCoordinates
PBMap::NominatimGeoLocationQuery(#Map, "Paris", @Pos)
```
### LoadGpxFile(MapGadget.i, FileName.s)
Charge un fichier GPX.
```purebasic
Define *Track = PBMap::LoadGpxFile(#Map, "track.gpx")
```
### SaveGpxFile(MapGadget.i, FileName.s, *Track)
Sauvegarde une trace GPX.
```purebasic
PBMap::SaveGpxFile(#Map, "export.gpx", *Track)
```
### ClearTracks(MapGadget.i)
Supprime toutes les traces.
```purebasic
PBMap::ClearTracks(#Map)
```
### DeleteTrack(MapGadget.i, *Ptr)
Supprime une trace.
```purebasic
PBMap::DeleteTrack(#Map, *Track)
```
### DeleteSelectedTracks(MapGadget.i)
Supprime les traces selectionnees.
```purebasic
PBMap::DeleteSelectedTracks(#Map)
```
### SetTrackColour(MapGadget.i, *Ptr, Colour.i)
Change la couleur d'une trace.
```purebasic
PBMap::SetTrackColour(#Map, *Track, RGBA(0, 200, 0, 200))
```
### AddMarker(MapGadget.i, Latitude.d, Longitude.d, Identifier.s = "", Legend.s = "", Color.l = -1, CallBackPointer.i = -1)
Ajoute un marqueur.
```purebasic
PBMap::AddMarker(#Map, 48.86, 2.35, "A", "Point A", RGBA(255, 80, 80, 255))
```
### ClearMarkers(MapGadget.i)
Supprime tous les marqueurs.
```purebasic
PBMap::ClearMarkers(#Map)
```
### DeleteMarker(MapGadget.i, *Ptr)
Supprime un marqueur.
```purebasic
PBMap::DeleteMarker(#Map, *Marker)
```
### DeleteSelectedMarkers(MapGadget.i)
Supprime les marqueurs selectionnes.
```purebasic
PBMap::DeleteSelectedMarkers(#Map)
```
### Drawing(MapGadget.i)
Force un rendu immediat.
```purebasic
PBMap::Drawing(#Map)
```
### FatalError(MapGadget.i, msg.s)
Affiche une erreur et termine.
```purebasic
PBMap::FatalError(#Map, "Erreur critique")
```
### Error(MapGadget.i, msg.s)
Affiche une erreur simple.
```purebasic
PBMap::Error(#Map, "Erreur")
```
### Refresh(MapGadget.i)
Demande un rafraichissement.
```purebasic
PBMap::Refresh(#Map)
```
### ClearDiskCache(MapGadget.i)
Vide le cache disque.
```purebasic
PBMap::ClearDiskCache(#Map)
```
## Clustering des marqueurs (explication)
Le clustering regroupe les marqueurs proches en un seul cercle.
- `EnableClusters`: active ou non.
- `ClusterPixelSize`: taille de la grille (en pixels).
- `ClusterMinCount`: nombre minimum pour afficher un cluster.
Double-clic sur un cluster: zoom sur le centre du cluster.
## Astuces pratiques
- Activez `Verbose` pour diagnostiquer les chargements de tuiles.
- Utilisez `TileLifetime` pour gerer l'expiration du cache.
- Si vous avez beaucoup de marqueurs, activez le clustering.
- Pour des couches multiples, ajustez `SetLayerAlpha`.
- Si l'interface devient lente, reduisez `MaxThreads` ou `MaxDownloadSlots`.
## Exemple complet (avec clustering)
```purebasic
IncludeFile "pbmap/PBMap.pb"
InitNetwork()
UseModule PBMap
Enumeration
#Win
EndEnumeration
OpenWindow(#Win, 0, 0, 1000, 700, "PBMap clustering", #PB_Window_SystemMenu)
Define MapId = MapGadget(#PB_Any, 0, 0, 1000, 700, 1, #Win)
SetOption(MapId, "EnableClusters", "1")
SetOption(MapId, "ClusterPixelSize", "60")
SetOption(MapId, "ClusterMinCount", "2")
SetLocation(MapId, 48.8566, 2.3522, 10)
AddMarker(MapId, 48.85, 2.34, "1", "A", RGBA(255, 80, 80, 255))
AddMarker(MapId, 48.86, 2.35, "2", "B", RGBA(255, 80, 80, 255))
AddMarker(MapId, 48.87, 2.36, "3", "C", RGBA(255, 80, 80, 255))
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
Break
EndSelect
ForEver
```

View File

@@ -1,20 +1,33 @@
# PBMap
# PBMap 0.98
Open source tiled map software.
To develop tiled map applications in PureBasic.
Module to develop tiled map applications in PureBasic, like like OpenStreetMap(c), Google Maps(c), Here(c), ...
Functional example based on OpenStreetMap(c) services
Based on OpenStreetMap services
OSM copyright : http://www.openstreetmap.org/copyright
This code is free !
Officials forums topics here :
http://www.purebasic.fr/english/viewtopic.php?f=27&t=66320 (english)
http://www.purebasic.fr/french/viewtopic.php?f=3&t=16160 (french)
This code is free, but any user should mention the origin of this code.
Official forums topics :
http://www.purebasic.fr/english/viewtopic.php?f=27\&t=66320 (english)
http://www.purebasic.fr/french/viewtopic.php?f=3\&t=16160 (french)
Contributors :
Thyphoon
djes
Idle
Thanks to :
Progi1984
yves86
André
falsam
Special thanks to Fred and Fantaisie Software's team