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 Microsoft.Maps.MapControl.WPF; using Microsoft.Maps.MapControl.WPF.Overlays; using System.Windows.Media.Effects; using Microsoft.Practices.ServiceLocation; using Plane.FormationCreator.ViewModels; using Plane.Geography; using Plane.FormationCreator.Maps; using Plane.Windows.Messages; namespace Plane.FormationCreator.Views { /// /// Interaction logic for MapView.xaml /// public partial class MapView : UserControl { public MapView() { InitializeComponent(); this.DataContext = ServiceLocator.Current.GetInstance(); _mapManager.MapView = this; _mapManager.SetCenterGetter(() => new LatLng { Lat = map.Center.Latitude, Lng = map.Center.Longitude }); _flightTaskManager.TaskAdded += FlightTaskManager_TaskAdded; _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): foreach (var item in _copterDrawings) { var copterDrawing = item.Value; copterDrawing.SetTaskEffect(_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; } }; map.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; map.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; var pos = map.ViewportPointToLocation(e.GetPosition(map)); var centerLat = copters.Average(c => c.Latitude); var centerLng = copters.Average(c => c.Longitude); var latDelta = pos.Latitude - centerLat; var lngDelta = pos.Longitude - centerLng; await Task.WhenAll(copters.Select(copter => copter.FlyToAsync(copter.Latitude + latDelta, copter.Longitude + lngDelta, copter.Altitude))); }; var center = _appConfig.Center; map.Center = new Location(center.Lat, center.Lng); map.ZoomLevel = _appConfig.ZoomLevel; map.ViewChangeOnFrame += (object sender, MapEventArgs e) => { if ( map.Mode.GetType().ToString() == "Microsoft.Maps.MapControl.WPF.AerialMode") if (map.ZoomLevel >19) map.ZoomLevel = 19; }; Rectangle rectangle = new Rectangle(); bool drawRectangle = false; Point startPosition = new Point(); Point leftTopPoint = new Point(); map.MouseRightButtonDown += (sender, e) => { 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"; map.Children.Add(rectangle); startPosition = e.GetPosition(this); MapLayer.SetPosition(rectangle, map.ViewportPointToLocation(startPosition)); drawRectangle = true; }; map.MouseMove += (sender, e) => { if (drawRectangle) { Point mousePosition = e.GetPosition(this); 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)); MapLayer.SetPosition(rectangle, map.ViewportPointToLocation(leftTopPoint)); } }; int selectedCount = 0; map.MouseRightButtonUp += (sender, e) => { selectedCount = 0; if (rectangle != null && map.Children.Contains(rectangle)) { map.Children.Remove(rectangle); if (_flightTaskManager.SelectedTask != null) { _copterManager.shiftkeydown = true; _copterManager.Select(null); foreach (FlightTaskSingleCopterInfo taskCopterInfo in _flightTaskManager.SelectedTask.SingleCopterInfos) { Location seekLocation = new Location(taskCopterInfo.TargetLat, taskCopterInfo.TargetLng); Point seekPoint = map.LocationToViewportPoint(seekLocation); if ((seekPoint.X > leftTopPoint.X && seekPoint.X < leftTopPoint.X + rectangle.Width) && seekPoint.Y > leftTopPoint.Y && seekPoint.Y < leftTopPoint.Y + rectangle.Height) { selectedCount++; _copterManager.Select(taskCopterInfo.Copter); } } _copterManager.shiftkeydown = false; } } rectangle = null; drawRectangle = false; }; map.MouseLeave += (sender, e) => { if (map.Children.Contains(rectangle)) { map.Children.Remove(rectangle); } rectangle = null; drawRectangle = false; }; map.MouseMove += new MouseEventHandler(OriginalMove); map.MouseLeftButtonUp += new MouseButtonEventHandler(OriginalMouseUp); } private CopterManager _copterManager = ServiceLocator.Current.GetInstance(); private MapManager _mapManager = ServiceLocator.Current.GetInstance(); private FlightTaskManager _flightTaskManager = ServiceLocator.Current.GetInstance(); private AppConfig _appConfig = ServiceLocator.Current.GetInstance(); 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().FirstOrDefault(); if (errorElement != null) { map.Children.Remove(errorElement); return true; } else { return false; } } public void GoHome() { map.ZoomLevel = 19; map.Center = new Location(40.0559055, 116.322233); } private void Copters_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { e.OldItems?.ForEach(async copter => { copter.LocationChanged -= Copter_LocationChanged; await Task.Delay(100); // 如果不等待一段时间,Copter_DataStreamReceived 很可能再被调用一次。 RemoveCopter(copter); }); e.NewItems?.ForEach(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 _copterDrawings = new Dictionary(); private void AddOrMoveCopter(ICopter copter) { var drawing = _copterDrawings.ContainsKey(copter) ? _copterDrawings[copter] : (_copterDrawings[copter] = new CopterDrawing(copter, map)); drawing.AddOrMoveCopter(); } private void RemoveCopter(ICopter copter) { if (_copterDrawings.ContainsKey(copter)) { var drawing = _copterDrawings[copter]; drawing.RemoveCopter(); _copterDrawings.Remove(copter); } } public void ClearCopters() { for (int i = map.Children.Count - 1; i >= 0; i--) { if (!(map.Children[i] is MapTileLayer)) { map.Children.RemoveAt(i); } } _copterDrawings.Clear(); } private bool IsMouseOnCopterOrWaypoint(object originalSource) { var elem = originalSource as FrameworkElement; string tag; while (elem != map && 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 Location(info.TargetLat, info.TargetLng, info.TargetAlt); drawingInfo.AddWaypoint(location, e.AddedTask.TaskType); } } Ellipse original = null; private void FlightTaskManager_SetOriginal(object sender, FlightTaskAddedOriginalEventArgs e) { if (map.Children.Contains(original)) return; Location location = new Location(); if (e.Lat == 0 && e.Lng == 0) location = map.Center; else location = new Location(e.Lat, e.Lng); original = new Ellipse { Tag = ORIGINALPOINT_TAG, Fill = new SolidColorBrush(Color.FromRgb(0, 0, 0)), StrokeThickness = 3, Stroke = new SolidColorBrush(Color.FromRgb(255, 255, 255)), Width = 18, Height = 18, }; map.Children.Add(original); MapLayer.SetPosition(original, location); original.ToolTip = location.ToString(); originaDrag = false; _flightTaskManager.OriginLat = location.Latitude; _flightTaskManager.OriginLng = location.Longitude; original.MouseLeftButtonDown += new MouseButtonEventHandler(OriginalMouseDown); } private bool originaDrag = false; double wpOffsetX = 0; double wpOffsetY = 0; private void OriginalMouseDown(object sender, MouseButtonEventArgs e) { originaDrag = true; var posInObject = e.GetPosition(original); wpOffsetX = posInObject.X; wpOffsetY = posInObject.Y; } private void OriginalMove(object sender, MouseEventArgs e) { if (originaDrag) { Point eventPos = e.GetPosition(map); var leftTopPos = new Point(eventPos.X - wpOffsetX, eventPos.Y - wpOffsetY); MapLayer.SetPosition(original, map.ViewportPointToLocation(leftTopPos)); } } private void OriginalMouseUp(object sender, MouseButtonEventArgs e) { if (originaDrag) { Point eventPos = e.GetPosition(map); Location location = map.ViewportPointToLocation(eventPos); _flightTaskManager.OriginLat = location.Latitude; _flightTaskManager.OriginLng = location.Longitude; original.ToolTip = location.ToString(); Console.WriteLine("original-----------"+original.ToolTip); Clipboard.SetDataObject(string.Format("{0},{1}", location.Latitude, location.Longitude), true); originaDrag = false; } } private void MapSelectionComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { 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().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; copterDrawing.SetShowroute(chk.IsChecked); } } 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); } } } } static class LocationExtensions { public static double CalcDistance(this Location loc1, 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); } } }