feat: 模型功能添加

master
tongg 7 months ago
parent d5b8e1cd58
commit e95ee69673
  1. 61
      Views/UserControl/Viewport3D.xaml
  2. 416
      Views/UserControl/Viewport3D.xaml.cs
  3. 13
      Views/UserControl/ViewportData/Helper/CommonHelper.cs
  4. 8
      Views/UserControl/ViewportData/Helper/ViewportHelperPro.cs
  5. 3
      Views/UserControl/ViewportData/Helper/ViewportManager.cs

@ -23,7 +23,8 @@
<ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Button Grid.Column="0" Background="Transparent" BorderBrush="Transparent" Height="50" Padding="2"> <Button Grid.Column="0" Background="Transparent" BorderBrush="Transparent" Height="50" Padding="2"
x:Name="BtnFrontView" Click="BtnAngle_OnClick">
<Border BorderThickness="1" CornerRadius="10" Padding="5"> <Border BorderThickness="1" CornerRadius="10" Padding="5">
<Border.Background> <Border.Background>
<RadialGradientBrush GradientOrigin="0.5,0.5" Center="0.5,0.5" RadiusX="0.5" RadiusY="0.5"> <RadialGradientBrush GradientOrigin="0.5,0.5" Center="0.5,0.5" RadiusX="0.5" RadiusY="0.5">
@ -33,7 +34,8 @@
<Image Source="pack://Application:,,,/Resource/Images/UserControl/zuanshi@3x.png" ></Image> <Image Source="pack://Application:,,,/Resource/Images/UserControl/zuanshi@3x.png" ></Image>
</Border> </Border>
</Button> </Button>
<Button Grid.Column="1" Background="Transparent" BorderBrush="Transparent" Height="50" Padding="2"> <Button Grid.Column="1" Background="Transparent" BorderBrush="Transparent" Height="50" Padding="2"
x:Name="BtnTopView" Click="BtnAngle_OnClick">
<Border BorderThickness="1" CornerRadius="10" Padding="5" > <Border BorderThickness="1" CornerRadius="10" Padding="5" >
<Border.Background> <Border.Background>
<RadialGradientBrush GradientOrigin="0.5,0.5" Center="0.5,0.5" RadiusX="0.5" RadiusY="0.5"> <RadialGradientBrush GradientOrigin="0.5,0.5" Center="0.5,0.5" RadiusX="0.5" RadiusY="0.5">
@ -43,7 +45,8 @@
<Image Source="pack://Application:,,,/Resource/Images/UserControl/Top@3x.png" ></Image> <Image Source="pack://Application:,,,/Resource/Images/UserControl/Top@3x.png" ></Image>
</Border> </Border>
</Button> </Button>
<Button Grid.Column="2" Background="Transparent" BorderBrush="Transparent" Height="50" Padding="2"> <Button Grid.Column="2" Background="Transparent" BorderBrush="Transparent" Height="50" Padding="2"
x:Name="BtnBottomView" Click="BtnAngle_OnClick">
<Border BorderThickness="1" CornerRadius="10" Padding="5" > <Border BorderThickness="1" CornerRadius="10" Padding="5" >
<Border.Background> <Border.Background>
<RadialGradientBrush GradientOrigin="0.5,0.5" Center="0.5,0.5" RadiusX="0.5" RadiusY="0.5"> <RadialGradientBrush GradientOrigin="0.5,0.5" Center="0.5,0.5" RadiusX="0.5" RadiusY="0.5">
@ -82,20 +85,24 @@
<MenuItem Header="{StaticResource ViewportRightMenuSaveViewToPNG}" x:Name="ViewportRightMenuSaveViewToPNG" Click="MenuItem_OnClick"/> <MenuItem Header="{StaticResource ViewportRightMenuSaveViewToPNG}" x:Name="ViewportRightMenuSaveViewToPNG" Click="MenuItem_OnClick"/>
<!-- 选择 --> <!-- 选择 -->
<Separator /> <Separator />
<MenuItem Header="{StaticResource ViewportRightMenuShowModelFace}" x:Name="ViewportRightMenuShowModelFace" IsCheckable="True" Checked="MenuItem_OnChecked" Unchecked="MenuItem_OnUnchecked"/> <MenuItem Header="{StaticResource ViewportRightMenuShowModelFace}" x:Name="ViewportRightMenuShowModelFace" IsCheckable="True" StaysOpenOnClick="True" Checked="MenuItem_OnCheckedChanged" Unchecked="MenuItem_OnCheckedChanged"/>
<MenuItem Header="{StaticResource ViewportRightMenuShowModelFrame}" x:Name="ViewportRightMenuShowModelFrame" IsCheckable="True" Checked="MenuItem_OnChecked" Unchecked="MenuItem_OnUnchecked"/> <MenuItem Header="{StaticResource ViewportRightMenuShowModelFrame}" x:Name="ViewportRightMenuShowModelFrame" IsCheckable="True" StaysOpenOnClick="True" Checked="MenuItem_OnCheckedChanged" Unchecked="MenuItem_OnCheckedChanged"/>
<MenuItem Header="{StaticResource ViewportRightMenuShowLighting}" x:Name="ViewportRightMenuShowLighting" IsCheckable="True" Checked="MenuItem_OnChecked" Unchecked="MenuItem_OnUnchecked"/> <MenuItem Header="{StaticResource ViewportRightMenuShowLighting}" x:Name="ViewportRightMenuShowLighting" IsCheckable="True" StaysOpenOnClick="True" Checked="MenuItem_OnCheckedChanged" Unchecked="MenuItem_OnCheckedChanged"/>
<MenuItem Header="{StaticResource ViewportRightMenuShowDefectFace}" x:Name="ViewportRightMenuShowDefectFace" IsCheckable="True" Checked="MenuItem_OnChecked" Unchecked="MenuItem_OnUnchecked"/> <MenuItem Header="{StaticResource ViewportRightMenuShowDefectFace}" x:Name="ViewportRightMenuShowDefectFace" IsCheckable="True" StaysOpenOnClick="True" Checked="MenuItem_OnCheckedChanged" Unchecked="MenuItem_OnCheckedChanged"/>
<MenuItem Header="{StaticResource ViewportRightMenuShowFront}" x:Name="ViewportRightMenuShowFront" IsCheckable="True" Checked="MenuItem_OnChecked" Unchecked="MenuItem_OnUnchecked"/> <MenuItem Header="{StaticResource ViewportRightMenuShowFront}" x:Name="ViewportRightMenuShowFront" IsCheckable="True" StaysOpenOnClick="True" Checked="MenuItem_OnCheckedChanged" Unchecked="MenuItem_OnCheckedChanged"/>
<Separator /> <Separator />
<MenuItem Header="{StaticResource ViewportRightMenuSelectFace}" x:Name="ViewportRightMenuSelectFace" IsCheckable="True" Checked="MenuItem_OnChecked" Unchecked="MenuItem_OnUnchecked"/> <MenuItem Header="{StaticResource ViewportRightMenuSelectFace}" x:Name="ViewportRightMenuSelectFace" IsCheckable="True" StaysOpenOnClick="True" Checked="MenuItem_OnCheckedChanged" Unchecked="MenuItem_OnCheckedChanged"/>
<MenuItem Header="{StaticResource ViewportRightMenuSelectFaceFrame}" x:Name="ViewportRightMenuSelectFaceFrame" IsCheckable="True" Checked="MenuItem_OnChecked" Unchecked="MenuItem_OnUnchecked"/> <MenuItem Header="{StaticResource ViewportRightMenuSelectFaceFrame}" x:Name="ViewportRightMenuSelectFaceFrame" IsCheckable="True" StaysOpenOnClick="True" Checked="MenuItem_OnCheckedChanged" Unchecked="MenuItem_OnCheckedChanged"/>
<MenuItem Header="{StaticResource ViewportRightMenuSelectFaceLengthText}" x:Name="ViewportRightMenuSelectFaceLengthText" IsCheckable="True" Checked="MenuItem_OnChecked" Unchecked="MenuItem_OnUnchecked"/> <MenuItem Header="{StaticResource ViewportRightMenuSelectFaceLengthText}" x:Name="ViewportRightMenuSelectFaceLengthText" IsCheckable="True" StaysOpenOnClick="True" Checked="MenuItem_OnCheckedChanged" Unchecked="MenuItem_OnCheckedChanged"/>
<MenuItem Header="{StaticResource ViewportRightMenuSelectFaceAngleText}" x:Name="ViewportRightMenuSelectFaceAngleText" IsCheckable="True" Checked="MenuItem_OnChecked" Unchecked="MenuItem_OnUnchecked"/> <MenuItem Header="{StaticResource ViewportRightMenuSelectFaceAngleText}" x:Name="ViewportRightMenuSelectFaceAngleText" IsCheckable="True" StaysOpenOnClick="True" Checked="MenuItem_OnCheckedChanged" Unchecked="MenuItem_OnCheckedChanged"/>
<MenuItem Header="{StaticResource ViewportRightMenuSelectFaceKind}" x:Name="ViewportRightMenuSelectFaceKind" IsCheckable="True" Checked="MenuItem_OnChecked" Unchecked="MenuItem_OnUnchecked"/> <MenuItem Header="{StaticResource ViewportRightMenuSelectFaceKind}" x:Name="ViewportRightMenuSelectFaceKind" IsCheckable="True" StaysOpenOnClick="True" Checked="MenuItem_OnCheckedChanged" Unchecked="MenuItem_OnCheckedChanged"/>
</ContextMenu> </ContextMenu>
</Border.ContextMenu> </Border.ContextMenu>
<hx:Viewport3DX x:Name="Viewport3Dx" ShowCoordinateSystem="True" PreviewMouseRightButtonUp="UIElement_OnPreviewMouseRightButtonUp" PreviewMouseRightButtonDown="UIElement_OnPreviewMouseRightButtonDown" PreviewMouseMove="Viewport3Dx_OnPreviewMouseMove"> <hx:Viewport3DX x:Name="Viewport3Dx" ShowCoordinateSystem="True"
PreviewMouseRightButtonUp="UIElement_OnPreviewMouseRightButtonUp"
PreviewMouseRightButtonDown="UIElement_OnPreviewMouseRightButtonDown"
PreviewMouseMove="Viewport3Dx_OnPreviewMouseMove"
MouseLeftButtonDown="Viewport3Dx_OnMouseLeftButtonDown">
<hx:Viewport3DX.EffectsManager><hx:EffectsManager ></hx:EffectsManager></hx:Viewport3DX.EffectsManager> <hx:Viewport3DX.EffectsManager><hx:EffectsManager ></hx:EffectsManager></hx:Viewport3DX.EffectsManager>
<hx:Viewport3DX.InputBindings> <hx:Viewport3DX.InputBindings>
<KeyBinding Key="B" Command="hx:ViewportCommands.BackView" /> <KeyBinding Key="B" Command="hx:ViewportCommands.BackView" />
@ -115,7 +122,7 @@
<Grid Width="100"> <Grid Width="100">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/> <ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/> <ColumnDefinition Width="2*"/>
<ColumnDefinition Width="1*"/> <ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Grid.RowDefinitions> <Grid.RowDefinitions>
@ -124,34 +131,44 @@
<RowDefinition Height="1*"/> <RowDefinition Height="1*"/>
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Button Grid.Column="1" Grid.Row="0" Padding="0" Background="Transparent" BorderBrush="Transparent" > <Button Grid.Column="1" Grid.Row="0" Padding="0" Background="Transparent" BorderBrush="Transparent"
x:Name="BtnTop" Click="BtnDirection_OnClick">
<Image Source="../../Resource/Images/UserControl/arrow.png" /> <Image Source="../../Resource/Images/UserControl/arrow.png" />
</Button> </Button>
<Button Grid.Column="0" Grid.Row="1" Padding="0" Background="Transparent" BorderBrush="Transparent" > <Button Grid.Column="0" Grid.Row="1" Padding="0" Background="Transparent" BorderBrush="Transparent"
x:Name="BtnLeft" Click="BtnDirection_OnClick">
<Image Source="../../Resource/Images/UserControl/arrow.png" RenderTransformOrigin="0.5,0.5"> <Image Source="../../Resource/Images/UserControl/arrow.png" RenderTransformOrigin="0.5,0.5">
<Image.RenderTransform > <Image.RenderTransform >
<RotateTransform Angle="-90" ></RotateTransform> <RotateTransform Angle="-90" ></RotateTransform>
</Image.RenderTransform> </Image.RenderTransform>
</Image> </Image>
</Button> </Button>
<Button Grid.Column="2" Grid.Row="1" Padding="0" Background="Transparent" BorderBrush="Transparent" > <Button Grid.Column="2" Grid.Row="1" Padding="0" Background="Transparent" BorderBrush="Transparent"
x:Name="BtnRight" Click="BtnDirection_OnClick">
<Image Source="../../Resource/Images/UserControl/arrow.png" RenderTransformOrigin="0.5,0.5"> <Image Source="../../Resource/Images/UserControl/arrow.png" RenderTransformOrigin="0.5,0.5">
<Image.RenderTransform > <Image.RenderTransform >
<RotateTransform Angle="90" ></RotateTransform> <RotateTransform Angle="90" ></RotateTransform>
</Image.RenderTransform> </Image.RenderTransform>
</Image> </Image>
</Button> </Button>
<Button Grid.Column="1" Grid.Row="2" Padding="0" Background="Transparent" BorderBrush="Transparent" > <Button Grid.Column="1" Grid.Row="2" Padding="0" Background="Transparent" BorderBrush="Transparent"
x:Name="BtnBottom" Click="BtnDirection_OnClick">
<Image Source="../../Resource/Images/UserControl/arrow.png" RenderTransformOrigin="0.5,0.5"> <Image Source="../../Resource/Images/UserControl/arrow.png" RenderTransformOrigin="0.5,0.5">
<Image.RenderTransform > <Image.RenderTransform >
<RotateTransform Angle="180" ></RotateTransform> <RotateTransform Angle="180" ></RotateTransform>
</Image.RenderTransform> </Image.RenderTransform>
</Image> </Image>
</Button> </Button>
<TextBox Grid.Column="1" Grid.Row="1" Style="{StaticResource TextBoxExtend}" Padding="0" TextAlignment="Center" Text="123">
</TextBox> <!-- <TextBox Grid.Column="1" Grid.Row="2" Style="{StaticResource TextBoxExtend}" -->
<!-- Padding="0" TextAlignment="Center" x:Name="TbCustomizeRevolve" -->
<!-- MaxLength="3" -->
<!-- PreviewTextInput="TbCustomizeRevolve_OnPreviewTextInput" -->
<!-- PreviewKeyDown="TbCustomizeRevolve_OnPreviewKeyDown" -->
<!-- TextChanged="TbCustomizeRevolve_OnTextChanged" -->
<!-- -->
<!-- /> -->
<hc:NumericUpDown Grid.Column="1" Grid.Row="1" Padding="0" HorizontalContentAlignment="Center" Maximum="360" x:Name="TbCustomizeRevolve"/>
</Grid> </Grid>
</Grid> </Grid>
</Grid> </Grid>

