增加了空间通道方式的路径连线

This commit is contained in:
tian 2025-09-14 17:06:04 +08:00
parent d1185d986d
commit 62349099aa
9 changed files with 880 additions and 24 deletions

View File

@ -134,7 +134,8 @@
"Read(//c/Users/Tellme/apps/OpenSource/AStar-master/**)", "Read(//c/Users/Tellme/apps/OpenSource/AStar-master/**)",
"Bash(\"./compile.bat\")", "Bash(\"./compile.bat\")",
"Bash(xcopy:*)", "Bash(xcopy:*)",
"Read(//c/ProgramData/Autodesk/Navisworks Manage 2026/NavisworksTransport/logs/**)" "Read(//c/ProgramData/Autodesk/Navisworks Manage 2026/NavisworksTransport/logs/**)",
"Bash(sed:*)"
], ],
"deny": [], "deny": [],
"additionalDirectories": [ "additionalDirectories": [

View File

@ -2,6 +2,10 @@
## 功能点 ## 功能点
### [2025/09/14]
1. [x] 功能增加两种路径连线方式1、宽度路径半透明膨胀直径10cm高立方体。2、和前面一样高度为车高加安全距离
### [2025/09/12] ### [2025/09/12]
1. [x] (功能)给动画增加步进功能,同时提供反向功能(反向播放、反向步进) 1. [x] (功能)给动画增加步进功能,同时提供反向功能(反向播放、反向步进)

View File

@ -378,4 +378,29 @@
- 正向播放 - 标准前进播放 - 正向播放 - 标准前进播放
- 下一帧 (→) - 精确单帧前进 - 下一帧 (→) - 精确单帧前进
- 快进10帧 (Shift+→) - 快速前进功能 - 快进10帧 (Shift+→) - 快速前进功能
- 停止 (Esc) - 停止并重置动画 - 停止 (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、【界面】-【选取】中,可以设置精度,从几何体、最低层次的对象、最高层级的唯一对象、最高层级的对象、图层、文件,默认是最低层次的对象。

View File

@ -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

48
path_visualization_ui.txt Normal file
View File

@ -0,0 +1,48 @@
<!-- 路径可视化设置 -->
<Grid Margin="0,10,0,10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0"
Content="路径可视化:"
Style="{StaticResource ParameterLabelStyle}"
Width="100"
VerticalAlignment="Center"/>
<StackPanel Grid.Column="1"
Orientation="Vertical"
Margin="5,0,0,0">
<!-- 可视化模式选择 -->
<StackPanel Orientation="Horizontal" Margin="0,0,0,5">
<RadioButton Content="标准连线"
GroupName="PathVisualizationMode"
IsChecked="{Binding IsStandardLineMode}"
Margin="0,0,20,0"
VerticalAlignment="Center"
ToolTip="显示标准圆柱形连线"/>
<RadioButton Content="车辆通行空间"
GroupName="PathVisualizationMode"
IsChecked="{Binding IsVehicleSpaceMode}"
VerticalAlignment="Center"
ToolTip="显示车辆通行空间(矩形通道)"/>
</StackPanel>
<!-- 车辆高度模式选择 -->
<StackPanel Orientation="Horizontal" Margin="0,5,0,0">
<Label Content="高度模式:" Style="{StaticResource ParameterLabelStyle}" Width="70" VerticalAlignment="Center"/>
<RadioButton Content="固定高度"
GroupName="VehicleHeightMode"
IsChecked="{Binding IsFixedHeightMode}"
Margin="5,0,15,0"
VerticalAlignment="Center"
ToolTip="使用车辆高度+安全间隙"/>
<RadioButton Content="自动高度"
GroupName="VehicleHeightMode"
IsChecked="{Binding IsAutoHeightMode}"
VerticalAlignment="Center"
ToolTip="根据网格大小自动计算"/>
</StackPanel>
</StackPanel>
</Grid>

View File

@ -7,6 +7,89 @@ using NavisworksTransport.Core;
namespace NavisworksTransport namespace NavisworksTransport
{ {
/// <summary>
/// 路径可视化模式枚举
/// </summary>
public enum PathVisualizationMode
{
/// <summary>
/// 标准连线模式 - 圆柱形连线
/// </summary>
StandardLine,
/// <summary>
/// 车辆通行空间模式 - 矩形通道
/// </summary>
VehicleSpace
}
/// <summary>
/// 高度计算模式枚举
/// </summary>
public enum VehicleHeightMode
{
/// <summary>
/// 固定高度 - 使用车辆高度+安全间隙
/// </summary>
FixedHeight,
/// <summary>
/// 自动高度 - 根据网格大小计算
/// </summary>
AutoHeight
}
/// <summary>
/// 车辆通行空间标记,用于渲染车辆通道空间
/// </summary>
public class VehicleSpaceMarker
{
/// <summary>
/// 通道起点
/// </summary>
public Point3D StartPoint { get; set; }
/// <summary>
/// 通道终点
/// </summary>
public Point3D EndPoint { get; set; }
/// <summary>
/// 通道宽度(车辆长宽最大值+2倍安全间隙
/// </summary>
public double Width { get; set; }
/// <summary>
/// 通道高度(车辆高度+安全间隙或自动高度)
/// </summary>
public double Height { get; set; }
/// <summary>
/// 通道颜色
/// </summary>
public Color Color { get; set; }
/// <summary>
/// 透明度0.0-1.0默认0.5即50%透明)
/// </summary>
public double Alpha { get; set; } = 0.5;
/// <summary>
/// 起点在路径中的索引
/// </summary>
public int FromIndex { get; set; }
/// <summary>
/// 终点在路径中的索引
/// </summary>
public int ToIndex { get; set; }
public override string ToString()
{
return $"VehicleSpaceMarker[{FromIndex}->{ToIndex}, 宽度={Width:F2}m, 高度={Height:F2}m, 透明度={Alpha:F1}]";
}
}
/// <summary> /// <summary>
/// 连线标记,用于渲染路径点之间的连接线 /// 连线标记,用于渲染路径点之间的连接线
/// </summary> /// </summary>
@ -73,6 +156,11 @@ namespace NavisworksTransport
/// </summary> /// </summary>
public List<LineMarker> LineMarkers { get; set; } public List<LineMarker> LineMarkers { get; set; }
/// <summary>
/// 车辆通行空间标记集合
/// </summary>
public List<VehicleSpaceMarker> VehicleSpaceMarkers { get; set; }
/// <summary> /// <summary>
/// 最后更新时间 /// 最后更新时间
/// </summary> /// </summary>
@ -85,6 +173,7 @@ namespace NavisworksTransport
{ {
PointMarkers = new List<CircleMarker>(); PointMarkers = new List<CircleMarker>();
LineMarkers = new List<LineMarker>(); LineMarkers = new List<LineMarker>();
VehicleSpaceMarkers = new List<VehicleSpaceMarker>();
LastUpdated = DateTime.Now; LastUpdated = DateTime.Now;
} }
@ -115,7 +204,17 @@ namespace NavisworksTransport
// 当前网格大小(米),用于自适应点大小计算 // 当前网格大小(米),用于自适应点大小计算
private double _currentGridSizeInMeters = 0.5; 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; private static PathPointRenderPlugin _instance;
@ -132,6 +231,34 @@ namespace NavisworksTransport
/// </summary> /// </summary>
public static PathPointRenderPlugin Instance => _instance; public static PathPointRenderPlugin Instance => _instance;
/// <summary>
/// 路径可视化模式
/// </summary>
public PathVisualizationMode VisualizationMode
{
get { return _visualizationMode; }
set
{
_visualizationMode = value;
// 模式改变时刷新所有路径可视化
RefreshAllPaths();
}
}
/// <summary>
/// 车辆高度计算模式
/// </summary>
public VehicleHeightMode VehicleHeightMode
{
get { return _vehicleHeightMode; }
set
{
_vehicleHeightMode = value;
// 高度模式改变时刷新所有路径可视化
RefreshAllPaths();
}
}
/// <summary> /// <summary>
/// 是否启用渲染 /// 是否启用渲染
/// </summary> /// </summary>
@ -220,13 +347,20 @@ namespace NavisworksTransport
graphics.Color(pointMarker.Color, pointMarker.Alpha); graphics.Color(pointMarker.Color, pointMarker.Alpha);
graphics.Sphere(pointMarker.Center, pointMarker.Radius); graphics.Sphere(pointMarker.Center, pointMarker.Radius);
} }
// 渲染所有连线(删除频繁的调试日志以避免日志泛滥) // 渲染所有连线(删除频繁的调试日志以避免日志泛滥)
foreach (var lineMarker in visualization.LineMarkers) foreach (var lineMarker in visualization.LineMarkers)
{ {
graphics.Color(lineMarker.Color, 1.0); graphics.Color(lineMarker.Color, 1.0);
graphics.Cylinder(lineMarker.StartPoint, lineMarker.EndPoint, lineMarker.Radius); 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
} }
} }
/// <summary>
/// 刷新所有路径可视化(用于可视化模式改变时)
/// </summary>
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();
}
}
}
/// <summary> /// <summary>
/// 移除路径 /// 移除路径
/// </summary> /// </summary>
@ -500,6 +658,7 @@ namespace NavisworksTransport
// 清空现有标记 // 清空现有标记
visualization.PointMarkers.Clear(); visualization.PointMarkers.Clear();
visualization.LineMarkers.Clear(); visualization.LineMarkers.Clear();
visualization.VehicleSpaceMarkers.Clear();
var points = visualization.PathRoute.Points; var points = visualization.PathRoute.Points;
if (points.Count == 0) return; if (points.Count == 0) return;
@ -514,22 +673,38 @@ namespace NavisworksTransport
visualization.PointMarkers.Add(pointMarker); 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]; for (int i = 0; i < sortedPoints.Count - 1; i++)
var lineMarker = new LineMarker
{ {
StartPoint = currentPoint.Position, var currentPoint = sortedPoints[i];
EndPoint = nextPoint.Position, var nextPoint = sortedPoints[i + 1];
Color = GetLineColor(),
Radius = GetLineRadius(), var lineMarker = new LineMarker
FromIndex = currentPoint.Index, {
ToIndex = nextPoint.Index StartPoint = currentPoint.Position,
}; EndPoint = nextPoint.Position,
visualization.LineMarkers.Add(lineMarker); 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; visualization.LastUpdated = DateTime.Now;
} }
/// <summary>
/// 创建车辆通行空间标记
/// </summary>
/// <param name="fromPoint">起点</param>
/// <param name="toPoint">终点</param>
/// <returns>车辆通行空间标记</returns>
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
};
}
/// <summary> /// <summary>
/// 创建点标记 /// 创建点标记
/// </summary> /// </summary>
@ -641,6 +857,29 @@ namespace NavisworksTransport
LogManager.WriteLog($"[网格点大小] 设置网格大小: {gridSizeInMeters:F2}米"); LogManager.WriteLog($"[网格点大小] 设置网格大小: {gridSizeInMeters:F2}米");
} }
/// <summary>
/// 设置车辆参数从PathPlanningManager同步
/// </summary>
/// <param name="vehicleLength">车辆长度(米)</param>
/// <param name="vehicleWidth">车辆宽度(米)</param>
/// <param name="vehicleHeight">车辆高度(米)</param>
/// <param name="safetyMargin">安全间隙(米)</param>
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();
}
}
/// <summary> /// <summary>
/// 获取连线颜色(统一使用橙色) /// 获取连线颜色(统一使用橙色)
/// </summary> /// </summary>
@ -1238,6 +1477,75 @@ namespace NavisworksTransport
return Math.Sqrt(dx * dx + dy * dy + dz * dz); return Math.Sqrt(dx * dx + dy * dy + dz * dz);
} }
/// <summary>
/// 渲染车辆通行空间(矩形通道)- 使用Cuboid API简化实现
/// </summary>
/// <param name="graphics">图形上下文</param>
/// <param name="vehicleSpace">车辆通行空间标记</param>
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}");
}
}
/// <summary> /// <summary>
/// 请求视图刷新(带防抖机制) /// 请求视图刷新(带防抖机制)
/// </summary> /// </summary>

