diff --git a/src/PathPlanning/ChannelBasedGridBuilder.cs b/src/PathPlanning/ChannelBasedGridBuilder.cs index a89f53c..aea6ad7 100644 --- a/src/PathPlanning/ChannelBasedGridBuilder.cs +++ b/src/PathPlanning/ChannelBasedGridBuilder.cs @@ -96,14 +96,67 @@ namespace NavisworksTransport.PathPlanning LogManager.Info($"[通道网格构建器] 成功投影 {processedChannels.Count}/{channelItems.Count} 个通道"); + // 5. 计算可通行网格的Z值范围 + var (walkableMinZ, walkableMaxZ, walkableCount) = CalculateWalkableGridZRange(gridMap); + return new ChannelCoverage { GridMap = gridMap, ChannelItems = processedChannels, - TotalBounds = totalBounds + TotalBounds = totalBounds, + WalkableMinZ = walkableMinZ, + WalkableMaxZ = walkableMaxZ, + WalkableGridCount = walkableCount }; } + /// + /// 计算可通行网格的Z值范围 + /// 遍历所有可通行网格,基于实际WorldPosition.Z坐标计算最小值和最大值 + /// + /// 网格地图 + /// 包含最小Z值、最大Z值和可通行网格数量的元组 + private (double minZ, double maxZ, int walkableCount) CalculateWalkableGridZRange(GridMap gridMap) + { + double minZ = double.MaxValue; + double maxZ = double.MinValue; + int walkableCount = 0; + + LogManager.Info("[通道Z值计算] 开始计算可通行网格Z值范围"); + + for (int x = 0; x < gridMap.Width; x++) + { + for (int y = 0; y < gridMap.Height; y++) + { + var cell = gridMap.Cells[x, y]; + + // 只计算可通行的网格 + if (cell.IsWalkable) + { + walkableCount++; + double cellZ = cell.WorldPosition.Z; + + if (cellZ < minZ) + minZ = cellZ; + if (cellZ > maxZ) + maxZ = cellZ; + } + } + } + + // 如果没有可通行网格,返回默认值 + if (walkableCount == 0) + { + LogManager.Warning("[通道Z值计算] 未找到可通行网格,使用默认Z值范围"); + minZ = 0.0; + maxZ = 0.0; + } + + LogManager.Info($"[通道Z值计算] 计算完成 - 可通行网格: {walkableCount}个, Z范围: [{minZ:F2}, {maxZ:F2}], 高度差: {maxZ - minZ:F2}"); + + return (minZ, maxZ, walkableCount); + } + /// /// 将通道投影到网格 diff --git a/src/PathPlanning/GridMap.cs b/src/PathPlanning/GridMap.cs index 32105ee..fefd986 100644 --- a/src/PathPlanning/GridMap.cs +++ b/src/PathPlanning/GridMap.cs @@ -788,6 +788,21 @@ namespace NavisworksTransport.PathPlanning /// public BoundingBox3D TotalBounds { get; set; } + /// + /// 可通行网格的最小Z坐标(基于实际网格位置) + /// + public double WalkableMinZ { get; set; } = double.MaxValue; + + /// + /// 可通行网格的最大Z坐标(基于实际网格位置) + /// + public double WalkableMaxZ { get; set; } = double.MinValue; + + /// + /// 可通行网格数量 + /// + public int WalkableGridCount { get; set; } = 0; + /// /// 获取统计信息 /// @@ -809,8 +824,12 @@ namespace NavisworksTransport.PathPlanning } } + var zRangeInfo = WalkableGridCount > 0 + ? $", Z范围: [{WalkableMinZ:F2}, {WalkableMaxZ:F2}], 可通行网格: {WalkableGridCount}个" + : ", Z范围: 未计算"; + return $"通道覆盖统计: {ChannelItems.Count} 个通道物品, {channelCellCount} 个通道网格单元, " + - $"网格大小: {GridMap?.Width}x{GridMap?.Height}"; + $"网格大小: {GridMap?.Width}x{GridMap?.Height}{zRangeInfo}"; } } diff --git a/src/PathPlanning/GridMapGenerator.cs b/src/PathPlanning/GridMapGenerator.cs index 30178bb..1bfa7c9 100644 --- a/src/PathPlanning/GridMapGenerator.cs +++ b/src/PathPlanning/GridMapGenerator.cs @@ -57,8 +57,25 @@ namespace NavisworksTransport.PathPlanning { try { - // 生成缓存键 - var cacheKey = GridMapCacheKey.CreateFrom(bounds, cellSize, vehicleRadius, safetyMargin, vehicleHeight); + // 第一步:统一转换所有米制参数为模型单位 + double metersToModelUnitsConversionFactor = UnitsConverter.GetMetersToUnitsConversionFactor(Application.ActiveDocument.Units); + double cellSizeInModelUnits = cellSize * metersToModelUnitsConversionFactor; + double vehicleRadiusInModelUnits = vehicleRadius * metersToModelUnitsConversionFactor; + double safetyMarginInModelUnits = safetyMargin * metersToModelUnitsConversionFactor; + double vehicleHeightInModelUnits = vehicleHeight * metersToModelUnitsConversionFactor; + double scanHeightInModelUnits = vehicleHeightInModelUnits + safetyMarginInModelUnits; // 扫描高度 = 车辆高度 + 安全间隙 + double totalInflationRadiusInModelUnits = vehicleRadiusInModelUnits + safetyMarginInModelUnits; // 膨胀半径 = 车辆半径 + 安全间隙 + + LogManager.Info($"【生成网格地图】参数单位转换完成 (转换系数: {metersToModelUnitsConversionFactor:F2}):"); + LogManager.Info($" 网格大小: {cellSize}米 → {cellSizeInModelUnits:F2}模型单位"); + LogManager.Info($" 车辆半径: {vehicleRadius}米 → {vehicleRadiusInModelUnits:F2}模型单位"); + LogManager.Info($" 安全间隙: {safetyMargin}米 → {safetyMarginInModelUnits:F2}模型单位"); + LogManager.Info($" 车辆高度: {vehicleHeight}米 → {vehicleHeightInModelUnits:F2}模型单位"); + LogManager.Info($" 扫描高度: {scanHeightInModelUnits:F2}模型单位"); + LogManager.Info($" 膨胀半径: {totalInflationRadiusInModelUnits:F2}模型单位"); + + // 生成缓存键(使用转换后的模型单位参数确保一致性) + var cacheKey = GridMapCacheKey.CreateFrom(bounds, cellSizeInModelUnits, vehicleRadiusInModelUnits, safetyMarginInModelUnits, vehicleHeightInModelUnits); // 尝试从缓存获取 var cachedGridMap = GlobalGridMapCache.Instance.Get(cacheKey, 5000); // 预估生成需要5秒 @@ -83,23 +100,6 @@ namespace NavisworksTransport.PathPlanning LogManager.Info($"【生成网格地图】缓存键: {cacheKey}"); var startTime = DateTime.Now; - // 第一步:统一转换所有米制参数为模型单位 - double metersToModelUnitsConversionFactor = UnitsConverter.GetMetersToUnitsConversionFactor(Application.ActiveDocument.Units); - double cellSizeInModelUnits = cellSize * metersToModelUnitsConversionFactor; - double vehicleRadiusInModelUnits = vehicleRadius * metersToModelUnitsConversionFactor; - double safetyMarginInModelUnits = safetyMargin * metersToModelUnitsConversionFactor; - double vehicleHeightInModelUnits = vehicleHeight * metersToModelUnitsConversionFactor; - double scanHeightInModelUnits = vehicleHeightInModelUnits + safetyMarginInModelUnits; // 扫描高度 = 车辆高度 + 安全间隙 - double totalInflationRadiusInModelUnits = vehicleRadiusInModelUnits + safetyMarginInModelUnits; // 膨胀半径 = 车辆半径 + 安全间隙 - - LogManager.Info($"【生成网格地图】参数单位转换完成 (转换系数: {metersToModelUnitsConversionFactor:F2}):"); - LogManager.Info($" 网格大小: {cellSize}米 → {cellSizeInModelUnits:F2}模型单位"); - LogManager.Info($" 车辆半径: {vehicleRadius}米 → {vehicleRadiusInModelUnits:F2}模型单位"); - LogManager.Info($" 安全间隙: {safetyMargin}米 → {safetyMarginInModelUnits:F2}模型单位"); - LogManager.Info($" 车辆高度: {vehicleHeight}米 → {vehicleHeightInModelUnits:F2}模型单位"); - LogManager.Info($" 扫描高度: {scanHeightInModelUnits:F2}模型单位"); - LogManager.Info($" 膨胀半径: {totalInflationRadiusInModelUnits:F2}模型单位"); - // 1. 使用通道构建器构建基础通道覆盖网格 LogManager.Info("【生成网格地图】步骤1: 构建通道覆盖网格"); var channelCoverage = _channelBuilder.BuildChannelCoverage(cellSizeInModelUnits); @@ -1069,13 +1069,14 @@ namespace NavisworksTransport.PathPlanning { try { - var properties = new ItemProperties(); - - // 已知条件:HasGeometry = true(Search API保证) - properties.HasGeometry = true; - - // 快速筛除1:通道相关项目(HashSet查找,极快) - properties.IsChannelItem = channelItemsSet.Contains(item); + var properties = new ItemProperties + { + // 已知条件:HasGeometry = true(Search API保证) + HasGeometry = true, + + // 快速筛除1:通道相关项目(HashSet查找,极快) + IsChannelItem = channelItemsSet.Contains(item) + }; if (properties.IsChannelItem) { skippedByChannel++; @@ -1168,13 +1169,13 @@ namespace NavisworksTransport.PathPlanning var filterElapsed = (DateTime.Now - filterStart).TotalMilliseconds; LogManager.Info($"[高性能障碍物处理] 阶段3完成: 从缓存中筛选出 {validItems.Count} 个有效项,耗时: {filterElapsed:F1}ms"); - // 获取通道高度范围信息 - var channelBounds = channelCoverage.TotalBounds; - var channelMinZ = channelBounds.Min.Z; - var channelMaxZ = channelBounds.Max.Z; - var channelHeightRange = channelMaxZ - channelMinZ; - LogManager.Info($"[高性能障碍物处理] 通道高度信息 - 最低点: {channelMinZ:F2}, 最高点: {channelMaxZ:F2}"); - LogManager.Info($"[高性能障碍物处理] 通道高度范围: {channelHeightRange:F2}, 加车辆高度后扫描范围: [{channelMinZ:F2}, {channelMaxZ + scanHeightInModelUnits:F2}]"); + // 获取可通行网格的实际高度范围信息 + var walkableMinZ = channelCoverage.WalkableMinZ; + var walkableMaxZ = channelCoverage.WalkableMaxZ; + var walkableGridCount = channelCoverage.WalkableGridCount; + var walkableHeightRange = walkableMaxZ - walkableMinZ; + LogManager.Info($"[高性能障碍物处理] 可通行网格高度信息 - 最低点: {walkableMinZ:F2}, 最高点: {walkableMaxZ:F2}"); + LogManager.Info($"[高性能障碍物处理] 可通行网格数量: {walkableGridCount}, 高度范围: {walkableHeightRange:F2}, 加车辆高度后扫描范围: [{walkableMinZ:F2}, {walkableMaxZ + scanHeightInModelUnits:F2}]"); // 阶段4:网格覆盖计算(并行几何计算)- 使用50%CPU核心优化 + 基于通道的精确高度检查 LogManager.Info("[高性能障碍物处理] 阶段4: 并行网格覆盖计算 + 基于通道高度的精确高度检查"); @@ -1197,10 +1198,10 @@ namespace NavisworksTransport.PathPlanning var centerCell = gridMap.Cells[centerGridPos.X, centerGridPos.Y]; - // 使用通道高度范围计算扫描范围 - // 扫描范围:从通道最低点开始,到通道最高点+车辆高度+安全间隙 - var scanMin = channelMinZ; - var scanMax = channelMaxZ + scanHeightInModelUnits; + // 使用可通行网格高度范围计算扫描范围 + // 扫描范围:从可通行网格最低点开始,到可通行网格最高点+车辆高度+安全间隙 + var scanMin = walkableMinZ; + var scanMax = walkableMaxZ + scanHeightInModelUnits; // 只有与该网格高度范围重叠的几何体才进入处理 bool isInRange = !(bbox.Max.Z <= scanMin || bbox.Min.Z > scanMax);