@ -2,6 +2,7 @@ using System.Text.Json.Nodes;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media.Media3D;
using HandyControl.Controls; using HandyControl.Controls;
using HelixToolkit.Wpf.SharpDX; using HelixToolkit.Wpf.SharpDX;
using SharpDX; using SharpDX;
@ -13,210 +14,353 @@ namespace SparkClient.Views.UserControl;
public partial class Viewport3D public partial class Viewport3D
{ {
// 注册一个依赖属性,类型是 Viewport3DData
public static readonly DependencyProperty ViewportDataProperty =
DependencyProperty.Register(
nameof(ViewportData),
typeof(ViewportData.ViewportData),
typeof(Viewport3D),
new PropertyMetadata(null, OnViewportDataChanged));
// 公开的 CLR 属性包装器 public Viewport3D()
public ViewportData.ViewportData ViewportData
{ {
get => (ViewportData.ViewportData)GetValue(ViewportDataProperty); InitializeComponent();
set => SetValue(ViewportDataProperty, value); DataContext = this;
this.Viewport3Dx.EffectsManager = new DefaultEffectsManager();
Viewport3Dx.ShowViewCube = false;
Viewport3Dx.ShowCoordinateSystem = false;
ViewportManager.SetViewport3D(Viewport3Dx);
} }
// 当 ViewportData 属性发生变化时触发 /// <summary>
private static void OnViewportDataChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) /// 初始化
{ /// </summary>
if (d is Viewport3D control && e.NewValue is ViewportData.ViewportData data) /// <param name="sender"></param>
/// <param name="e"></param>
private void Viewport3D_OnLoaded(object sender, RoutedEventArgs e)
{ {
control.Initialize(data); ViewportManager.LoadModelByEntities(new List<Viewport3DTriangleEntity>());
}
}
//选项初始化 显示-后端-管理类 一致
ViewportRightMenuSelectFaceFrame.IsEnabled = ViewportRightMenuSelectFace.IsChecked ;
ViewportRightMenuSelectFaceLengthText.IsEnabled = ViewportRightMenuSelectFace.IsChecked ;
ViewportRightMenuSelectFaceAngleText.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;
ViewportRightMenuSelectFaceKind.IsChecked = ViewportManager.DoubleClickSelectShowPlaneType;
private void Initialize(ViewportData.ViewportData vpData)
{
// 根据 Viewport3DData 的内容初始化控件
// 例如:设置控件内部的某些属性,渲染 3D 模型等
if (!string.IsNullOrEmpty(vpData.DiamondData))
{
JsonNode? json = null;
try
{
json = JsonNode.Parse(vpData.DiamondData);
} }
catch /// <summary>
/// 双击选择面
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Viewport3Dx_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{ {
throw new Exception("DiamondData is invalid"); if (ViewportManager.DoubleClickSelect == false) return;
}
if(json == null) throw new Exception("DiamondData is invalid"); var mousePosition = e.GetPosition(Viewport3Dx);
var hits = Viewport3Dx.FindHits(mousePosition);
try // 如果没有命中任何 3D 对象
{ if (hits == null || hits.Count == 0)
List<Viewport3DTriangleEntity> facets = new List<Viewport3DTriangleEntity>();
if (json.AsObject()["facets"] != null)
{ {
JsonArray jsonArray = json.AsObject()["facets"].AsArray(); ViewportManager.ClearDicModels();
foreach (var item in jsonArray) return;
{
var value = CommonHelper.CreateByJsonStr(item.ToString());
facets.Add(value);
}
}
else
{
throw new Exception("facets is invalid");
} }
if (json.AsObject()["positive_direction"] != null) // 获取第一个命中的对象
var hit = hits[0];
// 检查是否是 MeshGeometryModel3D
if (hit.ModelHit is MeshGeometryModel3D modelHit)
{ {
JsonObject positive = json.AsObject()["positive_direction"].AsObject(); // 获取几何信息
ViewportManager.PositiveDirection.X = float.Parse(positive["x"]?.ToString() ?? "1.0"); var geometry = modelHit.Geometry as HelixToolkit.Wpf.SharpDX.MeshGeometry3D;
ViewportManager.PositiveDirection.Y = float.Parse(positive["z"]?.ToString() ?? "0"); if (geometry != null)
ViewportManager.PositiveDirection.Z = float.Parse(positive["y"]?.ToString() ?? "0");
}
else
{ {
ViewportManager.PositiveDirection.X = 1.0f; // 获取命中的三角形索引
ViewportManager.PositiveDirection.Y = 0f; var triangleIndex = hit.TriangleIndices;
ViewportManager.PositiveDirection.Z = 0;
}
var midZ = facets.SelectMany(e => new[] { e.Point1.X, e.Point2.X, e.Point3.X }).OrderBy(z => Math.Abs(z)) // 获取三角形顶点
.First(); var vertex1 = geometry.Positions[triangleIndex.Item1];
List<Viewport3DTriangleEntity> facetsFinal = new List<Viewport3DTriangleEntity>(); var vertex2 = geometry.Positions[triangleIndex.Item2];
foreach (var item in facets) var vertex3 = geometry.Positions[triangleIndex.Item3];
{
var data = ViewportHelperPro.VectorClockwiseSort(new List<Vector3>
{ item.Point1, item.Point2, item.Point3 });
if (item.PlaneType == PlaneType.StarFacet || item.PlaneType == PlaneType.UpperGirdleFacet || ViewportManager.ChooseTriangleCode = CommonHelper.GenerateTriangleCode(vertex1, vertex2, vertex3);
item.PlaneType == PlaneType.UpperMainFacet || item.PlaneType == PlaneType.TableFacet) ViewportManager.ResetChooseAddModels();
{
item.Point1 = data[0];
item.Point2 = data[1];
item.Point3 = data[2];
} }
else if (item.PlaneType == PlaneType.Girdle)
{
var center = ViewportHelperPro.GetCentroid(data);
data.Sort((v1, v2) =>
{
double angle1 = Math.Atan2(v1.Y - center.Y, v1.X - center.X);
double angle2 = Math.Atan2(v2.Y - center.Y, v2.X - center.X);
return angle1.CompareTo(angle2);
});
if (center.Z >= midZ)
{
item.Point1 = data[0];
item.Point2 = data[1];
item.Point3 = data[2];
} }
else else
{ {
item.Point1 = data[2]; ViewportManager.ClearDicModels();
item.Point2 = data[1];
item.Point3 = data[0];
} }
} }
else
{
item.Point1 = data[2];
item.Point2 = data[1];
item.Point3 = data[0];
}
item.TriangleCode = CommonHelper.GenerateTriangleCode(item.Point1, item.Point2, item.Point3); /// <summary>
facetsFinal.Add(item); /// 顶部按钮 - 视角切换
} /// </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.PerspectiveCamera;
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;
// ViewportManager.ViewportTriangle.AddRange(facetsFinal);
ViewportManager.LoadModelByEntities(facetsFinal);
} }
catch (Exception ex) camera.LookDirection = new Vector3D(center.X - camera.Position.X, center.Y - camera.Position.Y, center.Z - camera.Position.Z);
{
throw new Exception(ex.Message);
} }
/// <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;
switch (directionName)
{
case "BtnTop":
//上
break;
case "BtnBottom":
//下
break;
case "BtnLeft":
//左
break;
case "BtnRight":
//右
break;
} }
} }
public Viewport3D()
#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 ;
ViewportRightMenuSelectFaceKind.IsEnabled = ViewportRightMenuSelectFace.IsChecked ;
var controlName = ((MenuItem)sender).Name.ToString();
var checkResult = (bool)((MenuItem)sender).IsChecked;
switch (controlName)
{
case "ViewportRightMenuShowModelFace":
//显示模型面
ViewportManager.ShowMainModel3D(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 "ViewportRightMenuSelectFaceAngleText":
//双击选择面的边框夹角文字
ViewportManager.DoubleClickSelectShowBorderAngle = checkResult;
ViewportManager.ResetChooseAddModels();
break;
case "ViewportRightMenuSelectFaceKind":
//双击选择面的选择同类面
ViewportManager.DoubleClickSelectShowPlaneType = checkResult;
ViewportManager.ResetChooseAddModels();
break;
}
}
/// <summary>
/// 右键按钮
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void MenuItem_OnClick(object sender, RoutedEventArgs e)
{ {
InitializeComponent(); var controlName = ((MenuItem)sender).Name.ToString();
DataContext = this; switch (controlName)
this.Viewport3Dx.EffectsManager = new DefaultEffectsManager(); {
ViewportManager.SetViewport3D(Viewport3Dx); 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":
//保存图片
break;
}
} }
#endregion
#region 菜单事件绑定 #region 页面隐式交互
private void MenuItem_OnChecked(object sender, RoutedEventArgs e)
public static readonly DependencyProperty ViewportDataProperty =
DependencyProperty.Register(
nameof(ViewportData),
typeof(ViewportData.ViewportData),
typeof(Viewport3D),
new PropertyMetadata(null, OnViewportDataChanged));
public ViewportData.ViewportData ViewportData
{ {
Growl.InfoGlobal("Viewport is checked" + e.OriginalSource); get => (ViewportData.ViewportData)GetValue(ViewportDataProperty);
set => SetValue(ViewportDataProperty, value);
} }
private static void OnViewportDataChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
private void MenuItem_OnUnchecked(object sender, RoutedEventArgs e)
{ {
Growl.InfoGlobal("Viewport is Unchecked" + e.OriginalSource); if (d is Viewport3D control && e.NewValue is ViewportData.ViewportData data)
{
control.Initialize(data);
} }
private void MenuItem_OnClick(object sender, RoutedEventArgs e) }
private void Initialize(ViewportData.ViewportData vpData)
{ {
} }
#endregion
#region 页面隐式交互
private System.Windows.Point _mouseDownPosition; private System.Windows.Point _mouseDownPosition;
private bool _isDragging = false; private bool _isDragging = false;
private void UIElement_OnPreviewMouseRightButtonUp(object sender, MouseButtonEventArgs e) private void UIElement_OnPreviewMouseRightButtonUp(object sender, MouseButtonEventArgs e)
{ {
if (_isDragging) if (_isDragging)
{ {
// 如果发生拖动,不显示菜单 _isDragging = false;
_isDragging = false; // 重置拖动状态
MainBorder.ContextMenu.Visibility = Visibility.Hidden; MainBorder.ContextMenu.Visibility = Visibility.Hidden;
MainBorder.ContextMenu.IsOpen = false;
return; return;
} }
MainBorder.ContextMenu.Visibility = Visibility.Visible; MainBorder.ContextMenu.Visibility = Visibility.Visible;
// 未拖动时,显示右键菜单
MainBorder.ContextMenu.IsOpen = true;
// e.Handled = true; // 阻止事件继续传播
} }
private void UIElement_OnPreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e) private void UIElement_OnPreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{ {
_mouseDownPosition = e.GetPosition(Viewport3Dx); _mouseDownPosition = e.GetPosition(Viewport3Dx);
_isDragging = false; // 重置拖动状态 _isDragging = false;
if (MainBorder.ContextMenu.Visibility == Visibility.Visible)
}
#endregion
private void Viewport3D_OnLoaded(object sender, RoutedEventArgs e)
{ {
//ViewportData.LoadData(); MainBorder.ContextMenu.Visibility = Visibility.Hidden;
ViewportManager.LoadModelByEntities(new List<Viewport3DTriangleEntity>()); MainBorder.ContextMenu.IsOpen = false;
}
} }
private void Viewport3Dx_OnPreviewMouseMove(object sender, MouseEventArgs e) private void Viewport3Dx_OnPreviewMouseMove(object sender, MouseEventArgs e)
{ {
if (e.RightButton == MouseButtonState.Pressed) if (e.RightButton == MouseButtonState.Pressed)
{ {
// 计算鼠标移动距离
var currentPosition = e.GetPosition(Viewport3Dx); var currentPosition = e.GetPosition(Viewport3Dx);
var distance = (currentPosition - _mouseDownPosition).Length; 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)
if (distance > 5) // 阈值可根据需要调整 {
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)
{ {
_isDragging = true; // 标记为拖动 textBox.Text = "360"; // 如果大于360,重置为360
}
textBox.SelectionStart = textBox.Text.Length; // 保持光标在文本末尾
} }
else if (!string.IsNullOrWhiteSpace(textBox.Text))
{
textBox.Text = "0";
} }
} }
#endregion
} }

