LazMapViewer: Remove duplicate distance calculation in TGPSPoint. Had to move some general-purpose geo-math routines to a new units mvGeoMath. Old functions kept in mvEngine, but marked as deprecated.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@9337 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
parent
e545177bc3
commit
93167ada8b
@ -7,8 +7,8 @@ interface
|
||||
uses
|
||||
Classes, SysUtils, LazFileUtils,
|
||||
LCLIntf, Forms, Controls, Graphics, Dialogs, StdCtrls,
|
||||
ExtCtrls, Grids, Buttons, mvMapViewer, mvTypes, mvEngine, Types, mvGpsObj,
|
||||
mvDrawingEngine;
|
||||
ExtCtrls, Grids, Buttons, Types,
|
||||
mvMapViewer, mvTypes, mvGeoMath, mvEngine, mvGpsObj, mvDrawingEngine;
|
||||
|
||||
type
|
||||
{ TMainForm }
|
||||
|
@ -6,9 +6,10 @@ object MainForm: TMainForm
|
||||
Caption = 'Flights - LazMapViewer'
|
||||
ClientHeight = 662
|
||||
ClientWidth = 942
|
||||
ShowHint = True
|
||||
LCLVersion = '3.99.0.0'
|
||||
OnCreate = FormCreate
|
||||
OnDestroy = FormDestroy
|
||||
ShowHint = True
|
||||
object MapView: TMapView
|
||||
Left = 0
|
||||
Height = 662
|
||||
@ -27823,192 +27824,33 @@ object MainForm: TMainForm
|
||||
MapCenter.Longitude = -87.9081388888889
|
||||
MapCenter.Latitude = 41.9769444444444
|
||||
POIImage.Data = {
|
||||
36170000424D36170000000000003600000028000000200000002E0000000100
|
||||
2000000000000017000064000000640000000000000000000000FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000FD560000FC4CFFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000F1110000FEE70000FEE10000
|
||||
EA0CFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000FE9A0000FFFF0000FFFF0000
|
||||
FE8FFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF000000FB3E0000FEFE0000FFFF0000FFFF0000
|
||||
FEFC0000FB35FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF000000DB070000FED70000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FECF0000C004FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF000000FE800000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FD75FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF000000F9290000FEF90000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FEF50000F821FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00000080020000FEC30000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FEB8FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF000000FD660000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FD5CFFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000
|
||||
F5180000FEEF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FEEA0000F213FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000
|
||||
FEAA0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FE9FFFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000FC4C0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FEFE0000FC42FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000EA0C0000FEE10000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FEDB0000E309FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000FE900000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FE86FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000FB350000FEFC0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FEFA0000
|
||||
FA2DFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF000000C0040000FED00000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FEC700008002FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF000000FD770000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FD6CFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF000000F8230000FEF80000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FEF50000F61CFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF000000FECF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FEC8FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF000000FE820000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FD79FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF000000F9270000FEFD0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FEFD0000F822FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF000000FEA70000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FEF70000FEB50000FE810000FD670000FD670000
|
||||
FE810000FEB50000FEF70000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FEA7FFFFFF00FFFFFF00FFFFFF000000
|
||||
FB340000FEFE0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FEFD0000FE920000F213FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF000000F2130000FE920000FEFD0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FEFE0000FB34FFFFFF00FFFFFF000000
|
||||
FEAC0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FEF60000FC4DFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF000000FC4D0000FEF60000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FEACFFFFFF000000F3150000
|
||||
FEFA0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FEFE0000
|
||||
FC54FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000FC540000FEFE0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FEFA0000F3150000FD610000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FEA2FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000FEA20000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FD610000FEA00000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FEFD0000F823FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000F8230000FEFD0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FEA00000FECD0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FEC5FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000FEC50000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FECD0000FEEC0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FE8CFFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000FE8C0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FEEC0000FEFA0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FD72FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000FD720000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FEFA0000FEF70000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FD75FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000FD750000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FEF70000FEE80000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FE95FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000FE950000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FEE80000FEC50000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FED5FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000FED50000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FEC50000FE940000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FB37FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000FB370000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FE940000FC520000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FEC00000
|
||||
8002FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00000080020000FEC00000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FC520000E60A0000
|
||||
FEF20000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FD7EFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000FD7E0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FEF20000E60AFFFFFF000000
|
||||
FE950000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FEFE0000FD7F00008002FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00000080020000FD7F0000FEFE0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FE95FFFFFF00FFFFFF000000
|
||||
F8200000FEF80000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FEC30000FB3DFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF000000FB3D0000FEC30000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FEF80000F820FFFFFF00FFFFFF00FFFF
|
||||
FF000000FE830000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FEDB0000FE9C0000FD7E0000FD7E0000
|
||||
FE9C0000FEDB0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FE83FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF000000DB070000FECC0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FECC0000DB07FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF000000F71F0000FEE40000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FEE40000F71FFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF000000FA2B0000FEE50000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FEE50000FA2BFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF000000F8210000FECD0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FECE0000F821FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000DB070000FE850000FEF90000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FEF90000FE850000
|
||||
DB07FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000F8230000
|
||||
FE990000FEF30000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FEF30000FE990000F823FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF000000EA0C0000FD570000FE980000FEC70000FEEB0000FEF90000FEF90000
|
||||
FEEB0000FEC70000FE980000FD570000EA0CFFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00
|
||||
4503000089504E470D0A1A0A0000000D49484452000000200000002E08060000
|
||||
0049701B840000030C49444154789CB5983B68145114867F4410C54644B0107C
|
||||
152262A7A4D2C2DA3422DAD8D868631510B1D1688855409104A2088634819056
|
||||
B00C488845626C82C55662A29204C40DC96ED66CD6F38F77976B76E6DCC7CC14
|
||||
077667CEF9FFEF3EE6CC03AD560B3EB1021C6C023777805189598955892D13AB
|
||||
E6D8287398EBABEB4CA803A745F895C47A92EE11CC650D6BA3012AC03E1119E4
|
||||
087D8D5340383B83D40A0210F29352381F6B9C02F2899A5E000DE09C142C1765
|
||||
6E412C535B05A801C72571A968730B62891EA90066CDE7CA32B720E6EC3DD101
|
||||
901303012215893772C93D62F0378F05D40FFC07201BE4841CAC7B147EF8035C
|
||||
CADAD13CC71C0F9D3A3D3B007260C451B023237DDC0FEC715DD7CC612E6B1C9A
|
||||
2309C077E080FCA96AC99C66DFCED68EA44607A8D21BDBC03547E2B4CFC8D366
|
||||
82B59A36BD39FDC35A92AC6B4FA8B9B5277A1C831B26C08C92B0186B6E5D5D8B
|
||||
8AFE0C137EBA364A4E80CC0D4E6F26D494CD773F2F40A2910D5023404301E82B
|
||||
00A04F016810604D49182A60098614FD3568B7DD6483E607D036F93C13C69484
|
||||
A6CF534D5698A7A9A6A23FC635BAEDB856C7738C7E5CD3A637D68123DA46644F
|
||||
978E753DD49C35DAFD809EF46E934E39666153047B03CC7B59E3D09C6AFDFB97
|
||||
B4CC0B1E77AFA6C4CB2A7038CB98E798A3AD7B7B56E9D90130B330A115D9CD43
|
||||
E29DC41359C3BB0CFE36C7329BDA2E8D89B66F07600B38E3222F22CC9575AA0B
|
||||
C0CCC2D3B20164C61EDA9E5DEB28100B258EFEE36EBF2E00D33C9CCF8711E61B
|
||||
9BC0312780B9813C2861EAEFA579A5024C037B85F87381A39FCD7AAC4B0530BD
|
||||
E1A2146E1760DE9057B2F3593E99006643BE2800E099E6A102F04383087CCD61
|
||||
5EF906EC8F06307DFD6AA4396F62575CFA4E00B3149311006F7DB4BD003680A3
|
||||
22F82BC07C45BB69050398DE7027E09ABFE5ABEB0D605EB57CDE7CDFFB6A0601
|
||||
30E48E7956FB68C5769BF52DA81000B321FB95A90F7E910906309F72BEA48C7E
|
||||
812DBC740086B4E9CBF6231C5B365B778C561480598AD716C0F3589D6880DFC0
|
||||
2131FEC1561DF26DB83000866CBA1B49ABCEA1F117D2B9A057721AC774000000
|
||||
0049454E44AE426082
|
||||
}
|
||||
POIImages = ilPOIs
|
||||
POIImagesWidth = 32
|
||||
@ -28031,8 +27873,8 @@ object MainForm: TMainForm
|
||||
TabOrder = 1
|
||||
object PgData: TTabSheet
|
||||
Caption = 'Tracking'
|
||||
ClientHeight = 627
|
||||
ClientWidth = 312
|
||||
ClientHeight = 634
|
||||
ClientWidth = 310
|
||||
object ZoomTrackBar: TTrackBar
|
||||
AnchorSideLeft.Control = PgData
|
||||
AnchorSideTop.Control = LblZoom
|
||||
@ -28041,12 +27883,12 @@ object MainForm: TMainForm
|
||||
AnchorSideRight.Side = asrBottom
|
||||
Left = 2
|
||||
Height = 40
|
||||
Top = 23
|
||||
Width = 308
|
||||
Top = 21
|
||||
Width = 306
|
||||
Min = 1
|
||||
OnChange = ZoomTrackBarChange
|
||||
Position = 4
|
||||
TickMarks = tmBoth
|
||||
OnChange = ZoomTrackBarChange
|
||||
Anchors = [akTop, akLeft, akRight]
|
||||
BorderSpacing.Left = 2
|
||||
BorderSpacing.Right = 2
|
||||
@ -28056,9 +27898,9 @@ object MainForm: TMainForm
|
||||
AnchorSideLeft.Control = PgData
|
||||
AnchorSideTop.Control = PgData
|
||||
Left = 6
|
||||
Height = 17
|
||||
Height = 15
|
||||
Top = 6
|
||||
Width = 43
|
||||
Width = 35
|
||||
BorderSpacing.Left = 6
|
||||
BorderSpacing.Top = 6
|
||||
Caption = 'Zoom:'
|
||||
@ -28071,9 +27913,9 @@ object MainForm: TMainForm
|
||||
AnchorSideRight.Control = PgData
|
||||
AnchorSideRight.Side = asrBottom
|
||||
Left = 6
|
||||
Height = 73
|
||||
Top = 71
|
||||
Width = 300
|
||||
Height = 70
|
||||
Top = 69
|
||||
Width = 298
|
||||
Anchors = [akTop, akLeft, akRight]
|
||||
AutoSize = True
|
||||
BorderSpacing.Left = 6
|
||||
@ -28081,17 +27923,17 @@ object MainForm: TMainForm
|
||||
BorderSpacing.Right = 6
|
||||
BorderSpacing.InnerBorder = 4
|
||||
Caption = 'Mouse position'
|
||||
ClientHeight = 54
|
||||
ClientWidth = 296
|
||||
ClientHeight = 50
|
||||
ClientWidth = 294
|
||||
TabOrder = 1
|
||||
object lblMouseLon: TLabel
|
||||
AnchorSideLeft.Control = gbMouse
|
||||
AnchorSideTop.Control = lblMouseLat
|
||||
AnchorSideTop.Side = asrBottom
|
||||
Left = 8
|
||||
Height = 17
|
||||
Top = 29
|
||||
Width = 68
|
||||
Height = 15
|
||||
Top = 27
|
||||
Width = 54
|
||||
BorderSpacing.Left = 8
|
||||
BorderSpacing.Top = 4
|
||||
Caption = 'Longitude'
|
||||
@ -28101,9 +27943,9 @@ object MainForm: TMainForm
|
||||
AnchorSideLeft.Control = gbMouse
|
||||
AnchorSideTop.Control = gbMouse
|
||||
Left = 8
|
||||
Height = 17
|
||||
Height = 15
|
||||
Top = 4
|
||||
Width = 57
|
||||
Width = 43
|
||||
BorderSpacing.Left = 8
|
||||
BorderSpacing.Top = 4
|
||||
BorderSpacing.Bottom = 8
|
||||
@ -28116,10 +27958,10 @@ object MainForm: TMainForm
|
||||
AnchorSideTop.Side = asrBottom
|
||||
AnchorSideRight.Control = gbMouse
|
||||
AnchorSideRight.Side = asrBottom
|
||||
Left = 235
|
||||
Height = 17
|
||||
Top = 29
|
||||
Width = 45
|
||||
Left = 244
|
||||
Height = 15
|
||||
Top = 27
|
||||
Width = 34
|
||||
Alignment = taRightJustify
|
||||
Anchors = [akTop, akRight]
|
||||
BorderSpacing.Top = 4
|
||||
@ -28132,10 +27974,10 @@ object MainForm: TMainForm
|
||||
AnchorSideTop.Control = gbMouse
|
||||
AnchorSideRight.Control = gbMouse
|
||||
AnchorSideRight.Side = asrBottom
|
||||
Left = 235
|
||||
Height = 17
|
||||
Left = 244
|
||||
Height = 15
|
||||
Top = 4
|
||||
Width = 45
|
||||
Width = 34
|
||||
Alignment = taRightJustify
|
||||
Anchors = [akTop, akRight]
|
||||
BorderSpacing.Top = 4
|
||||
@ -28152,25 +27994,25 @@ object MainForm: TMainForm
|
||||
AnchorSideRight.Control = gbMouse
|
||||
AnchorSideRight.Side = asrBottom
|
||||
Left = 6
|
||||
Height = 73
|
||||
Top = 152
|
||||
Width = 300
|
||||
Height = 70
|
||||
Top = 147
|
||||
Width = 298
|
||||
Anchors = [akTop, akLeft, akRight]
|
||||
AutoSize = True
|
||||
BorderSpacing.Top = 8
|
||||
BorderSpacing.InnerBorder = 4
|
||||
Caption = 'Center'
|
||||
ClientHeight = 54
|
||||
ClientWidth = 296
|
||||
ClientHeight = 50
|
||||
ClientWidth = 294
|
||||
TabOrder = 2
|
||||
object lblCenterLon: TLabel
|
||||
AnchorSideLeft.Control = gbCenter
|
||||
AnchorSideTop.Control = lblCenterLat
|
||||
AnchorSideTop.Side = asrBottom
|
||||
Left = 8
|
||||
Height = 17
|
||||
Top = 29
|
||||
Width = 68
|
||||
Height = 15
|
||||
Top = 27
|
||||
Width = 54
|
||||
BorderSpacing.Left = 8
|
||||
BorderSpacing.Top = 4
|
||||
Caption = 'Longitude'
|
||||
@ -28180,9 +28022,9 @@ object MainForm: TMainForm
|
||||
AnchorSideLeft.Control = gbCenter
|
||||
AnchorSideTop.Control = gbCenter
|
||||
Left = 8
|
||||
Height = 17
|
||||
Height = 15
|
||||
Top = 4
|
||||
Width = 57
|
||||
Width = 43
|
||||
BorderSpacing.Left = 8
|
||||
BorderSpacing.Top = 4
|
||||
BorderSpacing.Bottom = 8
|
||||
@ -28195,10 +28037,10 @@ object MainForm: TMainForm
|
||||
AnchorSideTop.Side = asrBottom
|
||||
AnchorSideRight.Control = gbCenter
|
||||
AnchorSideRight.Side = asrBottom
|
||||
Left = 235
|
||||
Height = 17
|
||||
Top = 29
|
||||
Width = 45
|
||||
Left = 244
|
||||
Height = 15
|
||||
Top = 27
|
||||
Width = 34
|
||||
Alignment = taRightJustify
|
||||
Anchors = [akTop, akRight]
|
||||
BorderSpacing.Top = 4
|
||||
@ -28211,10 +28053,10 @@ object MainForm: TMainForm
|
||||
AnchorSideTop.Control = gbCenter
|
||||
AnchorSideRight.Control = gbCenter
|
||||
AnchorSideRight.Side = asrBottom
|
||||
Left = 235
|
||||
Height = 17
|
||||
Left = 244
|
||||
Height = 15
|
||||
Top = 4
|
||||
Width = 45
|
||||
Width = 34
|
||||
Alignment = taRightJustify
|
||||
Anchors = [akTop, akRight]
|
||||
BorderSpacing.Top = 4
|
||||
@ -28230,9 +28072,9 @@ object MainForm: TMainForm
|
||||
AnchorSideRight.Side = asrBottom
|
||||
AnchorSideBottom.Control = plInfo
|
||||
Left = 6
|
||||
Height = 231
|
||||
Top = 233
|
||||
Width = 298
|
||||
Height = 246
|
||||
Top = 225
|
||||
Width = 296
|
||||
Anchors = [akTop, akLeft, akRight, akBottom]
|
||||
AutoFillColumns = True
|
||||
BorderSpacing.Top = 8
|
||||
@ -28248,12 +28090,12 @@ object MainForm: TMainForm
|
||||
item
|
||||
Title.Alignment = taCenter
|
||||
Title.Caption = 'Latitude'
|
||||
Width = 105
|
||||
Width = 111
|
||||
end
|
||||
item
|
||||
Title.Alignment = taCenter
|
||||
Title.Caption = 'Longitude'
|
||||
Width = 106
|
||||
Width = 111
|
||||
end>
|
||||
FixedCols = 0
|
||||
Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRangeSelect, goRowSelect, goSmoothScroll]
|
||||
@ -28262,8 +28104,8 @@ object MainForm: TMainForm
|
||||
OnDblClick = sgTracksDblClick
|
||||
ColWidths = (
|
||||
70
|
||||
105
|
||||
106
|
||||
111
|
||||
111
|
||||
)
|
||||
end
|
||||
object pnlFlightControl: TPanel
|
||||
@ -28274,8 +28116,8 @@ object MainForm: TMainForm
|
||||
AnchorSideBottom.Side = asrBottom
|
||||
Left = 0
|
||||
Height = 50
|
||||
Top = 577
|
||||
Width = 312
|
||||
Top = 584
|
||||
Width = 310
|
||||
Anchors = [akLeft, akRight, akBottom]
|
||||
BevelOuter = bvNone
|
||||
ChildSizing.LeftRightSpacing = 5
|
||||
@ -28288,13 +28130,13 @@ object MainForm: TMainForm
|
||||
ChildSizing.Layout = cclLeftToRightThenTopToBottom
|
||||
ChildSizing.ControlsPerLine = 99
|
||||
ClientHeight = 50
|
||||
ClientWidth = 312
|
||||
ClientWidth = 310
|
||||
TabOrder = 4
|
||||
object btnPlay: TSpeedButton
|
||||
Left = 5
|
||||
Height = 40
|
||||
Top = 5
|
||||
Width = 65
|
||||
Width = 66
|
||||
Glyph.Data = {
|
||||
36040000424D3604000000000000360000002800000010000000100000000100
|
||||
2000000000000004000064000000640000000000000000000000000000000000
|
||||
@ -28334,10 +28176,10 @@ object MainForm: TMainForm
|
||||
OnClick = btnPlayClick
|
||||
end
|
||||
object btnPause: TSpeedButton
|
||||
Left = 75
|
||||
Left = 76
|
||||
Height = 40
|
||||
Top = 5
|
||||
Width = 65
|
||||
Width = 66
|
||||
Glyph.Data = {
|
||||
36040000424D3604000000000000360000002800000010000000100000000100
|
||||
2000000000000004000064000000640000000000000000000000000000000000
|
||||
@ -28377,10 +28219,10 @@ object MainForm: TMainForm
|
||||
OnClick = btnPauseClick
|
||||
end
|
||||
object btnStop: TSpeedButton
|
||||
Left = 145
|
||||
Left = 147
|
||||
Height = 40
|
||||
Top = 5
|
||||
Width = 65
|
||||
Width = 67
|
||||
Glyph.Data = {
|
||||
36040000424D3604000000000000360000002800000010000000100000000100
|
||||
2000000000000004000064000000640000000000000000000000000000000000
|
||||
@ -28420,10 +28262,10 @@ object MainForm: TMainForm
|
||||
OnClick = btnStopClick
|
||||
end
|
||||
object btnWarp: TSpeedButton
|
||||
Left = 215
|
||||
Left = 219
|
||||
Height = 40
|
||||
Top = 5
|
||||
Width = 92
|
||||
Width = 86
|
||||
Caption = 'Warp+'
|
||||
OnClick = btnWarpClick
|
||||
end
|
||||
@ -28433,8 +28275,8 @@ object MainForm: TMainForm
|
||||
AnchorSideBottom.Control = pnlFlightControl
|
||||
Left = 6
|
||||
Height = 33
|
||||
Top = 536
|
||||
Width = 298
|
||||
Top = 543
|
||||
Width = 296
|
||||
Anchors = [akLeft, akRight, akBottom]
|
||||
BorderSpacing.Bottom = 8
|
||||
TabOrder = 5
|
||||
@ -28446,11 +28288,11 @@ object MainForm: TMainForm
|
||||
AnchorSideBottom.Control = pnlWarpInfo
|
||||
Left = 6
|
||||
Height = 72
|
||||
Top = 464
|
||||
Width = 298
|
||||
Top = 471
|
||||
Width = 296
|
||||
Anchors = [akLeft, akRight, akBottom]
|
||||
ClientHeight = 72
|
||||
ClientWidth = 298
|
||||
ClientWidth = 296
|
||||
Color = clCream
|
||||
ParentBackground = False
|
||||
ParentColor = False
|
||||
@ -28459,7 +28301,7 @@ object MainForm: TMainForm
|
||||
Left = 6
|
||||
Height = 60
|
||||
Top = 6
|
||||
Width = 286
|
||||
Width = 284
|
||||
Align = alClient
|
||||
AutoSize = False
|
||||
BorderSpacing.Around = 5
|
||||
@ -28473,16 +28315,16 @@ object MainForm: TMainForm
|
||||
AnchorSideBottom.Control = plInfo
|
||||
AnchorSideBottom.Side = asrBottom
|
||||
Left = 4
|
||||
Height = 21
|
||||
Top = 47
|
||||
Width = 114
|
||||
Height = 19
|
||||
Top = 49
|
||||
Width = 90
|
||||
Anchors = [akLeft, akBottom]
|
||||
BorderSpacing.Around = 3
|
||||
Caption = 'Follow tightly'
|
||||
Checked = True
|
||||
OnChange = cbTightFollowChange
|
||||
State = cbChecked
|
||||
TabOrder = 0
|
||||
OnChange = cbTightFollowChange
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -71,7 +71,7 @@ implementation
|
||||
{$R *.lfm}
|
||||
|
||||
uses
|
||||
LCLType, Math, FPImage, DateUtils, mvEngine;
|
||||
LCLType, Math, FPImage, DateUtils, mvGeoMath, mvEngine;
|
||||
|
||||
type
|
||||
|
||||
|
@ -5,7 +5,7 @@ unit globals;
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, mvEngine;
|
||||
Classes, SysUtils, mvGeoMath, mvEngine;
|
||||
|
||||
type
|
||||
TPOIMode = (pmDefaultDrawing, pmDefaultImage, pmImageList, pmCustomDrawing);
|
||||
|
@ -57,7 +57,7 @@ implementation
|
||||
{$R *.lfm}
|
||||
|
||||
uses
|
||||
mvTypes, mvEngine,
|
||||
mvTypes, mvGeoMath, mvEngine,
|
||||
globals;
|
||||
|
||||
destructor TGPSListViewer.Destroy;
|
||||
@ -143,7 +143,7 @@ begin
|
||||
// show distance between selected items
|
||||
ShowMessage(Format('Distance between %s and %s is: %.2n %s.', [
|
||||
CoordArr[0].Name, CoordArr[1].Name,
|
||||
CalcGeoDistance(CoordArr[0].Lat, CoordArr[0].Lon, CoordArr[1].Lat, CoordArr[1].Lon, DistanceUnit),
|
||||
CalcGeoDistance(CoordArr[0].Lat, CoordArr[0].Lon, CoordArr[1].Lat, CoordArr[1].Lon, DistanceUnit, esEllipsoid),
|
||||
DistanceUnit_Names[DistanceUnit]
|
||||
]));
|
||||
end;
|
||||
|
@ -15,7 +15,7 @@ uses
|
||||
Classes, SysUtils, Types, Forms, Controls, Graphics, Dialogs, ExtCtrls,
|
||||
StdCtrls, ComCtrls, Buttons, IntfGraphics, PrintersDlgs,
|
||||
Grids, ExtDlgs,
|
||||
mvGeoNames, mvMapViewer, mvTypes, mvGpsObj, mvDrawingEngine,
|
||||
mvGeoMath, mvGeoNames, mvMapViewer, mvTypes, mvGpsObj, mvDrawingEngine,
|
||||
{$IFDEF WITH_ADDONS}ConfigFrame_with_Addons{$ELSE}ConfigFrame{$ENDIF};
|
||||
|
||||
type
|
||||
|
@ -24,192 +24,33 @@ object MainForm: TMainForm
|
||||
Font.Pitch = fpVariable
|
||||
MapProvider = 'Google Maps'
|
||||
POIImage.Data = {
|
||||
36170000424D36170000000000003600000028000000200000002E0000000100
|
||||
2000000000000017000064000000640000000000000000000000FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000FD560000FC4CFFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000F1110000FEE70000FEE10000
|
||||
EA0CFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000FE9A0000FFFF0000FFFF0000
|
||||
FE8FFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF000000FB3E0000FEFE0000FFFF0000FFFF0000
|
||||
FEFC0000FB35FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF000000DB070000FED70000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FECF0000C004FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF000000FE800000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FD75FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF000000F9290000FEF90000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FEF50000F821FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00000080020000FEC30000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FEB8FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF000000FD660000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FD5CFFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000
|
||||
F5180000FEEF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FEEA0000F213FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000
|
||||
FEAA0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FE9FFFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000FC4C0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FEFE0000FC42FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000EA0C0000FEE10000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FEDB0000E309FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000FE900000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FE86FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000FB350000FEFC0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FEFA0000
|
||||
FA2DFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF000000C0040000FED00000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FEC700008002FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF000000FD770000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FD6CFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF000000F8230000FEF80000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FEF50000F61CFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF000000FECF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FEC8FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF000000FE820000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FD79FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF000000F9270000FEFD0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FEFD0000F822FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF000000FEA70000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FEF70000FEB50000FE810000FD670000FD670000
|
||||
FE810000FEB50000FEF70000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FEA7FFFFFF00FFFFFF00FFFFFF000000
|
||||
FB340000FEFE0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FEFD0000FE920000F213FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF000000F2130000FE920000FEFD0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FEFE0000FB34FFFFFF00FFFFFF000000
|
||||
FEAC0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FEF60000FC4DFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF000000FC4D0000FEF60000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FEACFFFFFF000000F3150000
|
||||
FEFA0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FEFE0000
|
||||
FC54FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000FC540000FEFE0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FEFA0000F3150000FD610000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FEA2FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000FEA20000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FD610000FEA00000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FEFD0000F823FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000F8230000FEFD0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FEA00000FECD0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FEC5FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000FEC50000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FECD0000FEEC0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FE8CFFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000FE8C0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FEEC0000FEFA0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FD72FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000FD720000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FEFA0000FEF70000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FD75FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000FD750000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FEF70000FEE80000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FE95FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000FE950000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FEE80000FEC50000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FED5FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000FED50000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FEC50000FE940000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FB37FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000FB370000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FE940000FC520000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FEC00000
|
||||
8002FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00000080020000FEC00000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FC520000E60A0000
|
||||
FEF20000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FD7EFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000FD7E0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FEF20000E60AFFFFFF000000
|
||||
FE950000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FEFE0000FD7F00008002FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00000080020000FD7F0000FEFE0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FE95FFFFFF00FFFFFF000000
|
||||
F8200000FEF80000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FEC30000FB3DFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF000000FB3D0000FEC30000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FEF80000F820FFFFFF00FFFFFF00FFFF
|
||||
FF000000FE830000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FEDB0000FE9C0000FD7E0000FD7E0000
|
||||
FE9C0000FEDB0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FE83FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF000000DB070000FECC0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FECC0000DB07FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF000000F71F0000FEE40000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FEE40000F71FFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF000000FA2B0000FEE50000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FEE50000FA2BFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF000000F8210000FECD0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FECE0000F821FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000DB070000FE850000FEF90000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FEF90000FE850000
|
||||
DB07FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000F8230000
|
||||
FE990000FEF30000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
|
||||
FFFF0000FFFF0000FFFF0000FFFF0000FEF30000FE990000F823FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF000000EA0C0000FD570000FE980000FEC70000FEEB0000FEF90000FEF90000
|
||||
FEEB0000FEC70000FE980000FD570000EA0CFFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00
|
||||
4503000089504E470D0A1A0A0000000D49484452000000200000002E08060000
|
||||
0049701B840000030C49444154789CB5983B68145114867F4410C54644B0107C
|
||||
152262A7A4D2C2DA3422DAD8D868631510B1D1688855409104A2088634819056
|
||||
B00C488845626C82C55662A29204C40DC96ED66CD6F38F77976B76E6DCC7CC14
|
||||
077667CEF9FFEF3EE6CC03AD560B3EB1021C6C023777805189598955892D13AB
|
||||
E6D8287398EBABEB4CA803A745F895C47A92EE11CC650D6BA3012AC03E1119E4
|
||||
087D8D5340383B83D40A0210F29352381F6B9C02F2899A5E000DE09C142C1765
|
||||
6E412C535B05A801C72571A968730B62891EA90066CDE7CA32B720E6EC3DD101
|
||||
901303012215893772C93D62F0378F05D40FFC07201BE4841CAC7B147EF8035C
|
||||
CADAD13CC71C0F9D3A3D3B007260C451B023237DDC0FEC715DD7CC612E6B1C9A
|
||||
2309C077E080FCA96AC99C66DFCED68EA44607A8D21BDBC03547E2B4CFC8D366
|
||||
82B59A36BD39FDC35A92AC6B4FA8B9B5277A1C831B26C08C92B0186B6E5D5D8B
|
||||
8AFE0C137EBA364A4E80CC0D4E6F26D494CD773F2F40A2910D5023404301E82B
|
||||
00A04F016810604D49182A60098614FD3568B7DD6483E607D036F93C13C69484
|
||||
A6CF534D5698A7A9A6A23FC635BAEDB856C7738C7E5CD3A637D68123DA46644F
|
||||
978E753DD49C35DAFD809EF46E934E39666153047B03CC7B59E3D09C6AFDFB97
|
||||
B4CC0B1E77AFA6C4CB2A7038CB98E798A3AD7B7B56E9D90130B330A115D9CD43
|
||||
E29DC41359C3BB0CFE36C7329BDA2E8D89B66F07600B38E3222F22CC9575AA0B
|
||||
C0CCC2D3B20164C61EDA9E5DEB28100B258EFEE36EBF2E00D33C9CCF8711E61B
|
||||
9BC0312780B9813C2861EAEFA579A5024C037B85F87381A39FCD7AAC4B0530BD
|
||||
E1A2146E1760DE9057B2F3593E99006643BE2800E099E6A102F04383087CCD61
|
||||
5EF906EC8F06307DFD6AA4396F62575CFA4E00B3149311006F7DB4BD003680A3
|
||||
22F82BC07C45BB69050398DE7027E09ABFE5ABEB0D605EB57CDE7CDFFB6A0601
|
||||
30E48E7956FB68C5769BF52DA81000B321FB95A90F7E910906309F72BEA48C7E
|
||||
812DBC740086B4E9CBF6231C5B365B778C561480598AD716C0F3589D6880DFC0
|
||||
2131FEC1561DF26DB83000866CBA1B49ABCEA1F117D2B9A057721AC774000000
|
||||
0049454E44AE426082
|
||||
}
|
||||
POITextBgColor = clCream
|
||||
UseThreads = True
|
||||
|
@ -6,7 +6,7 @@ interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls,
|
||||
Grids, StdCtrls, ColorBox, mvMapViewer, mvGpsObj;
|
||||
Grids, StdCtrls, ColorBox, mvMapViewer, mvGeoMath, mvGpsObj;
|
||||
|
||||
type
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
<Description Value="Component for viewing maps (Google, OpenStreetMap, etc). This is a fork of MapViewer by ti_dic (https://sourceforge.net/p/roadbook/code/ci/master/tree/mapviewer/) which itself is based on the MapViewer by Maciej Kaczkowski (https://github.com/maciejkaczkowski/mapviewer)."/>
|
||||
<License Value="Modified LGPL with linking exception, like FreePascal RTL/FCL and Lazarus LCL"/>
|
||||
<Version Minor="2" Release="7"/>
|
||||
<Files Count="21">
|
||||
<Files Count="22">
|
||||
<Item1>
|
||||
<Filename Value="source/mvcache.pas"/>
|
||||
<UnitName Value="mvCache"/>
|
||||
@ -108,6 +108,10 @@
|
||||
<HasRegisterProc Value="True"/>
|
||||
<UnitName Value="mvDE_LCL"/>
|
||||
</Item21>
|
||||
<Item22>
|
||||
<Filename Value="source/mvgeomath.pas"/>
|
||||
<UnitName Value="mvgeomath"/>
|
||||
</Item22>
|
||||
</Files>
|
||||
<CompatibilityMode Value="True"/>
|
||||
<RequiredPkgs Count="2">
|
||||
|
@ -11,7 +11,7 @@ uses
|
||||
mvCache, mvDownloadEngine, mvDragObj, mvEngine, mvGeoNames, mvGpsObj,
|
||||
mvJobQueue, mvJobs, mvMapProvider, mvTypes, mvMapViewer, mvExtraData,
|
||||
mvDLEFpc, mvMapViewerReg, mvGPX, mvDrawingEngine, mvDE_IntfGraphics,
|
||||
mvDLEWin, mvMapViewerPropEdits, mvLayersPropEditForm, mvDE_LCL,
|
||||
mvDLEWin, mvMapViewerPropEdits, mvLayersPropEditForm, mvDE_LCL, mvgeomath,
|
||||
LazarusPackageIntf;
|
||||
|
||||
implementation
|
||||
|
@ -21,13 +21,7 @@ interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, IntfGraphics, Controls, Math, GraphType, FPImage,
|
||||
mvTypes, mvJobQueue, mvMapProvider, mvDownloadEngine, mvCache, mvDragObj;
|
||||
|
||||
const
|
||||
EARTH_EQUATORIAL_RADIUS = 6378137;
|
||||
EARTH_POLAR_RADIUS = 6356752.3142;
|
||||
EARTH_CIRCUMFERENCE = 2 * pi * EARTH_EQUATORIAL_RADIUS;
|
||||
EARTH_ECCENTRICITY = sqrt(1 - sqr(EARTH_POLAR_RADIUS / EARTH_EQUATORIAL_RADIUS));
|
||||
mvTypes, mvGeoMath, mvJobQueue, mvMapProvider, mvDownloadEngine, mvCache, mvDragObj;
|
||||
|
||||
type
|
||||
TDrawTileEvent = procedure (const TileId: TTileId; X,Y: integer;
|
||||
@ -42,8 +36,6 @@ type
|
||||
|
||||
TTileIdArray = Array of TTileId;
|
||||
|
||||
TDistanceUnits = (duMeters, duKilometers, duMiles);
|
||||
|
||||
{ TMapWindow }
|
||||
|
||||
TMapWindow = Record
|
||||
@ -215,33 +207,19 @@ type
|
||||
property OnZoomChange: TNotifyEvent read FOnZoomChange write FOnZoomChange;
|
||||
end;
|
||||
|
||||
function RealPoint(Lat, Lon: Double): TRealPoint;
|
||||
function NormalizeLon(const Lon: Double): Double; inline;
|
||||
// The following functions have been moved to mvGeoMath and will be removed here sooner or later...
|
||||
function DMSToDeg(Deg, Min: Word; Sec: Double): Double; deprecated 'Use function in unit mvGeoMath';
|
||||
function GPSToDMS(Angle: Double): string; deprecated 'Use function in unit mvGeoMath';
|
||||
function GPSToDMS(Angle: Double; AFormatSettings: TFormatSettings): string; deprecated 'Use function in unit mvGeoMath';
|
||||
|
||||
function HaversineDist(Lat1, Lon1, Lat2, Lon2, Radius: Double): Double;
|
||||
function CalcGeoDistance(Lat1, Lon1, Lat2, Lon2: double;
|
||||
AUnits: TDistanceUnits = duKilometers): double;
|
||||
function LatToStr(ALatitude: Double; DMS: Boolean): String; deprecated 'Use function in unit mvGeoMath';
|
||||
function LatToStr(ALatitude: Double; DMS: Boolean; AFormatSettings: TFormatSettings): String; deprecated 'Use function in unit mvGeoMath';
|
||||
function LonToStr(ALongitude: Double; DMS: Boolean): String; deprecated 'Use function in unit mvGeoMath';
|
||||
function LonToStr(ALongitude: Double; DMS: Boolean; AFormatSettings: TFormatSettings): String; deprecated 'Use function in unit mvGeoMath';
|
||||
function TryStrToGps(const AValue: String; out ADeg: Double): Boolean; deprecated 'Use function in unit mvGeoMath';
|
||||
function TryStrDMSToDeg(const AValue: String; out ADeg: Double): Boolean; deprecated 'Use function in unit mvGeoMath';
|
||||
|
||||
function CalcBearing(Lat1, Lon1, Lat2, Lon2: Double): Double;
|
||||
procedure CalcLatLon(const Lat1, Lon1, ADist, ABearing: Double; out Lat2, Lon2: Double);
|
||||
procedure CalcMidpoint(const Lat1, Lon1, Lat2, Lon2: Double; out Lat, Lon: Double);
|
||||
procedure CalcIntermedPoint(const Lat1, Lon1, Lat2, Lon2, AFrac: Double; out Lat, Lon: Double);
|
||||
|
||||
|
||||
function DMSToDeg(Deg, Min: Word; Sec: Double): Double;
|
||||
function GPSToDMS(Angle: Double): string;
|
||||
function GPSToDMS(Angle: Double; AFormatSettings: TFormatSettings): string;
|
||||
|
||||
function LatToStr(ALatitude: Double; DMS: Boolean): String;
|
||||
function LatToStr(ALatitude: Double; DMS: Boolean; AFormatSettings: TFormatSettings): String;
|
||||
function LonToStr(ALongitude: Double; DMS: Boolean): String;
|
||||
function LonToStr(ALongitude: Double; DMS: Boolean; AFormatSettings: TFormatSettings): String;
|
||||
function TryStrToGps(const AValue: String; out ADeg: Double): Boolean;
|
||||
function TryStrDMSToDeg(const AValue: String; out ADeg: Double): Boolean;
|
||||
|
||||
procedure SplitGps(AValue: Double; out ADegs, AMins, ASecs: Double);
|
||||
|
||||
function ZoomFactor(AZoomLevel: Integer): Int64;
|
||||
function ZoomFactor(AZoomLevel: Integer): Int64; deprecated 'Use function in unit mvGeoMath';
|
||||
|
||||
var
|
||||
HERE_AppID: String = '';
|
||||
@ -249,8 +227,6 @@ var
|
||||
OpenWeatherMap_ApiKey: String = '';
|
||||
ThunderForest_ApiKey: String = '';
|
||||
|
||||
DMS_Decimals: Integer = 1;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
@ -258,25 +234,6 @@ uses
|
||||
Forms, TypInfo, laz2_xmlread, laz2_xmlwrite, laz2_dom,
|
||||
mvJobs, mvGpsObj;
|
||||
|
||||
const
|
||||
_K = 1024;
|
||||
_M = _K*_K;
|
||||
_G = _K*_M;
|
||||
ZOOM_FACTOR: array[0..32] of Int64 = (
|
||||
1, 2, 4, 8, 16, 32, 64, 128, 256, 512, // 0..9
|
||||
_K, 2*_K, 4*_K, 8*_K, 16*_K, 32*_K, 64*_K, 128*_K, 256*_K, 512*_K, // 10..19
|
||||
_M, 2*_M, 4*_M, 8*_M, 16*_M, 32*_M, 64*_M, 128*_M, 256*_M, 512*_M, // 20..29
|
||||
_G, 2*_G, 4*_G // 30..32
|
||||
);
|
||||
|
||||
function ZoomFactor(AZoomLevel: Integer): Int64;
|
||||
begin
|
||||
if (AZoomLevel >= Low(ZOOM_FACTOR)) and (AZoomLevel < High(ZOOM_FACTOR)) then
|
||||
Result := ZOOM_FACTOR[AZoomLevel]
|
||||
else
|
||||
Result := round(IntPower(2, AZoomLevel));
|
||||
end;
|
||||
|
||||
type
|
||||
|
||||
{ TEnvTile }
|
||||
@ -1474,492 +1431,56 @@ begin
|
||||
MapWin.MapProvider := MP; // Restore the old Map Provider
|
||||
end;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
{------------------------------------------------------------------------------}
|
||||
|
||||
function RealPoint(Lat, Lon: Double): TRealPoint;
|
||||
function DMSToDeg(Deg, Min: Word; Sec: Double): Double;
|
||||
begin
|
||||
Result.Lon := Lon;
|
||||
Result.Lat := Lat;
|
||||
end;
|
||||
|
||||
procedure SplitGps(AValue: Double; out ADegs, AMins: Double);
|
||||
begin
|
||||
AValue := abs(AValue);
|
||||
AMins := frac(AValue) * 60;
|
||||
if abs(AMins - 60) < 1E-3 then
|
||||
begin
|
||||
AMins := 0;
|
||||
ADegs := trunc(AValue) + 1;
|
||||
end else
|
||||
ADegs := trunc(AValue);
|
||||
if AValue < 0 then
|
||||
ADegs := -ADegs;
|
||||
end;
|
||||
|
||||
procedure SplitGps(AValue: Double; out ADegs, AMins, ASecs: Double);
|
||||
begin
|
||||
SplitGps(AValue, ADegs, AMins);
|
||||
ASecs := frac(AMins) * 60;
|
||||
AMins := trunc(AMins);
|
||||
if abs(ASecs - 60) < 1E-3 then
|
||||
begin
|
||||
ASecs := 0;
|
||||
AMins := AMins + 1;
|
||||
if abs(AMins - 60) < 1e-3 then
|
||||
begin
|
||||
AMins := 0;
|
||||
ADegs := ADegs + 1;
|
||||
end;
|
||||
end;
|
||||
if AValue < 0 then
|
||||
ADegs := -ADegs;
|
||||
Result := mvGeoMath.DMSToDeg(Deg, Min, Sec);
|
||||
end;
|
||||
|
||||
function GPSToDMS(Angle: Double): string;
|
||||
begin
|
||||
Result := GPSToDMS(Angle, DefaultFormatSettings);
|
||||
Result := mvGeoMath.GPSToDMS(Angle);
|
||||
end;
|
||||
|
||||
function GPSToDMS(Angle: Double; AFormatSettings: TFormatSettings): string;
|
||||
var
|
||||
deg, min, sec: Double;
|
||||
begin
|
||||
SplitGPS(Angle, deg, min, sec);
|
||||
Result := Format('%.0f° %.0f'' %.*f"', [deg, min, DMS_Decimals, sec], AFormatSettings);
|
||||
Result := mvGeoMath.GPSToDMS(Angle, AFormatSettings);
|
||||
end;
|
||||
|
||||
function LatToStr(ALatitude: Double; DMS: Boolean): String;
|
||||
begin
|
||||
Result := LatToStr(ALatitude, DMS, DefaultFormatSettings);
|
||||
Result := mvGeoMath.LatToStr(ALatitude, DMS);
|
||||
end;
|
||||
|
||||
function LatToStr(ALatitude: Double; DMS: Boolean; AFormatSettings: TFormatSettings): String;
|
||||
begin
|
||||
if DMS then
|
||||
Result := GPSToDMS(abs(ALatitude), AFormatSettings)
|
||||
else
|
||||
Result := Format('%.6f°',[abs(ALatitude)], AFormatSettings);
|
||||
if ALatitude > 0 then
|
||||
Result := Result + ' N'
|
||||
else
|
||||
if ALatitude < 0 then
|
||||
Result := Result + ' S';
|
||||
Result := mvGeoMath.LatToStr(ALatitude, DMS, AFormatSettings);
|
||||
end;
|
||||
|
||||
function LonToStr(ALongitude: Double; DMS: Boolean): String;
|
||||
begin
|
||||
Result := LonToStr(ALongitude, DMS, DefaultFormatSettings);
|
||||
Result := mvGeoMath.LonToStr(ALongitude, DMS);
|
||||
end;
|
||||
|
||||
function LonToStr(ALongitude: Double; DMS: Boolean; AFormatSettings: TFormatSettings): String;
|
||||
begin
|
||||
if DMS then
|
||||
Result := GPSToDMS(abs(ALongitude), AFormatSettings)
|
||||
else
|
||||
Result := Format('%.6f°', [abs(ALongitude)], AFormatSettings);
|
||||
if ALongitude > 0 then
|
||||
Result := Result + ' E'
|
||||
else if ALongitude < 0 then
|
||||
Result := Result + ' W';
|
||||
Result := mvGeoMath.LonToStr(ALongitude, DMS, AFormatSettings);
|
||||
end;
|
||||
|
||||
{ Combines up to three parts of a GPS coordinate string (degrees, minutes, seconds)
|
||||
to a floating-point degree value. The parts are separated by non-numeric
|
||||
characters:
|
||||
|
||||
three parts ---> d m s ---> d and m must be integer, s can be float
|
||||
two parts ---> d m ---> d must be integer, s can be float
|
||||
one part ---> d ---> d can be float
|
||||
|
||||
Each part can exhibit a unit identifier, such as °, ', or ". BUT: they are
|
||||
ignored. This means that an input string 50°30" results in the output value 50.5
|
||||
although the second part is marked as seconds, not minutes!
|
||||
|
||||
Hemisphere suffixes ('N', 'S', 'E', 'W') are supported at the end of the input string.
|
||||
}
|
||||
function TryStrToGps(const AValue: String; out ADeg: Double): Boolean;
|
||||
const
|
||||
NUMERIC_CHARS = ['0'..'9', '.', ',', '-', '+'];
|
||||
var
|
||||
mins, secs: Double;
|
||||
i, j, len: Integer;
|
||||
n: Integer;
|
||||
s: String = '';
|
||||
res: Integer;
|
||||
sgn: Double;
|
||||
begin
|
||||
Result := false;
|
||||
|
||||
ADeg := NaN;
|
||||
mins := 0;
|
||||
secs := 0;
|
||||
|
||||
if AValue = '' then
|
||||
exit;
|
||||
|
||||
len := Length(AValue);
|
||||
i := len;
|
||||
while (i >= 1) and (AValue[i] = ' ') do dec(i);
|
||||
sgn := 1.0;
|
||||
if (AValue[i] in ['S', 's', 'W', 'w']) then sgn := -1;
|
||||
|
||||
// skip leading non-numeric characters
|
||||
i := 1;
|
||||
while (i <= len) and not (AValue[i] in NUMERIC_CHARS) do
|
||||
inc(i);
|
||||
|
||||
// extract first value: degrees
|
||||
SetLength(s, len);
|
||||
j := 1;
|
||||
n := 0;
|
||||
while (i <= len) and (AValue[i] in NUMERIC_CHARS) do begin
|
||||
if AValue[i] = ',' then s[j] := '.' else s[j] := AValue[i];
|
||||
inc(i);
|
||||
inc(j);
|
||||
inc(n);
|
||||
end;
|
||||
if n > 0 then begin
|
||||
SetLength(s, n);
|
||||
val(s, ADeg, res);
|
||||
if res <> 0 then
|
||||
exit;
|
||||
end;
|
||||
|
||||
// skip non-numeric characters between degrees and minutes
|
||||
while (i <= len) and not (AValue[i] in NUMERIC_CHARS) do
|
||||
inc(i);
|
||||
|
||||
// extract second value: minutes
|
||||
SetLength(s, len);
|
||||
j := 1;
|
||||
n := 0;
|
||||
while (i <= len) and (AValue[i] in NUMERIC_CHARS) do begin
|
||||
if AValue[i] = ',' then s[j] := '.' else s[j] := AValue[i];
|
||||
inc(i);
|
||||
inc(j);
|
||||
inc(n);
|
||||
end;
|
||||
if n > 0 then begin
|
||||
SetLength(s, n);
|
||||
val(s, mins, res);
|
||||
if (res <> 0) or (mins < 0) then
|
||||
exit;
|
||||
end;
|
||||
|
||||
// skip non-numeric characters between minutes and seconds
|
||||
while (i <= len) and not (AValue[i] in NUMERIC_CHARS) do
|
||||
inc(i);
|
||||
|
||||
// extract third value: seconds
|
||||
SetLength(s, len);
|
||||
j := 1;
|
||||
n := 0;
|
||||
while (i <= len) and (AValue[i] in NUMERIC_CHARS) do begin
|
||||
if AValue[i] = ',' then s[j] := '.' else s[j] := AValue[i];
|
||||
inc(i);
|
||||
inc(j);
|
||||
inc(n);
|
||||
end;
|
||||
if n > 0 then begin
|
||||
SetLength(s, n);
|
||||
val(s, secs, res);
|
||||
if (res <> 0) or (secs < 0) then
|
||||
exit;
|
||||
end;
|
||||
|
||||
// If the string contains seconds then minutes and deegrees must be integers
|
||||
if (secs <> 0) and ((frac(ADeg) > 0) or (frac(mins) > 0)) then
|
||||
exit;
|
||||
// If the string does not contain seconds then degrees must be integer.
|
||||
if (secs = 0) and (mins <> 0) and (frac(ADeg) > 0) then
|
||||
exit;
|
||||
|
||||
// If the string contains minutes, but no seconds, then the degrees must be integer.
|
||||
Result := (mins >= 0) and (mins < 60) and (secs >= 0) and (secs < 60);
|
||||
|
||||
// A similar check should be made for the degrees range, but since this is
|
||||
// different for latitude and longitude the check is skipped here.
|
||||
if Result then
|
||||
ADeg := sgn * (abs(ADeg) + mins / 60 + secs / 3600);
|
||||
Result := mvGeoMath.TryStrToGps(AValue, ADeg);
|
||||
end;
|
||||
|
||||
{ Convert Lat/Lon string to degrees.
|
||||
|
||||
Recognized formats:
|
||||
|
||||
Degrees, Minutes and Seconds:
|
||||
DDD°MM'SS.S"
|
||||
32°18'23.1"N 122°36'52.5"W
|
||||
|
||||
Degrees and Decimal Minutes:
|
||||
DDD° MM.MMM'
|
||||
32°18.385'N 122°36.875'W
|
||||
|
||||
Decimal Degrees:
|
||||
DDD.DDDDD°
|
||||
32.30642°N 122.61458°W
|
||||
+32.30642 -122.61458
|
||||
}
|
||||
function TryStrDMSToDeg(const AValue: String; out ADeg: Double): Boolean;
|
||||
const
|
||||
NUMERIC_CHARS = ['0'..'9', '.', ',', '-', '+'];
|
||||
WS_CHARS = [' '];
|
||||
var
|
||||
I, Len, N: Integer;
|
||||
S: String;
|
||||
D, Minutes, Seconds: Double;
|
||||
R: Word;
|
||||
Last, Neg: Boolean;
|
||||
|
||||
function EOL: Boolean; inline;
|
||||
begin
|
||||
Result := Len < I;
|
||||
end;
|
||||
|
||||
procedure SkipWS; inline;
|
||||
begin
|
||||
while not EOL and (AValue[I] in WS_CHARS) do
|
||||
Inc(I);
|
||||
end;
|
||||
|
||||
function NextNum: String;
|
||||
begin
|
||||
Result := '';
|
||||
SkipWS;
|
||||
while not EOL and (AValue[I] in NUMERIC_CHARS) do
|
||||
begin
|
||||
if AValue[I] = ','
|
||||
then Result := Result + '.'
|
||||
else Result := Result + AValue[I];
|
||||
Inc(I);
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
Result := False;
|
||||
ADeg := NaN;
|
||||
Len := Length(AValue);
|
||||
I := 1;
|
||||
|
||||
// Degrees
|
||||
S := NextNum;
|
||||
if S = '' then
|
||||
Exit;
|
||||
Val(S, ADeg, R);
|
||||
if R > 0 then
|
||||
Exit;
|
||||
|
||||
// It must be the only part if negative or fractional
|
||||
Neg := ADeg < 0.0;
|
||||
Last := Neg or (Frac(ADeg) > 0.0);
|
||||
|
||||
// Eat the degree symbol if present
|
||||
if not EOL and (Utf8CodePointLen(@AValue[I], 2, False) = 2)
|
||||
and (AValue[I] = #$c2) and (AValue[I + 1] = #$b0)
|
||||
then
|
||||
Inc(I, 2);
|
||||
|
||||
Minutes := 0.0;
|
||||
Seconds := 0.0;
|
||||
|
||||
N := 1;
|
||||
while not (EOL or Last) and (N < 3) do
|
||||
begin
|
||||
S := NextNum;
|
||||
if S = '' then
|
||||
Break
|
||||
else
|
||||
begin
|
||||
Val(S, D, R);
|
||||
// Invalid part or negative one
|
||||
if (R > 0) or (D < 0.0) then
|
||||
Exit;
|
||||
// No more parts when fractional
|
||||
Last := Frac(D) > 0.0;
|
||||
if not EOL then
|
||||
case AValue[I] of
|
||||
'''': // Munutes suffix
|
||||
begin
|
||||
Minutes := D;
|
||||
Inc(I); // Eat the '
|
||||
end;
|
||||
'"': // Seconds suffix
|
||||
begin
|
||||
Seconds := D;
|
||||
Last := True; // Last part
|
||||
Inc(I); // Eat the "
|
||||
end;
|
||||
otherwise
|
||||
if N = 1
|
||||
then Minutes := D
|
||||
else Seconds := D;
|
||||
end;
|
||||
end;
|
||||
Inc(N);
|
||||
end;
|
||||
|
||||
// Merge parts
|
||||
ADeg := ADeg + Minutes / 60 + Seconds / 3600;
|
||||
|
||||
// Check for N-S and E-W designators
|
||||
SkipWS;
|
||||
if not (EOL or Neg) and (AValue[I] in ['S', 's', 'W', 'w', 'N', 'n', 'E', 'e']) then
|
||||
begin
|
||||
if AValue[I] in ['S', 's', 'W', 'w']
|
||||
then ADeg := -1 * ADeg;
|
||||
Inc(I);
|
||||
end;
|
||||
SkipWS;
|
||||
|
||||
// It must be entirely consumed
|
||||
Result := EOL;
|
||||
Result := mvGeoMath.TryStrDMSToDeg(AValue, ADeg);
|
||||
end;
|
||||
|
||||
// https://stackoverflow.com/questions/73608975/pascal-delphi-11-formula-for-distance-in-meters-between-two-decimal-gps-point
|
||||
function HaversineDist(Lat1, Lon1, Lat2, Lon2, Radius: Double): Double;
|
||||
var
|
||||
latFrom, latTo, lonDiff: Double;
|
||||
dx, dy, dz: Double;
|
||||
function ZoomFactor(AZoomLevel: Integer): Int64;
|
||||
begin
|
||||
lonDiff := DegToRad(Lon1 - Lon2);
|
||||
latFrom := DegToRad(Lat1);
|
||||
latTo := DegToRad(Lat2);
|
||||
|
||||
dz := sin(latFrom) - sin(latTo);
|
||||
dx := cos(lonDiff) * cos(latFrom) - cos(latTo);
|
||||
dy := sin(lonDiff) * cos(latFrom);
|
||||
|
||||
Result := arcsin(sqrt(sqr(dx) + sqr(dy) + sqr(dz)) / 2) * Radius * 2;
|
||||
end;
|
||||
|
||||
|
||||
{ Returns the direct distance (air-line) between two geo coordinates
|
||||
If latitude NOT between -90°..+90° and longitude NOT between -180°..+180°
|
||||
the function returns NaN.
|
||||
Usage: CalcGeoDistance(51.53323, -2.90130, 51.29442, -2.27275, duKilometers);
|
||||
}
|
||||
function CalcGeoDistance(Lat1, Lon1, Lat2, Lon2: double;
|
||||
AUnits: TDistanceUnits = duKilometers): double;
|
||||
begin
|
||||
// Validate
|
||||
if (Lat1 < -90.0) or (Lat1 > 90.0) then exit(NaN);
|
||||
if (Lat2 < -90.0) or (Lat2 > 90.0) then exit(NaN);
|
||||
|
||||
Result := HaversineDist(Lat1, Lon1, Lat2, Lon2, EARTH_EQUATORIAL_RADIUS);
|
||||
case AUnits of
|
||||
duMeters: ;
|
||||
duKilometers: Result := Result * 1E-3;
|
||||
duMiles: Result := Result * 0.62137E-3;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ Calculate initial bearing (in °) from the start point Lat1,Lon1 to
|
||||
the end point Lat2,Lon2. No parameter checks, result normalized to 0°..360°.
|
||||
}
|
||||
function CalcBearing(Lat1, Lon1, Lat2, Lon2: Double): Double;
|
||||
var
|
||||
latFrom, latTo, lonDiff: Double;
|
||||
begin
|
||||
lonDiff := DegToRad(Lon2 - Lon1);
|
||||
latFrom := DegToRad(Lat1);
|
||||
latTo := DegToRad(Lat2);
|
||||
Result := ArcTan2(Sin(lonDiff) * Cos(latTo),
|
||||
Cos(latFrom) * Sin(latTo) - Sin(latFrom) * Cos(latTo) * Cos(lonDiff));
|
||||
Result := RadToDeg(Result);
|
||||
if Result < 0.0 then
|
||||
Result := Result + 360.0;
|
||||
end;
|
||||
|
||||
{ Calculate end point Lat2,Lon2 by given start point Lat1,Lon1, distance
|
||||
ADist (in meters) and bearing ABearing (in °). No parameter checks,
|
||||
result Lon2 normalized to -180°..180°.
|
||||
}
|
||||
procedure CalcLatLon(const Lat1, Lon1, ADist, ABearing: Double; out Lat2,
|
||||
Lon2: Double);
|
||||
var
|
||||
latFrom, lonFrom, brng, aD: Double;
|
||||
begin
|
||||
latFrom := DegToRad(Lat1);
|
||||
lonFrom := DegToRad(Lon1);
|
||||
brng := DegToRad(ABearing);
|
||||
aD := ADist / EARTH_EQUATORIAL_RADIUS;
|
||||
Lat2 := ArcSin(Sin(latFrom) * Cos(aD) + Cos(latFrom) * Sin(aD) * Cos(brng));
|
||||
Lon2 := lonFrom + ArcTan2(Sin(brng) * Sin(aD) * Cos(latFrom),
|
||||
Cos(aD) - Sin(latFrom) * Sin(Lat2));
|
||||
Lat2 := RadToDeg(Lat2);
|
||||
Lon2 := NormalizeLon(RadToDeg(Lon2));
|
||||
end;
|
||||
|
||||
{ Calculate midpoint Lat,Lon by given start point Lat1,Lon1 and end point
|
||||
Lat2,Lon2. No parameter checks, result Lon normalized to -180°..180°.
|
||||
}
|
||||
procedure CalcMidpoint(const Lat1, Lon1, Lat2, Lon2: Double; out Lat,
|
||||
Lon: Double);
|
||||
var
|
||||
latFrom, lonDiff, latTo, lonTo, Bx, By: Double;
|
||||
begin
|
||||
lonDiff := DegToRad(Lon2 - Lon1);
|
||||
latFrom := DegToRad(Lat1);
|
||||
latTo := DegToRad(Lat2);
|
||||
lonTo := DegToRad(Lon2);
|
||||
Bx := Cos(latTo) * Cos(lonDiff);
|
||||
By := Cos(latTo) * Sin(lonDiff);
|
||||
Lat := ArcTan2(Sin(latFrom) + Sin(latTo), Sqrt(Sqr(Cos(latFrom) + Bx) + Sqr(By)));
|
||||
Lon := lonTo + ArcTan2(By, Cos(latFrom) + By);
|
||||
Lat := RadToDeg(Lat);
|
||||
Lon := NormalizeLon(RadToDeg(Lon));
|
||||
end;
|
||||
|
||||
{ Calculate intermediate point Lat,Lon by given start point Lat1,Lon1, end point
|
||||
Lat2,Lon2 and fraction AFrac (0.0-1.0). No parameter checks for
|
||||
Lat1,Lon1,Lat2 and Lon2. Result Lon normalized to -180°..180°.
|
||||
}
|
||||
procedure CalcIntermedPoint(const Lat1, Lon1, Lat2, Lon2, AFrac: Double; out
|
||||
Lat, Lon: Double);
|
||||
var
|
||||
latFrom, lonFrom, latTo, lonTo: Double;
|
||||
A, B, aD, X, Y, Z: Double;
|
||||
begin
|
||||
if (Lat1 = Lat2) and (Lon1 = Lon2) or (AFrac < 0.001) then
|
||||
begin
|
||||
Lat := Lat1;
|
||||
Lon := Lon1;
|
||||
Exit;
|
||||
end;
|
||||
if AFrac > 0.999 then
|
||||
begin
|
||||
Lat := Lat2;
|
||||
Lon := Lon2;
|
||||
Exit;
|
||||
end;
|
||||
aD := CalcGeoDistance(Lat1, Lon1, Lat2, Lon2) / EARTH_EQUATORIAL_RADIUS;
|
||||
latFrom := DegToRad(Lat1);
|
||||
lonFrom := DegToRad(Lon1);
|
||||
latTo := DegToRad(Lat2);
|
||||
lonTo := DegToRad(Lon2);
|
||||
A := Sin((1.0 - AFrac) * aD) / Sin(aD);
|
||||
B := Sin(AFrac * aD) / Sin(aD);
|
||||
X := A * Cos(latFrom) * Cos(lonFrom) + B * Cos(latTo) * Cos(lonTo);
|
||||
Y := A * Cos(latFrom) * Sin(lonFrom) + B * Cos(latTo) * Sin(lonTo);
|
||||
Z := A * Sin(latFrom) + B * Sin(latTo);
|
||||
Lat := ArcTan2(Z, Sqrt(Sqr(X) + Sqr(Y)));
|
||||
Lon := ArcTan2(Y, X);
|
||||
Lat := RadToDeg(Lat);
|
||||
Lon := NormalizeLon(RadToDeg(Lon));
|
||||
end;
|
||||
|
||||
function NormalizeLon(const Lon: Double): Double;
|
||||
begin
|
||||
if InRange(Lon, -180.0, 180.0)
|
||||
then Result := Lon
|
||||
else Result := FMod(Lon + 540.0, 360.0) - 180.0;
|
||||
end;
|
||||
|
||||
{ Converts an angle given as degrees, minutes and seconds to a single
|
||||
floating point degrees value. }
|
||||
function DMSToDeg(Deg, Min: Word; Sec: Double): Double;
|
||||
begin
|
||||
Result := Deg + Min/60.0 + Sec/3600.0;
|
||||
Result := mvGeoMath.ZoomFactor(AZoomLevel);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
601
components/lazmapviewer/source/mvgeomath.pas
Normal file
601
components/lazmapviewer/source/mvgeomath.pas
Normal file
@ -0,0 +1,601 @@
|
||||
unit mvGeoMath;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, Math;
|
||||
|
||||
const
|
||||
EARTH_EQUATORIAL_RADIUS = 6378137;
|
||||
EARTH_POLAR_RADIUS = 6356752.3142;
|
||||
EARTH_CIRCUMFERENCE = 2 * pi * EARTH_EQUATORIAL_RADIUS;
|
||||
EARTH_ECCENTRICITY = sqrt(1 - sqr(EARTH_POLAR_RADIUS / EARTH_EQUATORIAL_RADIUS));
|
||||
EARTH_FLATTENING = 1.0 - EARTH_POLAR_RADIUS / EARTH_EQUATORIAL_RADIUS;
|
||||
|
||||
DMS_Decimals: Integer = 1;
|
||||
|
||||
type
|
||||
TDistanceUnits = (duMeters, duKilometers, duMiles);
|
||||
TEarthShape = (esSphere, esEllipsoid);
|
||||
|
||||
function NormalizeLon(const Lon: Double): Double; inline;
|
||||
|
||||
function HaversineDist(Lat1, Lon1, Lat2, Lon2, Radius: Double): Double;
|
||||
function LambertsDist(Lat1, Lon1, Lat2, Lon2, Radius, Flattening: Double): Double;
|
||||
function CalcGeoDistance(Lat1, Lon1, Lat2, Lon2: double;
|
||||
AUnits: TDistanceUnits = duKilometers; AShape: TEarthShape = esSphere): double;
|
||||
|
||||
function CalcBearing(Lat1, Lon1, Lat2, Lon2: Double): Double;
|
||||
procedure CalcLatLon(const Lat1, Lon1, ADist, ABearing: Double; out Lat2, Lon2: Double);
|
||||
procedure CalcMidpoint(const Lat1, Lon1, Lat2, Lon2: Double; out Lat, Lon: Double);
|
||||
procedure CalcIntermedPoint(const Lat1, Lon1, Lat2, Lon2, AFrac: Double; out Lat, Lon: Double);
|
||||
|
||||
function DMSToDeg(Deg, Min: Word; Sec: Double): Double;
|
||||
function GPSToDMS(Angle: Double): string;
|
||||
function GPSToDMS(Angle: Double; AFormatSettings: TFormatSettings): string;
|
||||
|
||||
function LatToStr(ALatitude: Double; DMS: Boolean): String;
|
||||
function LatToStr(ALatitude: Double; DMS: Boolean; AFormatSettings: TFormatSettings): String;
|
||||
function LonToStr(ALongitude: Double; DMS: Boolean): String;
|
||||
function LonToStr(ALongitude: Double; DMS: Boolean; AFormatSettings: TFormatSettings): String;
|
||||
function TryStrToGps(const AValue: String; out ADeg: Double): Boolean;
|
||||
function TryStrDMSToDeg(const AValue: String; out ADeg: Double): Boolean;
|
||||
|
||||
procedure SplitGps(AValue: Double; out ADegs, AMins, ASecs: Double);
|
||||
|
||||
function ZoomFactor(AZoomLevel: Integer): Int64;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
const
|
||||
_K = 1024;
|
||||
_M = _K*_K;
|
||||
_G = _K*_M;
|
||||
ZOOM_FACTOR: array[0..32] of Int64 = (
|
||||
1, 2, 4, 8, 16, 32, 64, 128, 256, 512, // 0..9
|
||||
_K, 2*_K, 4*_K, 8*_K, 16*_K, 32*_K, 64*_K, 128*_K, 256*_K, 512*_K, // 10..19
|
||||
_M, 2*_M, 4*_M, 8*_M, 16*_M, 32*_M, 64*_M, 128*_M, 256*_M, 512*_M, // 20..29
|
||||
_G, 2*_G, 4*_G // 30..32
|
||||
);
|
||||
|
||||
function ZoomFactor(AZoomLevel: Integer): Int64;
|
||||
begin
|
||||
if (AZoomLevel >= Low(ZOOM_FACTOR)) and (AZoomLevel < High(ZOOM_FACTOR)) then
|
||||
Result := ZOOM_FACTOR[AZoomLevel]
|
||||
else
|
||||
Result := round(IntPower(2, AZoomLevel));
|
||||
end;
|
||||
|
||||
{ Calculation of distance on a sphere
|
||||
https://stackoverflow.com/questions/73608975/pascal-delphi-11-formula-for-distance-in-meters-between-two-decimal-gps-point
|
||||
}
|
||||
// angles in radians
|
||||
function HaversineAngle(Lat1, Lon1, Lat2, Lon2: Double): Double;
|
||||
var
|
||||
latFrom, latTo, lonDiff: Double;
|
||||
dx, dy, dz: Double;
|
||||
begin
|
||||
lonDiff := Lon1 - Lon2;
|
||||
latFrom := Lat1;
|
||||
latTo := Lat2;
|
||||
|
||||
dz := sin(latFrom) - sin(latTo);
|
||||
dx := cos(lonDiff) * cos(latFrom) - cos(latTo);
|
||||
dy := sin(lonDiff) * cos(latFrom);
|
||||
|
||||
Result := arcsin(sqrt(sqr(dx) + sqr(dy) + sqr(dz)) / 2.0) * 2.0;
|
||||
end;
|
||||
|
||||
// Angles in degrees
|
||||
function HaversineDist(Lat1, Lon1, Lat2, Lon2, Radius: Double): Double;
|
||||
begin
|
||||
Result := HaversineAngle(DegToRad(Lat1), DegToRad(Lon1), DegToRad(Lat2), DegToRad(Lon2)) * Radius;
|
||||
end;
|
||||
|
||||
{ Calculation of distance on an ellipsoid
|
||||
https://en.wikipedia.org/wiki/Geographical_distance
|
||||
}
|
||||
// Angles in degrees
|
||||
function LambertsDist(Lat1, Lon1, Lat2, Lon2, Radius, Flattening: Double): Double;
|
||||
var
|
||||
reducedLat1, reducedLat2, sigma: Double;
|
||||
P, Q: Double;
|
||||
X, Y: Double;
|
||||
sinP, cosP, sinQ, cosQ: Double;
|
||||
sinSigma, sinSigma2, cosSigma2: Double;
|
||||
begin
|
||||
Lat1 := DegToRad(Lat1);
|
||||
Lon1 := DegToRad(Lon1);
|
||||
Lat2 := DegToRad(Lat2);
|
||||
Lon2 := DegToRad(Lon2);
|
||||
reducedLat1 := arctan((1.0 - flattening) * tan(Lat1));
|
||||
reducedLat2 := arctan((1.0 - flattening) * tan(Lat2));
|
||||
sigma := HaversineAngle(reducedLat1, Lon1, reducedLat2, Lon2);
|
||||
P := (reducedLat1 + reducedLat2) * 0.5;
|
||||
Q := (reducedLat2 - reducedLat1) * 0.5;
|
||||
SinCos(P, sinP, cosP);
|
||||
SinCos(Q, sinQ, cosQ);
|
||||
SinCos(sigma*0.5, sinSigma2, cosSigma2);
|
||||
sinSigma := sin(sigma);
|
||||
X := (sigma - sinSigma) * sqr(sinP * cosQ / cosSigma2);
|
||||
Y := (sigma + sinSigma) * sqr(cosP * sinQ / sinSigma2);
|
||||
Result := (sigma - 0.5*Flattening*(X + Y)) * Radius;
|
||||
end;
|
||||
|
||||
|
||||
{ Returns the direct distance (air-line) between two geo coordinates
|
||||
If latitude is NOT between -90°..+90° and longitude is NOT between -180°..+180°
|
||||
the function returns NaN.
|
||||
|
||||
Usage example:
|
||||
CalcGeoDistance(51.53323, -2.90130, 51.29442, -2.27275, duKilometers, esEllipsoid);
|
||||
}
|
||||
function CalcGeoDistance(Lat1, Lon1, Lat2, Lon2: double;
|
||||
AUnits: TDistanceUnits = duKilometers; AShape: TEarthShape = esSphere): double;
|
||||
begin
|
||||
// Validate
|
||||
if (Lat1 < -90.0) or (Lat1 > 90.0) then exit(NaN);
|
||||
if (Lat2 < -90.0) or (Lat2 > 90.0) then exit(NaN);
|
||||
|
||||
case AShape of
|
||||
esSphere:
|
||||
Result := HaversineDist(Lat1, Lon1, Lat2, Lon2, EARTH_EQUATORIAL_RADIUS);
|
||||
esEllipsoid:
|
||||
Result := LambertsDist(Lat1, Lon1, Lat2, Lon2, EARTH_EQUATORIAL_RADIUS, EARTH_FLATTENING);
|
||||
end;
|
||||
|
||||
case AUnits of
|
||||
duMeters: ;
|
||||
duKilometers: Result := Result * 0.001;
|
||||
duMiles: Result := Result * 0.62137E-3;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ Calculate initial bearing (in °) from the start point Lat1,Lon1 to
|
||||
the end point Lat2,Lon2. No parameter checks, result normalized to 0°..360°.
|
||||
}
|
||||
function CalcBearing(Lat1, Lon1, Lat2, Lon2: Double): Double;
|
||||
var
|
||||
latFrom, latTo, lonDiff: Double;
|
||||
begin
|
||||
lonDiff := DegToRad(Lon2 - Lon1);
|
||||
latFrom := DegToRad(Lat1);
|
||||
latTo := DegToRad(Lat2);
|
||||
Result := ArcTan2(Sin(lonDiff) * Cos(latTo),
|
||||
Cos(latFrom) * Sin(latTo) - Sin(latFrom) * Cos(latTo) * Cos(lonDiff));
|
||||
Result := RadToDeg(Result);
|
||||
if Result < 0.0 then
|
||||
Result := Result + 360.0;
|
||||
end;
|
||||
|
||||
{ Calculate end point Lat2,Lon2 by given start point Lat1,Lon1, distance
|
||||
ADist (in meters) and bearing ABearing (in °). No parameter checks,
|
||||
result Lon2 normalized to -180°..180°.
|
||||
}
|
||||
procedure CalcLatLon(const Lat1, Lon1, ADist, ABearing: Double; out Lat2,
|
||||
Lon2: Double);
|
||||
var
|
||||
latFrom, lonFrom, brng, aD: Double;
|
||||
begin
|
||||
latFrom := DegToRad(Lat1);
|
||||
lonFrom := DegToRad(Lon1);
|
||||
brng := DegToRad(ABearing);
|
||||
aD := ADist / EARTH_EQUATORIAL_RADIUS;
|
||||
Lat2 := ArcSin(Sin(latFrom) * Cos(aD) + Cos(latFrom) * Sin(aD) * Cos(brng));
|
||||
Lon2 := lonFrom + ArcTan2(Sin(brng) * Sin(aD) * Cos(latFrom),
|
||||
Cos(aD) - Sin(latFrom) * Sin(Lat2));
|
||||
Lat2 := RadToDeg(Lat2);
|
||||
Lon2 := NormalizeLon(RadToDeg(Lon2));
|
||||
end;
|
||||
|
||||
{ Calculate midpoint Lat,Lon by given start point Lat1,Lon1 and end point
|
||||
Lat2,Lon2. No parameter checks, result Lon normalized to -180°..180°.
|
||||
}
|
||||
procedure CalcMidpoint(const Lat1, Lon1, Lat2, Lon2: Double; out Lat,
|
||||
Lon: Double);
|
||||
var
|
||||
latFrom, lonDiff, latTo, lonTo, Bx, By: Double;
|
||||
begin
|
||||
lonDiff := DegToRad(Lon2 - Lon1);
|
||||
latFrom := DegToRad(Lat1);
|
||||
latTo := DegToRad(Lat2);
|
||||
lonTo := DegToRad(Lon2);
|
||||
Bx := Cos(latTo) * Cos(lonDiff);
|
||||
By := Cos(latTo) * Sin(lonDiff);
|
||||
Lat := ArcTan2(Sin(latFrom) + Sin(latTo), Sqrt(Sqr(Cos(latFrom) + Bx) + Sqr(By)));
|
||||
Lon := lonTo + ArcTan2(By, Cos(latFrom) + By);
|
||||
Lat := RadToDeg(Lat);
|
||||
Lon := NormalizeLon(RadToDeg(Lon));
|
||||
end;
|
||||
|
||||
{ Calculate intermediate point Lat,Lon by given start point Lat1,Lon1, end point
|
||||
Lat2,Lon2 and fraction AFrac (0.0-1.0). No parameter checks for
|
||||
Lat1,Lon1,Lat2 and Lon2. Result Lon normalized to -180°..180°.
|
||||
}
|
||||
procedure CalcIntermedPoint(const Lat1, Lon1, Lat2, Lon2, AFrac: Double; out
|
||||
Lat, Lon: Double);
|
||||
var
|
||||
latFrom, lonFrom, latTo, lonTo: Double;
|
||||
A, B, aD, X, Y, Z: Double;
|
||||
begin
|
||||
if (Lat1 = Lat2) and (Lon1 = Lon2) or (AFrac < 0.001) then
|
||||
begin
|
||||
Lat := Lat1;
|
||||
Lon := Lon1;
|
||||
Exit;
|
||||
end;
|
||||
if AFrac > 0.999 then
|
||||
begin
|
||||
Lat := Lat2;
|
||||
Lon := Lon2;
|
||||
Exit;
|
||||
end;
|
||||
aD := CalcGeoDistance(Lat1, Lon1, Lat2, Lon2) / EARTH_EQUATORIAL_RADIUS;
|
||||
latFrom := DegToRad(Lat1);
|
||||
lonFrom := DegToRad(Lon1);
|
||||
latTo := DegToRad(Lat2);
|
||||
lonTo := DegToRad(Lon2);
|
||||
A := Sin((1.0 - AFrac) * aD) / Sin(aD);
|
||||
B := Sin(AFrac * aD) / Sin(aD);
|
||||
X := A * Cos(latFrom) * Cos(lonFrom) + B * Cos(latTo) * Cos(lonTo);
|
||||
Y := A * Cos(latFrom) * Sin(lonFrom) + B * Cos(latTo) * Sin(lonTo);
|
||||
Z := A * Sin(latFrom) + B * Sin(latTo);
|
||||
Lat := ArcTan2(Z, Sqrt(Sqr(X) + Sqr(Y)));
|
||||
Lon := ArcTan2(Y, X);
|
||||
Lat := RadToDeg(Lat);
|
||||
Lon := NormalizeLon(RadToDeg(Lon));
|
||||
end;
|
||||
|
||||
function NormalizeLon(const Lon: Double): Double;
|
||||
begin
|
||||
if InRange(Lon, -180.0, 180.0)
|
||||
then Result := Lon
|
||||
else Result := FMod(Lon + 540.0, 360.0) - 180.0;
|
||||
end;
|
||||
|
||||
{ Converts an angle given as degrees, minutes and seconds to a single
|
||||
floating point degrees value. }
|
||||
function DMSToDeg(Deg, Min: Word; Sec: Double): Double;
|
||||
begin
|
||||
Result := Deg + Min/60.0 + Sec/3600.0;
|
||||
end;
|
||||
|
||||
procedure SplitGps(AValue: Double; out ADegs, AMins: Double);
|
||||
begin
|
||||
AValue := abs(AValue);
|
||||
AMins := frac(AValue) * 60;
|
||||
if abs(AMins - 60) < 1E-3 then
|
||||
begin
|
||||
AMins := 0;
|
||||
ADegs := trunc(AValue) + 1;
|
||||
end else
|
||||
ADegs := trunc(AValue);
|
||||
if AValue < 0 then
|
||||
ADegs := -ADegs;
|
||||
end;
|
||||
|
||||
procedure SplitGps(AValue: Double; out ADegs, AMins, ASecs: Double);
|
||||
begin
|
||||
SplitGps(AValue, ADegs, AMins);
|
||||
ASecs := frac(AMins) * 60;
|
||||
AMins := trunc(AMins);
|
||||
if abs(ASecs - 60) < 1E-3 then
|
||||
begin
|
||||
ASecs := 0;
|
||||
AMins := AMins + 1;
|
||||
if abs(AMins - 60) < 1e-3 then
|
||||
begin
|
||||
AMins := 0;
|
||||
ADegs := ADegs + 1;
|
||||
end;
|
||||
end;
|
||||
if AValue < 0 then
|
||||
ADegs := -ADegs;
|
||||
end;
|
||||
|
||||
function GPSToDMS(Angle: Double): string;
|
||||
begin
|
||||
Result := GPSToDMS(Angle, DefaultFormatSettings);
|
||||
end;
|
||||
|
||||
function GPSToDMS(Angle: Double; AFormatSettings: TFormatSettings): string;
|
||||
var
|
||||
deg, min, sec: Double;
|
||||
begin
|
||||
SplitGPS(Angle, deg, min, sec);
|
||||
Result := Format('%.0f° %.0f'' %.*f"', [deg, min, DMS_Decimals, sec], AFormatSettings);
|
||||
end;
|
||||
|
||||
function LatToStr(ALatitude: Double; DMS: Boolean): String;
|
||||
begin
|
||||
Result := LatToStr(ALatitude, DMS, DefaultFormatSettings);
|
||||
end;
|
||||
|
||||
function LatToStr(ALatitude: Double; DMS: Boolean; AFormatSettings: TFormatSettings): String;
|
||||
begin
|
||||
if DMS then
|
||||
Result := GPSToDMS(abs(ALatitude), AFormatSettings)
|
||||
else
|
||||
Result := Format('%.6f°',[abs(ALatitude)], AFormatSettings);
|
||||
if ALatitude > 0 then
|
||||
Result := Result + ' N'
|
||||
else
|
||||
if ALatitude < 0 then
|
||||
Result := Result + ' S';
|
||||
end;
|
||||
|
||||
function LonToStr(ALongitude: Double; DMS: Boolean): String;
|
||||
begin
|
||||
Result := LonToStr(ALongitude, DMS, DefaultFormatSettings);
|
||||
end;
|
||||
|
||||
function LonToStr(ALongitude: Double; DMS: Boolean; AFormatSettings: TFormatSettings): String;
|
||||
begin
|
||||
if DMS then
|
||||
Result := GPSToDMS(abs(ALongitude), AFormatSettings)
|
||||
else
|
||||
Result := Format('%.6f°', [abs(ALongitude)], AFormatSettings);
|
||||
if ALongitude > 0 then
|
||||
Result := Result + ' E'
|
||||
else if ALongitude < 0 then
|
||||
Result := Result + ' W';
|
||||
end;
|
||||
|
||||
{ Combines up to three parts of a GPS coordinate string (degrees, minutes, seconds)
|
||||
to a floating-point degree value. The parts are separated by non-numeric
|
||||
characters:
|
||||
|
||||
three parts ---> d m s ---> d and m must be integer, s can be float
|
||||
two parts ---> d m ---> d must be integer, s can be float
|
||||
one part ---> d ---> d can be float
|
||||
|
||||
Each part can exhibit a unit identifier, such as °, ', or ". BUT: they are
|
||||
ignored. This means that an input string 50°30" results in the output value 50.5
|
||||
although the second part is marked as seconds, not minutes!
|
||||
|
||||
Hemisphere suffixes ('N', 'S', 'E', 'W') are supported at the end of the input string.
|
||||
}
|
||||
function TryStrToGps(const AValue: String; out ADeg: Double): Boolean;
|
||||
const
|
||||
NUMERIC_CHARS = ['0'..'9', '.', ',', '-', '+'];
|
||||
var
|
||||
mins, secs: Double;
|
||||
i, j, len: Integer;
|
||||
n: Integer;
|
||||
s: String = '';
|
||||
res: Integer;
|
||||
sgn: Double;
|
||||
begin
|
||||
Result := false;
|
||||
|
||||
ADeg := NaN;
|
||||
mins := 0;
|
||||
secs := 0;
|
||||
|
||||
if AValue = '' then
|
||||
exit;
|
||||
|
||||
len := Length(AValue);
|
||||
i := len;
|
||||
while (i >= 1) and (AValue[i] = ' ') do dec(i);
|
||||
sgn := 1.0;
|
||||
if (AValue[i] in ['S', 's', 'W', 'w']) then sgn := -1;
|
||||
|
||||
// skip leading non-numeric characters
|
||||
i := 1;
|
||||
while (i <= len) and not (AValue[i] in NUMERIC_CHARS) do
|
||||
inc(i);
|
||||
|
||||
// extract first value: degrees
|
||||
SetLength(s, len);
|
||||
j := 1;
|
||||
n := 0;
|
||||
while (i <= len) and (AValue[i] in NUMERIC_CHARS) do begin
|
||||
if AValue[i] = ',' then s[j] := '.' else s[j] := AValue[i];
|
||||
inc(i);
|
||||
inc(j);
|
||||
inc(n);
|
||||
end;
|
||||
if n > 0 then begin
|
||||
SetLength(s, n);
|
||||
val(s, ADeg, res);
|
||||
if res <> 0 then
|
||||
exit;
|
||||
end;
|
||||
|
||||
// skip non-numeric characters between degrees and minutes
|
||||
while (i <= len) and not (AValue[i] in NUMERIC_CHARS) do
|
||||
inc(i);
|
||||
|
||||
// extract second value: minutes
|
||||
SetLength(s, len);
|
||||
j := 1;
|
||||
n := 0;
|
||||
while (i <= len) and (AValue[i] in NUMERIC_CHARS) do begin
|
||||
if AValue[i] = ',' then s[j] := '.' else s[j] := AValue[i];
|
||||
inc(i);
|
||||
inc(j);
|
||||
inc(n);
|
||||
end;
|
||||
if n > 0 then begin
|
||||
SetLength(s, n);
|
||||
val(s, mins, res);
|
||||
if (res <> 0) or (mins < 0) then
|
||||
exit;
|
||||
end;
|
||||
|
||||
// skip non-numeric characters between minutes and seconds
|
||||
while (i <= len) and not (AValue[i] in NUMERIC_CHARS) do
|
||||
inc(i);
|
||||
|
||||
// extract third value: seconds
|
||||
SetLength(s, len);
|
||||
j := 1;
|
||||
n := 0;
|
||||
while (i <= len) and (AValue[i] in NUMERIC_CHARS) do begin
|
||||
if AValue[i] = ',' then s[j] := '.' else s[j] := AValue[i];
|
||||
inc(i);
|
||||
inc(j);
|
||||
inc(n);
|
||||
end;
|
||||
if n > 0 then begin
|
||||
SetLength(s, n);
|
||||
val(s, secs, res);
|
||||
if (res <> 0) or (secs < 0) then
|
||||
exit;
|
||||
end;
|
||||
|
||||
// If the string contains seconds then minutes and deegrees must be integers
|
||||
if (secs <> 0) and ((frac(ADeg) > 0) or (frac(mins) > 0)) then
|
||||
exit;
|
||||
// If the string does not contain seconds then degrees must be integer.
|
||||
if (secs = 0) and (mins <> 0) and (frac(ADeg) > 0) then
|
||||
exit;
|
||||
|
||||
// If the string contains minutes, but no seconds, then the degrees must be integer.
|
||||
Result := (mins >= 0) and (mins < 60) and (secs >= 0) and (secs < 60);
|
||||
|
||||
// A similar check should be made for the degrees range, but since this is
|
||||
// different for latitude and longitude the check is skipped here.
|
||||
if Result then
|
||||
ADeg := sgn * (abs(ADeg) + mins / 60 + secs / 3600);
|
||||
end;
|
||||
|
||||
{ Convert Lat/Lon string to degrees.
|
||||
|
||||
Recognized formats:
|
||||
|
||||
Degrees, Minutes and Seconds:
|
||||
DDD°MM'SS.S"
|
||||
32°18'23.1"N 122°36'52.5"W
|
||||
|
||||
Degrees and Decimal Minutes:
|
||||
DDD° MM.MMM'
|
||||
32°18.385'N 122°36.875'W
|
||||
|
||||
Decimal Degrees:
|
||||
DDD.DDDDD°
|
||||
32.30642°N 122.61458°W
|
||||
+32.30642 -122.61458
|
||||
}
|
||||
function TryStrDMSToDeg(const AValue: String; out ADeg: Double): Boolean;
|
||||
const
|
||||
NUMERIC_CHARS = ['0'..'9', '.', ',', '-', '+'];
|
||||
WS_CHARS = [' '];
|
||||
var
|
||||
I, Len, N: Integer;
|
||||
S: String;
|
||||
D, Minutes, Seconds: Double;
|
||||
R: Word;
|
||||
Last, Neg: Boolean;
|
||||
|
||||
function EOL: Boolean; inline;
|
||||
begin
|
||||
Result := Len < I;
|
||||
end;
|
||||
|
||||
procedure SkipWS; inline;
|
||||
begin
|
||||
while not EOL and (AValue[I] in WS_CHARS) do
|
||||
Inc(I);
|
||||
end;
|
||||
|
||||
function NextNum: String;
|
||||
begin
|
||||
Result := '';
|
||||
SkipWS;
|
||||
while not EOL and (AValue[I] in NUMERIC_CHARS) do
|
||||
begin
|
||||
if AValue[I] = ','
|
||||
then Result := Result + '.'
|
||||
else Result := Result + AValue[I];
|
||||
Inc(I);
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
Result := False;
|
||||
ADeg := NaN;
|
||||
Len := Length(AValue);
|
||||
I := 1;
|
||||
|
||||
// Degrees
|
||||
S := NextNum;
|
||||
if S = '' then
|
||||
Exit;
|
||||
Val(S, ADeg, R);
|
||||
if R > 0 then
|
||||
Exit;
|
||||
|
||||
// It must be the only part if negative or fractional
|
||||
Neg := ADeg < 0.0;
|
||||
Last := Neg or (Frac(ADeg) > 0.0);
|
||||
|
||||
// Eat the degree symbol if present
|
||||
if not EOL and (Utf8CodePointLen(@AValue[I], 2, False) = 2)
|
||||
and (AValue[I] = #$c2) and (AValue[I + 1] = #$b0)
|
||||
then
|
||||
Inc(I, 2);
|
||||
|
||||
Minutes := 0.0;
|
||||
Seconds := 0.0;
|
||||
|
||||
N := 1;
|
||||
while not (EOL or Last) and (N < 3) do
|
||||
begin
|
||||
S := NextNum;
|
||||
if S = '' then
|
||||
Break
|
||||
else
|
||||
begin
|
||||
Val(S, D, R);
|
||||
// Invalid part or negative one
|
||||
if (R > 0) or (D < 0.0) then
|
||||
Exit;
|
||||
// No more parts when fractional
|
||||
Last := Frac(D) > 0.0;
|
||||
if not EOL then
|
||||
case AValue[I] of
|
||||
'''': // Munutes suffix
|
||||
begin
|
||||
Minutes := D;
|
||||
Inc(I); // Eat the '
|
||||
end;
|
||||
'"': // Seconds suffix
|
||||
begin
|
||||
Seconds := D;
|
||||
Last := True; // Last part
|
||||
Inc(I); // Eat the "
|
||||
end;
|
||||
otherwise
|
||||
if N = 1
|
||||
then Minutes := D
|
||||
else Seconds := D;
|
||||
end;
|
||||
end;
|
||||
Inc(N);
|
||||
end;
|
||||
|
||||
// Merge parts
|
||||
ADeg := ADeg + Minutes / 60 + Seconds / 3600;
|
||||
|
||||
// Check for N-S and E-W designators
|
||||
SkipWS;
|
||||
if not (EOL or Neg) and (AValue[I] in ['S', 's', 'W', 'w', 'N', 'n', 'E', 'e']) then
|
||||
begin
|
||||
if AValue[I] in ['S', 's', 'W', 'w']
|
||||
then ADeg := -1 * ADeg;
|
||||
Inc(I);
|
||||
end;
|
||||
SkipWS;
|
||||
|
||||
// It must be entirely consumed
|
||||
Result := EOL;
|
||||
end;
|
||||
|
||||
|
||||
end.
|
||||
|
@ -16,7 +16,8 @@ unit mvGpsObj;
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, Graphics, fgl, mvtypes, contnrs, syncobjs;
|
||||
Classes, SysUtils, Graphics, fgl, contnrs, syncobjs,
|
||||
mvTypes, mvGeoMath;
|
||||
|
||||
const
|
||||
NO_ELE = -10000000;
|
||||
@ -1013,6 +1014,21 @@ begin
|
||||
Result := FDateTime <> NO_DATE;
|
||||
end;
|
||||
|
||||
function TGPSPoint.DistanceInKmFrom(OtherPt: TGPSPoint;
|
||||
UseElevation: Boolean = true): Double;
|
||||
var
|
||||
lat1, lon1, lat2, lon2: Double;
|
||||
dElev: Double;
|
||||
begin
|
||||
Result := CalcGeoDistance(Lat, Lon, OtherPt.Lat, OtherPt.Lon, duKilometers, esEllipsoid);
|
||||
if UseElevation and HasElevation and OtherPt.HasElevation and (FElevation <> OtherPt.Elevation) then
|
||||
begin
|
||||
dElev := (FElevation - OtherPt.Elevation) * 0.001; // Elevation is given in meters
|
||||
Result := sqrt(sqr(dElev) + sqr(Result));
|
||||
end;
|
||||
end;
|
||||
|
||||
(*
|
||||
function TGPSPoint.DistanceInKmFrom(OtherPt: TGPSPoint;
|
||||
UseElevation: boolean = true): double;
|
||||
var
|
||||
@ -1031,7 +1047,13 @@ begin
|
||||
t3 := cos(lon1 - lon2);
|
||||
t4 := t2 * t3;
|
||||
t5 := t1 + t4;
|
||||
rad_dist := arctan(-t5/sqrt(-t5 * t5 +1)) + 2 * arctan(1);
|
||||
if t5 >= 1.0 then
|
||||
rad_dist := 0.0
|
||||
else
|
||||
if t5 <= 1.0 then
|
||||
rad_dist := pi
|
||||
else
|
||||
rad_dist := arctan(-t5/sqrt(-t5 * t5 + 1)) + 2 * arctan(1);
|
||||
result := (rad_dist * 3437.74677 * 1.1508) * 1.6093470878864446;
|
||||
if UseElevation and (FElevation <> OtherPt.FElevation) then
|
||||
if (HasElevation) and (OtherPt.HasElevation) then
|
||||
@ -1041,6 +1063,7 @@ begin
|
||||
Result := sqrt(DiffEle*DiffEle + result*result);
|
||||
end;
|
||||
end;
|
||||
*)
|
||||
|
||||
procedure TGPSPoint.MoveTo(ALon, ALat: Double; AElevation: double = NO_ELE;
|
||||
ADateTime: TDateTime = NO_DATE);
|
||||
|
@ -29,8 +29,8 @@ interface
|
||||
uses
|
||||
Classes, SysUtils, Controls, GraphType, Graphics, FPImage, IntfGraphics,
|
||||
Forms, ImgList, LCLVersion, fgl,
|
||||
MvTypes, MvGPSObj, MvEngine, MvMapProvider, MvDownloadEngine, MvDrawingEngine,
|
||||
mvCache, mvExtraData;
|
||||
MvTypes, MvGeoMath, MvGPSObj, MvCache, MvExtraData, MvEngine, MvMapProvider,
|
||||
MvDownloadEngine, MvDrawingEngine;
|
||||
|
||||
Type
|
||||
|
||||
|
@ -78,8 +78,9 @@ procedure Register;
|
||||
implementation
|
||||
|
||||
uses
|
||||
Dialogs, IDEWindowIntf, mvMapViewer, mvGpsObj, mvLayersPropEditForm, mvEngine,
|
||||
StrUtils;
|
||||
Dialogs, IDEWindowIntf,
|
||||
StrUtils,
|
||||
mvGeoMath, mvMapViewer, mvGpsObj, mvLayersPropEditForm, mvEngine;
|
||||
|
||||
const
|
||||
NONE = '(none)';
|
||||
|
@ -63,6 +63,8 @@ Type
|
||||
function Union(const Area: TRealArea): TRealArea;
|
||||
end;
|
||||
|
||||
function RealPoint(Lat, Lon: Double): TRealPoint;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
@ -276,6 +278,12 @@ begin
|
||||
Self.Lat := RadToDeg(AValue);
|
||||
end;
|
||||
|
||||
function RealPoint(Lat, Lon: Double): TRealPoint;
|
||||
begin
|
||||
Result.Lon := Lon;
|
||||
Result.Lat := Lat;
|
||||
end;
|
||||
|
||||
|
||||
{ TRealArea
|
||||
|
||||
|
@ -8,7 +8,6 @@
|
||||
<Title Value="mapviewer_tests"/>
|
||||
<ResourceType Value="res"/>
|
||||
<UseXPManifest Value="True"/>
|
||||
<Icon Value="0"/>
|
||||
</General>
|
||||
<BuildModes>
|
||||
<Item Name="Default" Default="True"/>
|
||||
@ -41,7 +40,7 @@
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit>
|
||||
<Unit>
|
||||
<Filename Value="mvtests_engine.pas"/>
|
||||
<Filename Value="mvtests_geomath.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit>
|
||||
</Units>
|
||||
|
@ -4,7 +4,7 @@ program mapviewer_tests;
|
||||
|
||||
uses
|
||||
Interfaces, Forms, GuiTestRunner,
|
||||
mvtests_engine, mvtests_types;
|
||||
mvtests_geomath, mvtests_types;
|
||||
|
||||
{$R *.res}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
unit mvtests_engine;
|
||||
unit mvtests_geomath;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
@ -8,7 +8,7 @@ uses
|
||||
Classes, SysUtils, fpcunit, testutils, testregistry;
|
||||
|
||||
type
|
||||
TMvTests_Engine= class(TTestCase)
|
||||
TMvTests_GeoMath = class(TTestCase)
|
||||
published
|
||||
procedure Test_Distance;
|
||||
procedure Test_LatToStr_DMS;
|
||||
@ -22,7 +22,7 @@ type
|
||||
implementation
|
||||
|
||||
uses
|
||||
Math, mvEngine;
|
||||
Math, mvGeoMath;
|
||||
|
||||
type
|
||||
TDistanceRec = record
|
||||
@ -94,7 +94,7 @@ const
|
||||
var
|
||||
PointFormatsettings: TFormatSettings;
|
||||
|
||||
procedure TMvTests_Engine.Test_Distance;
|
||||
procedure TMvTests_GeoMath.Test_Distance;
|
||||
const
|
||||
TOLERANCE = 2;
|
||||
RADIUS = 6378; // Earth radius in km, as used by the references
|
||||
@ -110,7 +110,7 @@ begin
|
||||
);
|
||||
end;
|
||||
|
||||
procedure TMvTests_Engine.Test_LatToStr_Deg;
|
||||
procedure TMvTests_GeoMath.Test_LatToStr_Deg;
|
||||
const
|
||||
NO_DMS = false;
|
||||
var
|
||||
@ -125,7 +125,7 @@ begin
|
||||
);
|
||||
end;
|
||||
|
||||
procedure TMvTests_Engine.Test_LatToStr_DMS;
|
||||
procedure TMvTests_GeoMath.Test_LatToStr_DMS;
|
||||
const
|
||||
NEED_DMS = true;
|
||||
var
|
||||
@ -140,7 +140,7 @@ begin
|
||||
);
|
||||
end;
|
||||
|
||||
procedure TMvTests_Engine.Test_LonToStr_Deg;
|
||||
procedure TMvTests_GeoMath.Test_LonToStr_Deg;
|
||||
const
|
||||
NO_DMS = false;
|
||||
var
|
||||
@ -155,7 +155,7 @@ begin
|
||||
);
|
||||
end;
|
||||
|
||||
procedure TMvTests_Engine.Test_LonToStr_DMS;
|
||||
procedure TMvTests_GeoMath.Test_LonToStr_DMS;
|
||||
const
|
||||
NEED_DMS = true;
|
||||
var
|
||||
@ -170,7 +170,7 @@ begin
|
||||
);
|
||||
end;
|
||||
|
||||
procedure TMvTests_Engine.Test_SplitGPS;
|
||||
procedure TMvTests_GeoMath.Test_SplitGPS;
|
||||
const
|
||||
TOLERANCE = 1e-5;
|
||||
var
|
||||
@ -218,7 +218,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMvTests_Engine.Test_ZoomFactor;
|
||||
procedure TMvTests_GeoMath.Test_ZoomFactor;
|
||||
var
|
||||
z: Integer;
|
||||
f: Extended;
|
||||
@ -236,6 +236,6 @@ initialization
|
||||
PointFormatSettings.DecimalSeparator := '.';
|
||||
DMS_Decimals := 4;
|
||||
|
||||
RegisterTest(TMvTests_Engine);
|
||||
RegisterTest(TMvTests_GeoMath);
|
||||
end.
|
||||
|
@ -9,7 +9,7 @@ uses
|
||||
|
||||
type
|
||||
|
||||
TMvTestsArea= class(TTestCase)
|
||||
TMvTests_Area= class(TTestCase)
|
||||
published
|
||||
procedure Test_PointInArea;
|
||||
procedure Test_Intersection;
|
||||
@ -28,7 +28,7 @@ begin
|
||||
]);
|
||||
end;
|
||||
|
||||
procedure TMvTestsArea.Test_PointInArea;
|
||||
procedure TMvTests_Area.Test_PointInArea;
|
||||
var
|
||||
counter: Integer;
|
||||
a: TRealArea;
|
||||
@ -123,7 +123,7 @@ begin
|
||||
);
|
||||
end;
|
||||
|
||||
procedure TMvTestsArea.Test_Union;
|
||||
procedure TMvTests_Area.Test_Union;
|
||||
var
|
||||
counter: Integer;
|
||||
a, b, expected, actual: TRealArea;
|
||||
@ -298,7 +298,7 @@ begin
|
||||
);
|
||||
end;
|
||||
|
||||
procedure TMvTestsArea.Test_Intersection;
|
||||
procedure TMvTests_Area.Test_Intersection;
|
||||
var
|
||||
counter: Integer;
|
||||
a, b, expected, actual: TRealArea;
|
||||
@ -430,7 +430,7 @@ end;
|
||||
|
||||
|
||||
initialization
|
||||
RegisterTest(TMvTestsArea);
|
||||
RegisterTest(TMvTests_Area);
|
||||
|
||||
end.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user