Code makeup

This commit is contained in:
djes
2017-03-03 17:23:42 +01:00
parent 528279e85c
commit 8cb400f1a9

655
PBMap.pb
View File

@@ -12,7 +12,7 @@
;******************************************************************** ;********************************************************************
CompilerIf #PB_Compiler_Thread = #False CompilerIf #PB_Compiler_Thread = #False
MessageRequester("Warning !!","You must enable ThreadSafe support in compiler options",#PB_MessageRequester_Ok ) MessageRequester("Warning !", "You must enable ThreadSafe support in compiler options", #PB_MessageRequester_Ok )
End End
CompilerEndIf CompilerEndIf
@@ -22,23 +22,14 @@ InitNetwork()
UsePNGImageDecoder() UsePNGImageDecoder()
UsePNGImageEncoder() UsePNGImageEncoder()
;- Module declaration
DeclareModule PBMap DeclareModule PBMap
;-Show debug infos
Global MyDebugLevel = 0
CompilerIf #PB_Compiler_OS = #PB_OS_Linux CompilerIf #PB_Compiler_OS = #PB_OS_Linux
#Red = 255 #Red = 255
CompilerEndIf CompilerEndIf
Global slash.s
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
slash = "\"
CompilerDefault
slash = "/"
CompilerEndSelect
#SCALE_NAUTICAL = 1 #SCALE_NAUTICAL = 1
#SCALE_KM = 0 #SCALE_KM = 0
@@ -49,7 +40,10 @@ DeclareModule PBMap
#MARKER_EDIT_EVENT = #PB_Event_FirstCustomValue #MARKER_EDIT_EVENT = #PB_Event_FirstCustomValue
;-Declarations #PB_MAP_REDRAW = #PB_EventType_FirstCustomValue + 1
#PB_MAP_RETRY = #PB_EventType_FirstCustomValue + 2
#PB_MAP_TILE_CLEANUP = #PB_EventType_FirstCustomValue + 3
Declare InitPBMap(window) Declare InitPBMap(window)
Declare SetOption(Option.s, Value.s) Declare SetOption(Option.s, Value.s)
Declare LoadOptions(PreferencesFile.s = "PBMap.prefs") Declare LoadOptions(PreferencesFile.s = "PBMap.prefs")
@@ -57,16 +51,24 @@ DeclareModule PBMap
Declare.i AddMapServerLayer(LayerName.s, Order.i, ServerURL.s = "http://tile.openstreetmap.org/", TileSize = 256, ZoomMin = 0, ZoomMax = 18) Declare.i AddMapServerLayer(LayerName.s, Order.i, ServerURL.s = "http://tile.openstreetmap.org/", TileSize = 256, ZoomMin = 0, ZoomMax = 18)
Declare DeleteLayer(Nb.i) Declare DeleteLayer(Nb.i)
Declare BindMapGadget(Gadget.i) Declare BindMapGadget(Gadget.i)
Declare MapGadget(Gadget.i, X.i, Y.i, Width.i, Height.i)
Declare SetLocation(latitude.d, longitude.d, Zoom = -1, mode.i = #PB_Absolute)
Declare Drawing()
Declare SetAngle(Angle.d, Mode = #PB_Absolute)
Declare SetZoom(Zoom.i, mode.i = #PB_Relative)
Declare ZoomToArea(MinY.d, MaxY.d, MinX.d, MaxX.d)
Declare ZoomToTracks(*Tracks)
Declare SetCallBackLocation(*CallBackLocation) Declare SetCallBackLocation(*CallBackLocation)
Declare SetCallBackMainPointer(CallBackMainPointer.i) Declare SetCallBackMainPointer(CallBackMainPointer.i)
Declare MapGadget(Gadget.i, X.i, Y.i, Width.i, Height.i)
Declare.d GetLatitude()
Declare.d GetLongitude()
Declare.d GetMouseLatitude()
Declare.d GetMouseLongitude()
Declare.d GetAngle()
Declare.i GetZoom()
Declare.i GetMode()
Declare SetMode(Mode.i = #MODE_DEFAULT)
Declare SetMapScaleUnit(ScaleUnit=PBMAP::#SCALE_KM) Declare SetMapScaleUnit(ScaleUnit=PBMAP::#SCALE_KM)
Declare SetLocation(latitude.d, longitude.d, Zoom = -1, mode.i = #PB_Absolute)
Declare SetAngle(Angle.d, Mode = #PB_Absolute)
Declare SetZoom(Zoom.i, mode.i = #PB_Relative)
Declare SetZoomToArea(MinY.d, MaxY.d, MinX.d, MaxX.d)
Declare SetZoomToTracks(*Tracks)
Declare NominatimGeoLocationQuery(Address.s, *ReturnPosition= 0) ;Send back the position *ptr.GeographicCoordinates
Declare.i LoadGpxFile(file.s); Declare.i LoadGpxFile(file.s);
Declare ClearTracks() Declare ClearTracks()
Declare DeleteTrack(*Ptr) Declare DeleteTrack(*Ptr)
@@ -76,18 +78,10 @@ DeclareModule PBMap
Declare ClearMarkers() Declare ClearMarkers()
Declare DeleteMarker(*Ptr) Declare DeleteMarker(*Ptr)
Declare DeleteSelectedMarkers() Declare DeleteSelectedMarkers()
Declare Drawing()
Declare Quit() Declare Quit()
Declare Error(msg.s) Declare Error(msg.s)
Declare Refresh() Declare Refresh()
Declare.d GetLatitude()
Declare.d GetLongitude()
Declare.d MouseLatitude()
Declare.d MouseLongitude()
Declare.d GetAngle()
Declare.i GetZoom()
Declare.i GetMode()
Declare SetMode(Mode.i = #MODE_DEFAULT)
Declare NominatimGeoLocationQuery(Address.s, *ReturnPosition= 0) ;Send back the position *ptr.GeographicCoordinates
Declare.i ClearDiskCache() Declare.i ClearDiskCache()
EndDeclareModule EndDeclareModule
@@ -95,6 +89,8 @@ Module PBMap
EnableExplicit EnableExplicit
;-*** Structures
Structure GeographicCoordinates Structure GeographicCoordinates
Longitude.d Longitude.d
Latitude.d Latitude.d
@@ -110,7 +106,6 @@ Module PBMap
y.d y.d
EndStructure EndStructure
;- Tile Structure
Structure Tile Structure Tile
nImage.i nImage.i
key.s key.s
@@ -225,7 +220,7 @@ Module PBMap
StrokeWidth.i StrokeWidth.i
EndStructure EndStructure
;-PBMap Structure ;- PBMap
Structure PBMap Structure PBMap
Window.i ; Parent Window Window.i ; Parent Window
Gadget.i ; Canvas Gadget Id Gadget.i ; Canvas Gadget Id
@@ -267,14 +262,37 @@ Module PBMap
EndStructure EndStructure
#PB_MAP_REDRAW = #PB_EventType_FirstCustomValue + 1 ;-*** Global variables
#PB_MAP_RETRY = #PB_EventType_FirstCustomValue + 2
#PB_MAP_TILE_CLEANUP = #PB_EventType_FirstCustomValue + 3 ;-Show debug infos
Global MyDebugLevel = 0
;-Global variables
Global PBMap.PBMap, Null.i Global PBMap.PBMap, Null.i
Global slash.s
;Shows an error msg and terminates the program CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
Global slash = "\"
CompilerDefault
Global slash = "/"
CompilerEndSelect
;- *** GetText - Translation purpose
;TODO use this for all text
IncludeFile "gettext.pbi"
;-*** Misc tools
Macro Min(a, b)
(Bool((a) <= (b)) * (a) + Bool((b) < (a)) * (b))
EndMacro
Macro Max(a, b)
(Bool((a) >= (b)) * (a) + Bool((b) > (a)) * (b))
EndMacro
;Shows an error msg and terminates the program
Procedure Error(msg.s) Procedure Error(msg.s)
MessageRequester("PBMap", msg, #PB_MessageRequester_Ok) MessageRequester("PBMap", msg, #PB_MessageRequester_Ok)
End End
@@ -288,9 +306,49 @@ Module PBMap
EndIf EndIf
EndProcedure EndProcedure
;- *** GetText - Translation purpose ;(c) ts-soft http://www.purebasic.fr/english/viewtopic.php?f=12&t=58657&hilit=createdirectory&view=unread#unread
;TODO use this for all text CompilerSelect #PB_Compiler_OS
IncludeFile "gettext.pbi" CompilerCase #PB_OS_Windows
#FILE_ATTRIBUTE_DEVICE = 64 ;(0x40)
#FILE_ATTRIBUTE_INTEGRITY_STREAM = 32768 ;(0x8000)
#FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 8192;(0x2000)
#FILE_ATTRIBUTE_NO_SCRUB_DATA = 131072;(0x20000)
#FILE_ATTRIBUTE_VIRTUAL = 65536;(0x10000)
#FILE_ATTRIBUTE_DONTSETFLAGS = ~(#FILE_ATTRIBUTE_DIRECTORY|
#FILE_ATTRIBUTE_SPARSE_FILE|
#FILE_ATTRIBUTE_OFFLINE|
#FILE_ATTRIBUTE_NOT_CONTENT_INDEXED|
#FILE_ATTRIBUTE_VIRTUAL|
0)
Macro SetFileAttributesEx(Name, Attribs)
SetFileAttributes(Name, Attribs & #FILE_ATTRIBUTE_DONTSETFLAGS)
EndMacro
CompilerDefault
Macro SetFileAttributesEx(Name, Attribs)
SetFileAttributes(Name, Attribs)
EndMacro
CompilerEndSelect
Procedure CreateDirectoryEx(DirectoryName.s, FileAttribute = #PB_Default)
Protected i, c, tmp.s
If Right(DirectoryName, 1) = slash
DirectoryName = Left(DirectoryName, Len(DirectoryName) -1)
EndIf
c = CountString(DirectoryName, slash) + 1
For i = 1 To c
tmp + StringField(DirectoryName, i, slash)
If FileSize(tmp) <> -2
CreateDirectory(tmp)
EndIf
tmp + slash
Next
If FileAttribute <> #PB_Default
SetFileAttributesEx(DirectoryName, FileAttribute)
EndIf
If FileSize(DirectoryName) = -2
ProcedureReturn #True
EndIf
EndProcedure
Procedure TechnicalImagesCreation() Procedure TechnicalImagesCreation()
;"Loading" image ;"Loading" image
@@ -329,20 +387,182 @@ Module PBMap
EndIf EndIf
EndProcedure EndProcedure
Procedure.d Distance(x1.d, y1.d, x2.d, y2.d)
Protected Result.d
Result = Sqr( (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))
ProcedureReturn Result
EndProcedure
;*** Converts coords to tile.decimal
;Warning, structures used in parameters are not tested
Procedure LatLon2TileXY(*Location.GeographicCoordinates, *Coords.Coordinates, Zoom)
Protected n.d = Pow(2.0, Zoom)
Protected LatRad.d = Radian(*Location\Latitude)
*Coords\x = n * (Mod( *Location\Longitude + 180.0, 360) / 360.0 )
*Coords\y = n * ( 1.0 - Log(Tan(LatRad) + (1.0/Cos(LatRad))) / #PI ) / 2.0
MyDebug("Latitude : " + StrD(*Location\Latitude) + " ; Longitude : " + StrD(*Location\Longitude), 5)
MyDebug("Coords X : " + Str(*Coords\x) + " ; Y : " + Str(*Coords\y), 5)
EndProcedure
;*** Converts tile.decimal to coords
;Warning, structures used in parameters are not tested
Procedure TileXY2LatLon(*Coords.Coordinates, *Location.GeographicCoordinates, Zoom)
Protected n.d = Pow(2.0, Zoom)
;Ensures the longitude to be in the range [-180;180[
*Location\Longitude = Mod(Mod(*Coords\x / n * 360.0, 360.0) + 360.0, 360.0) - 180
*Location\Latitude = Degree(ATan(SinH(#PI * (1.0 - 2.0 * *Coords\y / n))))
If *Location\Latitude <= -89
*Location\Latitude = -89
EndIf
If *Location\Latitude >= 89
*Location\Latitude = 89
EndIf
EndProcedure
Procedure Pixel2LatLon(*Coords.PixelCoordinates, *Location.GeographicCoordinates, Zoom)
Protected n.d = PBMap\TileSize * Pow(2.0, Zoom)
;Ensures the longitude to be in the range [-180;180[
*Location\Longitude = Mod(Mod(*Coords\x / n * 360.0, 360.0) + 360.0, 360.0) - 180
*Location\Latitude = Degree(ATan(SinH(#PI * (1.0 - 2.0 * *Coords\y / n))))
If *Location\Latitude <= -89
*Location\Latitude = -89
EndIf
If *Location\Latitude >= 89
*Location\Latitude = 89
EndIf
EndProcedure
;Ensures the longitude to be in the range [-180;180[
Procedure.d ClipLongitude(Longitude.d)
ProcedureReturn Mod(Mod(Longitude + 180, 360.0) + 360.0, 360.0) - 180
EndProcedure
;Lat Lon coordinates 2 pixel absolute [0 to 2^Zoom * TileSize [
Procedure LatLon2Pixel(*Location.GeographicCoordinates, *Pixel.PixelCoordinates, Zoom)
Protected tilemax = Pow(2.0, Zoom) * PBMap\TileSize
Protected LatRad.d = Radian(*Location\Latitude)
*Pixel\x = tilemax * (Mod( *Location\Longitude + 180.0, 360) / 360.0 )
*Pixel\y = tilemax * ( 1.0 - Log(Tan(LatRad) + (1.0/Cos(LatRad))) / #PI ) / 2.0
EndProcedure
;Lat Lon coordinates 2 pixel relative to the center of view
Procedure LatLon2PixelRel(*Location.GeographicCoordinates, *Pixel.PixelCoordinates, Zoom)
Protected tilemax = Pow(2.0, Zoom) * PBMap\TileSize
Protected cx.d = PBMap\Drawing\RadiusX
Protected dpx.d = PBMap\PixelCoordinates\x
Protected LatRad.d = Radian(*Location\Latitude)
Protected px.d = tilemax * (Mod( *Location\Longitude + 180.0, 360) / 360.0 )
Protected py.d = tilemax * ( 1.0 - Log(Tan(LatRad) + (1.0/Cos(LatRad))) / #PI ) / 2.0
;check the x boundaries of the map to adjust the position (coz of the longitude wrapping)
If dpx - px >= tilemax / 2
;Debug "c1"
*Pixel\x = cx + (px - dpx + tilemax)
ElseIf px - dpx > tilemax / 2
;Debug "c2"
*Pixel\x = cx + (px - dpx - tilemax)
ElseIf px - dpx < 0
;Debug "c3"
*Pixel\x = cx - (dpx - px)
Else
;Debug "c0"
*Pixel\x = cx + (px - dpx)
EndIf
*Pixel\y = PBMap\Drawing\RadiusY + (py - PBMap\PixelCoordinates\y)
EndProcedure
Procedure.d Pixel2Lon(x)
Protected NewX.d = (PBMap\PixelCoordinates\x - PBMap\Drawing\RadiusX + x) / PBMap\TileSize
Protected n.d = Pow(2.0, PBMap\Zoom)
; double mod is to ensure the longitude to be in the range [-180;180[
ProcedureReturn Mod(Mod(NewX / n * 360.0, 360.0) + 360.0, 360.0) - 180
EndProcedure
Procedure.d Pixel2Lat(y)
Protected NewY.d = (PBMap\PixelCoordinates\y - PBMap\Drawing\RadiusY + y) / PBMap\TileSize
Protected n.d = Pow(2.0, PBMap\Zoom)
ProcedureReturn Degree(ATan(SinH(#PI * (1.0 - 2.0 * NewY / n))))
EndProcedure
; HaversineAlgorithm
; http://andrew.hedges.name/experiments/haversine/
Procedure.d HaversineInKM(*posA.GeographicCoordinates, *posB.GeographicCoordinates)
Protected eQuatorialEarthRadius.d = 6378.1370;6372.795477598;
Protected dlong.d = (*posB\Longitude - *posA\Longitude);
Protected dlat.d = (*posB\Latitude - *posA\Latitude) ;
Protected alpha.d=dlat/2
Protected beta.d=dlong/2
Protected a.d = Sin(Radian(alpha)) * Sin(Radian(alpha)) + Cos(Radian(*posA\Latitude)) * Cos(Radian(*posB\Latitude)) * Sin(Radian(beta)) * Sin(Radian(beta))
Protected c.d = ASin(Min(1,Sqr(a)));
Protected distance.d = 2*eQuatorialEarthRadius * c
ProcedureReturn distance ;
EndProcedure
Procedure.d HaversineInM(*posA.GeographicCoordinates, *posB.GeographicCoordinates)
ProcedureReturn (1000 * HaversineInKM(@*posA,@*posB));
EndProcedure
; No more used, see LatLon2PixelRel
Procedure GetPixelCoordFromLocation(*Location.GeographicCoordinates, *Pixel.PixelCoordinates, Zoom) ; TODO to Optimize
Protected mapWidth.l = Pow(2, Zoom + 8)
Protected mapHeight.l = Pow(2, Zoom + 8)
Protected x1.l,y1.l
x1 = (*Location\Longitude+180)*(mapWidth/360)
; convert from degrees To radians
Protected latRad.d = *Location\Latitude*#PI/180;
Protected mercN.d = Log(Tan((#PI/4)+(latRad/2)));
y1 = (mapHeight/2)-(mapWidth*mercN/(2*#PI)) ;
Protected x2.l, y2.l
x2 = (PBMap\GeographicCoordinates\Longitude+180)*(mapWidth/360)
; convert from degrees To radians
latRad = PBMap\GeographicCoordinates\Latitude*#PI/180;
mercN = Log(Tan((#PI/4)+(latRad/2)))
y2 = (mapHeight/2)-(mapWidth*mercN/(2*#PI));
*Pixel\x=PBMap\Drawing\RadiusX - (x2-x1)
*Pixel\y=PBMap\Drawing\RadiusY - (y2-y1)
EndProcedure
Procedure IsInDrawingPixelBoundaries(*Drawing.DrawingParameters, *Position.GeographicCoordinates)
Protected Pixel.PixelCoordinates
LatLon2PixelRel(*Position, @Pixel, PBMap\Zoom)
If Pixel\x >= 0 And Pixel\y >= 0 And Pixel\x < *Drawing\RadiusX * 2 And Pixel\y < *Drawing\RadiusY * 2
ProcedureReturn #True
Else
ProcedureReturn #False
EndIf
EndProcedure
Procedure IsInDrawingBoundaries(*Drawing.DrawingParameters, *Position.GeographicCoordinates)
Protected Lat.d = *Position\Latitude, Lon.d = *Position\Longitude
Protected LatNW.d = *Drawing\Bounds\NorthWest\Latitude, LonNW.d = *Drawing\Bounds\NorthWest\Longitude
Protected LatSE.d = *Drawing\Bounds\SouthEast\Latitude, LonSE.d = *Drawing\Bounds\SouthEast\Longitude
If Lat >= LatSE And Lat <= LatNW
If *Drawing\Width >= 360
ProcedureReturn #True
Else
If LonNW < LonSE
If Lon >= LonNW And Lon <= LonSE
ProcedureReturn #True
Else
ProcedureReturn #False
EndIf
Else
If (Lon >= -180 And Lon <= LonSE) Or (Lon >= LonNW And Lon <= 180)
ProcedureReturn #True
Else
ProcedureReturn #False
EndIf
EndIf
EndIf
Else
ProcedureReturn #False
EndIf
EndProcedure
;TODO : best cleaning of the string from bad behaviour ;TODO : best cleaning of the string from bad behaviour
Procedure.s StringCheck(String.s) 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)), "@"), "/"), "\"), "$"), "%")) ProcedureReturn Trim(RemoveString(RemoveString(RemoveString(RemoveString(RemoveString(RemoveString(RemoveString(RemoveString(RemoveString(RemoveString(String, Chr(0)), Chr(32)), Chr(39)), Chr(33)), Chr(34)), "@"), "/"), "\"), "$"), "%"))
EndProcedure EndProcedure
Macro SelBool(Name)
Select UCase(Value)
Case "0", "FALSE", "DISABLE"
PBMap\Options\Name = #False
Default
PBMap\Options\Name = #True
EndSelect
EndMacro
Procedure.i ColourString2Value(Value.s) Procedure.i ColourString2Value(Value.s)
;TODO : better string check ;TODO : better string check
Protected Col.s = RemoveString(Value, " ") Protected Col.s = RemoveString(Value, " ")
@@ -364,6 +584,17 @@ Module PBMap
EndIf EndIf
EndProcedure EndProcedure
;-*** Options
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) Procedure SetOption(Option.s, Value.s)
Option = StringCheck(Option) Option = StringCheck(Option)
Select LCase(Option) Select LCase(Option)
@@ -513,6 +744,8 @@ Module PBMap
EndWith EndWith
EndProcedure EndProcedure
;-*** Layers
Procedure.i AddMapServerLayer(LayerName.s, Order.i, ServerURL.s = "http://tile.openstreetmap.org/", TileSize = 256, ZoomMin = 0, ZoomMax = 18) 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 *Ptr = AddElement(PBMap\Layers())
If *Ptr If *Ptr
@@ -532,199 +765,9 @@ Module PBMap
FirstElement(PBMap\Layers()) FirstElement(PBMap\Layers())
SortStructuredList(PBMap\Layers(), #PB_Sort_Ascending, OffsetOf(Layer\Order),TypeOf(Layer\Order)) SortStructuredList(PBMap\Layers(), #PB_Sort_Ascending, OffsetOf(Layer\Order),TypeOf(Layer\Order))
EndProcedure EndProcedure
Procedure Quit()
PBMap\Drawing\End = #True
;Wait for loading threads to finish nicely. Passed 2 seconds, kills them.
Protected TimeCounter = ElapsedMilliseconds()
Repeat
ForEach PBMap\MemCache\Images()
If PBMap\MemCache\Images()\Tile <> 0
If IsThread(PBMap\MemCache\Images()\Tile\GetImageThread)
PBMap\MemCache\Images()\Tile\RetryNb = 0
If ElapsedMilliseconds() - TimeCounter > 2000
;Should not occur
KillThread(PBMap\MemCache\Images()\Tile\GetImageThread)
EndIf
Else
FreeMemory(PBMap\MemCache\Images()\Tile)
PBMap\MemCache\Images()\Tile = 0
EndIf
Else
DeleteMapElement(PBMap\MemCache\Images())
EndIf
Next
Delay(10)
Until MapSize(PBMap\MemCache\Images()) = 0
EndProcedure
Macro Min(a,b)
(Bool((a) <= (b)) * (a) + Bool((b) < (a)) * (b))
EndMacro
Macro Max(a,b)
(Bool((a) >= (b)) * (a) + Bool((b) > (a)) * (b))
EndMacro
Procedure.d Distance(x1.d, y1.d, x2.d, y2.d)
Protected Result.d
Result = Sqr( (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))
ProcedureReturn Result
EndProcedure
;*** Converts coords to tile.decimal
;Warning, structures used in parameters are not tested
Procedure LatLon2TileXY(*Location.GeographicCoordinates, *Coords.Coordinates, Zoom)
Protected n.d = Pow(2.0, Zoom)
Protected LatRad.d = Radian(*Location\Latitude)
*Coords\x = n * (Mod( *Location\Longitude + 180.0, 360) / 360.0 )
*Coords\y = n * ( 1.0 - Log(Tan(LatRad) + (1.0/Cos(LatRad))) / #PI ) / 2.0
MyDebug("Latitude : " + StrD(*Location\Latitude) + " ; Longitude : " + StrD(*Location\Longitude), 5)
MyDebug("Coords X : " + Str(*Coords\x) + " ; Y : " + Str(*Coords\y), 5)
EndProcedure
;*** Converts tile.decimal to coords
;Warning, structures used in parameters are not tested
Procedure TileXY2LatLon(*Coords.Coordinates, *Location.GeographicCoordinates, Zoom)
Protected n.d = Pow(2.0, Zoom)
;Ensures the longitude to be in the range [-180;180[
*Location\Longitude = Mod(Mod(*Coords\x / n * 360.0, 360.0) + 360.0, 360.0) - 180
*Location\Latitude = Degree(ATan(SinH(#PI * (1.0 - 2.0 * *Coords\y / n))))
If *Location\Latitude <= -89
*Location\Latitude = -89
EndIf
If *Location\Latitude >= 89
*Location\Latitude = 89
EndIf
EndProcedure
Procedure Pixel2LatLon(*Coords.PixelCoordinates, *Location.GeographicCoordinates, Zoom)
Protected n.d = PBMap\TileSize * Pow(2.0, Zoom)
;Ensures the longitude to be in the range [-180;180[
*Location\Longitude = Mod(Mod(*Coords\x / n * 360.0, 360.0) + 360.0, 360.0) - 180
*Location\Latitude = Degree(ATan(SinH(#PI * (1.0 - 2.0 * *Coords\y / n))))
If *Location\Latitude <= -89
*Location\Latitude = -89
EndIf
If *Location\Latitude >= 89
*Location\Latitude = 89
EndIf
EndProcedure
;Ensures the longitude to be in the range [-180;180[
Procedure.d ClipLongitude(Longitude.d)
ProcedureReturn Mod(Mod(Longitude + 180, 360.0) + 360.0, 360.0) - 180
EndProcedure
;Lat Lon coordinates 2 pixel absolute [0 to 2^Zoom * TileSize [
Procedure LatLon2Pixel(*Location.GeographicCoordinates, *Pixel.PixelCoordinates, Zoom)
Protected tilemax = Pow(2.0, Zoom) * PBMap\TileSize
Protected LatRad.d = Radian(*Location\Latitude)
*Pixel\x = tilemax * (Mod( *Location\Longitude + 180.0, 360) / 360.0 )
*Pixel\y = tilemax * ( 1.0 - Log(Tan(LatRad) + (1.0/Cos(LatRad))) / #PI ) / 2.0
EndProcedure
;Lat Lon coordinates 2 pixel relative to the center of view
Procedure LatLon2PixelRel(*Location.GeographicCoordinates, *Pixel.PixelCoordinates, Zoom)
Protected tilemax = Pow(2.0, Zoom) * PBMap\TileSize
Protected cx.d = PBMap\Drawing\RadiusX
Protected dpx.d = PBMap\PixelCoordinates\x
Protected LatRad.d = Radian(*Location\Latitude)
Protected px.d = tilemax * (Mod( *Location\Longitude + 180.0, 360) / 360.0 )
Protected py.d = tilemax * ( 1.0 - Log(Tan(LatRad) + (1.0/Cos(LatRad))) / #PI ) / 2.0
;check the x boundaries of the map to adjust the position (coz of the longitude wrapping)
If dpx - px >= tilemax / 2
;Debug "c1"
*Pixel\x = cx + (px - dpx + tilemax)
ElseIf px - dpx > tilemax / 2
;Debug "c2"
*Pixel\x = cx + (px - dpx - tilemax)
ElseIf px - dpx < 0
;Debug "c3"
*Pixel\x = cx - (dpx - px)
Else
;Debug "c0"
*Pixel\x = cx + (px - dpx)
EndIf
*Pixel\y = PBMap\Drawing\RadiusY + (py - PBMap\PixelCoordinates\y)
EndProcedure
; HaversineAlgorithm
; http://andrew.hedges.name/experiments/haversine/
Procedure.d HaversineInKM(*posA.GeographicCoordinates, *posB.GeographicCoordinates)
Protected eQuatorialEarthRadius.d = 6378.1370;6372.795477598;
Protected dlong.d = (*posB\Longitude - *posA\Longitude);
Protected dlat.d = (*posB\Latitude - *posA\Latitude) ;
Protected alpha.d=dlat/2
Protected beta.d=dlong/2
Protected a.d = Sin(Radian(alpha)) * Sin(Radian(alpha)) + Cos(Radian(*posA\Latitude)) * Cos(Radian(*posB\Latitude)) * Sin(Radian(beta)) * Sin(Radian(beta))
Protected c.d = ASin(Min(1,Sqr(a)));
Protected distance.d = 2*eQuatorialEarthRadius * c
ProcedureReturn distance ;
EndProcedure
Procedure.d HaversineInM(*posA.GeographicCoordinates, *posB.GeographicCoordinates)
ProcedureReturn (1000 * HaversineInKM(@*posA,@*posB));
EndProcedure
; No more used, see LatLon2PixelRel
Procedure GetPixelCoordFromLocation(*Location.GeographicCoordinates, *Pixel.PixelCoordinates, Zoom) ; TODO to Optimize
Protected mapWidth.l = Pow(2, Zoom + 8)
Protected mapHeight.l = Pow(2, Zoom + 8)
Protected x1.l,y1.l
x1 = (*Location\Longitude+180)*(mapWidth/360)
; convert from degrees To radians
Protected latRad.d = *Location\Latitude*#PI/180;
Protected mercN.d = Log(Tan((#PI/4)+(latRad/2)));
y1 = (mapHeight/2)-(mapWidth*mercN/(2*#PI)) ;
Protected x2.l, y2.l
x2 = (PBMap\GeographicCoordinates\Longitude+180)*(mapWidth/360)
; convert from degrees To radians
latRad = PBMap\GeographicCoordinates\Latitude*#PI/180;
mercN = Log(Tan((#PI/4)+(latRad/2)))
y2 = (mapHeight/2)-(mapWidth*mercN/(2*#PI));
*Pixel\x=PBMap\Drawing\RadiusX - (x2-x1)
*Pixel\y=PBMap\Drawing\RadiusY - (y2-y1)
EndProcedure
Procedure IsInDrawingPixelBoundaries(*Drawing.DrawingParameters, *Position.GeographicCoordinates)
Protected Pixel.PixelCoordinates
LatLon2PixelRel(*Position, @Pixel, PBMap\Zoom)
If Pixel\x >= 0 And Pixel\y >= 0 And Pixel\x < *Drawing\RadiusX * 2 And Pixel\y < *Drawing\RadiusY * 2
ProcedureReturn #True
Else
ProcedureReturn #False
EndIf
EndProcedure
Procedure IsInDrawingBoundaries(*Drawing.DrawingParameters, *Position.GeographicCoordinates)
Protected Lat.d = *Position\Latitude, Lon.d = *Position\Longitude
Protected LatNW.d = *Drawing\Bounds\NorthWest\Latitude, LonNW.d = *Drawing\Bounds\NorthWest\Longitude
Protected LatSE.d = *Drawing\Bounds\SouthEast\Latitude, LonSE.d = *Drawing\Bounds\SouthEast\Longitude
If Lat >= LatSE And Lat <= LatNW
If *Drawing\Width >= 360
ProcedureReturn #True
Else
If LonNW < LonSE
If Lon >= LonNW And Lon <= LonSE
ProcedureReturn #True
Else
ProcedureReturn #False
EndIf
Else
If (Lon >= -180 And Lon <= LonSE) Or (Lon >= LonNW And Lon <= 180)
ProcedureReturn #True
Else
ProcedureReturn #False
EndIf
EndIf
EndIf
Else
ProcedureReturn #False
EndIf
EndProcedure
;-*** These are threaded ;-*** These are threaded
Procedure.i GetTileFromHDD(CacheFile.s) Procedure.i GetTileFromHDD(CacheFile.s)
Protected nImage.i Protected nImage.i
If FileSize(CacheFile) > 0 If FileSize(CacheFile) > 0
@@ -803,10 +846,10 @@ Module PBMap
Protected img.i = -1 Protected img.i = -1
Protected *timg.ImgMemCach = FindMapElement(PBMap\MemCache\Images(), key) Protected *timg.ImgMemCach = FindMapElement(PBMap\MemCache\Images(), key)
If *timg If *timg
MyDebug("Key : " + key + " found in memory cache!", 3) MyDebug("Key : " + key + " found in memory cache", 3)
img = *timg\nImage img = *timg\nImage
If img <> -1 If img <> -1
MyDebug("Image : " + img + " found in memory cache!", 3) MyDebug("Image : " + img + " found in memory cache", 3)
;*** Cache management ;*** Cache management
; Move the newly used element to the last position of the time stack ; Move the newly used element to the last position of the time stack
SelectElement(PBMap\MemCache\ImagesTimeStack(), *timg\TimeStackPosition) SelectElement(PBMap\MemCache\ImagesTimeStack(), *timg\TimeStackPosition)
@@ -840,7 +883,7 @@ Module PBMap
;MoveElement(PBMap\MemCache\ImagesTimeStack(), #PB_List_Last) ;MoveElement(PBMap\MemCache\ImagesTimeStack(), #PB_List_Last)
PBMap\MemCache\ImagesTimeStack()\MapKey = MapKey(PBMap\MemCache\Images()) PBMap\MemCache\ImagesTimeStack()\MapKey = MapKey(PBMap\MemCache\Images())
;*** ;***
MyDebug("Key : " + key + " added in memory cache!", 3) MyDebug("Key : " + key + " added in memory cache", 3)
*timg = PBMap\MemCache\Images() *timg = PBMap\MemCache\Images()
*timg\nImage = -1 *timg\nImage = -1
EndIf EndIf
@@ -1063,6 +1106,8 @@ Module PBMap
StrokePath(1) StrokePath(1)
EndProcedure EndProcedure
;-*** Tracks
Procedure DrawTrackPointer(x.d, y.d, dist.l) Procedure DrawTrackPointer(x.d, y.d, dist.l)
Protected color.l Protected color.l
color=RGBA(0, 0, 0, 255) color=RGBA(0, 0, 0, 255)
@@ -1237,11 +1282,12 @@ Module PBMap
Wend Wend
EndIf EndIf
Next Next
ZoomToTracks(LastElement(PBMap\TracksList())) ; <-To center the view, and zoom on the tracks SetZoomToTracks(LastElement(PBMap\TracksList())) ; <-To center the view, and zoom on the tracks
ProcedureReturn *NewTrack ProcedureReturn *NewTrack
EndIf EndIf
EndProcedure EndProcedure
;-*** Markers
Procedure ClearMarkers() Procedure ClearMarkers()
ClearList(PBMap\Markers()) ClearList(PBMap\Markers())
@@ -1279,7 +1325,6 @@ Module PBMap
EndIf EndIf
EndProcedure EndProcedure
;-*** Marker Edit
Procedure MarkerIdentifierChange() Procedure MarkerIdentifierChange()
Protected *Marker.Marker = GetGadgetData(EventGadget()) Protected *Marker.Marker = GetGadgetData(EventGadget())
If GetGadgetText(EventGadget()) <> *Marker\Identifier If GetGadgetText(EventGadget()) <> *Marker\Identifier
@@ -1316,7 +1361,6 @@ Module PBMap
SetActiveWindow(*Marker\EditWindow) SetActiveWindow(*Marker\EditWindow)
EndIf EndIf
EndProcedure EndProcedure
;-***
Procedure DrawMarker(x.i, y.i, Nb.i, *Marker.Marker) Procedure DrawMarker(x.i, y.i, Nb.i, *Marker.Marker)
Protected Text.s Protected Text.s
@@ -1388,6 +1432,8 @@ Module PBMap
Next Next
EndProcedure EndProcedure
;-*** Main drawing stuff
Procedure DrawDebugInfos(*Drawing.DrawingParameters) Procedure DrawDebugInfos(*Drawing.DrawingParameters)
; Display how many images in cache ; Display how many images in cache
VectorFont(FontID(PBMap\Font), 16) VectorFont(FontID(PBMap\Font), 16)
@@ -1419,8 +1465,7 @@ Module PBMap
MovePathCursor(GadgetWidth(PBMAP\Gadget) - VectorTextWidth(Text), GadgetHeight(PBMAP\Gadget) - 20) MovePathCursor(GadgetWidth(PBMAP\Gadget) - VectorTextWidth(Text), GadgetHeight(PBMAP\Gadget) - 20)
DrawVectorText(Text) DrawVectorText(Text)
EndProcedure EndProcedure
;-*** Main drawing
Procedure Drawing() Procedure Drawing()
Protected *Drawing.DrawingParameters = @PBMap\Drawing Protected *Drawing.DrawingParameters = @PBMap\Drawing
Protected PixelCenter.PixelCoordinates Protected PixelCenter.PixelCoordinates
@@ -1489,27 +1534,16 @@ Module PBMap
;Drawing() ;Drawing()
EndProcedure EndProcedure
Procedure.d Pixel2Lon(x) ;-*** Misc functions
Protected NewX.d = (PBMap\PixelCoordinates\x - PBMap\Drawing\RadiusX + x) / PBMap\TileSize
Protected n.d = Pow(2.0, PBMap\Zoom) Procedure.d GetMouseLongitude()
; double mod is to ensure the longitude to be in the range [-180;180[
ProcedureReturn Mod(Mod(NewX / n * 360.0, 360.0) + 360.0, 360.0) - 180
EndProcedure
Procedure.d Pixel2Lat(y)
Protected NewY.d = (PBMap\PixelCoordinates\y - PBMap\Drawing\RadiusY + y) / PBMap\TileSize
Protected n.d = Pow(2.0, PBMap\Zoom)
ProcedureReturn Degree(ATan(SinH(#PI * (1.0 - 2.0 * NewY / n))))
EndProcedure
Procedure.d MouseLongitude()
Protected MouseX.d = (PBMap\PixelCoordinates\x - PBMap\Drawing\RadiusX + GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_MouseX)) / PBMap\TileSize Protected MouseX.d = (PBMap\PixelCoordinates\x - PBMap\Drawing\RadiusX + GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_MouseX)) / PBMap\TileSize
Protected n.d = Pow(2.0, PBMap\Zoom) 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 ProcedureReturn Mod(Mod(MouseX / n * 360.0, 360.0) + 360.0, 360.0) - 180
EndProcedure EndProcedure
Procedure.d MouseLatitude() Procedure.d GetMouseLatitude()
Protected MouseY.d = (PBMap\PixelCoordinates\y - PBMap\Drawing\RadiusY + GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_MouseY)) / PBMap\TileSize Protected MouseY.d = (PBMap\PixelCoordinates\y - PBMap\Drawing\RadiusY + GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_MouseY)) / PBMap\TileSize
Protected n.d = Pow(2.0, PBMap\Zoom) Protected n.d = Pow(2.0, PBMap\Zoom)
ProcedureReturn Degree(ATan(SinH(#PI * (1.0 - 2.0 * MouseY / n)))) ProcedureReturn Degree(ATan(SinH(#PI * (1.0 - 2.0 * MouseY / n))))
@@ -1549,7 +1583,7 @@ Module PBMap
EndIf EndIf
EndProcedure EndProcedure
Procedure ZoomToArea(MinY.d, MaxY.d, MinX.d, MaxX.d) Procedure SetZoomToArea(MinY.d, MaxY.d, MinX.d, MaxX.d)
;Source => http://gis.stackexchange.com/questions/19632/how-to-calculate-the-optimal-zoom-level-to-display-two-or-more-points-on-a-map ;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) ;bounding box in long/lat coords (x=long, y=lat)
Protected DeltaX.d = MaxX - MinX ;assumption ! In original code DeltaX have no source Protected DeltaX.d = MaxX - MinX ;assumption ! In original code DeltaX have no source
@@ -1576,7 +1610,7 @@ Module PBMap
EndIf EndIf
EndProcedure EndProcedure
Procedure ZoomToTracks(*Tracks.Tracks) Procedure SetZoomToTracks(*Tracks.Tracks)
Protected MinY.d, MaxY.d, MinX.d, MaxX.d Protected MinY.d, MaxY.d, MinX.d, MaxX.d
If ListSize(*Tracks\Track()) > 0 If ListSize(*Tracks\Track()) > 0
With *Tracks\Track() With *Tracks\Track()
@@ -1596,7 +1630,7 @@ Module PBMap
MaxY = \Latitude MaxY = \Latitude
EndIf EndIf
Next Next
ZoomToArea(MinY.d, MaxY.d, MinX.d, MaxX.d) SetZoomToArea(MinY.d, MaxY.d, MinX.d, MaxX.d)
EndWith EndWith
EndIf EndIf
EndProcedure EndProcedure
@@ -1659,7 +1693,7 @@ Module PBMap
EndProcedure EndProcedure
;Zoom on x, y pixel position from the center ;Zoom on x, y pixel position from the center
Procedure ZoomOnPixel(x, y, zoom) Procedure SetZoomOnPixel(x, y, zoom)
;*** First : Zoom ;*** First : Zoom
PBMap\Zoom + zoom PBMap\Zoom + zoom
If PBMap\Zoom > PBMap\ZoomMax : PBMap\Zoom = PBMap\ZoomMax : ProcedureReturn : EndIf If PBMap\Zoom > PBMap\ZoomMax : PBMap\Zoom = PBMap\ZoomMax : ProcedureReturn : EndIf
@@ -1682,8 +1716,8 @@ Module PBMap
EndProcedure EndProcedure
;Zoom on x, y position relative to the canvas gadget ;Zoom on x, y position relative to the canvas gadget
Procedure ZoomOnPixelRel(x, y, zoom) Procedure SetZoomOnPixelRel(x, y, zoom)
ZoomOnPixel(x - PBMap\Drawing\RadiusX, y - PBMap\Drawing\RadiusY, zoom) SetZoomOnPixel(x - PBMap\Drawing\RadiusX, y - PBMap\Drawing\RadiusY, zoom)
EndProcedure EndProcedure
;Go to x, y position relative to the canvas gadget left up ;Go to x, y position relative to the canvas gadget left up
@@ -1760,57 +1794,13 @@ Module PBMap
*ReturnPosition\Latitude = ValD(lat) *ReturnPosition\Latitude = ValD(lat)
*ReturnPosition\Longitude = ValD(lon) *ReturnPosition\Longitude = ValD(lon)
EndIf EndIf
If lat<> "" And lon <> "" If lat <> "" And lon <> ""
ZoomToArea(bbox\SouthEast\Latitude, bbox\NorthWest\Latitude, bbox\NorthWest\Longitude, bbox\SouthEast\Longitude) SetZoomToArea(bbox\SouthEast\Latitude, bbox\NorthWest\Latitude, bbox\NorthWest\Longitude, bbox\SouthEast\Longitude)
;SetLocation(Position\Latitude, Position\Longitude) ;SetLocation(Position\Latitude, Position\Longitude)
EndIf EndIf
EndIf EndIf
EndProcedure EndProcedure
;(c) ts-soft http://www.purebasic.fr/english/viewtopic.php?f=12&t=58657&hilit=createdirectory&view=unread#unread
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
#FILE_ATTRIBUTE_DEVICE = 64 ;(0x40)
#FILE_ATTRIBUTE_INTEGRITY_STREAM = 32768 ;(0x8000)
#FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 8192;(0x2000)
#FILE_ATTRIBUTE_NO_SCRUB_DATA = 131072;(0x20000)
#FILE_ATTRIBUTE_VIRTUAL = 65536;(0x10000)
#FILE_ATTRIBUTE_DONTSETFLAGS = ~(#FILE_ATTRIBUTE_DIRECTORY|
#FILE_ATTRIBUTE_SPARSE_FILE|
#FILE_ATTRIBUTE_OFFLINE|
#FILE_ATTRIBUTE_NOT_CONTENT_INDEXED|
#FILE_ATTRIBUTE_VIRTUAL|
0)
Macro SetFileAttributesEx(Name, Attribs)
SetFileAttributes(Name, Attribs & #FILE_ATTRIBUTE_DONTSETFLAGS)
EndMacro
CompilerDefault
Macro SetFileAttributesEx(Name, Attribs)
SetFileAttributes(Name, Attribs)
EndMacro
CompilerEndSelect
Procedure CreateDirectoryEx(DirectoryName.s, FileAttribute = #PB_Default)
Protected i, c, tmp.s
If Right(DirectoryName, 1) = slash
DirectoryName = Left(DirectoryName, Len(DirectoryName) -1)
EndIf
c = CountString(DirectoryName, slash) + 1
For i = 1 To c
tmp + StringField(DirectoryName, i, slash)
If FileSize(tmp) <> -2
CreateDirectory(tmp)
EndIf
tmp + slash
Next
If FileAttribute <> #PB_Default
SetFileAttributesEx(DirectoryName, FileAttribute)
EndIf
If FileSize(DirectoryName) = -2
ProcedureReturn #True
EndIf
EndProcedure
Procedure.i ClearDiskCache() Procedure.i ClearDiskCache()
If PBMap\Options\Warning If PBMap\Options\Warning
Protected Result.i = MessageRequester("Warning", "You will clear all cache content in " + PBMap\Options\HDDCachePath + ". Are you sure ?",#PB_MessageRequester_YesNo) Protected Result.i = MessageRequester("Warning", "You will clear all cache content in " + PBMap\Options\HDDCachePath + ". Are you sure ?",#PB_MessageRequester_YesNo)
@@ -1828,6 +1818,8 @@ Module PBMap
EndIf EndIf
EndProcedure EndProcedure
;-*** Main PBMap functions
Procedure CanvasEvents() Procedure CanvasEvents()
Protected CanvasMouseX.d, CanvasMouseY.d, MouseX.d, MouseY.d Protected CanvasMouseX.d, CanvasMouseY.d, MouseX.d, MouseY.d
Protected MarkerCoords.PixelCoordinates, *Tile.Tile, MapWidth = Pow(2, PBMap\Zoom) * PBMap\TileSize Protected MarkerCoords.PixelCoordinates, *Tile.Tile, MapWidth = Pow(2, PBMap\Zoom) * PBMap\TileSize
@@ -1918,7 +1910,7 @@ Module PBMap
Case #PB_EventType_MouseWheel Case #PB_EventType_MouseWheel
If PBMap\Options\WheelMouseRelative If PBMap\Options\WheelMouseRelative
;Relative zoom (centered on the mouse) ;Relative zoom (centered on the mouse)
ZoomOnPixel(CanvasMouseX, CanvasMouseY, GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_WheelDelta)) SetZoomOnPixel(CanvasMouseX, CanvasMouseY, GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_WheelDelta))
Else Else
;Absolute zoom (centered on the center of the map) ;Absolute zoom (centered on the center of the map)
SetZoom(GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_WheelDelta), #PB_Relative) SetZoom(GetGadgetAttribute(PBMap\Gadget, #PB_Canvas_WheelDelta), #PB_Relative)
@@ -2088,6 +2080,31 @@ Module PBMap
BindMapGadget(PBMap\Gadget) BindMapGadget(PBMap\Gadget)
EndProcedure EndProcedure
Procedure Quit()
PBMap\Drawing\End = #True
;Wait for loading threads to finish nicely. Passed 2 seconds, kills them.
Protected TimeCounter = ElapsedMilliseconds()
Repeat
ForEach PBMap\MemCache\Images()
If PBMap\MemCache\Images()\Tile <> 0
If IsThread(PBMap\MemCache\Images()\Tile\GetImageThread)
PBMap\MemCache\Images()\Tile\RetryNb = 0
If ElapsedMilliseconds() - TimeCounter > 2000
;Should not occur
KillThread(PBMap\MemCache\Images()\Tile\GetImageThread)
EndIf
Else
FreeMemory(PBMap\MemCache\Images()\Tile)
PBMap\MemCache\Images()\Tile = 0
EndIf
Else
DeleteMapElement(PBMap\MemCache\Images())
EndIf
Next
Delay(10)
Until MapSize(PBMap\MemCache\Images()) = 0
EndProcedure
Procedure InitPBMap(Window) Procedure InitPBMap(Window)
Protected Result.i Protected Result.i
PBMap\ZoomMin = 0 PBMap\ZoomMin = 0
@@ -2379,8 +2396,8 @@ CompilerEndIf
; IDE Options = PureBasic 5.60 beta 7 (Windows - x64) ; IDE Options = PureBasic 5.60 beta 7 (Windows - x64)
; CursorPosition = 2250 ; CursorPosition = 267
; FirstLine = 2260 ; FirstLine = 1960
; Folding = ----------------- ; Folding = -----------------
; EnableThread ; EnableThread
; EnableXP ; EnableXP