From 26dfcb035525f599681cd3c6559b3d1cc1f62c45 Mon Sep 17 00:00:00 2001 From: sunhonglei Date: Tue, 21 Jan 2025 17:31:44 +0800 Subject: [PATCH] fix: --- .../ViewportData/Helper/ViewportHelperPro.cs | 182 ++++++++++++++++-- 1 file changed, 161 insertions(+), 21 deletions(-) diff --git a/Views/UserControl/ViewportData/Helper/ViewportHelperPro.cs b/Views/UserControl/ViewportData/Helper/ViewportHelperPro.cs index f4e2248..d31d3cf 100644 --- a/Views/UserControl/ViewportData/Helper/ViewportHelperPro.cs +++ b/Views/UserControl/ViewportData/Helper/ViewportHelperPro.cs @@ -1399,6 +1399,7 @@ public class ViewportHelperPro } private static bool isDrawing = false; private static Point3D previousMousePosition; + private static bool isOutOfRange = false; private static void LineA_MouseMove3D(object sender, RoutedEventArgs e) { @@ -1406,6 +1407,20 @@ public class ViewportHelperPro { if (e is HelixToolkit.Wpf.SharpDX.MouseMove3DEventArgs ev) { + // 定义中心点和半径 + var Y = -0.01F; + if (!IsCrown()) + { + Y = ViewportManager.ModelBounds.Maximum.Y + 0.01f; + } + var center = ViewportManager.CenterVector; + center.Y = Y; + double radius = 5; + if (double.TryParse(ViewportManager.DiamondData["M2"].ToString(), out var v)) + { + radius = (v * 0.5); + } + double minDistance = 0.01; // 最小距离 var line = sender as LineGeometryModel3D; // 直线方向分量 var lineDirection = line.Geometry.Positions[1] - line.Geometry.Positions[0]; @@ -1416,37 +1431,126 @@ public class ViewportHelperPro // 计算鼠标移动的方向 var moveDirection = previousMousePosition - currentMousePosition; - + // 计算垂直于线的移动分量 var perpendicularDirection = Vector3D.CrossProduct(lineDirection.ToVector3D(), Vector3D.CrossProduct(moveDirection, lineDirection.ToVector3D())); perpendicularDirection.Normalize(); - double scaleFactor = 0.05; // 缩放因子 + double scaleFactor = 13000; // 缩放因子 // 计算垂直距离 double perpendicularDistance = Vector3D.DotProduct(moveDirection, perpendicularDirection) * scaleFactor; - System.Console.WriteLine("距离:"+ perpendicularDistance); // 垂直方向偏移量 Vector3D projectedVector = perpendicularDistance * perpendicularDirection; projectedVector.Y = 0; - + + // 计算直线的新位置 var transform = new TranslateTransform3D(projectedVector); + var newPosition1 = line.Geometry.Positions[0].ToVector3D() + projectedVector; + var newPosition2 = line.Geometry.Positions[1].ToVector3D() + projectedVector; + + // 计算直线的新中心点 + Point3D newCenter = new Point3D( + (newPosition1.X + newPosition2.X) / 2, + (newPosition1.Y + newPosition2.Y) / 2, + (newPosition1.Z + newPosition2.Z) / 2 + ); + + // 计算当前中心点与中心点的距离 + double currentDistance = (newCenter - center.ToPoint3D()).Length; + + // 计算上一帧中心点与中心点的距离 + Point3D previousCenter = new Point3D( + (line.Geometry.Positions[0].X + line.Geometry.Positions[1].X) / 2, + (line.Geometry.Positions[0].Y + line.Geometry.Positions[1].Y) / 2, + (line.Geometry.Positions[0].Z + line.Geometry.Positions[1].Z) / 2 + ); + + double previousDistance = (previousCenter - center.ToPoint3D()).Length; + // 检查移动方向 + bool isMovingAway = currentDistance > previousDistance; // 是否远离中心点 + if (isMovingAway) + { + isOutOfRange = false; + }else if (isOutOfRange) + { + Logger.Info("超出范围,停止移动"); + } + // 检查新中心点是否满足距离条件 + if (IsPointInRange(newCenter, center.ToPoint3D(), radius, minDistance)) + { + + } + else if(isMovingAway) + { + //// 如果新中心点不满足条件,将位置限制在范围内 + //projectedVector = LimitToRange(newCenter, center.ToPoint3D(), radius, minDistance) - newCenter; + // 如果新中心点超出范围,将直线位置固定到最大允许位置 + Point3D maxCenter = LimitToMaxPosition(center.ToPoint3D(), radius, newCenter); + // 计算直线的起点和终点在最大允许位置 + projectedVector = maxCenter - previousCenter; + projectedVector.Y = 0; + transform = new TranslateTransform3D(projectedVector); + //Logger.Info($"X:{projectedVector.X},Z:{projectedVector.Z}"); + Logger.Info("超出范围,停止移动"); + }else if(!isMovingAway) + { + isOutOfRange = true; + Logger.Info("isOutOfRange = true;"); + } line.Transform = transform; // 更新上一帧的鼠标位置 //previousMousePosition = currentMousePosition; var otherLineGuid = moveLines[line.GUID]; var Viewport = ViewportManager.GetViewport3D(); - var otherLine = Viewport.Items.Where(x=>x.GUID == otherLineGuid).FirstOrDefault(); - if (otherLine!= null ) + var otherLine = Viewport.Items.Where(x => x.GUID == otherLineGuid).FirstOrDefault(); + if (otherLine != null) { - Vector3D projectedVector_other = -perpendicularDistance * perpendicularDirection; - projectedVector_other.Y = 0; - var transform_other = new TranslateTransform3D(projectedVector_other); + var transform_other = new TranslateTransform3D(-projectedVector); otherLine.Transform = transform_other; } - } } } + // 检查点是否在范围内(距离大于 minDistance 且小于等于 radius) + private static bool IsPointInRange(Point3D point, Point3D center, double radius, double minDistance) + { + double distance = (point - center).Length; + Logger.Info("距离:" + distance); + return distance > minDistance && distance <= radius; + } + + private static Point3D LimitToMaxPosition(Point3D center, double radius, Point3D currentCenter) + { + // 计算当前中心点与中心点的方向 + Vector3D direction = currentCenter - center; + direction.Normalize(); + + // 计算最大允许位置 + return center + direction * radius; + } + + // 将点限制在范围内(距离大于 minDistance 且小于等于 radius) + private static Point3D LimitToRange(Point3D point, Point3D center, double radius, double minDistance) + { + Vector3D direction = point - center; + double distance = direction.Length; + + if (distance <= minDistance) + { + // 如果距离小于等于最小距离,将点偏移到最小距离处 + direction.Normalize(); + return center + direction * minDistance; + } + else if (distance > radius) + { + // 如果距离大于半径,将点限制在半径范围内 + direction.Normalize(); + return center + direction * radius; + } + + // 如果距离在范围内,直接返回点 + return point; + } private static void LineA_MouseUp3D(object sender, RoutedEventArgs e) { @@ -1470,13 +1574,9 @@ public class ViewportHelperPro { // 使用 HelixToolkit 的 Ray3D 和 Plane3D var Viewport = ViewportManager.GetViewport3D(); - var camera = Viewport.Camera as OrthographicCamera; - // 创建射线 - var ray = new Ray3D( - camera.Position, - new Vector3D(mousePosition.X - Viewport.ActualWidth / 2, -camera.Position.Y, -(mousePosition.Y - Viewport.ActualHeight / 2) ) - ); + // 获取射线 + var ray = GetRayFromMouse(mousePosition, Viewport); // 创建平面(假设平面为 Y=0) var plane = new Plane3D(new Point3D(0, 0, 0), new Vector3D(0, 1, 0)); @@ -1484,9 +1584,49 @@ public class ViewportHelperPro // 计算射线与平面的交点 var intersection = GetIntersection(ray, plane); - return intersection ?? new Point3D(0, 0, 0); + if (intersection == null) + { + // 如果没有交点,返回默认值或抛出异常 + throw new InvalidOperationException("No intersection found."); + } + return intersection.Value; } + private static Ray3D GetRayFromMouse(Point mousePosition, Viewport3DX viewport) + { + // 将鼠标坐标转换为归一化设备坐标 (NDC) + var ndc = new Vector2( + (float)(2.0 * mousePosition.X / viewport.ActualWidth - 1.0), + (float)(1.0 - 2.0 * mousePosition.Y / viewport.ActualHeight) + ); + + // 使用 UnProject 方法获取射线 + var ray = viewport.UnProject(ndc); + + // 返回射线 + return new Ray3D(ray.Position.ToPoint3D(), ray.Direction.ToPoint3D()); + } + + //private static Point3D? GetIntersection(Ray3D ray, Plane3D plane) + //{ + // // 计算射线方向与平面法向量的点积 + // double denominator = Vector3D.DotProduct(ray.Direction, plane.Normal); + + // // 如果点积为 0,说明射线与平面平行,没有交点 + // if (Math.Abs(denominator) < 1e-6) + // return null; + + // // 计算射线起点到平面的距离 + // double t = Vector3D.DotProduct(plane.Position - ray.Origin, plane.Normal) / denominator; + + // // 如果 t 为负数,说明交点在射线起点后方 + // if (t < 0) + // return null; + + // // 返回交点 + // return ray.Origin + ray.Direction * t; + //} + private static Point3D? GetIntersection(Ray3D ray, Plane3D plane) { // 将射线转换为直线(起点和终点) @@ -1571,25 +1711,25 @@ public class ViewportHelperPro // 计算鼠标与圆心的距离 double distance = CalculateDistance(mouseWorldPosition, center.ToPoint3D()); - + Console.WriteLine($"与圆心之间距离{distance}"); double scaleFactor = 0; if (distance < initDistance) { // 鼠标靠近圆心,缩小半径 - scaleFactor = -0.01; + scaleFactor = -1; } else { // 鼠标远离圆心,扩大半径 - scaleFactor = +0.01; + scaleFactor = +1; } // 计算鼠标移动的距离(以屏幕坐标为单位) double delta = (dragStartPoint - mousePosition).Length; // 计算新的半径 - double newRadius = initialRadius + delta * scaleFactor; // 缩放因子 + double newRadius = initialRadius + (distance - initDistance)*11000; // 缩放因子 // 限制半径范围 newRadius = Math.Clamp(newRadius, MinRadius, MaxRadius);