优化通行空间参数设置逻辑,动态根据路径类型调整通行空间尺寸

This commit is contained in:
tian 2026-01-18 21:57:02 +08:00
parent 405ea5ac7c
commit a52d8fdacb
6 changed files with 128 additions and 130 deletions

View File

@ -410,7 +410,24 @@ namespace NavisworksTransport.Core.Animation
}
// 计算朝向(使用前两个路径点的方向)
double yaw = Math.Atan2(_pathPoints[1].Y - _pathPoints[0].Y, _pathPoints[1].X - _pathPoints[0].X);
// 🔥 让物体的宽度方向Y轴朝向路径方向而不是长度方向X轴
// 因为通行空间的宽度使用车辆的宽度,所以宽度方向应该朝向路径
double pathDirectionYaw = Math.Atan2(_pathPoints[1].Y - _pathPoints[0].Y, _pathPoints[1].X - _pathPoints[0].X);
double yaw;
// 根据路径类型调整朝向
if (_route?.PathType == PathType.Hoisting)
{
// 吊装路径保持物体的原始旋转角度不旋转90度
yaw = _currentYaw;
LogManager.Debug($"[移动到起点] 吊装路径保持物体原始旋转角度: {yaw * 180 / Math.PI:F2}度");
}
else
{
// 地面路径和空轨旋转90度让Y轴朝向路径方向
yaw = pathDirectionYaw + Math.PI / 2.0;
LogManager.Debug($"[移动到起点] 地面/空轨路径旋转90度Y轴朝向路径方向: {yaw * 180 / Math.PI:F2}度");
}
// 根据路径类型调整起点位置
Point3D startPosition = _pathPoints[0];

View File