View File

@ -172,7 +172,10 @@ namespace NavisworksTransport.UI.WPF.ViewModels
LogManager.Warning("PathPointRenderPlugin实例为空无法更新路径可视化"); LogManager.Warning("PathPointRenderPlugin实例为空无法更新路径可视化");
return; return;
} }
// 0. 先同步车辆参数到渲染插件
SyncVehicleParametersToRenderPlugin();
// 1. 清理现有的路径可视化,但保留网格可视化 // 1. 清理现有的路径可视化,但保留网格可视化
PathPointRenderPlugin.Instance.ClearPathsExcept("grid_visualization_all", "grid_visualization_channel", "grid_visualization_unknown", "grid_visualization_obstacle", "grid_visualization_door"); PathPointRenderPlugin.Instance.ClearPathsExcept("grid_visualization_all", "grid_visualization_channel", "grid_visualization_unknown", "grid_visualization_obstacle", "grid_visualization_door");
LogManager.WriteLog("[路径可视化] 已清理现有路径显示(保留网格可视化)"); LogManager.WriteLog("[路径可视化] 已清理现有路径显示(保留网格可视化)");
@ -233,6 +236,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{ {
if (SetProperty(ref _vehicleLength, value)) if (SetProperty(ref _vehicleLength, value))
{ {
SyncVehicleParametersToRenderPlugin();
OnPropertyChanged(nameof(CanExecuteAutoPlanPath)); OnPropertyChanged(nameof(CanExecuteAutoPlanPath));
} }
} }
@ -245,6 +249,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{ {
if (SetProperty(ref _vehicleWidth, value)) if (SetProperty(ref _vehicleWidth, value))
{ {
SyncVehicleParametersToRenderPlugin();
OnPropertyChanged(nameof(CanExecuteAutoPlanPath)); OnPropertyChanged(nameof(CanExecuteAutoPlanPath));
} }
} }
@ -257,6 +262,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{ {
if (SetProperty(ref _vehicleHeight, value)) if (SetProperty(ref _vehicleHeight, value))
{ {
SyncVehicleParametersToRenderPlugin();
OnPropertyChanged(nameof(CanExecuteAutoPlanPath)); OnPropertyChanged(nameof(CanExecuteAutoPlanPath));
} }
} }
@ -271,6 +277,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
var roundedValue = Math.Round(value, 2); var roundedValue = Math.Round(value, 2);
if (SetProperty(ref _safetyMargin, roundedValue)) if (SetProperty(ref _safetyMargin, roundedValue))
{ {
SyncVehicleParametersToRenderPlugin();
OnPropertyChanged(nameof(CanExecuteAutoPlanPath)); OnPropertyChanged(nameof(CanExecuteAutoPlanPath));
} }
} }
@ -441,10 +448,14 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 初始化命令 // 初始化命令
InitializeCommands(); InitializeCommands();
// 初始化车辆参数同步在PathPointRenderPlugin实例不为空时才同步
// 如果PathPointRenderPlugin尚未初始化将在属性变更时自动同步
SyncVehicleParametersToRenderPlugin();
// 注意不在这里订阅PathPlanningManager事件 // 注意不在这里订阅PathPlanningManager事件
// 因为PathPlanningManager还没有设置事件订阅在PathPlanningManager属性setter中处理 // 因为PathPlanningManager还没有设置事件订阅在PathPlanningManager属性setter中处理
LogManager.Info("PathEditingViewModel构造函数执行完成已迁移原有业务逻辑"); LogManager.Info("PathEditingViewModel构造函数执行完成已迁移原有业务逻辑");
} }
catch (Exception ex) catch (Exception ex)
@ -486,10 +497,14 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 初始化命令 // 初始化命令
InitializeCommands(); InitializeCommands();
// 初始化车辆参数同步在PathPointRenderPlugin实例不为空时才同步
// 如果PathPointRenderPlugin尚未初始化将在属性变更时自动同步
SyncVehicleParametersToRenderPlugin();
// 注意不在这里订阅PathPlanningManager事件 // 注意不在这里订阅PathPlanningManager事件
// 因为PathPlanningManager还没有设置事件订阅在PathPlanningManager属性setter中处理 // 因为PathPlanningManager还没有设置事件订阅在PathPlanningManager属性setter中处理
LogManager.Info("PathEditingViewModel构造函数执行完成 - 支持统一状态栏"); LogManager.Info("PathEditingViewModel构造函数执行完成 - 支持统一状态栏");
} }
catch (Exception ex) catch (Exception ex)
@ -1912,6 +1927,37 @@ namespace NavisworksTransport.UI.WPF.ViewModels
#endregion #endregion
#region
/// <summary>
/// 同步车辆参数到渲染插件
/// </summary>
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 #region
/// <summary> /// <summary>

