用所有通道顶面最小值作为障碍物扫描基准

This commit is contained in:
tian 2025-09-19 18:15:02 +08:00
parent 1b95c37b80
commit 328263e846
3 changed files with 39 additions and 21 deletions

View File

@ -81,14 +81,17 @@ namespace NavisworksTransport.PathPlanning
// 3. 创建网格地图
var gridMap = new GridMap(totalBounds, gridSize);
// 新增:跟踪最小通道顶面高度
double minChannelTopZ = double.MaxValue;
// 4. 为每个通道生成精确投影
var processedChannels = new List<ModelItem>();
foreach (var channel in channelItems)
{
try
{
ProjectChannelToGrid(channel, gridMap);
ProjectChannelToGrid(channel, gridMap, ref minChannelTopZ);
processedChannels.Add(channel);
}
catch (Exception ex)
@ -98,12 +101,14 @@ namespace NavisworksTransport.PathPlanning
}
LogManager.Info($"[通道网格构建器] 成功投影 {processedChannels.Count}/{channelItems.Count} 个通道");
LogManager.Info($"[通道网格构建器] 最低通道顶面高度: {minChannelTopZ:F2}");
return new ChannelCoverage
{
GridMap = gridMap,
ChannelItems = processedChannels,
TotalBounds = totalBounds
TotalBounds = totalBounds,
MinChannelTopZ = minChannelTopZ
};
}
@ -114,7 +119,8 @@ namespace NavisworksTransport.PathPlanning
/// </summary>
/// <param name="channel">通道物品</param>
/// <param name="gridMap">目标网格地图</param>
private void ProjectChannelToGrid(ModelItem channel, GridMap gridMap)
/// <param name="minChannelTopZ">最小通道顶面高度的引用,用于跟踪所有通道中的最低顶面</param>
private void ProjectChannelToGrid(ModelItem channel, GridMap gridMap, ref double minChannelTopZ)
{
LogManager.Info($"[通道网格构建器] 投影通道: {channel.DisplayName}");
@ -156,13 +162,13 @@ namespace NavisworksTransport.PathPlanning
// 根据法向量决定处理方式
if (normal.Z > 0.7) // 朝上的水平面
{
RasterizeTriangleToGrid(gridMap, triangle);
RasterizeTriangleToGrid(gridMap, triangle, ref minChannelTopZ);
processedTriangles++;
}
else if (normal.Z > 0.2) // 可行走的斜面(楼梯、坡道)
{
// 对于斜面,也进行投影,适用于楼梯等倾斜通道
RasterizeTriangleToGrid(gridMap, triangle);
RasterizeTriangleToGrid(gridMap, triangle, ref minChannelTopZ);
processedTriangles++;
}
// 垂直面和朝下的面不投影
@ -210,7 +216,8 @@ namespace NavisworksTransport.PathPlanning
/// </summary>
/// <param name="gridMap">网格地图</param>
/// <param name="triangle">三角形</param>
private void RasterizeTriangleToGrid(GridMap gridMap, Triangle3D triangle)
/// <param name="minChannelTopZ">最小通道顶面高度的引用,用于跟踪所有通道中的最低顶面</param>
private void RasterizeTriangleToGrid(GridMap gridMap, Triangle3D triangle, ref double minChannelTopZ)
{
// 获取三角形的2D投影边界框
var minX = Math.Min(triangle.Point1.X, Math.Min(triangle.Point2.X, triangle.Point3.X));
@ -224,6 +231,9 @@ namespace NavisworksTransport.PathPlanning
// 计算三角形的平均高度作为通道顶面高度
double triangleHeight = (triangle.Point1.Z + triangle.Point2.Z + triangle.Point3.Z) / 3.0;
// 更新最小通道顶面高度
minChannelTopZ = Math.Min(minChannelTopZ, triangleHeight);
// 遍历边界框内的所有网格点
for (int x = minGrid.X; x <= maxGrid.X; x++)
{

View File

@ -843,6 +843,11 @@ namespace NavisworksTransport.PathPlanning
/// </summary>
public BoundingBox3D TotalBounds { get; set; }
/// <summary>
/// 最低通道顶面高度用作障碍物扫描的基准Z值
/// </summary>
public double MinChannelTopZ { get; set; } = double.MaxValue;
/// <summary>
/// 获取统计信息
/// </summary>

View File

@ -89,7 +89,8 @@ namespace NavisworksTransport.PathPlanning
// 2. 直接遍历处理障碍物(包围盒检测) - 使用高性能优化版本
LogManager.Info("【生成网格地图】步骤2: 高性能包围盒遍历处理障碍物");
double scanHeight = vehicleHeight + safetyMargin; // 扫描高度 = 车辆高度 + 安全间隙
ProcessObstaclesWithBoundingBoxOptimized(document, channelCoverage.GridMap, channelRelatedItems, scanHeight);
double minChannelTopZ = channelCoverage.MinChannelTopZ; // 提取最小通道顶面高度
ProcessObstaclesWithBoundingBoxOptimized(document, channelCoverage.GridMap, channelRelatedItems, scanHeight, minChannelTopZ);
LogManager.Info($"【阶段2完成】障碍物处理后网格统计: {channelCoverage.GridMap.GetStatistics()}");
@ -973,10 +974,11 @@ namespace NavisworksTransport.PathPlanning
/// 大幅减少API调用次数
/// </summary>
private Dictionary<ModelItem, ItemProperties> PostProcessGeometryItems(
List<ModelItem> geometryItems,
HashSet<ModelItem> channelItemsSet,
GridMap gridMap,
double scanHeight)
List<ModelItem> geometryItems,
HashSet<ModelItem> channelItemsSet,
GridMap gridMap,
double scanHeight,
double minChannelTopZ)
{
LogManager.Info("[轻量级后处理] 开始处理Search API筛选结果");
var startTime = DateTime.Now;
@ -1036,7 +1038,7 @@ namespace NavisworksTransport.PathPlanning
}
// 快速计算高度范围检查纯数值计算无API调用
properties.IsInScanHeightRange = IsInScanHeightRange(properties.BoundingBox, gridMap, scanHeight);
properties.IsInScanHeightRange = IsInScanHeightRange(properties.BoundingBox, minChannelTopZ, scanHeight);
if (!properties.IsInScanHeightRange)
{
skippedByHeight++;
@ -1067,7 +1069,8 @@ namespace NavisworksTransport.PathPlanning
/// <param name="gridMap">网格地图</param>
/// <param name="channelItems">通道模型项列表</param>
/// <param name="scanHeight">扫描高度范围</param>
private void ProcessObstaclesWithBoundingBoxOptimized(Document document, GridMap gridMap, HashSet<ModelItem> channelItems, double scanHeight)
/// <param name="minChannelTopZ">最小通道顶面高度,用作扫描基准</param>
private void ProcessObstaclesWithBoundingBoxOptimized(Document document, GridMap gridMap, HashSet<ModelItem> channelItems, double scanHeight, double minChannelTopZ)
{
try
{
@ -1082,7 +1085,7 @@ namespace NavisworksTransport.PathPlanning
LogManager.Info($"[高性能障碍物处理] 输入统计 - 几何体项目: {geometryItems.Count}, 通道元素: {channelItemsSet.Count}");
// 阶段2轻量级后处理只对预筛选结果进行必要的API调用
var itemCache = PostProcessGeometryItems(geometryItems, channelItemsSet, gridMap, scanHeight);
var itemCache = PostProcessGeometryItems(geometryItems, channelItemsSet, gridMap, scanHeight, minChannelTopZ);
// 阶段3条件过滤并行数值计算- 使用50%CPU核心优化
LogManager.Info("[高性能障碍物处理] 阶段3: 并行条件过滤");
@ -1351,17 +1354,17 @@ namespace NavisworksTransport.PathPlanning
/// 检查包围盒是否在扫描高度范围内
/// </summary>
/// <param name="bbox">包围盒</param>
/// <param name="gridMap">网格地图</param>
/// <param name="minChannelTopZ">最小通道顶面高度,用作扫描基准</param>
/// <param name="scanHeight">扫描高度范围</param>
/// <returns>是否在高度范围内</returns>
private bool IsInScanHeightRange(BoundingBox3D bbox, GridMap gridMap, double scanHeight)
private bool IsInScanHeightRange(BoundingBox3D bbox, double minChannelTopZ, double scanHeight)
{
try
{
// 使用通道的实际高度范围作为扫描基准
var scanMinZ = gridMap.Bounds.Max.Z; // 通道顶面
var scanMaxZ = gridMap.Bounds.Max.Z + scanHeight; // 从通道顶面向上扫描
// 使用最低通道顶面高度作为扫描基准,避免门高度干扰
var scanMinZ = minChannelTopZ; // 最低通道顶面
var scanMaxZ = minChannelTopZ + scanHeight; // 从最低通道顶面向上扫描
// 检查包围盒的Z范围是否与扫描范围有重叠
return !(bbox.Max.Z < scanMinZ || bbox.Min.Z > scanMaxZ);
}