277 lines
11 KiB
C#
277 lines
11 KiB
C#
using GalaSoft.MvvmLight;
|
||
using GalaSoft.MvvmLight.Command;
|
||
using HelixToolkit.Wpf;
|
||
using Microsoft.Practices.ServiceLocation;
|
||
using Plane.Collections;
|
||
using Plane.Copters;
|
||
using Plane.FormationCreator.Formation;
|
||
using Plane.Geography;
|
||
using Plane.Windows.Messages;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Collections.Specialized;
|
||
using System.ComponentModel;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
using System.Windows.Input;
|
||
using System.Windows.Media;
|
||
using System.Windows.Media.Media3D;
|
||
|
||
namespace Plane.FormationCreator.ViewModels
|
||
{
|
||
public class View3DViewModel : ViewModelBase
|
||
{
|
||
private FlightTaskManager _flightTaskManager;
|
||
private CopterManager _copterManager;
|
||
|
||
private View3DManager _view3DManager = ServiceLocator.Current.GetInstance<View3DManager>();
|
||
|
||
public View3DViewModel(FlightTaskManager flightTaskManager, CopterManager copterManager)
|
||
{
|
||
modelGroup = new Model3DGroup();
|
||
planeGroup = new Model3DGroup();
|
||
waypointGroup = new Model3DGroup();
|
||
modelGroup.Children.Add(waypointGroup);
|
||
modelGroup.Children.Add(planeGroup);
|
||
|
||
this.Model = modelGroup;
|
||
_flightTaskManager = flightTaskManager;
|
||
_copterManager = copterManager;
|
||
_flightTaskManager.PropertyChanged += new PropertyChangedEventHandler(flightTaskPropertyChanged);
|
||
_view3DManager._view3DViewModel = this;
|
||
|
||
_copterManager.Copters.CollectionChanged += Copters_CollectionChanged;
|
||
}
|
||
|
||
private void flightTaskPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||
{
|
||
switch (e.PropertyName)
|
||
{
|
||
case nameof(FlightTaskManager.SelectedTaskIndex):
|
||
SelectTask();
|
||
break;
|
||
case nameof(FlightTaskManager.RightSelectedTaskIndex): // 单击右键触发清除航点
|
||
|
||
int taskIndexTmp = Math.Abs(_flightTaskManager.RightSelectedTaskIndex);
|
||
if (_flightTaskManager.Tasks[taskIndexTmp].IsRightSelected)
|
||
{
|
||
if (waypointGroup == null) waypointGroup = new Model3DGroup();
|
||
waypointGroup.Children.Clear();
|
||
}
|
||
else SelectTask();
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
private void Copters_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||
{
|
||
e.OldItems?.ForEach<ICopter>(async copter =>
|
||
{
|
||
copter.LocationChanged -= Copter_LocationChanged;
|
||
await Task.Delay(100); // 如果不等待一段时间,Copter_DataStreamReceived 很可能再被调用一次。
|
||
Remove3DCopter(copter);
|
||
});
|
||
e.NewItems?.ForEach<ICopter>(copter => copter.LocationChanged += Copter_LocationChanged);
|
||
}
|
||
|
||
private void Remove3DCopter(ICopter copter)
|
||
{
|
||
if (planeModel3Ds.ContainsKey(copter))
|
||
{
|
||
GeometryModel3D panle3D = planeModel3Ds[copter];
|
||
planeGroup.Children.Remove(panle3D);
|
||
planeModel3Ds.Remove(copter);
|
||
panle3D = null;
|
||
}
|
||
}
|
||
|
||
public void Clear3DCopters()
|
||
{
|
||
planeModel3Ds.Clear();
|
||
planeGroup.Children.Clear();
|
||
observationLatLng = null;
|
||
}
|
||
|
||
private void Copter_LocationChanged(object sender, EventArgs e)
|
||
{
|
||
var copter = sender as ICopter;
|
||
if (App.Current.CheckAccess())
|
||
{
|
||
AddOrMove3DCopter(copter);
|
||
}
|
||
else
|
||
{
|
||
App.Current.Dispatcher.InvokeAsync(() => AddOrMove3DCopter(copter));
|
||
}
|
||
}
|
||
|
||
private Dictionary<ICopter, GeometryModel3D> planeModel3Ds = new Dictionary<ICopter, GeometryModel3D>();
|
||
Tuple<double, double> observationLatLng = null;
|
||
|
||
private void AddOrMove3DCopter(ICopter copter)
|
||
{
|
||
if (_flightTaskManager.TaskRun_2D) return; //不在3D模式运行直接退出
|
||
//var copternum1 = _copterManager.Copters.FirstOrDefault();
|
||
if (_flightTaskManager.OriginLat == 0 || _flightTaskManager.OriginLng == 0)
|
||
return;
|
||
|
||
//第一列到中间的距离
|
||
float midColDistance = (_flightTaskManager.ColumnCount - 1) * _flightTaskManager.ColumnDistance / 2;
|
||
|
||
if (observationLatLng == null)
|
||
{
|
||
observationLatLng = GeographyUtils.CalcLatLngSomeMetersAway2D(
|
||
_flightTaskManager.OriginLat,
|
||
_flightTaskManager.OriginLng,
|
||
_flightTaskManager.Orientation + 90,
|
||
midColDistance);
|
||
observationLatLng = GeographyUtils.CalcLatLngSomeMetersAway2D(
|
||
observationLatLng.Item1,
|
||
observationLatLng.Item2,
|
||
_flightTaskManager.Orientation + 180,
|
||
midColDistance * 2);
|
||
}
|
||
//没有这架飞机就加入
|
||
if (!planeModel3Ds.ContainsKey(copter))
|
||
{
|
||
|
||
//观测点的位置放到最后排飞机的中间位置
|
||
|
||
var meshBuilderwaypoint = new MeshBuilder(false, false);
|
||
|
||
//meshBuilderwaypoint.AddTriangle(new Point3D(-0.1, -0.1, 0), new Point3D(0.1, -0.1, 0), new Point3D(0, 0.2, 0));
|
||
//飞机点的大小形状
|
||
meshBuilderwaypoint.AddSphere(new Point3D(0, 0, 0), 0.3* _copterManager.scale3d);
|
||
var meshwaypoint = meshBuilderwaypoint.ToMesh(true);
|
||
|
||
double y = GeographyUtils.CalcDistance(0, observationLatLng.Item1, 0, 0, copter.Latitude, 0) / 2;
|
||
if (observationLatLng.Item1 > copter.Latitude) y = -y;
|
||
|
||
double x = GeographyUtils.CalcDistance(observationLatLng.Item2, 0, 0, copter.Longitude, 0, 0) / 2;
|
||
if (observationLatLng.Item2 > copter.Longitude) x = -x;
|
||
|
||
double z = copter.Altitude + 0.1;
|
||
|
||
x *= _copterManager.scale3d;
|
||
y *= _copterManager.scale3d;
|
||
z *= _copterManager.scale3d;
|
||
Color color ;
|
||
if (copter.LEDColor != null && copter.LEDColor != "")
|
||
color = (Color)ColorConverter.ConvertFromString("#" + copter.LEDColor);
|
||
else
|
||
color = (Color)ColorConverter.ConvertFromString("#" + CopterManager.CopterDefaultColor);
|
||
var model3D = new GeometryModel3D
|
||
{
|
||
Geometry = meshwaypoint,
|
||
Transform = new TranslateTransform3D(x, y, z),
|
||
Material = MaterialHelper.CreateMaterial(color),
|
||
BackMaterial = MaterialHelper.CreateMaterial(color)
|
||
};
|
||
|
||
planeModel3Ds.Add(copter, model3D);
|
||
planeGroup.Children.Add(model3D);
|
||
}
|
||
//有飞机在视图里就移动位置
|
||
else
|
||
{
|
||
|
||
double y = GeographyUtils.CalcDistance(0, observationLatLng.Item1, 0, 0, copter.Latitude, 0) / 2;
|
||
if (observationLatLng.Item1 > copter.Latitude) y = -y;
|
||
|
||
double x = GeographyUtils.CalcDistance(observationLatLng.Item2, 0, 0, copter.Longitude, 0, 0) / 2;
|
||
if (observationLatLng.Item2 > copter.Longitude) x = -x;
|
||
|
||
//保留小数后2位,精确到1cm
|
||
x = Math.Round(x, 2);//按照四舍五入的国际标准
|
||
y = Math.Round(y, 2);
|
||
double z = Math.Round(copter.Altitude / 2, 2);
|
||
|
||
GeometryModel3D panle3D = planeModel3Ds[copter];
|
||
x *= _copterManager.scale3d;
|
||
y *= _copterManager.scale3d;
|
||
z *= _copterManager.scale3d;
|
||
if (x != panle3D.Transform.Value.OffsetX || y != panle3D.Transform.Value.OffsetY || z != panle3D.Transform.Value.OffsetZ)
|
||
{
|
||
panle3D.Transform = new TranslateTransform3D(x, y, z);
|
||
}
|
||
|
||
Color color;
|
||
if (copter.LEDColor != null && copter.LEDColor != "")
|
||
{
|
||
color = (Color)ColorConverter.ConvertFromString("#" + copter.LEDColor);
|
||
panle3D.Material = MaterialHelper.CreateMaterial(color);
|
||
panle3D.BackMaterial = MaterialHelper.CreateMaterial(color);
|
||
}
|
||
//else
|
||
// color = (Color)ColorConverter.ConvertFromString("#" + CopterManager.CopterDefaultColor);
|
||
|
||
|
||
}
|
||
|
||
//Message.Show("添加3D飞机:" + copter.Name);
|
||
}
|
||
|
||
|
||
|
||
private void SelectTask()
|
||
{
|
||
if (waypointGroup == null) waypointGroup = new Model3DGroup();
|
||
waypointGroup.Children.Clear();
|
||
if (_flightTaskManager.SelectedTaskIndex > 0)
|
||
{
|
||
//观测点的位置放到最后排飞机的中间位置
|
||
Tuple<double, double> observationLatLng;
|
||
|
||
//列的中间位置
|
||
float midDistance = (_flightTaskManager.ColumnCount - 1) * _flightTaskManager.ColumnDistance / 2;
|
||
|
||
observationLatLng = GeographyUtils.CalcLatLngSomeMetersAway2D(
|
||
_flightTaskManager.OriginLat, _flightTaskManager.OriginLng, _flightTaskManager.Orientation + 90, midDistance);
|
||
observationLatLng = GeographyUtils.CalcLatLngSomeMetersAway2D(
|
||
observationLatLng.Item1, observationLatLng.Item2, _flightTaskManager.Orientation + 180, midDistance * 2);
|
||
|
||
//modelGroup.Children.Clear();
|
||
|
||
var meshBuilderwaypoint = new MeshBuilder(false, false);
|
||
//航点的大小形状
|
||
meshBuilderwaypoint.AddSphere(new Point3D(0, 0, 0), 0.2* _copterManager.scale3d);
|
||
var meshwaypoint = meshBuilderwaypoint.ToMesh(true);
|
||
var greenMaterial = MaterialHelper.CreateMaterial(Color.FromRgb(50,50,255));
|
||
|
||
foreach (FlightTaskSingleCopterInfo info in _flightTaskManager.Tasks[_flightTaskManager.SelectedTaskIndex].SingleCopterInfos)
|
||
{
|
||
|
||
double y = GeographyUtils.CalcDistance(0, observationLatLng.Item1, 0, 0, info.TargetLat, 0)/2;
|
||
if (observationLatLng.Item1 > info.TargetLat) y = -y;
|
||
|
||
double x = GeographyUtils.CalcDistance(observationLatLng.Item2, 0, 0, info.TargetLng, 0, 0)/2;
|
||
if (observationLatLng.Item2 > info.TargetLng) x = -x;
|
||
double z = info.TargetAlt / 2;
|
||
|
||
x *= _copterManager.scale3d;
|
||
y *= _copterManager.scale3d;
|
||
z *= _copterManager.scale3d;
|
||
|
||
waypointGroup.Children.Add(new GeometryModel3D
|
||
{
|
||
Geometry = meshwaypoint,
|
||
Transform = new TranslateTransform3D(x, y, z),
|
||
Material = greenMaterial,
|
||
BackMaterial = greenMaterial
|
||
});
|
||
}
|
||
}
|
||
}
|
||
|
||
public Model3D Model { get; set; }
|
||
public Model3DGroup modelGroup { get; set; }
|
||
|
||
public Model3DGroup planeGroup { get; set; }
|
||
public Model3DGroup waypointGroup { get; set; }
|
||
|
||
}
|
||
}
|