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.

621 lines
25 KiB

using System.Text.Json.Nodes;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media.Media3D;
using HandyControl.Controls;
using HelixToolkit.Wpf.SharpDX;
using Microsoft.Win32;
using SharpDX;
using SparkClient.Model.Helper;
using SparkClient.Views.UserControl.ViewportData.Entity;
using SparkClient.Views.UserControl.ViewportData.Enum;
using SparkClient.Views.UserControl.ViewportData.Helper;
using HelixToolkit.Wpf.SharpDX;
using SharpDX;
using SharpDX.Direct3D11;
using SharpDX.DXGI;
using MathNet.Numerics;
using System.Windows.Media;
using ObjExporter = SparkClient.Views.UserControl.ViewportData.Helper.ObjExporter;
namespace SparkClient.Views.UserControl;
public partial class Viewport3D
{
public Viewport3D()
{
InitializeComponent();
DataContext = this;
this.Viewport3Dx.EffectsManager = new DefaultEffectsManager();
Viewport3Dx.ShowViewCube = false;
Viewport3Dx.ShowCoordinateSystem = false;
ViewportManager.SetViewport3D(Viewport3Dx);
}
/// <summary>
/// 初始化
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Viewport3D_OnLoaded(object sender, RoutedEventArgs e)
{
ViewportManager.SetViewport3D(Viewport3Dx);
ViewportManager.SetViewport(this);
ViewportManager.LoadModelByEntities(new List<Viewport3DTriangleEntity>());
#if DEBUG
#else
// BtnShow3DView.Visibility = Visibility.Hidden;
#endif
//选项初始化 显示-后端-管理类 一致
ViewportRightMenuSelectFaceFrame.IsEnabled = ViewportRightMenuSelectFace.IsChecked ;
// ViewportRightMenuSelectFaceLengthText.IsEnabled = ViewportRightMenuSelectFace.IsChecked ;
// ViewportRightMenuSelectFaceAngleText.IsEnabled = ViewportRightMenuSelectFace.IsChecked ;
ViewportRightMenuSelectFaceText.IsEnabled = ViewportRightMenuSelectFace.IsChecked ;
ViewportRightMenuSelectFaceKind.IsEnabled = ViewportRightMenuSelectFace.IsChecked ;
ViewportRightMenuShowModelFace.IsChecked = true;
ViewportRightMenuShowModelFrame.IsChecked = true;
ViewportRightMenuShowLighting.IsChecked = true;
ViewportRightMenuSelectFace.IsChecked = ViewportManager.DoubleClickSelect;
ViewportRightMenuSelectFaceFrame.IsChecked = ViewportManager.DoubleClickSelectShowBorder;
// ViewportRightMenuSelectFaceLengthText.IsChecked = ViewportManager.DoubleClickSelectShowBorderLength;
// ViewportRightMenuSelectFaceAngleText.IsChecked = ViewportManager.DoubleClickSelectShowBorderAngle;
ViewportRightMenuSelectFaceText.IsChecked = ViewportManager.DoubleClickSelectShowInfoText;
ViewportRightMenuSelectFaceKind.IsChecked = ViewportManager.DoubleClickSelectShowPlaneType;
ViewportRightMenuShowModelFaceByType.IsChecked = true;
var a = Viewport3Dx.Items;
#if DEBUG
//Viewport3Dx.ShowViewCube = true;
//Viewport3Dx.ShowCoordinateSystem = true;
//Viewport3Dx.ShowCameraInfo = true;
//Viewport3Dx.ShowCameraTarget = !Viewport3Dx.ShowCameraTarget;
//Viewport3Dx.ShowFrameDetails = !Viewport3Dx.ShowFrameDetails;
//Viewport3Dx.ShowFrameRate = !Viewport3Dx.ShowFrameRate;
//Viewport3Dx.ShowTriangleCountInfo = !Viewport3Dx.ShowTriangleCountInfo;
#endif
}
/// <summary>
/// 双击选择面
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Viewport3Dx_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (ViewportManager.DoubleClickSelect == false) return;
var mousePosition = e.GetPosition(Viewport3Dx);
var hits = Viewport3Dx.FindHits(mousePosition);
// 如果没有命中任何 3D 对象
if (hits == null || hits.Count == 0)
{
ViewportManager.ClearDicModels();
return;
}
// 获取第一个命中的对象
var hit = hits[0];
// 检查是否是 MeshGeometryModel3D
if (hit.ModelHit is MeshGeometryModel3D modelHit)
{
// 获取几何信息
var geometry = modelHit.Geometry as HelixToolkit.Wpf.SharpDX.MeshGeometry3D;
if (geometry != null)
{
// 获取命中的三角形索引
var triangleIndex = hit.TriangleIndices;
// 获取三角形顶点
var vertex1 = geometry.Positions[triangleIndex.Item1];
var vertex2 = geometry.Positions[triangleIndex.Item2];
var vertex3 = geometry.Positions[triangleIndex.Item3];
ViewportManager.ChooseTriangleCode = CommonHelper.GenerateTriangleCode(vertex1, vertex2, vertex3);
ViewportManager.ResetChooseAddModels();
}
}
else
{
ViewportManager.ClearDicModels();
}
}
/// <summary>
/// 顶部按钮 - 视角切换
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
/// <exception cref="NotImplementedException"></exception>
private void BtnAngle_OnClick(object sender, RoutedEventArgs e)
{
var directionName = ((Button)sender).Name.ToString();
var directionValue = (int) TbCustomizeRevolve.Value;
var center = ViewportManager.ModelBounds.Center;
var maxDimension = ViewportManager.ModelBounds.Size.Length();
var distance = maxDimension * 1.2; // 调整相机到模型的距离,保证视野范围内
// 获取当前相机
var camera = Viewport3Dx.Camera as HelixToolkit.Wpf.SharpDX.OrthographicCamera;
switch (directionName)
{
case "BtnFrontView":
//测
camera.Position = new Point3D(center.X, center.Y, center.Z + distance); // 从前面看,Z轴正方向
camera.UpDirection = new Vector3D(0, -1, 0);
break;
break;
case "BtnTopView":
//顶、
camera.Position = new Point3D(center.X, center.Y - distance, center.Z); // 从底部看,Y轴负方向
camera.UpDirection = new Vector3D(0, 0, -1);
break;
case "BtnBottomView":
//低
camera.Position = new Point3D(center.X, center.Y + distance, center.Z); // 从顶部看,Y轴正方向
camera.UpDirection = new Vector3D(0, 0, 1);
break;
case "BtnFrontdView":
//测
camera.Position = new Point3D(center.X, center.Y, center.Z + distance); // 从前面看,Z轴正方向
camera.UpDirection = new Vector3D(0, 1, 0);
break;
}
camera.LookDirection = new Vector3D(center.X - camera.Position.X, center.Y - camera.Position.Y, center.Z - camera.Position.Z);
}
/// <summary>
/// 顶部按钮 - 功能
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
/// <exception cref="NotImplementedException"></exception>
private async void BtnFunction_OnClick(object sender, RoutedEventArgs e)
{
var directionName = ((Button)sender).Name.ToString();
var directionValue = (int) TbCustomizeRevolve.Value;
switch (directionName)
{
case "BtnFcuntion1View":
//测
break;
case "BtnFcuntion2View":
//顶
break;
case "BtnFcuntion3View":
//低
//var center = ViewportManager.ModelBounds.Center;
//var maxDimension = ViewportManager.ModelBounds.Size.Length();
//var distance = maxDimension *1.2; // 调整相机到模型的距离,保证视野范围内
//var camera = Viewport3Dx.Camera as HelixToolkit.Wpf.SharpDX.OrthographicCamera;
//camera.Position = new Point3D(center.X, center.Y, center.Z); // 从前面看,Z轴正方向
//camera.Width = ViewportManager.calCameraWidth();
//camera.UpDirection = new Vector3D(0, -1, 0);
//camera.LookDirection = new Vector3D(center.X - camera.Position.X, center.Y - camera.Position.Y, center.Z - camera.Position.Z);
var center = ViewportManager.ModelBounds.Center;
ViewportManager.ClearMeshLines();
var maxDimension = ViewportManager.ModelBounds.Size.Length();
var distance = maxDimension * 1.2; // 调整相机到模型的距离,保证视野范围内
var camera = Viewport3Dx.Camera as HelixToolkit.Wpf.SharpDX.OrthographicCamera;
camera.Position = new Point3D(center.X, center.Y, center.Z + distance); // 从前面看,Z轴正方向
camera.UpDirection = new Vector3D(0, -1, 0);
camera.LookDirection = new Vector3D(center.X - camera.Position.X, center.Y - camera.Position.Y, center.Z - camera.Position.Z);
await Task.Delay(100);
ViewportHelperPro.RotateModel(new Vector3D(0,-1,0));
await Task.Delay(7000);
ViewportHelperPro.RotateModel(new Vector3D(-1,0,0));
await Task.Delay(7000);
ViewportManager.DoubleClickSelect = !false;
break;
case "BtnShow3DView":
ObjExporter.ExportToObj2(ViewportManager.ViewportTriangle, @"D:\id03.obj");
// UnityHelper.GenerateRender(ViewportManager.ViewportTriangle.First().TriangleCode, "123");
break;
}
}
/// <summary>
/// 按钮调整相机方向[底部按钮]
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void BtnDirection_OnClick(object sender, RoutedEventArgs e)
{
var directionName = ((Button)sender).Name.ToString();
var directionValue = (int)TbCustomizeRevolve.Value; // 旋转角度(单位:度)
// 获取当前相机和模型中心
var camera = Viewport3Dx.Camera as HelixToolkit.Wpf.SharpDX.OrthographicCamera;
if (camera == null) return;
var modelCenter = ViewportManager.CenterVector; // 模型中心
var currentPosition = camera.Position;
// 将相机位置转换为极坐标
var dx = currentPosition.X - modelCenter.X;
var dy = currentPosition.Y - modelCenter.Y;
var dz = currentPosition.Z - modelCenter.Z;
var radius = Math.Sqrt(dx * dx + dy * dy + dz * dz); // 相机与模型中心的距离
var azimuth = Math.Atan2(dz, dx) * 180.0 / Math.PI; // 方位角(水平平面上的角度)
var elevation = Math.Atan2(dy, Math.Sqrt(dx * dx + dz * dz)) * 180.0 / Math.PI; // 仰角(垂直方向的角度)
switch (directionName)
{
case "BtnTop":
//上
elevation += directionValue;
break;
case "BtnBottom":
//下
elevation -= directionValue;
break;
case "BtnLeft":
//左
azimuth -= directionValue;
break;
case "BtnRight":
//右
azimuth += directionValue;
break;
}
// 限制仰角范围在 -89.9 到 89.9 度,避免超出范围导致位置错误
elevation = Math.Clamp(elevation, -89.9, 89.9);
azimuth = (azimuth + 360) % 360; // 方位角在 0 到 360 范围内循环
// 将极坐标转换回直角坐标
var newX = modelCenter.X + radius * Math.Cos(elevation * Math.PI / 180.0) * Math.Cos(azimuth * Math.PI / 180.0);
var newY = modelCenter.Y + radius * Math.Sin(elevation * Math.PI / 180.0);
var newZ = modelCenter.Z + radius * Math.Cos(elevation * Math.PI / 180.0) * Math.Sin(azimuth * Math.PI / 180.0);
// 更新相机位置和视角
camera.Position = new Point3D(newX, newY, newZ);
camera.LookDirection = new Vector3D(modelCenter.X - newX, modelCenter.Y - newY, modelCenter.Z - newZ);
// camera.UpDirection = new Vector3D(0, 1, 0); // 保持 Y 轴为上方向
}
// private void BtnDirection_OnClick(object sender, RoutedEventArgs e)
// {
// var directionName = ((Button)sender).Name.ToString();
// var directionValue = (int)TbCustomizeRevolve.Value; // 旋转角度(单位:度)
//
// if(directionValue == 0) return;
// // 获取当前相机和模型中心
// var camera = Viewport3Dx.Camera as HelixToolkit.Wpf.SharpDX.PerspectiveCamera;
// if (camera == null) return;
//
// var modelCenter = ViewportManager.CenterVector; // 模型中心
// var currentPosition = camera.Position;
//
// // 将相机位置转换为极坐标
// var dx = currentPosition.X - modelCenter.X;
// var dy = currentPosition.Y - modelCenter.Y;
// var dz = currentPosition.Z - modelCenter.Z;
//
// var radius = Math.Sqrt(dx * dx + dy * dy + dz * dz); // 相机与模型中心的距离
// var azimuth = Math.Atan2(dz, dx) * 180.0 / Math.PI; // 方位角(水平平面上的角度)
// var elevation = Math.Atan2(dy, Math.Sqrt(dx * dx + dz * dz)) * 180.0 / Math.PI; // 仰角(垂直方向的角度)
//
// switch (directionName)
// {
// case "BtnTop":
// //上
// elevation += directionValue;
// break;
// case "BtnBottom":
// //下
// elevation -= directionValue;
// break;
// case "BtnLeft":
// //左
// azimuth -= directionValue;
// break;
// case "BtnRight":
// //右
// azimuth += directionValue;
// break;
// }
// // 限制仰角范围在 -89.9 到 89.9 度,避免超出范围导致位置错误
// // elevation = elevation > 90 || elevation < -90 ? ? elevation + 90 : elevation - 90: elevation;
// // elevation = elevation;
// int isFan = 1;
// if (elevation > 90 || elevation < -90)
// {
// if (elevation < -90)
// {
// elevation += 90;
// }
// else
// {
// elevation -= 90;
// isFan = -1;
// }
// }
//
// azimuth = (azimuth + 360) % 360; // 方位角在 0 到 360 范围内循环
//
// // 将极坐标转换回直角坐标
// var newX = modelCenter.X + radius * Math.Cos(elevation * Math.PI / 180.0) * Math.Cos(azimuth * Math.PI / 180.0);
// var newY = modelCenter.Y + radius * Math.Sin(elevation * Math.PI / 180.0);
// var newZ = modelCenter.Z + radius * Math.Cos(elevation * Math.PI / 180.0) * Math.Sin(azimuth * Math.PI / 180.0);
//
// // 更新相机位置和视角
// camera.Position = new Point3D(newX, newY, newZ);
// camera.LookDirection = new Vector3D(modelCenter.X - newX, modelCenter.Y - newY, modelCenter.Z - newZ);
// camera.UpDirection = new Vector3D(camera.UpDirection.X, camera.UpDirection.Y * isFan, camera.UpDirection.Z); // 保持 Y 轴为上方向
//
//
//
// }
#region 右键菜单事件绑定
/// <summary>
/// 右键选择
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void MenuItem_OnCheckedChanged(object sender, RoutedEventArgs e)
{
ViewportRightMenuSelectFaceFrame.IsEnabled = ViewportRightMenuSelectFace.IsChecked ;
// ViewportRightMenuSelectFaceLengthText.IsEnabled = ViewportRightMenuSelectFace.IsChecked ;
// ViewportRightMenuSelectFaceAngleText.IsEnabled = ViewportRightMenuSelectFace.IsChecked ;
ViewportRightMenuSelectFaceText.IsEnabled = ViewportRightMenuSelectFace.IsChecked ;
ViewportRightMenuSelectFaceKind.IsEnabled = ViewportRightMenuSelectFace.IsChecked ;
var controlName = ((MenuItem)sender).Name.ToString();
var checkResult = (bool)((MenuItem)sender).IsChecked;
switch (controlName)
{
case "ViewportRightMenuShowModelFace":
//显示模型面
ViewportManager.ShowMainModel3D(checkResult);
// ViewportRightMenuShowModelFace.IsChecked = !checkResult;
// ViewportManager.ShowMainModel3DByType(!checkResult);
break;
case "ViewportRightMenuShowModelFaceByType":
//显示模型面
// ViewportManager.ShowMainModel3D(!checkResult);
// ViewportRightMenuShowModelFaceByType.IsChecked = !checkResult;
ViewportManager.ShowMainModel3DByType(checkResult);
break;
case "ViewportRightMenuShowModelFrame":
//显示模型边框
ViewportManager.ShowMainModelLines(checkResult);
break;
case "ViewportRightMenuShowLighting":
//显示光照
ViewportManager.ShowMainModelLighting(checkResult);
break;
case "ViewportRightMenuShowDefectFace":
//显示瑕疵面
ViewportManager.MarkSpecificFaces(checkResult);
break;
case "ViewportRightMenuShowFront":
//显示正方向箭头
ViewportManager.PointTowardsTheFront(checkResult);
break;
case "ViewportRightMenuSelectFace":
//双击选择面
ViewportManager.DoubleClickSelect = checkResult;
ViewportManager.ClearDicModels();
break;
case "ViewportRightMenuSelectFaceFrame":
//双击选择面的边框
ViewportManager.DoubleClickSelectShowBorder = checkResult;
ViewportManager.ResetChooseAddModels();
break;
case "ViewportRightMenuSelectFaceLengthText":
//双击选择面的边框长度文字
ViewportManager.DoubleClickSelectShowBorderLength = checkResult;
ViewportManager.ResetChooseAddModels();
break;
case "ViewportRightMenuSelectFaceText":
//双击选择面的边框长度文字
ViewportManager.DoubleClickSelectShowInfoText = checkResult;
ViewportManager.ResetChooseAddModels();
break;
case "ViewportRightMenuSelectFaceAngleText":
//双击选择面的边框夹角文字
ViewportManager.DoubleClickSelectShowBorderAngle = checkResult;
ViewportManager.ResetChooseAddModels();
break;
case "ViewportRightMenuSelectFaceKind":
//双击选择面的选择同类面
ViewportManager.DoubleClickSelectShowPlaneType = checkResult;
ViewportManager.ResetChooseAddModels();
break;
case "ViewportRightMenuShowMeshLines":
ViewportManager.ShowMeshLines(checkResult, ViewportHelperPro.IsCrown());
break;
}
}
/// <summary>
/// 右键按钮
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void MenuItem_OnClick(object sender, RoutedEventArgs e)
{
var controlName = ((MenuItem)sender).Name.ToString();
switch (controlName)
{
case "ViewportRightMenuFront":
//切换到正面
var Camear =
ViewportHelperPro.CalculateCamera(ViewportManager.PositiveDirection, ViewportManager.ModelBounds);
Viewport3Dx.Camera.Position = Camear.Position;
Viewport3Dx.Camera.LookDirection = Camear.LookDirection;
Viewport3Dx.Camera.UpDirection = new Vector3D(Camear.UpDirection.X, Camear.UpDirection.Y*-1, Camear.UpDirection.Z);
break;
case "ViewportRightMenuSaveViewToPNG":
//保存图片
var saveFileDialog = new SaveFileDialog
{
Filter = "PNG Files (*.png)|*.png",
Title = MultilingualHelper.getString("ViewportSelectPath"),
DefaultExt = "png"
};
if (saveFileDialog.ShowDialog() != true)
{
return; // 用户取消
}
string filePath = saveFileDialog.FileName;
try
{
ViewportHelperPro.SaveViewportAsImage(Viewport3Dx, filePath);
System.Windows.MessageBox.Show(MultilingualHelper.getString("ViewportSaveSucceed"));
}
catch (Exception ex)
{
System.Windows.MessageBox.Show($"{MultilingualHelper.getString("ViewportSaveFail")}:{ex.Message}", MultilingualHelper.getString("ViewportSaveFail"), System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
}
break;
case "ViewportRightMenuReset":
ViewportManager.ResetMeshLines();
break;
}
}
#endregion
// <sys:String x:Key="ViewportSaveSucceed">保存成功</sys:String>
// <sys:String x:Key="ViewportSaveFail">保存失败</sys:String>
// <sys:String x:Key="ViewportSelectPath">选择路径</sys:String>
#region 页面隐式交互
public static readonly DependencyProperty ViewportDataProperty =
DependencyProperty.Register(
nameof(ViewportData),
typeof(ViewportData.ViewportData),
typeof(Viewport3D),
new PropertyMetadata(null, OnViewportDataChanged));
public ViewportData.ViewportData ViewportData
{
get => (ViewportData.ViewportData)GetValue(ViewportDataProperty);
set => SetValue(ViewportDataProperty, value);
}
private static void OnViewportDataChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is Viewport3D control && e.NewValue is ViewportData.ViewportData data)
{
control.Initialize(data);
}
}
private void Initialize(ViewportData.ViewportData vpData)
{
}
private System.Windows.Point _mouseDownPosition;
private bool _isDragging = false;
private void UIElement_OnPreviewMouseRightButtonUp(object sender, MouseButtonEventArgs e)
{
if (_isDragging)
{
_isDragging = false;
MainBorder.ContextMenu.Visibility = Visibility.Hidden;
return;
}
MainBorder.ContextMenu.Visibility = Visibility.Visible;
}
private void UIElement_OnPreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
_mouseDownPosition = e.GetPosition(Viewport3Dx);
_isDragging = false;
if (MainBorder.ContextMenu.Visibility == Visibility.Visible)
{
MainBorder.ContextMenu.Visibility = Visibility.Hidden;
MainBorder.ContextMenu.IsOpen = false;
}
}
private void Viewport3Dx_OnPreviewMouseMove(object sender, MouseEventArgs e)
{
if (e.RightButton == MouseButtonState.Pressed)
{
var currentPosition = e.GetPosition(Viewport3Dx);
var distance = (currentPosition - _mouseDownPosition).Length;
MainBorder.ContextMenu.Visibility = Visibility.Hidden;
MainBorder.ContextMenu.IsOpen = false;
if (distance > 5)
{
_isDragging = true;
}
}
}
private void TbCustomizeRevolve_OnPreviewTextInput(object sender, TextCompositionEventArgs e)
{
e.Handled = !CommonHelper.IsTextNumeric(e.Text);
}
private void TbCustomizeRevolve_OnPreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Back || e.Key == Key.Delete || e.Key == Key.Tab || e.Key == Key.Left || e.Key == Key.Right)
{
e.Handled = false; // 不拦截
}
else
{
e.Handled = !CommonHelper.IsKeyNumeric(e.Key);
}
}
private void TbCustomizeRevolve_OnTextChanged(object sender, TextChangedEventArgs e)
{
var textBox = sender as System.Windows.Controls.TextBox;
if (int.TryParse(textBox.Text, out int value))
{
if (value < 0)
{
textBox.Text = "0"; // 如果小于0,重置为0
}
else if (value > 360)
{
textBox.Text = "360"; // 如果大于360,重置为360
}
textBox.SelectionStart = textBox.Text.Length; // 保持光标在文本末尾
}
else if (!string.IsNullOrWhiteSpace(textBox.Text))
{
textBox.Text = "0";
}
}
#endregion
private void TbCustomizeRevolve_OnMouseDoubleClick(object sender, MouseButtonEventArgs e)
{
//Viewport3Dx.ShowCameraInfo = !Viewport3Dx.ShowCameraInfo;
//Viewport3Dx.ShowCameraTarget = !Viewport3Dx.ShowCameraTarget ;
//Viewport3Dx.ShowFrameDetails = !Viewport3Dx.ShowFrameDetails;
//Viewport3Dx.ShowFrameRate = !Viewport3Dx.ShowFrameRate;
//Viewport3Dx.ShowTriangleCountInfo = !Viewport3Dx.ShowTriangleCountInfo;
}
}