View File

@ -28,6 +28,11 @@ namespace NavisworksTransport.UI.WPF.ViewModels
private bool _showObstacleGrid = false; private bool _showObstacleGrid = false;
private bool _showUnknownGrid = false; private bool _showUnknownGrid = false;
private bool _showDoorGrid = false; private bool _showDoorGrid = false;
// 路径可视化模式字段
private bool _isStandardLineMode = true;
private bool _isVehicleSpaceMode = false;
private bool _isFixedHeightMode = true;
private bool _isAutoHeightMode = false;
private ObservableCollection<string> _logLevels; private ObservableCollection<string> _logLevels;
private string _selectedLogLevel = "Info"; private string _selectedLogLevel = "Info";
private string _pluginVersion = "v1.0"; private string _pluginVersion = "v1.0";
@ -124,6 +129,81 @@ namespace NavisworksTransport.UI.WPF.ViewModels
} }
} }
} }
/// <summary>
/// 是否使用标准连线模式
/// </summary>
public bool IsStandardLineMode
{
get => _isStandardLineMode;
set
{
if (SetProperty(ref _isStandardLineMode, value))
{
if (value)
{
IsVehicleSpaceMode = false;
OnPathVisualizationModeChanged();
}
}
}
}
/// <summary>
/// 是否使用车辆通行空间模式
/// </summary>
public bool IsVehicleSpaceMode
{
get => _isVehicleSpaceMode;
set
{
if (SetProperty(ref _isVehicleSpaceMode, value))
{
if (value)
{
IsStandardLineMode = false;
OnPathVisualizationModeChanged();
}
}
}
}
/// <summary>
/// 是否使用固定高度模式
/// </summary>
public bool IsFixedHeightMode
{
get => _isFixedHeightMode;
set
{
if (SetProperty(ref _isFixedHeightMode, value))
{
if (value)
{
IsAutoHeightMode = false;
OnVehicleHeightModeChanged();
}
}
}
}
/// <summary>
/// 是否使用自动高度模式
/// </summary>
public bool IsAutoHeightMode
{
get => _isAutoHeightMode;
set
{
if (SetProperty(ref _isAutoHeightMode, value))
{
if (value)
{
IsFixedHeightMode = false;
OnVehicleHeightModeChanged();
}
}
}
}
/// <summary> /// <summary>
/// 日志级别集合 /// 日志级别集合
@ -345,7 +425,71 @@ namespace NavisworksTransport.UI.WPF.ViewModels
UpdateMainStatus("网格可视化设置应用失败"); UpdateMainStatus("网格可视化设置应用失败");
} }
} }
/// <summary>
/// 路径可视化模式变更事件处理
/// </summary>
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("路径可视化模式更新失败");
}
}
/// <summary>
/// 车辆高度模式变更事件处理
/// </summary>
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("车辆高度模式更新失败");
}
}
/// <summary> /// <summary>
/// 获取路径规划管理器实例 /// 获取路径规划管理器实例
/// </summary> /// </summary>
@ -891,6 +1035,121 @@ namespace NavisworksTransport.UI.WPF.ViewModels
#endregion #endregion
#region
/// <summary>
/// 同步车辆参数到渲染插件
/// 首先尝试从 PathPlanningManager 获取,如果不可用则尝试从 PathEditingViewModel 获取
/// </summary>
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);
}
}
/// <summary>
/// 获取 PathEditingViewModel 实例
/// </summary>
/// <returns>PathEditingViewModel 实例或 null</returns>
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 #region
/// <summary> /// <summary>

