You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

187 lines
7.1 KiB

using MODELING_DEF_DES_MI_VI.Helpers;
using MODELING_DEF_DES_MI_VI.Models;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
namespace MODELING_DEF_DES_MI_VI.Modules.PoreInspectionUnit
{
public class PoreInspectionViewModel : PropertyChangedClass
{
public MaterialModel GlobalMaterial { get; set; }
public List<FrameworkElement> Ellipses { get; set; } = new List<FrameworkElement>();
public Camera2D Camera { get; set; }
private bool IsCanceled { get; set; }
private bool IsBusy { get; set; }
public PoreInspectionViewModel(MaterialModel material, Camera2D camera)
{
GlobalMaterial = material;
Camera = camera;
Application.Current.MainWindow.KeyDown += OnKeyDown;
}
public async Task UpdateModel()
{
await Task.Run(async () =>
{
try
{
while (IsBusy) await Task.Delay(40);
IsBusy = true;
IsCanceled = false;
await Application.Current.Dispatcher.Invoke(async () =>
{
List<FrameworkElement> bufferedShapes = new List<FrameworkElement>();
bufferedShapes.Add(CreateMaterial());
var visibilityRange =
Tuple.Create(
(Camera.CutDepth + Camera.DepthVisibility) / Camera.Scale,
(Camera.CutDepth - Camera.DepthVisibility) / Camera.Scale);
foreach (Pore pore in GlobalMaterial.Pores)
{
if (IsCanceled)
return;
if (visibilityRange.Item2 < pore.Point.Z && pore.Point.Z < visibilityRange.Item1)
bufferedShapes.Add(CreateEllipse(pore));
}
Ellipses = bufferedShapes;
await Task.Delay(20);
IsBusy = false;
});
}
catch (Exception e)
{
MessageBox.Show(e.StackTrace, "Не удалось отобразить модель");
}
});
}
private Ellipse CreateEllipse(Pore pore)
{
var e = new Ellipse();
var scaledPoreRadius = pore.Radius * Camera.Scale;
var distanceFromCameraToPore = Camera.CutDepth - pore.Point.Z * Camera.Scale;
var cuttingHeight = Math.Abs(distanceFromCameraToPore);
if (cuttingHeight < scaledPoreRadius)
{
e.Fill = Brushes.Violet;
var cuttedDiameter = Math.Sqrt(Math.Pow(scaledPoreRadius, 2) - Math.Pow(cuttingHeight, 2)) * 2;
e.Width = cuttedDiameter;
e.Height = cuttedDiameter;
}
else if (pore.Point.Z < Camera.CutDepth / Camera.Scale)
{
e.Opacity = 0.5;
byte colorDegree = Convert.ToByte((1 - distanceFromCameraToPore / Camera.DepthVisibility) * 255);
e.Fill = new SolidColorBrush(Color.FromRgb(colorDegree, colorDegree, colorDegree));
e.Width = scaledPoreRadius * 2;
e.Height = scaledPoreRadius * 2;
}
else
{
e.Opacity = 0;
}
var x = Camera.Scale * pore.Point.X + Camera.StartPosition.X - e.Width / 2;
var y = Camera.Scale * pore.Point.Y + Camera.StartPosition.Y - e.Height / 2;
e.SetValue(Canvas.LeftProperty, x);
e.SetValue(Canvas.TopProperty, y);
return e;
}
private Rectangle CreateMaterial()
{
var material = new Rectangle()
{
Width = Camera.Scale * GlobalMaterial.Width,
Height = Camera.Scale * GlobalMaterial.Height,
Fill = Brushes.DarkBlue,
};
material.SetValue(Canvas.LeftProperty, Camera.StartPosition.X);
material.SetValue(Canvas.TopProperty, Camera.StartPosition.Y);
return material;
}
private void OnKeyDown(object sender, KeyEventArgs e)
{
if (!IsBusy)
switch (e.Key)
{
case Key.A:
IsCanceled = true;
Camera.StartPosition.X -= Camera.Speed;
UpdateModel();
break;
case Key.D:
IsCanceled = true;
Camera.StartPosition.X += Camera.Speed;
UpdateModel();
break;
case Key.W:
IsCanceled = true;
Camera.StartPosition.Y -= Camera.Speed;
UpdateModel();
break;
case Key.S:
IsCanceled = true;
Camera.StartPosition.Y += Camera.Speed;
UpdateModel();
break;
case Key.OemMinus:
IsCanceled = true;
Camera.Scale /= 2;
UpdateModel();
break;
case Key.OemPlus:
IsCanceled = true;
Camera.Scale *= 2;
UpdateModel();
break;
case Key.R:
IsCanceled = true;
Camera.CutDepth += Camera.Speed;
UpdateModel();
break;
case Key.F:
IsCanceled = true;
Camera.CutDepth -= Camera.Speed;
UpdateModel();
break;
case Key.D9:
if (Camera.Speed > 1)
{
IsCanceled = true;
Camera.Speed--;
UpdateModel();
}
break;
case Key.D0:
IsCanceled = true;
Camera.Speed++;
UpdateModel();
break;
case Key.T:
IsCanceled = true;
Camera.DepthVisibility -= Camera.Speed;
UpdateModel();
break;
case Key.G:
IsCanceled = true;
Camera.DepthVisibility += Camera.Speed;
UpdateModel();
break;
}
}
}
}