feat: 3D模型功能补全

master
Tongg 7 months ago
parent a92b3ba611
commit 20eae961e9
  1. 3
      Language/zh_CN.xaml
  2. 29
      Views/UserControl/Viewport3D.xaml
  3. 106
      Views/UserControl/Viewport3D.xaml.cs
  4. 15
      Views/UserControl/ViewportData/Helper/ViewportHelperPro.cs
  5. 7
      Views/UserControl/ViewportData/Helper/ViewportManager.cs
  6. 25
      Views/UserControl/ViewportData/ViewportData.cs

@ -114,4 +114,7 @@
<sys:String x:Key="ViewportRightMenuSelectFaceKind">显示选择面的同类面</sys:String>
<sys:String x:Key="ViewportRightMenuShowDefectFace">显示瑕疵面</sys:String>
<sys:String x:Key="ViewportRightMenuShowFront">显示正方向标识</sys:String>
<sys:String x:Key="ViewportSaveSucceed">保存成功</sys:String>
<sys:String x:Key="ViewportSaveFail">保存失败</sys:String>
<sys:String x:Key="ViewportSelectPath">选择路径</sys:String>
</ResourceDictionary>

@ -22,6 +22,7 @@
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Background="Transparent" BorderBrush="Transparent" Height="50" Padding="2"
x:Name="BtnFrontView" Click="BtnAngle_OnClick">
@ -31,7 +32,7 @@
<GradientStop Color="#FF4C4D4F" Offset="0.0" />
</RadialGradientBrush>
</Border.Background>
<Image Source="pack://Application:,,,/Resource/Images/UserControl/zuanshi@3x.png" ></Image>
<Image Source="pack://Application:,,,/Resource/Images/UserControl/zuanshi@3x.png" Width="30" Height="30"></Image>
</Border>
</Button>
<Button Grid.Column="1" Background="Transparent" BorderBrush="Transparent" Height="50" Padding="2"
@ -42,7 +43,7 @@
<GradientStop Color="#FF4C4D4F" Offset="0.0" />
</RadialGradientBrush>
</Border.Background>
<Image Source="pack://Application:,,,/Resource/Images/UserControl/Top@3x.png" ></Image>
<Image Source="pack://Application:,,,/Resource/Images/UserControl/Top@3x.png" Width="30" Height="30"></Image>
</Border>
</Button>
<Button Grid.Column="2" Background="Transparent" BorderBrush="Transparent" Height="50" Padding="2"
@ -53,27 +54,41 @@
<GradientStop Color="#FF4C4D4F" Offset="0.0" />
</RadialGradientBrush>
</Border.Background>
<Image Source="pack://Application:,,,/Resource/Images/UserControl/Bottom@3x.png" ></Image>
<Image Source="pack://Application:,,,/Resource/Images/UserControl/Bottom@3x.png" Width="30" Height="30"></Image>
</Border>
</Button>
<Button Grid.Column="3" Background="Transparent" BorderBrush="Transparent" Height="50" Padding="2"
x:Name="BtnFcuntion1View" Click="BtnFunction_OnClick">
<Border BorderThickness="1" CornerRadius="10" Padding="5" >
<Border.Background>
<RadialGradientBrush GradientOrigin="0.5,0.5" Center="0.5,0.5" RadiusX="0.5" RadiusY="0.5">
<GradientStop Color="#FF4C4D4F" Offset="0.0" />
</RadialGradientBrush>
</Border.Background>
<Image Source="pack://Application:,,,/Resource/Images/UserControl/biaochi1@3x.png" Width="30" Height="30"></Image>
</Border>
</Button>
<Button Grid.Column="3" Background="Transparent" BorderBrush="Transparent" Height="50" Padding="2">
<Button Grid.Column="4" Background="Transparent" BorderBrush="Transparent" Height="50" Padding="2"
x:Name="BtnFcuntion2View" Click="BtnFunction_OnClick">
<Border BorderThickness="1" CornerRadius="10" Padding="5" >
<Border.Background>
<RadialGradientBrush GradientOrigin="0.5,0.5" Center="0.5,0.5" RadiusX="0.5" RadiusY="0.5">
<GradientStop Color="#FF4C4D4F" Offset="0.0" />
</RadialGradientBrush>
</Border.Background>
<Image Source="pack://Application:,,,/Resource/Images/UserControl/biaochi1@3x.png" ></Image>
<Image Source="pack://Application:,,,/Resource/Images/UserControl/biaochi2@3x.png" Width="30" Height="30"></Image>
</Border>
</Button>
<Button Grid.Column="4" Background="Transparent" BorderBrush="Transparent" Height="50" Padding="2">
<Button Grid.Column="5" Background="Transparent" BorderBrush="Transparent" Height="50" Padding="2"
x:Name="BtnFcuntion3View" Click="BtnFunction_OnClick">
<Border BorderThickness="1" CornerRadius="10" Padding="5" >
<Border.Background>
<RadialGradientBrush GradientOrigin="0.5,0.5" Center="0.5,0.5" RadiusX="0.5" RadiusY="0.5">
<GradientStop Color="#FF4C4D4F" Offset="0.0" />
</RadialGradientBrush>
</Border.Background>
<Image Source="pack://Application:,,,/Resource/Images/UserControl/biaochi2@3x.png" ></Image>
<!-- <Image Source="pack://Application:,,,/Resource/Images/UserControl/biaochi2@3x.png" Width="30"></Image> -->
<Image Width="30" Height="30"></Image>
</Border>
</Button>
</Grid>

