From 131dfba7689de7ba2037cdf9be8cebd471defa5f Mon Sep 17 00:00:00 2001
From: tian <11429339@qq.com>
Date: Tue, 20 Jan 2026 20:58:22 +0800
Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E5=AE=8C=E5=96=84=E5=90=8A=E8=A3=85?=
=?UTF-8?q?=E8=B7=AF=E5=BE=84=E8=B7=AF=E5=BE=84=E7=82=B9=E7=BC=96=E8=BE=91?=
=?UTF-8?q?=E5=85=B3=E8=81=94=E9=80=BB=E8=BE=91?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/Core/PathPlanningManager.cs | 42 ++
src/UI/WPF/Models/PathRouteViewModel.cs | 34 +-
src/UI/WPF/ViewModels/PathEditingViewModel.cs | 366 ++++++++++++++----
src/UI/WPF/Views/AnimationControlView.xaml | 22 +-
src/UI/WPF/Views/LayerManagementView.xaml | 10 +-
src/UI/WPF/Views/LogisticsControlPanel.xaml | 4 +-
src/UI/WPF/Views/ModelSettingsView.xaml | 2 +-
src/UI/WPF/Views/PathEditingView.xaml | 44 ++-
8 files changed, 410 insertions(+), 114 deletions(-)
diff --git a/src/Core/PathPlanningManager.cs b/src/Core/PathPlanningManager.cs
index 78ffb2d..98fee70 100644
--- a/src/Core/PathPlanningManager.cs
+++ b/src/Core/PathPlanningManager.cs
@@ -1707,6 +1707,45 @@ namespace NavisworksTransport
}
}
+ ///
+ /// 更新吊装路径的关联点(通用方法)
+ ///
+ /// 路径
+ /// 修改的点的索引
+ private void UpdateAerialPathRelatedPoints(PathRoute route, int modifiedPointIndex)
+ {
+ if (route.PathType != PathType.Aerial ||
+ route.AerialSubType != AerialSubType.ThreeStepHoisting ||
+ route.Points.Count != 4)
+ {
+ return;
+ }
+
+ var points = route.Points;
+
+ // 修改起点(索引0):更新提升点(索引1)的X,Y坐标
+ if (modifiedPointIndex == 0)
+ {
+ var startPoint = points[0];
+ var liftPoint = points[1];
+ liftPoint.X = startPoint.X;
+ liftPoint.Y = startPoint.Y;
+ }
+ // 修改终点(索引3):更新平移终点(索引2)的X,Y坐标
+ else if (modifiedPointIndex == 3)
+ {
+ var endPoint = points[3];
+ var moveEndPoint = points[2];
+ moveEndPoint.X = endPoint.X;
+ moveEndPoint.Y = endPoint.Y;
+ }
+ // 修改起吊高度(通过起点或终点的Z坐标变化):更新提升点和平移终点的Z坐标
+ else if (modifiedPointIndex == 0 || modifiedPointIndex == 3)
+ {
+ // 这个逻辑在EditLiftHeightCommand中处理
+ }
+ }
+
///
/// 更新路径点位置(保存修改)
///
@@ -1728,6 +1767,9 @@ namespace NavisworksTransport
var pointToUpdate = CurrentRoute.Points[_editingPointIndex];
pointToUpdate.Position = _editingPreviewPoint.Position;
+ // 吊装路径:自动更新关联点
+ UpdateAerialPathRelatedPoints(CurrentRoute, _editingPointIndex);
+
// 添加历史记录
var historyEntry = new PathHistoryEntry(
CurrentRoute.Id,
diff --git a/src/UI/WPF/Models/PathRouteViewModel.cs b/src/UI/WPF/Models/PathRouteViewModel.cs
index 6247fa3..07c654c 100644
--- a/src/UI/WPF/Models/PathRouteViewModel.cs
+++ b/src/UI/WPF/Models/PathRouteViewModel.cs
@@ -19,6 +19,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
private double _z;
private string _name;
private NavisworksTransport.PathPointType _type; // 使用完全限定名
+ private int _index; // 路径点在列表中的索引
///
/// 路径点ID
@@ -112,14 +113,41 @@ namespace NavisworksTransport.UI.WPF.ViewModels
return "起点";
case NavisworksTransport.PathPointType.EndPoint:
return "终点";
- case NavisworksTransport.PathPointType.WayPoint:
- return "路径点";
default:
- return Type.ToString();
+ return "途经点";
}
}
}
+ ///
+ /// 路径点在列表中的索引
+ ///
+ public int Index
+ {
+ get => _index;
+ set => SetProperty(ref _index, value);
+ }
+
+ ///
+ /// 是否可以修改路径点(通过3D视图点击)
+ ///
+ public bool CanModifyPoint { get; set; } = true;
+
+ ///
+ /// 是否可以编辑坐标
+ ///
+ public bool CanEditCoordinates { get; set; } = true;
+
+ ///
+ /// 是否可以删除路径点
+ ///
+ public bool CanDelete { get; set; } = true;
+
+ ///
+ /// 是否显示起吊高度按钮(仅吊装路径的起点)
+ ///
+ public bool ShowLiftHeightButton { get; set; } = false;
+
///
/// 坐标字符串表示
///
diff --git a/src/UI/WPF/ViewModels/PathEditingViewModel.cs b/src/UI/WPF/ViewModels/PathEditingViewModel.cs
index 65e6d43..78b55e4 100644
--- a/src/UI/WPF/ViewModels/PathEditingViewModel.cs
+++ b/src/UI/WPF/ViewModels/PathEditingViewModel.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Drawing;
using System.Drawing.Imaging;
@@ -14,6 +15,7 @@ using NavisworksTransport.Core;
using NavisworksTransport.Core.Config;
using NavisworksTransport.Commands;
using NavisworksTransport.UI.WPF.Views;
+using NavisworksTransport.Utils;
namespace NavisworksTransport.UI.WPF.ViewModels
{
@@ -650,6 +652,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
public ICommand SelectStartPointCommand { get; private set; }
public ICommand SelectEndPointCommand { get; private set; }
public ICommand EditPointCoordinatesCommand { get; private set; }
+ public ICommand EditLiftHeightCommand { get; private set; }
public ICommand AutoPlanPathCommand { get; private set; }
public ICommand ClearAutoPathCommand { get; private set; }
public ICommand ImportPathCommand { get; private set; }
@@ -683,7 +686,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels
public bool CanExecuteSaveAsPath => SelectedPathRoute != null && SelectedPathRoute.Points.Count > 0;
public bool CanExecuteModifyPoint => SelectedPathPoint != null &&
- _pathPlanningManager?.PathEditState != PathEditState.EditingPoint;
+ _pathPlanningManager?.PathEditState != PathEditState.EditingPoint &&
+ SelectedPathPoint.CanModifyPoint;
public bool CanExecuteCancelModifyPoint => _pathPlanningManager?.PathEditState == PathEditState.EditingPoint;
#endregion
@@ -818,6 +822,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
SelectStartPointCommand = new RelayCommand(async () => await ExecuteSelectStartPointAsync());
SelectEndPointCommand = new RelayCommand(async () => await ExecuteSelectEndPointAsync());
EditPointCoordinatesCommand = new RelayCommand(ExecuteEditPointCoordinates);
+ EditLiftHeightCommand = new RelayCommand(ExecuteEditLiftHeight);
AutoPlanPathCommand = new RelayCommand(async () => await ExecuteAutoPlanPathAsync(), () => CanExecuteAutoPlanPath);
ClearAutoPathCommand = new RelayCommand(async () => await ExecuteClearAutoPathAsync());
ImportPathCommand = new RelayCommand(async () => await ExecuteImportPathAsync());
@@ -867,19 +872,11 @@ namespace NavisworksTransport.UI.WPF.ViewModels
IsActive = true
};
- // 转换路径点
- foreach (var corePoint in newRoute.Points)
+ // 使用统一的辅助方法创建路径点
+ var pathPoints = CreatePathPointViewModelsFromCoreRoute(newRoute);
+ foreach (var point in pathPoints)
{
- var wpfPoint = new PathPointViewModel
- {
- Id = corePoint.Id,
- Name = corePoint.Name,
- X = corePoint.X,
- Y = corePoint.Y,
- Z = corePoint.Z,
- Type = corePoint.Type
- };
- newPathViewModel.Points.Add(wpfPoint);
+ newPathViewModel.Points.Add(point);
}
// 添加到 UI 列表并选中
@@ -960,19 +957,11 @@ namespace NavisworksTransport.UI.WPF.ViewModels
PathType = PathType.Aerial
};
- // 转换路径点
- foreach (var corePoint in newRoute.Points)
+ // 使用统一的辅助方法创建路径点
+ var pathPoints = CreatePathPointViewModelsFromCoreRoute(newRoute);
+ foreach (var point in pathPoints)
{
- var wpfPoint = new PathPointViewModel
- {
- Id = corePoint.Id,
- Name = corePoint.Name,
- X = corePoint.X,
- Y = corePoint.Y,
- Z = corePoint.Z,
- Type = corePoint.Type
- };
- newPathViewModel.Points.Add(wpfPoint);
+ newPathViewModel.Points.Add(point);
}
// 添加到 UI 列表并选中
@@ -1043,7 +1032,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 设置路径类型为空中路径(吊装)
newRoute.PathType = PathType.Aerial;
newRoute.AerialSubType = AerialSubType.ThreeStepHoisting;
-
+
// 创建对应的 WPF ViewModel
var newPathViewModel = new PathRouteViewModel
{
@@ -1053,20 +1042,12 @@ namespace NavisworksTransport.UI.WPF.ViewModels
IsActive = true,
PathType = PathType.Aerial
};
-
- // 转换路径点
- foreach (var corePoint in newRoute.Points)
+
+ // 使用统一的辅助方法创建路径点
+ var pathPoints = CreatePathPointViewModelsFromCoreRoute(newRoute);
+ foreach (var point in pathPoints)
{
- var wpfPoint = new PathPointViewModel
- {
- Id = corePoint.Id,
- Name = corePoint.Name,
- X = corePoint.X,
- Y = corePoint.Y,
- Z = corePoint.Z,
- Type = corePoint.Type
- };
- newPathViewModel.Points.Add(wpfPoint);
+ newPathViewModel.Points.Add(point);
}
// 添加到 UI 列表并选中
@@ -1209,6 +1190,11 @@ namespace NavisworksTransport.UI.WPF.ViewModels
point.Y = dialog.Y;
point.Z = dialog.Z;
+ LogManager.Info($"[坐标编辑] 修改点: {point.Name}, 类型: {point.Type}, 索引: {point.Index}");
+
+ // 吊装路径:自动更新关联点(UI层)
+ UpdateAerialPathRelatedPoints(SelectedPathRoute, point.Index);
+
// 同步更新到底层数据模型
if (_pathPlanningManager != null)
{
@@ -1222,9 +1208,15 @@ namespace NavisworksTransport.UI.WPF.ViewModels
corePoint.Y = point.Y;
corePoint.Z = point.Z;
+ // 吊装路径:自动更新关联点(Core层)
+ UpdateAerialPathRelatedPointsCore(coreRoute, point.Index);
+
// 保存更改到数据库
_pathPlanningManager.UpdateRoute(coreRoute);
+ // 触发路径点列表更新事件,确保UI刷新
+ _pathPlanningManager.RaisePathPointsListUpdated(coreRoute, "编辑坐标");
+
// 刷新视图
UpdatePathVisualization();
@@ -1241,6 +1233,248 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
}
+ ///
+ /// 执行编辑起吊高度命令
+ ///
+ private void ExecuteEditLiftHeight(PathPointViewModel point)
+ {
+ if (point == null) return;
+ if (SelectedPathRoute == null) return;
+
+ // 确保是吊装路径
+ if (SelectedPathRoute.PathType != NavisworksTransport.PathType.Aerial ||
+ SelectedPathRoute.AerialSubType != NavisworksTransport.AerialSubType.ThreeStepHoisting)
+ {
+ LogManager.Warning("只有吊装路径才能编辑起吊高度");
+ return;
+ }
+
+ // 确保是起点
+ if (point.Type != NavisworksTransport.PathPointType.StartPoint)
+ {
+ LogManager.Warning("只有起点才能编辑起吊高度");
+ return;
+ }
+
+ try
+ {
+ // 获取路径点列表
+ var points = SelectedPathRoute.Points;
+ if (points.Count != 4)
+ {
+ LogManager.Warning($"吊装路径必须有4个路径点,当前有{points.Count}个");
+ return;
+ }
+
+ var startPoint = points[0];
+ var liftPoint = points[1];
+ var moveEndPoint = points[2];
+
+ // 计算当前起吊高度(米)
+ double currentHeightMeters = UnitsConverter.ConvertToMeters(liftPoint.Z - startPoint.Z);
+
+ // 显示对话框
+ var dialog = new AerialHeightDialog(currentHeightMeters);
+ if (dialog.ShowDialog() == true)
+ {
+ // 转换为模型单位
+ double newHeightModelUnits = UnitsConverter.ConvertFromMeters(dialog.LiftHeightMeters);
+
+ // 更新提升点和平移终点的Z坐标
+ liftPoint.Z = startPoint.Z + newHeightModelUnits;
+ moveEndPoint.Z = startPoint.Z + newHeightModelUnits;
+
+ // 同步更新到底层数据模型
+ if (_pathPlanningManager != null)
+ {
+ var coreRoute = _pathPlanningManager.Routes.FirstOrDefault(r => r.Id == SelectedPathRoute.Id);
+ if (coreRoute != null)
+ {
+ var coreLiftPoint = coreRoute.Points.FirstOrDefault(p => p.Id == liftPoint.Id);
+ var coreMoveEndPoint = coreRoute.Points.FirstOrDefault(p => p.Id == moveEndPoint.Id);
+
+ if (coreLiftPoint != null)
+ {
+ coreLiftPoint.Z = liftPoint.Z;
+ }
+ if (coreMoveEndPoint != null)
+ {
+ coreMoveEndPoint.Z = moveEndPoint.Z;
+ }
+
+ // 更新路径的提升高度
+ coreRoute.LiftHeightMeters = dialog.LiftHeightMeters;
+
+ // 保存更改到数据库
+ _pathPlanningManager.UpdateRoute(coreRoute);
+
+ // 刷新视图
+ UpdatePathVisualization();
+
+ LogManager.Info($"已更新吊装路径起吊高度为 {dialog.LiftHeightMeters:F2}米");
+ }
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error($"编辑起吊高度对话框操作失败: {ex.Message}", ex);
+ System.Windows.MessageBox.Show($"无法打开编辑对话框: {ex.Message}", "错误", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
+ }
+ }
+
+ ///
+ /// 设置吊装路径路径点的属性(CanModifyPoint、CanEditCoordinates、CanDelete、ShowLiftHeightButton)
+ ///
+ private void SetAerialPathPointProperties(PathPointViewModel point, int index, int totalCount)
+ {
+ if (point == null) return;
+
+ point.Index = index;
+
+ // 吊装路径:4个路径点
+ if (totalCount == 4)
+ {
+ switch (index)
+ {
+ case 0: // 起吊点
+ point.CanModifyPoint = true;
+ point.CanEditCoordinates = true;
+ point.CanDelete = false;
+ point.ShowLiftHeightButton = true;
+ break;
+ case 1: // 提升点
+ point.CanModifyPoint = false;
+ point.CanEditCoordinates = false;
+ point.CanDelete = false;
+ point.ShowLiftHeightButton = false;
+ break;
+ case 2: // 平移终点
+ point.CanModifyPoint = false;
+ point.CanEditCoordinates = false;
+ point.CanDelete = false;
+ point.ShowLiftHeightButton = false;
+ break;
+ case 3: // 下降点
+ point.CanModifyPoint = true;
+ point.CanEditCoordinates = true;
+ point.CanDelete = false;
+ point.ShowLiftHeightButton = false;
+ break;
+ }
+ }
+ else
+ {
+ // 非标准吊装路径,使用默认值
+ point.CanModifyPoint = true;
+ point.CanEditCoordinates = true;
+ point.CanDelete = true;
+ point.ShowLiftHeightButton = false;
+ }
+ }
+
+ ///
+ /// 从Core路径创建PathPointViewModel列表(统一处理吊装路径属性)
+ ///
+ private List CreatePathPointViewModelsFromCoreRoute(PathRoute coreRoute)
+ {
+ var points = new List();
+
+ foreach (var corePoint in coreRoute.Points)
+ {
+ var wpfPoint = new PathPointViewModel
+ {
+ Id = corePoint.Id,
+ Name = corePoint.Name,
+ X = corePoint.X,
+ Y = corePoint.Y,
+ Z = corePoint.Z,
+ Type = corePoint.Type
+ };
+ points.Add(wpfPoint);
+ }
+
+ // 设置吊装路径路径点属性
+ if (coreRoute.PathType == NavisworksTransport.PathType.Aerial &&
+ coreRoute.AerialSubType == NavisworksTransport.AerialSubType.ThreeStepHoisting)
+ {
+ for (int i = 0; i < points.Count; i++)
+ {
+ SetAerialPathPointProperties(points[i], i, points.Count);
+ }
+ }
+
+ return points;
+ }
+
+ ///
+ /// 更新吊装路径的关联点(UI层)
+ ///
+ /// 路径
+ /// 修改的点的索引
+ private void UpdateAerialPathRelatedPoints(PathRouteViewModel pathRoute, int modifiedPointIndex)
+ {
+ if (pathRoute.PathType != NavisworksTransport.PathType.Aerial ||
+ pathRoute.AerialSubType != NavisworksTransport.AerialSubType.ThreeStepHoisting ||
+ pathRoute.Points.Count != 4)
+ {
+ return;
+ }
+
+ var points = pathRoute.Points;
+
+ // 修改起点(索引0):更新提升点(索引1)的X,Y坐标
+ if (modifiedPointIndex == 0)
+ {
+ var startPoint = points[0];
+ var liftPoint = points[1];
+ liftPoint.X = startPoint.X;
+ liftPoint.Y = startPoint.Y;
+ }
+ // 修改终点(索引3):更新平移终点(索引2)的X,Y坐标
+ else if (modifiedPointIndex == 3)
+ {
+ var endPoint = points[3];
+ var moveEndPoint = points[2];
+ moveEndPoint.X = endPoint.X;
+ moveEndPoint.Y = endPoint.Y;
+ }
+ }
+
+ ///
+ /// 更新吊装路径的关联点(Core层)
+ ///
+ /// Core路径
+ /// 修改的点的索引
+ private void UpdateAerialPathRelatedPointsCore(PathRoute coreRoute, int modifiedPointIndex)
+ {
+ if (coreRoute.PathType != NavisworksTransport.PathType.Aerial ||
+ coreRoute.AerialSubType != NavisworksTransport.AerialSubType.ThreeStepHoisting ||
+ coreRoute.Points.Count != 4)
+ {
+ return;
+ }
+
+ var points = coreRoute.Points;
+
+ // 修改起点(索引0):更新提升点(索引1)的X,Y坐标
+ if (modifiedPointIndex == 0)
+ {
+ var startPoint = points[0];
+ var liftPoint = points[1];
+ liftPoint.X = startPoint.X;
+ liftPoint.Y = startPoint.Y;
+ }
+ // 修改终点(索引3):更新平移终点(索引2)的X,Y坐标
+ else if (modifiedPointIndex == 3)
+ {
+ var endPoint = points[3];
+ var moveEndPoint = points[2];
+ moveEndPoint.X = endPoint.X;
+ moveEndPoint.Y = endPoint.Y;
+ }
+ }
+
#endregion
#region 自动路径规划命令
@@ -2309,19 +2543,11 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 设置时间信息
pathViewModel.SetTimeInfo(coreRoute.CreatedTime, coreRoute.LastModified);
- // 转换路径点
- foreach (var corePoint in coreRoute.Points)
+ // 使用统一的辅助方法创建路径点
+ var pathPoints = CreatePathPointViewModelsFromCoreRoute(coreRoute);
+ foreach (var point in pathPoints)
{
- var wpfPoint = new PathPointViewModel
- {
- Id = corePoint.Id,
- Name = corePoint.Name,
- X = corePoint.X,
- Y = corePoint.Y,
- Z = corePoint.Z,
- Type = corePoint.Type
- };
- pathViewModel.Points.Add(wpfPoint);
+ pathViewModel.Points.Add(point);
}
PathRoutes.Add(pathViewModel);
@@ -3042,8 +3268,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 同步路径点数据
pathViewModel.Points.Clear();
- foreach (var point in e.Route.Points)
+ for (int i = 0; i < e.Route.Points.Count; i++)
{
+ var point = e.Route.Points[i];
var pointViewModel = new PathPointViewModel
{
Id = point.Id,
@@ -3051,7 +3278,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels
X = point.Position.X,
Y = point.Position.Y,
Z = point.Position.Z,
- Type = point.Type
+ Type = point.Type,
+ Index = i
};
pathViewModel.Points.Add(pointViewModel);
}
@@ -3219,19 +3447,11 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 设置时间信息
autoPathViewModel.SetTimeInfo(e.Route.CreatedTime, e.Route.LastModified);
- // 转换路径点
- foreach (var corePoint in e.Route.Points)
+ // 使用统一的辅助方法创建路径点
+ var pathPoints = CreatePathPointViewModelsFromCoreRoute(e.Route);
+ foreach (var point in pathPoints)
{
- var wpfPoint = new PathPointViewModel
- {
- Id = corePoint.Id,
- Name = corePoint.Name,
- X = corePoint.X,
- Y = corePoint.Y,
- Z = corePoint.Z,
- Type = corePoint.Type
- };
- autoPathViewModel.Points.Add(wpfPoint);
+ autoPathViewModel.Points.Add(point);
}
LogManager.Info($"*** 已创建PathRouteViewModel,包含 {autoPathViewModel.Points.Count} 个点 ***");
@@ -3332,19 +3552,11 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 设置时间信息
dbPathViewModel.SetTimeInfo(coreRoute.CreatedTime, coreRoute.LastModified);
- // 转换路径点
- foreach (var corePoint in coreRoute.Points)
+ // 使用统一的辅助方法创建路径点
+ var pathPoints = CreatePathPointViewModelsFromCoreRoute(coreRoute);
+ foreach (var point in pathPoints)
{
- var wpfPoint = new PathPointViewModel
- {
- Id = corePoint.Id,
- Name = corePoint.Name,
- X = corePoint.X,
- Y = corePoint.Y,
- Z = corePoint.Z,
- Type = corePoint.Type
- };
- dbPathViewModel.Points.Add(wpfPoint);
+ dbPathViewModel.Points.Add(point);
}
LogManager.Info($"*** 已创建PathRouteViewModel(数据库路径),包含 {dbPathViewModel.Points.Count} 个点 ***");
diff --git a/src/UI/WPF/Views/AnimationControlView.xaml b/src/UI/WPF/Views/AnimationControlView.xaml
index 4fe929a..842143e 100644
--- a/src/UI/WPF/Views/AnimationControlView.xaml
+++ b/src/UI/WPF/Views/AnimationControlView.xaml
@@ -26,7 +26,7 @@ NavisworksTransport 检测动画页签视图 - 采用与类别设置和分层管
-
+