From da89105269db75e3b596713b49c7fb8ccab4ed23 Mon Sep 17 00:00:00 2001 From: tian <11429339@qq.com> Date: Sat, 31 Jan 2026 20:12:44 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=90=8A=E8=A3=85=E8=B7=AF?= =?UTF-8?q?=E5=BE=84=E7=82=B9=E5=A4=84=E7=90=86=EF=BC=8C=E7=A6=81=E6=AD=A2?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=85=B3=E9=94=AE=E7=82=B9=E5=B9=B6=E5=9C=A8?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=90=8E=E8=87=AA=E5=8A=A8=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E8=B7=AF=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Core/PathPlanningManager.cs | 505 ++++++++++++++---- src/PathPlanning/AerialPathGenerator.cs | 31 +- src/UI/WPF/ViewModels/PathEditingViewModel.cs | 15 + 3 files changed, 436 insertions(+), 115 deletions(-) diff --git a/src/Core/PathPlanningManager.cs b/src/Core/PathPlanningManager.cs index ae55b48..a4895b5 100644 --- a/src/Core/PathPlanningManager.cs +++ b/src/Core/PathPlanningManager.cs @@ -1893,12 +1893,135 @@ namespace NavisworksTransport } } + /// + /// 检测两点之间是否为斜线,如果是则插入中间转折点或修正坐标 + /// + /// 路径点列表 + /// 开始检查的索引 + /// 是否进行了修改(插入点或修正坐标) + private bool InsertIntermediatePointForDiagonal(IList points, int startIndex) + { + if (points == null || startIndex < 0 || startIndex >= points.Count - 1) + { + return false; + } + + var currentPoint = points[startIndex]; + var nextPoint = points[startIndex + 1]; + + LogManager.Info($"[斜线处理] 检查索引 {startIndex} 和 {startIndex + 1} 之间的连线"); + LogManager.Info($"[斜线处理] 当前点 [{startIndex}]: {currentPoint.Name}, 位置: ({currentPoint.Position.X:F2}, {currentPoint.Position.Y:F2}, {currentPoint.Position.Z:F2})"); + LogManager.Info($"[斜线处理] 下一点 [{startIndex + 1}]: {nextPoint.Name}, 位置: ({nextPoint.Position.X:F2}, {nextPoint.Position.Y:F2}, {nextPoint.Position.Z:F2})"); + + double deltaX = Math.Abs(nextPoint.Position.X - currentPoint.Position.X); + double deltaY = Math.Abs(nextPoint.Position.Y - currentPoint.Position.Y); + + // 检测斜线(X和Y都变化) + bool isDiagonal = deltaX > 0.01 && deltaY > 0.01; + + if (!isDiagonal) + { + return false; + } + + // 区分两种情况: + // 1. 真正的斜线:deltaX和deltaY都比较大(>2.0)→ 插入中间点 + // 2. 微小偏差:其中一个值很小(<0.5)→ 修改下一点坐标,使其与上一点对齐 + + if (deltaX > 2.0 && deltaY > 2.0) + { + // 真正的斜线:插入中间点 + LogManager.Info($"[斜线处理] 检测到斜线,需要插入中间点 (deltaX={deltaX:F2}, deltaY={deltaY:F2})"); + + int intermediateIndex = points.Count > 0 ? points.Count : 1; + var intermediatePoint = new PathPoint( + new Point3D( + nextPoint.Position.X, // 使用新点的X + currentPoint.Position.Y, // 保持上一个点的Y + currentPoint.Position.Z // 保持吊装高度 + ), + $"路径点{intermediateIndex}", + PathPointType.WayPoint); + intermediatePoint.Direction = HoistingPointDirection.Longitudinal; // 纵向移动 + + int insertPosition = startIndex + 1; + points.Insert(insertPosition, intermediatePoint); + + // 更新所有点的索引 + for (int i = 0; i < points.Count; i++) + { + points[i].Index = i; + } + + LogManager.Info($"[斜线处理] 已插入中间点: {intermediatePoint.Name}, 位置: ({intermediatePoint.Position.X:F2}, {intermediatePoint.Position.Y:F2}, {intermediatePoint.Position.Z:F2}) - 方向: 纵向"); + LogManager.Info($"[斜线处理] 插入位置: 索引 {insertPosition}, 当前路径点总数: {points.Count}"); + + return true; + } + else if (deltaX < 0.5 && deltaY > 0.5) + { + // X方向微小偏差,Y方向移动:修改下一点坐标,保持X与上一点对齐(垂直线) + LogManager.Info($"[斜线处理] 检测到X方向微小偏差 (deltaX={deltaX:F2}, deltaY={deltaY:F2}),修正下一点坐标使其垂直"); + + nextPoint.Position = new Point3D( + currentPoint.Position.X, // 保持上一个点的X + nextPoint.Position.Y, // 保持新点的Y + nextPoint.Position.Z); // 保持新点的Z + + LogManager.Info($"[斜线处理] 已修正下一点 {nextPoint.Name} 坐标: ({nextPoint.Position.X:F2}, {nextPoint.Position.Y:F2}, {nextPoint.Position.Z:F2})"); + return true; + } + else if (deltaY < 0.5 && deltaX > 0.5) + { + // Y方向微小偏差,X方向移动:修改下一点坐标,保持Y与上一点对齐(水平线) + LogManager.Info($"[斜线处理] 检测到Y方向微小偏差 (deltaX={deltaX:F2}, deltaY={deltaY:F2}),修正下一点坐标使其水平"); + + nextPoint.Position = new Point3D( + nextPoint.Position.X, // 保持新点的X + currentPoint.Position.Y, // 保持上一个点的Y + nextPoint.Position.Z); // 保持新点的Z + + LogManager.Info($"[斜线处理] 已修正下一点 {nextPoint.Name} 坐标: ({nextPoint.Position.X:F2}, {nextPoint.Position.Y:F2}, {nextPoint.Position.Z:F2})"); + return true; + } + else + { + // 中等程度的偏差,插入中间点 + LogManager.Info($"[斜线处理] 检测到中等程度斜线,需要插入中间点 (deltaX={deltaX:F2}, deltaY={deltaY:F2})"); + + int intermediateIndex = points.Count > 0 ? points.Count : 1; + var intermediatePoint = new PathPoint( + new Point3D( + nextPoint.Position.X, // 使用新点的X + currentPoint.Position.Y, // 保持上一个点的Y + currentPoint.Position.Z // 保持吊装高度 + ), + $"路径点{intermediateIndex}", + PathPointType.WayPoint); + intermediatePoint.Direction = HoistingPointDirection.Longitudinal; // 纵向移动 + + int insertPosition = startIndex + 1; + points.Insert(insertPosition, intermediatePoint); + + // 更新所有点的索引 + for (int i = 0; i < points.Count; i++) + { + points[i].Index = i; + } + + LogManager.Info($"[斜线处理] 已插入中间点: {intermediatePoint.Name}, 位置: ({intermediatePoint.Position.X:F2}, {intermediatePoint.Position.Y:F2}, {intermediatePoint.Position.Z:F2}) - 方向: 纵向"); + LogManager.Info($"[斜线处理] 插入位置: 索引 {insertPosition}, 当前路径点总数: {points.Count}"); + + return true; + } + } + /// /// 优化直角转折路径点:出现斜线时插入点,在同一直线上时清除多余点 /// /// 要优化的路径 /// 是否进行了优化 - private bool OptimizeRightAnglePathPoints(PathRoute route) + public bool OptimizeRightAnglePathPoints(PathRoute route) { if (route == null || route.Points.Count < 2) { @@ -1908,79 +2031,96 @@ namespace NavisworksTransport bool hasChanges = false; var points = route.Points; double tolerance = 0.001; // 容差,用于判断是否在同一直线上 + double smallDeviation = 0.5; // 微小偏差阈值,用于修正坐标 + double minDistance = 1.0; // 最小距离阈值,小于此距离不删除点 - // 第一步:处理斜线,插入转折点 - for (int i = 0; i < points.Count - 1; i++) + // 第一步:处理斜线,插入转折点或修正坐标 + // 注意:由于可能插入点,需要从后往前遍历或使用while循环 + int i = 0; + while (i < points.Count - 1) { - var currentPoint = points[i]; - var nextPoint = points[i + 1]; - - // 判断是否为斜线(X和Y都不同) - bool isDiagonal = (Math.Abs(currentPoint.Position.X - nextPoint.Position.X) > tolerance && - Math.Abs(currentPoint.Position.Y - nextPoint.Position.Y) > tolerance); - - if (isDiagonal) + int originalCount = points.Count; + if (InsertIntermediatePointForDiagonal(points, i)) { - // 插入中间转折点 - Point3D intermediatePosition; - HoistingPointDirection direction; - - // 查找提升点的Z坐标作为吊装高度 - double aerialHeight = currentPoint.Position.Z; - for (int j = 0; j < points.Count; j++) + hasChanges = true; + // 如果插入了点,points.Count会增加 + // 新插入的点在位置i+1,继续检查从i开始 + if (points.Count > originalCount) { - if (points[j].Name == "提升点") - { - aerialHeight = points[j].Position.Z; - break; - } - } - - // 计算距离差 - double deltaX = Math.Abs(nextPoint.Position.X - currentPoint.Position.X); - double deltaY = Math.Abs(nextPoint.Position.Y - currentPoint.Position.Y); - - if (deltaX > deltaY) - { - // 纵向移动优先,先移动X - intermediatePosition = new Point3D( - nextPoint.Position.X, - currentPoint.Position.Y, - aerialHeight); - direction = HoistingPointDirection.Longitudinal; + // 插入了点,继续检查当前索引(因为插入点可能需要进一步优化) + LogManager.Debug($"[直角路径优化] 索引{i}处插入了点,继续检查"); } else { - // 横向移动优先,先移动Y - intermediatePosition = new Point3D( - currentPoint.Position.X, - nextPoint.Position.Y, - aerialHeight); - direction = HoistingPointDirection.Lateral; + // 只修改了坐标,继续下一个点 + i++; } - - // 创建中间路径点 - var intermediatePoint = new PathPoint( - intermediatePosition, - $"中间点_{i + 1}", - PathPointType.WayPoint); - - // 设置方向属性 - intermediatePoint.Direction = direction; - - // 插入到两点之间 - points.Insert(i + 1, intermediatePoint); - hasChanges = true; - - LogManager.Debug($"[直角路径优化] 在斜线处插入转折点 {i + 1}: ({intermediatePosition.X:F2}, {intermediatePosition.Y:F2}, {intermediatePosition.Z:F2})"); - - // 跳过新插入的点 + } + else + { i++; } } - // 第二步:清除在同一直线上的多余点 - for (int i = 1; i < points.Count - 1; i++) + // 第二步:处理微小转折(X或Y方向微小偏差) + for (i = 1; i < points.Count - 1; i++) + { + var prevPoint = points[i - 1]; + var currentPoint = points[i]; + var nextPoint = points[i + 1]; + + // 计算两个方向的偏差 + double deltaX1 = Math.Abs(currentPoint.Position.X - prevPoint.Position.X); + double deltaY1 = Math.Abs(currentPoint.Position.Y - prevPoint.Position.Y); + double deltaX2 = Math.Abs(nextPoint.Position.X - currentPoint.Position.X); + double deltaY2 = Math.Abs(nextPoint.Position.Y - currentPoint.Position.Y); + + // 检测微小转折:前一段和后一段都有微小偏差,但方向不同 + // 例如:前一段X变化很小,Y变化较大;后一段X变化较大,Y变化很小 + bool hasSmallTurn = false; + + // 前一段垂直,后一段水平 + if (deltaX1 < smallDeviation && deltaY1 > smallDeviation && + deltaY2 < smallDeviation && deltaX2 > smallDeviation) + { + hasSmallTurn = true; + } + // 前一段水平,后一段垂直 + else if (deltaY1 < smallDeviation && deltaX1 > smallDeviation && + deltaX2 < smallDeviation && deltaY2 > smallDeviation) + { + hasSmallTurn = true; + } + + if (hasSmallTurn && currentPoint.Type == PathPointType.WayPoint) + { + // 修正转折点坐标,使其完全垂直 + if (deltaX1 < smallDeviation) + { + // 前一段垂直:调整转折点X与上一点对齐 + currentPoint.Position = new Point3D( + prevPoint.Position.X, + currentPoint.Position.Y, + currentPoint.Position.Z); + LogManager.Debug($"[直角路径优化] 修正微小转折点 {i} X坐标: ({currentPoint.Position.X:F2}, {currentPoint.Position.Y:F2}, {currentPoint.Position.Z:F2})"); + hasChanges = true; + } + else + { + // 前一段水平:调整转折点Y与上一点对齐 + currentPoint.Position = new Point3D( + currentPoint.Position.X, + prevPoint.Position.Y, + currentPoint.Position.Z); + LogManager.Debug($"[直角路径优化] 修正微小转折点 {i} Y坐标: ({currentPoint.Position.X:F2}, {currentPoint.Position.Y:F2}, {currentPoint.Position.Z:F2})"); + hasChanges = true; + } + } + } + + // 第三步:清除在同一直线上的多余点 + i = 1; + while (i < points.Count - 1) { var prevPoint = points[i - 1]; var currentPoint = points[i]; @@ -1989,12 +2129,14 @@ namespace NavisworksTransport // 只删除普通的WayPoint,不删除起点、终点、起吊点、提升点、下降点等特殊点 if (currentPoint.Type != PathPointType.WayPoint) { + i++; continue; } // 额外检查:不删除提升点和下降点(通过名称识别) if (currentPoint.Name == "提升点" || currentPoint.Name == "下降点") { + i++; continue; } @@ -2006,16 +2148,29 @@ namespace NavisworksTransport bool isCollinear = sameX || sameY; + // 额外检查:中间点到前后两点的距离都大于最小距离 if (isCollinear) { - // 删除中间点 - points.RemoveAt(i); - hasChanges = true; - LogManager.Debug($"[直角路径优化] 删除共线的多余点 {i}: ({currentPoint.Position.X:F2}, {currentPoint.Position.Y:F2}, {currentPoint.Position.Z:F2})"); + double distToPrev = GeometryHelper.CalculatePointDistance(currentPoint.Position, prevPoint.Position); + double distToNext = GeometryHelper.CalculatePointDistance(currentPoint.Position, nextPoint.Position); - // 调整索引,因为删除了一个点 - i--; + if (distToPrev > minDistance || distToNext > minDistance) + { + // 删除中间点 + points.RemoveAt(i); + hasChanges = true; + LogManager.Debug($"[直角路径优化] 删除共线的多余点 {i}: ({currentPoint.Position.X:F2}, {currentPoint.Position.Y:F2}, {currentPoint.Position.Z:F2})"); + + // 不调整索引,因为删除了一个点,新位置的点会在下一次循环被检查 + continue; + } + else + { + LogManager.Debug($"[直角路径优化] 跳过距离过近的共线点 {i}: ({currentPoint.Position.X:F2}, {currentPoint.Position.Y:F2}, {currentPoint.Position.Z:F2})"); + } } + + i++; } if (hasChanges) @@ -2045,19 +2200,16 @@ namespace NavisworksTransport return false; } - // 更新路径点位置 - var pointToUpdate = CurrentRoute.Points[_editingPointIndex]; - pointToUpdate.Position = _editingPreviewPoint.Position; - - // 吊装路径:自动更新关联点 - UpdateAerialPathRelatedPoints(CurrentRoute, _editingPointIndex); - - // 吊装路径:优化路径点(处理斜线和清除多余点) + // 吊装路径:调用专用方法处理 if (CurrentRoute.PathType == PathType.Hoisting) { - OptimizeRightAnglePathPoints(CurrentRoute); + return UpdateHoistingPathPointPosition(); } + // 更新路径点位置(非吊装路径) + var pointToUpdate = CurrentRoute.Points[_editingPointIndex]; + pointToUpdate.Position = _editingPreviewPoint.Position; + // 核心修复:调用统一更新函数 CurrentRoute.RecalculateAndSaveRoute($"修改路径点 {pointToUpdate.Name} 位置"); @@ -2102,6 +2254,99 @@ namespace NavisworksTransport } } + /// + /// 更新吊装路径点位置(专用方法) + /// + /// + /// 智能处理吊装路径点的坐标更新: + /// - 空中路径点(提升点、下降点、中间路径点):只更新XY坐标,保留原有Z坐标(吊装高度) + /// - 地面路径点(起吊点、落地点):更新完整XYZ坐标 + /// + /// 是否成功更新 + private bool UpdateHoistingPathPointPosition() + { + try + { + if (PathEditState != PathEditState.EditingPoint || + _editingPointIndex == -1 || + _editingPreviewPoint == null || + CurrentRoute == null) + { + RaiseErrorOccurred("当前不在修改路径点状态或没有预览点"); + return false; + } + + // 更新路径点位置(吊装路径:智能处理Z坐标) + var pointToUpdate = CurrentRoute.Points[_editingPointIndex]; + + // 空中路径点只更新XY坐标,保持原有吊装高度 + if (pointToUpdate.Name != "起吊点" && pointToUpdate.Name != "落地点") + { + double originalZ = pointToUpdate.Position.Z; + pointToUpdate.Position = new Point3D( + _editingPreviewPoint.Position.X, + _editingPreviewPoint.Position.Y, + originalZ // 保留原有Z坐标(吊装高度) + ); + LogManager.Info($"[修改吊装路径点] 空中路径点 {pointToUpdate.Name},保留原有高度: {originalZ:F3}"); + } + else + { + // 起吊点/落地点使用完整位置 + pointToUpdate.Position = _editingPreviewPoint.Position; + LogManager.Info($"[修改吊装路径点] 地面路径点 {pointToUpdate.Name},更新完整位置"); + } + + // 吊装路径:自动更新关联点 + UpdateAerialPathRelatedPoints(CurrentRoute, _editingPointIndex); + + // 吊装路径:优化路径点(处理斜线和清除多余点) + OptimizeRightAnglePathPoints(CurrentRoute); + + // 核心修复:调用统一更新函数 + CurrentRoute.RecalculateAndSaveRoute($"修改吊装路径点 {pointToUpdate.Name} 位置"); + + // 添加历史记录 + var historyEntry = new PathHistoryEntry( + CurrentRoute.Id, + PathHistoryOperationType.Edited, + CurrentRoute, + $"修改吊装路径点 {pointToUpdate.Name} 位置"); + _historyManager.AddHistoryEntry(historyEntry); + + // 清理修改预览可视化(会自动清除预览并重新渲染正常路径) + ClearEditingPreviewVisualization(); + + // 清理修改状态 + ClearEditingState(); + + // 切换回查看状态 + PathEditState = PathEditState.Viewing; + + // 停用ToolPlugin + DeactivateToolPlugin(); + + // 更新可视化 + DrawRouteVisualization(CurrentRoute, isAutoPath: false); + + // 立即保存到数据库 + SavePathToDatabase(CurrentRoute); + + // 触发路径点列表更新事件 + RaisePathPointsListUpdated(CurrentRoute, "路径点修改完成"); + + RaiseStatusChanged($"吊装路径点 {pointToUpdate.Name} 修改完成", PathPlanningStatusType.Success); + LogManager.Info($"吊装路径点修改完成: {pointToUpdate.Name}"); + + return true; + } + catch (Exception ex) + { + RaiseErrorOccurred($"确认修改吊装路径点失败: {ex.Message}"); + return false; + } + } + /// /// 取消修改路径点 /// @@ -2454,22 +2699,85 @@ namespace NavisworksTransport try { - // 创建正式的路径点 - var confirmPoint = new PathPoint + PathPoint confirmPoint; + + // 吊装路径:使用专门的空中路径点生成逻辑 + if (CurrentRoute.PathType == PathType.Hoisting) { - Name = GeneratePointName(_previewPoint.Type), - Position = _previewPoint.Position, - Type = _previewPoint.Type - }; - - // 根据保存的插入索引决定添加方式 - if (_previewInsertIndex >= 0 && _previewInsertIndex <= CurrentRoute.Points.Count) - { - CurrentRoute.InsertPoint(confirmPoint, _previewInsertIndex); + LogManager.Info($"[预览点-吊装路径] 开始创建空中路径点"); + + // 获取上一个路径点 + Point3D previousPoint; + int previousPointIndex; + + if (_previewInsertIndex >= 0 && _previewInsertIndex < CurrentRoute.Points.Count) + { + // 插入模式:上一个点是插入位置前的一个点 + previousPointIndex = _previewInsertIndex - 1; + previousPoint = CurrentRoute.Points[previousPointIndex].Position; + LogManager.Info($"[预览点-吊装路径] 插入模式,上一个点索引: {previousPointIndex}, 名称: {CurrentRoute.Points[previousPointIndex].Name}"); + } + else if (CurrentRoute.Points.Count > 0) + { + // 追加模式:上一个点是最后一个点 + previousPointIndex = CurrentRoute.Points.Count - 1; + previousPoint = CurrentRoute.Points[previousPointIndex].Position; + LogManager.Info($"[预览点-吊装路径] 追加模式,上一个点索引: {previousPointIndex}, 名称: {CurrentRoute.Points[previousPointIndex].Name}"); + } + else + { + LogManager.Error("[预览点-吊装路径] 没有上一个路径点"); + return null; + } + + // 获取吊装高度 + double liftHeightMeters = CurrentRoute.LiftHeightMeters > 0 ? CurrentRoute.LiftHeightMeters : 3.0; + + // 使用 AerialPathGenerator 生成空中路径点 + var generator = new AerialPathGenerator(); + confirmPoint = generator.GenerateSmartHoistingPoint( + previousPoint, + _previewPoint.Position, // 用户点击的地面位置 + liftHeightMeters, + CurrentRoute.Points.Count > 0 ? CurrentRoute.Points.Count : 1); + + LogManager.Info($"[预览点-吊装路径] 已生成空中路径点: {confirmPoint.Name}, 位置: ({confirmPoint.Position.X:F2}, {confirmPoint.Position.Y:F2}, {confirmPoint.Position.Z:F2})"); + + // 插入到正确位置 + if (_previewInsertIndex >= 0 && _previewInsertIndex <= CurrentRoute.Points.Count) + { + CurrentRoute.InsertPoint(confirmPoint, _previewInsertIndex); + LogManager.Info($"[预览点-吊装路径] 已插入到索引 {_previewInsertIndex}"); + } + else + { + CurrentRoute.AddPoint(confirmPoint); + LogManager.Info($"[预览点-吊装路径] 已追加到末尾"); + } + + // 调用路径优化方法处理斜线、微小转折和共线点 + OptimizeRightAnglePathPoints(CurrentRoute); + LogManager.Info($"[预览点-吊装路径] 路径优化完成,当前路径点数: {CurrentRoute.Points.Count}"); } else { - CurrentRoute.AddPoint(confirmPoint); + // 非吊装路径:创建普通路径点 + confirmPoint = new PathPoint + { + Name = GeneratePointName(_previewPoint.Type), + Position = _previewPoint.Position, + Type = _previewPoint.Type + }; + + // 根据保存的插入索引决定添加方式 + if (_previewInsertIndex >= 0 && _previewInsertIndex <= CurrentRoute.Points.Count) + { + CurrentRoute.InsertPoint(confirmPoint, _previewInsertIndex); + } + else + { + CurrentRoute.AddPoint(confirmPoint); + } } // 清除预览状态 @@ -3190,16 +3498,29 @@ namespace NavisworksTransport if (aerialPoint != null) { + // 保存上一个路径点的索引(用于插入中间点) + int previousPointIndex = CurrentRoute.Points.Count - 1; + var previousPathPoint = CurrentRoute.Points[previousPointIndex]; + LogManager.Info($"[吊装模式] 上一个路径点索引: {previousPointIndex}, 名称: {previousPathPoint.Name}, 位置: ({previousPathPoint.Position.X:F2}, {previousPathPoint.Position.Y:F2})"); + // 记录原始地面点击位置 _hoistingGroundIntermediatePoints.Add(clickedPoint); LogManager.Debug($"[吊装模式] 已记录地面点击点: ({clickedPoint.X:F2}, {clickedPoint.Y:F2}, {clickedPoint.Z:F2})"); - // 添加到当前路径 + // 添加空中路径点(临时) CurrentRoute.AddPoint(aerialPoint); - LogManager.Info($"[吊装模式] 已添加空中路径点: {aerialPoint.Name} ({aerialPoint.Position.X:F2}, {aerialPoint.Position.Y:F2}, {aerialPoint.Position.Z:F2}) - 方向: {aerialPoint.Direction}"); + LogManager.Info($"[吊装模式] 已添加空中路径点: {aerialPoint.Name}, 位置: ({aerialPoint.Position.X:F2}, {aerialPoint.Position.Y:F2}), 当前路径点数: {CurrentRoute.Points.Count}"); - // 优化路径点:处理斜线和清除多余点 + // 调用路径优化方法处理斜线、微小转折和共线点 OptimizeRightAnglePathPoints(CurrentRoute); + LogManager.Info($"[吊装模式] 路径优化完成,当前路径点数: {CurrentRoute.Points.Count}"); + for (int i = 0; i < CurrentRoute.Points.Count; i++) + { + var p = CurrentRoute.Points[i]; + LogManager.Info($" [{i}] {p.Name}: ({p.Position.X:F2}, {p.Position.Y:F2}, {p.Position.Z:F2})"); + } + + LogManager.Info($"[吊装模式] 已添加空中路径点: {aerialPoint.Name} ({aerialPoint.Position.X:F2}, {aerialPoint.Position.Y:F2}, {aerialPoint.Position.Z:F2}) - 方向: {aerialPoint.Direction}"); // 渲染路径 if (_renderPlugin != null) diff --git a/src/PathPlanning/AerialPathGenerator.cs b/src/PathPlanning/AerialPathGenerator.cs index accc248..e3fbb2a 100644 --- a/src/PathPlanning/AerialPathGenerator.cs +++ b/src/PathPlanning/AerialPathGenerator.cs @@ -106,50 +106,35 @@ namespace NavisworksTransport.PathPlanning if (liftHeightMeters <= 0) throw new ArgumentException("提升高度必须大于0", nameof(liftHeightMeters)); - double liftHeightModelUnits = UnitsConverter.ConvertFromMeters(liftHeightMeters); - // 计算两个方向的距离 double deltaX = Math.Abs(clickedGroundPoint.X - previousPoint.X); double deltaY = Math.Abs(clickedGroundPoint.Y - previousPoint.Y); - Point3D newPoint; - HoistingPointDirection direction; - string pointName; + // 直接使用地面点的完整XY值,不调整位置 + Point3D newPoint = new Point3D( + clickedGroundPoint.X, + clickedGroundPoint.Y, + previousPoint.Z); // 使用上一个路径点的Z坐标(保持吊装高度) - // 判断移动方向 + // 判断移动方向(仅用于记录,不影响位置) + HoistingPointDirection direction; if (Math.Abs(deltaX - deltaY) < DIRECTION_TOLERANCE) { // 距离相等,默认选择纵向 - newPoint = new Point3D( - clickedGroundPoint.X, - previousPoint.Y, - previousPoint.Z); // 使用上一个路径点的Z坐标(保持吊装高度) direction = HoistingPointDirection.Longitudinal; - pointName = $"路径点{pointIndex}"; } else if (deltaX > deltaY) { // 更偏向纵向移动(X轴) - // 保持Y坐标不变,使用点击的X坐标 - newPoint = new Point3D( - clickedGroundPoint.X, - previousPoint.Y, - previousPoint.Z); // 使用上一个路径点的Z坐标(保持吊装高度) direction = HoistingPointDirection.Longitudinal; - pointName = $"路径点{pointIndex}"; } else { // 更偏向横向移动(Y轴) - // 保持X坐标不变,使用点击的Y坐标 - newPoint = new Point3D( - previousPoint.X, - clickedGroundPoint.Y, - previousPoint.Z); // 使用上一个路径点的Z坐标(保持吊装高度) direction = HoistingPointDirection.Lateral; - pointName = $"路径点{pointIndex}"; } + string pointName = $"路径点{pointIndex}"; var pathPoint = new PathPoint(newPoint, pointName, PathPointType.WayPoint); pathPoint.Direction = direction; diff --git a/src/UI/WPF/ViewModels/PathEditingViewModel.cs b/src/UI/WPF/ViewModels/PathEditingViewModel.cs index abc2768..7d7abb5 100644 --- a/src/UI/WPF/ViewModels/PathEditingViewModel.cs +++ b/src/UI/WPF/ViewModels/PathEditingViewModel.cs @@ -1911,10 +1911,25 @@ namespace NavisworksTransport.UI.WPF.ViewModels LogManager.Info($"终点被删除,上一个路径点 {prevPoint.Name} 已设为新的终点"); } + // 吊装路径:禁止删除关键点(提升点、下降点) + if (coreRoute.PathType == PathType.Hoisting && + (corePoint.Name == "提升点" || corePoint.Name == "下降点")) + { + LogManager.Warning($"不能删除吊装路径的关键点: {corePoint.Name}"); + UpdateMainStatus($"❌ 无法删除:{corePoint.Name} 是吊装路径的关键点"); + return; + } + // 删除Core数据 coreRoute.Points.Remove(corePoint); LogManager.Info($"已从Core数据删除路径点: {corePoint.Name}"); + // 吊装路径:优化路径点(处理斜线和清除多余点) + if (coreRoute.PathType == PathType.Hoisting) + { + _pathPlanningManager?.OptimizeRightAnglePathPoints(coreRoute); + } + // 调用PathPlanningManager的3D删除方法 _pathPlanningManager.RemovePathPoint(corePoint);