kopia lustrzana https://github.com/dl2alf/AirScout
1728 wiersze
74 KiB
C#
1728 wiersze
74 KiB
C#
// AirScout Aircraft Scatter Prediction
|
|
// Copyright (C) DL2ALF
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Data;
|
|
using System.Drawing;
|
|
using System.Drawing.Drawing2D;
|
|
using System.Drawing.Imaging;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Windows;
|
|
using System.Windows.Forms;
|
|
using System.Windows.Forms.VisualStyles;
|
|
using GMap.NET;
|
|
using GMap.NET.MapProviders;
|
|
using GMap.NET.WindowsForms;
|
|
using GMap.NET.WindowsForms.Markers;
|
|
using GMap.NET.WindowsForms.ToolTips;
|
|
using System.IO;
|
|
using System.IO.Ports;
|
|
using System.Net;
|
|
using System.Net.Sockets;
|
|
using System.Threading;
|
|
using System.Globalization;
|
|
using System.Runtime.InteropServices;
|
|
using System.Reflection;
|
|
using System.Configuration;
|
|
using System.Diagnostics;
|
|
using AirScout;
|
|
using AirScout.Core;
|
|
using AirScout.Aircrafts;
|
|
using ScoutBase;
|
|
using ScoutBase.Core;
|
|
using ScoutBase.Elevation;
|
|
using ScoutBase.Stations;
|
|
using ScoutBase.Propagation;
|
|
using Newtonsoft.Json;
|
|
using Newtonsoft.Json.Linq;
|
|
using SQLiteDatabase;
|
|
using System.Xml;
|
|
using System.Xml.Serialization;
|
|
using System.Security.Cryptography;
|
|
using OxyPlot;
|
|
using OxyPlot.WindowsForms;
|
|
using OxyPlot.Series;
|
|
using OxyPlot.Axes;
|
|
using System.Data.SQLite;
|
|
|
|
namespace AirScoutViewClient
|
|
{
|
|
|
|
public partial class MapViewDlg : Form
|
|
{
|
|
|
|
// Map
|
|
// Overlays
|
|
GMapOverlay gmo_Routes = new GMapOverlay("Routes");
|
|
GMapOverlay gmo_PropagationPaths = new GMapOverlay("PropagationPaths");
|
|
GMapOverlay gmo_Objects = new GMapOverlay("Objects");
|
|
GMapOverlay gmo_Planes = new GMapOverlay("Planes");
|
|
GMapOverlay gmo_Airports = new GMapOverlay("Airports");
|
|
GMapOverlay gmo_Callsigns = new GMapOverlay("Callsigns");
|
|
GMapOverlay gmo_NearestPaths = new GMapOverlay("PropagationPaths");
|
|
GMapOverlay gmo_NearestPlanes = new GMapOverlay("Planes");
|
|
|
|
// Routes
|
|
GMapRoute gmr_FullPath;
|
|
GMapRoute gmr_VisiblePpath;
|
|
GMapRoute gmr_NearestFull;
|
|
GMapRoute gmr_NearestVisible;
|
|
|
|
// Markers
|
|
GMapMarker gmm_MyLoc;
|
|
GMapMarker gmm_DXLoc;
|
|
GMapMarker gmm_CurrentMarker;
|
|
bool isDraggingMarker;
|
|
|
|
// Bitmap indices
|
|
private int bmindex_darkorange;
|
|
private int bmindex_lightgreen;
|
|
private int bmindex_red;
|
|
private int bmindex_gray;
|
|
private int bmindex_magenta;
|
|
|
|
// charting
|
|
|
|
// path chart
|
|
PlotModel pm_Path = new PlotModel();
|
|
PlotView pv_Path = new PlotView();
|
|
LinearAxis Path_X = new LinearAxis();
|
|
LinearAxis Path_Y = new LinearAxis();
|
|
AreaSeries Path_Elevation = new AreaSeries();
|
|
LineSeries Min_H1 = new LineSeries();
|
|
LineSeries Min_H2 = new LineSeries();
|
|
LineSeries Max_H = new LineSeries();
|
|
AreaSeries Min_H = new AreaSeries();
|
|
LineSeries Planes_Hi = new LineSeries();
|
|
LineSeries Planes_Lo = new LineSeries();
|
|
|
|
// elevation chart
|
|
PlotModel pm_Elevation = new PlotModel();
|
|
PlotView pv_Elevation = new PlotView();
|
|
LinearAxis Elevation_X = new LinearAxis();
|
|
LinearAxis Elevation_Y = new LinearAxis();
|
|
AreaSeries Elevation = new AreaSeries();
|
|
LineSeries LOS = new LineSeries();
|
|
|
|
|
|
// Tooltip font
|
|
public Font ToolTipFont;
|
|
|
|
public VarConverter VC = new VarConverter();
|
|
|
|
public static LogWriter Log;
|
|
|
|
public DateTime CurrentTime;
|
|
|
|
AIRSCOUTPLAYMODE PlayMode = AIRSCOUTPLAYMODE.NONE;
|
|
|
|
CultureInfo CurrentCulture = Application.CurrentCulture;
|
|
|
|
ElevationPathDesignator EPath = null;
|
|
PropagationPathDesignator PPath = null;
|
|
|
|
SortedList<string, PlaneInfo> ActivePlanes = new SortedList<string, PlaneInfo>();
|
|
private List<string> SelectedPlanes = new List<string>();
|
|
|
|
private VIEWCLIENTSTATUS VieClientStatus = VIEWCLIENTSTATUS.NONE;
|
|
|
|
[CategoryAttribute("Directories")]
|
|
[DescriptionAttribute("Application Directory")]
|
|
public string AppDirectory
|
|
{
|
|
get
|
|
{
|
|
return Application.StartupPath.TrimEnd(Path.DirectorySeparatorChar).Replace('\\', Path.DirectorySeparatorChar);
|
|
}
|
|
}
|
|
|
|
[CategoryAttribute("Directories")]
|
|
[DescriptionAttribute("Local Application Data Directory")]
|
|
public string AppDataDirectory
|
|
{
|
|
get
|
|
{
|
|
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), Application.CompanyName, Application.ProductName).TrimEnd(Path.DirectorySeparatorChar);
|
|
}
|
|
}
|
|
|
|
[CategoryAttribute("Directories")]
|
|
[DescriptionAttribute("Logfile Directory")]
|
|
public string LogDirectory
|
|
{
|
|
get
|
|
{
|
|
// get Property
|
|
string logdir = Properties.Settings.Default.Log_Directory;
|
|
// replace Windows/Linux directory spearator chars
|
|
logdir = logdir.Replace('\\', Path.DirectorySeparatorChar);
|
|
logdir = logdir.Replace('/', Path.DirectorySeparatorChar);
|
|
// set to default value if empty
|
|
if (String.IsNullOrEmpty(logdir))
|
|
logdir = "Log";
|
|
// replace variables, if any
|
|
logdir = VC.ReplaceAllVars(logdir);
|
|
// remove directory separator chars at begin and end
|
|
logdir = logdir.TrimStart(Path.DirectorySeparatorChar);
|
|
logdir = logdir.TrimEnd(Path.DirectorySeparatorChar);
|
|
// fully qualify path
|
|
if (!logdir.Contains(Path.VolumeSeparatorChar))
|
|
logdir = Path.Combine(AppDataDirectory, logdir);
|
|
return logdir;
|
|
}
|
|
}
|
|
|
|
[CategoryAttribute("Directories")]
|
|
[DescriptionAttribute("Tempfile Directory")]
|
|
public string TmpDirectory
|
|
{
|
|
get
|
|
{
|
|
// get Property
|
|
string tmpdir = Properties.Settings.Default.Tmp_Directory;
|
|
// replace Windows/Linux directory spearator chars
|
|
tmpdir = tmpdir.Replace('\\', Path.DirectorySeparatorChar);
|
|
tmpdir = tmpdir.Replace('/', Path.DirectorySeparatorChar);
|
|
// set to default value if empty
|
|
if (String.IsNullOrEmpty(tmpdir))
|
|
tmpdir = "Tmp";
|
|
// replace variables, if any
|
|
tmpdir = VC.ReplaceAllVars(tmpdir);
|
|
// remove directory separator chars at begin and end
|
|
tmpdir = tmpdir.TrimStart(Path.DirectorySeparatorChar);
|
|
tmpdir = tmpdir.TrimEnd(Path.DirectorySeparatorChar);
|
|
// fully qualify path
|
|
if (!tmpdir.Contains(Path.VolumeSeparatorChar))
|
|
tmpdir = Path.Combine(AppDataDirectory, tmpdir);
|
|
return tmpdir;
|
|
}
|
|
}
|
|
|
|
public MapViewDlg()
|
|
{
|
|
Application.CurrentCulture = CultureInfo.InvariantCulture;
|
|
// gets an instance of a LogWriter
|
|
Log = LogWriter.Instance;
|
|
InitializeComponent();
|
|
|
|
}
|
|
|
|
private void Say (string msg)
|
|
{
|
|
if (tsl_Status.Text != msg)
|
|
{
|
|
tsl_Status.Text = msg;
|
|
ss_Main.Refresh();
|
|
}
|
|
}
|
|
|
|
#region Initialization
|
|
|
|
private void InitializeSettings()
|
|
{
|
|
Say("Getting settings...");
|
|
if (!SettingsFromJSON())
|
|
return;
|
|
// initialize map
|
|
// setting User Agent to fix Open Street Map issue 2016-09-20
|
|
GMap.NET.MapProviders.GMapProvider.UserAgent = "AirScout";
|
|
// set initial settings for main map
|
|
gm_Main.MapProvider = GMapProviders.Find(Properties.Settings.Default.Map_Provider);
|
|
gm_Main.IgnoreMarkerOnMouseWheel = true;
|
|
gm_Main.MinZoom = 0;
|
|
gm_Main.MaxZoom = 20;
|
|
gm_Main.Zoom = 6;
|
|
gm_Main.DragButton = System.Windows.Forms.MouseButtons.Left;
|
|
gm_Main.CanDragMap = true;
|
|
gm_Main.ScalePen = new Pen(Color.Black, 3);
|
|
gm_Main.MapScaleInfoEnabled = true;
|
|
gm_Main.Overlays.Add(gmo_Airports);
|
|
gm_Main.Overlays.Add(gmo_Callsigns);
|
|
gm_Main.Overlays.Add(gmo_PropagationPaths);
|
|
gm_Main.Overlays.Add(gmo_Routes);
|
|
gm_Main.Overlays.Add(gmo_Objects);
|
|
gm_Main.Overlays.Add(gmo_Planes);
|
|
// center map
|
|
gm_Main.Position = new PointLatLng(Properties.Settings.Default.MyLat, Properties.Settings.Default.MyLon);
|
|
// intially fill dialog box elements and set band
|
|
string[] bands = Bands.GetStringValuesExceptNoneAndAll();
|
|
foreach (string b in bands)
|
|
cb_Band.Items.Add(b);
|
|
BAND band = Properties.Settings.Default.Band;
|
|
cb_Band.SelectedItem = Bands.GetStringValue(band);
|
|
PlayMode = AIRSCOUTPLAYMODE.PAUSE;
|
|
VieClientStatus = VIEWCLIENTSTATUS.CONNECTED;
|
|
UpdateStatus();
|
|
Say("");
|
|
}
|
|
|
|
private Bitmap CreatePlaneIcon(Color color)
|
|
{
|
|
// get the basic icon
|
|
Bitmap bm = new Bitmap(AppDirectory + Path.DirectorySeparatorChar + Properties.Settings.Default.Planes_IconFileName);
|
|
// read the content and change color of each pixel
|
|
for (int j = 0; j < bm.Width; j++)
|
|
{
|
|
for (int k = 0; k < bm.Height; k++)
|
|
{
|
|
// get the color of each pixel
|
|
Color c = bm.GetPixel(j, k);
|
|
// check if not transparent
|
|
if (c.A > 0)
|
|
{
|
|
// change color
|
|
bm.SetPixel(j, k, Color.FromArgb(c.A, color.R, color.G, color.B));
|
|
}
|
|
}
|
|
}
|
|
return bm;
|
|
}
|
|
|
|
public static Color ColorFromHSV(double hue, double saturation, double value)
|
|
{
|
|
int hi = Convert.ToInt32(Math.Floor(hue / 60)) % 6;
|
|
double f = hue / 60 - Math.Floor(hue / 60);
|
|
|
|
value = value * 255;
|
|
int v = Convert.ToInt32(value);
|
|
int p = Convert.ToInt32(value * (1 - saturation));
|
|
int q = Convert.ToInt32(value * (1 - f * saturation));
|
|
int t = Convert.ToInt32(value * (1 - (1 - f) * saturation));
|
|
|
|
if (hi == 0)
|
|
return Color.FromArgb(255, v, t, p);
|
|
else if (hi == 1)
|
|
return Color.FromArgb(255, q, v, p);
|
|
else if (hi == 2)
|
|
return Color.FromArgb(255, p, v, t);
|
|
else if (hi == 3)
|
|
return Color.FromArgb(255, p, q, v);
|
|
else if (hi == 4)
|
|
return Color.FromArgb(255, t, p, v);
|
|
else
|
|
return Color.FromArgb(255, v, p, q);
|
|
}
|
|
|
|
public Color GetColor(double power)
|
|
{
|
|
double H = power * 0.3; // Hue (note 0.4 = Green, see huge chart below)
|
|
double S = 0.95; // Saturation
|
|
double B = 0.95; // Brightness
|
|
|
|
return ColorFromHSV((float)H * 360, (float)S, (float)B);
|
|
}
|
|
|
|
private Bitmap CreateAirportIcon(int alpha)
|
|
{
|
|
// get the basic icon
|
|
Bitmap bm = new Bitmap(AppDirectory + Path.DirectorySeparatorChar + Properties.Settings.Default.Airports_IconFileName);
|
|
// read the content and change opacity of each pixel
|
|
for (int j = 0; j < bm.Width; j++)
|
|
{
|
|
for (int k = 0; k < bm.Height; k++)
|
|
{
|
|
// get the color of each pixel
|
|
Color c = bm.GetPixel(j, k);
|
|
// check if not transparent
|
|
if (c.A > 0)
|
|
{
|
|
// change color
|
|
bm.SetPixel(j, k, Color.FromArgb(alpha, c.R, c.G, c.B));
|
|
}
|
|
}
|
|
}
|
|
return bm;
|
|
}
|
|
|
|
|
|
private void InitializeIcons()
|
|
{
|
|
// create extra icons regular size
|
|
Log.WriteMessage("Started.");
|
|
try
|
|
{
|
|
// now generate 0% - 100% colored planes
|
|
for (int i = 0; i <= 100; i++)
|
|
{
|
|
Bitmap bm = CreatePlaneIcon(GetColor(1.0f - (float)i / 100.0f));
|
|
il_Planes_L.Images.Add(bm);
|
|
il_Planes_M.Images.Add(bm);
|
|
il_Planes_H.Images.Add(bm);
|
|
il_Planes_S.Images.Add(bm);
|
|
}
|
|
il_Planes_L.Images.Add(CreatePlaneIcon(Color.Gray));
|
|
il_Planes_M.Images.Add(CreatePlaneIcon(Color.Gray));
|
|
il_Planes_H.Images.Add(CreatePlaneIcon(Color.Gray));
|
|
il_Planes_S.Images.Add(CreatePlaneIcon(Color.Gray));
|
|
bmindex_gray = il_Planes_M.Images.Count - 1;
|
|
il_Planes_L.Images.Add(CreatePlaneIcon(Color.LightGreen));
|
|
il_Planes_M.Images.Add(CreatePlaneIcon(Color.LightGreen));
|
|
il_Planes_H.Images.Add(CreatePlaneIcon(Color.LightGreen));
|
|
il_Planes_S.Images.Add(CreatePlaneIcon(Color.LightGreen));
|
|
bmindex_lightgreen = il_Planes_M.Images.Count - 1;
|
|
il_Planes_L.Images.Add(CreatePlaneIcon(Color.DarkOrange));
|
|
il_Planes_M.Images.Add(CreatePlaneIcon(Color.DarkOrange));
|
|
il_Planes_H.Images.Add(CreatePlaneIcon(Color.DarkOrange));
|
|
il_Planes_S.Images.Add(CreatePlaneIcon(Color.DarkOrange));
|
|
bmindex_darkorange = il_Planes_M.Images.Count - 1;
|
|
il_Planes_L.Images.Add(CreatePlaneIcon(Color.Red));
|
|
il_Planes_M.Images.Add(CreatePlaneIcon(Color.Red));
|
|
il_Planes_H.Images.Add(CreatePlaneIcon(Color.Red));
|
|
il_Planes_S.Images.Add(CreatePlaneIcon(Color.Red));
|
|
bmindex_red = il_Planes_M.Images.Count - 1;
|
|
il_Planes_L.Images.Add(CreatePlaneIcon(Color.Magenta));
|
|
il_Planes_M.Images.Add(CreatePlaneIcon(Color.Magenta));
|
|
il_Planes_H.Images.Add(CreatePlaneIcon(Color.Magenta));
|
|
il_Planes_S.Images.Add(CreatePlaneIcon(Color.Magenta));
|
|
bmindex_magenta = il_Planes_M.Images.Count - 1;
|
|
il_Airports.Images.Add(CreateAirportIcon(255));
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.WriteMessage(ex.ToString(), LogLevel.Error);
|
|
}
|
|
Log.WriteMessage("Finished.");
|
|
}
|
|
|
|
private void InitializeCharts()
|
|
{
|
|
// propagation path chart
|
|
pm_Path.Title = String.Empty;
|
|
pm_Path.DefaultFontSize = 6F;
|
|
pm_Path.IsLegendVisible = false;
|
|
pv_Path.BackColor = Color.White;
|
|
pv_Path.Model = pm_Path;
|
|
// add axes
|
|
pm_Path.Axes.Clear();
|
|
// add X-axis
|
|
Path_X.IsZoomEnabled = false;
|
|
Path_X.Maximum = 1000;
|
|
Path_X.Minimum = 0;
|
|
Path_X.MajorGridlineStyle = LineStyle.Solid;
|
|
Path_X.MinorGridlineStyle = LineStyle.Dot;
|
|
Path_X.Position = AxisPosition.Bottom;
|
|
this.pm_Path.Axes.Add(Path_X);
|
|
// add Y-axis
|
|
Path_Y.IsZoomEnabled = false;
|
|
Path_Y.Maximum = 20000;
|
|
Path_Y.Minimum = 0;
|
|
Path_Y.MajorGridlineStyle = LineStyle.Solid;
|
|
Path_Y.MinorGridlineStyle = LineStyle.Dot;
|
|
Path_Y.Position = AxisPosition.Left;
|
|
this.pm_Path.Axes.Add(Path_Y);
|
|
// add series
|
|
pm_Path.Series.Clear();
|
|
Path_Elevation.Title = "Elevation";
|
|
Min_H1.Title = "Min_H1";
|
|
Min_H1.StrokeThickness = 2;
|
|
Min_H1.LineStyle = LineStyle.Solid;
|
|
Min_H1.Color = OxyColors.Red;
|
|
Min_H2.Title = "Min_H2";
|
|
Min_H2.StrokeThickness = 2;
|
|
Min_H2.LineStyle = LineStyle.Solid;
|
|
Min_H2.Color = OxyColors.Gold;
|
|
Max_H.Title = "Max_H";
|
|
Max_H.StrokeThickness = 2;
|
|
Max_H.LineStyle = LineStyle.Dot;
|
|
Max_H.Color = OxyColors.DarkBlue;
|
|
Min_H.Title = "Min_H";
|
|
Min_H.StrokeThickness = 0;
|
|
Min_H.LineStyle = LineStyle.Solid;
|
|
Min_H.Color = OxyColors.Magenta.ChangeSaturation(0.4);
|
|
Planes_Hi.Title = "Planes_Hi";
|
|
Planes_Hi.Color = OxyColors.Transparent;
|
|
Planes_Hi.MarkerType = MarkerType.Square;
|
|
Planes_Hi.MarkerFill = OxyColors.Magenta;
|
|
Planes_Lo.Title = "Planes_Lo";
|
|
Planes_Lo.Color = OxyColors.Transparent;
|
|
Planes_Lo.MarkerType = MarkerType.Square;
|
|
Planes_Lo.MarkerFill = OxyColors.Gray;
|
|
pm_Path.Series.Add(Path_Elevation);
|
|
pm_Path.Series.Add(Min_H1);
|
|
pm_Path.Series.Add(Min_H2);
|
|
pm_Path.Series.Add(Max_H);
|
|
pm_Path.Series.Add(Min_H);
|
|
pm_Path.Series.Add(Planes_Hi);
|
|
pm_Path.Series.Add(Planes_Lo);
|
|
// add legend
|
|
pm_Path.LegendTitle = "";
|
|
pm_Path.LegendPosition = LegendPosition.TopRight;
|
|
pm_Path.LegendBackground = OxyColors.White;
|
|
pm_Path.LegendBorder = OxyColors.Black;
|
|
pm_Path.LegendBorderThickness = 1;
|
|
// add control
|
|
this.gb_Path.Controls.Add(pv_Path);
|
|
pv_Path.Paint += new PaintEventHandler(pv_Path_Paint);
|
|
|
|
// zoomed elevation chart
|
|
pm_Elevation.Title = String.Empty;
|
|
pm_Elevation.DefaultFontSize = 6F;
|
|
pm_Elevation.IsLegendVisible = false;
|
|
pv_Elevation.BackColor = Color.White;
|
|
pv_Elevation.Model = pm_Elevation;
|
|
// add series
|
|
pm_Elevation.Series.Clear();
|
|
Elevation.Title = "Elevation";
|
|
LOS.Title = "LOS";
|
|
LOS.StrokeThickness = 2;
|
|
LOS.Color = OxyColors.Black;
|
|
pm_Elevation.Series.Add(Elevation);
|
|
pm_Elevation.Series.Add(LOS);
|
|
// create axes
|
|
pm_Elevation.Axes.Clear();
|
|
// add X-axis
|
|
Elevation_X.IsZoomEnabled = false;
|
|
Elevation_X.Maximum = 1000;
|
|
Elevation_X.Minimum = 0;
|
|
Elevation_X.MajorGridlineStyle = LineStyle.Solid;
|
|
Elevation_X.MinorGridlineStyle = LineStyle.Dot;
|
|
Elevation_X.Position = AxisPosition.Bottom;
|
|
this.pm_Elevation.Axes.Add(Elevation_X);
|
|
// add Y-axis
|
|
Elevation_Y.IsZoomEnabled = false;
|
|
// auto size maximum
|
|
// Elevation_Y.Maximum = maxelv,
|
|
Elevation_Y.Minimum = 0;
|
|
Elevation_Y.MajorGridlineStyle = LineStyle.Solid;
|
|
Elevation_Y.MinorGridlineStyle = LineStyle.Dot;
|
|
Elevation_Y.Position = AxisPosition.Left;
|
|
this.pm_Elevation.Axes.Add(Elevation_Y);
|
|
// add legend
|
|
pm_Elevation.LegendTitle = "";
|
|
pm_Elevation.LegendPosition = LegendPosition.TopRight;
|
|
pm_Elevation.LegendBackground = OxyColors.White;
|
|
pm_Elevation.LegendBorder = OxyColors.Black;
|
|
pm_Elevation.LegendBorderThickness = 1;
|
|
// add control
|
|
this.gb_Path.Controls.Add(pv_Elevation);
|
|
gb_Path_Resize(this, null);
|
|
}
|
|
|
|
#endregion
|
|
|
|
private void UpdateStatus()
|
|
{
|
|
// upddate TextBoxes
|
|
tb_UTC.Text = CurrentTime.ToString("yyyy-MM-dd HH:mm:ss");
|
|
tb_UTC.BackColor = Color.LightSalmon;
|
|
string call = Properties.Settings.Default.MyCall;
|
|
tb_MyCall.SilentText = Properties.Settings.Default.MyCall;
|
|
cb_MyLoc.SilentText = MaidenheadLocator.LocFromLatLon(Properties.Settings.Default.MyLat, Properties.Settings.Default.MyLon,
|
|
Properties.Settings.Default.Locator_SmallLettersForSubsquares,
|
|
(int)Properties.Settings.Default.Locator_MaxLength / 2,
|
|
Properties.Settings.Default.Locator_AutoLength);
|
|
tb_DXCall.Text = Properties.Settings.Default.DXCall;
|
|
cb_DXLoc.SilentText = MaidenheadLocator.LocFromLatLon(Properties.Settings.Default.DXLat,
|
|
Properties.Settings.Default.DXLon,
|
|
Properties.Settings.Default.Locator_SmallLettersForSubsquares,
|
|
(int)Properties.Settings.Default.Locator_MaxLength / 2,
|
|
Properties.Settings.Default.Locator_AutoLength);
|
|
if (MaidenheadLocator.Check(cb_MyLoc.Text) && MaidenheadLocator.Check(cb_DXLoc.Text))
|
|
{
|
|
tb_QTF.Text = Math.Round(LatLon.Bearing(Properties.Settings.Default.MyLat,
|
|
Properties.Settings.Default.MyLon,
|
|
Properties.Settings.Default.DXLat,
|
|
Properties.Settings.Default.DXLon)).ToString("F0");
|
|
tb_QRB.Text = Math.Round(LatLon.Distance(Properties.Settings.Default.MyLat,
|
|
Properties.Settings.Default.MyLon,
|
|
Properties.Settings.Default.DXLat,
|
|
Properties.Settings.Default.DXLon)).ToString("F0");
|
|
}
|
|
else
|
|
{
|
|
tb_QRB.Text = "0";
|
|
tb_QTF.Text = "0";
|
|
}
|
|
// colour Textbox if more precise lat/lon information is available
|
|
if (MaidenheadLocator.IsPrecise(Properties.Settings.Default.MyLat, Properties.Settings.Default.MyLon, 3))
|
|
{
|
|
cb_MyLoc.BackColor = Color.PaleGreen;
|
|
}
|
|
else
|
|
{
|
|
cb_MyLoc.BackColor = Color.FloralWhite;
|
|
}
|
|
// colour Textbox if more precise lat/lon information is available
|
|
if (MaidenheadLocator.IsPrecise(Properties.Settings.Default.DXLat, Properties.Settings.Default.DXLon, 3))
|
|
{
|
|
cb_DXLoc.BackColor = Color.PaleGreen;
|
|
}
|
|
else
|
|
{
|
|
cb_DXLoc.BackColor = Color.FloralWhite;
|
|
}
|
|
cb_Band.SelectedItem = Bands.GetStringValue(Properties.Settings.Default.Band);
|
|
}
|
|
|
|
private string GetServerURL(string server, int port, string filename, string paramstr = "")
|
|
{
|
|
if (!server.StartsWith("http://"))
|
|
server = "http://" + server;
|
|
server = server.TrimEnd('/');
|
|
return (String.IsNullOrEmpty(paramstr)) ? server + ":" + port.ToString() + "/" + filename : server + ":" + port.ToString() + "/" + filename + "?" + paramstr;
|
|
}
|
|
|
|
private string GetJSONFromURL(string url)
|
|
{
|
|
// reads JSON from webserver
|
|
// returns an empty string or null if webserver is not responding
|
|
// returns error message from webserver in case of error
|
|
// returns JSON string if successful
|
|
string json = "";
|
|
// calculate url and get json
|
|
// replace all vaiables, if any
|
|
url = VC.ReplaceAllVars(url);
|
|
try
|
|
{
|
|
Console.WriteLine("Creating web request: " + url);
|
|
HttpWebRequest webrequest = (HttpWebRequest)HttpWebRequest.Create(url);
|
|
webrequest.Referer = "";
|
|
webrequest.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:37.0) Gecko/20100101 Firefox/37.0";
|
|
webrequest.Accept = "application/json, text/javascript, */*;q=0.01";
|
|
webrequest.AutomaticDecompression = System.Net.DecompressionMethods.Deflate | System.Net.DecompressionMethods.GZip;
|
|
Console.WriteLine("Getting web response");
|
|
HttpWebResponse webresponse = (HttpWebResponse)webrequest.GetResponse();
|
|
Console.WriteLine("Reading stream");
|
|
using (StreamReader sr = new StreamReader(webresponse.GetResponseStream()))
|
|
{
|
|
json = sr.ReadToEnd();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Say(ex.Message);
|
|
Log.WriteMessage(ex.ToString(), LogLevel.Error);
|
|
// do nothing
|
|
}
|
|
return json;
|
|
}
|
|
|
|
public T PropertyFromJSON<T>(string propertyName, string json)
|
|
{
|
|
var allobjects = JObject.Parse(json);
|
|
JToken jo = allobjects[propertyName];
|
|
return (T)jo.ToObject(typeof(T));
|
|
}
|
|
|
|
private bool SettingsFromJSON()
|
|
{
|
|
try
|
|
{
|
|
string json = "";
|
|
// get settings
|
|
json = GetJSONFromURL(GetServerURL(Properties.Settings.Default.Server_URL, Properties.Settings.Default.Server_Port, "settings.json"));
|
|
if (String.IsNullOrEmpty(json))
|
|
{
|
|
VieClientStatus = VIEWCLIENTSTATUS.CONNECTING;
|
|
return false;
|
|
}
|
|
if (json.StartsWith("Error:"))
|
|
{
|
|
Say(json);
|
|
return false;
|
|
}
|
|
// copy settings
|
|
Properties.Settings.Default.Path_Band_Settings = PropertyFromJSON<BandSettings>("Path_Band_Settings", json);
|
|
Properties.Settings.Default.Map_Provider = PropertyFromJSON<string>("Map_Provider", json);
|
|
Properties.Settings.Default.MinLat = PropertyFromJSON<double>("MinLat", json);
|
|
Properties.Settings.Default.MinLon = PropertyFromJSON<double>("MinLon", json);
|
|
Properties.Settings.Default.MaxLat = PropertyFromJSON<double>("MaxLat", json);
|
|
Properties.Settings.Default.MaxLon = PropertyFromJSON<double>("MaxLon", json);
|
|
Properties.Settings.Default.MyCall = PropertyFromJSON<string>("MyCall", json);
|
|
Properties.Settings.Default.MyLat = PropertyFromJSON<double>("MyLat", json);
|
|
Properties.Settings.Default.MyLon = PropertyFromJSON<double>("MyLon", json);
|
|
// copy DXCall only if empty
|
|
if (String.IsNullOrEmpty(Properties.Settings.Default.DXCall))
|
|
{
|
|
Properties.Settings.Default.DXCall = PropertyFromJSON<string>("DXCall", json);
|
|
Properties.Settings.Default.DXLat = PropertyFromJSON<double>("DXLat", json);
|
|
Properties.Settings.Default.DXLon = PropertyFromJSON<double>("DXLon", json);
|
|
}
|
|
// set band only if NONE
|
|
if (Properties.Settings.Default.Band != BAND.BNONE)
|
|
Properties.Settings.Default.Band = PropertyFromJSON<BAND>("Band", json);
|
|
Properties.Settings.Default.InfoWin_Position = PropertyFromJSON<bool>("InfoWin_Position", json);
|
|
Properties.Settings.Default.InfoWin_Metric = PropertyFromJSON<bool>("InfoWin_Metric", json);
|
|
Properties.Settings.Default.InfoWin_Track = PropertyFromJSON<bool>("InfoWin_Track", json);
|
|
Properties.Settings.Default.InfoWin_Speed = PropertyFromJSON<bool>("InfoWin_Speed", json);
|
|
Properties.Settings.Default.InfoWin_Alt = PropertyFromJSON<bool>("InfoWin_Alt", json);
|
|
Properties.Settings.Default.InfoWin_Type = PropertyFromJSON<bool>("InfoWin_Type", json);
|
|
Properties.Settings.Default.InfoWin_Time = PropertyFromJSON<bool>("InfoWin_Time", json);
|
|
Properties.Settings.Default.InfoWin_Dist = PropertyFromJSON<bool>("InfoWin_Dist", json);
|
|
Properties.Settings.Default.InfoWin_Angle = PropertyFromJSON<bool>("InfoWin_Angle", json);
|
|
Properties.Settings.Default.InfoWin_Epsilon = PropertyFromJSON<bool>("InfoWin_Epsilon", json);
|
|
Properties.Settings.Default.InfoWin_Squint = PropertyFromJSON<bool>("InfoWin_Squint", json);
|
|
Properties.Settings.Default.Locator_AutoLength = PropertyFromJSON<bool>("Locator_AutoLength", json);
|
|
Properties.Settings.Default.Locator_SmallLettersForSubsquares = PropertyFromJSON<bool>("Locator_SmallLettersForSubsquares", json);
|
|
Properties.Settings.Default.Locator_MaxLength = PropertyFromJSON<decimal>("Locator_MaxLength", json);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Say(ex.Message);
|
|
Log.WriteMessage(ex.ToString(), LogLevel.Error);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private List<LocationDesignator> MyLocationsFromJSON()
|
|
{
|
|
string json = "";
|
|
List<LocationDesignator> l = null;
|
|
try
|
|
{
|
|
string url = GetServerURL(
|
|
Properties.Settings.Default.Server_URL,
|
|
Properties.Settings.Default.Server_Port,
|
|
"location.json",
|
|
"call=" + Properties.Settings.Default.MyCall +
|
|
"&loc=all");
|
|
json = GetJSONFromURL(url);
|
|
if (String.IsNullOrEmpty(json))
|
|
{
|
|
VieClientStatus = VIEWCLIENTSTATUS.CONNECTING;
|
|
return null;
|
|
}
|
|
if (json.StartsWith("Error:"))
|
|
{
|
|
Say(json);
|
|
return null;
|
|
}
|
|
JsonSerializerSettings settings = new JsonSerializerSettings();
|
|
settings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
|
|
settings.FloatFormatHandling = FloatFormatHandling.String;
|
|
settings.Formatting = Newtonsoft.Json.Formatting.Indented;
|
|
settings.Culture = CultureInfo.InvariantCulture;
|
|
l = JsonConvert.DeserializeObject<List<LocationDesignator>>(json, settings);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Say(ex.Message);
|
|
Log.WriteMessage(ex.ToString(), LogLevel.Error);
|
|
}
|
|
return l;
|
|
}
|
|
|
|
private LocationDesignator MyLocationFromJSON()
|
|
{
|
|
string json = "";
|
|
LocationDesignator ld = null;
|
|
try
|
|
{
|
|
string url = GetServerURL(
|
|
Properties.Settings.Default.Server_URL,
|
|
Properties.Settings.Default.Server_Port,
|
|
"location.json",
|
|
"call=" + Properties.Settings.Default.MyCall +
|
|
"&loc=" + MaidenheadLocator.LocFromLatLon(Properties.Settings.Default.MyLat, Properties.Settings.Default.MyLon, false, 3));
|
|
json = GetJSONFromURL(url);
|
|
if (String.IsNullOrEmpty(json))
|
|
{
|
|
VieClientStatus = VIEWCLIENTSTATUS.CONNECTING;
|
|
return null;
|
|
}
|
|
if (json.StartsWith("Error:"))
|
|
{
|
|
Say(json);
|
|
return null;
|
|
}
|
|
ld = LocationDesignator.FromJSON<LocationDesignator>(json);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Say(ex.Message);
|
|
Log.WriteMessage(ex.ToString(), LogLevel.Error);
|
|
}
|
|
return ld;
|
|
}
|
|
|
|
private List<LocationDesignator> DXLocationsFromJSON()
|
|
{
|
|
string json = "";
|
|
List<LocationDesignator> l = null;
|
|
try
|
|
{
|
|
string url = GetServerURL(
|
|
Properties.Settings.Default.Server_URL,
|
|
Properties.Settings.Default.Server_Port,
|
|
"location.json",
|
|
"call=" + Properties.Settings.Default.DXCall +
|
|
"&loc=all");
|
|
json = GetJSONFromURL(url);
|
|
if (String.IsNullOrEmpty(json))
|
|
{
|
|
VieClientStatus = VIEWCLIENTSTATUS.CONNECTING;
|
|
return null;
|
|
}
|
|
if (json.StartsWith("Error:"))
|
|
{
|
|
Say(json);
|
|
return null;
|
|
}
|
|
JsonSerializerSettings settings = new JsonSerializerSettings();
|
|
settings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
|
|
settings.FloatFormatHandling = FloatFormatHandling.String;
|
|
settings.Formatting = Newtonsoft.Json.Formatting.Indented;
|
|
settings.Culture = CultureInfo.InvariantCulture;
|
|
l = JsonConvert.DeserializeObject<List<LocationDesignator>>(json, settings);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Say(ex.Message);
|
|
Log.WriteMessage(ex.ToString(), LogLevel.Error);
|
|
}
|
|
return l;
|
|
}
|
|
|
|
private LocationDesignator DXLocationFromJSON()
|
|
{
|
|
string json = "";
|
|
LocationDesignator ld = null;
|
|
try
|
|
{
|
|
string url = GetServerURL(
|
|
Properties.Settings.Default.Server_URL,
|
|
Properties.Settings.Default.Server_Port,
|
|
"location.json",
|
|
"&call=" + Properties.Settings.Default.DXCall +
|
|
"&loc=" + MaidenheadLocator.LocFromLatLon(Properties.Settings.Default.DXLat, Properties.Settings.Default.DXLon, false, 3));
|
|
json = GetJSONFromURL(url);
|
|
if (String.IsNullOrEmpty(json))
|
|
{
|
|
VieClientStatus = VIEWCLIENTSTATUS.CONNECTING;
|
|
return null;
|
|
}
|
|
if (json.StartsWith("Error:"))
|
|
{
|
|
Say(json);
|
|
return null;
|
|
}
|
|
ld = LocationDesignator.FromJSON<LocationDesignator>(json);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Say(ex.Message);
|
|
Log.WriteMessage(ex.ToString(), LogLevel.Error);
|
|
}
|
|
return ld;
|
|
}
|
|
|
|
private ElevationPathDesignator ElevationPathFromJSON()
|
|
{
|
|
string json = "";
|
|
try
|
|
{
|
|
json = GetJSONFromURL(GetServerURL(
|
|
Properties.Settings.Default.Server_URL,
|
|
Properties.Settings.Default.Server_Port,
|
|
"elevationpath.json",
|
|
"mycall=" + Properties.Settings.Default.MyCall +
|
|
"&myloc=" + MaidenheadLocator.LocFromLatLon(Properties.Settings.Default.MyLat, Properties.Settings.Default.MyLon, false, 3) +
|
|
"&dxcall=" + Properties.Settings.Default.DXCall +
|
|
"&dxloc=" + MaidenheadLocator.LocFromLatLon(Properties.Settings.Default.DXLat, Properties.Settings.Default.DXLon, false, 3)));
|
|
if (String.IsNullOrEmpty(json))
|
|
{
|
|
VieClientStatus = VIEWCLIENTSTATUS.CONNECTING;
|
|
return null;
|
|
}
|
|
if (json.StartsWith("Error:"))
|
|
{
|
|
Say(json);
|
|
return null;
|
|
}
|
|
EPath = ElevationPathDesignator.FromJSON<ElevationPathDesignator>(json);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Say(ex.Message);
|
|
Log.WriteMessage(ex.ToString(), LogLevel.Error);
|
|
}
|
|
return EPath;
|
|
}
|
|
|
|
private PropagationPathDesignator PropagationPathFromJSON()
|
|
{
|
|
string json = "";
|
|
try
|
|
{
|
|
json = GetJSONFromURL(GetServerURL(
|
|
Properties.Settings.Default.Server_URL,
|
|
Properties.Settings.Default.Server_Port,
|
|
"propagationpath.json",
|
|
"mycall=" + Properties.Settings.Default.MyCall +
|
|
"&myloc=" + MaidenheadLocator.LocFromLatLon(Properties.Settings.Default.MyLat, Properties.Settings.Default.MyLon, false, 3) +
|
|
"&dxcall=" + Properties.Settings.Default.DXCall +
|
|
"&dxloc=" + MaidenheadLocator.LocFromLatLon(Properties.Settings.Default.DXLat, Properties.Settings.Default.DXLon, false, 3)));
|
|
if (String.IsNullOrEmpty(json))
|
|
{
|
|
VieClientStatus = VIEWCLIENTSTATUS.CONNECTING;
|
|
return null;
|
|
}
|
|
if (json.StartsWith("Error:"))
|
|
{
|
|
Say(json);
|
|
return null;
|
|
}
|
|
PPath = PropagationPathDesignator.FromJSON<PropagationPathDesignator>(json);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Say(ex.Message);
|
|
Log.WriteMessage(ex.ToString(), LogLevel.Error);
|
|
}
|
|
return PPath;
|
|
}
|
|
|
|
private List<PlaneInfo> NearestPlanesFromJSON()
|
|
{
|
|
string json = "";
|
|
List<PlaneInfo> l = null;
|
|
try
|
|
{
|
|
json = GetJSONFromURL(GetServerURL(
|
|
Properties.Settings.Default.Server_URL,
|
|
Properties.Settings.Default.Server_Port,
|
|
"nearestplanes.json",
|
|
"mycall=" + Properties.Settings.Default.MyCall +
|
|
"&myloc=" + MaidenheadLocator.LocFromLatLon(Properties.Settings.Default.MyLat, Properties.Settings.Default.MyLon, false, 3) +
|
|
"&dxcall=" + Properties.Settings.Default.DXCall +
|
|
"&dxloc=" + MaidenheadLocator.LocFromLatLon(Properties.Settings.Default.DXLat, Properties.Settings.Default.DXLon, false, 3)));
|
|
if (String.IsNullOrEmpty(json))
|
|
{
|
|
VieClientStatus = VIEWCLIENTSTATUS.CONNECTING;
|
|
return null;
|
|
}
|
|
if (json.StartsWith("Error:"))
|
|
{
|
|
Say(json);
|
|
return null;
|
|
}
|
|
JsonSerializerSettings settings = new JsonSerializerSettings();
|
|
settings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
|
|
settings.FloatFormatHandling = FloatFormatHandling.String;
|
|
settings.Formatting = Newtonsoft.Json.Formatting.Indented;
|
|
settings.Culture = CultureInfo.InvariantCulture;
|
|
l = (List<PlaneInfo>)JsonConvert.DeserializeObject<List<PlaneInfo>>(json, settings);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Say(ex.Message);
|
|
Log.WriteMessage(ex.ToString(), LogLevel.Error);
|
|
}
|
|
return l;
|
|
}
|
|
|
|
private static Bitmap RotateImageByAngle(System.Drawing.Image oldBitmap, float angle)
|
|
{
|
|
var newBitmap = new Bitmap(oldBitmap.Width, oldBitmap.Height);
|
|
var graphics = Graphics.FromImage(newBitmap);
|
|
graphics.TranslateTransform((float)oldBitmap.Width / 2, (float)oldBitmap.Height / 2);
|
|
graphics.RotateTransform(angle);
|
|
graphics.TranslateTransform(-(float)oldBitmap.Width / 2, -(float)oldBitmap.Height / 2);
|
|
graphics.DrawImage(oldBitmap, new System.Drawing.Point(0, 0));
|
|
return newBitmap;
|
|
}
|
|
|
|
private GMarkerGoogle CreatePlaneSimple(PlaneInfo info, bool selected)
|
|
{
|
|
// return on empty info
|
|
if (info == null)
|
|
return null;
|
|
// show flight info only
|
|
// get bitmap according to category
|
|
Bitmap bm;
|
|
int bmindex = bmindex_gray;
|
|
Brush brush = new SolidBrush(Color.FromArgb(180, Color.White));
|
|
if (info.Potential == 100)
|
|
{
|
|
bmindex = bmindex_magenta;
|
|
brush = new SolidBrush(Color.FromArgb(150, Color.Plum));
|
|
}
|
|
else if (info.Potential == 75)
|
|
{
|
|
bmindex = bmindex_red;
|
|
brush = new SolidBrush(Color.FromArgb(150, Color.Red));
|
|
}
|
|
else if (info.Potential == 50)
|
|
{
|
|
bmindex = bmindex_darkorange;
|
|
brush = new SolidBrush(Color.FromArgb(150, Color.DarkOrange));
|
|
}
|
|
if (info.Category == PLANECATEGORY.SUPERHEAVY)
|
|
bm = new Bitmap(il_Planes_S.Images[bmindex]);
|
|
else if (info.Category == PLANECATEGORY.HEAVY)
|
|
bm = new Bitmap(il_Planes_H.Images[bmindex]);
|
|
else if (info.Category == PLANECATEGORY.MEDIUM)
|
|
bm = new Bitmap(il_Planes_M.Images[bmindex]);
|
|
else if (info.Category == PLANECATEGORY.LIGHT)
|
|
bm = new Bitmap(il_Planes_L.Images[bmindex]);
|
|
else
|
|
bm = new Bitmap(il_Planes_M.Images[bmindex]);
|
|
GMarkerGoogle m = new GMarkerGoogle(new PointLatLng(info.Lat, info.Lon), ToolTipFont, RotateImageByAngle(bm, (float)info.Track));
|
|
m.Tag = info.Call;
|
|
string lat = "";
|
|
if (info.Lat >= 0)
|
|
lat = Math.Abs(info.Lat).ToString("00.00") + "°N";
|
|
else
|
|
lat = Math.Abs(info.Lat).ToString("00.00") + "°S";
|
|
string lon = "";
|
|
if (info.Lon >= 0)
|
|
lon = Math.Abs(info.Lon).ToString("000.00") + "°E";
|
|
else
|
|
lon = Math.Abs(info.Lon).ToString("000.00") + "°W";
|
|
m.ToolTipText = info.Call + "\n--------------------";
|
|
if (Properties.Settings.Default.InfoWin_Position)
|
|
m.ToolTipText += "\nPos: " + lat + " , " + lon;
|
|
if (Properties.Settings.Default.InfoWin_Alt)
|
|
{
|
|
if (Properties.Settings.Default.InfoWin_Metric)
|
|
m.ToolTipText += "\nAlt: " + (int)info.Alt_m + "m";
|
|
else
|
|
m.ToolTipText += "\nAlt: " + (int)info.Alt + "ft";
|
|
}
|
|
if (Properties.Settings.Default.InfoWin_Track)
|
|
m.ToolTipText += "\nTrack: " + (int)info.Track + "°";
|
|
if (Properties.Settings.Default.InfoWin_Type)
|
|
m.ToolTipText += "\nType: " + info.Manufacturer + " " + info.Model + " [" + PlaneCategories.GetShortStringValue(info.Category) + "]";
|
|
// set tooltip on if hot
|
|
if (selected)
|
|
m.ToolTipMode = MarkerTooltipMode.Always;
|
|
else
|
|
m.ToolTipMode = MarkerTooltipMode.OnMouseOver;
|
|
if (m.ToolTip != null)
|
|
m.ToolTip.Fill = brush;
|
|
return m;
|
|
}
|
|
|
|
private GMarkerGoogle CreatePlaneDetailed(PlaneInfo info, bool selected)
|
|
{
|
|
// return on empty info
|
|
if (info == null)
|
|
return null;
|
|
// get bitmap according to category
|
|
Bitmap bm;
|
|
int bmindex = bmindex_gray;
|
|
Brush brush = new SolidBrush(Color.FromArgb(180, Color.White));
|
|
if (info.Potential == 100)
|
|
{
|
|
bmindex = bmindex_magenta;
|
|
brush = new SolidBrush(Color.FromArgb(150, Color.Plum));
|
|
}
|
|
else if (info.Potential == 75)
|
|
{
|
|
bmindex = bmindex_red;
|
|
brush = new SolidBrush(Color.FromArgb(150, Color.Red));
|
|
}
|
|
else if (info.Potential == 50)
|
|
{
|
|
bmindex = bmindex_darkorange;
|
|
brush = new SolidBrush(Color.FromArgb(150, Color.DarkOrange));
|
|
}
|
|
if (info.Category == PLANECATEGORY.SUPERHEAVY)
|
|
bm = new Bitmap(il_Planes_S.Images[bmindex]);
|
|
else if (info.Category == PLANECATEGORY.HEAVY)
|
|
bm = new Bitmap(il_Planes_H.Images[bmindex]);
|
|
else if (info.Category == PLANECATEGORY.MEDIUM)
|
|
bm = new Bitmap(il_Planes_M.Images[bmindex]);
|
|
else if (info.Category == PLANECATEGORY.LIGHT)
|
|
bm = new Bitmap(il_Planes_L.Images[bmindex]);
|
|
else
|
|
bm = new Bitmap(il_Planes_M.Images[bmindex]);
|
|
GMarkerGoogle m = new GMarkerGoogle(new PointLatLng(info.Lat, info.Lon), ToolTipFont, RotateImageByAngle(bm, (float)info.Track));
|
|
m.Tag = info.Call;
|
|
string lat = "";
|
|
if (info.Lat >= 0)
|
|
lat = Math.Abs(info.Lat).ToString("00.00") + "°N";
|
|
else
|
|
lat = Math.Abs(info.Lat).ToString("00.00") + "°S";
|
|
string lon = "";
|
|
if (info.Lon >= 0)
|
|
lon = Math.Abs(info.Lon).ToString("000.00") + "°E";
|
|
else
|
|
lon = Math.Abs(info.Lon).ToString("000.00") + "°W";
|
|
int mins = 0;
|
|
if (info.Speed > 0)
|
|
mins = (int)(info.IntQRB / UnitConverter.kts_kmh(info.Speed) * 60.0);
|
|
// fill tooltip texts
|
|
m.ToolTipText = info.Call + "\n--------------------";
|
|
if (Properties.Settings.Default.InfoWin_Position)
|
|
m.ToolTipText += "\nPos: " + lat + " , " + lon;
|
|
if (Properties.Settings.Default.InfoWin_Alt)
|
|
{
|
|
if (Properties.Settings.Default.InfoWin_Metric)
|
|
m.ToolTipText += "\nAlt: " + (int)info.Alt_m + "m [" + info.AltDiff.ToString("+#;-#;0") + "m]";
|
|
else
|
|
m.ToolTipText += "\nAlt: " + (int)info.Alt + "ft [" + UnitConverter.m_ft(info.AltDiff).ToString("+#;-#;0") + "ft]";
|
|
}
|
|
if (Properties.Settings.Default.InfoWin_Track)
|
|
m.ToolTipText += "\nTrack: " + info.Track + "°";
|
|
if (Properties.Settings.Default.InfoWin_Speed)
|
|
{
|
|
if (Properties.Settings.Default.InfoWin_Metric)
|
|
m.ToolTipText += "\nSpeed: " + info.Speed_kmh.ToString("F0") + "km/h";
|
|
else
|
|
m.ToolTipText += "\nSpeed: " + info.Speed.ToString("F0") + "kts";
|
|
}
|
|
if (Properties.Settings.Default.InfoWin_Type)
|
|
m.ToolTipText += "\nType: " + info.Manufacturer + " " + info.Model + " [" + PlaneCategories.GetShortStringValue(info.Category) + "]";
|
|
if (Properties.Settings.Default.InfoWin_Dist)
|
|
{
|
|
if (Properties.Settings.Default.InfoWin_Metric)
|
|
m.ToolTipText += "\nDist: " + info.IntQRB.ToString("F0") + "km";
|
|
else
|
|
m.ToolTipText += "\nDist: " + UnitConverter.km_mi(info.IntQRB).ToString("F0") + "mi";
|
|
}
|
|
if (Properties.Settings.Default.InfoWin_Time)
|
|
m.ToolTipText += "\nTime: " + (CurrentTime + new TimeSpan(0, mins, 0)).ToString("HH:mm") + " [ " + mins.ToString("") + "min]";
|
|
if (Properties.Settings.Default.InfoWin_Angle)
|
|
m.ToolTipText += "\nAngle: " + (info.Angle / Math.PI * 180.0).ToString("F0") + "°";
|
|
if (Properties.Settings.Default.InfoWin_Epsilon)
|
|
m.ToolTipText += "\nEps: " + (info.Eps1 / Math.PI * 180.0).ToString("00.00") + "° <> " + (info.Eps2 / Math.PI * 180.0).ToString("00.00") + "°";
|
|
if (Properties.Settings.Default.InfoWin_Squint)
|
|
m.ToolTipText += "\nSquint: " + (info.Squint / Math.PI * 180).ToString("00.00") + "°";
|
|
if (selected)
|
|
{
|
|
m.ToolTipMode = MarkerTooltipMode.Always;
|
|
}
|
|
else
|
|
{
|
|
m.ToolTipMode = MarkerTooltipMode.OnMouseOver;
|
|
}
|
|
if (m.ToolTip != null)
|
|
m.ToolTip.Fill = brush;
|
|
return m;
|
|
}
|
|
|
|
private void DrawPlanes()
|
|
{
|
|
bool isselected = false;
|
|
|
|
if (EPath == null)
|
|
return;
|
|
if (PPath == null)
|
|
return;
|
|
|
|
// check for filter settings
|
|
// and color filter box
|
|
int planes_filter_minalt = 0;
|
|
planes_filter_minalt = Properties.Settings.Default.Planes_Filter_Min_Alt;
|
|
if (planes_filter_minalt < 0)
|
|
planes_filter_minalt = 0;
|
|
Stopwatch st = new Stopwatch();
|
|
st.Start();
|
|
|
|
// clear planes overlay in map
|
|
gmo_Planes.Clear();
|
|
// clear all routes except paths
|
|
gmo_Routes.Clear();
|
|
// clear active planes
|
|
ActivePlanes.Clear();
|
|
|
|
// clear data points in chart
|
|
Planes_Hi.Points.Clear();
|
|
Planes_Lo.Points.Clear();
|
|
|
|
// get nearest planes per path
|
|
List<PlaneInfo> nearestplanes = NearestPlanesFromJSON();
|
|
|
|
if (nearestplanes == null)
|
|
return;
|
|
foreach (PlaneInfo plane in nearestplanes)
|
|
{
|
|
// add or update plane in active planes list
|
|
PlaneInfo activeplane = null;
|
|
if (ActivePlanes.TryGetValue(plane.Hex, out activeplane))
|
|
{
|
|
// plane found --> update if necessary
|
|
bool update = false;
|
|
// plane has higher potential
|
|
if (plane.Potential > activeplane.Potential)
|
|
update = true;
|
|
// plane has same potetial but is nearer to path
|
|
else if ((plane.Potential == activeplane.Potential) && (plane.IntQRB < activeplane.IntQRB))
|
|
update = true;
|
|
// update if necessary
|
|
if (update)
|
|
{
|
|
ActivePlanes.Remove(activeplane.Hex);
|
|
ActivePlanes.Add(plane.Hex, plane);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// add plane to list if not foound
|
|
ActivePlanes.Add(plane.Hex, plane);
|
|
}
|
|
}
|
|
st.Stop();
|
|
Say("Get nearest planes: " + ActivePlanes.Count.ToString() + " plane(s), " + st.ElapsedMilliseconds.ToString() + " ms.");
|
|
st.Reset();
|
|
st.Start();
|
|
Log.WriteMessage("Drawing planes: " + ActivePlanes.Count.ToString() + " plane(s), " + st.ElapsedMilliseconds.ToString() + " ms.");
|
|
|
|
// check if any plane is on list --> return empty list
|
|
if ((ActivePlanes == null) || (ActivePlanes.Count == 0))
|
|
return;
|
|
// draw all planes
|
|
foreach (PlaneInfo plane in ActivePlanes.Values)
|
|
{
|
|
try
|
|
{
|
|
// show planes if it meets filter criteria
|
|
if ((plane.Alt_m >= Properties.Settings.Default.Planes_MinAlt) && (plane.Category >= Properties.Settings.Default.Planes_Filter_Min_Category))
|
|
{
|
|
// check selected state
|
|
isselected = SelectedPlanes.IndexOf(plane.Call) >= 0;
|
|
// now, show plane according to potential
|
|
switch (plane.Potential)
|
|
{
|
|
case 100:
|
|
gmo_Planes.Markers.Add(CreatePlaneDetailed(plane, isselected));
|
|
break;
|
|
case 75:
|
|
gmo_Planes.Markers.Add(CreatePlaneDetailed(plane, isselected));
|
|
break;
|
|
case 50:
|
|
gmo_Planes.Markers.Add(CreatePlaneDetailed(plane, isselected));
|
|
break;
|
|
default:
|
|
gmo_Planes.Markers.Add(CreatePlaneSimple(plane, isselected));
|
|
break;
|
|
}
|
|
|
|
// if selected: draw the thin path to crossing point if one
|
|
if (isselected)
|
|
{
|
|
if (plane.IntPoint != null)
|
|
{
|
|
GMapRoute intpath = new GMapRoute(plane.Call);
|
|
intpath.Stroke = new Pen(Color.Black, 1);
|
|
intpath.Points.Add(new PointLatLng(plane.Lat, plane.Lon));
|
|
intpath.Points.Add(new PointLatLng(plane.IntPoint.Lat, plane.IntPoint.Lon));
|
|
gmo_Routes.Routes.Add(intpath);
|
|
// Console.WriteLine(DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss") + ";" + info.IntQRB.ToString("F3"));
|
|
}
|
|
}
|
|
|
|
// show planes on chart if in sigle path mode
|
|
if ((plane.IntPoint != null) && (plane.IntQRB <= Properties.Settings.Default.Path_Band_Settings[Properties.Settings.Default.Band].MaxDistance))
|
|
{
|
|
// calculate distance from mylat/mylon
|
|
double dist = LatLon.Distance(Properties.Settings.Default.MyLat, Properties.Settings.Default.MyLon, plane.IntPoint.Lat, plane.IntPoint.Lon);
|
|
// add new data points
|
|
if (plane.AltDiff > 0)
|
|
{
|
|
Planes_Hi.Points.Add(new DataPoint(dist, plane.Alt_m));
|
|
}
|
|
else
|
|
{
|
|
Planes_Lo.Points.Add(new DataPoint(dist, plane.Alt_m));
|
|
}
|
|
}
|
|
}
|
|
|
|
// invalidate chart
|
|
pm_Path.InvalidatePlot(true);
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.WriteMessage(ex.ToString(), LogLevel.Error);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void DrawPath()
|
|
{
|
|
ElevationPathDesignator epath = ElevationPathFromJSON();
|
|
if (epath == null)
|
|
return;
|
|
// set MyDetails and DXDetails
|
|
Properties.Settings.Default.MyCall = epath.Location1.Call;
|
|
Properties.Settings.Default.MyLat = epath.Lat1;
|
|
Properties.Settings.Default.MyLon = epath.Lon1;
|
|
Properties.Settings.Default.DXCall = epath.Location2.Call;
|
|
Properties.Settings.Default.DXLat = epath.Lat2;
|
|
Properties.Settings.Default.DXLon = epath.Lon2;
|
|
PropagationPathDesignator ppath = PropagationPathFromJSON();
|
|
if (ppath == null)
|
|
return;
|
|
// clear charts
|
|
ClearCharts();
|
|
// draw my end on the map
|
|
gmm_MyLoc = new GMarkerGoogle(new PointLatLng(epath.Location1.Lat, epath.Location1.Lon), ToolTipFont, Properties.Settings.Default.Map_SmallMarkers ? GMarkerGoogleType.red_small : GMarkerGoogleType.red_dot);
|
|
gmm_MyLoc.ToolTipText = epath.Location1.Call + "\n" +
|
|
epath.Location1.Lat.ToString("F8", CultureInfo.InvariantCulture) + "\n" +
|
|
epath.Location1.Lon.ToString("F8", CultureInfo.InvariantCulture) + "\n" +
|
|
epath.Location1.Loc + "\n" +
|
|
epath.Location1.Elevation.ToString("F0") + "m";
|
|
gmm_MyLoc.ToolTipMode = MarkerTooltipMode.OnMouseOver;
|
|
gmm_MyLoc.Tag = epath.Location1.Call;
|
|
gmo_Objects.Markers.Add(gmm_MyLoc);
|
|
// draws a propagation path to map
|
|
PropagationPoint[] ppoints = new PropagationPoint[0];
|
|
try
|
|
{
|
|
// get infopoints for map
|
|
ppoints = ppath.GetInfoPoints();
|
|
// calculate midpoint
|
|
ScoutBase.Core.LatLon.GPoint midpoint = LatLon.MidPoint(ppath.Lat1, ppath.Lon1, ppath.Lat2, ppath.Lon2);
|
|
GMapMarker gmmid = new GMarkerGoogle(new PointLatLng(midpoint.Lat, midpoint.Lon), ToolTipFont, Properties.Settings.Default.Map_SmallMarkers ? GMarkerGoogleType.blue_small : GMarkerGoogleType.blue_dot);
|
|
gmmid.ToolTipText = ppath.Location1.Call + " <> " + ppath.Location2.Call;
|
|
gmmid.ToolTipMode = MarkerTooltipMode.OnMouseOver;
|
|
gmo_Objects.Markers.Add(gmmid);
|
|
// calculate dx end
|
|
gmm_DXLoc = new GMarkerGoogle(new PointLatLng(epath.Lat2, epath.Lon2), ToolTipFont, Properties.Settings.Default.Map_SmallMarkers ? GMarkerGoogleType.yellow_small : GMarkerGoogleType.yellow_dot);
|
|
gmm_DXLoc.ToolTipText = epath.Location2.Call + "\n" +
|
|
epath.Location2.Lat.ToString("F8", CultureInfo.InvariantCulture) + "\n" +
|
|
epath.Location2.Lon.ToString("F8", CultureInfo.InvariantCulture) + "\n" +
|
|
epath.Location2.Loc + "\n" +
|
|
epath.Location2.Elevation.ToString("F0") + "m";
|
|
gmm_DXLoc.ToolTipMode = MarkerTooltipMode.OnMouseOver;
|
|
gmm_DXLoc.Tag = epath.Location2.Call;
|
|
gmo_Objects.Markers.Add(gmm_DXLoc);
|
|
// set three small points for hot path, if one
|
|
if (!Properties.Settings.Default.Map_SmallMarkers)
|
|
{
|
|
int i1 = -1;
|
|
int i3 = -1;
|
|
for (int i = 0; i < ppoints.Length; i++)
|
|
{
|
|
if (Math.Max(ppoints[i].H1, ppoints[i].H2) < Properties.Settings.Default.Planes_MaxAlt)
|
|
{
|
|
if (i1 == -1)
|
|
i1 = i;
|
|
else i3 = i;
|
|
|
|
}
|
|
}
|
|
if ((i1 >= 0) && (i3 >= 0))
|
|
{
|
|
GMapMarker gmi1 = new GMarkerGoogle(new PointLatLng(ppoints[i1].Lat, ppoints[i1].Lon), GMarkerGoogleType.red_small);
|
|
gmo_Objects.Markers.Add(gmi1);
|
|
LatLon.GPoint gp = LatLon.MidPoint(ppoints[i1].Lat, ppoints[i1].Lon, ppoints[i3].Lat, ppoints[i3].Lon);
|
|
GMapMarker gmi2 = new GMarkerGoogle(new PointLatLng(gp.Lat, gp.Lon), GMarkerGoogleType.blue_small);
|
|
gmo_Objects.Markers.Add(gmi2);
|
|
GMapMarker gmi3 = new GMarkerGoogle(new PointLatLng(ppoints[i3].Lat, ppoints[i3].Lon), GMarkerGoogleType.yellow_small);
|
|
gmo_Objects.Markers.Add(gmi3);
|
|
}
|
|
}
|
|
// draw propagation path according to path status
|
|
// valid: black
|
|
// invalid: red
|
|
gmr_FullPath = new GMapRoute("fullpath");
|
|
gmr_FullPath.Stroke = (ppath.Valid) ? new Pen(Color.Black, 3) : new Pen(Color.Red, 3);
|
|
gmo_PropagationPaths.Routes.Add(gmr_FullPath);
|
|
gmr_NearestFull = new GMapRoute("fullpath");
|
|
gmr_NearestFull.Stroke = (ppath.Valid) ? new Pen(Color.Black, 3) : new Pen(Color.Red, 3);
|
|
gmo_NearestPaths.Routes.Add(gmr_NearestFull);
|
|
foreach (PropagationPoint ppoint in ppoints)
|
|
{
|
|
gmr_FullPath.Points.Add(new PointLatLng(ppoint.Lat, ppoint.Lon));
|
|
gmr_NearestFull.Points.Add(new PointLatLng(ppoint.Lat, ppoint.Lon));
|
|
}
|
|
// draw mutual visible path
|
|
gmr_VisiblePpath = new GMapRoute("visiblepath");
|
|
gmr_VisiblePpath.Stroke = new Pen(Color.Magenta, 3);
|
|
gmr_NearestVisible = new GMapRoute("visiblepath");
|
|
gmr_NearestVisible.Stroke = new Pen(Color.Magenta, 3);
|
|
for (int i = 0; i < ppoints.Length; i++)
|
|
{
|
|
if ((Math.Max(ppoints[i].H1, ppoints[i].H2) > 0) && (Math.Max(ppoints[i].H1, ppoints[i].H2) < Properties.Settings.Default.Planes_MaxAlt))
|
|
{
|
|
PointLatLng p = new PointLatLng(ppoints[i].Lat, ppoints[i].Lon);
|
|
gmr_VisiblePpath.Points.Add(p);
|
|
gmr_NearestVisible.Points.Add(p);
|
|
}
|
|
}
|
|
gmo_PropagationPaths.Routes.Add(gmr_VisiblePpath);
|
|
gmo_NearestPaths.Routes.Add(gmr_NearestVisible);
|
|
|
|
// calculate bounds
|
|
double minlat = Math.Min(epath.Lat1, epath.Lat2);
|
|
double minlon = Math.Min(epath.Lon1, epath.Lon2);
|
|
double maxlat = Math.Max(epath.Lat1, epath.Lat2);
|
|
double maxlon = Math.Max(epath.Lon1, epath.Lon2);
|
|
|
|
// calculate center
|
|
double centerlat = LatLon.MidPoint(minlat, minlon, maxlat, maxlon).Lat;
|
|
double centerlon = LatLon.MidPoint(minlat, minlon, maxlat, maxlon).Lon;
|
|
|
|
// ensure that whole path is visible and optionally centered
|
|
gm_Main.SetZoomToFitRect(RectLatLng.FromLTRB(minlon, maxlat, maxlon, minlat));
|
|
gm_Main.Position = new PointLatLng(centerlat, centerlon);
|
|
|
|
UpdateCharts(epath, ppath);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.WriteMessage(ex.ToString(), LogLevel.Error);
|
|
}
|
|
}
|
|
|
|
private void ti_Startup_Tick(object sender, EventArgs e)
|
|
{
|
|
ti_Startup.Stop();
|
|
// start timer
|
|
ti_Progress.Start();
|
|
}
|
|
|
|
private void ti_Progress_Tick(object sender, EventArgs e)
|
|
{
|
|
tsl_ConnectionStatus.Text = VieClientStatus.ToString();
|
|
switch (VieClientStatus)
|
|
{
|
|
case VIEWCLIENTSTATUS.CONNECTING:
|
|
{
|
|
tsl_ConnectionStatus.BackColor = Color.Yellow;
|
|
tsl_ConnectionStatus.ForeColor = Color.Green;
|
|
InitializeSettings();
|
|
break;
|
|
}
|
|
case VIEWCLIENTSTATUS.CONNECTED:
|
|
{
|
|
tsl_ConnectionStatus.BackColor = Color.Green;
|
|
tsl_ConnectionStatus.ForeColor = Color.White;
|
|
if (PlayMode != AIRSCOUTPLAYMODE.FORWARD)
|
|
return;
|
|
CurrentTime = DateTime.UtcNow;
|
|
UpdateStatus();
|
|
DrawPlanes();
|
|
break;
|
|
}
|
|
case VIEWCLIENTSTATUS.ERROR:
|
|
{
|
|
tsl_ConnectionStatus.BackColor = Color.Red;
|
|
tsl_ConnectionStatus.ForeColor = Color.White;
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
tsl_ConnectionStatus.BackColor = SystemColors.Control;
|
|
tsl_ConnectionStatus.ForeColor = SystemColors.ControlText;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void MapViewDlg_Load(object sender, EventArgs e)
|
|
{
|
|
VieClientStatus = VIEWCLIENTSTATUS.INIT;
|
|
InitializeIcons();
|
|
InitializeCharts();
|
|
this.Text = "AirScout View Client V" + Application.ProductVersion;
|
|
this.Show();
|
|
ti_Progress.Start();
|
|
VieClientStatus = VIEWCLIENTSTATUS.CONNECTING;
|
|
}
|
|
|
|
private void tsi_Exit_Click(object sender, EventArgs e)
|
|
{
|
|
this.Close();
|
|
}
|
|
|
|
private void MapViewDlg_FormClosing(object sender, FormClosingEventArgs e)
|
|
{
|
|
ti_Progress.Stop();
|
|
Properties.Settings.Default.Save();
|
|
}
|
|
|
|
private double GetMinH(double max_alt, double H1, double H2)
|
|
{
|
|
double max = Math.Max(H1, H2);
|
|
if (max <= max_alt)
|
|
return max;
|
|
return max_alt;
|
|
}
|
|
|
|
|
|
private void UpdateCharts(ElevationPathDesignator epath, PropagationPathDesignator ppath)
|
|
{
|
|
// updates the diagram area
|
|
short[] epoints = new short[0];
|
|
PropagationPoint[] ppoints = new PropagationPoint[0];
|
|
try
|
|
{
|
|
ClearCharts();
|
|
// adjust diagram axes
|
|
Path_X.Maximum = ppath.Distance;
|
|
Elevation_X.Maximum = epath.Distance;
|
|
// get infopoints for charting
|
|
epoints = epath.GetInfoPoints();
|
|
ppoints = ppath.GetInfoPoints();
|
|
// calculate epsilon for LOS
|
|
double eps_los = Propagation.EpsilonFromHeights(epath.Location1.Elevation + ppath.QRV1.AntennaHeight, ppath.Distance, epath.Location2.Elevation + ppath.QRV2.AntennaHeight, LatLon.Earth.Radius);
|
|
// fill chart
|
|
short maxelv = short.MinValue;
|
|
double myelev = epath.Location1.Elevation;
|
|
for (int i = 0; i < epoints.Length; i++)
|
|
{
|
|
Path_Elevation.Points.Add(new OxyPlot.DataPoint(i, epoints[i]));
|
|
Min_H1.Points.Add(new OxyPlot.DataPoint(i, ppoints[i].H1));
|
|
Min_H2.Points.Add(new OxyPlot.DataPoint(i, ppoints[i].H2));
|
|
Max_H.Points.Add(new OxyPlot.DataPoint(i, Properties.Settings.Default.Planes_MaxAlt));
|
|
Min_H.Points.Add(new OxyPlot.DataPoint(i, Properties.Settings.Default.Planes_MaxAlt));
|
|
Min_H.Points2.Add(new OxyPlot.DataPoint(i, GetMinH(Properties.Settings.Default.Planes_MaxAlt, Min_H1.Points[i].Y, Min_H2.Points[i].Y)));
|
|
LOS.Points.Add(new OxyPlot.DataPoint(i, Propagation.HeightFromEpsilon(myelev + ppath.QRV1.AntennaHeight, i, eps_los, LatLon.Earth.Radius)));
|
|
Elevation.Points.Add(new OxyPlot.DataPoint(i, epoints[i]));
|
|
if (maxelv < epoints[i])
|
|
maxelv = epoints[i];
|
|
}
|
|
// adjust Y-axis --> max elv + 10%
|
|
Elevation_Y.Maximum = maxelv + maxelv * 0.1;
|
|
// invalidate plots
|
|
pm_Path.InvalidatePlot(true);
|
|
pm_Elevation.InvalidatePlot(true);
|
|
// show path legends
|
|
Charts_ShowLegends(5000);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.WriteMessage(ex.ToString(), LogLevel.Error);
|
|
}
|
|
}
|
|
|
|
private void ClearCharts()
|
|
{
|
|
try
|
|
{
|
|
// clear all points
|
|
Path_Elevation.Points.Clear();
|
|
Min_H1.Points.Clear();
|
|
Min_H2.Points.Clear();
|
|
Max_H.Points.Clear();
|
|
Min_H.Points.Clear();
|
|
Min_H.Points2.Clear();
|
|
Planes_Hi.Points.Clear();
|
|
Planes_Lo.Points.Clear();
|
|
Elevation.Points.Clear();
|
|
LOS.Points.Clear();
|
|
// update view
|
|
pm_Path.InvalidatePlot(true);
|
|
pm_Elevation.InvalidatePlot(true);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.WriteMessage(ex.ToString(), LogLevel.Error);
|
|
}
|
|
}
|
|
|
|
private void Charts_ShowLegends(int ms)
|
|
{
|
|
// enable path legends for some seconds
|
|
pm_Path.IsLegendVisible = true;
|
|
pm_Path.InvalidatePlot(true);
|
|
pm_Elevation.IsLegendVisible = true;
|
|
pm_Elevation.InvalidatePlot(true);
|
|
ti_ShowLegends.Interval = ms;
|
|
ti_ShowLegends.Start();
|
|
}
|
|
|
|
private void ti_ShowLegends_Tick(object sender, EventArgs e)
|
|
{
|
|
pm_Path.IsLegendVisible = false;
|
|
pm_Path.InvalidatePlot(true);
|
|
pm_Elevation.IsLegendVisible = false;
|
|
pm_Elevation.InvalidatePlot(true);
|
|
ti_ShowLegends.Enabled = false;
|
|
}
|
|
|
|
private void pv_Path_Paint(object sender, PaintEventArgs e)
|
|
{
|
|
// draw calsign s on chart
|
|
string mycall = Properties.Settings.Default.MyCall;
|
|
string dxcall = Properties.Settings.Default.DXCall;
|
|
int top = pv_Path.Bottom - pv_Path.Height / 2;
|
|
int left = pv_Path.Left + 50;
|
|
int right = pv_Path.Width - 38;
|
|
Font font = new Font(FontFamily.GenericSansSerif, 8, FontStyle.Bold);
|
|
Graphics g = e.Graphics;
|
|
using (StringFormat format = new StringFormat(StringFormatFlags.DirectionVertical))
|
|
{
|
|
// measure text to emulate TextAlign.Middle
|
|
int mywidth = (int)g.MeasureString(mycall, font).Width;
|
|
int dxwidth = (int)g.MeasureString(dxcall, font).Width;
|
|
using (SolidBrush brush = new SolidBrush(Color.Black))
|
|
{
|
|
if (pv_Path.Height - 50 > mywidth)
|
|
g.DrawString(mycall, font, brush, left, top - mywidth / 2, format);
|
|
if (pv_Path.Height - 50 > dxwidth)
|
|
g.DrawString(dxcall, font, brush, right, top - dxwidth / 2, format);
|
|
/*
|
|
if (pv_Path.Height > 2 * mywidth + 50)
|
|
g.DrawString(mycall, font, brush, left, top, format);
|
|
if (pv_Path.Height > 2 * dxwdith + 50)
|
|
g.DrawString(dxcall, font, brush, right, top, format);
|
|
*/
|
|
}
|
|
}
|
|
}
|
|
|
|
private void gb_Path_Resize(object sender, EventArgs e)
|
|
{
|
|
// adjust charts
|
|
pv_Path.Location = new System.Drawing.Point(0, 0);
|
|
pv_Path.Width = gb_Path.Width;
|
|
pv_Path.Height = gb_Path.Height / 2;
|
|
pv_Elevation.Location = new System.Drawing.Point(0, gb_Path.Height / 2);
|
|
pv_Elevation.Width = gb_Path.Width;
|
|
pv_Elevation.Height = gb_Path.Height / 2;
|
|
}
|
|
|
|
private void gm_Main_OnMapZoomChanged()
|
|
{
|
|
double midlat = LatLon.MidPoint(Properties.Settings.Default.MyLat, Properties.Settings.Default.MyLon, Properties.Settings.Default.DXLat, Properties.Settings.Default.DXLon).Lat;
|
|
double midlon = LatLon.MidPoint(Properties.Settings.Default.MyLat, Properties.Settings.Default.MyLon, Properties.Settings.Default.DXLat, Properties.Settings.Default.DXLon).Lon;
|
|
if ((PlayMode == AIRSCOUTPLAYMODE.FORWARD) && Properties.Settings.Default.Map_AutoCenter)
|
|
gm_Main.Position = new PointLatLng(midlat, midlon);
|
|
tb_Map_Zoom.Text = gm_Main.Zoom.ToString();
|
|
}
|
|
|
|
private void gm_Main_OnMarkerClick(GMapMarker item, MouseEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
if (e.Button == System.Windows.Forms.MouseButtons.Left)
|
|
{
|
|
// check if plane clicked
|
|
if (item.Overlay == gmo_Planes)
|
|
{
|
|
// keep the selected state
|
|
int selectedindex = SelectedPlanes.IndexOf((string)item.Tag);
|
|
// clear all other selections if tracking is en
|
|
// toogle selection of the selected plane
|
|
if (selectedindex >= 0)
|
|
{
|
|
// remove item from selected planes list
|
|
SelectedPlanes.RemoveAt(selectedindex);
|
|
}
|
|
else
|
|
{
|
|
SelectedPlanes.Add((string)item.Tag);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
// do nothing if item not found in planes list
|
|
Log.WriteMessage(ex.ToString(), LogLevel.Error);
|
|
}
|
|
}
|
|
|
|
private void btn_Map_Zoom_In_Click(object sender, EventArgs e)
|
|
{
|
|
if (gm_Main.Zoom < 20)
|
|
gm_Main.Zoom++;
|
|
}
|
|
|
|
private void btn_Map_Zoom_Out_Click(object sender, EventArgs e)
|
|
{
|
|
if (gm_Main.Zoom > 0)
|
|
gm_Main.Zoom--;
|
|
}
|
|
|
|
private void tb_MyCall_TextChanged(object sender, EventArgs e)
|
|
{
|
|
if (!Callsign.Check(tb_MyCall.Text))
|
|
return;
|
|
Properties.Settings.Default.MyCall = tb_MyCall.Text;
|
|
// get callsign info
|
|
List<LocationDesignator> l = MyLocationsFromJSON();
|
|
if (l == null)
|
|
{
|
|
cb_MyLoc.Items.Clear();
|
|
cb_MyLoc.SilentText = "";
|
|
return;
|
|
}
|
|
cb_MyLoc.Items.Clear();
|
|
cb_MyLoc.DisplayMember = "Loc";
|
|
foreach (LocationDesignator ld in l)
|
|
{
|
|
cb_MyLoc.Items.Add(ld);
|
|
}
|
|
if (cb_MyLoc.Items.Count > 0)
|
|
{
|
|
cb_MyLoc.SelectedItem = cb_MyLoc.Items[0];
|
|
Properties.Settings.Default.MyLat = ((LocationDesignator)cb_MyLoc.Items[0]).Lat;
|
|
Properties.Settings.Default.MyLon = ((LocationDesignator)cb_MyLoc.Items[0]).Lon;
|
|
}
|
|
}
|
|
|
|
private void tb_DXCall_TextChanged(object sender, EventArgs e)
|
|
{
|
|
if (!Callsign.Check(tb_DXCall.Text))
|
|
return;
|
|
Properties.Settings.Default.DXCall = tb_DXCall.Text;
|
|
// get callsign info
|
|
List<LocationDesignator> l = DXLocationsFromJSON();
|
|
if (l == null)
|
|
{
|
|
cb_DXLoc.Items.Clear();
|
|
cb_DXLoc.SilentText = "";
|
|
return;
|
|
}
|
|
cb_DXLoc.Items.Clear();
|
|
cb_DXLoc.DisplayMember = "Loc";
|
|
foreach (LocationDesignator ld in l)
|
|
{
|
|
cb_DXLoc.Items.Add(ld);
|
|
}
|
|
if (cb_DXLoc.Items.Count > 0)
|
|
{
|
|
cb_DXLoc.SelectedItem = cb_DXLoc.Items[0];
|
|
Properties.Settings.Default.DXLat = ((LocationDesignator)cb_DXLoc.Items[0]).Lat;
|
|
Properties.Settings.Default.DXLon = ((LocationDesignator)cb_DXLoc.Items[0]).Lon;
|
|
}
|
|
}
|
|
|
|
private void cb_MyLoc_TextChanged(object sender, EventArgs e)
|
|
{
|
|
|
|
}
|
|
|
|
private void cb_DXLoc_TextChanged(object sender, EventArgs e)
|
|
{
|
|
|
|
}
|
|
|
|
private void tsi_Info_Click(object sender, EventArgs e)
|
|
{
|
|
MessageBox.Show("AirScout View Client V" + Application.ProductVersion.ToString(), "Info", MessageBoxButtons.OK);
|
|
}
|
|
|
|
private void btn_Map_PlayPause_Click(object sender, EventArgs e)
|
|
{
|
|
if (PlayMode != AIRSCOUTPLAYMODE.FORWARD)
|
|
{
|
|
PlayMode = AIRSCOUTPLAYMODE.FORWARD;
|
|
btn_Map_PlayPause.ImageIndex = 0;
|
|
// draw path
|
|
DrawPath();
|
|
}
|
|
else
|
|
{
|
|
PlayMode = AIRSCOUTPLAYMODE.PAUSE;
|
|
btn_Map_PlayPause.ImageIndex = 1;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|