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
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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|