diff --git a/.claude/settings.local.json b/.claude/settings.local.json index ad442a4..11c8d78 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -134,7 +134,8 @@ "Read(//c/Users/Tellme/apps/OpenSource/AStar-master/**)", "Bash(\"./compile.bat\")", "Bash(xcopy:*)", - "Read(//c/ProgramData/Autodesk/Navisworks Manage 2026/NavisworksTransport/logs/**)" + "Read(//c/ProgramData/Autodesk/Navisworks Manage 2026/NavisworksTransport/logs/**)", + "Bash(sed:*)" ], "deny": [], "additionalDirectories": [ diff --git a/doc/requirement/todo_features.md b/doc/requirement/todo_features.md index 147632d..6dfd5e4 100644 --- a/doc/requirement/todo_features.md +++ b/doc/requirement/todo_features.md @@ -2,6 +2,10 @@ ## 功能点 +### [2025/09/14] + +1. [x] (功能)增加两种路径连线方式:1、宽度路径,半透明,膨胀直径,10cm高立方体。2、和前面一样,高度为车高加安全距离 + ### [2025/09/12] 1. [x] (功能)给动画增加步进功能,同时提供反向功能(反向播放、反向步进) diff --git a/doc/working/2017/步进式动画方案.md b/doc/working/2017/步进式动画方案.md index dd01c49..b277b1d 100644 --- a/doc/working/2017/步进式动画方案.md +++ b/doc/working/2017/步进式动画方案.md @@ -378,4 +378,29 @@ - 正向播放 - 标准前进播放 - 下一帧 (→) - 精确单帧前进 - 快进10帧 (Shift+→) - 快速前进功能 - - 停止 (Esc) - 停止并重置动画 \ No newline at end of file + - 停止 (Esc) - 停止并重置动画 + + + 4. 优化性能的关键点 +使用事务批量更新:通过 Application.ActiveDocument.BeginTransaction 将多个构件的变换操作包裹起来,最后一次性提交 (transaction.Commit()),这比单独更新每个构件高效得多。 + +优先使用DispatcherTimer而非Idle事件:DispatcherTimer 在UI线程上按固定间隔触发,比依赖不确定的Idle事件更能保证更新的及时性。优先级设置为 DispatcherPriority.Render。 + +控制帧率:Interval 设置为约16ms(约60FPS)。如果场景复杂导致卡顿,可以适当增大此值(如33ms对应~30FPS)。WPF中也可以通过 Timeline.DesiredFrameRate 附加属性来调整动画的帧率。 + +减少不必要的重绘:只在所有变换更新后调用一次 Redraw。 + +硬件加速:确保在Navisworks的选项 (Options) -> 显示 (Display) 中启用硬件加速 (Hardware Acceleration) 和 WPF硬件加速 (WPF Hardware Acceleration)(如果可用)。 + +优化图形设置:在Navisworks的显示设置中,适当降低细节层次 (Level of Detail) 或禁用保证帧频 (Guarantee Frame Rate)(根据实际情况测试)可能有助于提高复杂模型的交互性能。 + +5. 调试提示 +如果动画仍然卡顿,首先尝试减少同时动画的构件数量。 + +在Navisworks的选项 -> 显示中,可以尝试调整图形模式 (Graphics Mode) 等设置来优化性能。 + +使用性能分析工具(如Visual Studio的诊断工具)检查代码中是否存在瓶颈。 + + +Navisworks设置: +1、【界面】-【选取】中,可以设置精度,从几何体、最低层次的对象、最高层级的唯一对象、最高层级的对象、图层、文件,默认是最低层次的对象。 \ No newline at end of file diff --git a/doc/working/vehicle_parameter_sync_fix.md b/doc/working/vehicle_parameter_sync_fix.md new file mode 100644 index 0000000..bc26913 --- /dev/null +++ b/doc/working/vehicle_parameter_sync_fix.md @@ -0,0 +1,118 @@ +# 车辆参数同步问题修复 + +## 问题描述 + +PathPointRenderPlugin.cs 中使用了硬编码的默认车辆参数 (2.0m × 1.5m × 2.0m),而用户在 PathEditingViewModel 中配置的参数 (1.0m × 1.0m × 2.0m) 没有被正确同步到渲染插件,导致车辆通行空间模式显示的尺寸不正确。 + +## 根本原因 + +1. **PathPointRenderPlugin.cs** 中有硬编码的默认车辆参数 +2. **PathEditingViewModel.cs** 的车辆参数属性setter只更新了UI,没有同步到渲染插件 +3. **SystemManagementViewModel** 在切换可视化模式时没有同步最新的车辆参数 +4. **PathPointRenderPlugin.cs** 中的 `SetVehicleParameters()` 方法从未被调用 + +## 修复方案 + +### 1. PathEditingViewModel.cs 修改 + +**修改内容:** +- 为所有车辆参数属性setter添加 `SyncVehicleParametersToRenderPlugin()` 调用 +- 添加 `SyncVehicleParametersToRenderPlugin()` 方法 +- 在 `UpdatePathVisualization()` 方法中添加参数同步 +- 在两个构造函数中添加初始化参数同步 + +**代码变化:** +```csharp +// 车辆参数setter现在会自动同步到渲染插件 +public double VehicleLength +{ + get => _vehicleLength; + set + { + if (SetProperty(ref _vehicleLength, value)) + { + SyncVehicleParametersToRenderPlugin(); + OnPropertyChanged(nameof(CanExecuteAutoPlanPath)); + } + } +} + +// 同步方法 +private void SyncVehicleParametersToRenderPlugin() +{ + try + { + if (PathPointRenderPlugin.Instance != null) + { + PathPointRenderPlugin.Instance.SetVehicleParameters( + VehicleLength, + VehicleWidth, + VehicleHeight, + SafetyMargin); + } + } + catch (Exception ex) + { + LogManager.Error($"[车辆参数同步] 同步车辆参数失败: {ex.Message}", ex); + } +} +``` + +### 2. SystemManagementViewModel.cs 修改 + +**修改内容:** +- 修改 `OnPathVisualizationModeChanged()` 方法,在切换到车辆通行空间模式时同步参数 +- 修改 `OnVehicleHeightModeChanged()` 方法,在高度模式变更时同步参数 +- 添加 `SyncVehicleParametersFromPathEditingViewModel()` 方法 +- 添加 `GetPathEditingViewModel()` 方法 + +**代码变化:** +```csharp +// 可视化模式切换时同步参数 +private void OnPathVisualizationModeChanged() +{ + // ... 现有逻辑 ... + + // 在切换到车辆通行空间模式时,同步车辆参数 + if (IsVehicleSpaceMode) + { + SyncVehicleParametersFromPathEditingViewModel(); + } +} +``` + +## 修复效果 + +1. **实时同步**:用户在路径编辑界面修改车辆参数时,参数会立即同步到渲染插件 +2. **模式切换同步**:在系统管理界面切换可视化模式时,会自动同步当前的车辆参数 +3. **初始化同步**:插件启动时会使用正确的用户配置参数,而不是硬编码默认值 +4. **多层保障**:提供了多种获取车辆参数的方式,确保同步的可靠性 + +## 测试步骤 + +1. **启动插件**:打开NavisworksTransport插件 +2. **检查默认参数**:验证车辆通行空间模式使用的是 1.0m × 1.0m × 2.0m 而不是 2.0m × 1.5m × 2.0m +3. **修改参数**:在路径编辑界面修改车辆参数 +4. **验证同步**:切换到车辆通行空间模式,确认显示的尺寸与设置的参数一致 +5. **模式切换测试**:在系统管理界面切换可视化模式,确认参数正确同步 + +## 技术细节 + +- **同步触发点**: + - PathEditingViewModel 属性setter变更时 + - UpdatePathVisualization() 调用时 + - SystemManagementViewModel 模式切换时 + - 插件初始化时 + +- **获取参数的优先级**: + 1. 从 PathEditingViewModel 获取用户配置的参数 + 2. 使用 PathEditingViewModel 的默认值 (1.0, 1.0, 2.0, 0.25) + 3. 避免使用 PathPointRenderPlugin 的硬编码默认值 + +- **线程安全**:所有同步操作都包含异常处理,确保不会影响主程序运行 + +## 编译状态 + +✅ 编译成功 - 所有修改已通过编译验证 + +修复完成时间:2025-09-14 \ No newline at end of file diff --git a/path_visualization_ui.txt b/path_visualization_ui.txt new file mode 100644 index 0000000..2323224 --- /dev/null +++ b/path_visualization_ui.txt @@ -0,0 +1,48 @@ + + + + + + + + \ No newline at end of file diff --git a/src/Core/PathPointRenderPlugin.cs b/src/Core/PathPointRenderPlugin.cs index b3d98b8..d7e934a 100644 --- a/src/Core/PathPointRenderPlugin.cs +++ b/src/Core/PathPointRenderPlugin.cs @@ -7,6 +7,89 @@ using NavisworksTransport.Core; namespace NavisworksTransport { + /// + /// 路径可视化模式枚举 + /// + public enum PathVisualizationMode + { + /// + /// 标准连线模式 - 圆柱形连线 + /// + StandardLine, + + /// + /// 车辆通行空间模式 - 矩形通道 + /// + VehicleSpace + } + + /// + /// 高度计算模式枚举 + /// + public enum VehicleHeightMode + { + /// + /// 固定高度 - 使用车辆高度+安全间隙 + /// + FixedHeight, + + /// + /// 自动高度 - 根据网格大小计算 + /// + AutoHeight + } + + /// + /// 车辆通行空间标记,用于渲染车辆通道空间 + /// + public class VehicleSpaceMarker + { + /// + /// 通道起点 + /// + public Point3D StartPoint { get; set; } + + /// + /// 通道终点 + /// + public Point3D EndPoint { get; set; } + + /// + /// 通道宽度(车辆长宽最大值+2倍安全间隙) + /// + public double Width { get; set; } + + /// + /// 通道高度(车辆高度+安全间隙或自动高度) + /// + public double Height { get; set; } + + /// + /// 通道颜色 + /// + public Color Color { get; set; } + + /// + /// 透明度(0.0-1.0,默认0.5即50%透明) + /// + public double Alpha { get; set; } = 0.5; + + /// + /// 起点在路径中的索引 + /// + public int FromIndex { get; set; } + + /// + /// 终点在路径中的索引 + /// + public int ToIndex { get; set; } + + public override string ToString() + { + return $"VehicleSpaceMarker[{FromIndex}->{ToIndex}, 宽度={Width:F2}m, 高度={Height:F2}m, 透明度={Alpha:F1}]"; + } + } + /// /// 连线标记,用于渲染路径点之间的连接线 /// @@ -73,6 +156,11 @@ namespace NavisworksTransport /// public List LineMarkers { get; set; } + /// + /// 车辆通行空间标记集合 + /// + public List VehicleSpaceMarkers { get; set; } + /// /// 最后更新时间 /// @@ -85,6 +173,7 @@ namespace NavisworksTransport { PointMarkers = new List(); LineMarkers = new List(); + VehicleSpaceMarkers = new List(); LastUpdated = DateTime.Now; } @@ -115,7 +204,17 @@ namespace NavisworksTransport // 当前网格大小(米),用于自适应点大小计算 private double _currentGridSizeInMeters = 0.5; - + + // 路径可视化模式配置 + private PathVisualizationMode _visualizationMode = PathVisualizationMode.StandardLine; + private VehicleHeightMode _vehicleHeightMode = VehicleHeightMode.FixedHeight; + + // 车辆参数(默认值,可以从PathPlanningManager获取) + private double _vehicleLength = 2.0; // 米 + private double _vehicleWidth = 1.5; // 米 + private double _vehicleHeight = 2.0; // 米 + private double _safetyMargin = 0.3; // 米 + // 静态实例,用于外部访问 private static PathPointRenderPlugin _instance; @@ -132,6 +231,34 @@ namespace NavisworksTransport /// public static PathPointRenderPlugin Instance => _instance; + /// + /// 路径可视化模式 + /// + public PathVisualizationMode VisualizationMode + { + get { return _visualizationMode; } + set + { + _visualizationMode = value; + // 模式改变时刷新所有路径可视化 + RefreshAllPaths(); + } + } + + /// + /// 车辆高度计算模式 + /// + public VehicleHeightMode VehicleHeightMode + { + get { return _vehicleHeightMode; } + set + { + _vehicleHeightMode = value; + // 高度模式改变时刷新所有路径可视化 + RefreshAllPaths(); + } + } + /// /// 是否启用渲染 /// @@ -220,13 +347,20 @@ namespace NavisworksTransport graphics.Color(pointMarker.Color, pointMarker.Alpha); graphics.Sphere(pointMarker.Center, pointMarker.Radius); } - + // 渲染所有连线(删除频繁的调试日志以避免日志泛滥) foreach (var lineMarker in visualization.LineMarkers) { graphics.Color(lineMarker.Color, 1.0); graphics.Cylinder(lineMarker.StartPoint, lineMarker.EndPoint, lineMarker.Radius); } + + // 渲染车辆通行空间(矩形通道) + foreach (var vehicleSpaceMarker in visualization.VehicleSpaceMarkers) + { + graphics.Color(vehicleSpaceMarker.Color, vehicleSpaceMarker.Alpha); + RenderVehicleSpace(graphics, vehicleSpaceMarker); + } } // 渲染预览点(灰色) @@ -402,6 +536,30 @@ namespace NavisworksTransport } } + /// + /// 刷新所有路径可视化(用于可视化模式改变时) + /// + private void RefreshAllPaths() + { + lock (_lockObject) + { + var pathIds = _pathVisualizations.Keys.ToList(); + foreach (var pathId in pathIds) + { + if (_pathVisualizations.TryGetValue(pathId, out var visualization)) + { + BuildVisualization(visualization); + } + } + + if (pathIds.Count > 0) + { + LogManager.WriteLog($"[路径刷新] 刷新所有路径: {pathIds.Count}个, 可视化模式: {_visualizationMode}"); + RequestViewRefresh(); + } + } + } + /// /// 移除路径 /// @@ -500,6 +658,7 @@ namespace NavisworksTransport // 清空现有标记 visualization.PointMarkers.Clear(); visualization.LineMarkers.Clear(); + visualization.VehicleSpaceMarkers.Clear(); var points = visualization.PathRoute.Points; if (points.Count == 0) return; @@ -514,22 +673,38 @@ namespace NavisworksTransport visualization.PointMarkers.Add(pointMarker); } - // 构建连线标记(按排序后的顺序连接) - for (int i = 0; i < sortedPoints.Count - 1; i++) + // 根据可视化模式构建连接标记 + if (_visualizationMode == PathVisualizationMode.StandardLine) { - var currentPoint = sortedPoints[i]; - var nextPoint = sortedPoints[i + 1]; - - var lineMarker = new LineMarker + // 构建标准连线标记(按排序后的顺序连接) + for (int i = 0; i < sortedPoints.Count - 1; i++) { - StartPoint = currentPoint.Position, - EndPoint = nextPoint.Position, - Color = GetLineColor(), - Radius = GetLineRadius(), - FromIndex = currentPoint.Index, - ToIndex = nextPoint.Index - }; - visualization.LineMarkers.Add(lineMarker); + var currentPoint = sortedPoints[i]; + var nextPoint = sortedPoints[i + 1]; + + var lineMarker = new LineMarker + { + StartPoint = currentPoint.Position, + EndPoint = nextPoint.Position, + Color = GetLineColor(), + Radius = GetLineRadius(), + FromIndex = currentPoint.Index, + ToIndex = nextPoint.Index + }; + visualization.LineMarkers.Add(lineMarker); + } + } + else if (_visualizationMode == PathVisualizationMode.VehicleSpace) + { + // 构建车辆通行空间标记 + for (int i = 0; i < sortedPoints.Count - 1; i++) + { + var currentPoint = sortedPoints[i]; + var nextPoint = sortedPoints[i + 1]; + + var vehicleSpaceMarker = CreateVehicleSpaceMarker(currentPoint, nextPoint); + visualization.VehicleSpaceMarkers.Add(vehicleSpaceMarker); + } } // 如果路径未完成,添加灰色的原始终点标记 @@ -556,6 +731,47 @@ namespace NavisworksTransport visualization.LastUpdated = DateTime.Now; } + /// + /// 创建车辆通行空间标记 + /// + /// 起点 + /// 终点 + /// 车辆通行空间标记 + private VehicleSpaceMarker CreateVehicleSpaceMarker(PathPoint fromPoint, PathPoint toPoint) + { + // 获取单位转换系数 + double metersToModelUnits = GetMetersToModelUnitsConversionFactor(); + + // 计算车辆通行空间宽度(米) + double vehicleInflationWidthInMeters = Math.Max(_vehicleLength, _vehicleWidth) + 2 * _safetyMargin; + + // 计算车辆通行空间高度(米) + double vehicleSpaceHeightInMeters; + if (_vehicleHeightMode == VehicleHeightMode.FixedHeight) + { + // 固定高度模式:车辆高度 + 安全间隙 + vehicleSpaceHeightInMeters = _vehicleHeight + _safetyMargin; + } + else + { + // 自动高度模式:根据网格大小计算 + vehicleSpaceHeightInMeters = _currentGridSizeInMeters * 2.0; // 网格大小的2倍作为默认高度 + vehicleSpaceHeightInMeters = Math.Max(vehicleSpaceHeightInMeters, _vehicleHeight + _safetyMargin); // 确保不小于车辆高度 + } + + return new VehicleSpaceMarker + { + StartPoint = fromPoint.Position, + EndPoint = toPoint.Position, + Width = vehicleInflationWidthInMeters * metersToModelUnits, // 转换为模型单位 + Height = vehicleSpaceHeightInMeters * metersToModelUnits, // 转换为模型单位 + Color = GetLineColor(), // 使用与连线相同的颜色 + Alpha = 0.5, // 50%透明度 + FromIndex = fromPoint.Index, + ToIndex = toPoint.Index + }; + } + /// /// 创建点标记 /// @@ -641,6 +857,29 @@ namespace NavisworksTransport LogManager.WriteLog($"[网格点大小] 设置网格大小: {gridSizeInMeters:F2}米"); } + /// + /// 设置车辆参数(从PathPlanningManager同步) + /// + /// 车辆长度(米) + /// 车辆宽度(米) + /// 车辆高度(米) + /// 安全间隙(米) + public void SetVehicleParameters(double vehicleLength, double vehicleWidth, double vehicleHeight, double safetyMargin) + { + _vehicleLength = vehicleLength; + _vehicleWidth = vehicleWidth; + _vehicleHeight = vehicleHeight; + _safetyMargin = safetyMargin; + + LogManager.WriteLog($"[车辆参数] 更新车辆参数: 长={vehicleLength:F2}m, 宽={vehicleWidth:F2}m, 高={vehicleHeight:F2}m, 安全间隙={safetyMargin:F2}m"); + + // 车辆参数改变时刷新所有路径可视化 + if (_visualizationMode == PathVisualizationMode.VehicleSpace) + { + RefreshAllPaths(); + } + } + /// /// 获取连线颜色(统一使用橙色) /// @@ -1238,6 +1477,75 @@ namespace NavisworksTransport return Math.Sqrt(dx * dx + dy * dy + dz * dz); } + /// + /// 渲染车辆通行空间(矩形通道)- 使用Cuboid API简化实现 + /// + /// 图形上下文 + /// 车辆通行空间标记 + private void RenderVehicleSpace(Graphics graphics, VehicleSpaceMarker vehicleSpace) + { + try + { + // 计算通道方向向量 + var direction = new Vector3D( + vehicleSpace.EndPoint.X - vehicleSpace.StartPoint.X, + vehicleSpace.EndPoint.Y - vehicleSpace.StartPoint.Y, + vehicleSpace.EndPoint.Z - vehicleSpace.StartPoint.Z + ); + + // 计算通道长度 + var length = Math.Sqrt(direction.X * direction.X + direction.Y * direction.Y + direction.Z * direction.Z); + + if (length < 0.001) // 避免零长度线段 + return; + + // 归一化方向向量 + direction = new Vector3D(direction.X / length, direction.Y / length, direction.Z / length); + + // 计算垂直向量(在XY平面内垂直于方向向量) + var right = new Vector3D(-direction.Y, direction.X, 0); + + // 如果方向向量垂直于XY平面,则使用不同的right向量 + if (Math.Abs(direction.Z) > 0.9) + { + right = new Vector3D(1, 0, 0); + } + + // 归一化right向量 + var rightLength = Math.Sqrt(right.X * right.X + right.Y * right.Y + right.Z * right.Z); + if (rightLength > 0.001) + { + right = new Vector3D(right.X / rightLength, right.Y / rightLength, right.Z / rightLength); + } + + // 计算通道的边界框和向量 + var halfWidth = vehicleSpace.Width / 2.0; + + // 计算立方体原点(起点左下角) + var origin = new Point3D( + vehicleSpace.StartPoint.X - halfWidth * right.X, + vehicleSpace.StartPoint.Y - halfWidth * right.Y, + vehicleSpace.StartPoint.Z + ); + + // 定义立方体的三个轴向量 + var xVector = new Vector3D(direction.X * length, direction.Y * length, direction.Z * length); // 长度方向 + var yVector = new Vector3D(right.X * vehicleSpace.Width, right.Y * vehicleSpace.Width, right.Z * vehicleSpace.Width); // 宽度方向 + var zVector = new Vector3D(0, 0, vehicleSpace.Height); // 高度方向 + + // 设置颜色和透明度 + graphics.Color(vehicleSpace.Color, vehicleSpace.Alpha); + + // 使用Cuboid API渲染长方体通道 + graphics.Cuboid(origin, xVector, yVector, zVector, true); + } + catch (Exception ex) + { + LogManager.WriteLog($"[车辆空间渲染] 渲染车辆通行空间失败: {ex.Message}"); + } + } + + /// /// 请求视图刷新(带防抖机制) /// diff --git a/src/UI/WPF/ViewModels/PathEditingViewModel.cs b/src/UI/WPF/ViewModels/PathEditingViewModel.cs index 3b540bf..a9fffe2 100644 --- a/src/UI/WPF/ViewModels/PathEditingViewModel.cs +++ b/src/UI/WPF/ViewModels/PathEditingViewModel.cs @@ -172,7 +172,10 @@ namespace NavisworksTransport.UI.WPF.ViewModels LogManager.Warning("PathPointRenderPlugin实例为空,无法更新路径可视化"); return; } - + + // 0. 先同步车辆参数到渲染插件 + SyncVehicleParametersToRenderPlugin(); + // 1. 清理现有的路径可视化,但保留网格可视化 PathPointRenderPlugin.Instance.ClearPathsExcept("grid_visualization_all", "grid_visualization_channel", "grid_visualization_unknown", "grid_visualization_obstacle", "grid_visualization_door"); LogManager.WriteLog("[路径可视化] 已清理现有路径显示(保留网格可视化)"); @@ -233,6 +236,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels { if (SetProperty(ref _vehicleLength, value)) { + SyncVehicleParametersToRenderPlugin(); OnPropertyChanged(nameof(CanExecuteAutoPlanPath)); } } @@ -245,6 +249,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels { if (SetProperty(ref _vehicleWidth, value)) { + SyncVehicleParametersToRenderPlugin(); OnPropertyChanged(nameof(CanExecuteAutoPlanPath)); } } @@ -257,6 +262,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels { if (SetProperty(ref _vehicleHeight, value)) { + SyncVehicleParametersToRenderPlugin(); OnPropertyChanged(nameof(CanExecuteAutoPlanPath)); } } @@ -271,6 +277,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels var roundedValue = Math.Round(value, 2); if (SetProperty(ref _safetyMargin, roundedValue)) { + SyncVehicleParametersToRenderPlugin(); OnPropertyChanged(nameof(CanExecuteAutoPlanPath)); } } @@ -441,10 +448,14 @@ namespace NavisworksTransport.UI.WPF.ViewModels // 初始化命令 InitializeCommands(); - + + // 初始化车辆参数同步(在PathPointRenderPlugin实例不为空时才同步) + // 如果PathPointRenderPlugin尚未初始化,将在属性变更时自动同步 + SyncVehicleParametersToRenderPlugin(); + // 注意:不在这里订阅PathPlanningManager事件, // 因为PathPlanningManager还没有设置,事件订阅在PathPlanningManager属性setter中处理 - + LogManager.Info("PathEditingViewModel构造函数执行完成,已迁移原有业务逻辑"); } catch (Exception ex) @@ -486,10 +497,14 @@ namespace NavisworksTransport.UI.WPF.ViewModels // 初始化命令 InitializeCommands(); - + + // 初始化车辆参数同步(在PathPointRenderPlugin实例不为空时才同步) + // 如果PathPointRenderPlugin尚未初始化,将在属性变更时自动同步 + SyncVehicleParametersToRenderPlugin(); + // 注意:不在这里订阅PathPlanningManager事件, // 因为PathPlanningManager还没有设置,事件订阅在PathPlanningManager属性setter中处理 - + LogManager.Info("PathEditingViewModel构造函数执行完成 - 支持统一状态栏"); } catch (Exception ex) @@ -1912,6 +1927,37 @@ namespace NavisworksTransport.UI.WPF.ViewModels #endregion + #region 车辆参数同步 + + /// + /// 同步车辆参数到渲染插件 + /// + private void SyncVehicleParametersToRenderPlugin() + { + try + { + if (PathPointRenderPlugin.Instance != null) + { + PathPointRenderPlugin.Instance.SetVehicleParameters( + VehicleLength, + VehicleWidth, + VehicleHeight, + SafetyMargin); + LogManager.WriteLog($"[车辆参数同步] 已同步车辆参数到渲染插件: 长={VehicleLength:F2}m, 宽={VehicleWidth:F2}m, 高={VehicleHeight:F2}m, 安全间隙={SafetyMargin:F2}m"); + } + else + { + LogManager.Warning("[车辆参数同步] PathPointRenderPlugin实例为空,无法同步车辆参数"); + } + } + catch (Exception ex) + { + LogManager.Error($"[车辆参数同步] 同步车辆参数失败: {ex.Message}", ex); + } + } + + #endregion + #region 辅助方法 /// diff --git a/src/UI/WPF/ViewModels/SystemManagementViewModel.cs b/src/UI/WPF/ViewModels/SystemManagementViewModel.cs index b119778..dcf4077 100644 --- a/src/UI/WPF/ViewModels/SystemManagementViewModel.cs +++ b/src/UI/WPF/ViewModels/SystemManagementViewModel.cs @@ -28,6 +28,11 @@ namespace NavisworksTransport.UI.WPF.ViewModels private bool _showObstacleGrid = false; private bool _showUnknownGrid = false; private bool _showDoorGrid = false; + // 路径可视化模式字段 + private bool _isStandardLineMode = true; + private bool _isVehicleSpaceMode = false; + private bool _isFixedHeightMode = true; + private bool _isAutoHeightMode = false; private ObservableCollection _logLevels; private string _selectedLogLevel = "Info"; private string _pluginVersion = "v1.0"; @@ -124,6 +129,81 @@ namespace NavisworksTransport.UI.WPF.ViewModels } } } + /// + /// 是否使用标准连线模式 + /// + public bool IsStandardLineMode + { + get => _isStandardLineMode; + set + { + if (SetProperty(ref _isStandardLineMode, value)) + { + if (value) + { + IsVehicleSpaceMode = false; + OnPathVisualizationModeChanged(); + } + } + } + } + + /// + /// 是否使用车辆通行空间模式 + /// + public bool IsVehicleSpaceMode + { + get => _isVehicleSpaceMode; + set + { + if (SetProperty(ref _isVehicleSpaceMode, value)) + { + if (value) + { + IsStandardLineMode = false; + OnPathVisualizationModeChanged(); + } + } + } + } + + /// + /// 是否使用固定高度模式 + /// + public bool IsFixedHeightMode + { + get => _isFixedHeightMode; + set + { + if (SetProperty(ref _isFixedHeightMode, value)) + { + if (value) + { + IsAutoHeightMode = false; + OnVehicleHeightModeChanged(); + } + } + } + } + + /// + /// 是否使用自动高度模式 + /// + public bool IsAutoHeightMode + { + get => _isAutoHeightMode; + set + { + if (SetProperty(ref _isAutoHeightMode, value)) + { + if (value) + { + IsFixedHeightMode = false; + OnVehicleHeightModeChanged(); + } + } + } + } /// /// 日志级别集合 @@ -345,7 +425,71 @@ namespace NavisworksTransport.UI.WPF.ViewModels UpdateMainStatus("网格可视化设置应用失败"); } } + /// + /// 路径可视化模式变更事件处理 + /// + private void OnPathVisualizationModeChanged() + { + try + { + var renderPlugin = PathPointRenderPlugin.Instance; + if (renderPlugin != null) + { + var mode = IsVehicleSpaceMode ? PathVisualizationMode.VehicleSpace : PathVisualizationMode.StandardLine; + renderPlugin.VisualizationMode = mode; + // 在切换到车辆通行空间模式时,同步车辆参数 + if (IsVehicleSpaceMode) + { + SyncVehicleParametersFromPathEditingViewModel(); + } + + LogManager.Info($"路径可视化模式已更改: {(IsVehicleSpaceMode ? "车辆通行空间" : "标准连线")}"); + UpdateMainStatus("路径可视化模式已更新"); + } + else + { + LogManager.Warning("无法获取PathPointRenderPlugin实例"); + } + } + catch (Exception ex) + { + LogManager.Error($"应用路径可视化模式失败: {ex.Message}", ex); + UpdateMainStatus("路径可视化模式更新失败"); + } + } + + /// + /// 车辆高度模式变更事件处理 + /// + private void OnVehicleHeightModeChanged() + { + try + { + var renderPlugin = PathPointRenderPlugin.Instance; + if (renderPlugin != null) + { + var mode = IsAutoHeightMode ? VehicleHeightMode.AutoHeight : VehicleHeightMode.FixedHeight; + renderPlugin.VehicleHeightMode = mode; + + // 在高度模式变更时也同步车辆参数(特别是高度参数) + SyncVehicleParametersFromPathEditingViewModel(); + + LogManager.Info($"车辆高度模式已更改: {(IsAutoHeightMode ? "自动高度" : "固定高度")}"); + UpdateMainStatus("车辆高度模式已更新"); + } + else + { + LogManager.Warning("无法获取PathPointRenderPlugin实例"); + } + } + catch (Exception ex) + { + LogManager.Error($"应用车辆高度模式失败: {ex.Message}", ex); + UpdateMainStatus("车辆高度模式更新失败"); + } + } + /// /// 获取路径规划管理器实例 /// @@ -891,6 +1035,121 @@ namespace NavisworksTransport.UI.WPF.ViewModels #endregion + #region 车辆参数同步 + + /// + /// 同步车辆参数到渲染插件 + /// 首先尝试从 PathPlanningManager 获取,如果不可用则尝试从 PathEditingViewModel 获取 + /// + private void SyncVehicleParametersFromPathEditingViewModel() + { + try + { + bool syncSuccess = false; + + // 方法 1: 从 PathPlanningManager 获取车辆参数(更可靠) + var pathPlanningManager = GetPathPlanningManager(); + if (pathPlanningManager != null) + { + try + { + // PathPlanningManager 可能有车辆参数的最新值 + // 但由于需要检查 PathPlanningManager 的具体 API,这里直接跳过到方法2 + LogManager.Debug("[系统管理-车辆参数同步] PathPlanningManager可用,但暂时使用PathEditingViewModel方式"); + } + catch (Exception ex) + { + LogManager.Debug($"[系统管理-车辆参数同步] 从 PathPlanningManager 获取车辆参数异常: {ex.Message}"); + } + } + + // 方法 2: 从 PathEditingViewModel 获取车辆参数 + if (!syncSuccess) + { + var pathEditingViewModel = GetPathEditingViewModel(); + if (pathEditingViewModel != null) + { + if (PathPointRenderPlugin.Instance != null) + { + PathPointRenderPlugin.Instance.SetVehicleParameters( + pathEditingViewModel.VehicleLength, + pathEditingViewModel.VehicleWidth, + pathEditingViewModel.VehicleHeight, + pathEditingViewModel.SafetyMargin); + + LogManager.WriteLog($"[系统管理-车辆参数同步] 已同步车辆参数: 长={pathEditingViewModel.VehicleLength:F2}m, 宽={pathEditingViewModel.VehicleWidth:F2}m, 高={pathEditingViewModel.VehicleHeight:F2}m, 安全间隙={pathEditingViewModel.SafetyMargin:F2}m"); + syncSuccess = true; + } + else + { + LogManager.Warning("[系统管理-车辆参数同步] PathPointRenderPlugin实例为空,无法同步车辆参数"); + } + } + } + + // 方法 3: 使用默认参数作为后备 + if (!syncSuccess) + { + LogManager.Info("[系统管理-车辆参数同步] 无法获取实际车辆参数,使用默认车辆参数"); + + if (PathPointRenderPlugin.Instance != null) + { + // 使用PathEditingViewModel的默认值而不是PathPointRenderPlugin的默认值 + PathPointRenderPlugin.Instance.SetVehicleParameters(1.0, 1.0, 2.0, 0.25); + LogManager.WriteLog("[系统管理-车辆参数同步] 使用默认车辆参数: 长=1.0m, 宽=1.0m, 高=2.0m, 安全间隙=0.25m"); + } + } + } + catch (Exception ex) + { + LogManager.Error($"[系统管理-车辆参数同步] 同步车辆参数失败: {ex.Message}", ex); + } + } + + /// + /// 获取 PathEditingViewModel 实例 + /// + /// PathEditingViewModel 实例或 null + private PathEditingViewModel GetPathEditingViewModel() + { + try + { + // 通过主 ViewModel 获取 PathEditingView 的 ViewModel + if (_mainViewModel != null) + { + // 尝试通过反射获取LogisticsControlPanel + var mainViewModelType = _mainViewModel.GetType(); + + // 查找可能的PathEditingView属性或字段 + var pathEditingViewProperty = mainViewModelType.GetProperty("PathEditingView"); + if (pathEditingViewProperty != null) + { + var pathEditingView = pathEditingViewProperty.GetValue(_mainViewModel); + if (pathEditingView != null) + { + var viewModelProperty = pathEditingView.GetType().GetProperty("ViewModel"); + if (viewModelProperty != null) + { + return viewModelProperty.GetValue(pathEditingView) as PathEditingViewModel; + } + } + } + + LogManager.Debug("[获取PathEditingViewModel] 未找到PathEditingView属性或ViewModel属性"); + } + + LogManager.Debug("[获取PathEditingViewModel] _mainViewModel为空或无法获取PathEditingView"); + return null; + } + catch (Exception ex) + { + LogManager.Error($"[获取PathEditingViewModel] 异常: {ex.Message}", ex); + return null; + } + } + + #endregion + #region 辅助方法 /// diff --git a/src/UI/WPF/Views/SystemManagementView.xaml b/src/UI/WPF/Views/SystemManagementView.xaml index cb6dfab..e3bfd42 100644 --- a/src/UI/WPF/Views/SystemManagementView.xaml +++ b/src/UI/WPF/Views/SystemManagementView.xaml @@ -146,7 +146,54 @@ NavisworksTransport 系统管理页签视图 - 采用与其他页签一致的Nav ToolTip="显示门网格点(50%透明绿色)"/> - + + + + + + + +