@ -206,20 +206,9 @@ namespace NavisworksTransport
_renderPlugin.SetGridSize(gridSizeInMeters);
LogManager.Info($"[渲染插件初始化] 已设置网格大小: {gridSizeInMeters}米(来自配置)");
// 从配置读取车辆参数
double vehicleLength = config.PathEditing.VehicleLengthMeters;
double vehicleWidth = config.PathEditing.VehicleWidthMeters;
double vehicleHeight = config.PathEditing.VehicleHeightMeters;
double safetyMargin = config.PathEditing.SafetyMarginMeters;
_renderPlugin.SetVehicleParameters(
vehicleLength,
vehicleWidth,
vehicleHeight,
safetyMargin
);
LogManager.Info($"[渲染插件初始化] 已设置车辆参数: 长={vehicleLength:F1}m, 宽={vehicleWidth:F1}m, 高={vehicleHeight:F1}m, 安全间隙={safetyMargin:F2}m来自配置");
// 通行空间参数将在UpdatePassageSpaceViewModel中根据路径类型动态设置
// 这里不设置默认值,因为不同路径类型的坐标系不同
LogManager.Info($"[渲染插件初始化] 通行空间参数将在使用时动态设置");
}
catch (Exception ex)
{

View File

@ -382,11 +382,10 @@ namespace NavisworksTransport
// 网格点类型配置
private GridPointType _gridPointType = GridPointType.Rectangle;
// 车辆参数必须通过SetVehicleParameters方法设置
private double _vehicleLength;
private double _vehicleWidth;
private double _vehicleHeight;
private double _safetyMargin;
// 通行空间参数(最终尺寸,已包括安全间隙)
private double _passageWidth; // 通行空间宽度(垂直于路径方向)
private double _passageHeight; // 通行空间高度(垂直于路径和宽度)
private double _passageLength; // 通行空间长度(沿路径方向,可能不使用)
// 静态实例,用于外部访问
private static PathPointRenderPlugin _instance;
@ -566,7 +565,7 @@ namespace NavisworksTransport
// 再渲染路径连线
foreach (var pathLineMarker in visualization.PathLineMarkers)
{
RenderRibbonLineMarker(graphics, pathLineMarker);
RenderLineMarker(graphics, pathLineMarker);
}
}
else
@ -1352,20 +1351,9 @@ namespace NavisworksTransport
if (_visualizationMode == PathVisualizationMode.VehicleSpace)
{
// VehicleSpace 模式:使用车辆高度和宽度
// 根据路径类型调整参数
if (visualization.PathRoute.PathType == NavisworksTransport.PathType.Hoisting)
{
// 吊装路径:通行空间截面使用车辆的宽度和长度(不是高度)
heightInMeters = _vehicleLength + _safetyMargin; // Y方向使用车辆长度
widthInMeters = _vehicleWidth + 2 * _safetyMargin; // X方向使用车辆宽度
}
else
{
// 地面路径和空轨:使用最大宽度和高度
heightInMeters = _vehicleHeight + _safetyMargin;
widthInMeters = _vehicleWidth + 2 * _safetyMargin;
}
// VehicleSpace 模式:直接使用已计算的通行空间尺寸(已包括安全间隙)
heightInMeters = _passageHeight;
widthInMeters = _passageWidth;
var renderStyle = GetRenderStyle(RenderStyleName.VehicleSpace);
lineColor = renderStyle.Color;
lineOpacity = renderStyle.Alpha;
@ -1374,12 +1362,11 @@ namespace NavisworksTransport
{
// RibbonLine 模式:使用较低的带状高度
heightInMeters = GetLineRadius() / metersToModelUnits * 0.1;
widthInMeters = _vehicleWidth; // 使用车辆宽度(与通行空间逻辑一致)
widthInMeters = _passageWidth; // 使用通行空间宽度
var renderStyle = GetRenderStyle(RenderStyleName.Line);
lineColor = renderStyle.Color;
lineOpacity = renderStyle.Alpha;
}
else
} else
{
// StandardLine 模式:不需要高度和宽度(圆柱体)
heightInMeters = 0;
@ -1461,7 +1448,7 @@ namespace NavisworksTransport
// 记录日志
if (_visualizationMode == PathVisualizationMode.VehicleSpace)
{
LogManager.Info($"[通行空间渲染] {visualization.PathRoute.PathType}路径: 车辆参数(长×宽×高)={_vehicleLength:F2}×{_vehicleWidth:F2}×{_vehicleHeight:F2}m, 安全间隙={_safetyMargin:F2}m, 通行空间截面(宽×高)={widthInModelUnits/metersToModelUnits:F2}×{heightInModelUnits/metersToModelUnits:F2}m");
LogManager.Info($"[通行空间渲染] {visualization.PathRoute.PathType}路径: 通行空间截面(宽×高)={_passageWidth:F2}×{_passageHeight:F2}m");
}
// 3. 构建路径连线Edges包含直线段和圆弧段
@ -1572,7 +1559,7 @@ namespace NavisworksTransport
// 记录日志
if (_visualizationMode == PathVisualizationMode.VehicleSpace)
{
LogManager.Info($"[通行空间渲染] {visualization.PathRoute.PathType}路径(直接连线): 车辆参数(长×宽×高)={_vehicleLength:F2}×{_vehicleWidth:F2}×{_vehicleHeight:F2}m, 安全间隙={_safetyMargin:F2}m, 通行空间截面(宽×高)={widthInModelUnits/metersToModelUnits:F2}×{heightInModelUnits/metersToModelUnits:F2}m");
LogManager.Info($"[通行空间渲染] {visualization.PathRoute.PathType}路径(直接连线): 通行空间截面(宽×高)={_passageWidth:F2}×{_passageHeight:F2}m");
}
// 直接使用路径点构建直线连线
@ -1665,10 +1652,10 @@ namespace NavisworksTransport
double metersToModelUnits = UnitsConverter.GetMetersToUnitsConversionFactor();
// 计算车辆通行空间宽度(米)
double vehicleInflationWidthInMeters = Math.Max(_vehicleLength, _vehicleWidth) + 2 * _safetyMargin;
double vehicleInflationWidthInMeters = _passageWidth;
// 计算车辆通行空间高度(米):车辆高度 + 安全间隙
double vehicleSpaceHeightInMeters = _vehicleHeight + _safetyMargin;
// 计算车辆通行空间高度(米)
double vehicleSpaceHeightInMeters = _passageHeight;
var style = GetRenderStyle(RenderStyleName.VehicleSpace);
return new VehicleSpaceMarker
@ -1776,14 +1763,13 @@ namespace NavisworksTransport
/// <param name="vehicleWidth">车辆宽度(米)</param>
/// <param name="vehicleHeight">车辆高度(米)</param>
/// <param name="safetyMargin">安全间隙(米)</param>
public void SetVehicleParameters(double vehicleLength, double vehicleWidth, double vehicleHeight, double safetyMargin)
public void SetVehicleParameters(double passageWidth, double passageHeight, double passageLength, double safetyMargin)
{
_vehicleLength = vehicleLength;
_vehicleWidth = vehicleWidth;
_vehicleHeight = vehicleHeight;
_safetyMargin = safetyMargin;
_passageWidth = passageWidth; // 通行空间宽度(已包括安全间隙)
_passageHeight = passageHeight; // 通行空间高度(已包括安全间隙)
_passageLength = passageLength; // 通行空间长度
// 车辆参数改变时刷新所有普通路径因为RibbonLine模式也使用车辆宽度
// 参数改变时刷新所有普通路径因为RibbonLine模式也使用车辆宽度
RefreshNormalPaths();
}
@ -2481,7 +2467,7 @@ namespace NavisworksTransport
// 计算垂直向量在XY平面内垂直于方向向量
var right = new Vector3D(-direction.Y, direction.X, 0);
// 如果方向向量垂直于XY平面则使用不同的right向量
// 如果方向向量垂直于XY平面(吊装路径)则使用不同的right向量
if (Math.Abs(direction.Z) > 0.9)
{
right = new Vector3D(1, 0, 0);

View File

@ -258,10 +258,11 @@ namespace NavisworksTransport.Core
// 🔥 对于虚拟车辆,直接应用缩放比例(不动态读取当前尺寸)
// 原因:虚拟车辆可能被旋转,导致包围盒尺寸不准确
// 单位立方体是 0.01m × 0.01m × 0.01m
// X方向 = 车辆宽度Y方向 = 车辆长度Z方向 = 车辆高度
double baseSizeMeters = 0.01;
double scaleX = lengthMeters / baseSizeMeters;
double scaleY = widthMeters / baseSizeMeters;
double scaleZ = heightMeters / baseSizeMeters;
double scaleX = widthMeters / baseSizeMeters; // X方向 = 车辆宽度
double scaleY = lengthMeters / baseSizeMeters; // Y方向 = 车辆长度
double scaleZ = heightMeters / baseSizeMeters; // Z方向 = 车辆高度
LogManager.Info($"目标尺寸: {lengthMeters:F2}m × {widthMeters:F2}m × {heightMeters:F2}m");
LogManager.Info($"缩放比例: X={scaleX:F2}, Y={scaleY:F2}, Z={scaleZ:F2}");

View File

@ -2413,94 +2413,101 @@ namespace NavisworksTransport.UI.WPF.ViewModels
var renderPlugin = PathPointRenderPlugin.Instance;
if (renderPlugin == null)
{
LogManager.Warning("[通行空间可视化] 无法获取PathPointRenderPlugin实例");
return;
throw new InvalidOperationException("[通行空间可视化] 无法获取PathPointRenderPlugin实例");
}
// 获取车辆尺寸(米)
double vehicleLength, vehicleWidth, vehicleHeight;
// 计算通行空间尺寸(米)
double passageWidth, passageHeight, passageLength;
// 获取安全间隙(从配置)
var config = Core.Config.ConfigManager.Instance?.Current;
if (config == null)
{
throw new InvalidOperationException("[通行空间可视化] 无法获取配置文件");
}
double safetyMargin = config.PathEditing.SafetyMarginMeters;
if (UseVirtualVehicle)
{
// 使用虚拟车辆尺寸,但需要根据路径类型调整
// 虚拟车辆的xy定义X方向 = 宽度1.0mY方向 = 长度1.2mZ方向 = 高度2.0m
if (CurrentPathRoute.PathType == NavisworksTransport.PathType.Hoisting)
{
// 吊装路径:通行空间截面使用车辆的宽度和长度(不是高度)
vehicleWidth = VirtualVehicleWidth; // X方向
vehicleHeight = VirtualVehicleLength; // Y方向使用车辆长度
vehicleLength = VirtualVehicleLength; // 保持虚拟车辆长度不变
LogManager.Info($"[通行空间可视化] 吊装路径使用虚拟车辆尺寸: 宽×高={vehicleWidth:F2}×{vehicleHeight:F2}m");
// 吊装路径:通行空间截面使用车辆的X和Y方向尺寸四周都加上检测间隙
passageWidth = VirtualVehicleWidth + 2 * safetyMargin; // X方向 + 2*间隙
passageHeight = VirtualVehicleLength + 2 * safetyMargin; // Y方向 + 2*间隙
passageLength = VirtualVehicleLength; // 不使用,保持一致
LogManager.Info($"[通行空间可视化] 吊装路径使用虚拟车辆尺寸: X方向={VirtualVehicleWidth:F2}m, Y方向={VirtualVehicleLength:F2}m, 通行空间宽×高={passageWidth:F2}×{passageHeight:F2}m");
}
else
else if (CurrentPathRoute.PathType == NavisworksTransport.PathType.Ground)
{
// 地面路径和空轨:使用虚拟车辆的宽度和高度
vehicleWidth = VirtualVehicleWidth; // 通行空间宽度 = 车辆宽度(垂直于路径方向)
vehicleHeight = VirtualVehicleHeight; // 通行空间高度 = 车辆高度
vehicleLength = VirtualVehicleLength; // 车辆长度(沿路径方向)
LogManager.Info($"[通行空间可视化] 地面/空轨路径使用虚拟车辆尺寸: 通行空间宽×高={vehicleWidth:F2}×{vehicleHeight:F2}m, 车辆长度={vehicleLength:F2}m");
// 地面路径物体的宽度方向Y轴朝向路径方向
// 通行空间宽度 = X方向尺寸垂直于路径方向高度上方加间隙下方不需要因为有地面
passageWidth = VirtualVehicleWidth + 2 * safetyMargin; // X方向 + 2*间隙
passageHeight = VirtualVehicleHeight + safetyMargin; // Z方向 + 间隙(只有上方)
passageLength = VirtualVehicleLength; // Y方向 = 长度1.2m
LogManager.Info($"[通行空间可视化] 地面路径使用虚拟车辆尺寸: X方向={VirtualVehicleWidth:F2}m, Y方向={VirtualVehicleLength:F2}m, 通行空间宽度={passageWidth:F2}m, 高度={passageHeight:F2}m");
}
else // Rail
{
// 空轨路径物体的宽度方向Y轴朝向路径方向
// 通行空间宽度 = X方向尺寸垂直于路径方向高度上下都加间隙在空中
passageWidth = VirtualVehicleWidth + 2 * safetyMargin; // X方向 + 2*间隙
passageHeight = VirtualVehicleHeight + 2 * safetyMargin; // Z方向 + 2*间隙(上下都加)
passageLength = VirtualVehicleLength; // Y方向 = 长度1.2m
LogManager.Info($"[通行空间可视化] 空轨路径使用虚拟车辆尺寸: X方向={VirtualVehicleWidth:F2}m, Y方向={VirtualVehicleLength:F2}m, 通行空间宽度={passageWidth:F2}m, 高度={passageHeight:F2}m");
}
}
else if (SelectedAnimatedObject != null)
{
// 使用选择物体的包围盒尺寸
try
{
var bbox = SelectedAnimatedObject.BoundingBox();
double metersToModelUnits = UnitsConverter.GetMetersToUnitsConversionFactor();
// 使用选择物体的包围盒尺寸
var bbox = SelectedAnimatedObject.BoundingBox();
double metersToModelUnits = UnitsConverter.GetMetersToUnitsConversionFactor();
// 将模型单位转换为米
double sizeX = (bbox.Max.X - bbox.Min.X) / metersToModelUnits;
double sizeY = (bbox.Max.Y - bbox.Min.Y) / metersToModelUnits;
double sizeZ = (bbox.Max.Z - bbox.Min.Z) / metersToModelUnits;
// 将模型单位转换为米
double sizeX = (bbox.Max.X - bbox.Min.X) / metersToModelUnits;
double sizeY = (bbox.Max.Y - bbox.Min.Y) / metersToModelUnits;
double sizeZ = (bbox.Max.Z - bbox.Min.Z) / metersToModelUnits;
// 根据路径类型确定车辆的长度、宽度、高度
if (CurrentPathRoute.PathType == NavisworksTransport.PathType.Hoisting)
{
// 吊装路径(严格垂直路径):
// 通行空间截面使用物体的长度和宽度
double objectLength = Math.Max(sizeX, sizeY);
double objectWidth = Math.Min(sizeX, sizeY);
vehicleWidth = objectWidth; // 通行空间宽度 = 物体宽度
vehicleHeight = objectLength; // 通行空间高度 = 物体长度
vehicleLength = sizeZ; // 物体Z尺寸
LogManager.Info($"[通行空间可视化] 吊装路径使用物体尺寸 ({SelectedAnimatedObject.DisplayName}): 物体长×宽={objectLength:F2}×{objectWidth:F2}m, 通行空间宽×高={vehicleWidth:F2}×{vehicleHeight:F2}m");
}
else
{
// 地面路径和空轨(可能有坡度):
// 使用物体的实际尺寸(不考虑朝向)
double objectLength = Math.Max(sizeX, sizeY);
double objectWidth = Math.Min(sizeX, sizeY);
vehicleWidth = objectWidth; // 通行空间宽度 = 物体宽度
vehicleHeight = sizeZ; // 通行空间高度 = 物体高度
vehicleLength = objectLength; // 车辆长度 = 物体长度
LogManager.Info($"[通行空间可视化] 地面/空轨路径使用物体尺寸 ({SelectedAnimatedObject.DisplayName}): 物体长×宽={objectLength:F2}×{objectWidth:F2}m, 通行空间宽×高={vehicleWidth:F2}×{vehicleHeight:F2}m");
}
}
catch (Exception ex)
{
LogManager.Warning($"[通行空间可视化] 获取物体包围盒失败: {ex.Message},使用默认尺寸");
vehicleLength = 1.0;
vehicleWidth = 1.0;
vehicleHeight = 2.0;
}
}
else
{
// 没有选择物体,使用默认尺寸
vehicleLength = 1.0;
vehicleWidth = 1.0;
vehicleHeight = 2.0;
LogManager.Info("[通行空间可视化] 使用默认车辆尺寸: 1.0×1.0×2.0m");
}
// 根据路径类型确定通行空间的尺寸
if (CurrentPathRoute.PathType == NavisworksTransport.PathType.Hoisting)
{
// 吊装路径(严格垂直路径):
// 通行空间截面使用物体的X和Y尺寸四周都加上检测间隙
passageWidth = sizeX + 2 * safetyMargin; // X方向 + 2*间隙
passageHeight = sizeY + 2 * safetyMargin; // Y方向 + 2*间隙
passageLength = sizeZ; // 不使用,保持一致
LogManager.Info($"[通行空间可视化] 吊装路径使用物体尺寸 ({SelectedAnimatedObject.DisplayName}): X方向={sizeX:F2}m, Y方向={sizeY:F2}m, 通行空间宽×高={passageWidth:F2}×{passageHeight:F2}m");
}
else if (CurrentPathRoute.PathType == NavisworksTransport.PathType.Ground)
{
// 地面路径(可能有坡度):
// 物体的宽度方向Y轴朝向路径方向
// 通行空间宽度 = X方向尺寸垂直于路径方向高度上方加间隙下方不需要因为有地面
passageWidth = sizeX + 2 * safetyMargin; // X方向 + 2*间隙
passageHeight = sizeZ + safetyMargin; // Z方向 + 间隙(只有上方)
passageLength = sizeY; // 不使用,保持一致
LogManager.Info($"[通行空间可视化] 地面路径使用物体尺寸 ({SelectedAnimatedObject.DisplayName}): X方向={sizeX:F2}m, Y方向={sizeY:F2}m, 通行空间宽度={passageWidth:F2}m, 高度={passageHeight:F2}m");
}
else // Rail
{
// 空轨路径(可能有坡度):
// 物体的宽度方向Y轴朝向路径方向
// 通行空间宽度 = X方向尺寸垂直于路径方向高度上下都加间隙在空中
passageWidth = sizeX + 2 * safetyMargin; // X方向 + 2*间隙
passageHeight = sizeZ + 2 * safetyMargin; // Z方向 + 2*间隙(上下都加)
passageLength = sizeY; // 不使用,保持一致
LogManager.Info($"[通行空间可视化] 空轨路径使用物体尺寸 ({SelectedAnimatedObject.DisplayName}): X方向={sizeX:F2}m, Y方向={sizeY:F2}m, 通行空间宽度={passageWidth:F2}m, 高度={passageHeight:F2}m");
}
}
else
{
// 默认就是使用虚拟车辆,如果既不使用虚拟车辆也没选择物体,说明配置错误
throw new InvalidOperationException("[通行空间可视化] 配置错误:既不使用虚拟车辆也没有选择物体");
}
// 获取安全间隙(从配置)
var config = Core.Config.ConfigManager.Instance?.Current;
double safetyMargin = config?.PathEditing?.SafetyMarginMeters ?? 0.05;
// 设置车辆参数到渲染插件所有路径类型都设置用于RibbonLine宽度等
renderPlugin.SetVehicleParameters(vehicleLength, vehicleWidth, vehicleHeight, safetyMargin);
LogManager.Info($"[通行空间可视化] 已设置车辆参数: {vehicleLength:F2}×{vehicleWidth:F2}×{vehicleHeight:F2}m, 安全间隙: {safetyMargin:F2}m");
// 设置通行空间参数到渲染插件所有路径类型都设置用于RibbonLine宽度等
renderPlugin.SetVehicleParameters(passageWidth, passageHeight, passageLength, safetyMargin);
LogManager.Info($"[通行空间可视化] 已设置通行空间参数: 宽={passageWidth:F2}m, 高={passageHeight:F2}m, 长={passageLength:F2}m, 安全间隙={safetyMargin:F2}m");
// 根据路径类型决定是否切换到车辆通行空间模式
bool enableVehicleSpace = false;

View File

@ -2579,11 +2579,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
if (PathPointRenderPlugin.Instance != null)
{
PathPointRenderPlugin.Instance.SetVehicleParameters(
VehicleLength,
VehicleWidth,
VehicleHeight,
SafetyMargin);
// 通行空间参数将在AnimationControlViewModel中根据路径类型动态设置
// 这里不设置通行空间参数,因为不同路径类型的坐标系不同
LogManager.Debug("[车辆参数同步] 跳过设置通行空间参数将在AnimationControlViewModel中根据路径类型动态设置");
}
else
{