LazMapViewer: Add GreatCirclePainterPlugin by Ekkehard Domning. Refactor some calculation routines in mvGeoMath
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@9609 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
parent
320d413df5
commit
06b87dfade
@ -0,0 +1,154 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<CONFIG>
|
||||
<ProjectOptions>
|
||||
<Version Value="12"/>
|
||||
<PathDelim Value="\"/>
|
||||
<General>
|
||||
<SessionStorage Value="InProjectDir"/>
|
||||
<Title Value="greatcircle_demo"/>
|
||||
<Scaled Value="True"/>
|
||||
<ResourceType Value="res"/>
|
||||
<UseXPManifest Value="True"/>
|
||||
<XPManifest>
|
||||
<DpiAware Value="True"/>
|
||||
</XPManifest>
|
||||
<Icon Value="0"/>
|
||||
</General>
|
||||
<BuildModes>
|
||||
<Item Name="Default" Default="True"/>
|
||||
<Item Name="Debug">
|
||||
<CompilerOptions>
|
||||
<Version Value="11"/>
|
||||
<PathDelim Value="\"/>
|
||||
<Target>
|
||||
<Filename Value="greatcircle_demo"/>
|
||||
</Target>
|
||||
<SearchPaths>
|
||||
<IncludeFiles Value="$(ProjOutDir)"/>
|
||||
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
|
||||
</SearchPaths>
|
||||
<Parsing>
|
||||
<SyntaxOptions>
|
||||
<IncludeAssertionCode Value="True"/>
|
||||
</SyntaxOptions>
|
||||
</Parsing>
|
||||
<CodeGeneration>
|
||||
<Checks>
|
||||
<IOChecks Value="True"/>
|
||||
<RangeChecks Value="True"/>
|
||||
<OverflowChecks Value="True"/>
|
||||
<StackChecks Value="True"/>
|
||||
</Checks>
|
||||
<VerifyObjMethodCallValidity Value="True"/>
|
||||
</CodeGeneration>
|
||||
<Linking>
|
||||
<Debugging>
|
||||
<DebugInfoType Value="dsDwarf3"/>
|
||||
<UseHeaptrc Value="True"/>
|
||||
<TrashVariables Value="True"/>
|
||||
<UseExternalDbgSyms Value="True"/>
|
||||
</Debugging>
|
||||
<Options>
|
||||
<Win32>
|
||||
<GraphicApplication Value="True"/>
|
||||
</Win32>
|
||||
</Options>
|
||||
</Linking>
|
||||
</CompilerOptions>
|
||||
</Item>
|
||||
<Item Name="Release">
|
||||
<CompilerOptions>
|
||||
<Version Value="11"/>
|
||||
<PathDelim Value="\"/>
|
||||
<Target>
|
||||
<Filename Value="greatcircle_demo"/>
|
||||
</Target>
|
||||
<SearchPaths>
|
||||
<IncludeFiles Value="$(ProjOutDir)"/>
|
||||
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
|
||||
</SearchPaths>
|
||||
<CodeGeneration>
|
||||
<SmartLinkUnit Value="True"/>
|
||||
<Optimizations>
|
||||
<OptimizationLevel Value="3"/>
|
||||
</Optimizations>
|
||||
</CodeGeneration>
|
||||
<Linking>
|
||||
<Debugging>
|
||||
<GenerateDebugInfo Value="False"/>
|
||||
<RunWithoutDebug Value="True"/>
|
||||
</Debugging>
|
||||
<LinkSmart Value="True"/>
|
||||
<Options>
|
||||
<Win32>
|
||||
<GraphicApplication Value="True"/>
|
||||
</Win32>
|
||||
</Options>
|
||||
</Linking>
|
||||
</CompilerOptions>
|
||||
</Item>
|
||||
</BuildModes>
|
||||
<PublishOptions>
|
||||
<Version Value="2"/>
|
||||
<UseFileFilters Value="True"/>
|
||||
</PublishOptions>
|
||||
<RunParams>
|
||||
<FormatVersion Value="2"/>
|
||||
</RunParams>
|
||||
<RequiredPackages>
|
||||
<Item>
|
||||
<PackageName Value="lazMapViewerPkg"/>
|
||||
</Item>
|
||||
<Item>
|
||||
<PackageName Value="LCL"/>
|
||||
</Item>
|
||||
</RequiredPackages>
|
||||
<Units>
|
||||
<Unit>
|
||||
<Filename Value="greatcircle_demo.lpr"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit>
|
||||
<Unit>
|
||||
<Filename Value="main.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<ComponentName Value="MainForm"/>
|
||||
<HasResources Value="True"/>
|
||||
<ResourceBaseClass Value="Form"/>
|
||||
</Unit>
|
||||
</Units>
|
||||
</ProjectOptions>
|
||||
<CompilerOptions>
|
||||
<Version Value="11"/>
|
||||
<PathDelim Value="\"/>
|
||||
<Target>
|
||||
<Filename Value="greatcircle_demo"/>
|
||||
</Target>
|
||||
<SearchPaths>
|
||||
<IncludeFiles Value="$(ProjOutDir)"/>
|
||||
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
|
||||
</SearchPaths>
|
||||
<Linking>
|
||||
<Debugging>
|
||||
<DebugInfoType Value="dsDwarf3"/>
|
||||
</Debugging>
|
||||
<Options>
|
||||
<Win32>
|
||||
<GraphicApplication Value="True"/>
|
||||
</Win32>
|
||||
</Options>
|
||||
</Linking>
|
||||
</CompilerOptions>
|
||||
<Debugging>
|
||||
<Exceptions>
|
||||
<Item>
|
||||
<Name Value="EAbort"/>
|
||||
</Item>
|
||||
<Item>
|
||||
<Name Value="ECodetoolError"/>
|
||||
</Item>
|
||||
<Item>
|
||||
<Name Value="EFOpenError"/>
|
||||
</Item>
|
||||
</Exceptions>
|
||||
</Debugging>
|
||||
</CONFIG>
|
@ -0,0 +1,24 @@
|
||||
program greatcircle_demo;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
uses
|
||||
{$IFDEF UNIX}
|
||||
cthreads,
|
||||
{$ENDIF}
|
||||
{$IFDEF HASAMIGA}
|
||||
athreads,
|
||||
{$ENDIF}
|
||||
Interfaces, // this includes the LCL widgetset
|
||||
Forms, main;
|
||||
|
||||
{$R *.res}
|
||||
|
||||
begin
|
||||
RequireDerivedFormResource:=True;
|
||||
Application.Scaled:=True;
|
||||
Application.Initialize;
|
||||
Application.CreateForm(TMainForm, MainForm);
|
||||
Application.Run;
|
||||
end.
|
||||
|
@ -0,0 +1,542 @@
|
||||
object MainForm: TMainForm
|
||||
Left = 324
|
||||
Height = 493
|
||||
Top = 119
|
||||
Width = 872
|
||||
Caption = 'Great Circle Plugin Demo'
|
||||
ClientHeight = 493
|
||||
ClientWidth = 872
|
||||
LCLVersion = '4.99.0.0'
|
||||
OnActivate = FormActivate
|
||||
OnCreate = FormCreate
|
||||
object ParamsPanel: TPanel
|
||||
Left = 8
|
||||
Height = 454
|
||||
Top = 8
|
||||
Width = 200
|
||||
Align = alLeft
|
||||
BorderSpacing.Around = 8
|
||||
BevelOuter = bvNone
|
||||
ClientHeight = 454
|
||||
ClientWidth = 200
|
||||
TabOrder = 0
|
||||
object cbCyclicMap: TCheckBox
|
||||
AnchorSideLeft.Control = ParamsPanel
|
||||
AnchorSideTop.Control = ParamsPanel
|
||||
Left = 0
|
||||
Height = 19
|
||||
Top = 0
|
||||
Width = 77
|
||||
Caption = 'Cyclic Map'
|
||||
Checked = True
|
||||
State = cbChecked
|
||||
TabOrder = 0
|
||||
OnChange = cbCyclicMapChange
|
||||
end
|
||||
object cbZOrder: TComboBox
|
||||
AnchorSideLeft.Control = tbSegmentLength
|
||||
AnchorSideTop.Control = cbCyclicMap
|
||||
AnchorSideTop.Side = asrBottom
|
||||
AnchorSideRight.Control = ParamsPanel
|
||||
AnchorSideRight.Side = asrBottom
|
||||
Left = 92
|
||||
Height = 23
|
||||
Top = 27
|
||||
Width = 108
|
||||
Anchors = [akTop, akLeft, akRight]
|
||||
BorderSpacing.Top = 8
|
||||
ItemHeight = 15
|
||||
ItemIndex = 0
|
||||
Items.Strings = (
|
||||
'Canvas'
|
||||
'In front of markers'
|
||||
'Behind markers'
|
||||
)
|
||||
Style = csDropDownList
|
||||
TabOrder = 1
|
||||
Text = 'Canvas'
|
||||
OnChange = cbZOrderChange
|
||||
end
|
||||
object lblZOrder: TLabel
|
||||
AnchorSideLeft.Control = ParamsPanel
|
||||
AnchorSideTop.Control = cbZOrder
|
||||
AnchorSideTop.Side = asrCenter
|
||||
AnchorSideRight.Control = Label2
|
||||
AnchorSideRight.Side = asrBottom
|
||||
Left = 42
|
||||
Height = 15
|
||||
Top = 31
|
||||
Width = 42
|
||||
Anchors = [akTop, akRight]
|
||||
BorderSpacing.Top = 4
|
||||
Caption = 'Z-Order'
|
||||
end
|
||||
object tbSegmentLength: TTrackBar
|
||||
AnchorSideLeft.Control = Label2
|
||||
AnchorSideLeft.Side = asrBottom
|
||||
AnchorSideTop.Control = cbZOrder
|
||||
AnchorSideTop.Side = asrBottom
|
||||
AnchorSideRight.Control = ParamsPanel
|
||||
AnchorSideRight.Side = asrBottom
|
||||
Left = 92
|
||||
Height = 25
|
||||
Top = 58
|
||||
Width = 108
|
||||
Position = 0
|
||||
OnChange = tbSegmentLengthChange
|
||||
Anchors = [akTop, akLeft, akRight]
|
||||
BorderSpacing.Left = 8
|
||||
BorderSpacing.Top = 8
|
||||
TabOrder = 2
|
||||
end
|
||||
object Label2: TLabel
|
||||
AnchorSideLeft.Control = ParamsPanel
|
||||
AnchorSideTop.Control = tbSegmentLength
|
||||
Left = 0
|
||||
Height = 15
|
||||
Top = 58
|
||||
Width = 84
|
||||
Caption = 'Segment length'
|
||||
end
|
||||
object gbPresets: TGroupBox
|
||||
AnchorSideLeft.Control = ParamsPanel
|
||||
AnchorSideTop.Control = GroupBox3
|
||||
AnchorSideTop.Side = asrBottom
|
||||
AnchorSideRight.Control = ParamsPanel
|
||||
AnchorSideRight.Side = asrBottom
|
||||
Left = 0
|
||||
Height = 161
|
||||
Top = 294
|
||||
Width = 200
|
||||
Anchors = [akTop, akLeft, akRight]
|
||||
AutoSize = True
|
||||
BorderSpacing.Top = 8
|
||||
Caption = 'Presets'
|
||||
ChildSizing.LeftRightSpacing = 16
|
||||
ChildSizing.TopBottomSpacing = 8
|
||||
ChildSizing.EnlargeHorizontal = crsHomogenousChildResize
|
||||
ChildSizing.Layout = cclLeftToRightThenTopToBottom
|
||||
ChildSizing.ControlsPerLine = 1
|
||||
ClientHeight = 141
|
||||
ClientWidth = 196
|
||||
TabOrder = 6
|
||||
object btnPresetPolar: TButton
|
||||
Left = 16
|
||||
Height = 25
|
||||
Top = 8
|
||||
Width = 164
|
||||
Caption = 'Polar'
|
||||
TabOrder = 0
|
||||
OnClick = btnPresetPolarClick
|
||||
end
|
||||
object btnPreseEquator: TButton
|
||||
Left = 16
|
||||
Height = 25
|
||||
Top = 33
|
||||
Width = 164
|
||||
Caption = 'Equator'
|
||||
TabOrder = 1
|
||||
OnClick = btnPreseEquatorClick
|
||||
end
|
||||
object btnPresetPorto: TButton
|
||||
Left = 16
|
||||
Height = 25
|
||||
Top = 58
|
||||
Width = 164
|
||||
Caption = 'Porto-PoS'
|
||||
TabOrder = 2
|
||||
OnClick = btnPresetPortoClick
|
||||
end
|
||||
object btnPresetLongestSeaWay: TButton
|
||||
Left = 16
|
||||
Height = 25
|
||||
Top = 83
|
||||
Width = 164
|
||||
Caption = 'Longest sea way'
|
||||
TabOrder = 3
|
||||
OnClick = btnPresetLongestSeaWayClick
|
||||
end
|
||||
object btnLongestEarthWay: TButton
|
||||
Left = 16
|
||||
Height = 25
|
||||
Top = 108
|
||||
Width = 164
|
||||
Caption = 'Longest earth way'
|
||||
TabOrder = 4
|
||||
OnClick = btnLongestEarthWayClick
|
||||
end
|
||||
end
|
||||
object cgOptions: TCheckGroup
|
||||
AnchorSideLeft.Control = ParamsPanel
|
||||
AnchorSideTop.Control = tbSegmentLength
|
||||
AnchorSideTop.Side = asrBottom
|
||||
AnchorSideRight.Control = ParamsPanel
|
||||
AnchorSideRight.Side = asrBottom
|
||||
Left = 0
|
||||
Height = 89
|
||||
Top = 83
|
||||
Width = 200
|
||||
Anchors = [akTop, akLeft, akRight]
|
||||
AutoFill = True
|
||||
AutoSize = True
|
||||
Caption = 'Options'
|
||||
ChildSizing.LeftRightSpacing = 6
|
||||
ChildSizing.TopBottomSpacing = 6
|
||||
ChildSizing.EnlargeHorizontal = crsHomogenousChildResize
|
||||
ChildSizing.EnlargeVertical = crsHomogenousChildResize
|
||||
ChildSizing.ShrinkHorizontal = crsScaleChilds
|
||||
ChildSizing.ShrinkVertical = crsScaleChilds
|
||||
ChildSizing.Layout = cclLeftToRightThenTopToBottom
|
||||
ChildSizing.ControlsPerLine = 1
|
||||
ClientHeight = 69
|
||||
ClientWidth = 196
|
||||
Items.Strings = (
|
||||
'Mark Start'
|
||||
'Mark Center'
|
||||
'Mark Destination'
|
||||
)
|
||||
TabOrder = 3
|
||||
OnItemClick = cgOptionsItemClick
|
||||
Data = {
|
||||
03000000020202
|
||||
}
|
||||
end
|
||||
object gbOrthodromePen: TGroupBox
|
||||
AnchorSideLeft.Control = ParamsPanel
|
||||
AnchorSideTop.Control = cgOptions
|
||||
AnchorSideTop.Side = asrBottom
|
||||
AnchorSideRight.Control = ParamsPanel
|
||||
AnchorSideRight.Side = asrBottom
|
||||
Left = 0
|
||||
Height = 49
|
||||
Top = 180
|
||||
Width = 200
|
||||
Anchors = [akTop, akLeft, akRight]
|
||||
AutoSize = True
|
||||
BorderSpacing.Top = 8
|
||||
Caption = 'Orthodrome Pen'
|
||||
ClientHeight = 29
|
||||
ClientWidth = 196
|
||||
TabOrder = 4
|
||||
object lblOrthodromePenWidth: TLabel
|
||||
AnchorSideLeft.Control = gbOrthodromePen
|
||||
AnchorSideTop.Control = seOrthodromePenWidth
|
||||
AnchorSideTop.Side = asrCenter
|
||||
Left = 16
|
||||
Height = 15
|
||||
Top = 4
|
||||
Width = 32
|
||||
BorderSpacing.Left = 16
|
||||
Caption = 'Width'
|
||||
end
|
||||
object seOrthodromePenWidth: TSpinEdit
|
||||
AnchorSideLeft.Control = lblOrthodromePenWidth
|
||||
AnchorSideLeft.Side = asrBottom
|
||||
AnchorSideTop.Control = clbOrthodromePenColor
|
||||
AnchorSideTop.Side = asrCenter
|
||||
Left = 56
|
||||
Height = 23
|
||||
Top = 0
|
||||
Width = 64
|
||||
Alignment = taRightJustify
|
||||
BorderSpacing.Left = 8
|
||||
BorderSpacing.Right = 8
|
||||
BorderSpacing.Bottom = 6
|
||||
MaxValue = 10
|
||||
MinValue = 1
|
||||
TabOrder = 0
|
||||
Value = 3
|
||||
OnChange = seOrthodromePenWidthChange
|
||||
end
|
||||
object clbOrthodromePenColor: TColorButton
|
||||
AnchorSideLeft.Control = seOrthodromePenWidth
|
||||
AnchorSideLeft.Side = asrBottom
|
||||
AnchorSideTop.Control = seOrthodromePenWidth
|
||||
AnchorSideRight.Control = gbOrthodromePen
|
||||
AnchorSideRight.Side = asrBottom
|
||||
Left = 128
|
||||
Height = 25
|
||||
Top = -1
|
||||
Width = 60
|
||||
Anchors = [akLeft, akRight]
|
||||
BorderSpacing.Right = 8
|
||||
BorderSpacing.Bottom = 8
|
||||
BorderWidth = 2
|
||||
ButtonColorSize = 16
|
||||
ButtonColor = clPurple
|
||||
OnColorChanged = clbOrthodromePenColorColorChanged
|
||||
end
|
||||
end
|
||||
object GroupBox3: TGroupBox
|
||||
AnchorSideLeft.Control = ParamsPanel
|
||||
AnchorSideTop.Control = gbOrthodromePen
|
||||
AnchorSideTop.Side = asrBottom
|
||||
AnchorSideRight.Control = ParamsPanel
|
||||
AnchorSideRight.Side = asrBottom
|
||||
Left = 0
|
||||
Height = 49
|
||||
Top = 237
|
||||
Width = 200
|
||||
Anchors = [akTop, akLeft, akRight]
|
||||
AutoSize = True
|
||||
BorderSpacing.Top = 8
|
||||
Caption = 'Great Circle Pen'
|
||||
ClientHeight = 29
|
||||
ClientWidth = 196
|
||||
TabOrder = 5
|
||||
object lblGreatCirclePenWidth: TLabel
|
||||
AnchorSideLeft.Control = GroupBox3
|
||||
AnchorSideTop.Control = seGreatCirclePenWidth
|
||||
AnchorSideTop.Side = asrCenter
|
||||
Left = 16
|
||||
Height = 15
|
||||
Top = 4
|
||||
Width = 32
|
||||
BorderSpacing.Left = 16
|
||||
Caption = 'Width'
|
||||
end
|
||||
object seGreatCirclePenWidth: TSpinEdit
|
||||
AnchorSideLeft.Control = lblGreatCirclePenWidth
|
||||
AnchorSideLeft.Side = asrBottom
|
||||
AnchorSideTop.Control = GroupBox3
|
||||
Left = 56
|
||||
Height = 23
|
||||
Top = 0
|
||||
Width = 64
|
||||
Alignment = taRightJustify
|
||||
BorderSpacing.Left = 8
|
||||
BorderSpacing.Right = 8
|
||||
BorderSpacing.Bottom = 6
|
||||
MaxValue = 10
|
||||
MinValue = 1
|
||||
TabOrder = 0
|
||||
Value = 1
|
||||
OnChange = seGreatCirclePenWidthChange
|
||||
end
|
||||
object clbGreatCirclePenColor: TColorButton
|
||||
AnchorSideLeft.Control = seGreatCirclePenWidth
|
||||
AnchorSideLeft.Side = asrBottom
|
||||
AnchorSideRight.Control = GroupBox3
|
||||
AnchorSideRight.Side = asrBottom
|
||||
Left = 128
|
||||
Height = 25
|
||||
Top = 0
|
||||
Width = 60
|
||||
Anchors = [akTop, akLeft, akRight]
|
||||
BorderSpacing.Right = 8
|
||||
BorderWidth = 2
|
||||
ButtonColorSize = 16
|
||||
ButtonColor = clBlack
|
||||
OnColorChanged = clbGreatCirclePenColorColorChanged
|
||||
end
|
||||
end
|
||||
end
|
||||
object StatusBar: TStatusBar
|
||||
Left = 0
|
||||
Height = 23
|
||||
Top = 470
|
||||
Width = 872
|
||||
Panels = <
|
||||
item
|
||||
Bevel = pbRaised
|
||||
Text = 'Orthodrome (km)'
|
||||
Width = 100
|
||||
end
|
||||
item
|
||||
Width = 60
|
||||
end
|
||||
item
|
||||
Text = 'Rest (km)'
|
||||
Width = 60
|
||||
end
|
||||
item
|
||||
Width = 60
|
||||
end
|
||||
item
|
||||
Bevel = pbRaised
|
||||
Text = 'Start'
|
||||
Width = 40
|
||||
end
|
||||
item
|
||||
Width = 120
|
||||
end
|
||||
item
|
||||
Bevel = pbRaised
|
||||
Text = 'Destination'
|
||||
Width = 70
|
||||
end
|
||||
item
|
||||
Width = 120
|
||||
end
|
||||
item
|
||||
Text = 'Bearing'
|
||||
Width = 50
|
||||
end
|
||||
item
|
||||
Width = 50
|
||||
end
|
||||
item
|
||||
Bevel = pbRaised
|
||||
Text = 'Pt. Cnt'
|
||||
Width = 50
|
||||
end
|
||||
item
|
||||
Width = 50
|
||||
end
|
||||
item
|
||||
Width = 50
|
||||
end>
|
||||
SimplePanel = False
|
||||
end
|
||||
object MapPanel: TPanel
|
||||
Left = 216
|
||||
Height = 470
|
||||
Top = 0
|
||||
Width = 656
|
||||
Align = alClient
|
||||
BevelOuter = bvNone
|
||||
Caption = 'MapPanel'
|
||||
ClientHeight = 470
|
||||
ClientWidth = 656
|
||||
TabOrder = 2
|
||||
object MapView: TMapView
|
||||
Left = 0
|
||||
Height = 443
|
||||
Top = 27
|
||||
Width = 656
|
||||
Align = alClient
|
||||
Cyclic = True
|
||||
DownloadEngine = MapView.BuiltInDLE
|
||||
DrawingEngine = MapView.BuiltInDE
|
||||
Layers = <>
|
||||
Font.Color = clBlack
|
||||
MapProvider = 'OpenStreetMap Standard'
|
||||
PluginManager = MvPluginManager
|
||||
POIImages = ImageList
|
||||
end
|
||||
object lblInfo: TLabel
|
||||
Left = 6
|
||||
Height = 15
|
||||
Top = 6
|
||||
Width = 644
|
||||
Align = alTop
|
||||
Alignment = taCenter
|
||||
BorderSpacing.Around = 6
|
||||
Caption = 'Drag start or destination points with left mouse button'
|
||||
end
|
||||
end
|
||||
object MvPluginManager: TMvPluginManager
|
||||
Left = 320
|
||||
Top = 40
|
||||
object MvPluginManagerDraggableMarkerPlugin1: TDraggableMarkerPlugin
|
||||
DraggableMarkerMovedEvent = MvPluginManagerDraggableMarkerPlugin1DraggableMarkerMovedEvent
|
||||
end
|
||||
end
|
||||
object PolarPopupMenu: TPopupMenu
|
||||
Left = 248
|
||||
Top = 328
|
||||
object MenuItem7: TMenuItem
|
||||
Tag = 1
|
||||
Caption = 'Antipodes E / NZ'
|
||||
OnClick = PoleMenuItemClick
|
||||
end
|
||||
object MenuItem1: TMenuItem
|
||||
Tag = 2
|
||||
Caption = 'Start North, Dest South'
|
||||
OnClick = PoleMenuItemClick
|
||||
end
|
||||
object MenuItem2: TMenuItem
|
||||
Tag = 3
|
||||
Caption = 'Dest North, Start South'
|
||||
OnClick = PoleMenuItemClick
|
||||
end
|
||||
object MenuItem3: TMenuItem
|
||||
Tag = 4
|
||||
Caption = 'Start North, Dest free'
|
||||
OnClick = PoleMenuItemClick
|
||||
end
|
||||
object MenuItem4: TMenuItem
|
||||
Tag = 5
|
||||
Caption = 'Start South, Dest free'
|
||||
OnClick = PoleMenuItemClick
|
||||
end
|
||||
object MenuItem5: TMenuItem
|
||||
Tag = 6
|
||||
Caption = 'Dest North, Start free'
|
||||
OnClick = PoleMenuItemClick
|
||||
end
|
||||
object MenuItem6: TMenuItem
|
||||
Tag = 7
|
||||
Caption = 'Dest South, Start Free'
|
||||
OnClick = PoleMenuItemClick
|
||||
end
|
||||
end
|
||||
object ImageList: TImageList
|
||||
Height = 24
|
||||
Scaled = True
|
||||
Width = 24
|
||||
Left = 432
|
||||
Top = 40
|
||||
Bitmap = {
|
||||
4C7A0200000018000000180000003B0700000000000078DACD566D6C54551A3E
|
||||
2DADA4C114C1C50F3E5AB4884BA5441713547691163F881451A844851A2BD568
|
||||
94862EFC80988E49811A7E18D94D2C89BF201A49955ADDD276415A2A0B65DB5A
|
||||
ECCED0292DED0CC5763A9D99FB7D673A1F9D79F63DF78EAED9CD2D1430D9499E
|
||||
E4E4DEF33EE7BDCFFBCE7B1E000C93606262229D904DF803E18F49F075762291
|
||||
48C735E2AD40B1D3A2D1E83255536D82229CB60BF6E1165F4B98C31EB00F8BAA
|
||||
D8120C052B684F1EDF3B55FE6030582C6BB2BDDE571F29BC5C88BC9E3CE4D873
|
||||
90F3630EF22EE4A1D05E88E323C723B22ADB69EF9629E49DA1EBFA9F3B840E6C
|
||||
746F44BA331DAC87813908FF22FC4068279C6348FF3E1D9B7EDC848EB10EF018
|
||||
1E7B2D4D42E3A1975DB26B74B56B3552FA52C0FA89AB8FD04BB848E84E9E719E
|
||||
708621B52515F9EDF9700BEED15028B47932AD78CD4893536557CB1206F70071
|
||||
B892B89C3CC34EE84A7EC359C2698694EF52B0C3BE23A1A8CA49E2C8B2E2D783
|
||||
7A69DD581DE65D9A67E6CC79AF323C36F618BED0BF801017204C08F85CFC1C2B
|
||||
9C2B0C8D582BE13B8679CDF350375497A05A6CB3E2A73EA9DD3DB41B698E34B0
|
||||
4B1437C8B06078011C3107FEFB670FD931FF87F960DFD3BE530C694D69D8EDD8
|
||||
0D5111BFB2E277492E77517F9159472733B47F5F781F56BF3D57F698F9133F6B
|
||||
6478A9FD25B804D7A0157F8FD8132EE82900BB90D499FAA6516FB4E46F141B0D
|
||||
FDB93E9C7FCDD935E8F1F784ADF87BC55EE5D98BCF827532F30CFA8ECFA4CF2C
|
||||
F98F788F80B5D0BE93840686B5E7D6E252E0926CC53F228D74BFDEFB7AC2E8BD
|
||||
0EB30F370C6EB0E45FEF586F6AF377423D4349674962441CB960C5AF69DABE6A
|
||||
773532CF659ABDC1CFF927C307C31F6028328448226260283C049BDB06D64CEF
|
||||
4F98B9673664A2BAAF1AC45169C51F8944FEE40C383D2B3B579A7DF10FB3C733
|
||||
DA3250E028C0CEC19DD839B01305DD05C868CD30756934735FD9BA124E9FD3C3
|
||||
39ACF8E3F17826CDB343C7AE1E8BA536A79ADA9E4EF6786B72DD9CACE789FF70
|
||||
A77E9B8A5A776D8CC7728EC966442C165B48DF78A2B2B712B79FBADDE439F92B
|
||||
70AD9B4C4DD8DF1866D4CF40A5BD92EB728262B3AF67C6D1BEE557C42B3F955E
|
||||
28C5F4A6E926D7CF386EF2B26F19A67F331D25ED257CF68CF098A9CC6741144A
|
||||
2EFA2E4AF967F20D2E03DF24F135A1966155F32A38C61CB2244BA5539DFFA4E3
|
||||
6DA467D94060405ADCB418EC1833F19589450D8BD0EFEF97694F39DF7B237718
|
||||
C5CDA2B9FE979A811A64D567817DC90CF0F5D181A3D074EDAF342F67DFE81D99
|
||||
3C638E5FF6B71D701CC0CCBA99C8FC3A1355F62AD0B30E7AF7BB9BE1FED5BDF0
|
||||
7B9A8BE76DDDB6784577459CEEDE767A967B2BB893F75A2ACDF5755EC9EBE2E0
|
||||
6BFEEC56F127CFB88D788B38F8FA56F1FEE6FE47D56C92A49E1E18D086BBBAB4
|
||||
7067A716EEEF578725496B09064337E57F1445B3B7B7EB91FDFB83D8BE3D8837
|
||||
DED0B1658B86E262153B76C868695122B2ACDD90FFE9EBD370F060082525116C
|
||||
DD1AC12BAF8C63D3A6109E7B4E47418186C71F57B07CB984B23209DDDDCAF5FB
|
||||
9FD0F8CB1E8F365A55358E37DF8CE2EDB7A378EBADA871CEABAF86F1E28B21AC
|
||||
5DAB63D52A95F8652C5D2AD2D9228686D4EBF23FA4C9A9C3874389D2D228DE7B
|
||||
2F86F2F23869318177DE8919676CDE3C8EC2C220D6ACD1B0628582BC3C098B16
|
||||
09B0D9C404C54EEE7FF460695B9B8E77DF0D1B3973DE3D7B12A8AE06BABA1208
|
||||
06417318686D9D205D4278E209050F3F2C61F16281BE258086067952FF238A6A
|
||||
ED9123BC86E3D8B62D4A358D61FFFE38BCDEFFBD7B5DAE385E784133F81F7C50
|
||||
4076B61F7BF78A1045CDD2FF0C0F6BEE0F3FD4515414C26BAF458C6FA8AF8F5B
|
||||
DEEF870E8DFF92FFDCB97ED22F00B75BB1F43F83835A78D72E1DEBD7070D9DB7
|
||||
6E0DC36E4F58F29F3D1BFB45FF7BEFF563C3063F9C4EC5D2FFB85C9AB26B9786
|
||||
679ED1F1FCF341A31FCF9CB1CEBFBE3E82DC5C11F7DD17C05D77F9B071A31F7D
|
||||
7DAAA5FFF17AB5EEBD7BD504EFBDA79FD68D5EDFB72F6CC9BF7DBB6E68B36041
|
||||
0077DE39463D26243C1E7552FF5353A360F56AD9E80D7E4E7EBE86C3872354E3
|
||||
046231201A053C9E043EF9649CEA2A62E1C200EEB9C787F9F3C7F0E9A7E235FD
|
||||
CFE5CBAAA7B858C6238FC878F451997A5CC6934F2AD4B33A3EFE781C1F7D14A2
|
||||
DEE27D63EA3277AECFC8FDA9A77CE8ED55AEED7F54FD505393125BB244C0430F
|
||||
8946FD962D33B174A984254B443CF08060E4FD33F7CC995ED4D549311E7BBDFE
|
||||
E7E041896A173072CCC909E0FEFBCD755656C0E8C5BBEFF661D6AC31AAAB97FE
|
||||
23C294FD0FCD939FCACB45E2F353EFF90C8D39E79C393ECC9E3D86CC4C2FEEB8
|
||||
C38BD252DEF3EAD4FD8F2096389DAAB46E9D9FBE9FF3999C3366789191318AF4
|
||||
F451AACB181C0E459624F9C6FC8FAA970D0E2A526EAE1769691E4C9BE6414A8A
|
||||
078C8DD07F6A14FDFD8A4C7B6EDEFFD4709D460D5E0EBE3E7A94F7A27E6BFC8F
|
||||
5F6D3B7040209D3CA49107555502E8D9ADF53FA27ADE660BC42B2A8438CDC8DF
|
||||
C6FF78551707DDEBFF37FEE7DF82F5EDA1
|
||||
}
|
||||
end
|
||||
end
|
@ -0,0 +1,300 @@
|
||||
unit main;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls,
|
||||
ComCtrls, Menus, Spin,
|
||||
mvMapViewer, mvTypes, mvGPSObj, mvPluginCommon,
|
||||
mvGeoMath, mvPlugins, mvGreatCirclePainterPlugin;
|
||||
|
||||
type
|
||||
|
||||
{ TMainForm }
|
||||
|
||||
TMainForm = class(TForm)
|
||||
btnPresetPolar: TButton;
|
||||
btnPreseEquator: TButton;
|
||||
btnPresetPorto: TButton;
|
||||
btnPresetLongestSeaWay: TButton;
|
||||
btnLongestEarthWay: TButton;
|
||||
cbCyclicMap: TCheckBox;
|
||||
cgOptions: TCheckGroup;
|
||||
clbOrthodromePenColor: TColorButton;
|
||||
clbGreatCirclePenColor: TColorButton;
|
||||
cbZOrder: TComboBox;
|
||||
gbPresets: TGroupBox;
|
||||
gbOrthodromePen: TGroupBox;
|
||||
GroupBox3: TGroupBox;
|
||||
ImageList: TImageList;
|
||||
lblInfo: TLabel;
|
||||
lblZOrder: TLabel;
|
||||
Label2: TLabel;
|
||||
lblOrthodromePenWidth: TLabel;
|
||||
lblGreatCirclePenWidth: TLabel;
|
||||
MapView: TMapView;
|
||||
MenuItem1: TMenuItem;
|
||||
MenuItem2: TMenuItem;
|
||||
MenuItem3: TMenuItem;
|
||||
MenuItem4: TMenuItem;
|
||||
MenuItem5: TMenuItem;
|
||||
MenuItem6: TMenuItem;
|
||||
MenuItem7: TMenuItem;
|
||||
MvPluginManager: TMvPluginManager;
|
||||
MvPluginManagerDraggableMarkerPlugin1: TDraggableMarkerPlugin;
|
||||
ParamsPanel: TPanel;
|
||||
MapPanel: TPanel;
|
||||
PolarPopupMenu: TPopupMenu;
|
||||
seOrthodromePenWidth: TSpinEdit;
|
||||
seGreatCirclePenWidth: TSpinEdit;
|
||||
StatusBar: TStatusBar;
|
||||
tbSegmentLength: TTrackBar;
|
||||
procedure btnPresetPolarClick(Sender: TObject);
|
||||
procedure btnPreseEquatorClick(Sender: TObject);
|
||||
procedure btnPresetPortoClick(Sender: TObject);
|
||||
procedure btnPresetLongestSeaWayClick(Sender: TObject);
|
||||
procedure btnLongestEarthWayClick(Sender: TObject);
|
||||
procedure cbCyclicMapChange(Sender: TObject);
|
||||
procedure cgOptionsItemClick(Sender: TObject; Index: integer);
|
||||
procedure clbOrthodromePenColorColorChanged(Sender: TObject);
|
||||
procedure clbGreatCirclePenColorColorChanged(Sender: TObject);
|
||||
procedure cbZOrderChange(Sender: TObject);
|
||||
procedure FormActivate(Sender: TObject);
|
||||
procedure FormCreate(Sender: TObject);
|
||||
procedure PoleMenuItemClick(Sender: TObject);
|
||||
procedure MvPluginManagerDraggableMarkerPlugin1DraggableMarkerMovedEvent(
|
||||
Sender: TDraggableMarkerPlugin; AMarker: TGPSPoint;
|
||||
AOrgPosition: TRealPoint);
|
||||
procedure seOrthodromePenWidthChange(Sender: TObject);
|
||||
procedure seGreatCirclePenWidthChange(Sender: TObject);
|
||||
procedure tbSegmentLengthChange(Sender: TObject);
|
||||
private
|
||||
FActivated: Boolean;
|
||||
FGreatCirclePainterPlugin : TGreatCirclePainterPlugin;
|
||||
FStartMarker : TGpsPointOfInterest;
|
||||
FDestinationMarker : TGpsPointOfInterest;
|
||||
procedure OnGreatCirclePainterGetCoords(Sender : TGreatCirclePainterPlugin;
|
||||
var FStart, FDestination : TRealPoint);
|
||||
procedure SetMarkerPositions(const AStartLat, AStartLon, ADestLat, ADestLon : Double);
|
||||
procedure OnGreatCirclePainterPluginChange(Sender : TObject);
|
||||
public
|
||||
|
||||
end;
|
||||
|
||||
var
|
||||
MainForm: TMainForm;
|
||||
|
||||
implementation
|
||||
|
||||
{$R *.lfm}
|
||||
|
||||
{ TMainForm }
|
||||
procedure TMainForm.FormCreate(Sender: TObject);
|
||||
|
||||
function AddTraditionalMarker(const ALat, ALon: Double;
|
||||
ACaption: String; const AImgIndex : Integer = -1) : TGpsPointOfInterest;
|
||||
var
|
||||
gpsPt: TGpsPointOfInterest;
|
||||
begin
|
||||
Result := Nil;
|
||||
gpsPt := TGpsPointOfInterest.Create(ALon,ALat);
|
||||
try
|
||||
gpsPt.Name := ACaption;
|
||||
gpsPt.ImageIndex := AImgIndex;
|
||||
MapView.GPSItems.Add(gpsPt, 100);
|
||||
Result := gpsPt;
|
||||
gpsPt := Nil;
|
||||
finally
|
||||
if Assigned(gpsPt) then
|
||||
gpsPt.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
MapView.Active := true;
|
||||
|
||||
FGreatCirclePainterPlugin := TGreatCirclePainterPlugin.Create(MvPluginManager);
|
||||
MvPluginManager.PluginList.Add(FGreatCirclePainterPlugin);
|
||||
FGreatCirclePainterPlugin.ZOrder := gcpzCanvas;
|
||||
FGreatCirclePainterPlugin.OnGetStartAndDestinationCoords:=@OnGreatCirclePainterGetCoords;
|
||||
FGreatCirclePainterPlugin.OnChange := @OnGreatCirclePainterPluginChange;
|
||||
FGreatCirclePainterPlugin.MapView := MapView;
|
||||
FGreatCirclePainterPlugin.GreatCirclePen.Color:= clbGreatCirclePenColor.ButtonColor;
|
||||
FGreatCirclePainterPlugin.GreatCirclePen.Style:= psSolid;
|
||||
FGreatCirclePainterPlugin.GreatCirclePen.Width:= seGreatCirclePenWidth.Value;
|
||||
FGreatCirclePainterPlugin.OrthodromePen.Color:= clbOrthodromePenColor.ButtonColor;
|
||||
FGreatCirclePainterPlugin.OrthodromePen.Style:= psSolid;
|
||||
FGreatCirclePainterPlugin.OrthodromePen.Width:= seOrthodromePenWidth.Value;
|
||||
FStartMarker := AddTraditionalMarker(41.1578,-8.6333, 'Start',0);
|
||||
FDestinationMarker := AddTraditionalMarker(10.6722,-61.5333, 'Destination',1);
|
||||
end;
|
||||
|
||||
procedure TMainForm.SetMarkerPositions(const AStartLat, AStartLon, ADestLat, ADestLon : Double);
|
||||
begin
|
||||
FStartMarker.MoveTo(AStartLon, AStartLat);
|
||||
FDestinationMarker.MoveTo(ADestLon, ADestLat);
|
||||
MapView.Invalidate;
|
||||
end;
|
||||
|
||||
procedure TMainForm.OnGreatCirclePainterPluginChange(Sender: TObject);
|
||||
var
|
||||
s : String;
|
||||
begin
|
||||
s := Format('%1.3f',[FGreatCirclePainterPlugin.OrthodromeDistance / 1000.0]);
|
||||
StatusBar.Panels[1].Text := s;
|
||||
s := Format('%1.3f',[(EARTH_CIRCUMFERENCE-FGreatCirclePainterPlugin.OrthodromeDistance) / 1000.0]);
|
||||
StatusBar.Panels[3].Text := s;
|
||||
s := Format('%1.6f:%1.6f',[FGreatCirclePainterPlugin.StartLat,FGreatCirclePainterPlugin.StartLon]);
|
||||
StatusBar.Panels[5].Text := s;
|
||||
s := Format('%1.6f:%1.6f',[FGreatCirclePainterPlugin.DestinationLat,FGreatCirclePainterPlugin.DestinationLon]);
|
||||
StatusBar.Panels[7].Text := s;
|
||||
s := Format('%1.2f°',[FGreatCirclePainterPlugin.InitialBearing]);
|
||||
StatusBar.Panels[9].Text := s;
|
||||
StatusBar.Panels[11].Text := IntToStr(FGreatCirclePainterPlugin.GreatCirclePointsCount);
|
||||
end;
|
||||
|
||||
|
||||
procedure TMainForm.PoleMenuItemClick(Sender: TObject);
|
||||
|
||||
begin
|
||||
if Sender is TMenuItem then
|
||||
begin
|
||||
case TMenuItem(Sender).Tag of
|
||||
1 : SetMarkerPositions(42.496909,-7.026229,-42.496909,172.973771); // Antipodes Spain / New Zealand
|
||||
2 : SetMarkerPositions(90.0,20.0,-90.0,-90.0); // Both Poles, Start North
|
||||
3 : SetMarkerPositions(-90.0,40.0,90.0,-100.0); // Both Poles, Start South
|
||||
4 : SetMarkerPositions(90.0,60.0,48.8582300,2.2945500); // Start North, Dest free
|
||||
5 : SetMarkerPositions(-90.0,80.0,22.2708100,114.1497900); // Start South, Dest free
|
||||
6 : SetMarkerPositions(-33.8707000,151.2082800,90.0,-110.0); // Dest North, Start free
|
||||
7 : SetMarkerPositions(43.6439500,-79.3884000,-90.0,-120.0); // Dest South, Start free
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMainForm.cbCyclicMapChange(Sender: TObject);
|
||||
begin
|
||||
MapView.Cyclic := cbCyclicMap.Checked;
|
||||
MapView.Invalidate;
|
||||
end;
|
||||
|
||||
procedure TMainForm.cgOptionsItemClick(Sender: TObject; Index: integer);
|
||||
var
|
||||
opt : TGreatCirclePainterOptions = [];
|
||||
begin
|
||||
if cgOptions.Checked[0] then
|
||||
Include(opt,gcpoMarkStart);
|
||||
if cgOptions.Checked[1] then
|
||||
Include(opt,gcpoMarkCenter);
|
||||
if cgOptions.Checked[2] then
|
||||
Include(opt,gcpoMarkDestination);
|
||||
FGreatCirclePainterPlugin.Options := opt;
|
||||
end;
|
||||
|
||||
procedure TMainForm.clbOrthodromePenColorColorChanged(Sender: TObject);
|
||||
begin
|
||||
FGreatCirclePainterPlugin.OrthodromePen.Color := clbOrthodromePenColor.ButtonColor;
|
||||
end;
|
||||
|
||||
procedure TMainForm.clbGreatCirclePenColorColorChanged(Sender: TObject);
|
||||
begin
|
||||
FGreatCirclePainterPlugin.GreatCirclePen.Color := clbGreatCirclePenColor.ButtonColor;
|
||||
end;
|
||||
|
||||
procedure TMainForm.btnPresetPolarClick(Sender: TObject);
|
||||
begin
|
||||
PolarPopupMenu.PopUp;
|
||||
end;
|
||||
|
||||
procedure TMainForm.btnPreseEquatorClick(Sender: TObject);
|
||||
begin
|
||||
FStartMarker.MoveTo(0.0,0.0);
|
||||
FDestinationMarker.MoveTo(100.0,0.0);
|
||||
MapView.Invalidate;
|
||||
end;
|
||||
|
||||
procedure TMainForm.btnPresetPortoClick(Sender: TObject);
|
||||
begin
|
||||
FStartMarker.MoveTo(-8.6333,41.1578);
|
||||
FDestinationMarker.MoveTo(-61.5333,10.6722);
|
||||
MapView.Invalidate;
|
||||
end;
|
||||
|
||||
procedure TMainForm.btnPresetLongestSeaWayClick(Sender: TObject);
|
||||
begin
|
||||
FStartMarker.MoveTo(DMSToDeg(66,40,0),DMSToDeg(25,17,0));
|
||||
FDestinationMarker.MoveTo(DMSToDeg(162,14,0),DMSToDeg(58,37,0));
|
||||
MapView.Invalidate;
|
||||
end;
|
||||
|
||||
procedure TMainForm.btnLongestEarthWayClick(Sender: TObject);
|
||||
begin
|
||||
// 24◦33′ N, 118◦38′ E
|
||||
// 37◦2′ N, 8◦55′ W
|
||||
FStartMarker.MoveTo(DMSToDeg(118,38,0),DMSToDeg(23,33,0));
|
||||
FDestinationMarker.MoveTo(-DMSToDeg(8,55,0),DMSToDeg(37,2,0));
|
||||
MapView.Invalidate;
|
||||
end;
|
||||
|
||||
procedure TMainForm.cbZOrderChange(Sender: TObject);
|
||||
begin
|
||||
case cbZOrder.ItemIndex of
|
||||
0 : FGreatCirclePainterPlugin.ZOrder := gcpzCanvas;
|
||||
1 : FGreatCirclePainterPlugin.ZOrder := gcpzInFrontOfMarkers;
|
||||
2 : FGreatCirclePainterPlugin.ZOrder := gcpzBehindMarkers;
|
||||
end;
|
||||
MapView.Invalidate;
|
||||
end;
|
||||
|
||||
procedure TMainForm.FormActivate(Sender: TObject);
|
||||
begin
|
||||
if not FActivated then
|
||||
begin
|
||||
Constraints.MinHeight := gbPresets.Top + gbPresets.Height +
|
||||
ParamsPanel.BorderSpacing.Around * 2 + Statusbar.Height;
|
||||
Constraints.MinWidth := ParamsPanel.Width + ParamsPanel.BorderSpacing.Around * 2;
|
||||
if Height < Constraints.MinHeight then
|
||||
Height := 0;
|
||||
FActivated := true;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMainForm.MvPluginManagerDraggableMarkerPlugin1DraggableMarkerMovedEvent
|
||||
(Sender: TDraggableMarkerPlugin; AMarker: TGPSPoint; AOrgPosition: TRealPoint
|
||||
);
|
||||
begin
|
||||
FGreatCirclePainterPlugin.SetStartAndDestination(
|
||||
FStartMarker.RealPoint, FDestinationMarker.RealPoint
|
||||
);
|
||||
end;
|
||||
|
||||
procedure TMainForm.seOrthodromePenWidthChange(Sender: TObject);
|
||||
begin
|
||||
FGreatCirclePainterPlugin.OrthodromePen.Width := seOrthodromePenWidth.Value;
|
||||
end;
|
||||
|
||||
procedure TMainForm.seGreatCirclePenWidthChange(Sender: TObject);
|
||||
begin
|
||||
FGreatCirclePainterPlugin.GreatCirclePen.Width := seGreatCirclePenWidth.Value;
|
||||
end;
|
||||
|
||||
procedure TMainForm.tbSegmentLengthChange(Sender: TObject);
|
||||
const
|
||||
SegmentLengths : array[0..10] of Integer = (
|
||||
1,2,5,10,20,30,50,70,100,150,200
|
||||
);
|
||||
begin
|
||||
FGreatCirclePainterPlugin.SegmentLength := SegmentLengths[tbSegmentLength.Position];
|
||||
MapView.Invalidate;
|
||||
end;
|
||||
|
||||
procedure TMainForm.OnGreatCirclePainterGetCoords(
|
||||
Sender: TGreatCirclePainterPlugin; var FStart, FDestination: TRealPoint);
|
||||
begin
|
||||
FStart := FStartMarker.RealPoint;
|
||||
FDestination := FDestinationMarker.RealPoint;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
@ -8,7 +8,7 @@
|
||||
<Version Value="11"/>
|
||||
<SearchPaths>
|
||||
<IncludeFiles Value="source"/>
|
||||
<OtherUnitFiles Value="source;source/addons/plugins;source/addons/plugins/spreadmarkers;source/addons/plugins/grids;source/addons/plugins/scale"/>
|
||||
<OtherUnitFiles Value="source;source/addons/plugins;source/addons/plugins/spreadmarkers;source/addons/plugins/grids;source/addons/plugins/scale;source/addons/plugins/greatcircle"/>
|
||||
<UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
|
||||
</SearchPaths>
|
||||
<Other>
|
||||
@ -23,7 +23,7 @@
|
||||
FPC 3.2.0 or newer required."/>
|
||||
<License Value="Modified LGPL with linking exception, like FreePascal RTL/FCL and Lazarus LCL"/>
|
||||
<Version Minor="2" Release="7"/>
|
||||
<Files Count="33">
|
||||
<Files Count="34">
|
||||
<Item1>
|
||||
<Filename Value="source/mvcache.pas"/>
|
||||
<UnitName Value="mvCache"/>
|
||||
@ -157,6 +157,10 @@ FPC 3.2.0 or newer required."/>
|
||||
<Filename Value="source/mvengine_mapreg.inc"/>
|
||||
<Type Value="Include"/>
|
||||
</Item33>
|
||||
<Item34>
|
||||
<Filename Value="source/addons/plugins/greatcircle/mvgreatcirclepainterplugin.pas"/>
|
||||
<UnitName Value="mvGreatCirclePainterPlugin"/>
|
||||
</Item34>
|
||||
</Files>
|
||||
<CompatibilityMode Value="True"/>
|
||||
<RequiredPkgs Count="2">
|
||||
|
@ -15,7 +15,7 @@ uses
|
||||
mvMapViewerPathEditForm, mvMapViewerPathEditDsgForm, mvDLECache,
|
||||
mvPluginEditors, mvClassRegistration, mvPluginCommon, mvPlugins,
|
||||
mvspreadmarker_plugin, uInactivityAlarmTimer, mvMapGridPlugin,
|
||||
mvMapScalePlugin, LazarusPackageIntf;
|
||||
mvMapScalePlugin, mvGreatCirclePainterPlugin, LazarusPackageIntf;
|
||||
|
||||
implementation
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -69,6 +69,19 @@ begin
|
||||
Result := round(IntPower(2, AZoomLevel));
|
||||
end;
|
||||
|
||||
{ Protected version of arcin which does not crash when the argument is outside
|
||||
domain due to round-off error. }
|
||||
function SafeArcsin(x: Double): Double;
|
||||
begin
|
||||
if x >= +1.0 then
|
||||
Result := pi * 0.5
|
||||
else
|
||||
if x <= -1.0 then
|
||||
Result := -pi * 0.5
|
||||
else
|
||||
Result := arcsin(x);
|
||||
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
|
||||
}
|
||||
@ -76,24 +89,24 @@ end;
|
||||
function HaversineAngle(Lat1, Lon1, Lat2, Lon2: Double): Double;
|
||||
var
|
||||
latFrom, latTo, lonDiff: Double;
|
||||
dx, dy, dz, arg: Double;
|
||||
sinLatFrom, cosLatFrom: Double;
|
||||
sinLatTo, cosLatTo: Double;
|
||||
sinLonDiff, cosLonDiff: 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);
|
||||
SinCos(latFrom, sinLatFrom, cosLatFrom);
|
||||
SinCos(latTo, sinLatTo, cosLatTo);
|
||||
SinCos(lonDiff, sinLonDiff, cosLonDiff);
|
||||
|
||||
arg := sqrt(sqr(dx) + sqr(dy) + sqr(dz)) / 2.0;
|
||||
if arg >= 1.0 then
|
||||
Result := pi
|
||||
else
|
||||
if arg <= -1.0 then
|
||||
Result := -pi
|
||||
else
|
||||
Result := arcsin(arg) * 2.0;
|
||||
dz := sinlatFrom - sinlatTo;
|
||||
dx := coslonDiff * coslatFrom - coslatTo;
|
||||
dy := sinlonDiff * coslatFrom;
|
||||
|
||||
Result := SafeArcsin(sqrt(sqr(dx) + sqr(dy) + sqr(dz)) / 2.0) * 2.0;
|
||||
end;
|
||||
|
||||
// Angles in degrees
|
||||
@ -167,12 +180,20 @@ end;
|
||||
function CalcBearing(Lat1, Lon1, Lat2, Lon2: Double): Double;
|
||||
var
|
||||
latFrom, latTo, lonDiff: Double;
|
||||
sin_LatFrom, cos_LatFrom: Double;
|
||||
sin_LatTo, cos_LatTo: Double;
|
||||
sin_LonDiff, cos_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));
|
||||
|
||||
SinCos(lonDiff, sin_LonDiff, cos_LonDiff);
|
||||
SinCos(latFrom, sin_LatFrom, cos_LatFrom);
|
||||
SinCos(latTo, sin_LatTo, cos_LatTo);
|
||||
|
||||
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;
|
||||
@ -186,16 +207,25 @@ procedure CalcLatLon(const Lat1, Lon1, ADist, ABearing: Double; out Lat2,
|
||||
Lon2: Double);
|
||||
var
|
||||
latFrom, lonFrom, brng, aD: Double;
|
||||
sin_LatFrom, cos_LatFrom: Double;
|
||||
sin_LonFrom, cos_LonFrom: Double;
|
||||
sin_brng, cos_brng: Double;
|
||||
sin_aD, cos_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));
|
||||
|
||||
SinCos(latFrom, sin_LatFrom, cos_LatFrom);
|
||||
SinCos(lonFrom, sin_lonFrom, cos_lonFrom);
|
||||
SinCos(brng, sin_brng, cos_brng);
|
||||
SinCos(aD, sin_aD, cos_aD);
|
||||
|
||||
Lat2 := SafeArcSin(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));
|
||||
Lon2 := {%H-}NormalizeLon(RadToDeg(Lon2));
|
||||
end;
|
||||
|
||||
{ Calculate midpoint Lat,Lon by given start point Lat1,Lon1 and end point
|
||||
@ -205,6 +235,7 @@ procedure CalcMidpoint(const Lat1, Lon1, Lat2, Lon2: Double; out Lat,
|
||||
Lon: Double);
|
||||
var
|
||||
latFrom, lonDiff, latTo, lonTo, Bx, By: Double;
|
||||
sin_latFrom, cos_latFrom: Double;
|
||||
begin
|
||||
lonDiff := DegToRad(Lon2 - Lon1);
|
||||
latFrom := DegToRad(Lat1);
|
||||
@ -212,10 +243,13 @@ begin
|
||||
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);
|
||||
|
||||
SinCos(latFrom, sin_latFrom, cos_latFrom);
|
||||
|
||||
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));
|
||||
Lon := {%H-}NormalizeLon(RadToDeg(Lon));
|
||||
end;
|
||||
|
||||
{ Calculate intermediate point Lat,Lon by given start point Lat1,Lon1, end point
|
||||
@ -227,6 +261,9 @@ procedure CalcIntermedPoint(const Lat1, Lon1, Lat2, Lon2, AFrac: Double; out
|
||||
var
|
||||
latFrom, lonFrom, latTo, lonTo: Double;
|
||||
A, B, aD, X, Y, Z: Double;
|
||||
sin_latFrom, cos_latFrom: Double;
|
||||
sin_lonFrom, cos_lonFrom: Double;
|
||||
sin_latTo, cos_latTo: Double;
|
||||
begin
|
||||
if (Lat1 = Lat2) and (Lon1 = Lon2) or (AFrac < 0.001) then
|
||||
begin
|
||||
@ -245,15 +282,20 @@ begin
|
||||
lonFrom := DegToRad(Lon1);
|
||||
latTo := DegToRad(Lat2);
|
||||
lonTo := DegToRad(Lon2);
|
||||
|
||||
SinCos(latFrom, sin_LatFrom, cos_LatFrom);
|
||||
SinCos(lonFrom, sin_LonFrom, cos_lonFrom);
|
||||
SinCos(latTo, sin_latTo, cos_latTo);
|
||||
|
||||
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);
|
||||
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));
|
||||
Lon := {%H-}NormalizeLon(RadToDeg(Lon));
|
||||
end;
|
||||
|
||||
function NormalizeLon(const Lon: Double): Double;
|
||||
|
Loading…
Reference in New Issue
Block a user