diff --git a/default_config.toml b/default_config.toml index 61a2661..2efa628 100644 --- a/default_config.toml +++ b/default_config.toml @@ -8,14 +8,14 @@ cell_size_meters = 0.5 # 最大高度差(米)- 楼梯、坡道可接受的高度阈值 max_height_diff_meters = 0.35 -# 车辆长度(米) -vehicle_length_meters = 1.5 +# 运动物体长度(米) +object_length_meters = 1.5 -# 车辆宽度(米) -vehicle_width_meters = 1.0 +# 运动物体宽度(米) +object_width_meters = 1.0 -# 车辆高度(米) -vehicle_height_meters = 2.0 +# 运动物体高度(米) +object_height_meters = 2.0 # 安全间隙(米) safety_margin_meters = 0.1 diff --git a/src/Commands/AutoPathPlanningCommand.cs b/src/Commands/AutoPathPlanningCommand.cs index 58d7edc..6a43d23 100644 --- a/src/Commands/AutoPathPlanningCommand.cs +++ b/src/Commands/AutoPathPlanningCommand.cs @@ -24,19 +24,19 @@ namespace NavisworksTransport.Commands public Point3D EndPoint { get; set; } /// - /// 车辆长度(米) + /// 运动物体长度(米) /// - public double VehicleLength { get; set; } = 1.0; + public double ObjectLength { get; set; } = 1.0; /// - /// 车辆宽度(米) + /// 运动物体宽度(米) /// - public double VehicleWidth { get; set; } = 1.0; + public double ObjectWidth { get; set; } = 1.0; /// - /// 车辆高度(米) + /// 运动物体高度(米) /// - public double VehicleHeight { get; set; } = 2.0; + public double ObjectHeight { get; set; } = 2.0; /// /// 安全边距(米) @@ -76,13 +76,13 @@ namespace NavisworksTransport.Commands if (EndPoint == null) errors.Add("终点不能为空"); - if (VehicleLength <= 0 || VehicleLength > 20) + if (ObjectLength <= 0 || ObjectLength > 20) errors.Add("车辆长度必须在0-20米之间"); - if (VehicleWidth <= 0 || VehicleWidth > 10) + if (ObjectWidth <= 0 || ObjectWidth > 10) errors.Add("车辆宽度必须在0-10米之间"); - if (VehicleHeight <= 0 || VehicleHeight > 10) + if (ObjectHeight <= 0 || ObjectHeight > 10) errors.Add("车辆高度必须在0-10米之间"); if (SafetyMargin < 0 || SafetyMargin > 5) @@ -279,7 +279,7 @@ namespace NavisworksTransport.Commands var actualGridSize = _parameters.GridSize > 0 ? _parameters.GridSize : -1; LogInfo($"使用参数 - 起点: ({_parameters.StartPoint.X:F2}, {_parameters.StartPoint.Y:F2}), " + $"终点: ({_parameters.EndPoint.X:F2}, {_parameters.EndPoint.Y:F2}), " + - $"车辆宽度: {_parameters.VehicleWidth}米, 安全边距: {_parameters.SafetyMargin}米, " + + $"运动物体宽度: {_parameters.ObjectWidth}米, 安全边距: {_parameters.SafetyMargin}米, " + $"网格大小: {(actualGridSize > 0 ? $"用户设置 {actualGridSize:F2}米" : "自动选择")}"); // 第三阶段:执行路径规划(30% - 80%) @@ -309,17 +309,17 @@ namespace NavisworksTransport.Commands }; // 计算车辆半径:基于长度和宽度的较大值的一半 - var vehicleRadius = Math.Max(_parameters.VehicleLength, _parameters.VehicleWidth) / 2.0; - LogInfo($"使用车辆半径: {vehicleRadius}m(基于车辆长度{_parameters.VehicleLength}m和宽度{_parameters.VehicleWidth}m的较大值)"); + var objectRadius = Math.Max(_parameters.ObjectLength, _parameters.ObjectWidth) / 2.0; + LogInfo($"使用运动物体半径: {objectRadius}m(基于长度{_parameters.ObjectLength}m和宽度{_parameters.ObjectWidth}m的较大值)"); // 调用PathPlanningManager的AutoPlanPath方法执行真实的A*算法 var pathPlanTask = _pathPlanningManager.AutoPlanPath( startPathPoint, endPathPoint, - vehicleRadius, + objectRadius, _parameters.SafetyMargin, actualGridSize, - _parameters.VehicleHeight, // 使用参数中的车辆高度 + _parameters.ObjectHeight, // 使用参数中的运动物体高度 _parameters.Strategy); // 使用参数中指定的路径策略 generatedRoute = await pathPlanTask; @@ -454,21 +454,21 @@ namespace NavisworksTransport.Commands /// /// 起点 /// 终点 - /// 车辆尺寸(应用于长度和宽度) + /// 运动物体尺寸(应用于长度和宽度) /// 路径名称 - /// 车辆高度(可选,默认2.0米) + /// 运动物体高度(可选,默认2.0米) /// 路径策略(可选,默认最短路径) /// 自动路径规划命令实例 public static AutoPathPlanningCommand CreateQuick(Point3D startPoint, Point3D endPoint, - double vehicleSize = 1.0, string pathName = null, double vehicleHeight = 2.0, PathStrategy strategy = PathStrategy.Shortest) + double objectSize = 1.0, string pathName = null, double objectHeight = 2.0, PathStrategy strategy = PathStrategy.Shortest) { var parameters = new AutoPathPlanningParameters { StartPoint = startPoint, EndPoint = endPoint, - VehicleLength = vehicleSize, - VehicleWidth = vehicleSize, - VehicleHeight = vehicleHeight, + ObjectLength = objectSize, + ObjectWidth = objectSize, + ObjectHeight = objectHeight, SafetyMargin = 0.5, GridSize = -1, // 自动选择 PathName = pathName, @@ -487,7 +487,7 @@ namespace NavisworksTransport.Commands { return $"自动路径规划命令 - 起点:({_parameters.StartPoint?.X:F1}, {_parameters.StartPoint?.Y:F1}), " + $"终点:({_parameters.EndPoint?.X:F1}, {_parameters.EndPoint?.Y:F1}), " + - $"车辆尺寸:长{_parameters.VehicleLength}×宽{_parameters.VehicleWidth}×高{_parameters.VehicleHeight}米, " + + $"运动物体尺寸:长{_parameters.ObjectLength}×宽{_parameters.ObjectWidth}×高{_parameters.ObjectHeight}米, " + $"状态:{Status}"; } diff --git a/src/Commands/CommandManager.cs b/src/Commands/CommandManager.cs index 830ed90..35d389a 100644 --- a/src/Commands/CommandManager.cs +++ b/src/Commands/CommandManager.cs @@ -160,7 +160,7 @@ namespace NavisworksTransport.Commands { StartPoint = startPoint, EndPoint = endPoint, - VehicleWidth = args.Length > 2 && args[2] is double v ? v : 1.0, + ObjectWidth = args.Length > 2 && args[2] is double v ? v : 1.0, SafetyMargin = args.Length > 3 && args[3] is double v1 ? v1 : 0.5, GridSize = args.Length > 4 && args[4] is double v2 ? v2 : -1, PathName = args.Length > 5 ? args[5]?.ToString() : null, @@ -182,10 +182,10 @@ namespace NavisworksTransport.Commands if (startPoint == null || endPoint == null) throw new ArgumentException("起点和终点必须是 Point3D 类型"); - var vehicleSize = args.Length > 2 && args[2] is double v ? v : 1.0; + var objectSize = args.Length > 2 && args[2] is double v ? v : 1.0; var pathName = args.Length > 3 ? args[3]?.ToString() : null; - return AutoPathPlanningCommand.CreateQuick(startPoint, endPoint, vehicleSize, pathName); + return AutoPathPlanningCommand.CreateQuick(startPoint, endPoint, objectSize, pathName); }); // 注册模拟路径规划命令(保留用于测试)- 暂时注释掉避免类型推断问题 diff --git a/src/Commands/CreateAerialPathCommand.cs b/src/Commands/CreateAerialPathCommand.cs index 21e87a8..d7e53bc 100644 --- a/src/Commands/CreateAerialPathCommand.cs +++ b/src/Commands/CreateAerialPathCommand.cs @@ -82,9 +82,9 @@ namespace NavisworksTransport.Commands // 设置车辆参数(从配置获取) var config = ConfigManager.Instance.Current; - route.MaxVehicleLength = config.PathEditing.VehicleLengthMeters; - route.MaxVehicleWidth = config.PathEditing.VehicleWidthMeters; - route.MaxVehicleHeight = config.PathEditing.VehicleHeightMeters; + route.MaxObjectLength = config.PathEditing.ObjectLengthMeters; + route.MaxObjectWidth = config.PathEditing.ObjectWidthMeters; + route.MaxObjectHeight = config.PathEditing.ObjectHeightMeters; route.SafetyMargin = config.PathEditing.SafetyMarginMeters; // 计算总长度 diff --git a/src/Commands/VoxelGridSDFTestCommand.cs b/src/Commands/VoxelGridSDFTestCommand.cs index 9afd8a2..2c656fe 100644 --- a/src/Commands/VoxelGridSDFTestCommand.cs +++ b/src/Commands/VoxelGridSDFTestCommand.cs @@ -17,22 +17,22 @@ namespace NavisworksTransport.Commands private readonly Document _document; private readonly double _cellSize; private readonly int _samplingRate; - private readonly double _vehicleRadius; - private readonly double _vehicleHeight; + private readonly double _objectRadius; + private readonly double _objectHeight; public VoxelGridSDFTestCommand( Document document, double cellSize, int samplingRate, - double vehicleRadius, - double vehicleHeight) + double objectRadius, + double objectHeight) : base("VoxelGridSDFTest", "体素网格SDF测试", "使用签名距离场进行精确体素化") { _document = document ?? throw new ArgumentNullException(nameof(document)); _cellSize = cellSize; _samplingRate = samplingRate; - _vehicleRadius = vehicleRadius; - _vehicleHeight = vehicleHeight; + _objectRadius = objectRadius; + _objectHeight = objectHeight; } protected override PathPlanningResult ValidateParameters() @@ -56,8 +56,8 @@ namespace NavisworksTransport.Commands { LogInfo("=== 开始体素网格 SDF 测试 ==="); LogInfo($"体素大小: {_cellSize}米"); - LogInfo($"车辆半径: {_vehicleRadius}米"); - LogInfo($"车辆高度: {_vehicleHeight}米"); + LogInfo($"车辆半径: {_objectRadius}米"); + LogInfo($"车辆高度: {_objectHeight}米"); LogInfo($"采样率: {_samplingRate}"); UpdateProgress(5, "正在获取模型空间范围..."); @@ -90,8 +90,8 @@ namespace NavisworksTransport.Commands var voxelGrid = generator.GenerateFromBIMWithSDF( spaceBounds, _cellSize, - _vehicleRadius, - _vehicleHeight, + _objectRadius, + _objectHeight, allModelItems); LogInfo($"体素网格生成完成: {voxelGrid.SizeX}×{voxelGrid.SizeY}×{voxelGrid.SizeZ} = {voxelGrid.TotalVoxels} 个体素"); diff --git a/src/Commands/VoxelPathFindingTestCommand.cs b/src/Commands/VoxelPathFindingTestCommand.cs index 91c7c06..522a476 100644 --- a/src/Commands/VoxelPathFindingTestCommand.cs +++ b/src/Commands/VoxelPathFindingTestCommand.cs @@ -15,24 +15,24 @@ namespace NavisworksTransport.Commands { private readonly Document _document; private readonly double _cellSize; - private readonly double _vehicleRadius; - private readonly double _vehicleHeight; + private readonly double _objectRadius; + private readonly double _objectHeight; private readonly Point3D _startPoint; private readonly Point3D _endPoint; public VoxelPathFindingTestCommand( Document document, double cellSize, - double vehicleRadius, - double vehicleHeight, + double objectRadius, + double objectHeight, Point3D startPoint, Point3D endPoint) : base("VoxelPathFindingTest", "体素路径规划测试", "测试VoxelPathFinder的3D A*路径规划") { _document = document ?? throw new ArgumentNullException(nameof(document)); _cellSize = cellSize; - _vehicleRadius = vehicleRadius; - _vehicleHeight = vehicleHeight; + _objectRadius = objectRadius; + _objectHeight = objectHeight; _startPoint = startPoint; _endPoint = endPoint; } @@ -58,8 +58,8 @@ namespace NavisworksTransport.Commands { LogInfo("=== 开始体素路径规划测试 ==="); LogInfo($"体素大小: {_cellSize}米"); - LogInfo($"车辆半径: {_vehicleRadius}米"); - LogInfo($"车辆高度: {_vehicleHeight}米"); + LogInfo($"车辆半径: {_objectRadius}米"); + LogInfo($"车辆高度: {_objectHeight}米"); LogInfo($"起点: ({_startPoint.X:F2}, {_startPoint.Y:F2}, {_startPoint.Z:F2})"); LogInfo($"终点: ({_endPoint.X:F2}, {_endPoint.Y:F2}, {_endPoint.Z:F2})"); @@ -92,8 +92,8 @@ namespace NavisworksTransport.Commands var voxelGrid = generator.GenerateFromBIMWithSDF( spaceBounds, _cellSize, - _vehicleRadius, - _vehicleHeight, + _objectRadius, + _objectHeight, allModelItems); LogInfo($"体素网格生成完成: {voxelGrid.SizeX}×{voxelGrid.SizeY}×{voxelGrid.SizeZ} = {voxelGrid.TotalVoxels:N0} 个体素"); diff --git a/src/Core/Animation/PathAnimationManager.cs b/src/Core/Animation/PathAnimationManager.cs index a4383e7..90b44f0 100644 --- a/src/Core/Animation/PathAnimationManager.cs +++ b/src/Core/Animation/PathAnimationManager.cs @@ -89,10 +89,11 @@ namespace NavisworksTransport.Core.Animation private static readonly Dictionary> _animationFrameCache = new Dictionary>(); // 动画帧缓存 private static readonly Dictionary> _collisionResultCache = new Dictionary>(); // 碰撞结果缓存 private ModelItem _animatedObject; - private bool _isVirtualVehicle = false; // 是否使用虚拟车辆 - private double _virtualVehicleLength = 0; // 虚拟车辆长度(米) - private double _virtualVehicleWidth = 0; // 虚拟车辆宽度(米) - private double _virtualVehicleHeight = 0; // 虚拟车辆高度(米) + private bool _useVirtualObject = false; // 是否使用虚拟运动物体 + private double _virtualObjectLength = 0; // 虚拟运动物体长度(模型单位) + private double _virtualObjectWidth = 0; // 虚拟运动物体宽度(模型单位) + private double _virtualObjectHeight = 0; // 虚拟运动物体高度(模型单位) + private bool _useSectionClip = true; // 是否使用剖面盒优化(默认启用) private List _pathPoints; private List _manualCollisionTargets = new List(); private bool _manualCollisionOverrideEnabled = false; @@ -350,7 +351,7 @@ namespace NavisworksTransport.Core.Animation /// public void SyncToPathStart(ModelItem item, List points) { - MoveVehicleToPathStart(item, points); + MoveObjectToPathStart(item, points); } /// @@ -364,16 +365,16 @@ namespace NavisworksTransport.Core.Animation var doc = NavisApplication.ActiveDocument; if (doc == null) return; - // 🔥 支持虚拟车辆的恢复 + // 🔥 支持虚拟物体的恢复 ModelItem objectToRestore = null; - bool isVirtual = _isVirtualVehicle; + bool isVirtual = _useVirtualObject; if (isVirtual) { - objectToRestore = VirtualVehicleManager.Instance.CurrentVirtualVehicle; + objectToRestore = VirtualObjectManager.Instance.CurrentVirtualObject; if (objectToRestore == null) { - LogManager.Warning("[归位] 虚拟车辆未激活,跳过恢复"); + LogManager.Warning("[归位] 虚拟物体未激活,跳过恢复"); return; } } @@ -403,7 +404,7 @@ namespace NavisworksTransport.Core.Animation originalBoundingBox.Min.Z ); - string objectName = isVirtual ? "虚拟车辆" : objectToRestore.DisplayName; + string objectName = isVirtual ? "虚拟物体" : objectToRestore.DisplayName; LogManager.Info($"[归位] {objectName} 已彻底恢复到原始位置, yaw={_currentYaw:F3}"); } catch (Exception ex) @@ -429,18 +430,27 @@ namespace NavisworksTransport.Core.Animation public void SetAnimatedObject(ModelItem animatedObject) { _animatedObject = animatedObject; - _isVirtualVehicle = (animatedObject == null); + _useVirtualObject = (animatedObject == null); } /// - /// 设置虚拟车辆参数(批处理专用) + /// 设置虚拟物体参数(批处理专用) /// - public void SetVirtualVehicleParameters(bool isVirtualVehicle, double length, double width, double height) + public void SetVirtualObjectParameters(bool useVirtualObject, double length, double width, double height) { - _isVirtualVehicle = isVirtualVehicle; - _virtualVehicleLength = length; - _virtualVehicleWidth = width; - _virtualVehicleHeight = height; + _useVirtualObject = useVirtualObject; + _virtualObjectLength = length; + _virtualObjectWidth = width; + _virtualObjectHeight = height; + } + + /// + /// 设置是否使用剖面盒优化 + /// + public void SetUseSectionClip(bool useSectionClip) + { + _useSectionClip = useSectionClip; + LogManager.Info($"[PathAnimationManager] 剖面盒优化已{(useSectionClip ? "启用" : "禁用")}"); } /// @@ -561,18 +571,18 @@ namespace NavisworksTransport.Core.Animation } /// - /// 将车辆移动到路径起点 + /// 将物体移动到路径起点 /// /// 动画对象(可选,如果不提供则使用当前的_animatedObject) /// 路径点(可选,如果不提供则使用当前的_pathPoints) - public void MoveVehicleToPathStart(ModelItem animatedObject = null, List pathPoints = null) + public void MoveObjectToPathStart(ModelItem animatedObject = null, List pathPoints = null) { try { // 🔥 重要:先恢复物体到原始状态(CAD位置和原始朝向),确保每次计算都从相同的状态开始 // 这样可以避免之前旋转导致的包围盒尺寸计算不准确的问题 - // 注意:也要处理虚拟车辆(_isVirtualVehicle为true时_animatedObject可能为null) - if (_animatedObject != null || _isVirtualVehicle) + // 注意:也要处理虚拟物体(_useVirtualObject为true时_animatedObject可能为null) + if (_animatedObject != null || _useVirtualObject) { RestoreObjectToCADPosition(); LogManager.Info($"[移动到起点] 已恢复物体到原始状态, _currentYaw={_currentYaw * 180 / Math.PI:F2}°"); @@ -586,7 +596,7 @@ namespace NavisworksTransport.Core.Animation _originalCenter = animatedObject.BoundingBox().Center; _currentPosition = new Point3D(_originalCenter.X, _originalCenter.Y, animatedObject.BoundingBox().Min.Z); - // 统一逻辑:从当前 Transform 中提取实际朝向(无论虚拟车辆还是普通物体) + // 统一逻辑:从当前 Transform 中提取实际朝向(无论虚拟物体还是普通物体) _currentYaw = ModelItemTransformHelper.GetYawFromTransform(_originalTransform); } @@ -636,19 +646,19 @@ namespace NavisworksTransport.Core.Animation if (_route?.PathType == PathType.Hoisting) { // 吊装路径:第一个路径点(起吊点)是地面位置,物体底面应该在这里 - // 不需要向下移动车辆高度 + // 不需要向下移动物体高度 LogManager.Debug($"[移动到起点] 吊装路径:起吊点是地面位置,物体底面Z={startPosition.Z:F2}"); } else if (_route?.PathType == PathType.Rail) { // 空轨路径:路径点是悬挂点,物体悬挂在下方 - double vehicleHeight = _animatedObject.BoundingBox().Max.Z - _animatedObject.BoundingBox().Min.Z; - startPosition = new Point3D(startPosition.X, startPosition.Y, startPosition.Z - vehicleHeight); - LogManager.Debug($"[移动到起点] 空轨路径调整: 悬挂点Z={_pathPoints[0].Z:F2}, 物体底面Z={startPosition.Z:F2}, 物体高度={vehicleHeight:F2}"); + double objectHeight = _animatedObject.BoundingBox().Max.Z - _animatedObject.BoundingBox().Min.Z; + startPosition = new Point3D(startPosition.X, startPosition.Y, startPosition.Z - objectHeight); + LogManager.Debug($"[移动到起点] 空轨路径调整: 悬挂点Z={_pathPoints[0].Z:F2}, 物体底面Z={startPosition.Z:F2}, 物体高度={objectHeight:F2}"); } else { - // 地面路径:points[0] 是地面位置,车辆底面应该在这里 + // 地面路径:points[0] 是地面位置,物体底面应该在这里 LogManager.Debug($"[移动到起点] 地面路径: pos=({startPosition.X:F2},{startPosition.Y:F2},{startPosition.Z:F2})"); } @@ -680,16 +690,16 @@ namespace NavisworksTransport.Core.Animation LogManager.Info($"实际物体位置: X={actualCenter.X:F2}, Y={actualCenter.Y:F2}, Z={actualCenter.Z:F2}"); LogManager.Info($"实际物体朝向: {actualYaw * 180 / Math.PI:F2}度"); } - else if (_isVirtualVehicle) + else if (_useVirtualObject) { - var virtualVehicle = VirtualVehicleManager.Instance.CurrentVirtualVehicle; - if (virtualVehicle != null) + var virtualObject = VirtualObjectManager.Instance.CurrentVirtualObject; + if (virtualObject != null) { - var bbox = virtualVehicle.BoundingBox(); + var bbox = virtualObject.BoundingBox(); var actualCenter = bbox.Center; - var actualYaw = ModelItemTransformHelper.GetYawFromTransform(virtualVehicle.Transform); - LogManager.Info($"虚拟车辆位置: X={actualCenter.X:F2}, Y={actualCenter.Y:F2}, Z={actualCenter.Z:F2}"); - LogManager.Info($"虚拟车辆朝向: {actualYaw * 180 / Math.PI:F2}度"); + var actualYaw = ModelItemTransformHelper.GetYawFromTransform(virtualObject.Transform); + LogManager.Info($"虚拟物体位置: X={actualCenter.X:F2}, Y={actualCenter.Y:F2}, Z={actualCenter.Z:F2}"); + LogManager.Info($"虚拟物体朝向: {actualYaw * 180 / Math.PI:F2}度"); } } } @@ -708,11 +718,50 @@ namespace NavisworksTransport.Core.Animation { LogManager.Info("=== 使用路径预计算动画帧 ==="); + // 🔥 设置剖面盒优化(根据配置) + if (_useSectionClip && _route != null && _route.Points != null && _route.Points.Count > 0) + { + var pathPoints = _route.Points.Select(p => p.Position).ToList(); + + // 计算剖面盒边距(模型单位):物体尺寸 + 安全间隙 + double objectLength, objectWidth, objectHeight; + + if (_useVirtualObject) + { + // 虚拟物体:使用预设尺寸 + objectLength = _virtualObjectLength; + objectWidth = _virtualObjectWidth; + objectHeight = _virtualObjectHeight; + LogManager.Debug($"[预计算] 使用虚拟运动物体尺寸: {objectLength:F2} x {objectWidth:F2} x {objectHeight:F2} (模型单位)"); + } + else + { + // 真实运动物体:从包围盒获取尺寸 + var bbox = _animatedObject.BoundingBox(); + objectLength = bbox.Max.X - bbox.Min.X; + objectWidth = bbox.Max.Y - bbox.Min.Y; + objectHeight = bbox.Max.Z - bbox.Min.Z; + LogManager.Debug($"[预计算] 使用真实运动物体尺寸: {objectLength:F2} x {objectWidth:F2} x {objectHeight:F2} (模型单位), 物体: {_animatedObject.DisplayName}"); + } + + double maxObjectSize = Math.Max(Math.Max(objectLength, objectWidth), objectHeight); + double margin = maxObjectSize + _safetyMargin; + double heightMargin = objectHeight + _safetyMargin; + + SectionClipHelper.SetClipBoxByPath(pathPoints, margin, heightMargin); + LogManager.Info($"[预计算] 已启用剖面盒优化 - 运动物体最大尺寸: {maxObjectSize:F2}, 安全间隙: {_safetyMargin:F2}, 边距: {margin:F2}, 高度边距: {heightMargin:F2} (模型单位)"); + } + else if (!_useSectionClip) + { + SectionClipHelper.ClearClipBox(); + LogManager.Info("[预计算] 已禁用剖面盒优化(性能对比测试模式)"); + } + // 🔥 重要:预计算前先将物体移动到起点位置 if (_animatedObject != null && _route != null && _route.Points != null && _route.Points.Count > 0) { var pathPoints = _route.Points.Select(p => p.Position).ToList(); - MoveVehicleToPathStart(_animatedObject, pathPoints); + MoveObjectToPathStart(_animatedObject, pathPoints); LogManager.Info("[预计算] 物体已移动到路径起点"); } @@ -849,7 +898,7 @@ namespace NavisworksTransport.Core.Animation LogManager.Info(spatialIndexManager.GetStatistics()); // 🔥 优化:使用AABB查询代替球形查询,查询范围更精确 - // 不再预计算球形半径,改为每帧计算车辆AABB + 安全间隙的搜索AABB + // 不再预计算球形半径,改为每帧计算物体AABB + 安全间隙的搜索AABB LogManager.Info($"空间查询使用AABB模式,安全间隙: {_safetyMargin:F4}模型单位"); } @@ -889,14 +938,14 @@ namespace NavisworksTransport.Core.Animation // 计算朝向(使用当前线段的方向) yawRadians = Math.Atan2(p2.Y - p1.Y, p2.X - p1.X); - // 吊装路径:所有线段都使用水平吊运方向(与MoveVehicleToPathStart保持一致) + // 吊装路径:所有线段都使用水平吊运方向(与MoveObjectToPathStart保持一致) if (_route.PathType == PathType.Hoisting) { yawRadians = Math.Atan2(_pathPoints[2].Y - _pathPoints[1].Y, _pathPoints[2].X - _pathPoints[1].X); } // 🔥 空中路径:根据路径类型和线段索引调整物体位置 - double vehicleHeight = _animatedObject.BoundingBox().Max.Z - _animatedObject.BoundingBox().Min.Z; + double objectHeight = _animatedObject.BoundingBox().Max.Z - _animatedObject.BoundingBox().Min.Z; if (_route.PathType == PathType.Hoisting) { @@ -919,25 +968,25 @@ namespace NavisworksTransport.Core.Animation if (segmentIndex == firstSegment) { - // 起吊段:从地面逐渐上升到悬挂点-车辆高度 + // 起吊段:从地面逐渐上升到悬挂点-物体高度 // 进度0时(地面):物体底面在地面,不向下移动 - // 进度1时(悬挂点):物体顶面在悬挂点,物体底面=悬挂点-车辆高度 - double heightOffset = segmentProgress * vehicleHeight; + // 进度1时(悬挂点):物体顶面在悬挂点,物体底面=悬挂点-物体高度 + double heightOffset = segmentProgress * objectHeight; framePosition = new Point3D(framePosition.X, framePosition.Y, framePosition.Z - heightOffset); LogManager.Debug($"[吊装路径-起吊段] 进度={segmentProgress:F2}, 高度偏移={heightOffset:F2}, 物体底面Z={framePosition.Z:F2}"); } else if (segmentIndex > firstSegment && segmentIndex < lastSegment) { // 平移段(中间的所有线段):全程都是悬挂点,物体顶面在悬挂点 - framePosition = new Point3D(framePosition.X, framePosition.Y, framePosition.Z - vehicleHeight); + framePosition = new Point3D(framePosition.X, framePosition.Y, framePosition.Z - objectHeight); LogManager.Debug($"[吊装路径-平移段] 线段{segmentIndex}, 进度={segmentProgress:F2}, 物体底面Z={framePosition.Z:F2}"); } else if (segmentIndex == lastSegment) { - // 下降段:从悬挂点-车辆高度逐渐下降到地面 - // 进度0时(悬挂点):物体顶面在悬挂点,物体底面=悬挂点-车辆高度 + // 下降段:从悬挂点-物体高度逐渐下降到地面 + // 进度0时(悬挂点):物体顶面在悬挂点,物体底面=悬挂点-物体高度 // 进度1时(地面):物体底面在地面,不向下移动 - double heightOffset = (1 - segmentProgress) * vehicleHeight; + double heightOffset = (1 - segmentProgress) * objectHeight; framePosition = new Point3D(framePosition.X, framePosition.Y, framePosition.Z - heightOffset); LogManager.Debug($"[吊装路径-下降段] 进度={segmentProgress:F2}, 高度偏移={heightOffset:F2}, 物体底面Z={framePosition.Z:F2}"); } @@ -946,8 +995,8 @@ namespace NavisworksTransport.Core.Animation { // 空轨路径:路径点是悬挂点,物体悬挂在下方 // 物体顶面应该在路径点,所以物体底面 = 路径点 - 物体高度 - framePosition = new Point3D(framePosition.X, framePosition.Y, framePosition.Z - vehicleHeight); - LogManager.Debug($"[空轨路径] 调整物体位置: 悬挂点Z={framePosition.Z + vehicleHeight:F2}, 物体底面Z={framePosition.Z:F2}"); + framePosition = new Point3D(framePosition.X, framePosition.Y, framePosition.Z - objectHeight); + LogManager.Debug($"[空轨路径] 调整物体位置: 悬挂点Z={framePosition.Z + objectHeight:F2}, 物体底面Z={framePosition.Z:F2}"); } } else @@ -994,30 +1043,30 @@ namespace NavisworksTransport.Core.Animation // 虚拟碰撞检测 - // 计算车辆包围盒相对于framePosition的偏移 - var currentVehicleBoundingBox = _animatedObject.BoundingBox(); + // 计算物体包围盒相对于framePosition的偏移 + var currentObjectBoundingBox = _animatedObject.BoundingBox(); var originalCenter = new Point3D( - (currentVehicleBoundingBox.Min.X + currentVehicleBoundingBox.Max.X) / 2, - (currentVehicleBoundingBox.Min.Y + currentVehicleBoundingBox.Max.Y) / 2, - (currentVehicleBoundingBox.Min.Z + currentVehicleBoundingBox.Max.Z) / 2 + (currentObjectBoundingBox.Min.X + currentObjectBoundingBox.Max.X) / 2, + (currentObjectBoundingBox.Min.Y + currentObjectBoundingBox.Max.Y) / 2, + (currentObjectBoundingBox.Min.Z + currentObjectBoundingBox.Max.Z) / 2 ); // 计算偏移量(当前包围盒中心到framePosition的偏移) var offsetX = framePosition.X - originalCenter.X; var offsetY = framePosition.Y - originalCenter.Y; - var offsetZ = framePosition.Z - currentVehicleBoundingBox.Min.Z; // Z方向:framePosition是底面,originalCenter是中心 + var offsetZ = framePosition.Z - currentObjectBoundingBox.Min.Z; // Z方向:framePosition是底面,originalCenter是中心 // 创建新的包围盒(将当前包围盒移动到framePosition) var virtualBoundingBox = new BoundingBox3D( new Point3D( - currentVehicleBoundingBox.Min.X + offsetX, - currentVehicleBoundingBox.Min.Y + offsetY, + currentObjectBoundingBox.Min.X + offsetX, + currentObjectBoundingBox.Min.Y + offsetY, framePosition.Z // 底面Z坐标 ), new Point3D( - currentVehicleBoundingBox.Max.X + offsetX, - currentVehicleBoundingBox.Max.Y + offsetY, - framePosition.Z + (currentVehicleBoundingBox.Max.Z - currentVehicleBoundingBox.Min.Z) // 保持高度 + currentObjectBoundingBox.Max.X + offsetX, + currentObjectBoundingBox.Max.Y + offsetY, + framePosition.Z + (currentObjectBoundingBox.Max.Z - currentObjectBoundingBox.Min.Z) // 保持高度 ) ); @@ -1034,7 +1083,7 @@ namespace NavisworksTransport.Core.Animation else { // 🔥 优化:使用AABB查询代替球形查询,避免球体扩大的无效范围 - // 查询AABB = 车辆AABB + 安全间隙扩展 + // 查询AABB = 物体AABB + 安全间隙扩展 var searchBounds = new BoundingBox3D( new Point3D( virtualBoundingBox.Min.X - _safetyMargin, @@ -1088,12 +1137,12 @@ namespace NavisworksTransport.Core.Animation (virtualBoundingBox.Min.Y + virtualBoundingBox.Max.Y + colliderBox.Min.Y + colliderBox.Max.Y) / 4, (virtualBoundingBox.Min.Z + virtualBoundingBox.Max.Z + colliderBox.Min.Z + colliderBox.Max.Z) / 4 ), - // 🔥 重要:记录虚拟车辆的包围盒中心,而不是底面中心 + // 🔥 重要:记录虚拟物体的包围盒中心,而不是底面中心 // 原因: - // 1. framePosition是路径点,代表车辆在地面上的位置(底面中心) + // 1. framePosition是路径点,代表物体在地面上的位置(底面中心) // 2. ClashDetective移动逻辑使用包围盒中心进行定位 - // 3. 如果记录底面中心,ClashDetective会把包围盒中心移动到底面位置,导致车辆下沉半个高度 - // 4. 记录包围盒中心可以确保ClashDetective移动后的位置与预计算时的虚拟车辆位置一致 + // 3. 如果记录底面中心,ClashDetective会把包围盒中心移动到底面位置,导致物体下沉半个高度 + // 4. 记录包围盒中心可以确保ClashDetective移动后的位置与预计算时的虚拟物体位置一致 Item1Position = new Point3D( framePosition.X, framePosition.Y, @@ -1355,7 +1404,7 @@ namespace NavisworksTransport.Core.Animation if (distanceToStart > 0.1 || yawDiff > 0.01) { LogManager.Info($"[动画开始] 物体不在起点,重置到起点: 距离={distanceToStart:F2}m, 角度差={yawDiff * 180 / Math.PI:F2}°"); - MoveVehicleToPathStart(); + MoveObjectToPathStart(); } } @@ -1423,10 +1472,10 @@ namespace NavisworksTransport.Core.Animation { var firstFrame = _animationFrames[0]; - LogManager.Debug($"[动画开始] _currentYaw之前={_currentYaw * 180 / Math.PI:F2}度, _isVirtualVehicle={_isVirtualVehicle}"); + LogManager.Debug($"[动画开始] _currentYaw之前={_currentYaw * 180 / Math.PI:F2}度, _useVirtualObject={_useVirtualObject}"); // 🔥 确保物体在起点位置和朝向 - // 注意:MoveVehicleToPathStart 已在 StartAnimation 中调用,这里只是日志记录 + // 注意:MoveObjectToPathStart 已在 StartAnimation 中调用,这里只是日志记录 LogManager.Debug($"[动画开始] 物体应在起点: pos=({firstFrame.Position.X:F2},{firstFrame.Position.Y:F2}), yaw={firstFrame.YawRadians:F3}rad"); } else @@ -1446,12 +1495,12 @@ namespace NavisworksTransport.Core.Animation ModelHighlightHelper.ClearCollisionHighlights(); LogManager.Debug("[动画开始] 已清除所有碰撞高亮"); - // 不再高亮车辆对象,保持原始外观(客户要求) + // 不再高亮物体对象,保持原始外观(客户要求) // if (_animatedObject != null) // { - // var vehicleItems = new List { _animatedObject }; - // ModelHighlightHelper.HighlightItems(ModelHighlightHelper.AnimatedObjectCategory, vehicleItems); - // LogManager.Debug("[动画开始] 已高亮车辆对象为绿色"); + // var animatedObjectItems = new List { _animatedObject }; + // ModelHighlightHelper.HighlightItems(ModelHighlightHelper.AnimatedObjectCategory, animatedObjectItems); + // LogManager.Debug("[动画开始] 已高亮物体对象为绿色"); // } // 启动动画播放 @@ -1572,7 +1621,7 @@ namespace NavisworksTransport.Core.Animation _pausedProgress = 0.0; // 重置暂停进度 _currentFrameIndex = 0; // 重置帧索引 - // 清除所有高亮(包括车辆和碰撞) + // 清除所有高亮(包括物体和碰撞) ModelHighlightHelper.ClearAllHighlights(); LogManager.Info("动画停止:已清除所有高亮"); @@ -1658,7 +1707,7 @@ namespace NavisworksTransport.Core.Animation // 直接设置为完成状态,避免中间状态切换 SetState(AnimationState.Finished); - // 清除所有高亮(包括车辆和碰撞) + // 清除所有高亮(包括物体和碰撞) ModelHighlightHelper.ClearAllHighlights(); LogManager.Info("动画完成:已清除所有高亮"); @@ -1689,12 +1738,12 @@ namespace NavisworksTransport.Core.Animation _detectionTolerance, _currentRouteId, _animatedObject, - _isVirtualVehicle, + _useVirtualObject, _animationFrameRate, _animationDuration, - _virtualVehicleLength, - _virtualVehicleWidth, - _virtualVehicleHeight, + _virtualObjectLength, + _virtualObjectWidth, + _virtualObjectHeight, _pathPoints ); } @@ -1811,7 +1860,7 @@ namespace NavisworksTransport.Core.Animation // 第二步:如果已经生成了动画路径,则重新对齐到起点(带旋转) if (_animationFrames != null && _animationFrames.Count > 0) { - MoveVehicleToPathStart(); + MoveObjectToPathStart(); LogManager.Info("已重新对齐到路径起点"); } } @@ -2809,15 +2858,15 @@ namespace NavisworksTransport.Core.Animation /// 动画持续时间(秒) /// 路径名称 /// 路由ID - public void CreateAnimation(ModelItem animatedObject, List pathPoints, double durationSeconds = 10.0, string pathName = "未知路径", string routeId = null, bool isVirtualVehicle = false, - double virtualVehicleLength = 0, double virtualVehicleWidth = 0, double virtualVehicleHeight = 0, double safetyMargin = 0) + public void CreateAnimation(ModelItem animatedObject, List pathPoints, double durationSeconds = 10.0, string pathName = "未知路径", string routeId = null, bool useVirtualObject = false, + double virtualObjectLength = 0, double virtualObjectWidth = 0, double virtualObjectHeight = 0, double safetyMargin = 0) { _pathName = pathName; _currentRouteId = routeId; - _isVirtualVehicle = isVirtualVehicle; // 设置是否使用虚拟车辆 - _virtualVehicleLength = virtualVehicleLength; // 模型单位 - _virtualVehicleWidth = virtualVehicleWidth; // 模型单位 - _virtualVehicleHeight = virtualVehicleHeight; // 模型单位 + _useVirtualObject = useVirtualObject; // 设置是否使用虚拟运动物体 + _virtualObjectLength = virtualObjectLength; // 模型单位 + _virtualObjectWidth = virtualObjectWidth; // 模型单位 + _virtualObjectHeight = virtualObjectHeight; // 模型单位 _safetyMargin = safetyMargin; // 模型单位 _pathPoints = pathPoints; _animatedObject = animatedObject; @@ -2829,14 +2878,14 @@ namespace NavisworksTransport.Core.Animation _originalCenter = animatedObject.BoundingBox().Center; _currentPosition = new Point3D(_originalCenter.X, _originalCenter.Y, animatedObject.BoundingBox().Min.Z); - // 保持当前的 _currentYaw(因为物体可能已经被 MoveVehicleToPathStart 旋转) + // 保持当前的 _currentYaw(因为物体可能已经被 MoveObjectToPathStart 旋转) // 不要从 Transform 中提取,因为 Transform 返回的是原始值,不是当前值 - LogManager.Debug($"[CreateAnimation] 保持_currentYaw={_currentYaw * 180 / Math.PI:F2}度不变, _isVirtualVehicle={_isVirtualVehicle}"); + LogManager.Debug($"[CreateAnimation] 保持_currentYaw={_currentYaw * 180 / Math.PI:F2}度不变, _useVirtualObject={_useVirtualObject}"); } // 设置动画参数并预计算动画帧 - // 注意:物体应该在调用CreateAnimation之前已经通过MoveVehicleToPathStart旋转到起点 - LogManager.Debug($"[CreateAnimation开始] _currentYaw之前={_currentYaw * 180 / Math.PI:F2}度, _isVirtualVehicle={_isVirtualVehicle}"); + // 注意:物体应该在调用CreateAnimation之前已经通过MoveObjectToPathStart旋转到起点 + LogManager.Debug($"[CreateAnimation开始] _currentYaw之前={_currentYaw * 180 / Math.PI:F2}度, _useVirtualObject={_useVirtualObject}"); SetupAnimation(animatedObject, durationSeconds, _route); LogManager.Debug($"[CreateAnimation结束] _currentYaw之后={_currentYaw * 180 / Math.PI:F2}度"); // 设置动画状态为Ready(动画已生成,可以播放) @@ -2858,7 +2907,7 @@ namespace NavisworksTransport.Core.Animation try { // 重新计算并应用朝向 - MoveVehicleToPathStart(); + MoveObjectToPathStart(); LogManager.Info($"[角度修正] 物体角度已更新: {_objectRotationCorrection:F1}°"); } catch (Exception ex) @@ -2930,7 +2979,7 @@ namespace NavisworksTransport.Core.Animation } else { - // 无碰撞:清除碰撞高亮(保留车辆高亮) + // 无碰撞:清除碰撞高亮(保留物体高亮) ModelHighlightHelper.ClearCategory(ModelHighlightHelper.PrecomputeCollisionResultsCategory); LogManager.Debug($"[高亮状态] 帧{_currentFrameIndex}: 清除碰撞高亮"); } @@ -3131,10 +3180,10 @@ namespace NavisworksTransport.Core.Animation sb.Append($"|DetectionTolerance:{_detectionTolerance:F4}"); sb.Append("|"); - // 包含虚拟车辆尺寸(确保车辆尺寸改变时重新检测) - // 使用传入的车辆尺寸参数,而不是从ConfigManager读取 - var vehicleSizeString = $"Vehicle:{_virtualVehicleLength:F2}x{_virtualVehicleWidth:F2}x{_virtualVehicleHeight:F2}"; - sb.Append(vehicleSizeString); + // 包含虚拟物体尺寸(确保物体尺寸改变时重新检测) + // 使用传入的物体尺寸参数,而不是从ConfigManager读取 + var objectSizeString = $"Object:{_virtualObjectLength:F2}x{_virtualObjectWidth:F2}x{_virtualObjectHeight:F2}"; + sb.Append(objectSizeString); sb.Append("|"); // 包含角度修正(确保角度修正改变时重新检测) diff --git a/src/Core/BatchQueueManager.cs b/src/Core/BatchQueueManager.cs index 836d81b..4dbc9e2 100644 --- a/src/Core/BatchQueueManager.cs +++ b/src/Core/BatchQueueManager.cs @@ -398,19 +398,19 @@ namespace NavisworksTransport.Core // 获取运动物体 ModelItem animatedObject = null; - bool isVirtualVehicle = item.IsVirtualVehicle; + bool isVirtualObject = item.IsVirtualObject; - if (isVirtualVehicle) + if (isVirtualObject) { // 使用现有的虚拟车辆,不创建和清理 - // ShowVirtualVehicle 会显示虚拟车辆并更新尺寸(如果已存在) - VirtualVehicleManager.Instance.ShowVirtualVehicle( - item.VirtualVehicleLength, - item.VirtualVehicleWidth, - item.VirtualVehicleHeight + // ShowVirtualObject 会显示虚拟车辆并更新尺寸(如果已存在) + VirtualObjectManager.Instance.ShowVirtualObject( + item.VirtualObjectLength, + item.VirtualObjectWidth, + item.VirtualObjectHeight ); - animatedObject = VirtualVehicleManager.Instance.CurrentVirtualVehicle; + animatedObject = VirtualObjectManager.Instance.CurrentVirtualObject; if (animatedObject == null) { @@ -516,19 +516,19 @@ namespace NavisworksTransport.Core FrameRate = item.FrameRate, DurationSeconds = item.DurationSeconds, DetectionToleranceMeters = item.DetectionToleranceMeters, - VirtualVehicleLength = item.VirtualVehicleLength, - VirtualVehicleWidth = item.VirtualVehicleWidth, - VirtualVehicleHeight = item.VirtualVehicleHeight, + VirtualObjectLength = item.VirtualObjectLength, + VirtualObjectWidth = item.VirtualObjectWidth, + VirtualObjectHeight = item.VirtualObjectHeight, CollisionDetectionEnabled = true, ReportGenerationEnabled = true }; var frames = _processor.PrecomputeFrames( pathRoute, animatedObject, - isVirtualVehicle, - config.VirtualVehicleLength, - config.VirtualVehicleWidth, - config.VirtualVehicleHeight, + isVirtualObject, + config.VirtualObjectLength, + config.VirtualObjectWidth, + config.VirtualObjectHeight, config.FrameRate, config.DurationSeconds, config.DetectionToleranceMeters, @@ -555,12 +555,12 @@ namespace NavisworksTransport.Core pathRoute.Name, pathRoute.Id, animatedObject, - isVirtualVehicle, + isVirtualObject, item.FrameRate, item.DurationSeconds, - item.VirtualVehicleLength, - item.VirtualVehicleWidth, - item.VirtualVehicleHeight, + item.VirtualObjectLength, + item.VirtualObjectWidth, + item.VirtualObjectHeight, pathPoints ); diff --git a/src/Core/Collision/BatchCollisionProcessor.cs b/src/Core/Collision/BatchCollisionProcessor.cs index 9611a3e..7702050 100644 --- a/src/Core/Collision/BatchCollisionProcessor.cs +++ b/src/Core/Collision/BatchCollisionProcessor.cs @@ -26,10 +26,10 @@ namespace NavisworksTransport.Core.Collision public List PrecomputeFrames( PathRoute route, ModelItem animatedObject, - bool isVirtualVehicle, - double virtualVehicleLength, - double virtualVehicleWidth, - double virtualVehicleHeight, + bool isVirtualObject, + double virtualObjectLength, + double virtualObjectWidth, + double virtualObjectHeight, int frameRate, double duration, double detectionGap, @@ -43,7 +43,7 @@ namespace NavisworksTransport.Core.Collision // 设置动画管理器参数(但不触发UI操作) _animationManager.SetRoute(route); _animationManager.SetAnimatedObject(animatedObject); - _animationManager.SetVirtualVehicleParameters(isVirtualVehicle, virtualVehicleLength, virtualVehicleWidth, virtualVehicleHeight); + _animationManager.SetVirtualObjectParameters(isVirtualObject, virtualObjectLength, virtualObjectWidth, virtualObjectHeight); _animationManager.SetAnimationParameters(frameRate, duration, detectionGap); _animationManager.SetObjectRotationCorrectionDirect(objectRotationCorrection); @@ -75,12 +75,12 @@ namespace NavisworksTransport.Core.Collision string pathName, string routeId, ModelItem animatedObject, - bool isVirtualVehicle, + bool isVirtualObject, int frameRate, double duration, - double virtualVehicleLength, - double virtualVehicleWidth, - double virtualVehicleHeight, + double virtualObjectLength, + double virtualObjectWidth, + double virtualObjectHeight, List pathPoints = null) { try @@ -93,12 +93,12 @@ namespace NavisworksTransport.Core.Collision detectionGap, routeId, animatedObject, - isVirtualVehicle, + isVirtualObject, frameRate, duration, - virtualVehicleLength, - virtualVehicleWidth, - virtualVehicleHeight, + virtualObjectLength, + virtualObjectWidth, + virtualObjectHeight, pathPoints ); diff --git a/src/Core/Collision/ClashDetectiveIntegration.cs b/src/Core/Collision/ClashDetectiveIntegration.cs index 0796812..05694d4 100644 --- a/src/Core/Collision/ClashDetectiveIntegration.cs +++ b/src/Core/Collision/ClashDetectiveIntegration.cs @@ -206,8 +206,8 @@ namespace NavisworksTransport /// private void SaveClashDetectiveResultToDatabase(string routeId, List clashResults, int frameRate, double duration, double detectionGap, - ModelItem animatedObject, bool isVirtualVehicle, - double virtualVehicleLength, double virtualVehicleWidth, double virtualVehicleHeight, + ModelItem animatedObject, bool isVirtualObject, + double virtualObjectLength, double virtualObjectWidth, double virtualObjectHeight, int precomputedCollisionCount = 0) { try @@ -217,24 +217,24 @@ namespace NavisworksTransport { // 获取动画对象名称和路径信息 string animatedObjectName = "未知对象"; - int? vehicleModelIndex = null; - string vehiclePathId = null; + int? ObjectModelIndex = null; + string ObjectPathId = null; - if (!isVirtualVehicle && animatedObject != null) + if (!isVirtualObject && animatedObject != null) { animatedObjectName = ModelItemAnalysisHelper.GetSafeDisplayName(animatedObject); // 获取真实车辆的 PathId 信息 var pathId = Application.ActiveDocument.Models.CreatePathId(animatedObject); - vehicleModelIndex = pathId.ModelIndex; - vehiclePathId = pathId.PathId; + ObjectModelIndex = pathId.ModelIndex; + ObjectPathId = pathId.PathId; } - else if (isVirtualVehicle) + else if (isVirtualObject) { animatedObjectName = "虚拟车辆"; } - // 打印虚拟车辆尺寸(用于调试) - LogManager.Info($"[SaveClashDetectiveResultToDatabase] IsVirtualVehicle={isVirtualVehicle}, 虚拟车辆尺寸: Length={virtualVehicleLength:F2}m, Width={virtualVehicleWidth:F2}m, Height={virtualVehicleHeight:F2}m"); + // 打印虚拟物体尺寸(用于调试) + LogManager.Info($"[SaveClashDetectiveResultToDatabase] IsVirtualObject={isVirtualObject}, 虚拟物体尺寸: Length={virtualObjectLength:F2}m, Width={virtualObjectWidth:F2}m, Height={virtualObjectHeight:F2}m"); var record = new ClashDetectiveResultRecord { @@ -247,16 +247,16 @@ namespace NavisworksTransport Duration = duration, DetectionGap = detectionGap, AnimatedObjectName = animatedObjectName, - IsVirtualVehicle = isVirtualVehicle, - VehicleModelIndex = vehicleModelIndex, - VehiclePathId = vehiclePathId, - VirtualVehicleLength = virtualVehicleLength, - VirtualVehicleWidth = virtualVehicleWidth, - VirtualVehicleHeight = virtualVehicleHeight, + IsVirtualObject = isVirtualObject, + ObjectModelIndex = ObjectModelIndex, + ObjectPathId = ObjectPathId, + VirtualObjectLength = virtualObjectLength, + VirtualObjectWidth = virtualObjectWidth, + VirtualObjectHeight = virtualObjectHeight, CreatedAt = DateTime.Now }; var resultId = pathDatabase.SaveClashDetectiveResult(record); - LogManager.Info($"ClashDetective结果已保存到数据库,Id={resultId}, IsVirtualVehicle={isVirtualVehicle}"); + LogManager.Info($"ClashDetective结果已保存到数据库,Id={resultId}, IsVirtualObject={isVirtualObject}"); // 保存被撞物体信息(只保存Item2,不保存车辆Item1) // 同时保存碰撞时运动物体的位置和朝向,用于还原碰撞场景 @@ -355,8 +355,8 @@ namespace NavisworksTransport // 1. 从数据库读取测试信息(添加JOIN获取PathName) var testInfoSql = @" - SELECT cdr.Id, pr.Name AS PathName, cdr.RouteId, cdr.IsVirtualVehicle, cdr.VehicleModelIndex, cdr.VehiclePathId, - cdr.VirtualVehicleLength, cdr.VirtualVehicleWidth, cdr.VirtualVehicleHeight + SELECT cdr.Id, pr.Name AS PathName, cdr.RouteId, cdr.IsVirtualObject, cdr.ObjectModelIndex, cdr.ObjectPathId, + cdr.VirtualObjectLength, cdr.VirtualObjectWidth, cdr.VirtualObjectHeight FROM ClashDetectiveResults cdr INNER JOIN PathRoutes pr ON cdr.RouteId = pr.Id WHERE cdr.TestName = @testName @@ -375,12 +375,12 @@ namespace NavisworksTransport Id = Convert.ToInt32(reader["Id"]), PathName = reader["PathName"].ToString(), RouteId = reader["RouteId"]?.ToString(), - IsVirtualVehicle = Convert.ToBoolean(reader["IsVirtualVehicle"]), - VehicleModelIndex = reader["VehicleModelIndex"] != DBNull.Value ? Convert.ToInt32(reader["VehicleModelIndex"]) : (int?)null, - VehiclePathId = reader["VehiclePathId"] != DBNull.Value ? reader["VehiclePathId"].ToString() : null, - VirtualVehicleLength = reader["VirtualVehicleLength"] != DBNull.Value ? Convert.ToDouble(reader["VirtualVehicleLength"]) : 0.0, - VirtualVehicleWidth = reader["VirtualVehicleWidth"] != DBNull.Value ? Convert.ToDouble(reader["VirtualVehicleWidth"]) : 0.0, - VirtualVehicleHeight = reader["VirtualVehicleHeight"] != DBNull.Value ? Convert.ToDouble(reader["VirtualVehicleHeight"]) : 0.0 + IsVirtualObject = Convert.ToBoolean(reader["IsVirtualObject"]), + ObjectModelIndex = reader["ObjectModelIndex"] != DBNull.Value ? Convert.ToInt32(reader["ObjectModelIndex"]) : (int?)null, + ObjectPathId = reader["ObjectPathId"] != DBNull.Value ? reader["ObjectPathId"].ToString() : null, + VirtualObjectLength = reader["VirtualObjectLength"] != DBNull.Value ? Convert.ToDouble(reader["VirtualObjectLength"]) : 0.0, + VirtualObjectWidth = reader["VirtualObjectWidth"] != DBNull.Value ? Convert.ToDouble(reader["VirtualObjectWidth"]) : 0.0, + VirtualObjectHeight = reader["VirtualObjectHeight"] != DBNull.Value ? Convert.ToDouble(reader["VirtualObjectHeight"]) : 0.0 }; } } @@ -393,45 +393,45 @@ namespace NavisworksTransport } // 2. 重建车辆对象 - ModelItem vehicleObject = null; - if (testInfo.IsVirtualVehicle) + ModelItem ObjectObject = null; + if (testInfo.IsVirtualObject) { // 显示虚拟车辆 var modelToMeters = UnitsConverter.GetUnitsToMetersConversionFactor(); - VirtualVehicleManager.Instance.ShowVirtualVehicle( - testInfo.VirtualVehicleLength * modelToMeters, - testInfo.VirtualVehicleWidth * modelToMeters, - testInfo.VirtualVehicleHeight * modelToMeters + VirtualObjectManager.Instance.ShowVirtualObject( + testInfo.VirtualObjectLength * modelToMeters, + testInfo.VirtualObjectWidth * modelToMeters, + testInfo.VirtualObjectHeight * modelToMeters ); - vehicleObject = VirtualVehicleManager.Instance.CurrentVirtualVehicle + ObjectObject = VirtualObjectManager.Instance.CurrentVirtualObject ?? throw new InvalidOperationException($"[LoadClashDetectiveResultsFromDatabase] 显示虚拟车辆失败"); } - else if (testInfo.VehicleModelIndex.HasValue && !string.IsNullOrEmpty(testInfo.VehiclePathId)) + else if (testInfo.ObjectModelIndex.HasValue && !string.IsNullOrEmpty(testInfo.ObjectPathId)) { // 通过 PathId 查找真实车辆 try { var pathIdObj = new Autodesk.Navisworks.Api.DocumentParts.ModelItemPathId { - ModelIndex = testInfo.VehicleModelIndex.Value, - PathId = testInfo.VehiclePathId + ModelIndex = testInfo.ObjectModelIndex.Value, + PathId = testInfo.ObjectPathId }; - vehicleObject = Application.ActiveDocument.Models.ResolvePathId(pathIdObj) ?? throw new InvalidOperationException($"[LoadClashDetectiveResultsFromDatabase] 无法通过 PathId 找到车辆对象: ModelIndex={testInfo.VehicleModelIndex}, PathId={testInfo.VehiclePathId}"); - LogManager.Info($"[LoadClashDetectiveResultsFromDatabase] 已找到真实车辆: {ModelItemAnalysisHelper.GetSafeDisplayName(vehicleObject)}"); + ObjectObject = Application.ActiveDocument.Models.ResolvePathId(pathIdObj) ?? throw new InvalidOperationException($"[LoadClashDetectiveResultsFromDatabase] 无法通过 PathId 找到车辆对象: ModelIndex={testInfo.ObjectModelIndex}, PathId={testInfo.ObjectPathId}"); + LogManager.Info($"[LoadClashDetectiveResultsFromDatabase] 已找到真实车辆: {ModelItemAnalysisHelper.GetSafeDisplayName(ObjectObject)}"); } catch (Exception ex) { - throw new InvalidOperationException($"[LoadClashDetectiveResultsFromDatabase] ResolvePathId 失败: ModelIndex={testInfo.VehicleModelIndex}, PathId={testInfo.VehiclePathId}", ex); + throw new InvalidOperationException($"[LoadClashDetectiveResultsFromDatabase] ResolvePathId 失败: ModelIndex={testInfo.ObjectModelIndex}, PathId={testInfo.ObjectPathId}", ex); } } - if (vehicleObject == null) + if (ObjectObject == null) { - throw new InvalidOperationException($"[LoadClashDetectiveResultsFromDatabase] 无法重建车辆对象: IsVirtualVehicle={testInfo.IsVirtualVehicle}, VehicleModelIndex={testInfo.VehicleModelIndex}, VehiclePathId={testInfo.VehiclePathId}"); + throw new InvalidOperationException($"[LoadClashDetectiveResultsFromDatabase] 无法重建车辆对象: IsVirtualObject={testInfo.IsVirtualObject}, ObjectModelIndex={testInfo.ObjectModelIndex}, ObjectPathId={testInfo.ObjectPathId}"); } // 如果是虚拟车辆,将其移动到路径起点 - if (testInfo.IsVirtualVehicle && !string.IsNullOrEmpty(testInfo.RouteId)) + if (testInfo.IsVirtualObject && !string.IsNullOrEmpty(testInfo.RouteId)) { try { @@ -446,7 +446,7 @@ namespace NavisworksTransport // 使用 PathAnimationManager 将车辆移动到起点 var pathAnimationManager = PathAnimationManager.GetInstance(); - pathAnimationManager.MoveVehicleToPathStart(vehicleObject, new List { startPointPosition, startPointPosition }); + pathAnimationManager.MoveObjectToPathStart(ObjectObject, new List { startPointPosition, startPointPosition }); LogManager.Info($"[LoadClashDetectiveResultsFromDatabase] 虚拟车辆已移动到路径起点: ({startPointPosition.X:F2}, {startPointPosition.Y:F2}, {startPointPosition.Z:F2})"); } } @@ -529,7 +529,7 @@ namespace NavisworksTransport ClashGuid = Guid.NewGuid(), DisplayName = $"历史碰撞: {collidedObjectName}", Status = ClashResultStatus.Active, - Item1 = vehicleObject, + Item1 = ObjectObject, Item2 = collidedObject, Center = collidedObject.BoundingBox().Center, Distance = 0.0, @@ -669,12 +669,12 @@ namespace NavisworksTransport double detectionGap, string routeId, ModelItem animatedObject, - bool isVirtualVehicle, + bool isVirtualObject, int frameRate, double duration, - double virtualVehicleLength, - double virtualVehicleWidth, - double virtualVehicleHeight, + double virtualObjectLength, + double virtualObjectWidth, + double virtualObjectHeight, Progress progress = null, int precomputedCollisionCount = 0) { @@ -738,10 +738,10 @@ namespace NavisworksTransport duration, detectionGap, animatedObject, - isVirtualVehicle, - virtualVehicleLength, - virtualVehicleWidth, - virtualVehicleHeight, + isVirtualObject, + virtualObjectLength, + virtualObjectWidth, + virtualObjectHeight, precomputedCollisionCount ); @@ -1061,8 +1061,8 @@ namespace NavisworksTransport _clashDetectiveCollisionCount = clashResults.Count; // 保存到数据库(使用去重后的结果) - SaveClashDetectiveResultToDatabase(routeId, finalClashResults, frameRate, duration, detectionGap, animatedObject, isVirtualVehicle, - virtualVehicleLength, virtualVehicleWidth, virtualVehicleHeight, precomputedCollisionCount); + SaveClashDetectiveResultToDatabase(routeId, finalClashResults, frameRate, duration, detectionGap, animatedObject, isVirtualObject, + virtualObjectLength, virtualObjectWidth, virtualObjectHeight, precomputedCollisionCount); LogManager.Info($"[ClashDetective] 结果已保存到数据库"); @@ -1077,24 +1077,24 @@ namespace NavisworksTransport /// 检测间隙容差 /// 路由ID /// 动画对象(如果是真实车辆) - /// 是否使用虚拟车辆 + /// 是否使用虚拟物体 /// 帧率 /// 动画时长 - /// 虚拟车辆长度(米) - /// 虚拟车辆宽度(米) - /// 虚拟车辆高度(米) + /// 虚拟车辆长度(米) + /// 虚拟车辆宽度(米) + /// 虚拟车辆高度(米) /// 路径点列表(用于测试完成后恢复物体位置) public void CreateAllAnimationCollisionTests( List precomputedCollisions, double detectionGap, string routeId, ModelItem animatedObject, - bool isVirtualVehicle, + bool isVirtualObject, int frameRate, double duration, - double virtualVehicleLength, - double virtualVehicleWidth, - double virtualVehicleHeight, + double virtualObjectLength, + double virtualObjectWidth, + double virtualObjectHeight, List pathPoints = null) { try @@ -1137,12 +1137,12 @@ namespace NavisworksTransport detectionGap, routeId, animatedObject, - isVirtualVehicle, + isVirtualObject, frameRate, duration, - virtualVehicleLength, - virtualVehicleWidth, - virtualVehicleHeight, + virtualObjectLength, + virtualObjectWidth, + virtualObjectHeight, progress, precomputedCollisionCount ); @@ -1929,12 +1929,12 @@ namespace NavisworksTransport double detectionGap, string routeId, ModelItem animatedObject, - bool isVirtualVehicle, + bool isVirtualObject, int frameRate, double duration, - double virtualVehicleLength, - double virtualVehicleWidth, - double virtualVehicleHeight, + double virtualObjectLength, + double virtualObjectWidth, + double virtualObjectHeight, List pathPoints = null) { try @@ -1953,12 +1953,12 @@ namespace NavisworksTransport detectionGap, routeId, animatedObject, - isVirtualVehicle, + isVirtualObject, frameRate, duration, - virtualVehicleLength, - virtualVehicleWidth, - virtualVehicleHeight, + virtualObjectLength, + virtualObjectWidth, + virtualObjectHeight, null, precomputedCollisionCount ); @@ -1987,7 +1987,7 @@ namespace NavisworksTransport // { // try // { - // PathAnimationManager.GetInstance().MoveVehicleToPathStart(animatedObject, pathPoints); + // PathAnimationManager.GetInstance().MoveObjectToPathStart(animatedObject, pathPoints); // LogManager.Info($"[批处理] 已将 {animatedObject.DisplayName} 恢复到路径起点位置"); // } // catch (Exception restoreEx) diff --git a/src/Core/Collision/IBatchCollisionProcessor.cs b/src/Core/Collision/IBatchCollisionProcessor.cs index db5c2b3..3047706 100644 --- a/src/Core/Collision/IBatchCollisionProcessor.cs +++ b/src/Core/Collision/IBatchCollisionProcessor.cs @@ -15,11 +15,11 @@ namespace NavisworksTransport.Core.Collision /// 预计算动画帧和碰撞(纯计算,无UI操作) /// /// 路径 - /// 动画对象(可为null,表示使用虚拟车辆) - /// 是否使用虚拟车辆 - /// 虚拟车辆长度(米) - /// 虚拟车辆宽度(米) - /// 虚拟车辆高度(米) + /// 动画对象(可为null,表示使用虚拟物体) + /// 是否使用虚拟物体 + /// 虚拟物体长度(米) + /// 虚拟物体宽度(米) + /// 虚拟物体高度(米) /// 帧率 /// 持续时间(秒) /// 检测间隙(米) @@ -28,10 +28,10 @@ namespace NavisworksTransport.Core.Collision List PrecomputeFrames( PathRoute route, ModelItem animatedObject, - bool isVirtualVehicle, - double virtualVehicleLength, - double virtualVehicleWidth, - double virtualVehicleHeight, + bool isVirtualObject, + double virtualObjectLength, + double virtualObjectWidth, + double virtualObjectHeight, int frameRate, double duration, double detectionGap, @@ -46,13 +46,13 @@ namespace NavisworksTransport.Core.Collision /// 检测间隙(米) /// 路径名称 /// 路径ID - /// 动画对象(可为null,表示使用虚拟车辆) - /// 是否使用虚拟车辆 + /// 动画对象(可为null,表示使用虚拟物体) + /// 是否使用虚拟物体 /// 帧率 /// 持续时间(秒) - /// 虚拟车辆长度(米) - /// 虚拟车辆宽度(米) - /// 虚拟车辆高度(米) + /// 虚拟物体长度(米) + /// 虚拟物体宽度(米) + /// 虚拟物体高度(米) /// 路径点列表(用于测试完成后恢复物体位置) /// ClashDetective测试名称 string CreateAndRunClashDetectiveTest( @@ -61,12 +61,12 @@ namespace NavisworksTransport.Core.Collision string pathName, string routeId, ModelItem animatedObject, - bool isVirtualVehicle, + bool isVirtualObject, int frameRate, double duration, - double virtualVehicleLength, - double virtualVehicleWidth, - double virtualVehicleHeight, + double virtualObjectLength, + double virtualObjectWidth, + double virtualObjectHeight, List pathPoints = null); } } \ No newline at end of file diff --git a/src/Core/Config/ConfigManager.cs b/src/Core/Config/ConfigManager.cs index eea5f58..155a762 100644 --- a/src/Core/Config/ConfigManager.cs +++ b/src/Core/Config/ConfigManager.cs @@ -388,9 +388,9 @@ namespace NavisworksTransport.Core.Config // 使用带默认值的读取方法,不抛出异常 config.PathEditing.CellSizeMeters = GetDoubleValueWithDefault(pathEdit, "cell_size_meters", 0.5, missingItems); config.PathEditing.MaxHeightDiffMeters = GetDoubleValueWithDefault(pathEdit, "max_height_diff_meters", 0.35, missingItems); - config.PathEditing.VehicleLengthMeters = GetDoubleValueWithDefault(pathEdit, "vehicle_length_meters", 1.5, missingItems); - config.PathEditing.VehicleWidthMeters = GetDoubleValueWithDefault(pathEdit, "vehicle_width_meters", 1.0, missingItems); - config.PathEditing.VehicleHeightMeters = GetDoubleValueWithDefault(pathEdit, "vehicle_height_meters", 2.0, missingItems); + config.PathEditing.ObjectLengthMeters = GetDoubleValueWithDefault(pathEdit, "object_length_meters", 1.5, missingItems); + config.PathEditing.ObjectWidthMeters = GetDoubleValueWithDefault(pathEdit, "object_width_meters", 1.0, missingItems); + config.PathEditing.ObjectHeightMeters = GetDoubleValueWithDefault(pathEdit, "object_height_meters", 2.0, missingItems); config.PathEditing.SafetyMarginMeters = GetDoubleValueWithDefault(pathEdit, "safety_margin_meters", 0.1, missingItems); config.PathEditing.DefaultPathTurnRadiusMeters = GetDoubleValueWithDefault(pathEdit, "default_path_turn_radius", 2.5, missingItems); config.PathEditing.ArcSamplingStepMeters = GetDoubleValueWithDefault(pathEdit, "arc_sampling_step", 0.05, missingItems); @@ -613,9 +613,9 @@ namespace NavisworksTransport.Core.Config { pathEdit["cell_size_meters"] = config.PathEditing.CellSizeMeters; pathEdit["max_height_diff_meters"] = config.PathEditing.MaxHeightDiffMeters; - pathEdit["vehicle_length_meters"] = config.PathEditing.VehicleLengthMeters; - pathEdit["vehicle_width_meters"] = config.PathEditing.VehicleWidthMeters; - pathEdit["vehicle_height_meters"] = config.PathEditing.VehicleHeightMeters; + pathEdit["object_length_meters"] = config.PathEditing.ObjectLengthMeters; + pathEdit["object_width_meters"] = config.PathEditing.ObjectWidthMeters; + pathEdit["object_height_meters"] = config.PathEditing.ObjectHeightMeters; pathEdit["safety_margin_meters"] = config.PathEditing.SafetyMarginMeters; pathEdit["default_path_turn_radius"] = config.PathEditing.DefaultPathTurnRadiusMeters; pathEdit["arc_sampling_step"] = config.PathEditing.ArcSamplingStepMeters; @@ -714,7 +714,7 @@ namespace NavisworksTransport.Core.Config var newConfig = ParseTomlToConfig(templateContent); LogManager.Info($"解析后的配置 - CellSizeMeters: {newConfig.PathEditing.CellSizeMeters}"); - LogManager.Info($"解析后的配置 - VehicleLengthMeters: {newConfig.PathEditing.VehicleLengthMeters}"); + LogManager.Info($"解析后的配置 - ObjectLengthMeters: {newConfig.PathEditing.ObjectLengthMeters}"); _currentConfig = newConfig; diff --git a/src/Core/Config/SystemConfig.cs b/src/Core/Config/SystemConfig.cs index 7bb14d6..1541b80 100644 --- a/src/Core/Config/SystemConfig.cs +++ b/src/Core/Config/SystemConfig.cs @@ -72,19 +72,19 @@ namespace NavisworksTransport.Core.Config public double MaxHeightDiffMeters { get; set; } /// - /// 车辆长度(米) + /// 运动物体长度(米) /// - public double VehicleLengthMeters { get; set; } + public double ObjectLengthMeters { get; set; } /// - /// 车辆宽度(米) + /// 运动物体宽度(米) /// - public double VehicleWidthMeters { get; set; } + public double ObjectWidthMeters { get; set; } /// - /// 车辆高度(米) + /// 运动物体高度(米) /// - public double VehicleHeightMeters { get; set; } + public double ObjectHeightMeters { get; set; } /// /// 安全间隙(米) @@ -114,19 +114,19 @@ namespace NavisworksTransport.Core.Config public double MaxHeightDiff => MaxHeightDiffMeters * Utils.UnitsConverter.GetMetersToUnitsConversionFactor(); /// - /// 车辆长度(模型单位) + /// 运动物体长度(模型单位) /// - public double VehicleLength => VehicleLengthMeters * Utils.UnitsConverter.GetMetersToUnitsConversionFactor(); + public double ObjectLength => ObjectLengthMeters * Utils.UnitsConverter.GetMetersToUnitsConversionFactor(); /// - /// 车辆宽度(模型单位) + /// 运动物体宽度(模型单位) /// - public double VehicleWidth => VehicleWidthMeters * Utils.UnitsConverter.GetMetersToUnitsConversionFactor(); + public double ObjectWidth => ObjectWidthMeters * Utils.UnitsConverter.GetMetersToUnitsConversionFactor(); /// - /// 车辆高度(模型单位) + /// 运动物体高度(模型单位) /// - public double VehicleHeight => VehicleHeightMeters * Utils.UnitsConverter.GetMetersToUnitsConversionFactor(); + public double ObjectHeight => ObjectHeightMeters * Utils.UnitsConverter.GetMetersToUnitsConversionFactor(); /// /// 安全间隙(模型单位) diff --git a/src/Core/MainPlugin.cs b/src/Core/MainPlugin.cs index 8a5e3cb..e2a2c46 100644 --- a/src/Core/MainPlugin.cs +++ b/src/Core/MainPlugin.cs @@ -387,8 +387,8 @@ namespace NavisworksTransport if (activeDoc != null && activeDoc.Models != null && activeDoc.Models.Count > 0) { LogManager.Info("[文档管理] 插件加载时发现包含模型的活动文档,立即初始化管理器"); - // 🔥 插件加载时不是虚拟车辆变化,传入 false - InitializeManagers(isVirtualVehicleChange: false); + // 🔥 插件加载时不是虚拟物体变化,传入 false + InitializeManagers(isVirtualObjectChange: false); } else if (activeDoc != null) { @@ -495,14 +495,14 @@ namespace NavisworksTransport LogManager.Warning($"[文档管理] 订阅新文档事件时出现警告: {ex.Message}"); } - // 🔥 优化:检测是否是虚拟车辆引起的文档变化 - bool isVirtualVehicleChange = IsVirtualVehicleChange(activeDoc); - if (isVirtualVehicleChange) + // 🔥 优化:检测是否是虚拟物体引起的文档变化 + bool isVirtualObjectChange = IsVirtualObjectChange(activeDoc); + if (isVirtualObjectChange) { - LogManager.Info("[文档管理] 检测到虚拟车辆文档变化,使用快速初始化模式"); + LogManager.Info("[文档管理] 检测到虚拟物体文档变化,使用快速初始化模式"); } - InitializeManagers(isVirtualVehicleChange); + InitializeManagers(isVirtualObjectChange); } else { @@ -513,29 +513,29 @@ namespace NavisworksTransport } /// - /// 检测是否是虚拟车辆引起的文档变化 - /// 🔥 优化:通过 VirtualVehicleManager 的标志精确检测,避免误触发缓存重建 + /// 检测是否是虚拟物体引起的文档变化 + /// 🔥 优化:通过 VirtualObjectManager 的标志精确检测,避免误触发缓存重建 /// - private bool IsVirtualVehicleChange(Document doc) + private bool IsVirtualObjectChange(Document doc) { try { - // 🔥 优先检查 VirtualVehicleManager 的更新标志(最准确) - if (VirtualVehicleManager.Instance.IsUpdatingVirtualVehicle) + // 🔥 优先检查 VirtualObjectManager 的更新标志(最准确) + if (VirtualObjectManager.Instance.IsUpdatingVirtualObject) { - LogManager.Debug("[文档管理] VirtualVehicleManager 正在更新,判定为虚拟车辆变化"); + LogManager.Debug("[文档管理] VirtualObjectManager 正在更新,判定为虚拟物体变化"); return true; } if (doc?.Models == null) return false; - // 备选:检查是否包含虚拟车辆模型 + // 备选:检查是否包含虚拟物体模型 foreach (var model in doc.Models) { var modelName = model.RootItem?.DisplayName ?? ""; - if (modelName.Contains("unit_cube") || modelName.Contains("VirtualVehicle")) + if (modelName.Contains("unit_cube") || modelName.Contains("VirtualObject")) { - LogManager.Debug($"[文档管理] 检测到虚拟车辆模型: {modelName}"); + LogManager.Debug($"[文档管理] 检测到虚拟物体模型: {modelName}"); return true; } } @@ -544,7 +544,7 @@ namespace NavisworksTransport } catch (Exception ex) { - LogManager.Debug($"[文档管理] 检测虚拟车辆变化时出错: {ex.Message}"); + LogManager.Debug($"[文档管理] 检测虚拟物体变化时出错: {ex.Message}"); return false; } } @@ -693,8 +693,8 @@ namespace NavisworksTransport /// /// 初始化各个管理器 /// - /// 是否由虚拟车辆变化引起 - private void InitializeManagers(bool isVirtualVehicleChange = false) + /// 是否由虚拟物体变化引起 + private void InitializeManagers(bool isVirtualObjectChange = false) { try { @@ -713,10 +713,10 @@ namespace NavisworksTransport // 通知DocumentStateManager文档已就绪 DocumentStateManager.Instance.OnDocumentReady(); - // 🔥 优化:虚拟车辆变化时不清除缓存,避免80秒重建 - if (isVirtualVehicleChange) + // 🔥 优化:虚拟物体变化时不清除缓存,避免80秒重建 + if (isVirtualObjectChange) { - LogManager.Info("[文档管理] 检测到虚拟车辆变化,保留现有缓存,仅更新运动物体引用"); + LogManager.Info("[文档管理] 检测到虚拟物体变化,保留现有缓存,仅更新运动物体引用"); // 只清除运动物体引用,不清除基础缓存 ClashDetectiveIntegration.ClearAnimatedObject(); } @@ -811,15 +811,15 @@ namespace NavisworksTransport LogManager.Warning($"[文档管理] 清理Idle事件管理器时出现警告: {ex.Message}"); } - // 清理虚拟车辆 + // 清理虚拟物体 try { - VirtualVehicleManager.Instance.Cleanup(); - LogManager.Info("[文档管理] 已清理虚拟车辆"); + VirtualObjectManager.Instance.Cleanup(); + LogManager.Info("[文档管理] 已清理虚拟物体"); } catch (Exception ex) { - LogManager.Warning($"[文档管理] 清理虚拟车辆时出现警告: {ex.Message}"); + LogManager.Warning($"[文档管理] 清理虚拟物体时出现警告: {ex.Message}"); } // 清除临时材质 diff --git a/src/Core/Models/BatchQueueItem.cs b/src/Core/Models/BatchQueueItem.cs index 54fa109..b202c64 100644 --- a/src/Core/Models/BatchQueueItem.cs +++ b/src/Core/Models/BatchQueueItem.cs @@ -25,11 +25,11 @@ namespace NavisworksTransport.Core.Models public double DetectionToleranceMeters { get; set; } // 运动物体配置 - public bool IsVirtualVehicle { get; set; } - public double VirtualVehicleLength { get; set; } - public double VirtualVehicleWidth { get; set; } - public double VirtualVehicleHeight { get; set; } - public string MovingObjectName { get; set; } // 运动物体名称,虚拟车辆时为 null + public bool IsVirtualObject { get; set; } + public double VirtualObjectLength { get; set; } + public double VirtualObjectWidth { get; set; } + public double VirtualObjectHeight { get; set; } + public string MovingObjectName { get; set; } // 运动物体名称,虚拟物体时为 null // 碰撞检测配置 public bool DetectAllObjects { get; set; } = true; diff --git a/src/Core/Models/CollisionDetectionConfig.cs b/src/Core/Models/CollisionDetectionConfig.cs index 2d52e31..94d9436 100644 --- a/src/Core/Models/CollisionDetectionConfig.cs +++ b/src/Core/Models/CollisionDetectionConfig.cs @@ -11,10 +11,10 @@ namespace NavisworksTransport.Core.Models public bool CollisionDetectionEnabled { get; set; } public bool ReportGenerationEnabled { get; set; } - // 虚拟车辆参数 - public double VirtualVehicleLength { get; set; } - public double VirtualVehicleWidth { get; set; } - public double VirtualVehicleHeight { get; set; } + // 虚拟物体参数 + public double VirtualObjectLength { get; set; } + public double VirtualObjectWidth { get; set; } + public double VirtualObjectHeight { get; set; } /// /// 序列化为JSON字符串(简化版) diff --git a/src/Core/PathDataManager.cs b/src/Core/PathDataManager.cs index 4353eab..0f75898 100644 --- a/src/Core/PathDataManager.cs +++ b/src/Core/PathDataManager.cs @@ -31,7 +31,7 @@ namespace NavisworksTransport /// /// JSON格式的车辆限制数据 /// - public class JsonVehicleLimits + public class JsonObjectLimits { public double maxLength { get; set; } public double maxWidth { get; set; } @@ -49,7 +49,7 @@ namespace NavisworksTransport public string description { get; set; } public string pathType { get; set; } public double totalLength { get; set; } - public JsonVehicleLimits vehicleLimits { get; set; } + public JsonObjectLimits ObjectLimits { get; set; } public double gridSize { get; set; } public double liftHeightMeters { get; set; } public string created { get; set; } @@ -270,11 +270,11 @@ namespace NavisworksTransport description = route.Description ?? "", pathType = route.PathType.ToString(), totalLength = Math.Round(route.TotalLength, exportSettings?.Precision ?? 3), - vehicleLimits = new + ObjectLimits = new { - maxLength = Math.Round(route.MaxVehicleLength, exportSettings?.Precision ?? 3), - maxWidth = Math.Round(route.MaxVehicleWidth, exportSettings?.Precision ?? 3), - maxHeight = Math.Round(route.MaxVehicleHeight, exportSettings?.Precision ?? 3), + maxLength = Math.Round(route.MaxObjectLength, exportSettings?.Precision ?? 3), + maxWidth = Math.Round(route.MaxObjectWidth, exportSettings?.Precision ?? 3), + maxHeight = Math.Round(route.MaxObjectHeight, exportSettings?.Precision ?? 3), safetyMargin = Math.Round(route.SafetyMargin, exportSettings?.Precision ?? 3) }, gridSize = Math.Round(route.GridSize, exportSettings?.Precision ?? 3), @@ -476,10 +476,10 @@ namespace NavisworksTransport Id = jsonRoute.id, Description = jsonRoute.description ?? "", CreatedTime = ParseJsonDateTime(jsonRoute.created), - MaxVehicleLength = jsonRoute.vehicleLimits?.maxLength ?? 0, - MaxVehicleWidth = jsonRoute.vehicleLimits?.maxWidth ?? 0, - MaxVehicleHeight = jsonRoute.vehicleLimits?.maxHeight ?? 0, - SafetyMargin = jsonRoute.vehicleLimits?.safetyMargin ?? 0, + MaxObjectLength = jsonRoute.ObjectLimits?.maxLength ?? 0, + MaxObjectWidth = jsonRoute.ObjectLimits?.maxWidth ?? 0, + MaxObjectHeight = jsonRoute.ObjectLimits?.maxHeight ?? 0, + SafetyMargin = jsonRoute.ObjectLimits?.safetyMargin ?? 0, GridSize = jsonRoute.gridSize, LiftHeightMeters = jsonRoute.liftHeightMeters }; @@ -989,9 +989,9 @@ namespace NavisworksTransport routeElement.SetAttribute("description", route.Description ?? ""); routeElement.SetAttribute("pathType", route.PathType.ToString()); routeElement.SetAttribute("totalLength", route.TotalLength.ToString("F3")); - routeElement.SetAttribute("maxVehicleLength", route.MaxVehicleLength.ToString("F3")); - routeElement.SetAttribute("maxVehicleWidth", route.MaxVehicleWidth.ToString("F3")); - routeElement.SetAttribute("maxVehicleHeight", route.MaxVehicleHeight.ToString("F3")); + routeElement.SetAttribute("maxObjectLength", route.MaxObjectLength.ToString("F3")); + routeElement.SetAttribute("maxObjectWidth", route.MaxObjectWidth.ToString("F3")); + routeElement.SetAttribute("maxObjectHeight", route.MaxObjectHeight.ToString("F3")); routeElement.SetAttribute("safetyMargin", route.SafetyMargin.ToString("F3")); routeElement.SetAttribute("gridSize", route.GridSize.ToString("F3")); routeElement.SetAttribute("liftHeightMeters", route.LiftHeightMeters.ToString("F3")); @@ -1112,9 +1112,9 @@ namespace NavisworksTransport Name = routeNode.Attributes?["name"]?.Value ?? "导入路径", Description = routeNode.Attributes?["description"]?.Value ?? "", PathType = pathType, - MaxVehicleLength = double.TryParse(routeNode.Attributes?["maxVehicleLength"]?.Value, out double maxLength) ? maxLength : 0, - MaxVehicleWidth = double.TryParse(routeNode.Attributes?["maxVehicleWidth"]?.Value, out double maxWidth) ? maxWidth : 0, - MaxVehicleHeight = double.TryParse(routeNode.Attributes?["maxVehicleHeight"]?.Value, out double maxHeight) ? maxHeight : 0, + MaxObjectLength = double.TryParse(routeNode.Attributes?["maxObjectLength"]?.Value, out double maxLength) ? maxLength : 0, + MaxObjectWidth = double.TryParse(routeNode.Attributes?["maxObjectWidth"]?.Value, out double maxWidth) ? maxWidth : 0, + MaxObjectHeight = double.TryParse(routeNode.Attributes?["maxObjectHeight"]?.Value, out double maxHeight) ? maxHeight : 0, SafetyMargin = double.TryParse(routeNode.Attributes?["safetyMargin"]?.Value, out double safetyMargin) ? safetyMargin : 0, GridSize = double.TryParse(routeNode.Attributes?["gridSize"]?.Value, out double gridSize) ? gridSize : 0, LiftHeightMeters = double.TryParse(routeNode.Attributes?["liftHeightMeters"]?.Value, out double liftHeight) ? liftHeight : 0 @@ -1212,13 +1212,13 @@ namespace NavisworksTransport pathElement.SetAttribute("length", route.TotalLength.ToString("F3")); // 添加车辆限制元素 - var vehicleConstraints = xmlDoc.CreateElement("VehicleConstraints", _delmiaNamespace); - vehicleConstraints.SetAttribute("maxLength", route.MaxVehicleLength.ToString("F3")); - vehicleConstraints.SetAttribute("maxWidth", route.MaxVehicleWidth.ToString("F3")); - vehicleConstraints.SetAttribute("maxHeight", route.MaxVehicleHeight.ToString("F3")); - vehicleConstraints.SetAttribute("safetyMargin", route.SafetyMargin.ToString("F3")); - vehicleConstraints.SetAttribute("gridSize", route.GridSize.ToString("F3")); - pathElement.AppendChild(vehicleConstraints); + var ObjectConstraints = xmlDoc.CreateElement("ObjectConstraints", _delmiaNamespace); + ObjectConstraints.SetAttribute("maxLength", route.MaxObjectLength.ToString("F3")); + ObjectConstraints.SetAttribute("maxWidth", route.MaxObjectWidth.ToString("F3")); + ObjectConstraints.SetAttribute("maxHeight", route.MaxObjectHeight.ToString("F3")); + ObjectConstraints.SetAttribute("safetyMargin", route.SafetyMargin.ToString("F3")); + ObjectConstraints.SetAttribute("gridSize", route.GridSize.ToString("F3")); + pathElement.AppendChild(ObjectConstraints); // 添加路径段 var segmentsElement = xmlDoc.CreateElement("Segments", _delmiaNamespace); diff --git a/src/Core/PathDatabase.cs b/src/Core/PathDatabase.cs index b531b35..61036d4 100644 --- a/src/Core/PathDatabase.cs +++ b/src/Core/PathDatabase.cs @@ -62,6 +62,12 @@ namespace NavisworksTransport // 这样可以确保所有表都存在,避免在旧数据库中缺少新表的问题 CreateTables(); + // 执行数据库迁移(处理字段名变更等) + if (!isNewDatabase) + { + RunMigrations(); + } + if (isNewDatabase) { LogManager.Info($"创建新数据库: {_dbPath}"); @@ -86,9 +92,9 @@ namespace NavisworksTransport EstimatedTime REAL, TurnRadius REAL, IsCurved INTEGER, - MaxVehicleLength REAL, - MaxVehicleWidth REAL, - MaxVehicleHeight REAL, + MaxObjectLength REAL, + MaxObjectWidth REAL, + MaxObjectHeight REAL, SafetyMargin REAL, GridSize REAL, PathType INTEGER, @@ -184,12 +190,12 @@ namespace NavisworksTransport Duration REAL, DetectionGap REAL, AnimatedObjectName TEXT, - IsVirtualVehicle INTEGER, - VehicleModelIndex INTEGER, - VehiclePathId TEXT, - VirtualVehicleLength REAL, - VirtualVehicleWidth REAL, - VirtualVehicleHeight REAL, + IsVirtualObject INTEGER, + ObjectModelIndex INTEGER, + ObjectPathId TEXT, + VirtualObjectLength REAL, + VirtualObjectWidth REAL, + VirtualObjectHeight REAL, CreatedAt DATETIME DEFAULT CURRENT_TIMESTAMP ) "); @@ -260,10 +266,10 @@ namespace NavisworksTransport FrameRate INTEGER NOT NULL, DurationSeconds REAL NOT NULL, DetectionToleranceMeters REAL NOT NULL, - IsVirtualVehicle INTEGER NOT NULL, - VirtualVehicleLength REAL, - VirtualVehicleWidth REAL, - VirtualVehicleHeight REAL, + IsVirtualObject INTEGER NOT NULL, + VirtualObjectLength REAL, + VirtualObjectWidth REAL, + VirtualObjectHeight REAL, DetectAllObjects INTEGER NOT NULL DEFAULT 1, ClashDetectiveTestName TEXT, CollisionCount INTEGER, @@ -339,6 +345,124 @@ namespace NavisworksTransport ExecuteNonQuery("CREATE INDEX IF NOT EXISTS idx_clash_excluded_object ON ClashDetectiveExcludedObjects(ExcludedObjectId)"); } + /// + /// 执行数据库迁移 + /// 处理字段名变更等结构升级 + /// + private void RunMigrations() + { + try + { + // 迁移1: ClashDetectiveResults 表字段名变更 (VirtualVehicleXxx -> VirtualObjectXxx) + MigrateClashDetectiveResultsTable(); + + // 迁移2: BatchQueueItems 表字段名变更 + MigrateBatchQueueItemsTable(); + } + catch (Exception ex) + { + LogManager.Warning($"[数据库迁移] 执行迁移时出错: {ex.Message}"); + } + } + + /// + /// 迁移 ClashDetectiveResults 表字段名 + /// + private void MigrateClashDetectiveResultsTable() + { + try + { + // 检查是否存在旧字段名 + var columns = GetTableColumns("ClashDetectiveResults"); + + // 迁移 VirtualVehicleWidth -> VirtualObjectWidth + if (columns.Contains("VirtualVehicleWidth") && !columns.Contains("VirtualObjectWidth")) + { + ExecuteNonQuery("ALTER TABLE ClashDetectiveResults RENAME COLUMN VirtualVehicleWidth TO VirtualObjectWidth"); + LogManager.Info("[数据库迁移] ClashDetectiveResults.VirtualVehicleWidth -> VirtualObjectWidth"); + } + + // 迁移 VirtualVehicleHeight -> VirtualObjectHeight + if (columns.Contains("VirtualVehicleHeight") && !columns.Contains("VirtualObjectHeight")) + { + ExecuteNonQuery("ALTER TABLE ClashDetectiveResults RENAME COLUMN VirtualVehicleHeight TO VirtualObjectHeight"); + LogManager.Info("[数据库迁移] ClashDetectiveResults.VirtualVehicleHeight -> VirtualObjectHeight"); + } + + // 迁移 VirtualObjecctLength -> VirtualObjectLength (同时修复拼写错误) + if (columns.Contains("VirtualObjecctLength") && !columns.Contains("VirtualObjectLength")) + { + ExecuteNonQuery("ALTER TABLE ClashDetectiveResults RENAME COLUMN VirtualObjecctLength TO VirtualObjectLength"); + LogManager.Info("[数据库迁移] ClashDetectiveResults.VirtualObjecctLength -> VirtualObjectLength"); + } + } + catch (Exception ex) + { + LogManager.Warning($"[数据库迁移] ClashDetectiveResults 表迁移失败: {ex.Message}"); + } + } + + /// + /// 迁移 BatchQueueItems 表字段名 + /// + private void MigrateBatchQueueItemsTable() + { + try + { + // 检查是否存在旧字段名 + var columns = GetTableColumns("BatchQueueItems"); + + // 迁移 VirtualVehicleWidth -> VirtualObjectWidth + if (columns.Contains("VirtualVehicleWidth") && !columns.Contains("VirtualObjectWidth")) + { + ExecuteNonQuery("ALTER TABLE BatchQueueItems RENAME COLUMN VirtualVehicleWidth TO VirtualObjectWidth"); + LogManager.Info("[数据库迁移] BatchQueueItems.VirtualVehicleWidth -> VirtualObjectWidth"); + } + + // 迁移 VirtualVehicleHeight -> VirtualObjectHeight + if (columns.Contains("VirtualVehicleHeight") && !columns.Contains("VirtualObjectHeight")) + { + ExecuteNonQuery("ALTER TABLE BatchQueueItems RENAME COLUMN VirtualVehicleHeight TO VirtualObjectHeight"); + LogManager.Info("[数据库迁移] BatchQueueItems.VirtualVehicleHeight -> VirtualObjectHeight"); + } + + // 迁移 VirtualObjecctLength -> VirtualObjectLength + if (columns.Contains("VirtualObjecctLength") && !columns.Contains("VirtualObjectLength")) + { + ExecuteNonQuery("ALTER TABLE BatchQueueItems RENAME COLUMN VirtualObjecctLength TO VirtualObjectLength"); + LogManager.Info("[数据库迁移] BatchQueueItems.VirtualObjecctLength -> VirtualObjectLength"); + } + } + catch (Exception ex) + { + LogManager.Warning($"[数据库迁移] BatchQueueItems 表迁移失败: {ex.Message}"); + } + } + + /// + /// 获取表的列名列表 + /// + private List GetTableColumns(string tableName) + { + var columns = new List(); + try + { + using (var cmd = new SQLiteCommand($"PRAGMA table_info({tableName})", _connection)) + using (var reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + columns.Add(reader["name"].ToString()); + } + } + } + catch (Exception ex) + { + LogManager.Warning($"[数据库迁移] 获取 {tableName} 表列信息失败: {ex.Message}"); + } + return columns; + } + /// /// 保存路径基本信息 /// @@ -352,7 +476,7 @@ namespace NavisworksTransport // 保存路径基本信息 var sql = @" INSERT OR REPLACE INTO PathRoutes - (Id, Name, TotalLength, EstimatedTime, TurnRadius, IsCurved, MaxVehicleLength, MaxVehicleWidth, MaxVehicleHeight, SafetyMargin, GridSize, PathType, LiftHeightMeters, CreatedTime, LastModified) + (Id, Name, TotalLength, EstimatedTime, TurnRadius, IsCurved, MaxObjectLength, MaxObjectWidth, MaxObjectHeight, SafetyMargin, GridSize, PathType, LiftHeightMeters, CreatedTime, LastModified) VALUES (@id, @name, @length, @time, @turnRadius, @isCurved, @maxLength, @maxWidth, @maxHeight, @safetyMargin, @gridSize, @pathType, @liftHeightMeters, @created, @modified) "; @@ -364,9 +488,9 @@ namespace NavisworksTransport cmd.Parameters.AddWithValue("@time", route.EstimatedTime); cmd.Parameters.AddWithValue("@turnRadius", route.TurnRadius); cmd.Parameters.AddWithValue("@isCurved", route.IsCurved ? 1 : 0); - cmd.Parameters.AddWithValue("@maxLength", route.MaxVehicleLength); - cmd.Parameters.AddWithValue("@maxWidth", route.MaxVehicleWidth); - cmd.Parameters.AddWithValue("@maxHeight", route.MaxVehicleHeight); + cmd.Parameters.AddWithValue("@maxLength", route.MaxObjectLength); + cmd.Parameters.AddWithValue("@maxWidth", route.MaxObjectWidth); + cmd.Parameters.AddWithValue("@maxHeight", route.MaxObjectHeight); cmd.Parameters.AddWithValue("@safetyMargin", route.SafetyMargin); cmd.Parameters.AddWithValue("@gridSize", route.GridSize); cmd.Parameters.AddWithValue("@pathType", (int)route.PathType); @@ -755,11 +879,11 @@ namespace NavisworksTransport var sql = @" INSERT INTO ClashDetectiveResults (TestName, RouteId, TestTime, CollisionCount, AnimationCollisionCount, - FrameRate, Duration, DetectionGap, AnimatedObjectName, IsVirtualVehicle, VehicleModelIndex, VehiclePathId, - VirtualVehicleLength, VirtualVehicleWidth, VirtualVehicleHeight, CreatedAt) + FrameRate, Duration, DetectionGap, AnimatedObjectName, IsVirtualObject, ObjectModelIndex, ObjectPathId, + VirtualObjectLength, VirtualObjectWidth, VirtualObjectHeight, CreatedAt) VALUES (@testName, @routeId, @testTime, @collisionCount, @animationCollisionCount, - @frameRate, @duration, @detectionGap, @animatedObjectName, @isVirtualVehicle, @vehicleModelIndex, @vehiclePathId, - @virtualVehicleLength, @virtualVehicleWidth, @virtualVehicleHeight, @createdAt) + @frameRate, @duration, @detectionGap, @animatedObjectName, @isVirtualObject, @ObjectModelIndex, @ObjectPathId, + @virtualObjectLength, @virtualObjectWidth, @virtualObjectHeight, @createdAt) "; long newId = 0; @@ -774,12 +898,12 @@ namespace NavisworksTransport cmd.Parameters.AddWithValue("@duration", record.Duration); cmd.Parameters.AddWithValue("@detectionGap", record.DetectionGap); cmd.Parameters.AddWithValue("@animatedObjectName", record.AnimatedObjectName ?? ""); - cmd.Parameters.AddWithValue("@isVirtualVehicle", record.IsVirtualVehicle); - cmd.Parameters.AddWithValue("@vehicleModelIndex", record.VehicleModelIndex.HasValue ? (object)record.VehicleModelIndex.Value : DBNull.Value); - cmd.Parameters.AddWithValue("@vehiclePathId", record.VehiclePathId ?? (object)DBNull.Value); - cmd.Parameters.AddWithValue("@virtualVehicleLength", record.VirtualVehicleLength); - cmd.Parameters.AddWithValue("@virtualVehicleWidth", record.VirtualVehicleWidth); - cmd.Parameters.AddWithValue("@virtualVehicleHeight", record.VirtualVehicleHeight); + cmd.Parameters.AddWithValue("@isVirtualObject", record.IsVirtualObject); + cmd.Parameters.AddWithValue("@ObjectModelIndex", record.ObjectModelIndex.HasValue ? (object)record.ObjectModelIndex.Value : DBNull.Value); + cmd.Parameters.AddWithValue("@ObjectPathId", record.ObjectPathId ?? (object)DBNull.Value); + cmd.Parameters.AddWithValue("@virtualObjectLength", record.VirtualObjectLength); + cmd.Parameters.AddWithValue("@virtualObjectWidth", record.VirtualObjectWidth); + cmd.Parameters.AddWithValue("@virtualObjectHeight", record.VirtualObjectHeight); cmd.Parameters.AddWithValue("@createdAt", record.CreatedAt); cmd.ExecuteNonQuery(); newId = _connection.LastInsertRowId; @@ -1320,9 +1444,9 @@ namespace NavisworksTransport EstimatedTime = Convert.ToDouble(reader["EstimatedTime"]), TurnRadius = Convert.ToDouble(reader["TurnRadius"]), IsCurved = Convert.ToInt32(reader["IsCurved"]) == 1, - MaxVehicleLength = Convert.ToDouble(reader["MaxVehicleLength"]), - MaxVehicleWidth = Convert.ToDouble(reader["MaxVehicleWidth"]), - MaxVehicleHeight = Convert.ToDouble(reader["MaxVehicleHeight"]), + MaxObjectLength = Convert.ToDouble(reader["MaxObjectLength"]), + MaxObjectWidth = Convert.ToDouble(reader["MaxObjectWidth"]), + MaxObjectHeight = Convert.ToDouble(reader["MaxObjectHeight"]), SafetyMargin = Convert.ToDouble(reader["SafetyMargin"]), GridSize = Convert.ToDouble(reader["GridSize"]), PathType = (PathType)Convert.ToInt32(reader["PathType"]), @@ -2099,7 +2223,7 @@ namespace NavisworksTransport using (var cmd = new SQLiteCommand(_connection)) { cmd.CommandText = @" - SELECT Id, TestName, PathName, RouteId, TestTime, CollisionCount, AnimationCollisionCount, FrameRate, Duration, DetectionGap, AnimatedObjectName, IsVirtualVehicle, VehicleModelIndex, VehiclePathId, VirtualVehicleLength, VirtualVehicleWidth, VirtualVehicleHeight, CreatedAt + SELECT Id, TestName, PathName, RouteId, TestTime, CollisionCount, AnimationCollisionCount, FrameRate, Duration, DetectionGap, AnimatedObjectName, IsVirtualObject, ObjectModelIndex, ObjectPathId, VirtualObjectLength, VirtualObjectWidth, VirtualObjectHeight, CreatedAt FROM ClashDetectiveResults WHERE TestName = @TestName"; @@ -2122,12 +2246,12 @@ namespace NavisworksTransport Duration = Convert.ToDouble(reader["Duration"]), DetectionGap = Convert.ToDouble(reader["DetectionGap"]), AnimatedObjectName = reader["AnimatedObjectName"].ToString(), - IsVirtualVehicle = Convert.ToBoolean(reader["IsVirtualVehicle"]), - VehicleModelIndex = !Convert.IsDBNull(reader["VehicleModelIndex"]) ? (int?)Convert.ToInt32(reader["VehicleModelIndex"]) : null, - VehiclePathId = reader["VehiclePathId"].ToString(), - VirtualVehicleLength = Convert.ToDouble(reader["VirtualVehicleLength"]), - VirtualVehicleWidth = Convert.ToDouble(reader["VirtualVehicleWidth"]), - VirtualVehicleHeight = Convert.ToDouble(reader["VirtualVehicleHeight"]), + IsVirtualObject = Convert.ToBoolean(reader["IsVirtualObject"]), + ObjectModelIndex = !Convert.IsDBNull(reader["ObjectModelIndex"]) ? (int?)Convert.ToInt32(reader["ObjectModelIndex"]) : null, + ObjectPathId = reader["ObjectPathId"].ToString(), + VirtualObjectLength = Convert.ToDouble(reader["VirtualObjectLength"]), + VirtualObjectWidth = Convert.ToDouble(reader["VirtualObjectWidth"]), + VirtualObjectHeight = Convert.ToDouble(reader["VirtualObjectHeight"]), CreatedAt = DateTime.Parse(reader["CreatedAt"].ToString()) }; } @@ -2157,7 +2281,7 @@ namespace NavisworksTransport { cmd.CommandText = @" SELECT Id, Name, CreatedTime, LastModified, TotalLength, - TurnRadius, IsCurved, MaxVehicleLength, MaxVehicleWidth, MaxVehicleHeight, + TurnRadius, IsCurved, MaxObjectLength, MaxObjectWidth, MaxObjectHeight, SafetyMargin, GridSize, PathType, LiftHeightMeters FROM PathRoutes WHERE Id = @Id"; @@ -2176,9 +2300,9 @@ namespace NavisworksTransport TotalLength = Convert.ToDouble(reader["TotalLength"]), TurnRadius = Convert.ToDouble(reader["TurnRadius"]), IsCurved = Convert.ToInt32(reader["IsCurved"]) == 1, - MaxVehicleLength = Convert.ToDouble(reader["MaxVehicleLength"]), - MaxVehicleWidth = Convert.ToDouble(reader["MaxVehicleWidth"]), - MaxVehicleHeight = Convert.ToDouble(reader["MaxVehicleHeight"]), + MaxObjectLength = Convert.ToDouble(reader["MaxObjectLength"]), + MaxObjectWidth = Convert.ToDouble(reader["MaxObjectWidth"]), + MaxObjectHeight = Convert.ToDouble(reader["MaxObjectHeight"]), SafetyMargin = Convert.ToDouble(reader["SafetyMargin"]), GridSize = Convert.ToDouble(reader["GridSize"]), PathType = (PathType)Convert.ToInt32(reader["PathType"]), @@ -2212,14 +2336,14 @@ namespace NavisworksTransport INSERT INTO BatchQueueItems ( RouteId, Status, CreatedTime, StartTime, EndTime, ErrorMessage, FrameRate, DurationSeconds, DetectionToleranceMeters, - IsVirtualVehicle, VirtualVehicleLength, VirtualVehicleWidth, VirtualVehicleHeight, + IsVirtualObject, VirtualObjectLength, VirtualObjectWidth, VirtualObjectHeight, DetectAllObjects, ClashDetectiveTestName, CollisionCount, ObjectRotationCorrection ) VALUES ( @RouteId, @Status, @CreatedTime, @StartTime, @EndTime, @ErrorMessage, @FrameRate, @DurationSeconds, @DetectionToleranceMeters, - @IsVirtualVehicle, @VirtualVehicleLength, @VirtualVehicleWidth, @VirtualVehicleHeight, + @IsVirtualObject, @VirtualObjectLength, @VirtualObjectWidth, @VirtualObjectHeight, @DetectAllObjects, @ClashDetectiveTestName, @CollisionCount, @ObjectRotationCorrection ); @@ -2234,10 +2358,10 @@ namespace NavisworksTransport cmd.Parameters.AddWithValue("@FrameRate", item.FrameRate); cmd.Parameters.AddWithValue("@DurationSeconds", item.DurationSeconds); cmd.Parameters.AddWithValue("@DetectionToleranceMeters", item.DetectionToleranceMeters); - cmd.Parameters.AddWithValue("@IsVirtualVehicle", item.IsVirtualVehicle ? 1 : 0); - cmd.Parameters.AddWithValue("@VirtualVehicleLength", item.VirtualVehicleLength); - cmd.Parameters.AddWithValue("@VirtualVehicleWidth", item.VirtualVehicleWidth); - cmd.Parameters.AddWithValue("@VirtualVehicleHeight", item.VirtualVehicleHeight); + cmd.Parameters.AddWithValue("@IsVirtualObject", item.IsVirtualObject ? 1 : 0); + cmd.Parameters.AddWithValue("@VirtualObjectLength", item.VirtualObjectLength); + cmd.Parameters.AddWithValue("@VirtualObjectWidth", item.VirtualObjectWidth); + cmd.Parameters.AddWithValue("@VirtualObjectHeight", item.VirtualObjectHeight); cmd.Parameters.AddWithValue("@DetectAllObjects", item.DetectAllObjects ? 1 : 0); cmd.Parameters.AddWithValue("@ClashDetectiveTestName", item.ClashDetectiveTestName ?? ""); cmd.Parameters.AddWithValue("@CollisionCount", item.CollisionCount ?? (object)DBNull.Value); @@ -2261,7 +2385,7 @@ namespace NavisworksTransport private BatchQueueItem ReadBatchQueueItemFromReader(SQLiteDataReader reader) { var itemId = Convert.ToInt32(reader["Id"]); - var isVirtualVehicle = Convert.ToBoolean(reader["IsVirtualVehicle"]); + var isVirtualObject = Convert.ToBoolean(reader["IsVirtualObject"]); var item = new BatchQueueItem { @@ -2277,10 +2401,10 @@ namespace NavisworksTransport FrameRate = Convert.ToInt32(reader["FrameRate"]), DurationSeconds = Convert.ToDouble(reader["DurationSeconds"]), DetectionToleranceMeters = Convert.ToDouble(reader["DetectionToleranceMeters"]), - IsVirtualVehicle = isVirtualVehicle, - VirtualVehicleLength = Convert.ToDouble(reader["VirtualVehicleLength"]), - VirtualVehicleWidth = Convert.ToDouble(reader["VirtualVehicleWidth"]), - VirtualVehicleHeight = Convert.ToDouble(reader["VirtualVehicleHeight"]), + IsVirtualObject = isVirtualObject, + VirtualObjectLength = Convert.ToDouble(reader["VirtualObjectLength"]), + VirtualObjectWidth = Convert.ToDouble(reader["VirtualObjectWidth"]), + VirtualObjectHeight = Convert.ToDouble(reader["VirtualObjectHeight"]), DetectAllObjects = Convert.ToBoolean(reader["DetectAllObjects"]), ClashDetectiveTestName = reader["ClashDetectiveTestName"].ToString(), CollisionCount = !Convert.IsDBNull(reader["CollisionCount"]) ? (int?)Convert.ToInt32(reader["CollisionCount"]) : null, @@ -2288,7 +2412,7 @@ namespace NavisworksTransport }; // 填充 MovingObjectName 属性 - if (!isVirtualVehicle) + if (!isVirtualObject) { // 从 ModelItemReferences 表查询运动物体名称 var movingObjectReferences = GetModelItemReferencesSync(itemId, "BatchQueueItem", "MovingObject"); @@ -2315,7 +2439,7 @@ namespace NavisworksTransport var sql = @" SELECT bqi.Id, bqi.RouteId, pr.Name AS PathRouteName, pr.PathType, bqi.Status, bqi.CreatedTime, bqi.StartTime, bqi.EndTime, bqi.ErrorMessage, bqi.FrameRate, bqi.DurationSeconds, bqi.DetectionToleranceMeters, - bqi.IsVirtualVehicle, bqi.VirtualVehicleLength, bqi.VirtualVehicleWidth, bqi.VirtualVehicleHeight, + bqi.IsVirtualObject, bqi.VirtualObjectLength, bqi.VirtualObjectWidth, bqi.VirtualObjectHeight, bqi.DetectAllObjects, bqi.ClashDetectiveTestName, bqi.CollisionCount, bqi.ObjectRotationCorrection FROM BatchQueueItems bqi @@ -2374,7 +2498,7 @@ namespace NavisworksTransport cmd.CommandText = @" SELECT bqi.Id, bqi.RouteId, pr.Name AS PathRouteName, pr.PathType, bqi.Status, bqi.CreatedTime, bqi.StartTime, bqi.EndTime, bqi.ErrorMessage, bqi.FrameRate, bqi.DurationSeconds, bqi.DetectionToleranceMeters, - bqi.IsVirtualVehicle, bqi.VirtualVehicleLength, bqi.VirtualVehicleWidth, bqi.VirtualVehicleHeight, + bqi.IsVirtualObject, bqi.VirtualObjectLength, bqi.VirtualObjectWidth, bqi.VirtualObjectHeight, bqi.DetectAllObjects, bqi.ClashDetectiveTestName, bqi.CollisionCount, bqi.ObjectRotationCorrection FROM BatchQueueItems bqi @@ -2607,12 +2731,12 @@ namespace NavisworksTransport public double Duration { get; set; } public double DetectionGap { get; set; } public string AnimatedObjectName { get; set; } - public bool IsVirtualVehicle { get; set; } - public int? VehicleModelIndex { get; set; } - public string VehiclePathId { get; set; } - public double VirtualVehicleLength { get; set; } - public double VirtualVehicleWidth { get; set; } - public double VirtualVehicleHeight { get; set; } + public bool IsVirtualObject { get; set; } + public int? ObjectModelIndex { get; set; } + public string ObjectPathId { get; set; } + public double VirtualObjectLength { get; set; } + public double VirtualObjectWidth { get; set; } + public double VirtualObjectHeight { get; set; } public DateTime CreatedAt { get; set; } } diff --git a/src/Core/PathPlanningManager.cs b/src/Core/PathPlanningManager.cs index d97c6a1..9913a1d 100644 --- a/src/Core/PathPlanningManager.cs +++ b/src/Core/PathPlanningManager.cs @@ -74,7 +74,7 @@ namespace NavisworksTransport private bool _showUnknownGrid = false; private bool _showDoorGrid = false; private GridMap _currentGridMap = null; // 保存当前网格地图用于刷新 - private double _currentVehicleHeight = 2.0; // 保存当前车辆高度(米)用于网格刷新 + private double _currentObjectHeight = 2.0; // 保存当前物体高度(米)用于网格刷新 private bool _isPreviewMode = false; private int _previewInsertIndex = -1; // 保存预览点应该插入的索引位置 @@ -141,7 +141,7 @@ namespace NavisworksTransport LogManager.Info("[路径管理] ✅ PathPointRenderPlugin实例获取成功"); LogManager.Debug($"[路径管理] 渲染插件状态 - 启用: {_renderPlugin.IsEnabled}, 标记数量: {_renderPlugin.MarkerCount}"); - // 推送默认的网格大小和车辆参数,确保渲染插件有合理的初始值 + // 推送默认的网格大小和物体参数,确保渲染插件有合理的初始值 InitializeRenderPluginDefaults(); } else @@ -205,7 +205,7 @@ namespace NavisworksTransport /// /// 初始化渲染插件的默认值 - /// 从配置文件读取网格大小和车辆参数,确保渲染插件在任何情况下都有正确的可视化效果 + /// 从配置文件读取网格大小和物体参数,确保渲染插件在任何情况下都有正确的可视化效果 /// private void InitializeRenderPluginDefaults() { @@ -1011,13 +1011,13 @@ namespace NavisworksTransport /// /// 起点 /// 终点 - /// 车辆尺寸(米) + /// 物体尺寸(米) /// 安全间隙(米) /// 网格精度(米) - /// 车辆高度(米) + /// 物体高度(米) /// 路径规划策略 /// 规划结果 - public Task AutoPlanPath(PathPoint startPoint, PathPoint endPoint, double vehicleRadius, double safetyMargin, double gridSize, double vehicleHeight, PathStrategy strategy) + public Task AutoPlanPath(PathPoint startPoint, PathPoint endPoint, double ObjectRadius, double safetyMargin, double gridSize, double ObjectHeight, PathStrategy strategy) { try { @@ -1029,7 +1029,7 @@ namespace NavisworksTransport LogManager.Info($"开始自动路径规划: {startPoint.Name} -> {endPoint.Name}"); LogManager.Info($"起点坐标: ({startPoint.Position.X:F2}, {startPoint.Position.Y:F2}, {startPoint.Position.Z:F2})"); LogManager.Info($"终点坐标: ({endPoint.Position.X:F2}, {endPoint.Position.Y:F2}, {endPoint.Position.Z:F2})"); - LogManager.Info($"车辆半径: {vehicleRadius}m, 安全间隙: {safetyMargin}m, 车辆高度: {vehicleHeight}m"); + LogManager.Info($"物体半径: {ObjectRadius}m, 安全间隙: {safetyMargin}m, 物体高度: {ObjectHeight}m"); RaiseStatusChanged("正在进行自动路径规划...", PathPlanningStatusType.Info); @@ -1060,7 +1060,7 @@ namespace NavisworksTransport // 获取当前文档 var document = Application.ActiveDocument; LogManager.Info($"网格生成参数 - 边界: {bounds.Min.X:F2},{bounds.Min.Y:F2} -> {bounds.Max.X:F2},{bounds.Max.Y:F2}"); - LogManager.Info($"网格生成参数 - 网格大小: {gridSize}m, 车辆半径: {vehicleRadius}m, 安全边距: {safetyMargin}m"); + LogManager.Info($"网格生成参数 - 网格大小: {gridSize}m, 物体半径: {ObjectRadius}m, 安全边距: {safetyMargin}m"); LogManager.Info($"网格生成参数 - 起点: ({startPoint.Position.X:F2}, {startPoint.Position.Y:F2}, {startPoint.Position.Z:F2})"); LogManager.Info($"网格生成参数 - 终点: ({endPoint.Position.X:F2}, {endPoint.Position.Y:F2}, {endPoint.Position.Z:F2})"); @@ -1069,11 +1069,11 @@ namespace NavisworksTransport gridMap = gridMapGenerator.GenerateFromBIM( bounds, gridSize, - vehicleRadius, + ObjectRadius, safetyMargin, startPoint.Position, endPoint.Position, - vehicleHeight + ObjectHeight ); LogManager.Info("✅ 网格地图生成成功"); } @@ -1096,7 +1096,7 @@ namespace NavisworksTransport if (_showWalkableGrid || _showObstacleGrid || _showUnknownGrid || _showDoorGrid) { LogManager.Info("开始网格可视化,显示所有可通行网格单元"); - VisualizeGridCells(gridMap, vehicleHeight); + VisualizeGridCells(gridMap, ObjectHeight); } // 3. 获取通道高度数据 @@ -1132,9 +1132,9 @@ namespace NavisworksTransport try { pathFinder = new AutoPathFinder(); - double vehicleHeightInModelUnits = vehicleHeight * UnitsConverter.GetMetersToUnitsConversionFactor(Application.ActiveDocument.Units); - LogManager.Info($"使用2.5D模式进行路径查找,车辆高度: {vehicleHeight}m ({vehicleHeightInModelUnits:F2}模型单位),策略: {strategy}"); - pathResult = pathFinder.FindPath(startPoint.Position, endPoint.Position, gridMap, channelCoverage, vehicleHeightInModelUnits, strategy); + double ObjectHeightInModelUnits = ObjectHeight * UnitsConverter.GetMetersToUnitsConversionFactor(Application.ActiveDocument.Units); + LogManager.Info($"使用2.5D模式进行路径查找,物体高度: {ObjectHeight}m ({ObjectHeightInModelUnits:F2}模型单位),策略: {strategy}"); + pathResult = pathFinder.FindPath(startPoint.Position, endPoint.Position, gridMap, channelCoverage, ObjectHeightInModelUnits, strategy); LogManager.Info("FindPath方法调用完成"); } catch (Exception ex) @@ -1170,10 +1170,10 @@ namespace NavisworksTransport // 保存GridMap和参数到PathRoute以便后续恢复网格可视化 autoRoute.AssociatedGridMap = gridMap; autoRoute.GridSize = gridSize; - // 将vehicleRadius拆分为长宽(暂时使用相同值,后续可以传入更详细的参数) - autoRoute.MaxVehicleLength = vehicleRadius * 2; // 车辆半径转换为长度 - autoRoute.MaxVehicleWidth = vehicleRadius * 2; // 车辆半径转换为宽度 - autoRoute.MaxVehicleHeight = vehicleHeight; + // 将ObjectRadius拆分为长宽(暂时使用相同值,后续可以传入更详细的参数) + autoRoute.MaxObjectLength = ObjectRadius * 2; // 物体半径转换为长度 + autoRoute.MaxObjectWidth = ObjectRadius * 2; // 物体半径转换为宽度 + autoRoute.MaxObjectHeight = ObjectHeight; autoRoute.SafetyMargin = safetyMargin; LogManager.Info($"已保存GridMap到路径: {routeName}, 网格大小: {gridSize}米"); @@ -4535,7 +4535,7 @@ namespace NavisworksTransport if (_currentGridMap != null && IsAnyGridVisualizationEnabled) { LogManager.Info("[网格可视化] 使用缓存的网格地图重新渲染"); - VisualizeGridCells(_currentGridMap, _currentVehicleHeight); + VisualizeGridCells(_currentGridMap, _currentObjectHeight); } else if (_currentGridMap == null) { @@ -4557,8 +4557,8 @@ namespace NavisworksTransport /// 在每个可通行网格的中心绘制一个绿色小球 /// /// 要可视化的网格地图 - /// 车辆高度(米),用于判断层高是否足够 - public void VisualizeGridCells(GridMap gridMap, double vehicleHeight = 2.0) + /// 物体高度(米),用于判断层高是否足够 + public void VisualizeGridCells(GridMap gridMap, double ObjectHeight = 2.0) { if (gridMap == null) { @@ -4568,10 +4568,10 @@ namespace NavisworksTransport try { - // 保存当前网格地图和车辆高度用于后续刷新 + // 保存当前网格地图和物体高度用于后续刷新 _currentGridMap = gridMap; - _currentVehicleHeight = vehicleHeight; - LogManager.Info($"[网格可视化] 开始可视化网格:{gridMap.Width}x{gridMap.Height}, 车辆高度:{vehicleHeight}m"); + _currentObjectHeight = ObjectHeight; + LogManager.Info($"[网格可视化] 开始可视化网格:{gridMap.Width}x{gridMap.Height}, 物体高度:{ObjectHeight}m"); // 获取渲染插件 var renderPlugin = PathPointRenderPlugin.Instance; diff --git a/src/Core/PathPlanningModels.cs b/src/Core/PathPlanningModels.cs index 917bed0..38ea9c3 100644 --- a/src/Core/PathPlanningModels.cs +++ b/src/Core/PathPlanningModels.cs @@ -570,17 +570,17 @@ namespace NavisworksTransport /// /// 最大车辆长度(米) - 路径适用的车辆长度限制 /// - public double MaxVehicleLength { get; set; } + public double MaxObjectLength { get; set; } /// /// 最大车辆宽度(米) - 路径适用的车辆宽度限制 /// - public double MaxVehicleWidth { get; set; } + public double MaxObjectWidth { get; set; } /// /// 最大车辆高度(米) - 路径适用的车辆高度限制 /// - public double MaxVehicleHeight { get; set; } + public double MaxObjectHeight { get; set; } /// /// 安全间隙(米) @@ -906,9 +906,9 @@ namespace NavisworksTransport CompletionPercentage = CompletionPercentage, AssociatedGridMap = AssociatedGridMap, // 共享引用,不深拷贝 GridSize = GridSize, - MaxVehicleLength = MaxVehicleLength, - MaxVehicleWidth = MaxVehicleWidth, - MaxVehicleHeight = MaxVehicleHeight, + MaxObjectLength = MaxObjectLength, + MaxObjectWidth = MaxObjectWidth, + MaxObjectHeight = MaxObjectHeight, SafetyMargin = SafetyMargin }; @@ -1428,7 +1428,7 @@ namespace NavisworksTransport // 获取通道属性信息 string channelType = "通道"; string traversable = "是"; - string vehicleSize = "标准"; + string ObjectSize = "标准"; try { @@ -1456,7 +1456,7 @@ namespace NavisworksTransport // 添加子项 item.SubItems.Add(channelType); item.SubItems.Add(traversable); - item.SubItems.Add(vehicleSize); + item.SubItems.Add(ObjectSize); item.SubItems.Add(length.ToString("F2")); item.SubItems.Add(width.ToString("F2")); item.SubItems.Add(height.ToString("F2")); diff --git a/src/Core/PathPointRenderPlugin.cs b/src/Core/PathPointRenderPlugin.cs index b356697..555da3e 100644 --- a/src/Core/PathPointRenderPlugin.cs +++ b/src/Core/PathPointRenderPlugin.cs @@ -25,9 +25,9 @@ namespace NavisworksTransport RibbonLine, /// - /// 车辆通行空间模式 - 矩形通道 + /// 物体通行空间模式 - 矩形通道 /// - VehicleSpace + ObjectSpace } /// @@ -78,9 +78,9 @@ namespace NavisworksTransport Line, /// - /// 车辆通行空间样式(灰色) + /// 物体通行空间样式(灰色) /// - VehicleSpace, + ObjectSpace, /// /// 预览点样式(白色) @@ -166,9 +166,9 @@ namespace NavisworksTransport } /// - /// 车辆通行空间标记,用于渲染车辆通道空间 + /// 物体通行空间标记,用于渲染物体通道空间 /// - public class VehicleSpaceMarker + public class ObjectSpaceMarker { /// /// 通道起点 @@ -212,7 +212,7 @@ namespace NavisworksTransport public override string ToString() { - return $"VehicleSpaceMarker[{FromIndex}->{ToIndex}, 宽度={Width:F2}m, 高度={Height:F2}m, 透明度={Alpha:F1}]"; + return $"ObjectSpaceMarker[{FromIndex}->{ToIndex}, 宽度={Width:F2}m, 高度={Height:F2}m, 透明度={Alpha:F1}]"; } } @@ -267,12 +267,12 @@ namespace NavisworksTransport public List SampledPoints { get; set; } /// - /// 带状连线高度(仅用于 RibbonLine 和 VehicleSpace 模式) + /// 带状连线高度(仅用于 RibbonLine 和 ObjectSpace 模式) /// public double Height { get; set; } /// - /// 带状连线宽度(仅用于 VehicleSpace 模式) + /// 带状连线宽度(仅用于 ObjectSpace 模式) /// public double Width { get; set; } @@ -328,9 +328,9 @@ namespace NavisworksTransport public List TangentMarkers { get; set; } /// - /// 车辆通行空间标记集合 + /// 物体通行空间标记集合 /// - public List VehicleSpaceMarkers { get; set; } + public List ObjectSpaceMarkers { get; set; } /// /// 是否显示控制点可视化(用户意图) @@ -351,7 +351,7 @@ namespace NavisworksTransport ControlLineMarkers = new List(); PathLineMarkers = new List(); TangentMarkers = new List(); - VehicleSpaceMarkers = new List(); + ObjectSpaceMarkers = new List(); LastUpdated = DateTime.Now; } @@ -388,7 +388,7 @@ namespace NavisworksTransport // 独立可视化开关(替代单一模式) private bool _showPathLines = true; // 显示路径线(地面连线/带状线) - private bool _showVehicleSpace = false; // 显示通行空间 + private bool _showObjectSpace = false; // 显示通行空间 // 网格点类型配置 private GridPointType _gridPointType = GridPointType.Rectangle; @@ -464,14 +464,14 @@ namespace NavisworksTransport public static PathPointRenderPlugin Instance => _instance; /// - /// 路径可视化模式(向后兼容,根据 ShowPathLines 和 ShowVehicleSpace 计算) + /// 路径可视化模式(向后兼容,根据 ShowPathLines 和 ShowObjectSpace 计算) /// public PathVisualizationMode VisualizationMode { get { // 根据新的独立开关计算模式 - if (_showVehicleSpace) return PathVisualizationMode.VehicleSpace; + if (_showObjectSpace) return PathVisualizationMode.ObjectSpace; if (_showPathLines) return PathVisualizationMode.RibbonLine; return PathVisualizationMode.StandardLine; } @@ -479,7 +479,7 @@ namespace NavisworksTransport { _visualizationMode = value; // 同步到新的独立开关 - _showVehicleSpace = (value == PathVisualizationMode.VehicleSpace); + _showObjectSpace = (value == PathVisualizationMode.ObjectSpace); _showPathLines = (value == PathVisualizationMode.RibbonLine || value == PathVisualizationMode.StandardLine); // 模式改变时刷新所有普通路径(排除网格) RefreshNormalPaths(); @@ -500,14 +500,14 @@ namespace NavisworksTransport } /// - /// 是否显示通行空间(车辆通行空间) + /// 是否显示通行空间(物体通行空间) /// - public bool ShowVehicleSpace + public bool ShowObjectSpace { - get { return _showVehicleSpace; } + get { return _showObjectSpace; } set { - _showVehicleSpace = value; + _showObjectSpace = value; RefreshNormalPaths(); } } @@ -654,9 +654,9 @@ namespace NavisworksTransport } // 再渲染通行空间(可以在路径线之上) - if (_showVehicleSpace) + if (_showObjectSpace) { - // VehicleSpace 模式:使用车辆通行空间渲染(高高度长方体) + // ObjectSpace 模式:使用物体通行空间渲染(高高度长方体) foreach (var pathLineMarker in visualization.PathLineMarkers) { RenderRibbonLineMarker(graphics, pathLineMarker); @@ -1290,7 +1290,7 @@ namespace NavisworksTransport visualization.ControlLineMarkers.Clear(); visualization.PathLineMarkers.Clear(); visualization.TangentMarkers.Clear(); - visualization.VehicleSpaceMarkers.Clear(); + visualization.ObjectSpaceMarkers.Clear(); var points = visualization.PathRoute.Points; if (points.Count == 0) return; @@ -1315,7 +1315,7 @@ namespace NavisworksTransport { // 空中路径:默认只显示控制点连线 // 但如果启用了通行空间可视化,则构建路径连线以显示通行空间 - if (_showVehicleSpace) + if (_showObjectSpace) { string aerialSubTypeName = visualization.PathRoute.PathType == NavisworksTransport.PathType.Rail ? "空轨" : "吊装"; BuildPathLines(visualization, sortedPoints); @@ -1406,7 +1406,7 @@ namespace NavisworksTransport Color lineColor; double lineOpacity; - if (_showVehicleSpace) + if (_showObjectSpace) { // 通行空间模式:根据路径类型和段类型计算通行空间尺寸 // _passage* 和 _object* 字段已经是模型单位(由 SetPassageSpaceParameters 转换) @@ -1430,7 +1430,7 @@ namespace NavisworksTransport height = _passageNormalToPath; } - var renderStyle = GetRenderStyle(RenderStyleName.VehicleSpace); + var renderStyle = GetRenderStyle(RenderStyleName.ObjectSpace); lineColor = renderStyle.Color; lineOpacity = renderStyle.Alpha; } @@ -1456,7 +1456,7 @@ namespace NavisworksTransport // 计算通行空间的垂直偏移(根据路径类型) double verticalOffset = 0; - if (_showVehicleSpace) + if (_showObjectSpace) { if (visualization.PathRoute.PathType == NavisworksTransport.PathType.Ground) { @@ -1549,7 +1549,7 @@ namespace NavisworksTransport Point3D adjustedStartPoint; Point3D adjustedEndPoint; - if (_showVehicleSpace && Math.Abs(verticalOffset) > 0.001) + if (_showObjectSpace && Math.Abs(verticalOffset) > 0.001) { // 通行空间模式且有垂直偏移时,沿着up向量方向平移 adjustedStartPoint = new Point3D( @@ -1571,9 +1571,9 @@ namespace NavisworksTransport } // 🔥 地面/空轨路径水平段:起点和终点向路径方向延伸半个物体尺寸(仅通行空间) - if (_showVehicleSpace) + if (_showObjectSpace) { - ExtendLineSegmentForVehicleSpace(ref adjustedStartPoint, ref adjustedEndPoint, _passageAlongPath); + ExtendLineSegmentForObjectSpace(ref adjustedStartPoint, ref adjustedEndPoint, _passageAlongPath); } var lineMarker = new LineMarker @@ -1620,7 +1620,7 @@ namespace NavisworksTransport Point3D adjustedEndPoint; List adjustedSampledPoints; - if (_showVehicleSpace && Math.Abs(verticalOffset) > 0.001) + if (_showObjectSpace && Math.Abs(verticalOffset) > 0.001) { // 通行空间模式且有垂直偏移时,沿着up向量方向平移 adjustedStartPoint = new Point3D( @@ -1657,9 +1657,9 @@ namespace NavisworksTransport } // 🔥 圆弧段:起点和终点向路径方向延伸半个物体尺寸(仅通行空间) - if (_showVehicleSpace) + if (_showObjectSpace) { - ExtendLineSegmentForVehicleSpace(ref adjustedStartPoint, ref adjustedEndPoint, _passageAlongPath); + ExtendLineSegmentForObjectSpace(ref adjustedStartPoint, ref adjustedEndPoint, _passageAlongPath); } var arcMarker = new LineMarker @@ -1847,7 +1847,7 @@ namespace NavisworksTransport Point3D adjustedStartPoint; Point3D adjustedEndPoint; - if (_showVehicleSpace && Math.Abs(verticalOffset) > 0.001) + if (_showObjectSpace && Math.Abs(verticalOffset) > 0.001) { // 通行空间模式且有垂直偏移时,沿着up向量方向平移 adjustedStartPoint = new Point3D( @@ -1869,7 +1869,7 @@ namespace NavisworksTransport } // 🔥 通行空间包裹调整:水平段起点和终点延伸以完全包裹物体(仅通行空间) - if (_showVehicleSpace && !isVerticalSegment) + if (_showObjectSpace && !isVerticalSegment) { // 沿路径方向的物体尺寸(吊装路径根据是否转折90度选择) double alongPathSize = _passageAlongPath; @@ -1877,7 +1877,7 @@ namespace NavisworksTransport { alongPathSize = isTurn90Horizontal ? _passageAcrossPath : _objectLength; } - ExtendLineSegmentForVehicleSpace(ref adjustedStartPoint, ref adjustedEndPoint, alongPathSize); + ExtendLineSegmentForObjectSpace(ref adjustedStartPoint, ref adjustedEndPoint, alongPathSize); } var lineMarker = new LineMarker @@ -1995,21 +1995,21 @@ namespace NavisworksTransport } /// - /// 创建车辆通行空间标记 + /// 创建物体通行空间标记 /// /// 起点 /// 终点 - /// 车辆通行空间标记 - private VehicleSpaceMarker CreateVehicleSpaceMarker(PathPoint fromPoint, PathPoint toPoint) + /// 物体通行空间标记 + private ObjectSpaceMarker CreateObjectSpaceMarker(PathPoint fromPoint, PathPoint toPoint) { - var style = GetRenderStyle(RenderStyleName.VehicleSpace); - return new VehicleSpaceMarker + var style = GetRenderStyle(RenderStyleName.ObjectSpace); + return new ObjectSpaceMarker { StartPoint = fromPoint.Position, EndPoint = toPoint.Position, Width = _passageAcrossPath, // 直接使用模型单位 Height = _passageNormalToPath, // 直接使用模型单位 - Color = style.Color, // 车辆通行空间颜色 + Color = style.Color, // 物体通行空间颜色 Alpha = style.Alpha, // 透明度,统一管理 FromIndex = fromPoint.Index, ToIndex = toPoint.Index @@ -2102,11 +2102,11 @@ namespace NavisworksTransport } /// - /// 设置车辆参数(从PathPlanningManager同步) + /// 设置物体参数(从PathPlanningManager同步) /// - /// 车辆长度(米) - /// 车辆宽度(米) - /// 车辆高度(米) + /// 物体长度(米) + /// 物体宽度(米) + /// 物体高度(米) /// 安全间隙(米) /// 垂直段的高度(物体长度 + 2×安全间隙,模型单位) /// 水平段的高度(物体高度 + 2×安全间隙,模型单位) @@ -2125,7 +2125,7 @@ namespace NavisworksTransport _objectLength = passageNormalToPathVerticalInMeters * factor; _objectHeight = passageNormalToPathHorizontalInMeters * factor; - // 参数改变时刷新所有普通路径(因为RibbonLine模式也使用车辆宽度) + // 参数改变时刷新所有普通路径(因为RibbonLine模式也使用物体宽度) RefreshNormalPaths(); } @@ -2152,7 +2152,7 @@ namespace NavisworksTransport case RenderStyleName.Line: return new RenderStyle(Color.FromByteRGB(255, 152, 0), 0.8); // Material Orange连线,20%透明 - case RenderStyleName.VehicleSpace: + case RenderStyleName.ObjectSpace: { // 从配置读取通行空间透明度,默认为0.4(40%不透明,60%透明) double opacity = ConfigManager.Instance.Current.Visualization.PassageSpaceOpacity; @@ -2759,7 +2759,7 @@ namespace NavisworksTransport lineMarker.SampledPoints != null && lineMarker.SampledPoints.Count >= 2) { - // 圆弧段:在每个采样点渲染完整的车辆长方体 + // 圆弧段:在每个采样点渲染完整的物体长方体 RenderArcSegmentCuboids(graphics, lineMarker, width); } else @@ -2779,8 +2779,8 @@ namespace NavisworksTransport } /// - /// 渲染圆弧段的车辆长方体 - /// 在每个采样点处渲染一个完整的车辆长方体,中心在采样点,向前后各延伸 L/2 + /// 渲染圆弧段的物体长方体 + /// 在每个采样点处渲染一个完整的物体长方体,中心在采样点,向前后各延伸 L/2 /// /// 图形上下文 /// 连线标记(必须是圆弧段) @@ -2790,7 +2790,7 @@ namespace NavisworksTransport // 设置颜色和透明度 graphics.Color(lineMarker.Color, lineMarker.Opacity); - // 在每个采样点处渲染完整的车辆长方体 + // 在每个采样点处渲染完整的物体长方体 for (int i = 0; i < lineMarker.SampledPoints.Count; i++) { // 计算当前采样点的切线方向 @@ -2992,10 +2992,10 @@ namespace NavisworksTransport private void RenderLineMarker(Graphics graphics, LineMarker lineMarker) { // 🔥 路径线渲染逻辑:保持原有行为 - // 注意:ShowVehicleSpace 的通行空间使用 RenderRibbonLineMarker 单独渲染 - if (_visualizationMode == PathVisualizationMode.VehicleSpace || _visualizationMode == PathVisualizationMode.RibbonLine) + // 注意:ShowObjectSpace 的通行空间使用 RenderRibbonLineMarker 单独渲染 + if (_visualizationMode == PathVisualizationMode.ObjectSpace || _visualizationMode == PathVisualizationMode.RibbonLine) { - // VehicleSpace 或 RibbonLine 模式:使用长方体渲染 + // ObjectSpace 或 RibbonLine 模式:使用长方体渲染 RenderRibbonLineMarker(graphics, lineMarker); } else @@ -3039,14 +3039,14 @@ namespace NavisworksTransport } /// - /// 延伸线段起点和终点以完全包裹物体(VehicleSpace模式) + /// 延伸线段起点和终点以完全包裹物体(ObjectSpace模式) /// /// 起点(会被修改) /// 终点(会被修改) - private void ExtendLineSegmentForVehicleSpace(ref Point3D startPoint, ref Point3D endPoint, double alongPathSize) + private void ExtendLineSegmentForObjectSpace(ref Point3D startPoint, ref Point3D endPoint, double alongPathSize) { - // 注意:调用此方法前应该检查 _showVehicleSpace - if (!_showVehicleSpace) + // 注意:调用此方法前应该检查 _showObjectSpace + if (!_showObjectSpace) return; var segDx = endPoint.X - startPoint.X; diff --git a/src/Core/Spatial/SpatialIndexManager.cs b/src/Core/Spatial/SpatialIndexManager.cs index 9af43ed..1c4a7e6 100644 --- a/src/Core/Spatial/SpatialIndexManager.cs +++ b/src/Core/Spatial/SpatialIndexManager.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using System.Linq; using Autodesk.Navisworks.Api; using g4; +using NavisworksTransport.Utils; // 使用命名空间引用以避免类名冲突 using ClashIntegration = NavisworksTransport.ClashDetectiveIntegration; @@ -152,6 +153,7 @@ namespace NavisworksTransport.Core.Spatial /// /// 范围查询:查找指定位置附近的对象 + /// 支持剖面盒精筛(如果剖面盒已启用) /// /// 查询中心位置(Navisworks Point3D) /// 查询半径(模型单位) @@ -175,7 +177,7 @@ namespace NavisworksTransport.Core.Spatial // 转换为 geometry4Sharp 的 Vector3d var centerVec = new Vector3d(position.X, position.Y, position.Z); - // 使用空间哈希网格进行范围查询(带精确距离检查) + // 步骤1:使用空间哈希网格进行范围查询(快速粗筛) var nearbyObjects = _globalSpatialIndex.FindInRadiusExact( centerVec, searchRadiusInModelUnits, @@ -197,7 +199,23 @@ namespace NavisworksTransport.Core.Spatial } ); - // 排除指定对象 + // 步骤2:剖面盒精筛(如果启用) + int beforeClipFilter = nearbyObjects.Count; + if (SectionClipHelper.IsClipBoxEnabled) + { + nearbyObjects = nearbyObjects + .Where(item => SectionClipHelper.IntersectsClipBox(item.BoundingBox())) + .ToList(); + + int filteredCount = beforeClipFilter - nearbyObjects.Count; + LogManager.Debug($"[空间查询] 剖面盒过滤: 粗筛{beforeClipFilter}个 → 精筛{nearbyObjects.Count}个,过滤{filteredCount}个({(beforeClipFilter > 0 ? filteredCount*100.0/beforeClipFilter : 0):F1}%)"); + } + else + { + LogManager.Debug($"[空间查询] 剖面盒未启用,使用全部{beforeClipFilter}个对象"); + } + + // 步骤3:排除指定对象 if (excludeObject != null) { nearbyObjects = nearbyObjects.Where(obj => !obj.Equals(excludeObject)).ToList(); @@ -240,6 +258,7 @@ namespace NavisworksTransport.Core.Spatial /// /// AABB范围查询:查找与指定AABB相交的对象 /// 比球形查询更精确,避免球体扩大的无效范围 + /// 支持剖面盒精筛(如果剖面盒已启用) /// /// 查询AABB(Navisworks BoundingBox3D) /// 要排除的对象 @@ -256,10 +275,40 @@ namespace NavisworksTransport.Core.Spatial try { - // 直接使用AABB查询(更精确) + // 步骤1:使用空间索引进行AABB查询(快速粗筛) var nearbyObjects = _globalSpatialIndex.FindInAABB(bounds); - // 排除指定对象 + // 步骤2:剖面盒精筛(如果启用) + int beforeClipFilter = nearbyObjects.Count; + if (SectionClipHelper.IsClipBoxEnabled) + { + int intersectCount = 0; + int outsideCount = 0; + nearbyObjects = nearbyObjects + .Where(item => { + bool intersects = SectionClipHelper.IntersectsClipBox(item.BoundingBox()); + if (intersects) intersectCount++; + else outsideCount++; + return intersects; + }) + .ToList(); + + int filteredCount = beforeClipFilter - nearbyObjects.Count; + LogManager.Debug($"[AABB查询] 剖面盒过滤: 粗筛{beforeClipFilter}个 → 精筛{nearbyObjects.Count}个,过滤{filteredCount}个({(beforeClipFilter > 0 ? filteredCount*100.0/beforeClipFilter : 0):F1}%)"); + + // 如果全部过滤,输出警告并采样被过滤的对象 + if (nearbyObjects.Count == 0 && beforeClipFilter > 0) + { + SectionClipHelper.TryGetCurrentClipBox(out var clipBox); + LogManager.Warning($"[AABB查询] 剖面盒过滤后无对象!剖面盒范围: X[{clipBox.Min.X:F2},{clipBox.Max.X:F2}], Y[{clipBox.Min.Y:F2},{clipBox.Max.Y:F2}], Z[{clipBox.Min.Z:F2},{clipBox.Max.Z:F2}]"); + } + } + else + { + LogManager.Debug($"[AABB查询] 剖面盒未启用,使用全部{beforeClipFilter}个对象"); + } + + // 步骤3:排除指定对象 if (excludeObject != null) { nearbyObjects = nearbyObjects.Where(obj => !obj.Equals(excludeObject)).ToList(); diff --git a/src/Core/VirtualVehicleManager.cs b/src/Core/VirtualVehicleManager.cs index 3371e7e..4ec05ab 100644 --- a/src/Core/VirtualVehicleManager.cs +++ b/src/Core/VirtualVehicleManager.cs @@ -7,18 +7,18 @@ using Autodesk.Navisworks.Api; namespace NavisworksTransport.Core { /// - /// 虚拟车辆管理器 - 负责创建和管理虚拟车辆几何体 - /// 通过追加预制的单位立方体NWC文件并缩放来创建指定尺寸的虚拟车辆 + /// 虚拟物体管理器 - 负责创建和管理虚拟物体几何体 + /// 通过追加预制的单位立方体NWC文件并缩放来创建指定尺寸的虚拟物体 /// - public class VirtualVehicleManager + public class VirtualObjectManager { - private static VirtualVehicleManager _instance; + private static VirtualObjectManager _instance; private static readonly object _lock = new object(); /// /// 单例实例 /// - public static VirtualVehicleManager Instance + public static VirtualObjectManager Instance { get { @@ -28,7 +28,7 @@ namespace NavisworksTransport.Core { if (_instance == null) { - _instance = new VirtualVehicleManager(); + _instance = new VirtualObjectManager(); } } } @@ -36,167 +36,167 @@ namespace NavisworksTransport.Core } } - private ModelItem _virtualVehicleModelItem; - private Model _virtualVehicleModel; - private bool _isVirtualVehicleActive; + private ModelItem _virtualObjectModelItem; + private Model _virtualObjectModel; + private bool _isVirtualObjectActive; - // 🔥 新增:标记是否正在更新虚拟车辆,用于避免触发缓存重建 - private bool _isUpdatingVirtualVehicle = false; + // 🔥 新增:标记是否正在更新虚拟物体,用于避免触发缓存重建 + private bool _isUpdatingVirtualObject = false; /// - /// 是否正在更新虚拟车辆(用于外部检测是否应该跳过缓存重建) + /// 是否正在更新虚拟物体(用于外部检测是否应该跳过缓存重建) /// - public bool IsUpdatingVirtualVehicle => _isUpdatingVirtualVehicle; + public bool IsUpdatingVirtualObject => _isUpdatingVirtualObject; - // 🔥 记住虚拟车辆的尺寸变换参数(避免动态计算) + // 🔥 记住虚拟物体的尺寸变换参数(避免动态计算) private double _currentLengthMeters = 0; private double _currentWidthMeters = 0; private double _currentHeightMeters = 0; /// - /// 当前虚拟车辆ModelItem + /// 当前虚拟物体ModelItem /// - public ModelItem CurrentVirtualVehicle => _virtualVehicleModelItem; + public ModelItem CurrentVirtualObject => _virtualObjectModelItem; /// - /// 虚拟车辆是否激活 + /// 虚拟物体是否激活 /// - public bool IsVirtualVehicleActive => _isVirtualVehicleActive; + public bool IsVirtualObjectActive => _isVirtualObjectActive; - private VirtualVehicleManager() + private VirtualObjectManager() { - _isVirtualVehicleActive = false; + _isVirtualObjectActive = false; } /// - /// 显示虚拟车辆 + /// 显示虚拟物体 /// /// 长度(米) /// 宽度(米) /// 高度(米) - public void ShowVirtualVehicle(double lengthMeters, double widthMeters, double heightMeters) + public void ShowVirtualObject(double lengthMeters, double widthMeters, double heightMeters) { // 🔥 设置标志,防止文档变化事件触发缓存重建 - _isUpdatingVirtualVehicle = true; + _isUpdatingVirtualObject = true; try { var doc = Application.ActiveDocument; - // 检查虚拟车辆模型是否已存在 - if (_virtualVehicleModel != null) + // 检查虚拟物体模型是否已存在 + if (_virtualObjectModel != null) { - int currentIndex = doc.Models.IndexOf(_virtualVehicleModel); + int currentIndex = doc.Models.IndexOf(_virtualObjectModel); if (currentIndex >= 0) { // 模型存在,显示它并更新尺寸 - LogManager.Info($"虚拟车辆模型已存在(索引: {currentIndex}),显示并更新尺寸"); + LogManager.Info($"虚拟物体模型已存在(索引: {currentIndex}),显示并更新尺寸"); - var modelItems = new ModelItemCollection { _virtualVehicleModelItem }; + var modelItems = new ModelItemCollection { _virtualObjectModelItem }; doc.Models.SetHidden(modelItems, false); // 获取实际的几何体项 - _virtualVehicleModelItem = _virtualVehicleModel.RootItem; - var geometryItem = FindFirstGeometryItem(_virtualVehicleModelItem); - if (geometryItem != null && !geometryItem.Equals(_virtualVehicleModelItem)) + _virtualObjectModelItem = _virtualObjectModel.RootItem; + var geometryItem = FindFirstGeometryItem(_virtualObjectModelItem); + if (geometryItem != null && !geometryItem.Equals(_virtualObjectModelItem)) { - _virtualVehicleModelItem = geometryItem; + _virtualObjectModelItem = geometryItem; } // 清除覆盖变换(之前动画移动和旋转的累积) modelItems.Clear(); - modelItems.Add(_virtualVehicleModelItem); + modelItems.Add(_virtualObjectModelItem); doc.Models.ResetPermanentTransform(modelItems); // 重置变换并缩放到目标尺寸 - ResetVirtualVehicleTransform(); - ScaleVirtualVehicle(lengthMeters, widthMeters, heightMeters); + ResetVirtualObjectTransform(); + ScaleVirtualObject(lengthMeters, widthMeters, heightMeters); - _isVirtualVehicleActive = true; - LogManager.Info($"虚拟车辆更新成功"); + _isVirtualObjectActive = true; + LogManager.Info($"虚拟物体更新成功"); return; } else { - LogManager.Warning($"已保存的虚拟车辆模型不在文档中,需要重新创建"); + LogManager.Warning($"已保存的虚拟物体模型不在文档中,需要重新创建"); } } // 模型不存在,创建新的 - CreateVirtualVehicleInternal(doc, lengthMeters, widthMeters, heightMeters); + CreateVirtualObjectInternal(doc, lengthMeters, widthMeters, heightMeters); } catch (Exception ex) { - LogManager.Error($"显示虚拟车辆失败: {ex.Message}"); + LogManager.Error($"显示虚拟物体失败: {ex.Message}"); } finally { // 🔥 清除标志 - _isUpdatingVirtualVehicle = false; + _isUpdatingVirtualObject = false; } } /// - /// 隐藏虚拟车辆 + /// 隐藏虚拟物体 /// - public void HideVirtualVehicle() + public void HideVirtualObject() { try { - if (_virtualVehicleModelItem != null) + if (_virtualObjectModelItem != null) { var doc = Application.ActiveDocument; - var modelItems = new ModelItemCollection { _virtualVehicleModelItem }; + var modelItems = new ModelItemCollection { _virtualObjectModelItem }; doc.Models.SetHidden(modelItems, true); - LogManager.Info($"已隐藏虚拟车辆模型"); + LogManager.Info($"已隐藏虚拟物体模型"); } // 隐藏时设置为非激活状态,但保留模型引用 - _isVirtualVehicleActive = false; + _isVirtualObjectActive = false; } catch (Exception ex) { - LogManager.Error($"隐藏虚拟车辆失败: {ex.Message}"); - _isVirtualVehicleActive = false; + LogManager.Error($"隐藏虚拟物体失败: {ex.Message}"); + _isVirtualObjectActive = false; } } /// - /// 创建虚拟车辆(内部方法) + /// 创建虚拟物体(内部方法) /// - private void CreateVirtualVehicleInternal(Document doc, double lengthMeters, double widthMeters, double heightMeters) + private void CreateVirtualObjectInternal(Document doc, double lengthMeters, double widthMeters, double heightMeters) { - LogManager.Info($"=== 创建虚拟车辆 ==="); + LogManager.Info($"=== 创建虚拟物体 ==="); LogManager.Info($"目标尺寸: {lengthMeters:F2}m × {widthMeters:F2}m × {heightMeters:F2}m"); - // 加载新的虚拟车辆模型 - LoadNewVirtualVehicleModel(doc); + // 加载新的虚拟物体模型 + LoadNewVirtualObjectModel(doc); // 获取实际的几何体项 - _virtualVehicleModelItem = _virtualVehicleModel.RootItem; - var geometryItem = FindFirstGeometryItem(_virtualVehicleModelItem); - if (geometryItem != null && !geometryItem.Equals(_virtualVehicleModelItem)) + _virtualObjectModelItem = _virtualObjectModel.RootItem; + var geometryItem = FindFirstGeometryItem(_virtualObjectModelItem); + if (geometryItem != null && !geometryItem.Equals(_virtualObjectModelItem)) { - _virtualVehicleModelItem = geometryItem; + _virtualObjectModelItem = geometryItem; } // 重置变换并缩放到目标尺寸 - ResetVirtualVehicleTransform(); - ScaleVirtualVehicle(lengthMeters, widthMeters, heightMeters); + ResetVirtualObjectTransform(); + ScaleVirtualObject(lengthMeters, widthMeters, heightMeters); // 设置状态 - _isVirtualVehicleActive = true; + _isVirtualObjectActive = true; - LogManager.Info($"虚拟车辆创建成功"); + LogManager.Info($"虚拟物体创建成功"); } /// - /// 加载新的虚拟车辆模型 + /// 加载新的虚拟物体模型 /// - private void LoadNewVirtualVehicleModel(Document doc) + private void LoadNewVirtualObjectModel(Document doc) { - LogManager.Info($"需要加载新的虚拟车辆模型"); + LogManager.Info($"需要加载新的虚拟物体模型"); // 1. 获取单位立方体文件路径 var unitCubePath = GetUnitCubeFilePath(); @@ -227,19 +227,19 @@ namespace NavisworksTransport.Core } // 保存模型引用(最后一个模型就是刚追加的) - _virtualVehicleModel = doc.Models.Last(); + _virtualObjectModel = doc.Models.Last(); - LogManager.Info($"虚拟车辆模型: {_virtualVehicleModel.FileName}"); - LogManager.Info($"虚拟车辆根项: {_virtualVehicleModel.RootItem.DisplayName}"); + LogManager.Info($"虚拟物体模型: {_virtualObjectModel.FileName}"); + LogManager.Info($"虚拟物体根项: {_virtualObjectModel.RootItem.DisplayName}"); } /// /// - /// 重置虚拟车辆变换为单位矩阵(公开方法,供批处理使用) + /// 重置虚拟物体变换为单位矩阵(公开方法,供批处理使用) /// - public void ResetVirtualVehicleTransform() + public void ResetVirtualObjectTransform() { - if (_virtualVehicleModel == null) return; + if (_virtualObjectModel == null) return; var doc = Application.ActiveDocument; @@ -248,19 +248,19 @@ namespace NavisworksTransport.Core Transform3DComponents identityComponents = identityTransform.Factor(); // 应用单位变换 - Units currentUnits = _virtualVehicleModel.Units; - doc.Models.SetModelUnitsAndTransform(_virtualVehicleModel, currentUnits, identityTransform, false); + Units currentUnits = _virtualObjectModel.Units; + doc.Models.SetModelUnitsAndTransform(_virtualObjectModel, currentUnits, identityTransform, false); - LogManager.Info("已重置虚拟车辆变换"); + LogManager.Info("已重置虚拟物体变换"); } /// - /// 缩放虚拟车辆到目标尺寸 + /// 缩放虚拟物体到目标尺寸 /// 使用DocumentModels.SetModelUnitsAndTransform方法进行模型级缩放 /// - private void ScaleVirtualVehicle(double lengthMeters, double widthMeters, double heightMeters) + private void ScaleVirtualObject(double lengthMeters, double widthMeters, double heightMeters) { - if (_virtualVehicleModel == null || _virtualVehicleModelItem == null) return; + if (_virtualObjectModel == null || _virtualObjectModelItem == null) return; var doc = Application.ActiveDocument; @@ -272,21 +272,21 @@ namespace NavisworksTransport.Core // 获取单位转换因子(米到模型单位) double metersToUnits = Utils.UnitsConverter.GetMetersToUnitsConversionFactor(doc.Units); - // 🔥 对于虚拟车辆,直接应用缩放比例(不动态读取当前尺寸) - // 原因:虚拟车辆可能被旋转,导致包围盒尺寸不准确 + // 🔥 对于虚拟物体,直接应用缩放比例(不动态读取当前尺寸) + // 原因:虚拟物体可能被旋转,导致包围盒尺寸不准确 // 单位立方体是 0.01m × 0.01m × 0.01m - // X方向 = 车辆长度(前进方向),Y方向 = 车辆宽度(侧面),Z方向 = 车辆高度 + // X方向 = 物体长度(前进方向),Y方向 = 物体宽度(侧面),Z方向 = 物体高度 double baseSizeMeters = 0.01; - double scaleX = lengthMeters / baseSizeMeters; // X方向 = 车辆长度(前进方向) - double scaleY = widthMeters / baseSizeMeters; // Y方向 = 车辆宽度(侧面) - double scaleZ = heightMeters / baseSizeMeters; // Z方向 = 车辆高度 + double scaleX = lengthMeters / baseSizeMeters; // X方向 = 物体长度(前进方向) + double scaleY = widthMeters / 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}"); // 使用Transform3DComponents进行缩放 // 获取当前模型的变换并分解 - Transform3D currentTransform = _virtualVehicleModel.Transform; + Transform3D currentTransform = _virtualObjectModel.Transform; Transform3DComponents transformComponents = currentTransform.Factor(); // 获取当前值 @@ -304,13 +304,13 @@ namespace NavisworksTransport.Core Transform3D newTransform = transformComponents.Combine(); // 获取当前模型单位 - Units currentUnits = _virtualVehicleModel.Units; + Units currentUnits = _virtualObjectModel.Units; // 应用新的变换 - doc.Models.SetModelUnitsAndTransform(_virtualVehicleModel, currentUnits, newTransform, false); + doc.Models.SetModelUnitsAndTransform(_virtualObjectModel, currentUnits, newTransform, false); // 验证缩放结果 - var newBoundingBox = _virtualVehicleModelItem.BoundingBox(); + var newBoundingBox = _virtualObjectModelItem.BoundingBox(); double newLength = newBoundingBox.Max.X - newBoundingBox.Min.X; double newWidth = newBoundingBox.Max.Y - newBoundingBox.Min.Y; double newHeight = newBoundingBox.Max.Z - newBoundingBox.Min.Z; @@ -323,18 +323,18 @@ namespace NavisworksTransport.Core } /// - /// 移除虚拟车辆(使用 TryRemoveFile 真正删除模型) + /// 移除虚拟物体(使用 TryRemoveFile 真正删除模型) /// - public void RemoveVirtualVehicle() + public void RemoveVirtualObject() { try { var doc = Application.ActiveDocument; - if (_virtualVehicleModel != null) + if (_virtualObjectModel != null) { // 动态查找模型索引 - int currentIndex = doc.Models.IndexOf(_virtualVehicleModel); + int currentIndex = doc.Models.IndexOf(_virtualObjectModel); if (currentIndex >= 0) { @@ -343,30 +343,30 @@ namespace NavisworksTransport.Core if (removed) { - LogManager.Info($"已删除虚拟车辆模型(索引: {currentIndex})"); + LogManager.Info($"已删除虚拟物体模型(索引: {currentIndex})"); } else { - LogManager.Warning($"删除虚拟车辆模型失败(索引: {currentIndex})"); + LogManager.Warning($"删除虚拟物体模型失败(索引: {currentIndex})"); } } else { - LogManager.Warning($"虚拟车辆模型不在文档中,无法删除"); + LogManager.Warning($"虚拟物体模型不在文档中,无法删除"); } } // 清理引用 - _virtualVehicleModel = null; - _virtualVehicleModelItem = null; - _isVirtualVehicleActive = false; + _virtualObjectModel = null; + _virtualObjectModelItem = null; + _isVirtualObjectActive = false; } catch (Exception ex) { - LogManager.Error($"删除虚拟车辆失败: {ex.Message}"); - _virtualVehicleModel = null; - _virtualVehicleModelItem = null; - _isVirtualVehicleActive = false; + LogManager.Error($"删除虚拟物体失败: {ex.Message}"); + _virtualObjectModel = null; + _virtualObjectModelItem = null; + _isVirtualObjectActive = false; } } @@ -431,7 +431,7 @@ namespace NavisworksTransport.Core /// public void Cleanup() { - RemoveVirtualVehicle(); + RemoveVirtualObject(); } } } diff --git a/src/PathPlanning/AutoPathFinder.cs b/src/PathPlanning/AutoPathFinder.cs index 4f19ad1..ba4eb68 100644 --- a/src/PathPlanning/AutoPathFinder.cs +++ b/src/PathPlanning/AutoPathFinder.cs @@ -123,14 +123,14 @@ namespace NavisworksTransport.PathPlanning /// /// 真3D路径规划(使用通道覆盖数据、高度约束和路径策略) /// - public PathFindingResult FindPath(Point3D start, Point3D end, GridMap gridMap, ChannelCoverage channelCoverage, double vehicleHeight, PathStrategy strategy = PathStrategy.Shortest) + public PathFindingResult FindPath(Point3D start, Point3D end, GridMap gridMap, ChannelCoverage channelCoverage, double objectHeight, PathStrategy strategy = PathStrategy.Shortest) { try { LogManager.Info("[3D路径规划] 开始执行"); // 构建3D图 - var graph3D = BuildGraphWithStrategy(gridMap, channelCoverage, vehicleHeight, start, end, strategy); + var graph3D = BuildGraphWithStrategy(gridMap, channelCoverage, objectHeight, start, end, strategy); // 执行A*搜索 var pathResult = ExecuteAStarOnGraph(start, end, gridMap, graph3D); @@ -159,7 +159,7 @@ namespace NavisworksTransport.PathPlanning /// /// 构建3D图(每个(x,y,layerIndex)作为独立节点) /// - private Graph3DResult BuildGraph3D(GridMap gridMap, ChannelCoverage channelCoverage, double vehicleHeight, Point3D startPos, Point3D endPos, SpeedCalculator speedCalculator = null) + private Graph3DResult BuildGraph3D(GridMap gridMap, ChannelCoverage channelCoverage, double objectHeight, Point3D startPos, Point3D endPos, SpeedCalculator speedCalculator = null) { LogManager.Info("[3D图构建] 开始构建真3D图"); @@ -200,7 +200,7 @@ namespace NavisworksTransport.PathPlanning continue; } - if (layer.PassableHeight.GetSpan() < vehicleHeight) + if (layer.PassableHeight.GetSpan() < objectHeight) continue; // 使用2D位置(用于A*启发式) @@ -239,7 +239,7 @@ namespace NavisworksTransport.PathPlanning for (int li = 0; li < cell.HeightLayers.Count; li++) { var currentLayer = cell.HeightLayers[li]; - if (currentLayer.PassableHeight.GetSpan() < vehicleHeight) + if (currentLayer.PassableHeight.GetSpan() < objectHeight) continue; if (!nodes.TryGetValue((x, y, li), out var currentNode)) @@ -263,7 +263,7 @@ namespace NavisworksTransport.PathPlanning for (int nli = 0; nli < neighborCell.HeightLayers.Count; nli++) { var neighborLayer = neighborCell.HeightLayers[nli]; - if (neighborLayer.PassableHeight.GetSpan() < vehicleHeight) + if (neighborLayer.PassableHeight.GetSpan() < objectHeight) continue; double heightDiff = Math.Abs(neighborLayer.Z - currentZ); @@ -331,8 +331,8 @@ namespace NavisworksTransport.PathPlanning layer1.Type != CategoryAttributeManager.LogisticsElementType.电梯) continue; - if (layer1.PassableHeight.GetSpan() < vehicleHeight || - layer2.PassableHeight.GetSpan() < vehicleHeight) + if (layer1.PassableHeight.GetSpan() < objectHeight || + layer2.PassableHeight.GetSpan() < objectHeight) continue; double heightDiff = Math.Abs(layer2.Z - layer1.Z); @@ -390,7 +390,7 @@ namespace NavisworksTransport.PathPlanning /// /// 根据策略构建图 /// - private Graph3DResult BuildGraphWithStrategy(GridMap gridMap, ChannelCoverage channelCoverage, double vehicleHeight, Point3D startPos, Point3D endPos, PathStrategy strategy) + private Graph3DResult BuildGraphWithStrategy(GridMap gridMap, ChannelCoverage channelCoverage, double objectHeight, Point3D startPos, Point3D endPos, PathStrategy strategy) { SpeedCalculator speedCalc = null; @@ -415,7 +415,7 @@ namespace NavisworksTransport.PathPlanning var currentPos = new GridPoint2D(cx, cy); // 计算沿该方向能够直走的距离 - int straightDistance = CalculateStraightDistance(currentPos, direction, gridMap, vehicleHeight); + int straightDistance = CalculateStraightDistance(currentPos, direction, gridMap, objectHeight); // 直走距离越长,速度加成越高(最多+30 km/h) float bonusSpeed = Math.Min(straightDistance * 0.5f, 30.0f); @@ -458,7 +458,7 @@ namespace NavisworksTransport.PathPlanning break; } - return BuildGraph3D(gridMap, channelCoverage, vehicleHeight, startPos, endPos, speedCalc); + return BuildGraph3D(gridMap, channelCoverage, objectHeight, startPos, endPos, speedCalc); } /// @@ -723,7 +723,7 @@ namespace NavisworksTransport.PathPlanning /// /// 2.5D路径规划(使用通道覆盖数据、高度约束和路径策略)[已废弃,保留作为备份] /// - private PathFindingResult FindPath_Legacy_2_5D(Point3D start, Point3D end, GridMap gridMap, ChannelCoverage channelCoverage, double vehicleHeight, PathStrategy strategy = PathStrategy.Shortest) + private PathFindingResult FindPath_Legacy_2_5D(Point3D start, Point3D end, GridMap gridMap, ChannelCoverage channelCoverage, double objectHeight, PathStrategy strategy = PathStrategy.Shortest) { try { @@ -735,19 +735,19 @@ namespace NavisworksTransport.PathPlanning // 1. 检查起点和终点的高度约束 var startGridPos = gridMap.WorldToGrid(start); - if (!IsPointPassableAtHeight(startGridPos, start, gridMap, vehicleHeight)) + if (!IsPointPassableAtHeight(startGridPos, start, gridMap, objectHeight)) { LogManager.Warning("[2.5D路径规划] 起点位置不满足高度约束"); } var endGridPos = gridMap.WorldToGrid(end); - if (!IsPointPassableAtHeight(endGridPos, end, gridMap, vehicleHeight)) + if (!IsPointPassableAtHeight(endGridPos, end, gridMap, objectHeight)) { LogManager.Warning("[2.5D路径规划] 终点位置不满足高度约束"); } // 2. 根据策略选择合适的网格转换方法(返回A*网格和激活层字典) - var (astarGrid, activeLayerZ) = ConvertToAStarGridWithStrategy(gridMap, channelCoverage, vehicleHeight, start, end, strategy); + var (astarGrid, activeLayerZ) = ConvertToAStarGridWithStrategy(gridMap, channelCoverage, objectHeight, start, end, strategy); // 3. 执行A*算法 var pathResult = ExecuteAStarAlgorithm(start, end, gridMap, astarGrid); @@ -794,13 +794,13 @@ namespace NavisworksTransport.PathPlanning /// /// 网格地图 /// 通道覆盖数据 - /// 车辆高度(模型单位) + /// 运动物体高度(模型单位) /// A*算法网格 - private (Grid grid, Dictionary activeLayerZ) ConvertToAStarGridWith2_5D(GridMap gridMap, ChannelCoverage channelCoverage, double vehicleHeight, Point3D startPos, Point3D endPos) + private (Grid grid, Dictionary activeLayerZ) ConvertToAStarGridWith2_5D(GridMap gridMap, ChannelCoverage channelCoverage, double objectHeight, Point3D startPos, Point3D endPos) { try { - LogManager.Info($"[A*转换-2.5D] 开始转换网格格式: {gridMap.Width}x{gridMap.Height},车辆高度: {vehicleHeight}m"); + LogManager.Info($"[A*转换-2.5D] 开始转换网格格式: {gridMap.Width}x{gridMap.Height},运动物体高度: {objectHeight}m"); // 初始化激活层字典 var activeLayerZ = new Dictionary(); @@ -871,8 +871,8 @@ namespace NavisworksTransport.PathPlanning totalNonWalkableCells++; } - // 检查是否有满足车辆高度的层 - if (!HasCompatibleLayer(cell, vehicleHeight)) + // 检查是否有满足运动物体高度的层 + if (!HasCompatibleLayer(cell, objectHeight)) { if (cell.HasAnyWalkableLayer()) { @@ -882,7 +882,7 @@ namespace NavisworksTransport.PathPlanning var layerInfo = cell.HeightLayers != null && cell.HeightLayers.Count > 0 ? $"有{cell.HeightLayers.Count}个高度层" : "无高度层"; - LogManager.Info($"[A*高度约束] 单元格({x},{y})被高度约束排除:车辆高度{vehicleHeight:F2}模型单位,{layerInfo}"); + LogManager.Info($"[A*高度约束] 单元格({x},{y})被高度约束排除:运动物体高度{objectHeight:F2}模型单位,{layerInfo}"); } else if (heightConstrainedCells == 11) { @@ -893,7 +893,7 @@ namespace NavisworksTransport.PathPlanning } // 为当前单元格选择最优高度层 - var currentZ = SelectBestLayerForTarget(cell.HeightLayers, targetZ, vehicleHeight); + var currentZ = SelectBestLayerForTarget(cell.HeightLayers, targetZ, objectHeight); if (!currentZ.HasValue) continue; @@ -908,7 +908,7 @@ namespace NavisworksTransport.PathPlanning if (x + 1 < gridMap.Width) { var rightCell = gridMap.Cells[x + 1, y]; - var rightZ = SelectBestLayerForTarget(rightCell.HeightLayers, targetZ, vehicleHeight); + var rightZ = SelectBestLayerForTarget(rightCell.HeightLayers, targetZ, objectHeight); if (rightZ.HasValue) { var rightPos = new GridPosition(x + 1, y); @@ -935,7 +935,7 @@ namespace NavisworksTransport.PathPlanning if (y + 1 < gridMap.Height) { var bottomCell = gridMap.Cells[x, y + 1]; - var bottomZ = SelectBestLayerForTarget(bottomCell.HeightLayers, targetZ, vehicleHeight); + var bottomZ = SelectBestLayerForTarget(bottomCell.HeightLayers, targetZ, objectHeight); if (bottomZ.HasValue) { var bottomPos = new GridPosition(x, y + 1); @@ -954,7 +954,7 @@ namespace NavisworksTransport.PathPlanning if (x - 1 >= 0) { var leftCell = gridMap.Cells[x - 1, y]; - var leftZ = SelectBestLayerForTarget(leftCell.HeightLayers, targetZ, vehicleHeight); + var leftZ = SelectBestLayerForTarget(leftCell.HeightLayers, targetZ, objectHeight); if (leftZ.HasValue) { var leftPos = new GridPosition(x - 1, y); @@ -973,7 +973,7 @@ namespace NavisworksTransport.PathPlanning if (y - 1 >= 0) { var topCell = gridMap.Cells[x, y - 1]; - var topZ = SelectBestLayerForTarget(topCell.HeightLayers, targetZ, vehicleHeight); + var topZ = SelectBestLayerForTarget(topCell.HeightLayers, targetZ, objectHeight); if (topZ.HasValue) { var topPos = new GridPosition(x, y - 1); @@ -1013,30 +1013,30 @@ namespace NavisworksTransport.PathPlanning /// /// 网格地图 /// 通道覆盖数据 - /// 车辆高度(模型单位) + /// 运动物体高度(模型单位) /// 起点坐标 /// 终点坐标 /// 路径规划策略 /// A*网格和激活层字典的元组 - private (Grid grid, Dictionary activeLayerZ) ConvertToAStarGridWithStrategy(GridMap gridMap, ChannelCoverage channelCoverage, double vehicleHeight, Point3D startPos, Point3D endPos, PathStrategy strategy) + private (Grid grid, Dictionary activeLayerZ) ConvertToAStarGridWithStrategy(GridMap gridMap, ChannelCoverage channelCoverage, double objectHeight, Point3D startPos, Point3D endPos, PathStrategy strategy) { switch (strategy) { case PathStrategy.Shortest: LogManager.Info($"[策略路由] 使用最短路径策略"); - return ConvertToAStarGridWith2_5D(gridMap, channelCoverage, vehicleHeight, startPos, endPos); + return ConvertToAStarGridWith2_5D(gridMap, channelCoverage, objectHeight, startPos, endPos); case PathStrategy.Straightest: LogManager.Info($"[策略路由] 使用直线优先策略"); - return ConvertToAStarGridStraightest(gridMap, channelCoverage, vehicleHeight, startPos, endPos); + return ConvertToAStarGridStraightest(gridMap, channelCoverage, objectHeight, startPos, endPos); case PathStrategy.SafestCenter: LogManager.Info($"[策略路由] 使用安全优先策略"); - return ConvertToAStarGridSafestCenter(gridMap, channelCoverage, vehicleHeight, startPos, endPos); + return ConvertToAStarGridSafestCenter(gridMap, channelCoverage, objectHeight, startPos, endPos); default: LogManager.Warning($"[策略路由] 未知策略 {strategy},使用默认最短路径"); - return ConvertToAStarGridWith2_5D(gridMap, channelCoverage, vehicleHeight, startPos, endPos); + return ConvertToAStarGridWith2_5D(gridMap, channelCoverage, objectHeight, startPos, endPos); } } @@ -1046,11 +1046,11 @@ namespace NavisworksTransport.PathPlanning /// /// 网格地图 /// 通道覆盖数据 - /// 车辆高度(模型单位) + /// 运动物体高度(模型单位) /// 起点坐标 /// 终点坐标 /// A*网格 - private (Grid grid, Dictionary activeLayerZ) ConvertToAStarGridStraightest(GridMap gridMap, ChannelCoverage channelCoverage, double vehicleHeight, Point3D startPos, Point3D endPos) + private (Grid grid, Dictionary activeLayerZ) ConvertToAStarGridStraightest(GridMap gridMap, ChannelCoverage channelCoverage, double objectHeight, Point3D startPos, Point3D endPos) { try { @@ -1097,7 +1097,7 @@ namespace NavisworksTransport.PathPlanning var cell = gridMap.Cells[x, y]; // 检查是否有兼容的高度层 - if (!HasCompatibleLayer(cell, vehicleHeight)) + if (!HasCompatibleLayer(cell, objectHeight)) { if (cell.HasAnyWalkableLayer()) { @@ -1107,7 +1107,7 @@ namespace NavisworksTransport.PathPlanning } // 选择当前网格的最佳高度层 - var currentZ = SelectBestLayerForTarget(cell.HeightLayers, targetZ, vehicleHeight); + var currentZ = SelectBestLayerForTarget(cell.HeightLayers, targetZ, objectHeight); if (!currentZ.HasValue) { continue; @@ -1126,10 +1126,10 @@ namespace NavisworksTransport.PathPlanning var rightCell = gridMap.Cells[x + 1, y]; // 检查右侧网格是否有兼容的高度层 - if (HasCompatibleLayer(rightCell, vehicleHeight)) + if (HasCompatibleLayer(rightCell, objectHeight)) { // 选择右侧网格的最佳高度层 - var rightZ = SelectBestLayerForTarget(rightCell.HeightLayers, targetZ, vehicleHeight); + var rightZ = SelectBestLayerForTarget(rightCell.HeightLayers, targetZ, objectHeight); if (rightZ.HasValue) { var rightPos = new GridPosition(x + 1, y); @@ -1139,7 +1139,7 @@ namespace NavisworksTransport.PathPlanning activeLayerZ[rightGridPos] = rightZ.Value; // 计算沿右方向的直线距离 - var rightDistance = CalculateStraightDistance(gridPos, new GridPoint2D(1, 0), gridMap, vehicleHeight); + var rightDistance = CalculateStraightDistance(gridPos, new GridPoint2D(1, 0), gridMap, objectHeight); // 计算基础速度(基于直线距离) float baseSpeed = 5.0f; @@ -1165,10 +1165,10 @@ namespace NavisworksTransport.PathPlanning var bottomCell = gridMap.Cells[x, y + 1]; // 检查下方网格是否有兼容的高度层 - if (HasCompatibleLayer(bottomCell, vehicleHeight)) + if (HasCompatibleLayer(bottomCell, objectHeight)) { // 选择下方网格的最佳高度层 - var bottomZ = SelectBestLayerForTarget(bottomCell.HeightLayers, targetZ, vehicleHeight); + var bottomZ = SelectBestLayerForTarget(bottomCell.HeightLayers, targetZ, objectHeight); if (bottomZ.HasValue) { var bottomPos = new GridPosition(x, y + 1); @@ -1178,7 +1178,7 @@ namespace NavisworksTransport.PathPlanning activeLayerZ[bottomGridPos] = bottomZ.Value; // 计算沿下方向的直线距离 - var downDistance = CalculateStraightDistance(gridPos, new GridPoint2D(0, 1), gridMap, vehicleHeight); + var downDistance = CalculateStraightDistance(gridPos, new GridPoint2D(0, 1), gridMap, objectHeight); // 计算基础速度(基于直线距离) float baseSpeed = 5.0f; @@ -1204,10 +1204,10 @@ namespace NavisworksTransport.PathPlanning var leftCell = gridMap.Cells[x - 1, y]; // 检查左侧网格是否有兼容的高度层 - if (HasCompatibleLayer(leftCell, vehicleHeight)) + if (HasCompatibleLayer(leftCell, objectHeight)) { // 选择左侧网格的最佳高度层 - var leftZ = SelectBestLayerForTarget(leftCell.HeightLayers, targetZ, vehicleHeight); + var leftZ = SelectBestLayerForTarget(leftCell.HeightLayers, targetZ, objectHeight); if (leftZ.HasValue) { var leftPos = new GridPosition(x - 1, y); @@ -1217,7 +1217,7 @@ namespace NavisworksTransport.PathPlanning activeLayerZ[leftGridPos] = leftZ.Value; // 计算沿左方向的直线距离 - var leftDistance = CalculateStraightDistance(gridPos, new GridPoint2D(-1, 0), gridMap, vehicleHeight); + var leftDistance = CalculateStraightDistance(gridPos, new GridPoint2D(-1, 0), gridMap, objectHeight); // 计算基础速度(基于直线距离) float baseSpeed = 5.0f; @@ -1243,10 +1243,10 @@ namespace NavisworksTransport.PathPlanning var topCell = gridMap.Cells[x, y - 1]; // 检查上方网格是否有兼容的高度层 - if (HasCompatibleLayer(topCell, vehicleHeight)) + if (HasCompatibleLayer(topCell, objectHeight)) { // 选择上方网格的最佳高度层 - var topZ = SelectBestLayerForTarget(topCell.HeightLayers, targetZ, vehicleHeight); + var topZ = SelectBestLayerForTarget(topCell.HeightLayers, targetZ, objectHeight); if (topZ.HasValue) { var topPos = new GridPosition(x, y - 1); @@ -1256,7 +1256,7 @@ namespace NavisworksTransport.PathPlanning activeLayerZ[topGridPos] = topZ.Value; // 计算沿上方向的直线距离 - var upDistance = CalculateStraightDistance(gridPos, new GridPoint2D(0, -1), gridMap, vehicleHeight); + var upDistance = CalculateStraightDistance(gridPos, new GridPoint2D(0, -1), gridMap, objectHeight); // 计算基础速度(基于直线距离) float baseSpeed = 5.0f; @@ -1281,9 +1281,9 @@ namespace NavisworksTransport.PathPlanning if (x + 1 < gridMap.Width && y + 1 < gridMap.Height) { var diagonalCell = gridMap.Cells[x + 1, y + 1]; - if (HasCompatibleLayer(diagonalCell, vehicleHeight)) + if (HasCompatibleLayer(diagonalCell, objectHeight)) { - var diagonalZ = SelectBestLayerForTarget(diagonalCell.HeightLayers, targetZ, vehicleHeight); + var diagonalZ = SelectBestLayerForTarget(diagonalCell.HeightLayers, targetZ, objectHeight); if (diagonalZ.HasValue) { var diagonalPos = new GridPosition(x + 1, y + 1); @@ -1317,19 +1317,19 @@ namespace NavisworksTransport.PathPlanning /// 检查单元格是否满足高度约束 /// /// 网格单元格 - /// 车辆高度(模型单位) + /// 运动物体高度(模型单位) /// 是否可通行 - private bool IsPassableWithHeight(GridCell cell, double vehicleHeight) + private bool IsPassableWithHeight(GridCell cell, double objectHeight) { if (!cell.HasAnyWalkableLayer()) return false; - // 检查是否有任何高度层满足车辆高度要求 + // 检查是否有任何高度层满足运动物体高度要求 if (cell.HeightLayers != null && cell.HeightLayers.Count > 0) { foreach (var layer in cell.HeightLayers) { - if (layer.PassableHeight.GetSpan() >= vehicleHeight) + if (layer.PassableHeight.GetSpan() >= objectHeight) return true; } return false; @@ -1339,12 +1339,12 @@ namespace NavisworksTransport.PathPlanning } /// - /// 检查单元格是否有满足车辆高度的高度层 + /// 检查单元格是否有满足运动物体高度的高度层 /// /// 网格单元格 - /// 车辆高度(模型单位) + /// 运动物体高度(模型单位) /// 是否有兼容的高度层 - private bool HasCompatibleLayer(GridCell cell, double vehicleHeight) + private bool HasCompatibleLayer(GridCell cell, double objectHeight) { if (!cell.HasAnyWalkableLayer()) return false; @@ -1354,7 +1354,7 @@ namespace NavisworksTransport.PathPlanning foreach (var layer in cell.HeightLayers) { - if (layer.PassableHeight.GetSpan() >= vehicleHeight) + if (layer.PassableHeight.GetSpan() >= objectHeight) return true; } @@ -1362,13 +1362,13 @@ namespace NavisworksTransport.PathPlanning } /// - /// 从高度层列表中选择最接近目标高度且满足车辆高度的层 + /// 从高度层列表中选择最接近目标高度且满足运动物体高度的层 /// /// 高度层列表 /// 目标高度(米) - /// 车辆高度(模型单位) + /// 运动物体高度(模型单位) /// 选中的高度层Z坐标,如果没有合适的返回null - private double? SelectBestLayerForTarget(List layers, double targetZ, double vehicleHeight) + private double? SelectBestLayerForTarget(List layers, double targetZ, double objectHeight) { if (layers == null || layers.Count == 0) return null; @@ -1378,8 +1378,8 @@ namespace NavisworksTransport.PathPlanning foreach (var layer in layers) { - // 必须满足车辆高度 - if (layer.PassableHeight.GetSpan() < vehicleHeight) + // 必须满足运动物体高度 + if (layer.PassableHeight.GetSpan() < objectHeight) continue; // 选择最接近目标高度的层 @@ -1414,16 +1414,16 @@ namespace NavisworksTransport.PathPlanning /// 起始网格位置 /// 方向 (1,0)=右, (0,1)=下, (-1,0)=左, (0,-1)=上 /// 网格地图 - /// 车辆高度(模型单位) + /// 运动物体高度(模型单位) /// 直线距离(网格单位) private int CalculateStraightDistance(GridPoint2D startPos, GridPoint2D direction, - GridMap gridMap, double vehicleHeight) + GridMap gridMap, double objectHeight) { int distance = 0; var currentPos = new GridPoint2D(startPos.X + direction.X, startPos.Y + direction.Y); // 沿方向前进,直到遇到障碍 - while (IsValidAndPassable(currentPos, gridMap, vehicleHeight)) + while (IsValidAndPassable(currentPos, gridMap, objectHeight)) { distance++; currentPos = new GridPoint2D(currentPos.X + direction.X, currentPos.Y + direction.Y); @@ -1440,9 +1440,9 @@ namespace NavisworksTransport.PathPlanning /// /// 网格位置 /// 网格地图 - /// 车辆高度(模型单位) + /// 运动物体高度(模型单位) /// 是否有效且可通行 - private bool IsValidAndPassable(GridPoint2D pos, GridMap gridMap, double vehicleHeight) + private bool IsValidAndPassable(GridPoint2D pos, GridMap gridMap, double objectHeight) { // 检查边界 if (pos.X < 0 || pos.X >= gridMap.Width || pos.Y < 0 || pos.Y >= gridMap.Height) @@ -1450,7 +1450,7 @@ namespace NavisworksTransport.PathPlanning // 检查可通行性 var cell = gridMap.Cells[pos.X, pos.Y]; - return IsPassableWithHeight(cell, vehicleHeight); + return IsPassableWithHeight(cell, objectHeight); } /// @@ -2034,9 +2034,9 @@ namespace NavisworksTransport.PathPlanning /// 网格坐标 /// 检查点(世界坐标) /// 网格地图 - /// 车辆高度(模型单位) + /// 运动物体高度(模型单位) /// 是否可通行 - private bool IsPointPassableAtHeight(GridPoint2D gridPos, Point3D point, GridMap gridMap, double vehicleHeight) + private bool IsPointPassableAtHeight(GridPoint2D gridPos, Point3D point, GridMap gridMap, double objectHeight) { try { @@ -2062,19 +2062,19 @@ namespace NavisworksTransport.PathPlanning // 检查高度层约束 if (cell.HeightLayers != null && cell.HeightLayers.Count > 0) { - // 查找包含指定Z坐标且满足车辆高度的层 + // 查找包含指定Z坐标且满足运动物体高度的层 var matchingLayer = gridMap.FindLayerContainingZ(gridPos, point.Z, tolerance: 0.5); if (matchingLayer.HasValue) { - bool heightOk = matchingLayer.Value.PassableHeight.GetSpan() >= vehicleHeight; + bool heightOk = matchingLayer.Value.PassableHeight.GetSpan() >= objectHeight; if (heightOk) { return true; } else { - LogManager.Warning($"[高度检查] ❌ 找到匹配Z={point.Z:F2}的层Z={matchingLayer.Value.Z:F2},但高度不足:车辆高度{vehicleHeight:F2},层高度跨度{matchingLayer.Value.PassableHeight.GetSpan():F2}"); + LogManager.Warning($"[高度检查] ❌ 找到匹配Z={point.Z:F2}的层Z={matchingLayer.Value.Z:F2},但高度不足:运动物体高度{objectHeight:F2},层高度跨度{matchingLayer.Value.PassableHeight.GetSpan():F2}"); } } else @@ -2099,11 +2099,11 @@ namespace NavisworksTransport.PathPlanning /// /// 路径点和对应的网格坐标 /// 网格地图 - /// 车辆高度(模型单位) + /// 运动物体高度(模型单位) /// 用户指定的原始起点(保留原始Z坐标) /// 用户指定的原始终点(保留原始Z坐标) /// 调整后的路径 - private List ApplyGridHeightConstraints(List<(Point3D point, GridPoint2D gridPos)> pathWithGridCoords, GridMap gridMap, double vehicleHeight, Point3D originalStart, Point3D originalEnd) + private List ApplyGridHeightConstraints(List<(Point3D point, GridPoint2D gridPos)> pathWithGridCoords, GridMap gridMap, double objectHeight, Point3D originalStart, Point3D originalEnd) { LogManager.Info($"[智能选层] 开始为路径点选择最优高度层,路径点数: {pathWithGridCoords.Count}"); @@ -2148,7 +2148,7 @@ namespace NavisworksTransport.PathPlanning // 起点和终点:锁定到包含其Z坐标的层 if (i == 0) { - var selectedLayer = SelectBestLayer(cell.HeightLayers, startZ, vehicleHeight, startZ, endZ, i, pathWithGridCoords.Count, true); + var selectedLayer = SelectBestLayer(cell.HeightLayers, startZ, objectHeight, startZ, endZ, i, pathWithGridCoords.Count, true); if (selectedLayer.HasValue) { adjustedPath.Add(new Point3D(point.X, point.Y, selectedLayer.Value.Z)); @@ -2161,7 +2161,7 @@ namespace NavisworksTransport.PathPlanning } else if (i == pathWithGridCoords.Count - 1) { - var selectedLayer = SelectBestLayer(cell.HeightLayers, endZ, vehicleHeight, startZ, endZ, i, pathWithGridCoords.Count, true); + var selectedLayer = SelectBestLayer(cell.HeightLayers, endZ, objectHeight, startZ, endZ, i, pathWithGridCoords.Count, true); if (selectedLayer.HasValue) { adjustedPath.Add(new Point3D(point.X, point.Y, selectedLayer.Value.Z)); @@ -2176,7 +2176,7 @@ namespace NavisworksTransport.PathPlanning { // 中间点:根据高度趋势选择最佳层 var prevZ = adjustedPath[i - 1].Z; - var selectedLayer = SelectBestLayer(cell.HeightLayers, prevZ, vehicleHeight, startZ, endZ, i, pathWithGridCoords.Count, false); + var selectedLayer = SelectBestLayer(cell.HeightLayers, prevZ, objectHeight, startZ, endZ, i, pathWithGridCoords.Count, false); if (selectedLayer.HasValue) { @@ -2260,14 +2260,14 @@ namespace NavisworksTransport.PathPlanning /// /// 可用的高度层列表 /// 参考Z坐标(起点/终点为目标Z,中间点为前一点Z) - /// 车辆高度 + /// 运动物体高度 /// 路径起点Z /// 路径终点Z /// 当前点索引 /// 总点数 /// 是否精确匹配(起点/终点使用) /// 选中的高度层,如果没有合适的返回null - private HeightLayer? SelectBestLayer(List layers, double referenceZ, double vehicleHeight, + private HeightLayer? SelectBestLayer(List layers, double referenceZ, double objectHeight, double startZ, double endZ, int currentIndex, int totalPoints, bool exactMatch) { if (layers == null || layers.Count == 0) @@ -2277,7 +2277,7 @@ namespace NavisworksTransport.PathPlanning if (layers.Count == 1) { var layer = layers[0]; - if (layer.PassableHeight.GetSpan() >= vehicleHeight) + if (layer.PassableHeight.GetSpan() >= objectHeight) return layer; return null; } @@ -2307,13 +2307,13 @@ namespace NavisworksTransport.PathPlanning } } - // 选择最接近目标Z且满足车辆高度要求的层 + // 选择最接近目标Z且满足运动物体高度要求的层 HeightLayer? bestLayer = null; double minDistance = double.MaxValue; foreach (var layer in layers) { - if (layer.PassableHeight.GetSpan() < vehicleHeight) + if (layer.PassableHeight.GetSpan() < objectHeight) continue; double distance = Math.Abs(layer.Z - targetZ); @@ -2439,8 +2439,8 @@ namespace NavisworksTransport.PathPlanning /// /// 路径点和对应的网格坐标 /// 网格地图 - /// 车辆高度(模型单位) - private void ValidatePathHeightConstraints(List<(Point3D point, GridPoint2D gridPos)> pathWithGridCoords, GridMap gridMap, double vehicleHeight) + /// 运动物体高度(模型单位) + private void ValidatePathHeightConstraints(List<(Point3D point, GridPoint2D gridPos)> pathWithGridCoords, GridMap gridMap, double objectHeight) { LogManager.Info($"[路径高度验证] 开始验证 {pathWithGridCoords.Count} 个路径点的高度约束"); @@ -2466,7 +2466,7 @@ namespace NavisworksTransport.PathPlanning } // 进行高度约束检查 - bool isPassable = IsPointPassableAtHeight(gridPos, point, gridMap, vehicleHeight); + bool isPassable = IsPointPassableAtHeight(gridPos, point, gridMap, objectHeight); if (isPassable) { passedPoints++; @@ -2595,7 +2595,7 @@ namespace NavisworksTransport.PathPlanning /// 安全优先的A*网格转换方法 /// 🔥 重写:参照局部直线优先算法的成功模式,重新构建网格连接 /// - private (Grid grid, Dictionary activeLayerZ) ConvertToAStarGridSafestCenter(GridMap gridMap, ChannelCoverage channelCoverage, double vehicleHeight, Point3D startPos, Point3D endPos) + private (Grid grid, Dictionary activeLayerZ) ConvertToAStarGridSafestCenter(GridMap gridMap, ChannelCoverage channelCoverage, double objectHeight, Point3D startPos, Point3D endPos) { try { @@ -2648,7 +2648,7 @@ namespace NavisworksTransport.PathPlanning var cell = gridMap.Cells[x, y]; // 检查是否有兼容的高度层 - if (!HasCompatibleLayer(cell, vehicleHeight)) + if (!HasCompatibleLayer(cell, objectHeight)) { if (cell.HasAnyWalkableLayer()) { @@ -2658,7 +2658,7 @@ namespace NavisworksTransport.PathPlanning } // 选择当前网格的最佳高度层 - var currentZ = SelectBestLayerForTarget(cell.HeightLayers, targetZ, vehicleHeight); + var currentZ = SelectBestLayerForTarget(cell.HeightLayers, targetZ, objectHeight); if (!currentZ.HasValue) { continue; @@ -2678,10 +2678,10 @@ namespace NavisworksTransport.PathPlanning var rightCell = gridMap.Cells[x + 1, y]; // 检查右侧网格是否有兼容的高度层 - if (HasCompatibleLayer(rightCell, vehicleHeight)) + if (HasCompatibleLayer(rightCell, objectHeight)) { // 选择右侧网格的最佳高度层 - var rightZ = SelectBestLayerForTarget(rightCell.HeightLayers, targetZ, vehicleHeight); + var rightZ = SelectBestLayerForTarget(rightCell.HeightLayers, targetZ, objectHeight); if (rightZ.HasValue) { var rightPos = new GridPosition(x + 1, y); @@ -2720,10 +2720,10 @@ namespace NavisworksTransport.PathPlanning var bottomCell = gridMap.Cells[x, y + 1]; // 检查下方网格是否有兼容的高度层 - if (HasCompatibleLayer(bottomCell, vehicleHeight)) + if (HasCompatibleLayer(bottomCell, objectHeight)) { // 选择下方网格的最佳高度层 - var bottomZ = SelectBestLayerForTarget(bottomCell.HeightLayers, targetZ, vehicleHeight); + var bottomZ = SelectBestLayerForTarget(bottomCell.HeightLayers, targetZ, objectHeight); if (bottomZ.HasValue) { var bottomPos = new GridPosition(x, y + 1); @@ -2762,10 +2762,10 @@ namespace NavisworksTransport.PathPlanning var leftCell = gridMap.Cells[x - 1, y]; // 检查左侧网格是否有兼容的高度层 - if (HasCompatibleLayer(leftCell, vehicleHeight)) + if (HasCompatibleLayer(leftCell, objectHeight)) { // 选择左侧网格的最佳高度层 - var leftZ = SelectBestLayerForTarget(leftCell.HeightLayers, targetZ, vehicleHeight); + var leftZ = SelectBestLayerForTarget(leftCell.HeightLayers, targetZ, objectHeight); if (leftZ.HasValue) { var leftPos = new GridPosition(x - 1, y); @@ -2804,10 +2804,10 @@ namespace NavisworksTransport.PathPlanning var topCell = gridMap.Cells[x, y - 1]; // 检查上方网格是否有兼容的高度层 - if (HasCompatibleLayer(topCell, vehicleHeight)) + if (HasCompatibleLayer(topCell, objectHeight)) { // 选择上方网格的最佳高度层 - var topZ = SelectBestLayerForTarget(topCell.HeightLayers, targetZ, vehicleHeight); + var topZ = SelectBestLayerForTarget(topCell.HeightLayers, targetZ, objectHeight); if (topZ.HasValue) { var topPos = new GridPosition(x, y - 1); diff --git a/src/PathPlanning/GridMapCacheKey.cs b/src/PathPlanning/GridMapCacheKey.cs index d525aea..90ca22f 100644 --- a/src/PathPlanning/GridMapCacheKey.cs +++ b/src/PathPlanning/GridMapCacheKey.cs @@ -8,7 +8,7 @@ namespace NavisworksTransport.PathPlanning { /// /// GridMap缓存键,用于标识唯一的GridMap生成配置 - /// 基于所有物流属性构件、车辆尺寸、网格尺寸等关键参数 + /// 基于所有物流属性构件、运动物体尺寸、网格尺寸等关键参数 /// public class GridMapCacheKey : IEquatable { @@ -28,9 +28,9 @@ namespace NavisworksTransport.PathPlanning public double CellSize { get; set; } /// - /// 车辆半径(米) + /// 运动物体半径(米) /// - public double VehicleRadius { get; set; } + public double ObjectRadius { get; set; } /// /// 安全间隙(米) @@ -38,22 +38,22 @@ namespace NavisworksTransport.PathPlanning public double SafetyMargin { get; set; } /// - /// 车辆高度(米) + /// 运动物体高度(米) /// - public double VehicleHeight { get; set; } + public double ObjectHeight { get; set; } /// /// 构造函数 /// public GridMapCacheKey(string logisticsDataHash, string boundsHash, double cellSize, - double vehicleRadius, double safetyMargin, double vehicleHeight) + double objectRadius, double safetyMargin, double objectHeight) { LogisticsDataHash = logisticsDataHash ?? throw new ArgumentNullException(nameof(logisticsDataHash)); BoundsHash = boundsHash ?? throw new ArgumentNullException(nameof(boundsHash)); CellSize = cellSize; - VehicleRadius = vehicleRadius; + ObjectRadius = objectRadius; SafetyMargin = safetyMargin; - VehicleHeight = vehicleHeight; + ObjectHeight = objectHeight; } /// @@ -67,9 +67,9 @@ namespace NavisworksTransport.PathPlanning return LogisticsDataHash == other.LogisticsDataHash && BoundsHash == other.BoundsHash && Math.Abs(CellSize - other.CellSize) < 1e-6 && - Math.Abs(VehicleRadius - other.VehicleRadius) < 1e-6 && + Math.Abs(ObjectRadius - other.ObjectRadius) < 1e-6 && Math.Abs(SafetyMargin - other.SafetyMargin) < 1e-6 && - Math.Abs(VehicleHeight - other.VehicleHeight) < 1e-6; + Math.Abs(ObjectHeight - other.ObjectHeight) < 1e-6; } /// @@ -91,9 +91,9 @@ namespace NavisworksTransport.PathPlanning hash = hash * 23 + (LogisticsDataHash?.GetHashCode() ?? 0); hash = hash * 23 + (BoundsHash?.GetHashCode() ?? 0); hash = hash * 23 + CellSize.GetHashCode(); - hash = hash * 23 + VehicleRadius.GetHashCode(); + hash = hash * 23 + ObjectRadius.GetHashCode(); hash = hash * 23 + SafetyMargin.GetHashCode(); - hash = hash * 23 + VehicleHeight.GetHashCode(); + hash = hash * 23 + ObjectHeight.GetHashCode(); return hash; } } @@ -111,7 +111,7 @@ namespace NavisworksTransport.PathPlanning "NULL"; return $"GridMapKey[Logistics={logisticsPreview}, Bounds={boundsPreview}, " + - $"Cell={CellSize:F2}, VR={VehicleRadius:F1}m, SM={SafetyMargin:F1}m, VH={VehicleHeight:F1}m]"; + $"Cell={CellSize:F2}, OR={ObjectRadius:F1}m, SM={SafetyMargin:F1}m, OH={ObjectHeight:F1}m]"; } /// @@ -119,19 +119,19 @@ namespace NavisworksTransport.PathPlanning /// /// 边界范围 /// 网格大小 - /// 车辆半径(米) + /// 运动物体半径(米) /// 安全间隙(米) - /// 车辆高度(米) + /// 运动物体高度(米) /// 缓存键 public static GridMapCacheKey CreateFrom(BoundingBox3D bounds, - double cellSize, double vehicleRadius, - double safetyMargin, double vehicleHeight) + double cellSize, double objectRadius, + double safetyMargin, double objectHeight) { var logisticsDataHash = ComputeLogisticsDataHash(); var boundsHash = ComputeBoundsHash(bounds); return new GridMapCacheKey(logisticsDataHash, boundsHash, cellSize, - vehicleRadius, safetyMargin, vehicleHeight); + objectRadius, safetyMargin, objectHeight); } /// diff --git a/src/PathPlanning/GridMapGenerator.cs b/src/PathPlanning/GridMapGenerator.cs index efb5edf..467abef 100644 --- a/src/PathPlanning/GridMapGenerator.cs +++ b/src/PathPlanning/GridMapGenerator.cs @@ -58,35 +58,35 @@ namespace NavisworksTransport.PathPlanning /// Navisworks文档 /// 扫描边界 /// 网格单元大小(米) - /// 车辆半径(米) + /// 运动物体半径(米) /// 安全间隙(米) /// 规划起点 /// 规划终点 - /// 车辆高度(米) + /// 运动物体高度(米) /// 生成的网格地图 - public GridMap GenerateFromBIM(BoundingBox3D bounds, double cellSize, double vehicleRadius, double safetyMargin, Point3D planningStartPoint, Point3D planningEndPoint, double vehicleHeight) + public GridMap GenerateFromBIM(BoundingBox3D bounds, double cellSize, double objectRadius, double safetyMargin, Point3D planningStartPoint, Point3D planningEndPoint, double objectHeight) { try { // 第一步:统一转换所有米制参数为模型单位 double metersToModelUnitsConversionFactor = UnitsConverter.GetMetersToUnitsConversionFactor(Application.ActiveDocument.Units); double cellSizeInModelUnits = cellSize * metersToModelUnitsConversionFactor; - double vehicleRadiusInModelUnits = vehicleRadius * metersToModelUnitsConversionFactor; + double objectRadiusInModelUnits = objectRadius * metersToModelUnitsConversionFactor; double safetyMarginInModelUnits = safetyMargin * metersToModelUnitsConversionFactor; - double vehicleHeightInModelUnits = vehicleHeight * metersToModelUnitsConversionFactor; - double scanHeightInModelUnits = vehicleHeightInModelUnits + safetyMarginInModelUnits; // 扫描高度 = 车辆高度 + 安全间隙 - double totalInflationRadiusInModelUnits = vehicleRadiusInModelUnits + safetyMarginInModelUnits; // 膨胀半径 = 车辆半径 + 安全间隙 + double objectHeightInModelUnits = objectHeight * metersToModelUnitsConversionFactor; + double scanHeightInModelUnits = objectHeightInModelUnits + safetyMarginInModelUnits; // 扫描高度 = 运动物体高度 + 安全间隙 + double totalInflationRadiusInModelUnits = objectRadiusInModelUnits + safetyMarginInModelUnits; // 膨胀半径 = 运动物体半径 + 安全间隙 LogManager.Info($"【生成网格地图】参数单位转换完成 (转换系数: {metersToModelUnitsConversionFactor:F2}):"); LogManager.Info($" 网格大小: {cellSize}米 → {cellSizeInModelUnits:F2}模型单位"); - LogManager.Info($" 车辆半径: {vehicleRadius}米 → {vehicleRadiusInModelUnits:F2}模型单位"); + LogManager.Info($" 运动物体半径: {objectRadius}米 → {objectRadiusInModelUnits:F2}模型单位"); LogManager.Info($" 安全间隙: {safetyMargin}米 → {safetyMarginInModelUnits:F2}模型单位"); - LogManager.Info($" 车辆高度: {vehicleHeight}米 → {vehicleHeightInModelUnits:F2}模型单位"); + LogManager.Info($" 运动物体高度: {objectHeight}米 → {objectHeightInModelUnits:F2}模型单位"); LogManager.Info($" 扫描高度: {scanHeightInModelUnits:F2}模型单位"); LogManager.Info($" 膨胀半径: {totalInflationRadiusInModelUnits:F2}模型单位"); // 生成缓存键(使用转换后的模型单位参数确保一致性) - var cacheKey = GridMapCacheKey.CreateFrom(bounds, cellSizeInModelUnits, vehicleRadiusInModelUnits, safetyMarginInModelUnits, vehicleHeightInModelUnits); + var cacheKey = GridMapCacheKey.CreateFrom(bounds, cellSizeInModelUnits, objectRadiusInModelUnits, safetyMarginInModelUnits, objectHeightInModelUnits); // 尝试从缓存获取 var cachedGridMap = GlobalGridMapCache.Instance.Get(cacheKey, 5000); // 预估生成需要5秒 @@ -163,10 +163,10 @@ namespace NavisworksTransport.PathPlanning LogManager.Info($"【阶段2.7完成】边界层标记后网格统计: {channelCoverage.GridMap.GetStatistics()}"); // 3. 应用车辆尺寸膨胀 - if (vehicleRadius > 0 || safetyMargin > 0) + if (objectRadius > 0 || safetyMargin > 0) { LogManager.Info("【生成网格地图】步骤3: 应用车辆膨胀"); - ApplyVehicleInflation(channelCoverage.GridMap, totalInflationRadiusInModelUnits); + ApplyObjectInflation(channelCoverage.GridMap, totalInflationRadiusInModelUnits); LogManager.Info($"【生成网格地图】车辆膨胀完成,膨胀半径: {totalInflationRadiusInModelUnits:F2}模型单位"); LogManager.Info($"【阶段3完成】车辆膨胀后网格统计: {channelCoverage.GridMap.GetStatistics()}"); } @@ -834,19 +834,19 @@ namespace NavisworksTransport.PathPlanning /// 在障碍物周围扩展不可通行区域,考虑车辆尺寸 /// /// 网格地图 - /// 车辆半径(模型单位) - private void ApplyVehicleInflation(GridMap gridMap, double vehicleRadiusInModelUnits) + /// 运动物体半径(模型单位) + private void ApplyObjectInflation(GridMap gridMap, double objectRadiusInModelUnits) { - if (vehicleRadiusInModelUnits <= 0) return; + if (objectRadiusInModelUnits <= 0) return; try { // 计算膨胀半径(网格单元格数) - int inflationRadius = (int)Math.Ceiling(vehicleRadiusInModelUnits / gridMap.CellSize); + int inflationRadius = (int)Math.Ceiling(objectRadiusInModelUnits / gridMap.CellSize); LogManager.Info($"[高效膨胀] 膨胀半径: {inflationRadius}个网格单元"); // 使用高效的距离变换算法 - ApplyVehicleInflation(gridMap, inflationRadius); + ApplyObjectInflation(gridMap, inflationRadius); } catch (Exception ex) { @@ -859,7 +859,7 @@ namespace NavisworksTransport.PathPlanning /// 多层膨胀算法 - 分两次处理:障碍物膨胀 + 边界膨胀 /// 核心原则:障碍物从外围膨胀(不含本身),边界从边界本身膨胀(包含边界) /// - private void ApplyVehicleInflation(GridMap gridMap, int inflationRadius) + private void ApplyObjectInflation(GridMap gridMap, int inflationRadius) { var stopwatch = System.Diagnostics.Stopwatch.StartNew(); @@ -1313,7 +1313,7 @@ namespace NavisworksTransport.PathPlanning var walkableGridCount = channelCoverage.WalkableGridCount; var walkableHeightRange = walkableMaxZ - walkableMinZ; LogManager.Info($"[高性能障碍物处理] 可通行网格高度信息 - 最低点: {walkableMinZ:F2}, 最高点: {walkableMaxZ:F2}"); - LogManager.Info($"[高性能障碍物处理] 可通行网格数量: {walkableGridCount}, 高度范围: {walkableHeightRange:F2}, 加车辆高度后扫描范围: [{walkableMinZ:F2}, {walkableMaxZ + scanHeightInModelUnits:F2}]"); + LogManager.Info($"[高性能障碍物处理] 可通行网格数量: {walkableGridCount}, 高度范围: {walkableHeightRange:F2}, 加运动物体高度后扫描范围: [{walkableMinZ:F2}, {walkableMaxZ + scanHeightInModelUnits:F2}]"); // 阶段4:网格覆盖计算(并行几何计算)- 使用50%CPU核心优化 + 基于通道的精确高度检查 LogManager.Info("[高性能障碍物处理] 阶段4: 并行网格覆盖计算 + 基于通道高度的精确高度检查"); @@ -1337,7 +1337,7 @@ namespace NavisworksTransport.PathPlanning var centerCell = gridMap.Cells[centerGridPos.X, centerGridPos.Y]; // 使用可通行网格高度范围计算扫描范围 - // 扫描范围:从可通行网格最低点开始,到可通行网格最高点+车辆高度+安全间隙 + // 扫描范围:从可通行网格最低点开始,到可通行网格最高点+运动物体高度+安全间隙 var scanMin = walkableMinZ; var scanMax = walkableMaxZ + scanHeightInModelUnits; diff --git a/src/PathPlanning/PathOptimizer.cs b/src/PathPlanning/PathOptimizer.cs index b82bb5e..72d9d39 100644 --- a/src/PathPlanning/PathOptimizer.cs +++ b/src/PathPlanning/PathOptimizer.cs @@ -47,14 +47,14 @@ namespace NavisworksTransport.PathPlanning public bool EnableCollisionCheck { get; set; } /// - /// 车辆长度(米,未来扩展) + /// 物体长度(米,未来扩展) /// - public double VehicleLength { get; set; } + public double ObjectLength { get; set; } /// - /// 车辆宽度(米,未来扩展) + /// 物体宽度(米,未来扩展) /// - public double VehicleWidth { get; set; } + public double ObjectWidth { get; set; } } private readonly OptimizationConfig _config; diff --git a/src/PathPlanning/VoxelGridGenerator.cs b/src/PathPlanning/VoxelGridGenerator.cs index 15325ce..dc189bb 100644 --- a/src/PathPlanning/VoxelGridGenerator.cs +++ b/src/PathPlanning/VoxelGridGenerator.cs @@ -93,15 +93,15 @@ namespace NavisworksTransport.PathPlanning /// /// 网格边界(世界坐标,模型单位) /// 体素尺寸(米) - /// 车辆半径(米),用于安全间隙 - /// 车辆高度(米) + /// 车辆半径(米),用于安全间隙 + /// 车辆高度(米) /// 障碍物模型元素列表 /// 生成的体素网格 public VoxelGrid GenerateFromBIMWithSDF( BoundingBox3D bounds, double voxelSizeMeters, - double vehicleRadiusMeters, - double vehicleHeightMeters, + double objectRadiusMeters, + double objectHeightMeters, IEnumerable obstacleItems) { var stopwatch = Stopwatch.StartNew(); @@ -112,13 +112,13 @@ namespace NavisworksTransport.PathPlanning Autodesk.Navisworks.Api.Application.ActiveDocument.Units); double voxelSizeInModelUnits = voxelSizeMeters * metersToModelUnits; - double vehicleRadiusInModelUnits = vehicleRadiusMeters * metersToModelUnits; - double vehicleHeightInModelUnits = vehicleHeightMeters * metersToModelUnits; - double safetyMarginInModelUnits = vehicleRadiusInModelUnits; // 安全间隙 = 车辆半径 + double objectRadiusInModelUnits = objectRadiusMeters * metersToModelUnits; + double objectHeightInModelUnits = objectHeightMeters * metersToModelUnits; + double safetyMarginInModelUnits = objectRadiusInModelUnits; // 安全间隙 = 车辆半径 LogManager.Info($"单位转换系数: {metersToModelUnits:F4}"); LogManager.Info($"体素尺寸: {voxelSizeMeters}米 = {voxelSizeInModelUnits:F2}模型单位"); - LogManager.Info($"安全间隙: {vehicleRadiusMeters}米 = {safetyMarginInModelUnits:F2}模型单位"); + LogManager.Info($"安全间隙: {objectRadiusMeters}米 = {safetyMarginInModelUnits:F2}模型单位"); // 第二步:创建体素网格 var voxelGrid = new VoxelGrid(bounds, voxelSizeInModelUnits); @@ -286,12 +286,12 @@ namespace NavisworksTransport.PathPlanning LogManager.Info($"标记统计: 障碍物={obstacleCount:N0}, 可通行={passableCount:N0}, 边界={boundaryCount:N0}"); // 第六步:障碍物膨胀(可选) - if (vehicleRadiusMeters > 0) + if (objectRadiusMeters > 0) { LogManager.Info("开始障碍物膨胀..."); var inflationStopwatch = Stopwatch.StartNew(); - int inflatedCount = voxelGrid.InflateObstacles(vehicleRadiusMeters, metersToModelUnits); + int inflatedCount = voxelGrid.InflateObstacles(objectRadiusMeters, metersToModelUnits); inflationStopwatch.Stop(); LogManager.Info($"障碍物膨胀完成,耗时: {inflationStopwatch.ElapsedMilliseconds} ms"); diff --git a/src/UI/WPF/ViewModels/AnimationControlViewModel.cs b/src/UI/WPF/ViewModels/AnimationControlViewModel.cs index 31f46bf..22cb50f 100644 --- a/src/UI/WPF/ViewModels/AnimationControlViewModel.cs +++ b/src/UI/WPF/ViewModels/AnimationControlViewModel.cs @@ -313,12 +313,15 @@ namespace NavisworksTransport.UI.WPF.ViewModels private bool _canGenerateAnimation = false; // 虚拟车辆相关字段 - private bool _useVirtualVehicle = false; // 使用虚拟车辆 - private double _virtualVehicleLength; // 虚拟车辆长度(米) - private double _virtualVehicleWidth; // 虚拟车辆宽度(米) - private double _virtualVehicleHeight; // 虚拟车辆高度(米) + private bool _useVirtualObject = false; // 使用虚拟车辆 + private double _virtualObjectLength; // 虚拟车辆长度(米) + private double _virtualObjectWidth; // 虚拟车辆宽度(米) + private double _virtualObjectHeight; // 虚拟车辆高度(米) private double _safetyMargin; // 检测间隙(米),从路径编辑同步 + // 剖面盒优化相关字段 + private bool _useSectionClip = true; // 使用剖面盒优化(默认启用,用于性能对比测试) + // 角度修正相关字段 private double _objectRotationCorrection; // 物体角度修正值(度,顺时针) @@ -613,14 +616,29 @@ namespace NavisworksTransport.UI.WPF.ViewModels /// 是否使用选择的模型物体 /// /// - /// 是否使用虚拟车辆 + /// 是否使用剖面盒优化(用于性能对比测试) /// - public bool UseVirtualVehicle + public bool UseSectionClip { - get => _useVirtualVehicle; + get => _useSectionClip; set { - if (SetProperty(ref _useVirtualVehicle, value)) + if (SetProperty(ref _useSectionClip, value)) + { + LogManager.Info($"[剖面盒] 优化开关已{(value ? "启用" : "禁用")}"); + } + } + } + + /// + /// 是否使用虚拟车辆 + /// + public bool UseVirtualObject + { + get => _useVirtualObject; + set + { + if (SetProperty(ref _useVirtualObject, value)) { // ✨ 模式切换清理:切换到虚拟车辆模式时,移除选择物体的动画数据 if (value) @@ -630,7 +648,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels // 只有在当前动画对象不是虚拟车辆时才执行重置 if (_pathAnimationManager != null && _pathAnimationManager.AnimatedObject != null && - !VirtualVehicleManager.Instance.IsVirtualVehicleActive) + !VirtualObjectManager.Instance.IsVirtualObjectActive) { _pathAnimationManager.RestoreObjectToCADPosition(); _pathAnimationManager.ClearAnimationResults(); // 清理手动选择物体留下的动画数据 @@ -639,8 +657,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels // 显示虚拟车辆 LogManager.Info("正在显示虚拟车辆..."); - VirtualVehicleManager.Instance.ShowVirtualVehicle( - VirtualVehicleLength, VirtualVehicleWidth, VirtualVehicleHeight); + VirtualObjectManager.Instance.ShowVirtualObject( + VirtualObjectLength, VirtualObjectWidth, VirtualObjectHeight); // 重置角度修正值(虚拟车辆重新选择时重置) ObjectRotationCorrection = 0.0; @@ -663,7 +681,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels try { // 不删除虚拟车辆,只隐藏它 - VirtualVehicleManager.Instance.HideVirtualVehicle(); + VirtualObjectManager.Instance.HideVirtualObject(); _pathAnimationManager?.ClearAnimationResults(); // 清理虚拟车辆留下的动画数据 LogManager.Info("已切换到手动选择模式,自动隐藏虚拟车辆并清理动画数据"); } @@ -680,28 +698,28 @@ namespace NavisworksTransport.UI.WPF.ViewModels /// /// 虚拟车辆长度(米)- 只读,从路径编辑同步 /// - public double VirtualVehicleLength + public double VirtualObjectLength { - get => _virtualVehicleLength; - private set => SetProperty(ref _virtualVehicleLength, value); + get => _virtualObjectLength; + private set => SetProperty(ref _virtualObjectLength, value); } /// /// 虚拟车辆宽度(米)- 只读,从路径编辑同步 /// - public double VirtualVehicleWidth + public double VirtualObjectWidth { - get => _virtualVehicleWidth; - private set => SetProperty(ref _virtualVehicleWidth, value); + get => _virtualObjectWidth; + private set => SetProperty(ref _virtualObjectWidth, value); } /// /// 虚拟车辆高度(米)- 只读,从路径编辑同步 /// - public double VirtualVehicleHeight + public double VirtualObjectHeight { - get => _virtualVehicleHeight; - private set => SetProperty(ref _virtualVehicleHeight, value); + get => _virtualObjectHeight; + private set => SetProperty(ref _virtualObjectHeight, value); } /// @@ -724,18 +742,18 @@ namespace NavisworksTransport.UI.WPF.ViewModels /// 设置虚拟车辆参数(由主ViewModel调用) /// 参数单位:米 /// - public void SetVirtualVehicleParameters(double length, double width, double height, double safetyMargin) + public void SetVirtualObjectParameters(double length, double width, double height, double safetyMargin) { - LogManager.Info($"[AnimationControlViewModel] SetVirtualVehicleParameters被调用: length={length:F4}, width={width:F4}, height={height:F4}, safetyMargin={safetyMargin:F4}"); - VirtualVehicleLength = length; - VirtualVehicleWidth = width; - VirtualVehicleHeight = height; + LogManager.Info($"[AnimationControlViewModel] SetVirtualObjectParameters被调用: length={length:F4}, width={width:F4}, height={height:F4}, safetyMargin={safetyMargin:F4}"); + VirtualObjectLength = length; + VirtualObjectWidth = width; + VirtualObjectHeight = height; _safetyMargin = safetyMargin; LogManager.Info($"[AnimationControlViewModel] 虚拟车辆参数已更新: {length:F1}米 × {width:F1}米 × {height:F1}米, 检测间隙: {safetyMargin:F2}米, _safetyMargin={_safetyMargin:F4}"); // 如果当前使用虚拟车辆模式,更新生成动画的可用状态 - if (UseVirtualVehicle) + if (UseVirtualObject) { UpdateCanGenerateAnimation(); // 更新通行空间可视化 @@ -1053,9 +1071,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels _detectionTolerance = config.Animation.DetectionToleranceMeters; // 🔥 从配置加载虚拟车辆尺寸(与路径编辑保持一致,使用米单位接口) - VirtualVehicleLength = config.PathEditing.VehicleLengthMeters; - VirtualVehicleWidth = config.PathEditing.VehicleWidthMeters; - VirtualVehicleHeight = config.PathEditing.VehicleHeightMeters; + VirtualObjectLength = config.PathEditing.ObjectLengthMeters; + VirtualObjectWidth = config.PathEditing.ObjectWidthMeters; + VirtualObjectHeight = config.PathEditing.ObjectHeightMeters; // 设置动画按钮的初始状态 UpdateAnimationButtonStates(); @@ -1134,12 +1152,12 @@ namespace NavisworksTransport.UI.WPF.ViewModels var config = ConfigManager.Instance.Current; // 更新车辆参数 - VirtualVehicleLength = config.PathEditing.VehicleLengthMeters; - VirtualVehicleWidth = config.PathEditing.VehicleWidthMeters; - VirtualVehicleHeight = config.PathEditing.VehicleHeightMeters; + VirtualObjectLength = config.PathEditing.ObjectLengthMeters; + VirtualObjectWidth = config.PathEditing.ObjectWidthMeters; + VirtualObjectHeight = config.PathEditing.ObjectHeightMeters; _safetyMargin = config.PathEditing.SafetyMarginMeters; - LogManager.Info($"车辆参数已更新 - 尺寸:{VirtualVehicleLength:F1}x{VirtualVehicleWidth:F1}x{VirtualVehicleHeight:F1}米, 安全间隙:{_safetyMargin:F2}米"); + LogManager.Info($"车辆参数已更新 - 尺寸:{VirtualObjectLength:F1}x{VirtualObjectWidth:F1}x{VirtualObjectHeight:F1}米, 安全间隙:{_safetyMargin:F2}米"); } } catch (Exception ex) @@ -3089,7 +3107,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels /// /// 获取运动物体的 PathId 信息 /// - private (int ModelIndex, string PathId) GetVehiclePathIdInfo() + private (int ModelIndex, string PathId) GetObjectPathIdInfo() { try { @@ -3258,7 +3276,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels Mouse.OverrideCursor = Cursors.Wait; UpdateMainStatus("正在生成动画...", -1, true); - LogManager.Info($"开始生成动画 - 模式: {(UseVirtualVehicle ? "虚拟车辆" : "选择物体")}"); + LogManager.Info($"开始生成动画 - 模式: {(UseVirtualObject ? "虚拟车辆" : "选择物体")}"); var cacheStartTime = DateTime.Now; @@ -3277,7 +3295,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels } // 🔥 预计算动画对象的排除列表(仅在非虚拟车辆、非手工模式下) - if (!manualModeEnabled && !UseVirtualVehicle) + if (!manualModeEnabled && !UseVirtualObject) { UpdateMainStatus("正在分析动画对象...", -1, true); @@ -3313,18 +3331,18 @@ namespace NavisworksTransport.UI.WPF.ViewModels ModelItem animatedObject = null; - if (UseVirtualVehicle) + if (UseVirtualObject) { - // 使用虚拟车辆:总是调用 ShowVirtualVehicle 来更新尺寸 + // 使用虚拟车辆:总是调用 ShowVirtualObject 来更新尺寸 LogManager.Info("[ExecuteGenerateAnimation] 显示并更新虚拟车辆..."); UpdateMainStatus("正在显示虚拟车辆...", -1, true); - VirtualVehicleManager.Instance.ShowVirtualVehicle( - VirtualVehicleLength, - VirtualVehicleWidth, - VirtualVehicleHeight + VirtualObjectManager.Instance.ShowVirtualObject( + VirtualObjectLength, + VirtualObjectWidth, + VirtualObjectHeight ); - animatedObject = VirtualVehicleManager.Instance.CurrentVirtualVehicle; + animatedObject = VirtualObjectManager.Instance.CurrentVirtualObject; if (animatedObject == null) { @@ -3337,7 +3355,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels if (CurrentPathRoute != null && CurrentPathRoute.Points != null) { var points = CurrentPathRoute.Points.Select(p => new Point3D(p.X, p.Y, p.Z)).ToList(); - _pathAnimationManager?.MoveVehicleToPathStart(animatedObject, points); + _pathAnimationManager?.MoveObjectToPathStart(animatedObject, points); LogManager.Info("[ExecuteGenerateAnimation] 虚拟车辆已移到路径起点"); } @@ -3380,23 +3398,26 @@ namespace NavisworksTransport.UI.WPF.ViewModels // 准备车辆尺寸参数(从米转换为模型单位) var metersToModelUnits = Utils.UnitsConverter.GetMetersToUnitsConversionFactor(); - double vLength = UseVirtualVehicle ? VirtualVehicleLength * metersToModelUnits : 0; - double vWidth = UseVirtualVehicle ? VirtualVehicleWidth * metersToModelUnits : 0; - double vHeight = UseVirtualVehicle ? VirtualVehicleHeight * metersToModelUnits : 0; + double vLength = UseVirtualObject ? VirtualObjectLength * metersToModelUnits : 0; + double vWidth = UseVirtualObject ? VirtualObjectWidth * metersToModelUnits : 0; + double vHeight = UseVirtualObject ? VirtualObjectHeight * metersToModelUnits : 0; double safetyMargin = _safetyMargin * metersToModelUnits; - LogManager.Info($"[ExecuteGenerateAnimation] 准备调用CreateAnimation: UseVirtualVehicle={UseVirtualVehicle}, 车辆尺寸: {vLength:F2}×{vWidth:F2}×{vHeight:F2}模型单位, 安全间隙: {safetyMargin:F4}模型单位 (_safetyMargin={_safetyMargin:F4}米)"); + LogManager.Info($"[ExecuteGenerateAnimation] 准备调用CreateAnimation: UseVirtualObject={UseVirtualObject}, 车辆尺寸: {vLength:F2}×{vWidth:F2}×{vHeight:F2}模型单位, 安全间隙: {safetyMargin:F4}模型单位 (_safetyMargin={_safetyMargin:F4}米)"); - _pathAnimationManager.CreateAnimation(animatedObject, pathPoints, AnimationDuration, CurrentPathRoute.Name, CurrentPathRoute.Id, UseVirtualVehicle, + // 设置剖面盒优化开关 + _pathAnimationManager.SetUseSectionClip(UseSectionClip); + + _pathAnimationManager.CreateAnimation(animatedObject, pathPoints, AnimationDuration, CurrentPathRoute.Name, CurrentPathRoute.Id, UseVirtualObject, vLength, vWidth, vHeight, safetyMargin); var totalElapsed = (DateTime.Now - cacheStartTime).TotalMilliseconds; LogManager.Info($"[动画生成] 动画生成完成,总耗时: {totalElapsed:F1}ms"); LogManager.Info($"动画生成成功: 物体={animatedObject.DisplayName}, 路径={CurrentPathRoute.Name}"); - if (UseVirtualVehicle) + if (UseVirtualObject) { - LogManager.Info($"虚拟车辆尺寸: {VirtualVehicleLength:F1}×{VirtualVehicleWidth:F1}×{VirtualVehicleHeight:F1}m"); + LogManager.Info($"虚拟车辆尺寸: {VirtualObjectLength:F1}×{VirtualObjectWidth:F1}×{VirtualObjectHeight:F1}m"); } if (IsManualCollisionTargetEnabled) @@ -3458,10 +3479,10 @@ namespace NavisworksTransport.UI.WPF.ViewModels { double baseLength, baseWidth; - if (UseVirtualVehicle) + if (UseVirtualObject) { - baseLength = VirtualVehicleLength; - baseWidth = VirtualVehicleWidth; + baseLength = VirtualObjectLength; + baseWidth = VirtualObjectWidth; } else if (SelectedAnimatedObject != null) { @@ -3526,18 +3547,18 @@ namespace NavisworksTransport.UI.WPF.ViewModels // 使用从路径编辑同步过来的检测间隙 double safetyMargin = _safetyMargin; - if (UseVirtualVehicle) + if (UseVirtualObject) { // 虚拟车辆的xyz定义:X方向 = 长度(前进方向),Y方向 = 宽度(侧面),Z方向 = 高度 if (CurrentPathRoute.PathType == NavisworksTransport.PathType.Rail || CurrentPathRoute.PathType == NavisworksTransport.PathType.Hoisting) { // 空中路径(空轨或吊装):高度上下都加间隙 passageAcrossPath = effectiveWidth + 2 * safetyMargin; // 旋转后宽度 + 2*间隙(垂直于路径方向) - passageNormalToPath = VirtualVehicleHeight + 2 * safetyMargin; // Z方向(高度)+ 2*间隙(法线方向) + passageNormalToPath = VirtualObjectHeight + 2 * safetyMargin; // Z方向(高度)+ 2*间隙(法线方向) passageAlongPath = effectiveLength; // 旋转后长度(沿路径方向) // 吊装路径分段参数 passageNormalToPathVertical = effectiveLength + 2 * safetyMargin; // 垂直段:物体长度 + 2*间隙 - passageNormalToPathHorizontal = VirtualVehicleHeight + 2 * safetyMargin; // 水平段:物体高度 + 2*间隙 + passageNormalToPathHorizontal = VirtualObjectHeight + 2 * safetyMargin; // 水平段:物体高度 + 2*间隙 LogManager.Debug($"[通行空间可视化] 空中路径使用虚拟车辆尺寸: 有效长度={effectiveLength:F2}m, 有效宽度={effectiveWidth:F2}m, 通行空间沿路径={passageAlongPath:F2}m, 垂直路径={passageAcrossPath:F2}m, 法线={passageNormalToPath:F2}m"); } else if (CurrentPathRoute.PathType == NavisworksTransport.PathType.Ground) @@ -3545,7 +3566,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels // 地面路径:物体的长度方向(X轴,前进方向)朝向路径方向 // 通行空间沿路径方向 = X方向尺寸(长度),垂直于路径方向 = Y方向尺寸(宽度),高度上方加间隙(下方不需要,因为有地面) passageAcrossPath = effectiveWidth + 2 * safetyMargin; // 旋转后宽度 + 2*间隙(垂直于路径方向) - passageNormalToPath = VirtualVehicleHeight + safetyMargin; // Z方向(高度)+ 间隙(法线方向,只有上方) + passageNormalToPath = VirtualObjectHeight + safetyMargin; // Z方向(高度)+ 间隙(法线方向,只有上方) passageAlongPath = effectiveLength; // 旋转后长度(沿路径方向) // 地面路径不需要分段参数 passageNormalToPathVertical = passageNormalToPath; @@ -3557,7 +3578,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels // 空轨路径:物体的长度方向(X轴,前进方向)朝向路径方向 // 通行空间沿路径方向 = X方向尺寸(长度),垂直于路径方向 = Y方向尺寸(宽度),高度上下都加间隙(在空中) passageAcrossPath = effectiveWidth + 2 * safetyMargin; // 旋转后宽度 + 2*间隙(垂直于路径方向) - passageNormalToPath = VirtualVehicleHeight + 2 * safetyMargin; // Z方向(高度)+ 2*间隙(法线方向,上下都加) + passageNormalToPath = VirtualObjectHeight + 2 * safetyMargin; // Z方向(高度)+ 2*间隙(法线方向,上下都加) passageAlongPath = effectiveLength; // 旋转后长度(沿路径方向) // 空轨路径不需要分段参数 passageNormalToPathVertical = passageNormalToPath; @@ -3631,16 +3652,16 @@ namespace NavisworksTransport.UI.WPF.ViewModels LogManager.Debug($"[通行空间可视化] 已设置通行空间参数: 沿路径={passageAlongPath:F2}m, 垂直路径={passageAcrossPath:F2}m, 法线={passageNormalToPath:F2}m, 安全间隙={safetyMargin:F2}m"); // 根据路径类型决定是否切换到车辆通行空间模式 - bool enableVehicleSpace = false; + bool enableObjectSpace = false; switch (CurrentPathRoute.PathType) { case NavisworksTransport.PathType.Rail: case NavisworksTransport.PathType.Hoisting: - enableVehicleSpace = true; + enableObjectSpace = true; LogManager.Debug($"[通行空间可视化] 路径类型={CurrentPathRoute.PathType}(空中路径),切换到车辆通行空间模式"); break; case NavisworksTransport.PathType.Ground: - enableVehicleSpace = false; + enableObjectSpace = false; LogManager.Debug($"[通行空间可视化] 路径类型={CurrentPathRoute.PathType},不切换到车辆通行空间模式"); break; default: @@ -3649,9 +3670,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels } // 切换到车辆通行空间模式(如果需要) - if (enableVehicleSpace) + if (enableObjectSpace) { - renderPlugin.VisualizationMode = PathVisualizationMode.VehicleSpace; + renderPlugin.VisualizationMode = PathVisualizationMode.ObjectSpace; LogManager.Debug("[通行空间可视化] 已切换到车辆通行空间模式"); } @@ -3697,12 +3718,12 @@ namespace NavisworksTransport.UI.WPF.ViewModels var hasPath = CurrentPathRoute != null && CurrentPathRoute.Points.Count >= 2; bool hasValidObject; - if (UseVirtualVehicle) + if (UseVirtualObject) { // 使用虚拟车辆时,只需要有效的车辆尺寸 - hasValidObject = VirtualVehicleLength > 0 && - VirtualVehicleWidth > 0 && - VirtualVehicleHeight > 0; + hasValidObject = VirtualObjectLength > 0 && + VirtualObjectWidth > 0 && + VirtualObjectHeight > 0; } else { @@ -3722,11 +3743,11 @@ namespace NavisworksTransport.UI.WPF.ViewModels } else if (!hasPath && !hasValidObject) { - UpdateMainStatus(UseVirtualVehicle ? "请选择动画路径" : "请选择移动物体和动画路径"); + UpdateMainStatus(UseVirtualObject ? "请选择动画路径" : "请选择移动物体和动画路径"); } else if (!hasValidObject) { - UpdateMainStatus(UseVirtualVehicle ? "虚拟车辆参数无效" : "请选择移动物体"); + UpdateMainStatus(UseVirtualObject ? "虚拟车辆参数无效" : "请选择移动物体"); } else if (!hasPath) { @@ -4356,10 +4377,10 @@ namespace NavisworksTransport.UI.WPF.ViewModels DetectionToleranceMeters = _detectionTolerance, // 运动物体配置 - IsVirtualVehicle = UseVirtualVehicle, - VirtualVehicleLength = VirtualVehicleLength, - VirtualVehicleWidth = VirtualVehicleWidth, - VirtualVehicleHeight = VirtualVehicleHeight, + IsVirtualObject = UseVirtualObject, + VirtualObjectLength = VirtualObjectLength, + VirtualObjectWidth = VirtualObjectWidth, + VirtualObjectHeight = VirtualObjectHeight, // 被检测项配置 DetectAllObjects = !IsManualCollisionTargetEnabled, @@ -4380,10 +4401,10 @@ namespace NavisworksTransport.UI.WPF.ViewModels var itemId = await batchQueueManager.AddQueueItemAsync(queueItem); // 存储运动物体到 ModelItemReferences 表 - if (!UseVirtualVehicle && SelectedAnimatedObject != null) + if (!UseVirtualObject && SelectedAnimatedObject != null) { LogManager.Info($"[批处理] 准备存储运动物体: {SelectedAnimatedObject.DisplayName}"); - var pathIdInfo = GetVehiclePathIdInfo(); + var pathIdInfo = GetObjectPathIdInfo(); LogManager.Info($"[批处理] 运动物体 PathId: ModelIndex={pathIdInfo.ModelIndex}, PathId={pathIdInfo.PathId}"); // 只要 PathId 不为空就认为是有效的(ModelIndex=0 表示主模型,也是有效的) @@ -4413,7 +4434,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels } else { - LogManager.Info($"[批处理] 跳过存储运动物体: UseVirtualVehicle={UseVirtualVehicle}, SelectedAnimatedObject 是否为 null={SelectedAnimatedObject == null}"); + LogManager.Info($"[批处理] 跳过存储运动物体: UseVirtualObject={UseVirtualObject}, SelectedAnimatedObject 是否为 null={SelectedAnimatedObject == null}"); } // 存储手工指定的碰撞检测目标到 ModelItemReferences 表 @@ -4441,7 +4462,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels } LogManager.Info($"[批处理] 已创建队列项: {CurrentPathRoute.Name}, " + - $"虚拟车辆: {queueItem.IsVirtualVehicle}, " + + $"虚拟车辆: {queueItem.IsVirtualObject}, " + $"帧率: {queueItem.FrameRate}, " + $"时长: {queueItem.DurationSeconds:F2}秒, " + $"角度修正: {queueItem.ObjectRotationCorrection:F1}°, " + diff --git a/src/UI/WPF/ViewModels/LogisticsControlViewModel.cs b/src/UI/WPF/ViewModels/LogisticsControlViewModel.cs index 501afa8..79a6a36 100644 --- a/src/UI/WPF/ViewModels/LogisticsControlViewModel.cs +++ b/src/UI/WPF/ViewModels/LogisticsControlViewModel.cs @@ -99,7 +99,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels } private bool _showPathLines = true; - private bool _showVehicleSpace = false; + private bool _showObjectSpace = false; /// /// 是否显示路径线/地面连线 @@ -123,17 +123,17 @@ namespace NavisworksTransport.UI.WPF.ViewModels /// /// 是否显示通行空间 /// - public bool ShowVehicleSpace + public bool ShowObjectSpace { - get => _showVehicleSpace; + get => _showObjectSpace; set { - if (SetProperty(ref _showVehicleSpace, value)) + if (SetProperty(ref _showObjectSpace, value)) { var renderPlugin = PathPointRenderPlugin.Instance; if (renderPlugin != null) { - renderPlugin.ShowVehicleSpace = value; + renderPlugin.ShowObjectSpace = value; } } } @@ -148,9 +148,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels if (renderPlugin != null) { _showPathLines = renderPlugin.ShowPathLines; - _showVehicleSpace = renderPlugin.ShowVehicleSpace; + _showObjectSpace = renderPlugin.ShowObjectSpace; OnPropertyChanged(nameof(ShowPathLines)); - OnPropertyChanged(nameof(ShowVehicleSpace)); + OnPropertyChanged(nameof(ShowObjectSpace)); } } diff --git a/src/UI/WPF/ViewModels/PathEditingViewModel.cs b/src/UI/WPF/ViewModels/PathEditingViewModel.cs index 798e4c5..80bd5fa 100644 --- a/src/UI/WPF/ViewModels/PathEditingViewModel.cs +++ b/src/UI/WPF/ViewModels/PathEditingViewModel.cs @@ -68,9 +68,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels private bool _isSelectingEndPoint = false; // 车辆参数 - 改为三个独立参数(从配置初始化) - private double _vehicleLength; // 车辆长度(米) - private double _vehicleWidth; // 车辆宽度(米) - private double _vehicleHeight; // 车辆高度(米) + private double _ObjectLength; // 车辆长度(米) + private double _ObjectWidth; // 车辆宽度(米) + private double _ObjectHeight; // 车辆高度(米) private double _safetyMargin; // 安全间隙(米) // 网格大小参数(从配置初始化) @@ -86,11 +86,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels // 三种渲染模式独立开关 private bool _showControlVisualization = true; // 默认显示控制点连线 private bool _showPathLines = true; // 默认显示路径线(地面连线) - private bool _showVehicleSpace = false; // 默认不显示通行空间 - // 兼容旧代码的互斥属性(已废弃,使用独立开关) - private bool _isStandardLineMode = false; - private bool _isRibbonLineMode = true; - private bool _isVehicleSpaceMode = false; + private bool _showObjectSpace = false; // 默认不显示通行空间 // 路径策略参数 private PathStrategyOption _selectedPathStrategy; @@ -242,7 +238,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels } // 0. 先同步车辆参数到渲染插件 - SyncVehicleParametersToRenderPlugin(); + SyncObjectParametersToRenderPlugin(); // 检查是否在编辑状态 bool isInEditMode = _pathPlanningManager?.IsInEditableState ?? false; @@ -330,40 +326,40 @@ namespace NavisworksTransport.UI.WPF.ViewModels } - public double VehicleLength + public double ObjectLength { - get => _vehicleLength; + get => _ObjectLength; set { - if (SetProperty(ref _vehicleLength, value)) + if (SetProperty(ref _ObjectLength, value)) { - SyncVehicleParametersToRenderPlugin(); + SyncObjectParametersToRenderPlugin(); OnPropertyChanged(nameof(CanExecuteAutoPlanPath)); } } } - public double VehicleWidth + public double ObjectWidth { - get => _vehicleWidth; + get => _ObjectWidth; set { - if (SetProperty(ref _vehicleWidth, value)) + if (SetProperty(ref _ObjectWidth, value)) { - SyncVehicleParametersToRenderPlugin(); + SyncObjectParametersToRenderPlugin(); OnPropertyChanged(nameof(CanExecuteAutoPlanPath)); } } } - public double VehicleHeight + public double ObjectHeight { - get => _vehicleHeight; + get => _ObjectHeight; set { - if (SetProperty(ref _vehicleHeight, value)) + if (SetProperty(ref _ObjectHeight, value)) { - SyncVehicleParametersToRenderPlugin(); + SyncObjectParametersToRenderPlugin(); OnPropertyChanged(nameof(CanExecuteAutoPlanPath)); } } @@ -378,7 +374,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels var roundedValue = Math.Round(value, 2); if (SetProperty(ref _safetyMargin, roundedValue)) { - SyncVehicleParametersToRenderPlugin(); + SyncObjectParametersToRenderPlugin(); OnPropertyChanged(nameof(CanExecuteAutoPlanPath)); } } @@ -558,12 +554,12 @@ namespace NavisworksTransport.UI.WPF.ViewModels /// /// 是否显示通行空间(独立开关) /// - public bool ShowVehicleSpace + public bool ShowObjectSpace { - get => _showVehicleSpace; + get => _showObjectSpace; set { - if (SetProperty(ref _showVehicleSpace, value)) + if (SetProperty(ref _showObjectSpace, value)) { OnPathVisualizationModeChanged(); } @@ -589,24 +585,24 @@ namespace NavisworksTransport.UI.WPF.ViewModels /// public bool IsStandardLineMode { - get => _showPathLines && !_showVehicleSpace; + get => _showPathLines && !_showObjectSpace; set { if (value) { ShowPathLines = true; - ShowVehicleSpace = false; + ShowObjectSpace = false; } } } /// - /// 是否使用车辆通行空间模式(向后兼容,等同于 ShowVehicleSpace) + /// 是否使用车辆通行空间模式(向后兼容,等同于 ShowObjectSpace) /// - public bool IsVehicleSpaceMode + public bool IsObjectSpaceMode { - get => _showVehicleSpace; - set => ShowVehicleSpace = value; + get => _showObjectSpace; + set => ShowObjectSpace = value; } /// @@ -711,7 +707,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels #region Can Execute属性 public bool CanExecuteAutoPlanPath => _hasStartPoint && _hasEndPoint && - VehicleLength > 0 && VehicleWidth > 0 && VehicleHeight > 0 && + ObjectLength > 0 && ObjectWidth > 0 && ObjectHeight > 0 && SafetyMargin >= 0; public bool CanExecuteNewPath => !IsSelectingStartPoint && !IsSelectingEndPoint; @@ -780,7 +776,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels // 初始化车辆参数同步(在PathPointRenderPlugin实例不为空时才同步) // 如果PathPointRenderPlugin尚未初始化,将在属性变更时自动同步 - SyncVehicleParametersToRenderPlugin(); + SyncObjectParametersToRenderPlugin(); // 注意:不在这里订阅PathPlanningManager事件, // 因为PathPlanningManager还没有设置,事件订阅在PathPlanningManager属性setter中处理 @@ -841,12 +837,12 @@ namespace NavisworksTransport.UI.WPF.ViewModels // 从 PathEditing 配置加载所有参数(使用米单位接口) _gridSize = config.PathEditing.CellSizeMeters; - _vehicleLength = config.PathEditing.VehicleLengthMeters; - _vehicleWidth = config.PathEditing.VehicleWidthMeters; - _vehicleHeight = config.PathEditing.VehicleHeightMeters; + _ObjectLength = config.PathEditing.ObjectLengthMeters; + _ObjectWidth = config.PathEditing.ObjectWidthMeters; + _ObjectHeight = config.PathEditing.ObjectHeightMeters; _safetyMargin = config.PathEditing.SafetyMarginMeters; - LogManager.Info($"从配置加载参数 - 车辆: {_vehicleLength:F1}x{_vehicleWidth:F1}x{_vehicleHeight:F1}米, 安全间隙: {_safetyMargin:F2}米, 网格: {_gridSize:F1}米"); + LogManager.Info($"从配置加载参数 - 车辆: {_ObjectLength:F1}x{_ObjectWidth:F1}x{_ObjectHeight:F1}米, 安全间隙: {_safetyMargin:F2}米, 网格: {_gridSize:F1}米"); } catch (Exception ex) { @@ -910,19 +906,19 @@ namespace NavisworksTransport.UI.WPF.ViewModels // 触发属性变更通知,更新UI OnPropertiesChanged( - nameof(VehicleLength), - nameof(VehicleWidth), - nameof(VehicleHeight), + nameof(ObjectLength), + nameof(ObjectWidth), + nameof(ObjectHeight), nameof(SafetyMargin), nameof(GridSize) ); // 同步车辆参数到渲染插件 - SyncVehicleParametersToRenderPlugin(); + SyncObjectParametersToRenderPlugin(); // 更新状态栏 string source = eventArgs.IsExternalChange ? "外部修改" : "内部更新"; - UpdateMainStatus($"配置已更新 ({source}) - 车辆参数: {VehicleLength:F1}x{VehicleWidth:F1}x{VehicleHeight:F1}米"); + UpdateMainStatus($"配置已更新 ({source}) - 车辆参数: {ObjectLength:F1}x{ObjectWidth:F1}x{ObjectHeight:F1}米"); LogManager.Info($"PathEditing 配置参数已更新完成 - 来源: {source}"); } @@ -1639,10 +1635,10 @@ namespace NavisworksTransport.UI.WPF.ViewModels LogManager.Info($"终点: ({_endPoint3D.X:F2}, {_endPoint3D.Y:F2}, {_endPoint3D.Z:F2})"); // 计算车辆半径:基于长度和宽度的较大值的一半,高度暂时不参与半径计算 - var vehicleRadius = Math.Max(VehicleLength, VehicleWidth) / 2.0; + var ObjectRadius = Math.Max(ObjectLength, ObjectWidth) / 2.0; - LogManager.Info($"车辆参数: 长{VehicleLength:F1}m × 宽{VehicleWidth:F1}m × 高{VehicleHeight:F1}m"); - LogManager.Info($"计算得出车辆半径: {vehicleRadius:F2}m (基于长宽较大值的一半)"); + LogManager.Info($"车辆参数: 长{ObjectLength:F1}m × 宽{ObjectWidth:F1}m × 高{ObjectHeight:F1}m"); + LogManager.Info($"计算得出车辆半径: {ObjectRadius:F2}m (基于长宽较大值的一半)"); // 确定网格大小:如果启用手动设置则使用用户设置的值,否则使用-1(自动选择) var gridSize = IsGridSizeManuallyEnabled ? GridSize : -1; @@ -1654,7 +1650,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels LogManager.Info($"路径策略: {SelectedPathStrategy?.DisplayName ?? "最短路径"}"); // 在STA线程中执行Navisworks API调用 - var pathRoute = await _pathPlanningManager?.AutoPlanPath(startPathPoint, endPathPoint, vehicleRadius, SafetyMargin, gridSize, VehicleHeight, selectedStrategy); + var pathRoute = await _pathPlanningManager?.AutoPlanPath(startPathPoint, endPathPoint, ObjectRadius, SafetyMargin, gridSize, ObjectHeight, selectedStrategy); if (pathRoute != null && pathRoute.Points.Count > 0) { @@ -2778,7 +2774,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels /// /// 同步车辆参数到渲染插件 /// - private void SyncVehicleParametersToRenderPlugin() + private void SyncObjectParametersToRenderPlugin() { try { @@ -2800,30 +2796,30 @@ namespace NavisworksTransport.UI.WPF.ViewModels if (pathType == PathType.Rail) { // 空轨路径:车辆水平悬挂,垂直于路径的截面包含车辆的宽度和高度 - passageAcrossPath = VehicleWidth + 2 * SafetyMargin; // Y方向(宽度)+ 2*间隙(垂直于路径方向) - passageNormalToPath = VehicleHeight + 2 * SafetyMargin; // Z方向(高度)+ 2*间隙(法线方向) - passageAlongPath = VehicleLength; // X方向(长度)(沿路径方向) + passageAcrossPath = ObjectWidth + 2 * SafetyMargin; // Y方向(宽度)+ 2*间隙(垂直于路径方向) + passageNormalToPath = ObjectHeight + 2 * SafetyMargin; // Z方向(高度)+ 2*间隙(法线方向) + passageAlongPath = ObjectLength; // X方向(长度)(沿路径方向) } else if (pathType == PathType.Hoisting) { // 吊装路径:车辆垂直悬挂,垂直于路径的截面包含车辆的长度和宽度 - passageAcrossPath = VehicleWidth + 2 * SafetyMargin; // Y方向(宽度)+ 2*间隙(垂直于路径方向) - passageNormalToPath = VehicleLength + 2 * SafetyMargin; // X方向(长度)+ 2*间隙(法线方向) - passageAlongPath = VehicleHeight; // Z方向(高度)(沿路径方向) + passageAcrossPath = ObjectWidth + 2 * SafetyMargin; // Y方向(宽度)+ 2*间隙(垂直于路径方向) + passageNormalToPath = ObjectLength + 2 * SafetyMargin; // X方向(长度)+ 2*间隙(法线方向) + passageAlongPath = ObjectHeight; // Z方向(高度)(沿路径方向) } else // Ground { // 地面路径:高度只有上方加间隙 - passageAcrossPath = VehicleWidth + 2 * SafetyMargin; // Y方向(宽度)+ 2*间隙(垂直于路径方向) - passageNormalToPath = VehicleHeight + SafetyMargin; // Z方向(高度)+ 间隙(法线方向,只有上方) - passageAlongPath = VehicleLength; // X方向(长度)(沿路径方向) + passageAcrossPath = ObjectWidth + 2 * SafetyMargin; // Y方向(宽度)+ 2*间隙(垂直于路径方向) + passageNormalToPath = ObjectHeight + SafetyMargin; // Z方向(高度)+ 间隙(法线方向,只有上方) + passageAlongPath = ObjectLength; // X方向(长度)(沿路径方向) } // 设置通行空间参数到渲染插件 // passageNormalToPathVertical: 垂直段的高度(物体长度 + 2×安全间隙) // passageNormalToPathHorizontal: 水平段的高度(物体高度 + 2×安全间隙) - double passageNormalToPathVertical = VehicleLength + 2 * SafetyMargin; - double passageNormalToPathHorizontal = VehicleHeight + 2 * SafetyMargin; + double passageNormalToPathVertical = ObjectLength + 2 * SafetyMargin; + double passageNormalToPathHorizontal = ObjectHeight + 2 * SafetyMargin; PathPointRenderPlugin.Instance.SetPassageSpaceParameters( passageAcrossPath, passageNormalToPath, @@ -2943,14 +2939,14 @@ namespace NavisworksTransport.UI.WPF.ViewModels case PathType.Hoisting: // 空中路径:通行空间 + 控制点,不能使用路径线 ShowPathLines = false; - ShowVehicleSpace = true; + ShowObjectSpace = true; LogManager.Debug($"[路径编辑] 路径类型={pathType}(空中路径),默认模式:控制点+通行空间"); break; case PathType.Ground: // 地面路径:路径线 + 控制点,不使用通行空间 ShowPathLines = true; - ShowVehicleSpace = false; + ShowObjectSpace = false; LogManager.Debug($"[路径编辑] 路径类型={pathType}(地面路径),默认模式:控制点+路径线"); break; @@ -2959,7 +2955,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels return; } - LogManager.Info($"[路径编辑] 已根据路径类型自动设置可视化模式:控制点={ShowControlVisualization}, 路径线={ShowPathLines}, 通行空间={ShowVehicleSpace}"); + LogManager.Info($"[路径编辑] 已根据路径类型自动设置可视化模式:控制点={ShowControlVisualization}, 路径线={ShowPathLines}, 通行空间={ShowObjectSpace}"); // 🔥 触发可视化状态变更事件,通知状态栏刷新按钮 _pathPlanningManager?.RaiseVisualizationStateChanged(); @@ -2982,14 +2978,14 @@ namespace NavisworksTransport.UI.WPF.ViewModels { // 使用新的独立开关设置渲染插件 renderPlugin.ShowPathLines = ShowPathLines; - renderPlugin.ShowVehicleSpace = ShowVehicleSpace; + renderPlugin.ShowObjectSpace = ShowObjectSpace; string modeName = ""; - if (ShowPathLines && ShowVehicleSpace) + if (ShowPathLines && ShowObjectSpace) modeName = "路径线 + 通行空间"; else if (ShowPathLines) modeName = "路径线"; - else if (ShowVehicleSpace) + else if (ShowObjectSpace) modeName = "通行空间"; else modeName = "无路径可视化"; @@ -3806,7 +3802,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels /// /// 车辆参数类 - 用于传递车辆尺寸信息给路径规划算法 /// - public class VehicleParameters + public class ObjectParameters { public double Length { get; set; } public double Width { get; set; } diff --git a/src/UI/WPF/ViewModels/SystemManagementViewModel.cs b/src/UI/WPF/ViewModels/SystemManagementViewModel.cs index b1ddb55..94adebf 100644 --- a/src/UI/WPF/ViewModels/SystemManagementViewModel.cs +++ b/src/UI/WPF/ViewModels/SystemManagementViewModel.cs @@ -1268,8 +1268,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels document, cellSize: cellSizeMeters, // 使用系统配置的体素大小 samplingRate: 1, // 采样率 1(显示所有体素) - vehicleRadius: 0.6, // 车辆半径 0.6米(必须 >= 体素大小才能看到膨胀效果) - vehicleHeight: 1.8 // 车辆高度 1.8米 + objectRadius: 0.6, // 物体半径 0.6米(必须 >= 体素大小才能看到膨胀效果) + objectHeight: 1.8 // 物体高度 1.8米 ); var result = await testCommand.ExecuteAsync(); @@ -1359,8 +1359,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels var testCommand = new VoxelPathFindingTestCommand( document, cellSize: cellSizeMeters, // 体素大小(米) - vehicleRadius: 0.6, // 车辆半径 0.6米 - vehicleHeight: 1.8, // 车辆高度 1.8米 + objectRadius: 0.6, // 物体半径 0.6米 + objectHeight: 1.8, // 物体高度 1.8米 startPoint: startPoint, // 起点 endPoint: endPoint // 终点 ); diff --git a/src/UI/WPF/Views/AnimationControlView.xaml b/src/UI/WPF/Views/AnimationControlView.xaml index 1d2ca73..a2fbe19 100644 --- a/src/UI/WPF/Views/AnimationControlView.xaml +++ b/src/UI/WPF/Views/AnimationControlView.xaml @@ -322,7 +322,7 @@ NavisworksTransport 检测动画页签视图 - 采用与类别设置和分层管 GroupName="ObjectSource" VerticalAlignment="Center"/> @@ -330,7 +330,7 @@ NavisworksTransport 检测动画页签视图 - 采用与类别设置和分层管 + Visibility="{Binding UseVirtualObject, Converter={StaticResource BoolToVisibilityConverter}, ConverterParameter=Inverse}"> @@ -361,7 +361,7 @@ NavisworksTransport 检测动画页签视图 - 采用与类别设置和分层管 + Visibility="{Binding UseVirtualObject, Converter={StaticResource BoolToVisibilityConverter}}"> @@ -375,11 +375,11 @@ NavisworksTransport 检测动画页签视图 - 采用与类别设置和分层管 Foreground="#FF2B579A" Background="#FFF5F5F5"> - + - + - + private void rbRealObject_Checked(object sender, RoutedEventArgs e) { - borderVirtualVehicle.Visibility = Visibility.Collapsed; + borderVirtualObject.Visibility = Visibility.Collapsed; borderRealObject.Visibility = Visibility.Visible; } @@ -208,21 +208,21 @@ namespace NavisworksTransport.UI.WPF.Views try { // 验证虚拟车辆参数 - if (rbVirtualVehicle.IsChecked == true) + if (rbVirtualObject.IsChecked == true) { - if (!double.TryParse(txtVehicleLength.Text, out var length) || length <= 0) + if (!double.TryParse(txtObjectLength.Text, out var length) || length <= 0) { MessageBox.Show("请输入有效的车辆长度", "提示", MessageBoxButton.OK, MessageBoxImage.Warning); return; } - if (!double.TryParse(txtVehicleWidth.Text, out var width) || width <= 0) + if (!double.TryParse(txtObjectWidth.Text, out var width) || width <= 0) { MessageBox.Show("请输入有效的车辆宽度", "提示", MessageBoxButton.OK, MessageBoxImage.Warning); return; } - if (!double.TryParse(txtVehicleHeight.Text, out var height) || height <= 0) + if (!double.TryParse(txtObjectHeight.Text, out var height) || height <= 0) { MessageBox.Show("请输入有效的车辆高度", "提示", MessageBoxButton.OK, MessageBoxImage.Warning); return; @@ -282,10 +282,10 @@ namespace NavisworksTransport.UI.WPF.Views /// public class PathConfigResult { - public bool IsVirtualVehicle { get; set; } - public double VirtualVehicleLength { get; set; } - public double VirtualVehicleWidth { get; set; } - public double VirtualVehicleHeight { get; set; } + public bool IsVirtualObject { get; set; } + public double VirtualObjectLength { get; set; } + public double VirtualObjectWidth { get; set; } + public double VirtualObjectHeight { get; set; } public string MovingObjectId { get; set; } public string MovingObjectName { get; set; } public List DetectionItems { get; set; } diff --git a/src/UI/WPF/Views/PathEditingView.xaml b/src/UI/WPF/Views/PathEditingView.xaml index 1e727e3..c0bf673 100644 --- a/src/UI/WPF/Views/PathEditingView.xaml +++ b/src/UI/WPF/Views/PathEditingView.xaml @@ -2,7 +2,7 @@ NavisworksTransport 路径编辑页签视图 - 采用与动画控制和分层管理一致的Navisworks 2026风格 功能说明: -1. 自动路径规划:起终点选择、车辆尺寸参数(长宽高)、安全间隙设置 +1. 自动路径规划:起终点选择、运动物体尺寸参数(长宽高)、安全间隙设置 2. 路径列表:新建、删除、重命名路径,显示路径状态 3. 路径编辑:开始编辑、结束编辑、清空路径、路径点管理 4. 路径文件管理:导入、导出全部、导出选中路径操作和状态显示 @@ -65,7 +65,7 @@ NavisworksTransport 路径编辑页签视图 - 采用与动画控制和分层管 - + @@ -80,24 +80,24 @@ NavisworksTransport 路径编辑页签视图 - 采用与动画控制和分层管 - -