@ -1,5 +1,6 @@
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text; using System.Text;
using System.Windows.Input;
using Newtonsoft.Json; using Newtonsoft.Json;
using SharpDX; using SharpDX;
using SparkClient.Views.UserControl.ViewportData.Entity; using SparkClient.Views.UserControl.ViewportData.Entity;
@ -9,6 +10,18 @@ namespace SparkClient.Views.UserControl.ViewportData.Helper;
public class CommonHelper public class CommonHelper
{ {
public static bool IsTextNumeric(string text)
{
return int.TryParse(text, out _); // 只允许数字输入
}
public static bool IsKeyNumeric(Key key)
{
// 判断按键是否是数字键
return (key >= Key.D0 && key <= Key.D9) || (key >= Key.NumPad0 && key <= Key.NumPad9);
}
public static Viewport3DTriangleEntity CreateByJsonStr(string json) public static Viewport3DTriangleEntity CreateByJsonStr(string json)
{ {
// 解析 JSON 数据 // 解析 JSON 数据

@ -558,11 +558,11 @@ public class ViewportHelperPro
Vector3 cameraPosition, Vector3 cameraPosition,
Vector3 modelCenter, Vector3 modelCenter,
BoundingBox modelBounds, BoundingBox modelBounds,
float totalLength = 2f, // 箭头总长度 float totalLength = 1.5f, // 箭头总长度
float cylinderRatio = 0.7f,// 圆柱部分占比 float cylinderRatio = 0.7f,// 圆柱部分占比
float diameter = 0.5f, // 箭头直径 float diameter = 0.25f, // 箭头直径
float headDiameterRatio = 1f, // 圆锥直径与圆柱直径的比例 float headDiameterRatio = 2f, // 圆锥直径与圆柱直径的比例
float padding = 2.0f float padding = 1.0f
) )
{ {
// 计算模型的半径(对角线的一半) // 计算模型的半径(对角线的一半)

@ -1,8 +1,10 @@
using System.Windows.Media.Media3D;
using HelixToolkit.Wpf.SharpDX; using HelixToolkit.Wpf.SharpDX;
using SharpDX; using SharpDX;
using SharpDX.Direct3D11; using SharpDX.Direct3D11;
using SparkClient.Views.UserControl.ViewportData.Entity; using SparkClient.Views.UserControl.ViewportData.Entity;
using SparkClient.Views.UserControl.ViewportData.Enum; using SparkClient.Views.UserControl.ViewportData.Enum;
using GeometryModel3D = HelixToolkit.Wpf.SharpDX.GeometryModel3D;
namespace SparkClient.Views.UserControl.ViewportData.Helper; namespace SparkClient.Views.UserControl.ViewportData.Helper;
@ -152,6 +154,7 @@ public class ViewportManager
MainModelLighting = ViewportHelperPro.GenerateLightingForModel(_viewport); MainModelLighting = ViewportHelperPro.GenerateLightingForModel(_viewport);
//切换相机视角 //切换相机视角
_viewport.Camera = ViewportHelperPro.CalculateCamera(PositiveDirection, ModelBounds); _viewport.Camera = ViewportHelperPro.CalculateCamera(PositiveDirection, ModelBounds);
_viewport.Camera.UpDirection = new Vector3D(0, -1, 0);
_viewport.RenderHost.MSAA = MSAALevel.Maximum; _viewport.RenderHost.MSAA = MSAALevel.Maximum;
} }

Loading…
Cancel
Save