View File

@ -146,7 +146,54 @@ NavisworksTransport 系统管理页签视图 - 采用与其他页签一致的Nav
ToolTip="显示门网格点50%透明绿色)"/> ToolTip="显示门网格点50%透明绿色)"/>
</StackPanel> </StackPanel>
</Grid> </Grid>
<!-- 路径可视化设置 -->
<Grid Margin="0,10,0,10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0"
Content="路径可视化:"
Style="{StaticResource ParameterLabelStyle}"
Width="100"
VerticalAlignment="Center"/>
<StackPanel Grid.Column="1"
Orientation="Vertical"
Margin="5,0,0,0">
<!-- 可视化模式选择 -->
<StackPanel Orientation="Horizontal" Margin="0,0,0,5">
<RadioButton Content="标准连线"
GroupName="PathVisualizationMode"
IsChecked="{Binding IsStandardLineMode}"
Margin="0,0,20,0"
VerticalAlignment="Center"
ToolTip="显示标准圆柱形连线"/>
<RadioButton Content="车辆通行空间"
GroupName="PathVisualizationMode"
IsChecked="{Binding IsVehicleSpaceMode}"
VerticalAlignment="Center"
ToolTip="显示车辆通行空间(矩形通道)"/>
</StackPanel>
<!-- 车辆高度模式选择 -->
<StackPanel Orientation="Horizontal" Margin="0,5,0,0">
<Label Content="高度模式:" Style="{StaticResource ParameterLabelStyle}" Width="70" VerticalAlignment="Center"/>
<RadioButton Content="固定高度"
GroupName="VehicleHeightMode"
IsChecked="{Binding IsFixedHeightMode}"
Margin="5,0,15,0"
VerticalAlignment="Center"
ToolTip="使用车辆高度+安全间隙"/>
<RadioButton Content="自动高度"
GroupName="VehicleHeightMode"
IsChecked="{Binding IsAutoHeightMode}"
VerticalAlignment="Center"
ToolTip="根据网格大小自动计算"/>
</StackPanel>
</StackPanel>
</Grid>
</StackPanel> </StackPanel>
</Border> </Border>