diff --git a/src/Core/PathPlanningManager.cs b/src/Core/PathPlanningManager.cs
index a4895b5..d14dd7f 100644
--- a/src/Core/PathPlanningManager.cs
+++ b/src/Core/PathPlanningManager.cs
@@ -2255,7 +2255,158 @@ namespace NavisworksTransport
}
///
- /// 更新吊装路径点位置(专用方法)
+ /// 更新路径点位置(带约束的公共方法)
+ ///
+ ///
+ /// 根据路径类型智能处理坐标更新:
+ /// - 吊装路径:
+ /// - 空中路径点(提升点、下降点、中间路径点):只更新XY坐标,保留原有Z坐标(吊装高度)
+ /// - 地面路径点(起吊点、落地点):更新完整XYZ坐标
+ /// - 其他路径类型:更新完整XYZ坐标
+ ///
+ /// 路径
+ /// 路径点索引
+ /// 新位置
+ /// 是否成功更新
+ public bool UpdatePathPointWithConstraints(PathRoute route, int pointIndex, Point3D newPosition)
+ {
+ try
+ {
+ if (route == null || pointIndex < 0 || pointIndex >= route.Points.Count)
+ {
+ LogManager.Error($"UpdatePathPointWithConstraints: 无效的参数,route={route}, pointIndex={pointIndex}");
+ return false;
+ }
+
+ var pointToUpdate = route.Points[pointIndex];
+
+ // 吊装路径:智能处理Z坐标
+ if (route.PathType == PathType.Hoisting)
+ {
+ bool isLiftPoint = pointToUpdate.Name == "提升点";
+ bool isDescendPoint = pointToUpdate.Name == "下降点";
+ bool isStartPoint = pointToUpdate.Name == "起吊点";
+ bool isEndPoint = pointToUpdate.Name == "落地点";
+
+ // 🔥 新功能:允许修改提升点和下降点的Z坐标来调整吊装高度
+ if (isLiftPoint || isDescendPoint)
+ {
+ // 修改提升点或下降点的Z坐标,同步更新所有空中路径点的Z坐标
+ double newHoistingHeight = newPosition.Z;
+ double originalZ = pointToUpdate.Position.Z;
+ double heightDelta = newHoistingHeight - originalZ;
+
+ // 更新当前点的XY和Z坐标
+ pointToUpdate.Position = new Point3D(
+ newPosition.X,
+ newPosition.Y,
+ newHoistingHeight
+ );
+
+ // 同步更新所有空中路径点的Z坐标
+ foreach (var point in route.Points)
+ {
+ // 只更新空中路径点(提升点、下降点、中间路径点)
+ // 跳过当前正在修改的点,避免重复更新
+ if (point.Name != "起吊点" && point.Name != "落地点" && point != pointToUpdate)
+ {
+ point.Position = new Point3D(
+ point.Position.X,
+ point.Position.Y,
+ point.Position.Z + heightDelta
+ );
+ }
+ }
+
+ // 🔥 更新路径的提升高度属性(转换为米)
+ double hoistingHeightMeters = CalculateHoistingHeight(route);
+ route.LiftHeightMeters = hoistingHeightMeters;
+ LogManager.Info($"[更新路径点] 吊装路径 {pointToUpdate.Name},提升高度已调整为: {hoistingHeightMeters:F3}米");
+
+ // 使用路径的 LiftHeightMeters 属性显示提升高度
+ RaiseStatusChanged($"吊装高度: {route.LiftHeightMeters:F3}米", PathPlanningStatusType.Info);
+ }
+ // 空中路径点(非提升点、下降点):只更新XY坐标,保持原有吊装高度
+ else if (!isStartPoint && !isEndPoint)
+ {
+ double originalZ = pointToUpdate.Position.Z;
+ pointToUpdate.Position = new Point3D(
+ newPosition.X,
+ newPosition.Y,
+ originalZ // 保留原有Z坐标(吊装高度)
+ );
+ LogManager.Info($"[更新路径点] 吊装路径空中点 {pointToUpdate.Name},保留原有高度: {originalZ:F3}");
+ }
+ // 起吊点/落地点:更新完整位置
+ else
+ {
+ pointToUpdate.Position = newPosition;
+ LogManager.Info($"[更新路径点] 吊装路径地面点 {pointToUpdate.Name},更新完整位置");
+ }
+
+ // 吊装路径:自动更新关联点(仅当修改起吊点或落地点时)
+ // 注意:修改提升点/下降点时,已经在上面同步更新了所有空中路径点,不需要再次调用
+ if (isStartPoint || isEndPoint)
+ {
+ UpdateAerialPathRelatedPoints(route, pointIndex);
+ }
+
+ // 吊装路径:优化路径点(处理斜线和清除多余点)
+ OptimizeRightAnglePathPoints(route);
+ }
+ else
+ {
+ // 其他路径类型:更新完整位置
+ pointToUpdate.Position = newPosition;
+ LogManager.Info($"[更新路径点] {route.PathType}路径点 {pointToUpdate.Name},更新完整位置");
+ }
+
+ // 调用统一更新函数
+ route.RecalculateAndSaveRoute($"更新路径点 {pointToUpdate.Name} 位置");
+
+ // 保存到数据库
+ SavePathToDatabase(route);
+
+ // 触发路径点列表更新事件
+ RaisePathPointsListUpdated(route, "路径点更新完成");
+
+ LogManager.Info($"路径点更新完成: {pointToUpdate.Name}");
+ return true;
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error($"UpdatePathPointWithConstraints 失败: {ex.Message}");
+ return false;
+ }
+ }
+
+ ///
+ /// 计算吊装路径的提升高度
+ ///
+ /// 吊装路径
+ /// 提升高度(从起吊点到提升点的高度差)
+ private double CalculateHoistingHeight(PathRoute route)
+ {
+ if (route == null || route.PathType != PathType.Hoisting || route.Points.Count < 2)
+ {
+ return 0.0;
+ }
+
+ // 找到起吊点和提升点
+ var startPoint = route.Points.FirstOrDefault(p => p.Name == "起吊点");
+ var liftPoint = route.Points.FirstOrDefault(p => p.Name == "提升点");
+
+ if (startPoint == null || liftPoint == null)
+ {
+ return 0.0;
+ }
+
+ // 计算高度差(提升点Z - 起吊点Z)
+ return liftPoint.Position.Z - startPoint.Position.Z;
+ }
+
+ ///
+ /// 更新吊装路径点位置(专用方法,用于3D修改流程)
///
///
/// 智能处理吊装路径点的坐标更新:
@@ -2276,69 +2427,39 @@ namespace NavisworksTransport
return false;
}
- // 更新路径点位置(吊装路径:智能处理Z坐标)
- var pointToUpdate = CurrentRoute.Points[_editingPointIndex];
-
- // 空中路径点只更新XY坐标,保持原有吊装高度
- if (pointToUpdate.Name != "起吊点" && pointToUpdate.Name != "落地点")
+ // 调用公共方法处理
+ bool success = UpdatePathPointWithConstraints(CurrentRoute, _editingPointIndex, _editingPreviewPoint.Position);
+
+ if (success)
{
- 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},更新完整位置");
+ // 添加历史记录
+ var pointToUpdate = CurrentRoute.Points[_editingPointIndex];
+ 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);
+
+ RaiseStatusChanged($"吊装路径点 {pointToUpdate.Name} 修改完成", PathPlanningStatusType.Success);
}
- // 吊装路径:自动更新关联点
- 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;
+ return success;
}
catch (Exception ex)
{
diff --git a/src/UI/WPF/ViewModels/PathEditingViewModel.cs b/src/UI/WPF/ViewModels/PathEditingViewModel.cs
index 7d7abb5..46608e1 100644
--- a/src/UI/WPF/ViewModels/PathEditingViewModel.cs
+++ b/src/UI/WPF/ViewModels/PathEditingViewModel.cs
@@ -1180,48 +1180,51 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 创建并显示对话框
// 注意:在Navisworks插件的ViewModel中,不设置Owner
// 因为Application.Current.MainWindow在Navisworks环境中不可用
- var dialog = new EditCoordinatesWindow(point.X, point.Y, point.Z);
-
+ var dialog = new EditCoordinatesWindow(point.X, point.Y, point.Z, point.Name, point.Type.ToString());
if (dialog.ShowDialog() == true)
{
- // 更新ViewModel中的坐标
- point.X = dialog.X;
- point.Y = dialog.Y;
- point.Z = dialog.Z;
-
LogManager.Info($"[坐标编辑] 修改点: {point.Name}, 类型: {point.Type}, 索引: {point.Index}");
- // 吊装路径:自动更新关联点(UI层)
- UpdateAerialPathRelatedPoints(SelectedPathRoute, point.Index);
-
// 同步更新到底层数据模型
if (_pathPlanningManager != null)
{
var coreRoute = _pathPlanningManager.Routes.FirstOrDefault(r => r.Id == SelectedPathRoute.Id);
if (coreRoute != null)
{
- var corePoint = coreRoute.Points.FirstOrDefault(p => p.Id == point.Id);
- if (corePoint != null)
+ // 验证索引是否有效
+ if (point.Index < 0 || point.Index >= coreRoute.Points.Count)
{
- corePoint.X = point.X;
- corePoint.Y = point.Y;
- corePoint.Z = point.Z;
+ LogManager.Error($"[坐标编辑] 索引错误: point.Index={point.Index}, coreRoute.Points.Count={coreRoute.Points.Count}");
+ System.Windows.MessageBox.Show($"路径点索引错误", "错误", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
+ return;
+ }
- // 吊装路径:自动更新关联点(Core层)
- UpdateAerialPathRelatedPointsCore(coreRoute, point.Index);
+ var corePoint = coreRoute.Points[point.Index];
+ LogManager.Info($"[坐标编辑] Core路径点: {corePoint.Name}, 索引: {point.Index}, 位置: ({corePoint.Position.X:F3}, {corePoint.Position.Y:F3}, {corePoint.Position.Z:F3})");
- // 保存更改到数据库
- _pathPlanningManager.UpdateRoute(coreRoute);
+ // 使用公共方法更新路径点(自动处理吊装路径约束)
+ var newPosition = new Point3D(dialog.X, dialog.Y, dialog.Z);
+ bool success = _pathPlanningManager.UpdatePathPointWithConstraints(coreRoute, point.Index, newPosition);
- // 触发路径点列表更新事件,确保UI刷新
- _pathPlanningManager.RaisePathPointsListUpdated(coreRoute, "编辑坐标");
+ if (success)
+ {
+ // 更新ViewModel中的坐标(从Core数据同步)
+ corePoint = coreRoute.Points[point.Index];
+ point.X = corePoint.Position.X;
+ point.Y = corePoint.Position.Y;
+ point.Z = corePoint.Position.Z;
// 刷新视图
UpdatePathVisualization();
LogManager.Info($"已更新路径点 {point.Name} 的坐标为 ({point.X:F3}, {point.Y:F3}, {point.Z:F3})");
}
+ else
+ {
+ LogManager.Error($"更新路径点失败: {point.Name}");
+ System.Windows.MessageBox.Show($"更新路径点失败", "错误", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
+ }
}
}
}
@@ -1240,8 +1243,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
var points = new List();
- foreach (var corePoint in coreRoute.Points)
+ for (int i = 0; i < coreRoute.Points.Count; i++)
{
+ var corePoint = coreRoute.Points[i];
var wpfPoint = new PathPointViewModel
{
Id = corePoint.Id,
@@ -1249,7 +1253,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels
X = corePoint.X,
Y = corePoint.Y,
Z = corePoint.Z,
- Type = corePoint.Type
+ Type = corePoint.Type,
+ Index = i // 🔥 设置正确的索引
};
points.Add(wpfPoint);
}
@@ -1891,24 +1896,23 @@ namespace NavisworksTransport.UI.WPF.ViewModels
await _uiStateManager.ExecuteUIUpdateAsync(() =>
{
- // 4. 起点和终点的特殊处理逻辑
+ // 4. 禁止删除起点和终点
if (corePoint != null)
{
int pointIndex = coreRoute.Points.IndexOf(corePoint);
- if (corePoint.Type == PathPointType.StartPoint && coreRoute.Points.Count > 1)
+ if (corePoint.Type == PathPointType.StartPoint)
{
- // 删除起点:下一个点变为起点
- var nextPoint = coreRoute.Points[pointIndex + 1];
- nextPoint.Type = PathPointType.StartPoint;
- LogManager.Info($"起点被删除,下一个路径点 {nextPoint.Name} 已设为新的起点");
+ LogManager.Warning($"不能删除路径的起点");
+ UpdateMainStatus($"❌ 无法删除:{corePoint.Name} 是路径的起点");
+ return;
}
- else if (corePoint.Type == PathPointType.EndPoint && coreRoute.Points.Count > 1)
+
+ if (corePoint.Type == PathPointType.EndPoint)
{
- // 删除终点:上一个点变为终点
- var prevPoint = coreRoute.Points[pointIndex - 1];
- prevPoint.Type = PathPointType.EndPoint;
- LogManager.Info($"终点被删除,上一个路径点 {prevPoint.Name} 已设为新的终点");
+ LogManager.Warning($"不能删除路径的终点");
+ UpdateMainStatus($"❌ 无法删除:{corePoint.Name} 是路径的终点");
+ return;
}
// 吊装路径:禁止删除关键点(提升点、下降点)
@@ -3160,6 +3164,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
Index = i
};
pathViewModel.Points.Add(pointViewModel);
+ LogManager.Debug($"[路径点列表更新] 索引{i}: {point.Name}, Id={point.Id}, 位置=({point.Position.X:F2}, {point.Position.Y:F2}, {point.Position.Z:F2})");
}
LogManager.Info($"已更新路径点列表,当前点数: {pathViewModel.Points.Count}");
diff --git a/src/UI/WPF/Views/EditCoordinatesWindow.xaml b/src/UI/WPF/Views/EditCoordinatesWindow.xaml
index 7d3afc6..78c5f77 100644
--- a/src/UI/WPF/Views/EditCoordinatesWindow.xaml
+++ b/src/UI/WPF/Views/EditCoordinatesWindow.xaml
@@ -1,7 +1,7 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/UI/WPF/Views/EditCoordinatesWindow.xaml.cs b/src/UI/WPF/Views/EditCoordinatesWindow.xaml.cs
index 8dbc25c..cf02a70 100644
--- a/src/UI/WPF/Views/EditCoordinatesWindow.xaml.cs
+++ b/src/UI/WPF/Views/EditCoordinatesWindow.xaml.cs
@@ -9,8 +9,10 @@ namespace NavisworksTransport.UI.WPF.Views
public double X { get; set; }
public double Y { get; set; }
public double Z { get; set; }
+ public string PointName { get; set; }
+ public string PointType { get; set; }
- public EditCoordinatesWindow(double x, double y, double z)
+ public EditCoordinatesWindow(double x, double y, double z, string pointName = "", string pointType = "")
{
try
{
@@ -18,6 +20,8 @@ namespace NavisworksTransport.UI.WPF.Views
X = x;
Y = y;
Z = z;
+ PointName = pointName;
+ PointType = pointType;
DataContext = this;
}
catch (Exception ex)