Plane.FormationCreator/Plane.FormationCreator/ViewModels/View3DViewModel.cs
zxd cce5722a52 为三亚做准备:
导入起飞位置
导入C4D关键帧
碰撞检测不暂停任务
起飞摆放高度
添加分组设置
灯光设置优化
当前检测碰撞为1.8米
2019-03-23 21:46:04 +08:00

245 lines
9.7 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 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;
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)
{
//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.2);
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;
var model3D = new GeometryModel3D
{
Geometry = meshwaypoint,
Transform = new TranslateTransform3D(x, y, copter.Altitude + 0.1),
Material = MaterialHelper.CreateMaterial(Color.FromRgb(238, 210, 238)),
BackMaterial = MaterialHelper.CreateMaterial(Color.FromRgb(238, 210, 238))
};
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];
if (x != panle3D.Transform.Value.OffsetX || y != panle3D.Transform.Value.OffsetY || z != panle3D.Transform.Value.OffsetZ)
{
panle3D.Transform = new TranslateTransform3D(x, y, z);
}
if (copter.LEDColor != null && copter.LEDColor != "")
{
Color color = (Color)ColorConverter.ConvertFromString("#" + copter.LEDColor);
panle3D.Material = MaterialHelper.CreateMaterial(color);
panle3D.BackMaterial = MaterialHelper.CreateMaterial(color);
}
}
//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);
var meshwaypoint = meshBuilderwaypoint.ToMesh(true);
var greenMaterial = MaterialHelper.CreateMaterial(Color.FromRgb(0,255,0));
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;
waypointGroup.Children.Add(new GeometryModel3D
{
Geometry = meshwaypoint,
Transform = new TranslateTransform3D(x, y, info.TargetAlt/2),
Material = greenMaterial,
BackMaterial = greenMaterial
});
}
}
}
public Model3D Model { get; set; }
public Model3DGroup modelGroup { get; set; }
public Model3DGroup planeGroup { get; set; }
public Model3DGroup waypointGroup { get; set; }
}
}