diff --git a/Views/UserControl/Viewport3D.xaml b/Views/UserControl/Viewport3D.xaml index 138e33b..2c2ccfc 100644 --- a/Views/UserControl/Viewport3D.xaml +++ b/Views/UserControl/Viewport3D.xaml @@ -74,7 +74,6 @@ PreviewMouseRightButtonUp="UIElement_OnPreviewMouseRightButtonUp" PreviewMouseRightButtonDown="UIElement_OnPreviewMouseRightButtonDown" PreviewMouseMove="Viewport3Dx_OnPreviewMouseMove" - MouseLeftButtonDown="Viewport3Dx_MouseLeftButtonDown" MouseDoubleClick="Viewport3Dx_OnMouseLeftButtonDown"> diff --git a/Views/UserControl/Viewport3D.xaml.cs b/Views/UserControl/Viewport3D.xaml.cs index 1dc994f..74a0429 100644 --- a/Views/UserControl/Viewport3D.xaml.cs +++ b/Views/UserControl/Viewport3D.xaml.cs @@ -596,28 +596,4 @@ public partial class Viewport3D //Viewport3Dx.ShowTriangleCountInfo = !Viewport3Dx.ShowTriangleCountInfo; } - private void Viewport3Dx_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) - { - 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 LineGeometryModel3D modelHit) - //{ - // // 获取几何信息 - // if (modelHit != null) - // { - // } - //} - //else - //{ - // ViewportManager.ClearDicModels(); - //} - } } \ No newline at end of file diff --git a/Views/UserControl/ViewportData/Helper/ViewportHelperPro.cs b/Views/UserControl/ViewportData/Helper/ViewportHelperPro.cs index d1397a3..e14f879 100644 --- a/Views/UserControl/ViewportData/Helper/ViewportHelperPro.cs +++ b/Views/UserControl/ViewportData/Helper/ViewportHelperPro.cs @@ -1,29 +1,23 @@ -using System.Collections.Frozen; using System.Collections.ObjectModel; -using System.Diagnostics; -using System.Drawing.Text; using System.IO; -using System.Text.Json.Nodes; using System.Windows; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Media.Imaging; using System.Windows.Media.Media3D; -using System.Windows.Threading; -using HandyControl.Controls; using HelixToolkit.Wpf.SharpDX; using log4net; -using NPOI.OpenXmlFormats.Vml.Office; using SharpDX; using SharpDX.Direct3D11; -using SharpDX.DXGI; using SparkClient.Views.UserControl.ViewportData.Enum; using SparkClient.Views.UserControl.ViewportData.Entity; using Color = SharpDX.Color; using GeometryModel3D = HelixToolkit.Wpf.SharpDX.GeometryModel3D; -using NPOI.SS.Formula.Functions; using MeshGeometry3D = HelixToolkit.Wpf.SharpDX.MeshGeometry3D; -using NPOI.SS.UserModel; +using Point = System.Windows.Point; +using PerspectiveCamera = HelixToolkit.Wpf.SharpDX.PerspectiveCamera; +using System.Windows.Controls; + namespace SparkClient.Views.UserControl.ViewportData.Helper; @@ -1331,7 +1325,8 @@ public class ViewportHelperPro return lines; } private static bool isDrawing = false; - private static Vector3 startpoint; + private static Point3D previousMousePosition; + private static Vector3D _totalTranslation = new Vector3D(0, 0, 0); private static void LineA_MouseMove3D(object sender, RoutedEventArgs e) { if (isDrawing) @@ -1339,15 +1334,40 @@ public class ViewportHelperPro if (e is HelixToolkit.Wpf.SharpDX.MouseMove3DEventArgs ev) { var line = sender as LineGeometryModel3D; - var newPoint = ev.HitTestResult.PointHit; - var moveDirection = newPoint - startpoint; + var mousePosition = ev.Position; + var hitResult = ev.Viewport.FindNearestPoint(mousePosition); + if (hitResult == null) + { + return; + } var lineDirection = line.Geometry.Positions[1] - line.Geometry.Positions[0]; + lineDirection.Normalize(); - var perpendicularDirection = Vector3.Cross(lineDirection, Vector3.Cross(moveDirection, lineDirection)); + Vector3D referenceVector = new Vector3D(0, 1, 0); + Vector3D perpendicularDirection = Vector3D.CrossProduct(lineDirection.ToVector3D(), referenceVector); perpendicularDirection.Normalize(); - line.Geometry.Positions[0] += perpendicularDirection * Vector3.Dot(moveDirection, perpendicularDirection); - line.Geometry.Positions[1] += perpendicularDirection * Vector3.Dot(moveDirection, perpendicularDirection); + var currentMousePosition = Get3DPointFromMouse(mousePosition, ev.Viewport); + //// 计算垂直于线的移动分量 + //var perpendicularDirection = Vector3.Cross(lineDirection, Vector3.Cross(moveDirection,lineDirection)); + //perpendicularDirection.Normalize(); + + var point = hitResult.Value; + + var dragVector = point - ev.HitTestResult.PointHit.ToPoint3D(); + double dotProduct = Vector3D.DotProduct(dragVector, perpendicularDirection); + Vector3D projectedVector = dotProduct * perpendicularDirection; + projectedVector.Y = 0; + //// 计算垂直距离 + //float perpendicularDistance = Vector3.Dot(moveDirection, perpendicularDirection); + + //line.Geometry.Positions[0] += perpendicularDirection * perpendicularDistance; + + //line.Geometry.Positions[1] += perpendicularDirection * perpendicularDistance; + + _totalTranslation += projectedVector; + var transform = new TranslateTransform3D(projectedVector); + line.Transform = transform; } } } @@ -1361,10 +1381,36 @@ public class ViewportHelperPro { isDrawing = true; if(e is HelixToolkit.Wpf.SharpDX.MouseDown3DEventArgs ev){ - startpoint = ev.HitTestResult.PointHit; + // 获取鼠标点击的位置 + var mousePosition = ev.Position; + var a = ev.Viewport; + previousMousePosition = Get3DPointFromMouse(mousePosition, a); + + var line = sender as LineGeometryModel3D; + //var transform = new TranslateTransform3D(10, 0, 10); + //line.Transform = transform; + } } + private static Point3D Get3DPointFromMouse(Point mousePosition, Viewport3DX Viewport) + { + // 将2D屏幕坐标转换为3D世界坐标 + var ray = GetRayFromMouse(mousePosition, Viewport); + var plane = new Plane3D(new Point3D(0, 0, 0), new Vector3D(0, 0, 1)); // 假设平面为Z=0 + var intersection = plane.IntersectWith(ray); + + return intersection ?? new Point3D(0, 0, 0); + } + + private static Ray3D GetRayFromMouse(Point mousePosition, Viewport3DX Viewport) + { + // 获取从相机发出的射线 + var camera = Viewport.Camera as PerspectiveCamera; + var rayDirection = new Vector3D(mousePosition.X - Viewport.ActualWidth / 2, -(mousePosition.Y - Viewport.ActualHeight / 2), -camera.Position.Z); + rayDirection.Normalize(); + return new Ray3D(camera.Position, rayDirection); + } public static LineGeometryModel3D ShowCircleLine(double radius = 1.0, double thickness = 1.0) { @@ -1651,4 +1697,39 @@ public class ViewportHelperPro #endregion +} + +// 辅助类:表示3D射线 +public class Ray3D +{ + public Point3D Origin { get; } + public Vector3D Direction { get; } + + public Ray3D(Point3D origin, Vector3D direction) + { + Origin = origin; + Direction = direction; + } +} + +// 辅助类:表示3D平面 +public class Plane3D +{ + public Point3D Point { get; } + public Vector3D Normal { get; } + + public Plane3D(Point3D point, Vector3D normal) + { + Point = point; + Normal = normal; + } + + public Point3D? IntersectWith(Ray3D ray) + { + var denominator = Vector3D.DotProduct(ray.Direction, Normal); + if (Math.Abs(denominator) < 1e-6) return null; // 平行,无交点 + + var t = Vector3D.DotProduct(Point - ray.Origin, Normal) / denominator; + return ray.Origin + t * ray.Direction; + } } \ No newline at end of file