@ -5,7 +5,9 @@ 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;
@ -134,6 +136,46 @@ public partial class Viewport3D
}
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.PerspectiveCamera;
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);
ViewportHelperPro.RotateModel(new Vector3D(0,-1,0));
await Task.Delay(5000);
ViewportHelperPro.RotateModel(new Vector3D(-1,0,0));
break;
}
}
/// <summary>
/// 按钮调整相机方向[底部按钮]
@ -143,23 +185,56 @@ public partial class Viewport3D
private void BtnDirection_OnClick(object sender, RoutedEventArgs e)
{
var directionName = ((Button)sender).Name.ToString();
var directionValue = (int) TbCustomizeRevolve.Value;
var directionValue = (int)TbCustomizeRevolve.Value; // 旋转角度(单位:度)
// 获取当前相机和模型中心
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 = 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 轴为上方向
}
@ -247,11 +322,38 @@ public partial class Viewport3D
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;
}
}
#endregion
// <sys:String x:Key="ViewportSaveSucceed">保存成功</sys:String>
// <sys:String x:Key="ViewportSaveFail">保存失败</sys:String>
// <sys:String x:Key="ViewportSelectPath">选择路径</sys:String>
#region 页面隐式交互

@ -113,6 +113,8 @@ public class ViewportHelperPro
/// <param name="filePath"></param>
public static void ExportModelsToStl(Viewport3DX viewport, string filePath)
{
if (viewport == null)
viewport = ViewportManager.GetViewport3D();
// 打开文件写入流
using (StreamWriter writer = new StreamWriter(filePath))
{
@ -400,11 +402,11 @@ public class ViewportHelperPro
/// <param name="axis">中心</param>
/// <param name="hasLine">是否包含线</param>
/// <param name="speed">旋转时间 秒</param>
public static void RotateModel(Vector3D axis, bool hasLine = true, int speed = 5)
public static void RotateModel(Vector3D axis, bool hasLine = true, int speed = 5, int to = 360)
{
// 设置旋转的中心点和旋转轴
var rotateTransform = new RotateTransform3D();
var rotation = new AxisAngleRotation3D(axis, 0); // 初始角度为 0
var rotation = new AxisAngleRotation3D(axis, 0);
rotateTransform.Rotation = rotation;
rotateTransform.CenterX = ViewportManager.CenterVector.X;
rotateTransform.CenterY = ViewportManager.CenterVector.Y;
@ -414,11 +416,13 @@ public class ViewportHelperPro
ViewportManager.MainModel3D.Transform = rotateTransform;
if(hasLine)
ViewportManager.MainModelLines.ForEach(e => e.Transform = rotateTransform);
double currentAngle = rotation.Angle;
// 创建旋转动画
var rotateAnimation = new DoubleAnimation
{
From = 0,
To = 360,
From = currentAngle,
To = to + currentAngle,
Duration = new Duration(TimeSpan.FromSeconds(speed)),
FillBehavior = FillBehavior.HoldEnd
};
@ -427,9 +431,6 @@ public class ViewportHelperPro
rotation.BeginAnimation(AxisAngleRotation3D.AngleProperty, rotateAnimation);
}
/// <summary>
/// 在场景中添加文字
/// </summary>

@ -55,6 +55,13 @@ public class ViewportManager
if (_viewport == null)
_viewport = viewport3D;
}
public static Viewport3DX GetViewport3D()
{
if (_viewport == null)
throw new Exception("Viewport is not set");
return _viewport;
}
#region 模型选中交互管理
//是否双击选中

@ -140,4 +140,29 @@ public class ViewportData
}
public bool SaveAsToStlFile(string filename)
{
try
{
ViewportHelperPro.ExportModelsToStl(null, filename);
return true;
}
catch
{
return false;
}
}
public bool SaveAsToVedioFile(string filename)
{
try
{
ViewportHelperPro.ExportModelsToStl(null, filename);
return true;
}
catch
{
return false;
}
}
}
Loading…
Cancel
Save