From 91c8f5c6f7cc398db1402d57a0fcbc845bdd2f66 Mon Sep 17 00:00:00 2001
From: tian <11429339@qq.com>
Date: Wed, 21 Jan 2026 15:01:13 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E9=80=9A=E8=A1=8C=E7=A9=BA?=
=?UTF-8?q?=E9=97=B4=E5=8F=82=E6=95=B0=E8=AE=BE=E7=BD=AE=EF=BC=8C=E7=BB=9F?=
=?UTF-8?q?=E4=B8=80=E4=BD=BF=E7=94=A8=E6=A8=A1=E5=9E=8B=E5=8D=95=E4=BD=8D?=
=?UTF-8?q?=EF=BC=8C=E8=B0=83=E6=95=B4=E6=97=A5=E5=BF=97=E8=BE=93=E5=87=BA?=
=?UTF-8?q?=E6=A0=BC=E5=BC=8F?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/Core/PathPointRenderPlugin.cs | 111 ++++++++++++------
.../ViewModels/AnimationControlViewModel.cs | 34 +++---
src/UI/WPF/ViewModels/PathEditingViewModel.cs | 28 +++--
3 files changed, 108 insertions(+), 65 deletions(-)
diff --git a/src/Core/PathPointRenderPlugin.cs b/src/Core/PathPointRenderPlugin.cs
index 20b709c..1592df5 100644
--- a/src/Core/PathPointRenderPlugin.cs
+++ b/src/Core/PathPointRenderPlugin.cs
@@ -1612,6 +1612,69 @@ namespace NavisworksTransport
var adjustedStartPoint = new Point3D(startPoint.Position.X, startPoint.Position.Y, startPoint.Position.Z + verticalOffset);
var adjustedEndPoint = new Point3D(endPoint.Position.X, endPoint.Position.Y, endPoint.Position.Z + verticalOffset);
+ // 暂时注释掉起点终点调整,先观察原始通行空间的误差
+ /*
+ // 通行空间模式下,调整起点和终点以包裹车辆
+ if (_visualizationMode == PathVisualizationMode.VehicleSpace)
+ {
+ bool needAdjust = false;
+ if (visualization.PathRoute.PathType == NavisworksTransport.PathType.Ground)
+ {
+ needAdjust = true;
+ }
+ else if (visualization.PathRoute.PathType == NavisworksTransport.PathType.Aerial &&
+ visualization.PathRoute.AerialSubType == AerialSubType.Rail)
+ {
+ needAdjust = true;
+ }
+
+ if (needAdjust)
+ {
+ // 调整起点:沿起点→第二个点的方向后退半个车辆长度
+ if (i == 0 && sortedPoints.Count >= 2)
+ {
+ var nextPoint = sortedPoints[1];
+ var dx = nextPoint.Position.X - startPoint.Position.X;
+ var dy = nextPoint.Position.Y - startPoint.Position.Y;
+ var dz = nextPoint.Position.Z - startPoint.Position.Z;
+ var length = Math.Sqrt(dx * dx + dy * dy + dz * dz);
+ LogManager.Info($"[通行空间调整] 起点: 原点=({startPoint.Position.X:F3},{startPoint.Position.Y:F3},{startPoint.Position.Z:F3}), 方向=({dx:F3},{dy:F3},{dz:F3}), 长度={length:F3}, _passageAlongPath={_passageAlongPath:F3}");
+ if (length > 0.001)
+ {
+ var offset = _passageAlongPath / 2.0;
+ adjustedStartPoint = new Point3D(
+ startPoint.Position.X - dx / length * offset,
+ startPoint.Position.Y - dy / length * offset,
+ startPoint.Position.Z - dz / length * offset + verticalOffset
+ );
+ LogManager.Info($"[通行空间调整] 调整后起点=({adjustedStartPoint.X:F3},{adjustedStartPoint.Y:F3},{adjustedStartPoint.Z:F3})");
+ }
+ }
+
+ // 调整终点:沿倒数第二个点→终点的方向前进半个车辆长度
+ if (i == sortedPoints.Count - 2 && sortedPoints.Count >= 2)
+ {
+ var prevPoint = sortedPoints[i];
+ var dx = endPoint.Position.X - prevPoint.Position.X;
+ var dy = endPoint.Position.Y - prevPoint.Position.Y;
+ var dz = endPoint.Position.Z - prevPoint.Position.Z;
+ var length = Math.Sqrt(dx * dx + dy * dy + dz * dz);
+ LogManager.Info($"[通行空间调整] 终点: 原点=({endPoint.Position.X:F3},{endPoint.Position.Y:F3},{endPoint.Position.Z:F3}), 方向=({dx:F3},{dy:F3},{dz:F3}), 长度={length:F3}, _passageAlongPath={_passageAlongPath:F3}");
+ if (length > 0.001)
+ {
+ var offset = _passageAlongPath / 2.0;
+ adjustedEndPoint = new Point3D(
+ endPoint.Position.X + dx / length * offset,
+ endPoint.Position.Y + dy / length * offset,
+ endPoint.Position.Z + dz / length * offset + verticalOffset
+ );
+ LogManager.Info($"[通行空间调整] 调整后终点=({adjustedEndPoint.X:F3},{adjustedEndPoint.Y:F3},{adjustedEndPoint.Z:F3})");
+ }
+ }
+ }
+ }
+ */
+
var lineMarker = new LineMarker
{
StartPoint = adjustedStartPoint,
@@ -1689,22 +1752,13 @@ namespace NavisworksTransport
/// 车辆通行空间标记
private VehicleSpaceMarker CreateVehicleSpaceMarker(PathPoint fromPoint, PathPoint toPoint)
{
- // 获取单位转换系数
- double metersToModelUnits = UnitsConverter.GetMetersToUnitsConversionFactor();
-
- // 计算车辆通行空间垂直于路径方向的尺寸(米)
- double vehicleInflationAcrossPathInMeters = _passageAcrossPath;
-
- // 计算车辆通行空间法线方向的尺寸(米)
- double vehicleSpaceNormalToPathInMeters = _passageNormalToPath;
-
var style = GetRenderStyle(RenderStyleName.VehicleSpace);
return new VehicleSpaceMarker
{
StartPoint = fromPoint.Position,
EndPoint = toPoint.Position,
- Width = vehicleInflationAcrossPathInMeters * metersToModelUnits, // 转换为模型单位
- Height = vehicleSpaceNormalToPathInMeters * metersToModelUnits, // 转换为模型单位
+ Width = _passageAcrossPath, // 直接使用模型单位
+ Height = _passageNormalToPath, // 直接使用模型单位
Color = style.Color, // 车辆通行空间颜色
Alpha = style.Alpha, // 透明度,统一管理
FromIndex = fromPoint.Index,
@@ -1804,17 +1858,17 @@ namespace NavisworksTransport
/// 车辆宽度(米)
/// 车辆高度(米)
/// 安全间隙(米)
- /// 垂直段的高度(物体长度 + 2×安全间隙,米)
- /// 水平段的高度(物体高度 + 2×安全间隙,米)
- public void SetPassageSpaceParameters(double passageAcrossPath, double passageNormalToPath, double passageAlongPath,double passageNormalToPathVertical = 0, double passageNormalToPathHorizontal = 0)
+ /// 垂直段的高度(物体长度 + 2×安全间隙,模型单位)
+ /// 水平段的高度(物体高度 + 2×安全间隙,模型单位)
+ public void SetPassageSpaceParameters(double passageAcrossPath, double passageNormalToPath, double passageAlongPath, double passageNormalToPathVertical = 0, double passageNormalToPathHorizontal = 0)
{
- _passageAlongPath = passageAlongPath; // 通行空间沿路径方向的尺寸(已包括安全间隙,暂不使用)
- _passageAcrossPath = passageAcrossPath; // 通行空间垂直于路径方向的尺寸(已包括安全间隙)
- _passageNormalToPath = passageNormalToPath; // 通行空间法线方向的尺寸(已包括安全间隙,默认值)
+ _passageAlongPath = passageAlongPath; // 通行空间沿路径方向的尺寸(模型单位)
+ _passageAcrossPath = passageAcrossPath; // 通行空间垂直于路径方向的尺寸(模型单位)
+ _passageNormalToPath = passageNormalToPath; // 通行空间法线方向的尺寸(模型单位)
// 保存垂直段和水平段的高度(用于吊装路径分段渲染)
- _objectLength = passageNormalToPathVertical; // 垂直段高度
- _objectHeight = passageNormalToPathHorizontal; // 水平段高度
+ _objectLength = passageNormalToPathVertical; // 垂直段高度(模型单位)
+ _objectHeight = passageNormalToPathHorizontal; // 水平段高度(模型单位)
// 参数改变时刷新所有普通路径(因为RibbonLine模式也使用车辆宽度)
RefreshNormalPaths();
@@ -2475,25 +2529,6 @@ namespace NavisworksTransport
}
}
- ///
- /// 渲染车辆通行空间(矩形通道)- 使用Cuboid API简化实现
- ///
- /// 图形上下文
- /// 车辆通行空间标记
- private void RenderVehicleSpace(Graphics graphics, VehicleSpaceMarker vehicleSpace)
- {
- var style = GetRenderStyle(RenderStyleName.VehicleSpace);
- // 设置颜色和透明度
- graphics.Color(vehicleSpace.Color, vehicleSpace.Alpha);
- RenderCuboidMarker(
- graphics,
- vehicleSpace.StartPoint,
- vehicleSpace.EndPoint,
- vehicleSpace.Width,
- vehicleSpace.Height
- );
- }
-
///
/// 渲染长方体标记(指定长度)
///
diff --git a/src/UI/WPF/ViewModels/AnimationControlViewModel.cs b/src/UI/WPF/ViewModels/AnimationControlViewModel.cs
index 9656ff8..bf49c6c 100644
--- a/src/UI/WPF/ViewModels/AnimationControlViewModel.cs
+++ b/src/UI/WPF/ViewModels/AnimationControlViewModel.cs
@@ -645,6 +645,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
///
/// 设置虚拟车辆参数(由主ViewModel调用)
+ /// 参数单位:模型单位
///
public void SetVirtualVehicleParameters(double length, double width, double height, double safetyMargin)
{
@@ -653,7 +654,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
VirtualVehicleHeight = height;
SafetyMargin = safetyMargin;
- LogManager.Info($"[AnimationControlViewModel] 虚拟车辆参数已更新: {length:F1}m × {width:F1}m × {height:F1}m, 检测间隙: {safetyMargin:F2}m");
+ LogManager.Info($"[AnimationControlViewModel] 虚拟车辆参数已更新: {length:F1}模型单位 × {width:F1}模型单位 × {height:F1}模型单位, 检测间隙: {safetyMargin:F2}模型单位");
// 如果当前使用虚拟车辆模式,更新生成动画的可用状态
if (UseVirtualVehicle)
@@ -918,20 +919,22 @@ namespace NavisworksTransport.UI.WPF.ViewModels
HasClashDetectiveResults = false;
UpdateMainStatus("碰撞检测就绪");
- // 从配置读取碰撞检测参数
- DetectionGap = config.Animation.DetectionGapMeters;
- AnimationFrameRate = config.Animation.FrameRate;
-
- // 🔥 从配置加载虚拟车辆尺寸(与路径编辑保持一致)
- VirtualVehicleLength = config.PathEditing.VehicleLengthMeters;
- VirtualVehicleWidth = config.PathEditing.VehicleWidthMeters;
- VirtualVehicleHeight = config.PathEditing.VehicleHeightMeters;
-
- // 设置动画按钮的初始状态
- UpdateAnimationButtonStates();
-
- LogManager.Info($"动画设置初始化完成 - 帧率:{SelectedFrameRate}fps, 持续时间:{AnimationDuration}秒, 检测间隙:{DetectionGap}米");
- }
+ // 获取单位转换系数
+ double metersToModelUnits = UnitsConverter.GetMetersToUnitsConversionFactor();
+
+ // 从配置读取碰撞检测参数(转换为模型单位)
+ DetectionGap = config.Animation.DetectionGapMeters * metersToModelUnits;
+ AnimationFrameRate = config.Animation.FrameRate;
+
+ // 🔥 从配置加载虚拟车辆尺寸(与路径编辑保持一致,转换为模型单位)
+ VirtualVehicleLength = config.PathEditing.VehicleLengthMeters * metersToModelUnits;
+ VirtualVehicleWidth = config.PathEditing.VehicleWidthMeters * metersToModelUnits;
+ VirtualVehicleHeight = config.PathEditing.VehicleHeightMeters * metersToModelUnits;
+
+ // 设置动画按钮的初始状态
+ UpdateAnimationButtonStates();
+
+ LogManager.Info($"动画设置初始化完成 - 帧率:{SelectedFrameRate}fps, 持续时间:{AnimationDuration}秒, 检测间隙:{DetectionGap}模型单位"); }
///
/// 初始化命令
@@ -2679,7 +2682,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
passageAcrossPath = effectiveWidth + 2 * safetyMargin; // 旋转后宽度 + 2*间隙(垂直于路径方向)
passageNormalToPath = sizeZ + 2 * safetyMargin; // Z方向(高度)+ 2*间隙(法线方向,上下都加)
passageAlongPath = effectiveLength; // 旋转后长度(沿路径方向)
- // 空轨路径不需要分段参数
passageNormalToPathVertical = passageNormalToPath;
passageNormalToPathHorizontal = passageNormalToPath;
LogManager.Info($"[通行空间可视化] 空轨路径使用物体尺寸 ({SelectedAnimatedObject.DisplayName}): 有效长度={effectiveLength:F2}m, 有效宽度={effectiveWidth:F2}m, 通行空间沿路径={passageAlongPath:F2}m, 垂直路径={passageAcrossPath:F2}m, 法线={passageNormalToPath:F2}m");
diff --git a/src/UI/WPF/ViewModels/PathEditingViewModel.cs b/src/UI/WPF/ViewModels/PathEditingViewModel.cs
index 78b55e4..ff3a4cd 100644
--- a/src/UI/WPF/ViewModels/PathEditingViewModel.cs
+++ b/src/UI/WPF/ViewModels/PathEditingViewModel.cs
@@ -790,14 +790,17 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
var config = ConfigManager.Instance.Current;
- // 从 PathEditing 配置加载所有参数
- _gridSize = config.PathEditing.CellSizeMeters;
- _vehicleLength = config.PathEditing.VehicleLengthMeters;
- _vehicleWidth = config.PathEditing.VehicleWidthMeters;
- _vehicleHeight = config.PathEditing.VehicleHeightMeters;
- _safetyMargin = config.PathEditing.SafetyMarginMeters;
+ // 获取单位转换系数
+ double metersToModelUnits = UnitsConverter.GetMetersToUnitsConversionFactor();
- LogManager.Info($"从配置加载参数 - 车辆: {_vehicleLength:F1}x{_vehicleWidth:F1}x{_vehicleHeight:F1}米, 安全间隙: {_safetyMargin:F2}米, 网格: {_gridSize:F1}米");
+ // 从 PathEditing 配置加载所有参数(转换为模型单位)
+ _gridSize = config.PathEditing.CellSizeMeters * metersToModelUnits;
+ _vehicleLength = config.PathEditing.VehicleLengthMeters * metersToModelUnits;
+ _vehicleWidth = config.PathEditing.VehicleWidthMeters * metersToModelUnits;
+ _vehicleHeight = config.PathEditing.VehicleHeightMeters * metersToModelUnits;
+ _safetyMargin = config.PathEditing.SafetyMarginMeters * metersToModelUnits;
+
+ LogManager.Info($"从配置加载参数 - 车辆: {_vehicleLength:F1}x{_vehicleWidth:F1}x{_vehicleHeight:F1}模型单位, 安全间隙: {_safetyMargin:F2}模型单位, 网格: {_gridSize:F1}模型单位");
}
catch (Exception ex)
{
@@ -2758,7 +2761,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
if (PathPointRenderPlugin.Instance != null)
{
// 根据路径类型计算通行空间尺寸
- double passageAcrossPath, passageNormalToPath;
+ double passageAcrossPath, passageNormalToPath, passageAlongPath;
PathType pathType = SelectedPathRoute?.PathType ?? PathType.Ground;
if (pathType == PathType.Aerial)
@@ -2769,18 +2772,21 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 空轨路径:车辆水平悬挂,垂直于路径的截面包含车辆的宽度和高度
passageAcrossPath = VehicleWidth + 2 * SafetyMargin; // Y方向(宽度)+ 2*间隙(垂直于路径方向)
passageNormalToPath = VehicleHeight + 2 * SafetyMargin; // Z方向(高度)+ 2*间隙(法线方向)
+ passageAlongPath = VehicleLength; // X方向(长度)(沿路径方向)
}
else if (SelectedPathRoute?.AerialSubType == AerialSubType.ThreeStepHoisting)
{
// 吊装路径:车辆垂直悬挂,垂直于路径的截面包含车辆的长度和宽度
passageAcrossPath = VehicleWidth + 2 * SafetyMargin; // Y方向(宽度)+ 2*间隙(垂直于路径方向)
passageNormalToPath = VehicleLength + 2 * SafetyMargin; // X方向(长度)+ 2*间隙(法线方向)
+ passageAlongPath = VehicleHeight; // Z方向(高度)(沿路径方向)
}
else
{
// 默认:使用宽度和高度
passageAcrossPath = VehicleWidth + 2 * SafetyMargin;
passageNormalToPath = VehicleHeight + 2 * SafetyMargin;
+ passageAlongPath = VehicleLength;
}
}
else // Ground
@@ -2788,10 +2794,10 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 地面路径:高度只有上方加间隙
passageAcrossPath = VehicleWidth + 2 * SafetyMargin; // Y方向(宽度)+ 2*间隙(垂直于路径方向)
passageNormalToPath = VehicleHeight + SafetyMargin; // Z方向(高度)+ 间隙(法线方向,只有上方)
+ passageAlongPath = VehicleLength; // X方向(长度)(沿路径方向)
}
// 设置通行空间参数到渲染插件
- // passageAlongPath: 沿路径方向的尺寸(由路径长度决定,不需要设置)
// passageNormalToPathVertical: 垂直段的高度(物体长度 + 2×安全间隙)
// passageNormalToPathHorizontal: 水平段的高度(物体高度 + 2×安全间隙)
double passageNormalToPathVertical = VehicleLength + 2 * SafetyMargin;
@@ -2799,10 +2805,10 @@ namespace NavisworksTransport.UI.WPF.ViewModels
PathPointRenderPlugin.Instance.SetPassageSpaceParameters(
passageAcrossPath,
passageNormalToPath,
- 0,
+ passageAlongPath,
passageNormalToPathVertical,
passageNormalToPathHorizontal);
- LogManager.Debug($"[车辆参数同步] 已设置通行空间参数: 垂直路径={passageAcrossPath:F2}m, 法线={passageNormalToPath:F2}m, 间隙={SafetyMargin:F2}m");
+ LogManager.Debug($"[车辆参数同步] 已设置通行空间参数: 垂直路径={passageAcrossPath:F2}m, 法线={passageNormalToPath:F2}m, 沿路径={passageAlongPath:F2}m, 间隙={SafetyMargin:F2}m");
}
else
{