From 3b1fae6a1e336696b3c3391b1a9bd33f45d66041 Mon Sep 17 00:00:00 2001 From: tian <11429339@qq.com> Date: Sun, 28 Sep 2025 17:46:16 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E4=BA=86=E8=B7=AF=E5=BE=84?= =?UTF-8?q?=E5=9C=A8=E6=96=9C=E9=9D=A2=EF=BC=88=E5=A6=82=E6=A5=BC=E6=A2=AF?= =?UTF-8?q?=EF=BC=89=E4=B8=8A=E7=9A=84=E8=A7=84=E5=88=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/PathPlanning/AutoPathFinder.cs | 153 +++++--------------- src/PathPlanning/ChannelBasedGridBuilder.cs | 2 +- src/PathPlanning/GridMap.cs | 40 +---- src/PathPlanning/GridMapGenerator.cs | 57 +++----- src/PathPlanning/VerticalScanProcessor.cs | 71 +++++---- 5 files changed, 107 insertions(+), 216 deletions(-) diff --git a/src/PathPlanning/AutoPathFinder.cs b/src/PathPlanning/AutoPathFinder.cs index 301a9a3..1f681d4 100644 --- a/src/PathPlanning/AutoPathFinder.cs +++ b/src/PathPlanning/AutoPathFinder.cs @@ -101,17 +101,14 @@ namespace NavisworksTransport.PathPlanning // 5. 根据网格点通行高度区间对路径点Z坐标调整 var enhancedPath = ApplyGridHeightConstraints(pathResult.PathPoints, gridMap, vehicleHeight); - // 6. 精确高度修正 - var heightCorrectedPath = ApplyPreciseHeightCorrection(enhancedPath, gridMap); - - // 8. 验证路径中所有点的高度约束(特别是门网格) - ValidatePathHeightConstraints(heightCorrectedPath, gridMap, vehicleHeight); + // 6. 验证路径中所有点的高度约束(特别是门网格) + ValidatePathHeightConstraints(enhancedPath, gridMap, vehicleHeight); // 更新PathFindingResult - pathResult.PathPoints = heightCorrectedPath; + pathResult.PathPoints = enhancedPath; pathResult.OriginalEndPoint = originalEnd; - LogManager.Info($"[2.5D路径规划] 路径生成完成,最终包含 {heightCorrectedPath.Count} 个路径点,完成度: {pathResult.CompletionPercentage:F1}%"); + LogManager.Info($"[2.5D路径规划] 路径生成完成,最终包含 {enhancedPath.Count} 个路径点,完成度: {pathResult.CompletionPercentage:F1}%"); // 路径优化 - 去除共线点 pathResult = OptimizePath(pathResult, gridMap); @@ -198,10 +195,10 @@ namespace NavisworksTransport.PathPlanning if (isPassable) { - if (cell.PassableHeights != null && cell.PassableHeights.Any()) + if (cell.PassableHeight.MaxZ > cell.PassableHeight.MinZ) { // vehicleHeight已经是模型单位,直接比较即可 - bool heightOk = cell.PassableHeights.Any(interval => interval.GetSpan() >= vehicleHeight); + bool heightOk = cell.PassableHeight.GetSpan() >= vehicleHeight; if (!heightOk) { heightConstrainedCells++; @@ -209,7 +206,7 @@ namespace NavisworksTransport.PathPlanning // 详细日志:记录被高度约束排除的单元格(仅记录前10个避免日志过多) if (heightConstrainedCells <= 10) { - LogManager.Info($"[A*高度约束] 单元格({x},{y})被高度约束排除:车辆高度{vehicleHeight:F2}模型单位,可用区间:{string.Join(", ", cell.PassableHeights.Select(i => $"{i.MinZ:F2}-{i.MaxZ:F2}(跨度{i.GetSpan():F2})"))}"); + LogManager.Info($"[A*高度约束] 单元格({x},{y})被高度约束排除:车辆高度{vehicleHeight:F2}模型单位,可用区间:{cell.PassableHeight.MinZ:F2}-{cell.PassableHeight.MaxZ:F2}(跨度{cell.PassableHeight.GetSpan():F2})"); } else if (heightConstrainedCells == 11) { @@ -236,9 +233,9 @@ namespace NavisworksTransport.PathPlanning { var rightCell = gridMap.Cells[x + 1, y]; bool rightPassable = rightCell.IsWalkable; - if (rightPassable && rightCell.PassableHeights != null && rightCell.PassableHeights.Any()) + if (rightPassable && rightCell.PassableHeight.MaxZ > rightCell.PassableHeight.MinZ) { - rightPassable = rightCell.PassableHeights.Any(interval => interval.GetSpan() >= vehicleHeight); + rightPassable = rightCell.PassableHeight.GetSpan() >= vehicleHeight; } if (rightPassable) { @@ -253,9 +250,9 @@ namespace NavisworksTransport.PathPlanning { var bottomCell = gridMap.Cells[x, y + 1]; bool bottomPassable = bottomCell.IsWalkable; - if (bottomPassable && bottomCell.PassableHeights != null && bottomCell.PassableHeights.Any()) + if (bottomPassable && bottomCell.PassableHeight.MaxZ > bottomCell.PassableHeight.MinZ) { - bottomPassable = bottomCell.PassableHeights.Any(interval => interval.GetSpan() >= vehicleHeight); + bottomPassable = bottomCell.PassableHeight.GetSpan() >= vehicleHeight; } if (bottomPassable) { @@ -368,10 +365,10 @@ namespace NavisworksTransport.PathPlanning // 检查基本可通行性和高度约束 bool isPassable = cell.IsWalkable; - if (isPassable && cell.PassableHeights != null && cell.PassableHeights.Any()) + if (isPassable && cell.PassableHeight.MaxZ > cell.PassableHeight.MinZ) { // vehicleHeight已经是模型单位,直接比较即可 - bool heightOk = cell.PassableHeights.Any(interval => interval.GetSpan() >= vehicleHeight); + bool heightOk = cell.PassableHeight.GetSpan() >= vehicleHeight; if (!heightOk) { heightConstrainedCells++; @@ -500,10 +497,10 @@ namespace NavisworksTransport.PathPlanning if (!cell.IsWalkable) return false; - if (cell.PassableHeights != null && cell.PassableHeights.Any()) + if (cell.PassableHeight.MaxZ > cell.PassableHeight.MinZ) { // vehicleHeight已经是模型单位,直接比较即可 - return cell.PassableHeights.Any(interval => interval.GetSpan() >= vehicleHeight); + return cell.PassableHeight.GetSpan() >= vehicleHeight; } return false; @@ -1074,80 +1071,6 @@ namespace NavisworksTransport.PathPlanning return turns; } - /// - /// 对最终路径点应用精确高度校正,使路径点贴合通道表面 - /// - /// 重要:使用GetChannelTopHeight确保车辆路径点位于正确的行驶表面 - /// - 楼板类通道:校正到楼板顶面(行驶面)而非底面 - /// - 走廊类通道:校正到可行驶的表面高度 - /// - /// 原始路径点 - /// 网格地图(包含通道信息,通道可能是楼板、走廊等) - /// 高度校正后的路径点 - private List ApplyPreciseHeightCorrection(List path, GridMap gridMap) - { - try - { - LogManager.Info($"[高度校正] 开始对 {path.Count} 个路径点进行精确高度校正"); - - // 如果没有通道数据,直接返回原路径 - if (gridMap.ChannelItems == null || !gridMap.ChannelItems.Any()) - { - LogManager.Info("[高度校正] 无通道数据,跳过高度校正"); - return path; - } - - // 确保高度检测器可用 - if (gridMap.HeightDetector == null) - { - LogManager.Warning("[高度校正] 高度检测器不可用,跳过高度校正"); - return path; - } - - var correctedPath = new List(); - int correctedCount = 0; - - for (int i = 0; i < path.Count; i++) - { - var originalPoint = path[i]; - - try - { - // 🔥 关键修改:使用GetChannelTopHeight获取通道顶面高度,而不是底面高度 - // 因为通道是楼板,车辆应该在楼板顶面行驶 - var preciseHeight = gridMap.HeightDetector.GetChannelTopHeight(originalPoint, gridMap.ChannelItems); - - // 检查高度是否需要校正(容差1cm) - const double heightTolerance = 0.01; // 1cm - if (Math.Abs(originalPoint.Z - preciseHeight) > heightTolerance) - { - var correctedPoint = new Point3D(originalPoint.X, originalPoint.Y, preciseHeight); - correctedPath.Add(correctedPoint); - correctedCount++; - } - else - { - // 高度已经正确,无需校正 - correctedPath.Add(originalPoint); - } - } - catch (Exception ex) - { - // 如果某个点的高度检测失败,使用原始点 - LogManager.Warning($"[高度校正] 点{i}高度校正失败: {ex.Message},使用原始高度"); - correctedPath.Add(originalPoint); - } - } - - LogManager.Info($"[高度校正] 高度校正完成,共校正了 {correctedCount}/{path.Count} 个点"); - return correctedPath; - } - catch (Exception ex) - { - LogManager.Error($"[高度校正] 路径高度校正失败: {ex.Message},返回原始路径"); - return path; - } - } /// /// 修正路径的起点和终点为原始用户指定的坐标,避免网格转换造成的错位 @@ -1232,22 +1155,19 @@ namespace NavisworksTransport.PathPlanning } // 检查高度约束 - if (cell.PassableHeights != null && cell.PassableHeights.Any()) + if (cell.PassableHeight.MaxZ > cell.PassableHeight.MinZ) { - foreach (var interval in cell.PassableHeights) - { - bool spanOk = interval.GetSpan() >= vehicleHeight; - // 将绝对坐标转换为相对于网格底面的坐标 - double relativeZ = point.Z - cell.WorldPosition.Z; - bool containsHeight = interval.Contains(relativeZ); + bool spanOk = cell.PassableHeight.GetSpan() >= vehicleHeight; + // 将绝对坐标转换为相对于网格底面的坐标 + double relativeZ = point.Z - cell.WorldPosition.Z; + bool containsHeight = cell.PassableHeight.Contains(relativeZ); - if (spanOk && containsHeight) - { - return true; - } + if (spanOk && containsHeight) + { + return true; } - LogManager.Warning($"[高度检查] ❌ 所有高度区间都不满足要求"); + LogManager.Warning($"[高度检查] ❌ 高度区间不满足要求"); return false; } @@ -1278,7 +1198,7 @@ namespace NavisworksTransport.PathPlanning { var gridPos = gridMap.WorldToGrid(point); - // 检查网格有效性 + // 检查网格位置有效性 if (!gridMap.IsValidGridPosition(gridPos)) { adjustedPath.Add(point); @@ -1287,13 +1207,18 @@ namespace NavisworksTransport.PathPlanning var cell = gridMap.Cells[gridPos.X, gridPos.Y]; - var bestInterval = cell.PassableHeights - .Where(interval => interval.GetSpan() >= vehicleHeight) - .OrderBy(interval => interval.MinZ) - .FirstOrDefault(); - - var optimalZ = cell.WorldPosition.Z + bestInterval.MinZ; - adjustedPath.Add(new Point3D(point.X, point.Y, optimalZ)); + // 检查单个高度区间是否满足车辆高度要求 + if (cell.PassableHeight.GetSpan() >= vehicleHeight) + { + // 使用高度区间的底部作为最优Z坐标 + var optimalZ = cell.WorldPosition.Z + cell.PassableHeight.MinZ; + adjustedPath.Add(new Point3D(point.X, point.Y, optimalZ)); + } + else + { + // 高度不足,保持原始点 + adjustedPath.Add(point); + } adjustedCount++; } @@ -1600,10 +1525,10 @@ namespace NavisworksTransport.PathPlanning // 检查基本可通行性和高度约束 bool isPassable = cell.IsWalkable; - if (isPassable && cell.PassableHeights != null && cell.PassableHeights.Any()) + if (isPassable && cell.PassableHeight.MaxZ > cell.PassableHeight.MinZ) { // vehicleHeight已经是模型单位,直接比较即可 - bool heightOk = cell.PassableHeights.Any(interval => interval.GetSpan() >= vehicleHeight); + bool heightOk = cell.PassableHeight.GetSpan() >= vehicleHeight; if (!heightOk) { heightConstrainedCells++; diff --git a/src/PathPlanning/ChannelBasedGridBuilder.cs b/src/PathPlanning/ChannelBasedGridBuilder.cs index 922e34b..a0be163 100644 --- a/src/PathPlanning/ChannelBasedGridBuilder.cs +++ b/src/PathPlanning/ChannelBasedGridBuilder.cs @@ -225,7 +225,7 @@ namespace NavisworksTransport.PathPlanning IsWalkable = true, CellType = CategoryAttributeManager.LogisticsElementType.通道, IsInChannel = true, - PassableHeights = new List(), + PassableHeight = new HeightInterval(), ChannelType = ChannelType.Corridor, WorldPosition = new Point3D(worldPos.X, worldPos.Y, gridCenterHeight), RelatedModelItem = null diff --git a/src/PathPlanning/GridMap.cs b/src/PathPlanning/GridMap.cs index a8f0cb8..32105ee 100644 --- a/src/PathPlanning/GridMap.cs +++ b/src/PathPlanning/GridMap.cs @@ -163,7 +163,7 @@ namespace NavisworksTransport.PathPlanning IsWalkable = false, CellType = CategoryAttributeManager.LogisticsElementType.Unknown, // 修改:默认为未知/空洞类型 IsInChannel = false, - PassableHeights = new List(), + PassableHeight = new HeightInterval(), ChannelType = ChannelType.Other, WorldPosition = worldPos }; @@ -256,7 +256,7 @@ namespace NavisworksTransport.PathPlanning IsWalkable = isWalkable, CellType = cellType, IsInChannel = cellType == CategoryAttributeManager.LogisticsElementType.通道, - PassableHeights = new List(), + PassableHeight = new HeightInterval(), ChannelType = cellType == CategoryAttributeManager.LogisticsElementType.通道 ? ChannelType.Corridor : ChannelType.Other, WorldPosition = worldPos }; @@ -277,26 +277,6 @@ namespace NavisworksTransport.PathPlanning Cells[gridPosition.X, gridPosition.Y] = cell; } - - /// - /// 添加可通行高度区间到指定网格单元 - /// - /// 网格坐标 - /// 高度区间 - public void AddPassableHeight(GridPoint2D gridPosition, HeightInterval heightInterval) - { - if (!IsValidGridPosition(gridPosition)) - return; - - var cell = Cells[gridPosition.X, gridPosition.Y]; - if (cell.PassableHeights == null) - { - cell.PassableHeights = new List(); - } - cell.PassableHeights.Add(heightInterval); - Cells[gridPosition.X, gridPosition.Y] = cell; - } - /// /// 检查指定位置在指定高度是否可通行 /// @@ -312,12 +292,8 @@ namespace NavisworksTransport.PathPlanning if (!cell.IsWalkable) return false; - // 如果没有设置高度区间,使用传统的可通行性判断 - if (cell.PassableHeights == null || !cell.PassableHeights.Any()) - return true; - // 检查是否有任何高度区间包含指定高度 - return cell.PassableHeights.Any(interval => interval.Contains(height)); + return (cell.PassableHeight.MaxZ - cell.PassableHeight.MinZ) >= height; } /// @@ -589,7 +565,7 @@ namespace NavisworksTransport.PathPlanning /// /// 可通行高度区间列表 - 支持2.5D路径规划 /// - public List PassableHeights { get; set; } + public HeightInterval PassableHeight { get; set; } /// /// 通道类型 - 用于区分不同类型的通道 @@ -650,7 +626,7 @@ namespace NavisworksTransport.PathPlanning IsWalkable = false, CellType = CategoryAttributeManager.LogisticsElementType.障碍物, IsInChannel = false, - PassableHeights = new List(), + PassableHeight = new HeightInterval(), ChannelType = ChannelType.Other }; cell.Cost = cell.GetCost(); @@ -668,7 +644,7 @@ namespace NavisworksTransport.PathPlanning IsWalkable = true, CellType = CategoryAttributeManager.LogisticsElementType.楼板, IsInChannel = false, - PassableHeights = new List(), + PassableHeight = new HeightInterval(), ChannelType = ChannelType.Other }; cell.Cost = cell.GetCost(); @@ -687,7 +663,7 @@ namespace NavisworksTransport.PathPlanning IsWalkable = isOpen, CellType = CategoryAttributeManager.LogisticsElementType.门, IsInChannel = isOpen, - PassableHeights = new List(), + PassableHeight = new HeightInterval(), ChannelType = ChannelType.Other }; cell.Cost = cell.GetCost(); @@ -706,7 +682,7 @@ namespace NavisworksTransport.PathPlanning IsWalkable = true, CellType = CategoryAttributeManager.LogisticsElementType.通道, IsInChannel = true, - PassableHeights = new List(), + PassableHeight = new HeightInterval(), ChannelType = channelType }; cell.Cost = cell.GetCost(); diff --git a/src/PathPlanning/GridMapGenerator.cs b/src/PathPlanning/GridMapGenerator.cs index b7addde..91170e6 100644 --- a/src/PathPlanning/GridMapGenerator.cs +++ b/src/PathPlanning/GridMapGenerator.cs @@ -298,10 +298,7 @@ namespace NavisworksTransport.PathPlanning // 将门的高度范围存储在PassableHeights中供后续使用(使用相对坐标) if (doorHeight > 0) { - cell.PassableHeights = new List - { - new HeightInterval(0, doorHeight) - }; + cell.PassableHeight = new HeightInterval(0, doorHeight); } // 将修改后的结构体设置回数组 @@ -343,10 +340,7 @@ namespace NavisworksTransport.PathPlanning var cell = gridMap.Cells[x, y]; if (cell.IsWalkable) { - cell.PassableHeights = new List - { - new HeightInterval(0, scanHeightInModelUnits) - }; + cell.PassableHeight = new HeightInterval(0, scanHeightInModelUnits); gridMap.Cells[x, y] = cell; processedCount++; } @@ -461,12 +455,7 @@ namespace NavisworksTransport.PathPlanning /// /// 网格地图 /// 高度区间数据 - /// - /// 将高度区间信息集成到网格地图中 - /// - /// 网格地图 - /// 高度区间数据 - private void IntegrateHeightIntervalsToGrid(GridMap gridMap, Dictionary> heightIntervals) + private void IntegrateHeightIntervalsToGrid(GridMap gridMap, Dictionary heightIntervals) { int updatedCells = 0; int channelCellsWithHeightData = 0; @@ -475,44 +464,39 @@ namespace NavisworksTransport.PathPlanning foreach (var kvp in heightIntervals) { var point = kvp.Key; - var intervals = kvp.Value; - + var interval = kvp.Value; + // 将世界坐标转换为网格坐标 var gridPos = gridMap.WorldToGrid(new Point3D(point.X, point.Y, 0)); int gridX = gridPos.X; int gridY = gridPos.Y; - + // 确保坐标在有效范围内 if (gridX >= 0 && gridX < gridMap.Width && gridY >= 0 && gridY < gridMap.Height) { // 更新网格单元格的高度区间信息 var cell = gridMap.Cells[gridX, gridY]; - - if (cell.PassableHeights == null) - { - cell.PassableHeights = new List(); - } - - cell.PassableHeights.Clear(); - cell.PassableHeights.AddRange(intervals); + + // 直接设置高度区间 + cell.PassableHeight = interval; // 关键修复:只处理通道单元格的高度信息集成 // 非通道单元格不应该通过高度扫描而改变其类型或可通行性 if (cell.CellType == CategoryAttributeManager.LogisticsElementType.通道 && cell.IsInChannel) { channelCellsWithHeightData++; - - if (intervals.Any()) + + if (interval.MaxZ > interval.MinZ) { // 通道区域有足够净空高度,设置为可通行 // 🔥 关键修复:使用SetCell方法正确更新网格统计 var cellPos = new GridPoint2D(gridX, gridY); gridMap.SetCell(cellPos, true, 1.0, CategoryAttributeManager.LogisticsElementType.通道); - + // 设置世界坐标和高度信息 var updatedCell = gridMap.Cells[gridX, gridY]; updatedCell.WorldPosition = point; - updatedCell.PassableHeights = new List(intervals); + updatedCell.PassableHeight = interval; updatedCell.IsInChannel = true; gridMap.Cells[gridX, gridY] = updatedCell; } @@ -521,14 +505,14 @@ namespace NavisworksTransport.PathPlanning // 通道区域但净空高度不足,标记为不可通行但保持通道类型 var cellPos = new GridPoint2D(gridX, gridY); gridMap.SetCell(cellPos, false, double.MaxValue, CategoryAttributeManager.LogisticsElementType.通道); - + // 设置世界坐标和高度信息 var updatedCell = gridMap.Cells[gridX, gridY]; updatedCell.WorldPosition = point; - updatedCell.PassableHeights = new List(intervals); + updatedCell.PassableHeight = interval; updatedCell.IsInChannel = true; gridMap.Cells[gridX, gridY] = updatedCell; - + channelCellsBecomingUnwalkable++; } } @@ -540,7 +524,7 @@ namespace NavisworksTransport.PathPlanning // 仍然更新高度信息,但保持原有状态 cell.WorldPosition = point; - cell.PassableHeights = new List(intervals); + cell.PassableHeight = interval; gridMap.Cells[gridX, gridY] = cell; } updatedCells++; @@ -1259,14 +1243,11 @@ namespace NavisworksTransport.PathPlanning cell.RelatedModelItem = update.Item; // 记录高度信息 - if (cell.PassableHeights == null) - cell.PassableHeights = new List(); - var groundHeight = cell.WorldPosition.Z; - cell.PassableHeights.Add(new HeightInterval( + cell.PassableHeight = new HeightInterval( update.BoundingBox.Min.Z - groundHeight, update.BoundingBox.Max.Z - groundHeight - )); + ); gridMap.Cells[update.X, update.Y] = cell; updatedCells++; diff --git a/src/PathPlanning/VerticalScanProcessor.cs b/src/PathPlanning/VerticalScanProcessor.cs index 62d15d5..aa1549b 100644 --- a/src/PathPlanning/VerticalScanProcessor.cs +++ b/src/PathPlanning/VerticalScanProcessor.cs @@ -280,8 +280,8 @@ namespace NavisworksTransport.PathPlanning /// 网格点列表 /// 扫描高度(从地面向上的距离) /// 车辆高度(用于通行检查) - /// 每个网格点的高度区间列表 - public Dictionary> ParallelScanHeightIntervals( + /// 每个网格点的高度区间 + public Dictionary ParallelScanHeightIntervals( IEnumerable gridPoints, double scanHeight = 20.0, double vehicleHeight = 3.0) @@ -289,7 +289,7 @@ namespace NavisworksTransport.PathPlanning LogManager.Info($"[垂直扫描处理器] 开始并行扫描高度区间,扫描高度: {scanHeight}m, 车辆高度: {vehicleHeight}m"); var startTime = DateTime.Now; - var results = new ConcurrentDictionary>(); + var results = new ConcurrentDictionary(); var pointsList = gridPoints?.ToList() ?? new List(); LogManager.Info($"[垂直扫描处理器] 准备处理{pointsList.Count}个点"); @@ -307,8 +307,8 @@ namespace NavisworksTransport.PathPlanning { if (gridPoint != null) { - var intervals = ScanVerticalLine(gridPoint, scanHeight, vehicleHeight); - results[gridPoint] = intervals ?? new List(); + var interval = ScanVerticalLine(gridPoint, scanHeight, vehicleHeight); + results[gridPoint] = interval; } } catch (OutOfMemoryException) @@ -316,7 +316,7 @@ namespace NavisworksTransport.PathPlanning LogManager.Error($"[垂直扫描处理器] 内存不足,跳过点 {gridPoint}"); if (gridPoint != null) { - results[gridPoint] = new List(); + results[gridPoint] = new HeightInterval(); } throw; // 内存不足需要重新抛出 } @@ -325,7 +325,7 @@ namespace NavisworksTransport.PathPlanning LogManager.Error($"[垂直扫描处理器] 扫描点 {gridPoint} 失败: {ex.Message}"); if (gridPoint != null) { - results[gridPoint] = new List(); + results[gridPoint] = new HeightInterval(); } } }); @@ -342,8 +342,8 @@ namespace NavisworksTransport.PathPlanning { if (gridPoint != null && !results.ContainsKey(gridPoint)) { - var intervals = ScanVerticalLine(gridPoint, scanHeight, vehicleHeight); - results[gridPoint] = intervals ?? new List(); + var interval = ScanVerticalLine(gridPoint, scanHeight, vehicleHeight); + results[gridPoint] = interval; } } catch (Exception serialEx) @@ -351,14 +351,14 @@ namespace NavisworksTransport.PathPlanning LogManager.Error($"[垂直扫描处理器] 串行扫描点 {gridPoint} 也失败: {serialEx.Message}"); if (gridPoint != null) { - results[gridPoint] = new List(); + results[gridPoint] = new HeightInterval(); } } } } var elapsed = (DateTime.Now - startTime).TotalMilliseconds; - var totalIntervals = results.Values.Sum(list => list.Count); + var validIntervals = results.Values.Count(interval => interval.MaxZ > interval.MinZ); // 输出缓存统计信息 if (_cacheHits + _cacheMisses > 0) @@ -367,14 +367,14 @@ namespace NavisworksTransport.PathPlanning LogManager.Info($"[垂直扫描处理器] 缓存统计 - 命中: {_cacheHits}, 未命中: {_cacheMisses}, 命中率: {hitRate:F1}%, 缓存大小: {_candidateCache.Count}"); } - LogManager.Info($"[垂直扫描处理器] 并行扫描完成,耗时: {elapsed:F1}ms, 扫描点: {pointsList.Count}, 总区间: {totalIntervals}"); + LogManager.Info($"[垂直扫描处理器] 并行扫描完成,耗时: {elapsed:F1}ms, 扫描点: {pointsList.Count}, 有效区间: {validIntervals}"); // 清理缓存,为下次扫描做准备 _candidateCache.Clear(); _cacheHits = 0; _cacheMisses = 0; - return new Dictionary>(results); + return new Dictionary(results); } /// @@ -383,8 +383,8 @@ namespace NavisworksTransport.PathPlanning /// 基础点(X,Y坐标) /// 扫描高度 /// 车辆高度 - /// 可通行的高度区间列表 - public List ScanVerticalLine(Point3D basePoint, double scanHeight, double vehicleHeight) + /// 可通行的高度区间 + public HeightInterval ScanVerticalLine(Point3D basePoint, double scanHeight, double vehicleHeight) { // 第一级筛选:邻域筛选 - 获取空间哈希邻域内的候选项 var candidateItems = GetCandidateItemsFromSpatialHash(basePoint); @@ -396,9 +396,9 @@ namespace NavisworksTransport.PathPlanning var intersectionResults = PerformIntersectionTests(heightFilteredItems, basePoint, scanHeight); // 计算可通行区间 - var passableIntervals = CalculatePassableIntervals(intersectionResults, basePoint.Z, scanHeight, vehicleHeight); + var passableInterval = CalculatePassableInterval(intersectionResults, basePoint.Z, scanHeight, vehicleHeight); - return passableIntervals; + return passableInterval; } @@ -625,8 +625,8 @@ namespace NavisworksTransport.PathPlanning /// 基础Z坐标 /// 扫描高度 /// 车辆高度 - /// 可通行区间列表 - private List CalculatePassableIntervals( + /// 可通行区间 + private HeightInterval CalculatePassableInterval( List intersectionResults, double baseZ, double scanHeight, @@ -664,8 +664,8 @@ namespace NavisworksTransport.PathPlanning // 合并重叠的障碍物区间 var mergedObstacles = MergeOverlappingIntervals(obstacles); - // 计算可通行区间 - var passableIntervals = new List(); + // 计算最优可通行区间(取最大的一个) + HeightInterval bestInterval = new HeightInterval(); var scanRange = new HeightInterval(baseZ, baseZ + scanHeight); // 如果没有找到地面,使用基础Z坐标作为默认地面 @@ -674,7 +674,7 @@ namespace NavisworksTransport.PathPlanning floors.Add(new HeightInterval(baseZ - 0.1, baseZ + 0.1)); } - // 对每个潜在的地面,计算其上方的可通行空间 + // 对每个潜在的地面,计算其上方的可通行空间,取最大的 foreach (var floor in floors) { double floorTop = floor.MaxZ; @@ -694,18 +694,21 @@ namespace NavisworksTransport.PathPlanning if (clearHeight >= MIN_PASSABLE_HEIGHT) { var interval = new HeightInterval(floorTop, availableTop); - passableIntervals.Add(interval); + if (interval.MaxZ - interval.MinZ > bestInterval.MaxZ - bestInterval.MinZ) + { + bestInterval = interval; + } } } else { - // 有障碍物,计算障碍物之间的可通行空间 + // 有障碍物,计算障碍物之间的可通行空间,取最大的 double currentBottom = floorTop; - + foreach (var obstacle in conflictingObstacles) { double obstacleBottom = Math.Max(obstacle.MinZ, currentBottom); - + if (obstacleBottom > currentBottom) { double clearHeight = obstacleBottom - currentBottom; @@ -713,13 +716,16 @@ namespace NavisworksTransport.PathPlanning if (clearHeight >= vehicleHeight) { var interval = new HeightInterval(currentBottom, obstacleBottom); - passableIntervals.Add(interval); + if (interval.MaxZ - interval.MinZ > bestInterval.MaxZ - bestInterval.MinZ) + { + bestInterval = interval; + } } } - + currentBottom = Math.Max(currentBottom, obstacle.MaxZ); } - + // 检查最后一个障碍物之后的空间 if (currentBottom < availableTop) { @@ -728,13 +734,16 @@ namespace NavisworksTransport.PathPlanning if (clearHeight >= vehicleHeight) { var interval = new HeightInterval(currentBottom, availableTop); - passableIntervals.Add(interval); + if (interval.MaxZ - interval.MinZ > bestInterval.MaxZ - bestInterval.MinZ) + { + bestInterval = interval; + } } } } } - return passableIntervals; + return bestInterval; } #endregion