using Plane.Collections; using Plane.Copters; using Plane.FormationCreator.Formation; using Plane.Logging; 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; using GMap.NET.WindowsPresentation; using GMap.NET; using Plane.FormationCreator.Maps; using Microsoft.Maps.MapControl.WPF; using Plane.FormationCreator.ViewModels; namespace Plane.FormationCreator.Views { public partial class MapView { private class CopterDrawing { public CopterDrawing(ICopter copter, GoogleMap.GMap 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); } Color Copterdefaultcolor = (Color)ColorConverter.ConvertFromString("#" + CopterManager.CopterDefaultColor); _brush = new SolidColorBrush(Copterdefaultcolor); _flightTaskManager.TasksCleared += (sender, e) => { //清除计划航线 if (Route!=null) Route.Points.Clear(); // for (int i = this.Route.Locations.Count - 1; i >= 1; i--) // { // this.Route.Locations.RemoveAt(i); // } foreach (var wp in this.Waypoints) { _map.Markers.Remove(wp); } this.Waypoints.Clear(); }; //_map.ViewChangeOnFrame += new EventHandler(Map_ViewChanged); //删除任务事件 _flightTaskManager.TaskDeled += (sender, e) => { if (this.Waypoints.Count == 0) return; // Waypoints没有起飞任务所以-1 int WaypointsIndex = e.TaskIndex - 1; //删除地图上的航点 var wp = this.Waypoints[WaypointsIndex]; _map.Markers.Remove(wp); //删除航点列表里的航点 this.Waypoints.RemoveAt(WaypointsIndex); }; selectMarkup.Width = 7; selectMarkup.Height = 7; selectMarkup.HorizontalAlignment = HorizontalAlignment.Left; selectMarkup.VerticalAlignment = VerticalAlignment.Top; selectMarkup.Fill = new SolidColorBrush(Colors.Red); //选中做红色标记 } Rectangle selectMarkup = new Rectangle(); 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 GMapMarker DotMarker { 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 GMapRoute Route { get; set; } //某架飞机的地图显示航点列表 public List Waypoints { get; set; } = new List(); GoogleMap.GMap _map; Color _color; public Brush _brush; ILogger _logger = ServiceLocator.Current.GetInstance(); CopterManager _copterManager = ServiceLocator.Current.GetInstance(); FlightTaskManager _flightTaskManager = ServiceLocator.Current.GetInstance(); View3DViewModel _view3DViewModel = ServiceLocator.Current.GetInstance(); private void Map_ViewChanged(object sender, MapEventArgs e) { /* for (int index = 1; index < _flightTaskManager.Tasks.Count; index++) { var info = _flightTaskManager.Tasks[index].SingleCopterInfos.Find(i => i.Copter == this.Copter); ; ShapesContainer wpContainer = Waypoints[index - 1]; //起飞任务没有Waypoint; Location location = new Location(info.TargetLat, info.TargetLng); Point wpPos = _map.LocationToViewportPoint(location); wpPos.X -= WAYPOINT_RADIUS; wpPos.Y -= WAYPOINT_RADIUS; MapLayer.SetPosition(wpContainer, _map.ViewportPointToLocation(wpPos)); } */ } public void AddOrMoveCopter() { if (!_flightTaskManager.TaskRun_2D) return; //不在2D模式运行直接退出 try { var location = new Microsoft.Maps.MapControl.WPF.Location(Copter.Latitude, Copter.Longitude, Copter.Altitude); if (this.Dot != null ) { if (Copter is PLCopter && !Copter.IsGpsAccurate) this.Dot.Fill = new SolidColorBrush(Color.FromRgb(0, 0, 0)); else this.Dot.Fill = _brush; if (Copter.LEDColor != null && Copter.LEDColor!="") { Color color = (Color)ColorConverter.ConvertFromString("#" + Copter.LEDColor); _brush = new SolidColorBrush(color); if (this.Dot.Fill != _brush) { this.Dot.Fill = _brush; } } } PointLatLng gmapLatLng = new LatLng(location.Latitude, location.Longitude).ToGCJ02(); GPoint center = _map.FromLatLngToLocal(gmapLatLng); 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(); 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.White), Margin = new Thickness(-COPTER_RADIUS * 2, -COPTER_RADIUS * 1.5, 0, 0), HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center }; DotMarker = new GMapMarker(new PointLatLng(0, 0)); DotContainer.Children.Add(CopterText); DotMarker.Shape = DotContainer; _map.Markers.Add(DotMarker); //MapLayer.SetZIndex(DotContainer, 100); this.Route = new GMapRoute(new List() { gmapLatLng, gmapLatLng }); /* Path path = new Path() { Stroke = new SolidColorBrush(Colors.Red), StrokeThickness = 2.0 }; this.Route.Shape = path; */ //显示计划航线 //_map.Markers.Add(Route); this.LastLocation = location; RegisterEventHandlersForDraggingCopter(DotMarker); } else { if ((bool)_copterManager.CopterStatus[_copterManager.Copters.IndexOf(Copter)]) { CopterText.Foreground = new SolidColorBrush(Colors.Red); } else { CopterText.Foreground = new SolidColorBrush(Colors.White); } 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}"; } } switch (_copterManager.SortType) { case CopterManager.CopterSortType.ByID: CopterText.Text = Copter.Name; CopterText.Foreground = new SolidColorBrush(Colors.White); break; case CopterManager.CopterSortType.ByVID: case CopterManager.CopterSortType.ByVIDShowAll: CopterText.Text = Copter.VirtualId.ToString(); CopterText.Foreground = new SolidColorBrush(Colors.Yellow); break; default: CopterText.Text = Copter.Name; CopterText.Foreground = new SolidColorBrush(Colors.White); break; } 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); DotMarker.Position = new LatLng(location.Latitude, location.Longitude).ToGCJ02(); //MapLayer.SetPosition(Dot.Parent, location); this.LastLocation = location; } } catch (Exception ex) { _logger.Log(ex); } } public void ChangeBrush(string RGB) { //Color color = (Color)ColorConverter.ConvertFromString("#" + RGB); //_brush = new SolidColorBrush(Color.FromRgb(255, 0, 255)); //this.Dot.Fill = _brush; } public void ShowWaypoint(int taskIndex) { var wpIndex = taskIndex - 1; // Waypoints 中没有起飞点。 foreach (var item in this.Waypoints) { _map.Markers.Remove(item); } if (wpIndex >= 0 && wpIndex < Waypoints.Count) { //选中的航点 GMapMarker wpmarker = (GMapMarker)(Waypoints[wpIndex]); //航点轮廓变为白色 // wpmarker.Shape.Stroke = _selectedTaskStroke; _map.Markers.Add(wpmarker); //消耗大量时间费时 } } public void ShowAllWaypoint() { foreach (var item in this.Waypoints) { _map.Markers.Remove(item); } foreach (var item in this.Waypoints) { _map.Markers.Add(item); } } //加入航点 public void AddWaypoint(Location location, FlightTaskType type, FlightTask vtask) { // Add waypoint. LatLng gmapLatLng = new LatLng(location.Latitude, location.Longitude); //创建marker,设定位置 GMapMarker marker = new GMapMarker(gmapLatLng.ToGCJ02()); //航点默认颜色 SolidColorBrush Waypoint_brush = new SolidColorBrush(Color.FromRgb(0, 0, 255)); //makrer的形状,包含一个圆圈和一个选中方块 ShapesContainer shapesContainer = new ShapesContainer(Waypoint_brush); shapesContainer.Tag = WAYPOINT_TAG; marker.Tag = WAYPOINT_TAG; //形状设置为shapesContainer marker.Shape = shapesContainer; //加入航点列表Waypoints为某架飞机的航点列表 Waypoints.Insert(vtask.TaskIndex-1,marker); //该航点的飞机是否选中 bool PontisSelected = _copterManager.SelectedCopters.Contains(Copter); shapesContainer.Ismark = PontisSelected; // 选中飞机在地图上显示一个红色方块---选中时也会调用,这儿可以不调用 SetEffect(PontisSelected); //_map.Markers.Add(marker); //消耗大量时间费时 ,为了提高效率改为选中才添加见ShowWaypoint marker.ZIndex = 100; //MapLayer.SetZIndex(shapesContainer, 100); //var wpPos = _map.LocationToViewportPoint(location); //wpPos.X -= WAYPOINT_RADIUS; //wpPos.Y -= WAYPOINT_RADIUS; //MapLayer.SetPosition(shapesContainer, _map.ViewportPointToLocation(wpPos)); // Register event handlers. RegisterEventHandlersForDraggingWaypoint(marker, vtask); // Register event handlers for task info. RegisterEventHandlersForTaskInfo(marker, vtask); } private void RegisterEventHandlersForDraggingCopter(GMapMarker copterMarker) { Grid copterElement = copterMarker.Shape as Grid; 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.CanDragMap = false; } }; _map.MouseMove += (sender, e) => { if (dragMoving) { var pos = e.GetPosition(_map); pos.X -= offsetX; pos.Y -= offsetY; copterMarker.Position = _map.FromLocalToLatLng((int)pos.X, (int)pos.Y); //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: copterMarker.Position.ToWGS84().Lat, longitude: copterMarker.Position.ToWGS84().Lng ); } }; _map.MouseLeftButtonUp += (sender, e) => { _map.CanDragMap = true; if (dragMoving) dragMoving = false; }; } private Dictionary selectWayOriginPoint = new Dictionary(); private Dictionary _dictDraggingWp = new Dictionary(); private void RegisterEventHandlersForDraggingWaypoint(GMapMarker wpMarker, FlightTask vtask) { Grid wp = wpMarker.Shape as Grid; _dictDraggingWp[wp] = false; double originX = 0; double originY = 0; double wpOffsetX = 0; double wpOffsetY = 0; wp.MouseLeftButtonDown += (sender, e) => { //判断点击的航点 //非SelectedTask中的航点 或者 当前SelectedTask中未选择的航点 单选拖动 //否则多选拖动 if (_flightTaskManager.SelectedTask != vtask || !_copterManager.SelectedCopters.Contains(this.Copter)) { //_copterManager.Select(null); _copterManager.Select(this.Copter); _flightTaskManager.SelectTask(vtask.TaskIndex); } var originPoint = e.GetPosition(_map); originX = originPoint.X; originY = originPoint.Y; var posInObject = e.GetPosition(wp); wpOffsetX = posInObject.X; wpOffsetY = posInObject.Y; _dictDraggingWp[wp] = true; selectWayOriginPoint.Clear(); foreach (FlightTaskSingleCopterInfo info in _flightTaskManager.SelectedTask.SingleCopterInfos) { if (_copterManager.SelectedCopters.Contains(info.Copter)) { PointLatLng originLocation = new LatLng(info.TargetLat, info.TargetLng).ToGCJ02(); selectWayOriginPoint[info.Copter] = _map.FromLatLngToLocal(originLocation); } } _map.CanDragMap = false; }; wp.MouseRightButtonDown += (sender, e) => { _flightTaskManager.RightSelect(vtask.TaskIndex, this.Copter); }; _map.MouseMove += (sender, e) => { if (_dictDraggingWp[wp]) { var eventPos = e.GetPosition(_map); var offsetX = eventPos.X - originX; var offsetY = eventPos.Y - originY; foreach (KeyValuePair kv in selectWayOriginPoint) { Point curPoint = new Point(kv.Value.X + offsetX, kv.Value.Y + offsetY); var curLoc = _map.FromLocalToLatLng((int)curPoint.X, (int)curPoint.Y).ToWGS84(); var modifyingSingleCopterInfo = _flightTaskManager.SelectedTask.SingleCopterInfos.Find(i => i.Copter == kv.Key); //modifyingSingleCopterInfo.TargetLat = routePoint.Latitude = curLoc.Latitude; //modifyingSingleCopterInfo.TargetLng = routePoint.Longitude = curLoc.Longitude; modifyingSingleCopterInfo.TargetLat = curLoc.Lat; modifyingSingleCopterInfo.TargetLng = curLoc.Lng; Console.WriteLine("-------" + curLoc.Lat + "," + curLoc.Lng); } // var routePoint = this.Route.Points[1]; var leftTopPos = new Point(eventPos.X - wpOffsetX, eventPos.Y - wpOffsetY); var newRoutePoint = new Point(leftTopPos.X + WAYPOINT_RADIUS, leftTopPos.Y + WAYPOINT_RADIUS); var lat_lng = _map.FromLocalToLatLng((int)leftTopPos.X, (int)leftTopPos.Y); Route.Points.RemoveAt(1); Route.Points.Add(lat_lng); // routePoint.Lat = lat_lng.Lat; // routePoint.Lng = lat_lng.Lng; this.Route.RegenerateShape(_map); wpMarker.Position = lat_lng; //MapLayer.SetPosition(wp, _map.ViewportPointToLocation(leftTopPos)); } }; _map.MouseLeftButtonUp += (sender, e) => { _map.CanDragMap = true; if (_dictDraggingWp[wp]) _dictDraggingWp[wp] = false; }; } private void RegisterEventHandlersForTaskInfo(GMapMarker marker, FlightTask vtask) { var wp = marker.Shape as ShapesContainer; var info = vtask.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, centerPos.Y); //MapLayer.SetPosition(wp, _map.ViewportPointToLocation(leftTopPos)); marker.Position = new LatLng(info.TargetLat, info.TargetLng).ToGCJ02(); // var routePoint = Route.Points[1]; // routePoint.Lat = info.TargetLat; // routePoint.Lng = info.TargetLng; if (Route != null) { if (Route.Points.Count>1) Route.Points.RemoveAt(1); Route.Points.Add(marker.Position); this.Route.RegenerateShape(_map); } //routePoint.Altitude = info.TargetAlt; } break; } }; } public void RemoveCopter() { _map.Markers.Remove(this.DotMarker); //_map.Markers.Remove(this.Track); //_map.Markers.Remove(this.Route); foreach (var item in this.Waypoints) { _map.Markers.Remove(item); } } public void RemoveMap_ViewChanged() { //_map.ViewChangeOnFrame -= Map_ViewChanged; } //显示或隐藏计划线路 public void UpdateShowroute() { if (_flightTaskManager.showroute) { if (_copterManager.ShowCopter.Count > 0) { if (_copterManager.ShowCopter.Contains(Copter)) { if (!_map.Markers.Contains(this.Route)) _map.Markers.Add(this.Route); Route.ZIndex = 99; } } else { //将计划线路加入地图 if (!_map.Markers.Contains(this.Route)) _map.Markers.Add(this.Route); Route.ZIndex = 99; } } else { //将计划线路从地图移除 if (_map.Markers.Contains(this.Route)) _map.Markers.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) { if (selected) { if ((DotContainer!=null)&&(!DotContainer.Children.Contains(selectMarkup))) DotContainer.Children.Add(selectMarkup); } else { if ((DotContainer != null) && (DotContainer.Children.Contains(selectMarkup))) DotContainer.Children.Remove(selectMarkup); } Waypoints.ForEach(wp => ((ShapesContainer)(wp.Shape)).Ismark = selected); /* Waypoints.ForEach(wp => wp.Effect = Dot.Effect); //Dot.Effect = selected ? _selectedEffect : null; Waypoints.ForEach(wp => wp.Effect = Dot.Effect); */ } //添加计划航线---只显示两个点 public void ResetRoute(int taskIndex) { var wpIndex = taskIndex - 1; // Waypoints 中没有起飞点。 if (Route == null) return; Route.Points.Clear(); if (wpIndex >= 0 && wpIndex < Waypoints.Count) { //起始点时 var info1 = _flightTaskManager.Tasks[wpIndex].SingleCopterInfos.Find(i => i.Copter == this.Copter); var info2 = _flightTaskManager.Tasks[taskIndex].SingleCopterInfos.Find(i => i.Copter == this.Copter); PointLatLng loc1 = new LatLng(info1.TargetLat, info1.TargetLng).ToGCJ02(); PointLatLng loc2 = new LatLng(info2.TargetLat, info2.TargetLng).ToGCJ02(); Route.Points.Add(loc1); //起始点 Route.Points.Add(loc2); //结束点 } Path path = new Path() { Stroke = new SolidColorBrush(Colors.Red), StrokeThickness = 2.0 }; Route.Shape = path; Route.RegenerateShape(_map); UpdateShowroute(); } //设置选中任务航点为白色外框 public void SetTaskEffect(int taskIndex) { var wpIndex = taskIndex - 1; // Waypoints 中没有起飞点。 if (wpIndex >= 0 && wpIndex < Waypoints.Count) { //清除所有白色轮廓 Waypoints.ForEach(p => ((ShapesContainer)(p.Shape)).wp.Stroke = null); //选中的航点 var wp = ((ShapesContainer)(Waypoints[wpIndex].Shape)).wp; //航点轮廓变为白色 wp.Stroke = _selectedTaskStroke; } } // 右击任务时触发 //显示或者隐藏任务航点 public void SetTaskRightEffect(int taskIndex, bool flag) { var wpIndex = taskIndex - 1; // Waypoints 中没有起飞点。 if (wpIndex >= 0 && wpIndex < Waypoints.Count) { var wp = Waypoints[wpIndex].Shape as ShapesContainer; //计划航线 UIElement RouteShape = null; if ((Route != null) && (Route.Shape != null)) RouteShape = Route.Shape; if (!flag) { wp.Visibility = Visibility.Hidden; if (RouteShape!=null) RouteShape.Visibility= Visibility.Hidden; } else { if (_copterManager.ShowCopter.Count > 0 ) { if (_copterManager.ShowCopter.Contains(Copter)) { wp.Visibility = Visibility.Visible; if (RouteShape != null) RouteShape.Visibility = Visibility.Visible; } else { wp.Visibility = Visibility.Hidden; if (RouteShape != null) RouteShape.Visibility = Visibility.Hidden; } } else { wp.Visibility = Visibility.Visible; //3d模式Route可能为空 if (RouteShape != null) RouteShape.Visibility = Visibility.Visible; } //var info = _flightTaskManager.Tasks[taskIndex].SingleCopterInfos.Find(i => i.Copter == this.Copter); } } } } //航点选中方块 public class ShapesContainer : Grid { const double WAYPOINT_RADIUS = 6; public ShapesContainer(Brush brush) { wp = new Ellipse { //Tag = WAYPOINT_TAG, Fill = brush, StrokeThickness = 2, Width = WAYPOINT_RADIUS * 2, Height = WAYPOINT_RADIUS * 2, Margin = new Thickness(-WAYPOINT_RADIUS, -WAYPOINT_RADIUS, 0, 0) }; this.Children.Add(wp); mark = new Rectangle(); mark.Width = 6; mark.Height = 6; mark.HorizontalAlignment = HorizontalAlignment.Left; mark.VerticalAlignment = VerticalAlignment.Top; mark.Fill = new SolidColorBrush(Colors.GreenYellow); this.Children.Add(mark); mark.Visibility = Visibility.Hidden; } //public MapPolygon private bool isMarked; public Ellipse wp; //航点选中方块 public Rectangle mark; //航点是否选中 public bool Ismark { get { return isMarked; } set { isMarked = value; mark.Visibility = value ? Visibility.Visible : Visibility.Hidden; } } } } }