Plane.FormationCreator/Plane.FormationCreator/Views/MapView_CopterDrawing.cs
pxzleo 39a1002852 1解决无法退出问题
2按下shift后可以批量点中航点选择
3倒计时视觉bug
2017-09-16 12:19:05 +08:00

449 lines
17 KiB
C#

using Plane.Collections;
using Plane.Copters;
using Plane.FormationCreator.Formation;
using Plane.Logging;
using Microsoft.Maps.MapControl.WPF;
using Microsoft.Practices.ServiceLocation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Effects;
using System.Windows.Shapes;
namespace Plane.FormationCreator.Views
{
public partial class MapView
{
private class CopterDrawing
{
public CopterDrawing(ICopter copter, Map map)
{
this.Copter = copter;
_map = map;
if (copter is Copter)
{
_brush = ((Copter)copter).Brush;
_color = ((SolidColorBrush)_brush).Color;
}
else
{
_color = _colors[(_colorIndex++ % _colors.Length)];
_brush = new SolidColorBrush(_color);
}
_flightTaskManager.TasksCleared += (sender, e) =>
{
for (int i = this.Route.Locations.Count - 1; i >= 1; i--)
{
this.Route.Locations.RemoveAt(i);
}
foreach (var wp in this.Waypoints)
{
_map.Children.Remove(wp);
}
this.Waypoints.Clear();
};
}
static DropShadowEffect _selectedEffect = new DropShadowEffect();
static SolidColorBrush _selectedTaskStroke = new SolidColorBrush(Colors.White);
static Color[] _colors = new Color[]
{
Color.FromArgb(180, 255, 0, 0),
Color.FromArgb(180, 235, 97, 0),
Color.FromArgb(180, 255, 255, 0),
Color.FromArgb(180, 0, 255, 0),
Color.FromArgb(180, 0, 198, 255),
Color.FromArgb(180, 0, 122, 204),
Color.FromArgb(180, 174, 0, 255)
};
static int _colorIndex = 0;
const double COPTER_RADIUS = 12;
const double WAYPOINT_RADIUS = 6;
public ICopter Copter { get; set; }
public Grid DotContainer { get; set; }
public Polygon Dot { get; set; }
public TextBlock CopterText { get; set; }
public MapPolyline Track { get; set; }
public Location LastLocation { get; set; }
public MapPolyline Route { get; set; }
public List<Ellipse> Waypoints { get; set; } = new List<Ellipse>();
Map _map;
Color _color;
Brush _brush;
ILogger _logger = ServiceLocator.Current.GetInstance<ILogger>();
CopterManager _copterManager = ServiceLocator.Current.GetInstance<CopterManager>();
FlightTaskManager _flightTaskManager = ServiceLocator.Current.GetInstance<FlightTaskManager>();
public void AddOrMoveCopter()
{
try
{
var location = new Location(Copter.Latitude, Copter.Longitude, Copter.Altitude);
Point center = _map.LocationToViewportPoint(location);
bool locationUpdated = true;
SolidColorBrush blackBrush = new SolidColorBrush();
if (this.Dot == null)
{
Track = new MapPolyline();
Track.Stroke = _brush;
Track.StrokeThickness = 3.0;
Track.Locations = new LocationCollection();
//实时飞行航线
// _map.Children.Add(Track);
//画三角形飞机
Dot = new Polygon();
// (0,-12)(-8,12)(8,12)是个倒三角形
//
//
Dot.Points.Add(new Point(0, -COPTER_RADIUS));
Dot.Points.Add(new Point(-COPTER_RADIUS * 2 / 3, COPTER_RADIUS));
Dot.Points.Add(new Point(COPTER_RADIUS * 2 / 3, COPTER_RADIUS));
Dot.Fill = _brush; // new SolidColorBrush(Color.FromArgb(200, 0, 122, 204));
Dot.StrokeThickness = 1;
Dot.Width = COPTER_RADIUS * 2;
Dot.Height = COPTER_RADIUS * 2;
ToolTip tt = new ToolTip();
tt.Content = $"Name: {Copter.Name}, Location: {location}";
Dot.ToolTip = tt;
DotContainer = new Grid { Tag = COPTER_TAG };
DotContainer.Children.Add(Dot);
//飞机里面的编号
CopterText = new TextBlock
{
Text = Copter.Name,
Foreground = new SolidColorBrush(Colors.Black),
Margin = new Thickness(-COPTER_RADIUS * 2, -COPTER_RADIUS * 1.5, 0, 0),
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center
};
DotContainer.Children.Add(CopterText);
//飞机加入地图
_map.Children.Add(DotContainer);
MapLayer.SetZIndex(DotContainer, 100);
this.Route = new MapPolyline { Locations = new LocationCollection { location } };
this.Route.Stroke = _brush;
this.Route.StrokeThickness = 2.0;
//显示计划航线
// _map.Children.Add(this.Route);
this.LastLocation = location;
RegisterEventHandlersForDraggingCopter(DotContainer);
}
else
{
if (Copter.MissionStatus == 1)
{
CopterText.Foreground = new SolidColorBrush(Colors.White);
}
else {
CopterText.Foreground = new SolidColorBrush(Colors.Black);
}
if (LastLocation != null && location.CalcDistance(LastLocation) < 0.1)
{
locationUpdated = false;
}
if (locationUpdated)
{
//dot.RenderTransform = new RotateTransform(GeographyUtils.CalcDirection2D(lastLocation.Latitude, lastLocation.Longitude, location.Latitude, location.Longitude).RadiansToDegrees());
(Dot.ToolTip as ToolTip).Content = $"Name: {Copter.Name}, Location: {location}";
}
}
if (Copter.GetShowLEDAsync())
blackBrush.Color = Colors.White;
else
blackBrush.Color = Colors.Transparent;
Dot.Stroke = blackBrush;
var trans = Dot.RenderTransform as RotateTransform;
if (trans == null)
{
Dot.RenderTransform = new RotateTransform(Copter.Heading);
}
else
{
if (trans.Angle != Copter.Heading)
{
trans.Angle = Copter.Heading;
}
}
if (locationUpdated)
{
Track.Locations.Add(location);
this.Route.Locations[0] = location;
MapLayer.SetPosition(Dot.Parent, location);
this.LastLocation = location;
}
}
catch (Exception ex)
{
_logger.Log(ex);
}
}
public void AddWaypoint(Location location, FlightTaskType type)
{
// Add waypoint.
var wp = new Ellipse
{
Tag = WAYPOINT_TAG,
Fill = _brush,
StrokeThickness = 2,
Width = WAYPOINT_RADIUS * 2,
Height = WAYPOINT_RADIUS * 2
}; ;
Waypoints.Add(wp);
_map.Children.Add(wp);
MapLayer.SetZIndex(wp, 100);
var wpPos = _map.LocationToViewportPoint(location);
wpPos.X -= WAYPOINT_RADIUS;
wpPos.Y -= WAYPOINT_RADIUS;
MapLayer.SetPosition(wp, _map.ViewportPointToLocation(wpPos));
SetEffect(_copterManager.SelectedCopters.Contains(Copter));
// Add route point.
Route.Locations.Add(location);
// Register event handlers.
RegisterEventHandlersForDraggingWaypoint(wp, taskIndex: Waypoints.Count);
// Register event handlers for task info.
RegisterEventHandlersForTaskInfo(wp, taskIndex: Waypoints.Count);
}
private void RegisterEventHandlersForDraggingCopter(Grid copterElement)
{
var dragMoving = false;
double offsetX = 0;
double offsetY = 0;
copterElement.MouseLeftButtonDown += (sender, e) =>
{
_copterManager.Select(this.Copter);
if (Copter is FakeCopter)
{
var posInObject = e.GetPosition(copterElement);
offsetX = posInObject.X;
offsetY = posInObject.Y;
dragMoving = true;
}
};
_map.MouseMove += (sender, e) =>
{
if (dragMoving)
{
var pos = e.GetPosition(_map);
pos.X -= offsetX;
pos.Y -= offsetY;
MapLayer.SetPosition(copterElement, _map.ViewportPointToLocation(pos));
var center = _map.ViewportPointToLocation(pos);
var routePoint = this.Route.Locations[0];
routePoint.Latitude = center.Latitude;
routePoint.Longitude = center.Longitude;
var fc = Copter as FakeCopter;
fc.SetProperties(
latitude: center.Latitude,
longitude: center.Longitude
);
}
};
_map.MouseLeftButtonUp += (sender, e) =>
{
if (dragMoving) dragMoving = false;
};
}
private Dictionary<object, bool> _dictDraggingWp = new Dictionary<object, bool>();
private void RegisterEventHandlersForDraggingWaypoint(Ellipse wp, int taskIndex)
{
_dictDraggingWp[wp] = false;
double offsetX = 0;
double offsetY = 0;
wp.MouseLeftButtonDown += (sender, e) =>
{
_copterManager.Select(this.Copter);
_flightTaskManager.Select(taskIndex, this.Copter);
var posInObject = e.GetPosition(wp);
offsetX = posInObject.X;
offsetY = posInObject.Y;
_dictDraggingWp[wp] = true;
};
wp.MouseRightButtonDown += (sender, e) =>
{
_flightTaskManager.RightSelect(taskIndex, this.Copter);
};
_map.MouseMove += (sender, e) =>
{
if (_dictDraggingWp[wp])
{
var eventPos = e.GetPosition(_map);
var leftTopPos = new Point(eventPos.X - offsetX, eventPos.Y - offsetY);
MapLayer.SetPosition(wp, _map.ViewportPointToLocation(leftTopPos));
var centerPos = new Point(leftTopPos.X + WAYPOINT_RADIUS, leftTopPos.Y + WAYPOINT_RADIUS);
var centerLoc = _map.ViewportPointToLocation(centerPos);
var routePoint = this.Route.Locations[taskIndex];
var modifyingSingleCopterInfo = _flightTaskManager.SelectedTask.SingleCopterInfos.Find(i => i.Copter == Copter);
modifyingSingleCopterInfo.TargetLat = routePoint.Latitude = centerLoc.Latitude;
modifyingSingleCopterInfo.TargetLng = routePoint.Longitude = centerLoc.Longitude;
}
};
_map.MouseLeftButtonUp += (sender, e) =>
{
if (_dictDraggingWp[wp]) _dictDraggingWp[wp] = false;
};
}
private void RegisterEventHandlersForTaskInfo(Ellipse wp, int taskIndex)
{
var info = _flightTaskManager.Tasks[taskIndex].SingleCopterInfos.FirstOrDefault(i => i.Copter == this.Copter);
if (info == null) return;
info.PropertyChanged += (sender, e) =>
{
switch (e.PropertyName)
{
case nameof(FlightTaskSingleCopterInfo.TargetLat):
case nameof(FlightTaskSingleCopterInfo.TargetLng):
case nameof(FlightTaskSingleCopterInfo.TargetAlt):
if (!_dictDraggingWp.GetValue(wp, false))
{
var centerLocation = new Location(info.TargetLat, info.TargetLng, info.TargetAlt);
var centerPos = _map.LocationToViewportPoint(centerLocation);
var leftTopPos = new Point(centerPos.X - WAYPOINT_RADIUS, centerPos.Y - WAYPOINT_RADIUS);
MapLayer.SetPosition(wp, _map.ViewportPointToLocation(leftTopPos));
var routePoint = Route.Locations[taskIndex];
routePoint.Latitude = info.TargetLat;
routePoint.Longitude = info.TargetLng;
routePoint.Altitude = info.TargetAlt;
}
break;
}
};
}
public void RemoveCopter()
{
_map.Children.Remove(this.DotContainer);
_map.Children.Remove(this.Track);
_map.Children.Remove(this.Route);
foreach (var item in this.Waypoints)
{
_map.Children.Remove(item);
}
}
public void SetShowroute(bool? showroute)
{
if (showroute ?? false )
_map.Children.Add(this.Route);
else
_map.Children.Remove(this.Route);
}
public void SetShowtrack(bool? showtrack)
{
if (showtrack ?? false)
_map.Children.Add(Track);
else
_map.Children.Remove(Track);
}
public void SetEffect(bool selected)
{
Dot.Effect = selected ? _selectedEffect : null;
Waypoints.ForEach(wp => wp.Effect = Dot.Effect);
}
public void SetTaskEffect(int taskIndex)
{
var wpIndex = taskIndex - 1; // Waypoints 中没有起飞点。
if (wpIndex >= 0 && wpIndex < Waypoints.Count)
{
Waypoints.ForEach(p => p.Stroke = null);
var wp = Waypoints[wpIndex];
wp.Stroke = _selectedTaskStroke;
}
}
// 右击任务时触发
public void SetTaskRightEffect(int taskIndex, bool flag)
{
var wpIndex = taskIndex - 1; // Waypoints 中没有起飞点。
if (wpIndex >= 0 && wpIndex < Waypoints.Count)
{
// Waypoints.ForEach(p => p.Stroke = null);
var wp = Waypoints[wpIndex];
// Route.Locations.RemoveAt(wpIndex);
// Route.Visibility = Visibility.Hidden;
// wp.Stroke = _selectedTaskStroke;
// var flightTaskTmp = _flightTaskManager.Tasks[taskIndex];
if (!flag)
{
wp.Visibility = Visibility.Hidden;
//Route.Visibility = Visibility.Hidden;
//Route.Children.RemoveAt(1);
}
else
{
wp.Visibility = Visibility.Visible;
//Route.Visibility = Visibility.Visible;
}
}
}
}
}
}