Plane.FormationCreator/Plane.FormationCreator/Views/MapView.xaml.cs
xu f787069624 修改任务选中颜色,更明显
可导入ai和obj模型文件
增加删除任务和在任务中插入任务功能(添加改为选中任务后一个添加)
航线改为默认显示,优化右键隐藏航点功能
更改飞机和航点默认颜色
界面加入“飞行前准备”等分组页面,更方便操作
修改bug:清除飞机重新添加后飞行航线发虚,右键隐藏状态没有重置,
2020-04-20 00:12:11 +08:00

682 lines
26 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Plane.Copters;
using Plane;
using Plane.FormationCreator.Formation;
using Plane.Logging;
using Microsoft.Win32;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Plane.Collections;
using System.Windows.Media.Effects;
using Microsoft.Practices.ServiceLocation;
using Plane.FormationCreator.ViewModels;
using Plane.Geography;
using Plane.FormationCreator.Maps;
using Plane.Windows.Messages;
using GMap.NET;
using GMap.NET.WindowsPresentation;
using GMap.NET.MapProviders;
using System.Globalization;
namespace Plane.FormationCreator.Views
{
/// <summary>
/// Interaction logic for MapView.xaml
/// </summary>
public partial class MapView : UserControl
{
public void initmap()
{
gmap.MinZoom = 2; //最小缩放
gmap.MaxZoom = 30; //最大缩放
gmap.Zoom = 19; //当前缩放
gmap.ShowCenter = true; //不显示中心十字点
gmap.DragButton = MouseButton.Middle; //中键拖拽地图
}
public MapView()
{
InitializeComponent();
this.DataContext = ServiceLocator.Current.GetInstance<MapViewModel>();
gmap.MapProvider = GMapProviders.BingHybridMap; //google china 地图
initmap();
gmap.Position = new LatLng(40.07734857737275, 116.34323845862502).ToGCJ02();
_mapManager.MapView = this;
_mapManager.SetCenterGetter(() => new LatLng { Lat = gmap.Position.ToWGS84().Lat, Lng = gmap.Position.ToWGS84().Lng });
_flightTaskManager.TaskAdded += FlightTaskManager_TaskAdded;
_flightTaskManager.TaskDeled += FlightTaskManager_TaskDeled;
_flightTaskManager.OnOriginalSet += FlightTaskManager_SetOriginal;
/*
Task.Factory.StartNew(async () =>
{
int delay = 500;
while (true)
{
if (Dispatcher.Invoke(RemoveLoadingErrorMessage))
{
delay = 2000;
}
await Task.Delay(delay);
}
});
*/
_copterManager.SelectedCoptersChanged += (sender, e) =>
{
//if (AppEx.Instance.CurrentMode.IsForTasks())
//{
e.RemovedCopters?.ForEach(copter => _copterDrawings.GetValue(copter)?.SetEffect(false));
e.AddedCopters?.ForEach(copter => _copterDrawings.GetValue(copter)?.SetEffect(true));
//}
};
_flightTaskManager.PropertyChanged += (sender, e) =>
{
switch (e.PropertyName)
{
//选中任务时触发
case nameof(FlightTaskManager.SelectedTaskIndex):
//_copterDrawings有多少架飞机航点
foreach (var item in _copterDrawings)
{
var copterDrawing = item.Value;
//设置选中的航点白边和下面任务块的白影
copterDrawing.ShowWaypoint(_flightTaskManager.SelectedTaskIndex);
copterDrawing.SetTaskEffect(_flightTaskManager.SelectedTaskIndex);
//画计划航线
copterDrawing.ResetRoute(_flightTaskManager.SelectedTaskIndex);
}
break;
case nameof(FlightTaskManager.RightSelectedTaskIndex): // 单击右键触发
int taskIndexTmp = Math.Abs(_flightTaskManager.RightSelectedTaskIndex);
foreach (var item in _copterDrawings)
{
var copterDrawing = item.Value;
copterDrawing.SetTaskRightEffect(taskIndexTmp,
_flightTaskManager.Tasks[taskIndexTmp].IsRightSelected);
}
_flightTaskManager.Tasks[taskIndexTmp].IsRightSelected = !_flightTaskManager.Tasks[taskIndexTmp].IsRightSelected;
break;
default:
break;
}
};
gmap.MouseLeftButtonDown += (sender, e) =>
{
if (IsMouseOnCopterOrWaypoint(e.OriginalSource))
{
e.Handled = true;
}
};
_copterManager.Copters.ForEach(copter => copter.LocationChanged += Copter_LocationChanged);
_copterManager.Copters.CollectionChanged += Copters_CollectionChanged;
//_copterManager.Copters.ForEach(copter => AddOrMoveCopterForModifyingTask(copter));
//_copterManager.Copters.CollectionChanged += CoptersForModifyingTask_CollectionChanged;
gmap.MouseDoubleClick += async (sender, e) =>
{
e.Handled = true;
//// Test
//var pos = map.ViewportPointToLocation(e.GetPosition(map));
//AddOrMoveCopter(new FakeCopter(pos.Latitude, pos.Longitude));
// 林俊清, 20150930, AppMode 存在意义已不大;只有正在运行任务的时候才不允许指点。
//if (AppEx.Current.AppMode != AppMode.ControllingCopters) return;
if (_flightTaskManager.IsPaused == false) return;
var copters = _copterManager.AcceptingControlCopters;
if (!copters.Any()) return;
Point clickPoint = e.GetPosition(gmap);
var pos = gmap.FromLocalToLatLng((int)clickPoint.X, (int)clickPoint.Y);
var centerLat = copters.Average(c => c.Latitude);
var centerLng = copters.Average(c => c.Longitude);
var latDelta = pos.Lat - centerLat;
var lngDelta = pos.Lng - centerLng;
await Task.WhenAll(copters.Select(copter => copter.FlyToAsync(copter.Latitude + latDelta, copter.Longitude + lngDelta, copter.Altitude)));
};
var center = _appConfig.Center;
gmap.Position = new LatLng(center.Lat, center.Lng).ToGCJ02();
gmap.Zoom = _appConfig.ZoomLevel;
gmap.OnMapZoomChanged += () =>
{
// if ( gmap.Mode.GetType().ToString() == "Microsoft.Maps.MapControl.WPF.AerialMode")
// if (map.ZoomLevel >19)
// map.ZoomLevel = 19;
if (originalMarker != null && gmap.Markers.Contains(originalMarker))
{
PointLatLng location = new LatLng(_flightTaskManager.OriginLat, _flightTaskManager.OriginLng).ToGCJ02();
GPoint wpPos = gmap.FromLatLngToLocal(location);
//Point wpPos = gmap.LocationToViewportPoint(location);
wpPos.X -= (long)ORIGIN_RADIUS;
wpPos.Y -= (long)ORIGIN_RADIUS;
originalMarker.Position = gmap.FromLocalToLatLng((int)wpPos.X, (int)wpPos.Y);
//MapLayer.SetPosition(original, gmap.ViewportPointToLocation(wpPos));
}
};
GMapMarker rectangleMarker = null;
Rectangle rectangle = new Rectangle();
bool drawRectangle = false;
Point startPosition = new Point();
Point leftTopPoint = new Point();
gmap.MouseRightButtonDown += (sender, e) =>
{
startPosition = e.GetPosition(this);
rectangleMarker = new GMapMarker(gmap.FromLocalToLatLng((int)startPosition.X, (int)startPosition.Y));
rectangle = new Rectangle();
rectangle.Width = 0;
rectangle.Height = 0;
rectangle.StrokeThickness = 1;
rectangle.Stroke = new SolidColorBrush(Color.FromRgb(0, 120, 215));
rectangle.Fill = new SolidColorBrush(Color.FromArgb(80, 0, 120, 215));
rectangle.Tag = "Rectangle";
rectangleMarker.Shape = rectangle;
rectangleMarker.Tag = "Rectangle";
gmap.Markers.Add(rectangleMarker);
//MapLayer.SetPosition(rectangle, map.ViewportPointToLocation(startPosition));
drawRectangle = true;
};
gmap.MouseMove += (sender, e) =>
{
if (drawRectangle)
{
Point mousePosition = e.GetPosition(gmap);
rectangle.Width = Math.Abs(mousePosition.X - startPosition.X);
rectangle.Height = Math.Abs(mousePosition.Y - startPosition.Y);
leftTopPoint = new Point(Math.Min(mousePosition.X, startPosition.X), Math.Min(mousePosition.Y, startPosition.Y));
rectangleMarker.Position = gmap.FromLocalToLatLng((int)leftTopPoint.X, (int)leftTopPoint.Y);
//MapLayer.SetPosition(rectangle, map.ViewportPointToLocation(leftTopPoint));
}
};
int selectedCount = 0;
gmap.MouseRightButtonUp += (sender, e) =>
{
selectedCount = 0;
if (rectangleMarker != null && gmap.Markers.Contains(rectangleMarker))
{
gmap.Markers.Remove(rectangleMarker);
if (!_copterManager.shiftkeydown)
_copterManager.Select(null);
if (_flightTaskManager.SelectedTask != null && _flightTaskManager.SelectedTask.TaskType != FlightTaskType.TakeOff)
{
_copterManager.shiftkeydown = true;
foreach (FlightTaskSingleCopterInfo taskCopterInfo in _flightTaskManager.SelectedTask.SingleCopterInfos)
{
PointLatLng seekLocation = new LatLng(taskCopterInfo.TargetLat, taskCopterInfo.TargetLng).ToGCJ02();
GPoint seekPoint = gmap.FromLatLngToLocal(seekLocation);
if ((seekPoint.X > leftTopPoint.X && seekPoint.X < leftTopPoint.X + rectangle.Width) &&
seekPoint.Y > leftTopPoint.Y && seekPoint.Y < leftTopPoint.Y + rectangle.Height)
{
selectedCount++;
if (_copterManager.ShowCopter.Count != 0 )
{
if (_copterManager.ShowCopter.Contains(taskCopterInfo.Copter))
{
_copterManager.Select(taskCopterInfo.Copter);
}
}
else
_copterManager.Select(taskCopterInfo.Copter);
}
}
_copterManager.shiftkeydown = false;
}
}
rectangle = null;
rectangleMarker = null;
drawRectangle = false;
};
gmap.MouseLeave += (sender, e) =>
{
if (gmap.Markers.Contains(rectangleMarker))
{
gmap.Markers.Remove(rectangleMarker);
}
rectangle = null;
drawRectangle = false;
};
gmap.MouseMove += new MouseEventHandler(OriginalMove);
gmap.MouseLeftButtonUp += new MouseButtonEventHandler(OriginalMouseUp);
}
private CopterManager _copterManager = ServiceLocator.Current.GetInstance<CopterManager>();
private MapManager _mapManager = ServiceLocator.Current.GetInstance<MapManager>();
private FlightTaskManager _flightTaskManager = ServiceLocator.Current.GetInstance<FlightTaskManager>();
private AppConfig _appConfig = ServiceLocator.Current.GetInstance<AppConfig>();
const string COPTER_TAG = "Copter";
const string WAYPOINT_TAG = "Waypoint";
const string ORIGINALPOINT_TAG = "Originalpoint";
public void Refresh()
{
foreach (var drawing in _copterDrawings.Values)
{
drawing.Track.Locations.Clear();
}
}
public bool RemoveLoadingErrorMessage()
{
/*
var errorElement = map.Children.OfType<LoadingErrorMessage>().FirstOrDefault();
if (errorElement != null)
{
map.Children.Remove(errorElement);
return true;
}
else
{
return false;
}
*/
return true;
}
public void GoHome()
{
gmap.Zoom = 19;
//map.Center = new Location(40.0559055, 116.322233);
//gmap.Position = new LatLng(40.6801557090282, 114.670060030638).ToGCJ02();
gmap.Position = new PointLatLng(38.973616, 117.200116);
}
private void Copters_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
e.OldItems?.ForEach<ICopter>(async copter =>
{
copter.LocationChanged -= Copter_LocationChanged;
await Task.Delay(100); // 如果不等待一段时间Copter_DataStreamReceived 很可能再被调用一次。
RemoveCopter(copter);
});
e.NewItems?.ForEach<ICopter>(copter => copter.LocationChanged += Copter_LocationChanged);
}
private void Copter_LocationChanged(object sender, EventArgs e)
{
var copter = sender as ICopter;
if (App.Current.CheckAccess())
{
AddOrMoveCopter(copter);
}
else
{
App.Current.Dispatcher.InvokeAsync(() => AddOrMoveCopter(copter));
}
}
private Dictionary<ICopter, CopterDrawing> _copterDrawings = new Dictionary<ICopter, CopterDrawing>();
private void AddOrMoveCopter(ICopter copter)
{
var drawing = _copterDrawings.ContainsKey(copter) ?
_copterDrawings[copter] :
(_copterDrawings[copter] = new CopterDrawing(copter, gmap));
drawing.AddOrMoveCopter();
}
private void RemoveCopter(ICopter copter)
{
if (_copterDrawings.ContainsKey(copter))
{
var drawing = _copterDrawings[copter];
drawing.RemoveCopter();
_copterDrawings.Remove(copter);
}
}
public void ShowAllWaypoint()
{
foreach (var item in _copterDrawings)
{
var copterDrawing = item.Value;
copterDrawing.ShowAllWaypoint();
}
}
public void ClearCopters()
{
/*
for (int i = map.Children.Count - 1; i >= 0; i--)
{
if (!(map.Children[i] is MapTileLayer))
{
map.Children.RemoveAt(i);
}
}
foreach (var item in _copterDrawings)
{
item.Value.RemoveMap_ViewChanged();
}
*/
gmap.Markers.Clear();
//_copterManager.Copters.ForEach(copter => _copterDrawings[copter]=null );
_copterDrawings.Clear();
}
private bool IsMouseOnCopterOrWaypoint(object originalSource)
{
var elem = originalSource as FrameworkElement;
string tag;
while (elem != gmap && elem != null)
{
tag = elem.Tag?.ToString();
if (tag == COPTER_TAG || tag == WAYPOINT_TAG || tag == ORIGINALPOINT_TAG)
{
return true;
}
elem = elem.Parent as FrameworkElement;
}
return false;
}
private void FlightTaskManager_TaskAdded(object sender, FlightTaskAddedEventArgs e)
{
//给每个任务在地图上添加航点
foreach (var info in e.AddedTask.SingleCopterInfos)
{
var drawingInfo = _copterDrawings[info.Copter];
//计算位置
var location = new Microsoft.Maps.MapControl.WPF.Location(info.TargetLat, info.TargetLng, info.TargetAlt);
//添加航点
drawingInfo.AddWaypoint(location, e.AddedTask.TaskType,e.AddedTask);
}
}
private void FlightTaskManager_TaskDeled(object sender, FlightTaskDeledEventArgs e)
{
//清除每架飞机的这个任务的航点
// foreach (var info in e.DeledTask.SingleCopterInfos)
// {
// _copterDrawings[info.Copter].Waypoints.RemoveAt(e.TaskIndex);
// }
}
GMapMarker originalMarker = null;
Microsoft.Expression.Shapes.RegularPolygon original = null;
const double ORIGIN_RADIUS = 12;
private void FlightTaskManager_SetOriginal(object sender, FlightTaskAddedOriginalEventArgs e)
{
if (_copterManager.Copters.Count == 0) return;
if (gmap.Markers.Contains(originalMarker))
gmap.Markers.Remove(originalMarker);
PointLatLng location = new LatLng(_copterManager.Copters[0].Latitude, _copterManager.Copters[0].Longitude).ToGCJ02();
GPoint point = gmap.FromLatLngToLocal(location);
point.X -= (long)ORIGIN_RADIUS;
point.Y -= (long)ORIGIN_RADIUS;
PointLatLng mapLocation = gmap.FromLocalToLatLng((int)point.X , (int)point.Y);
original = new Microsoft.Expression.Shapes.RegularPolygon
{
Tag = ORIGINALPOINT_TAG,
Fill = new SolidColorBrush(Color.FromArgb(200, 237, 155, 3)),
Stroke = new SolidColorBrush(Color.FromArgb(200, 238, 80, 238)),
StrokeThickness = 1,
Width = ORIGIN_RADIUS * 2,
Height = ORIGIN_RADIUS * 2,
InnerRadius = 0.5,
PointCount = 5,
};
originalMarker = new GMapMarker(mapLocation);
originalMarker.ZIndex = 200;
originalMarker.Shape = original;
gmap.Markers.Add(originalMarker);
//MapLayer.SetPosition(original, mapLocation);
//MapLayer.SetZIndex(original, 200);
original.ToolTip = location.ToString();
originaDrag = false;
_flightTaskManager.OriginLat = location.Lat;
_flightTaskManager.OriginLng = location.Lng;
original.MouseLeftButtonDown += new MouseButtonEventHandler(OriginalMouseDown);
}
private bool originaDrag = false;
double originX = 0;
double originY = 0;
double wpOffsetX = 0;
double wpOffsetY = 0;
private void OriginalMouseDown(object sender, MouseButtonEventArgs e)
{
originaDrag = true;
gmap.CanDragMap = false;
var originPoint = e.GetPosition(gmap);
originX = originPoint.X;
originY = originPoint.Y;
var posInObject = e.GetPosition(original);
wpOffsetX = posInObject.X;
wpOffsetY = posInObject.Y;
}
private void OriginalMove(object sender, MouseEventArgs e)
{
if (originaDrag)
{
Point eventPos = e.GetPosition(gmap);
var leftTopPos = new Point(eventPos.X - wpOffsetX, eventPos.Y - wpOffsetY);
originalMarker.Position = gmap.FromLocalToLatLng((int)leftTopPos.X, (int)leftTopPos.Y);
//MapLayer.SetPosition(original, map.ViewportPointToLocation(leftTopPos));
}
}
private void OriginalMouseUp(object sender, MouseButtonEventArgs e)
{
if (originaDrag)
{
Point eventPos = e.GetPosition(gmap);
var centrePos = new Point(eventPos.X - wpOffsetX + ORIGIN_RADIUS, eventPos.Y - wpOffsetY + ORIGIN_RADIUS);
PointLatLng location = gmap.FromLocalToLatLng((int)centrePos.X, (int)centrePos.Y);
_flightTaskManager.OriginLat = location.Lat;
_flightTaskManager.OriginLng = location.Lng;
original.ToolTip = location.ToString();
//Clipboard.SetDataObject(string.Format("{0},{1}", location.Lat, location.Lng), true);
originaDrag = false;
gmap.CanDragMap = true;
}
}
private void MapSelectionComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
switch ((e.AddedItems[0] as FrameworkElement).Tag.ToString())
{
case "Bing地图":
gmap.MapProvider = GMapProviders.BingHybridMap;
break;
case "谷歌地图":
gmap.MapProvider = GMapProviders.GoogleChinaHybridMap;
break;
case "高德地图":
gmap.MapProvider = GMapProviders.AMapStatelite;
break;
}
initmap();
/*
switch ((e.AddedItems[0] as FrameworkElement).Tag.ToString())
{
case "卫星地图":
map.Mode = new AerialMode();
RemoveTileLayers();
break;
case "道路":
// map.Mode = new GoogleMode();
map.Mode = new RoadMode();
RemoveTileLayers();
break;
case "OpenStreet":
map.Mode = new MercatorMode();
if (!map.Children.OfType<OpenStreetMapTileLayer>().Any())
{
map.Children.Add(new OpenStreetMapTileLayer
{ UriFormat =
"http://tile.openstreetmap.org/{z}/{x}/{y}.png"
});
}
break;
}
*/
}
private void showallpoint_Checked(object sender, RoutedEventArgs e)
{
CheckBox chk = (CheckBox)sender;
bool ischecked= chk.IsChecked ?? false;
foreach (var taskitme in _flightTaskManager.Tasks)
{
// if taskitme.IsRightSelected = chk.IsChecked ?? true;
if ((taskitme.IsRightSelected == ischecked) && (!taskitme.IsSelected))
{
_flightTaskManager.RightSelect(taskitme);
// TaskbarControl.setRightSelect(taskitme, ischecked);
}
}
}
private void showpanline_Checked(object sender, RoutedEventArgs e)
{
CheckBox chk = (CheckBox)sender;
foreach (var item in _copterDrawings)
{
var copterDrawing = item.Value;
_flightTaskManager.showroute = chk.IsChecked??false;
copterDrawing.UpdateShowroute();
}
}
private void showrealtimeline_Checked(object sender, RoutedEventArgs e)
{
CheckBox chk = (CheckBox)sender;
foreach (var item in _copterDrawings)
{
var copterDrawing = item.Value;
copterDrawing.SetShowtrack (chk.IsChecked);
}
}
private void RemoveTileLayers()
{
/*
for (int i = map.Children.Count - 1; i >= 0; i--)
{
if (map.Children[i] is MapTileLayer)
{
map.Children.RemoveAt(i);
}
}
*/
}
private void Map_Opacity(object sender, RoutedEventArgs e)
{
if (gmap.Opacity == 1)
{
gmap.Opacity = 0.5;
}
else
{
gmap.Opacity = 1;
}
}
private void Load_Background(object sender, RoutedEventArgs e)
{
var dialog = new OpenFileDialog
{
Filter = "图片 |*.jpg;*.bmp;*.png"
};
if (dialog.ShowDialog() == true)
{
ImageBrush ib = new ImageBrush();
ib.AlignmentX = AlignmentX.Left;
ib.AlignmentY = AlignmentY.Top;
ib.Stretch = Stretch.None;
ib.ImageSource = new BitmapImage(new Uri(dialog.FileName, UriKind.RelativeOrAbsolute));
grid_bg.Background = ib;
gmap.Opacity = 0.5;
}
}
}
static class LocationExtensions
{
public static double CalcDistance(this Microsoft.Maps.MapControl.WPF.Location loc1, Microsoft.Maps.MapControl.WPF.Location loc2)
{
if (loc1 == null)
{
throw new ArgumentNullException(nameof(loc1));
}
if (loc2 == null)
{
throw new ArgumentNullException(nameof(loc2));
}
return GeographyUtils.CalcDistance(loc1.Latitude, loc1.Longitude, loc1.Altitude, loc2.Latitude, loc2.Longitude, loc2.Altitude);
}
}
}