Plane.FormationCreator/Plane.FormationCreator/ViewModels/View3DViewModel.cs
xu e1c81f28ff 增加保存读取虚拟编号
多次写入参数
加入测试灯光和灯光频率可以为小数---需要升级飞控

修改3D颜色和编号刷新的bug
2020-05-03 12:14:27 +08:00

277 lines
11 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;
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; }
}
}