修改一个网格生成时的单位转换bug

This commit is contained in:
tian 2025-09-20 11:06:13 +08:00
parent 328263e846
commit 8c8ce89978

View File

@ -62,11 +62,23 @@ namespace NavisworksTransport.PathPlanning
{
LogManager.Info("【生成网格地图】开始生成网格地图");
var startTime = DateTime.Now;
// 重要:将米制网格大小转换为模型单位
// 第一步:统一转换所有米制参数为模型单位
double metersToModelUnitsConversionFactor = UnitsConverter.GetMetersToUnitsConversionFactor(Application.ActiveDocument.Units);
double cellSizeInModelUnits = cellSize * metersToModelUnitsConversionFactor;
LogManager.Info($"【生成网格地图】网格大小单位转换: {cellSize}米 → {cellSizeInModelUnits:F2}模型单位 (转换系数: {metersToModelUnitsConversionFactor:F2})");
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: 构建通道覆盖网格");
@ -88,15 +100,14 @@ namespace NavisworksTransport.PathPlanning
// 2. 直接遍历处理障碍物(包围盒检测) - 使用高性能优化版本
LogManager.Info("【生成网格地图】步骤2: 高性能包围盒遍历处理障碍物");
double scanHeight = vehicleHeight + safetyMargin; // 扫描高度 = 车辆高度 + 安全间隙
double minChannelTopZ = channelCoverage.MinChannelTopZ; // 提取最小通道顶面高度
ProcessObstaclesWithBoundingBoxOptimized(document, channelCoverage.GridMap, channelRelatedItems, scanHeight, minChannelTopZ);
double minChannelTopZ = channelCoverage.MinChannelTopZ; // 提取最小通道顶面高度(模型单位)
ProcessObstaclesWithBoundingBoxOptimized(document, channelCoverage.GridMap, channelRelatedItems, scanHeightInModelUnits, minChannelTopZ);
LogManager.Info($"【阶段2完成】障碍物处理后网格统计: {channelCoverage.GridMap.GetStatistics()}");
// 2.5. 为所有可通行网格设置PassableHeights确保高度约束检查
LogManager.Info("【生成网格地图】步骤2.5: 为可通行网格设置高度约束");
SetChannelPassableHeights(channelCoverage.GridMap, scanHeight);
SetChannelPassableHeights(channelCoverage.GridMap, scanHeightInModelUnits);
LogManager.Info($"【阶段2.5完成】高度约束设置后网格统计: {channelCoverage.GridMap.GetStatistics()}");
// 2.6. 单独处理门元素,设置为可通行,并设置通行高度
@ -108,10 +119,8 @@ namespace NavisworksTransport.PathPlanning
if (vehicleRadius > 0 || safetyMargin > 0)
{
LogManager.Info("【生成网格地图】步骤3: 应用车辆膨胀");
double metersToModelUnits = UnitsConverter.GetMetersToUnitsConversionFactor(Application.ActiveDocument.Units);
double totalInflationRadius = (vehicleRadius + safetyMargin) * metersToModelUnits;
ApplyVehicleInflation(channelCoverage.GridMap, totalInflationRadius);
LogManager.Info($"【生成网格地图】车辆膨胀完成,膨胀半径: {totalInflationRadius:F2}模型单位");
ApplyVehicleInflation(channelCoverage.GridMap, totalInflationRadiusInModelUnits);
LogManager.Info($"【生成网格地图】车辆膨胀完成,膨胀半径: {totalInflationRadiusInModelUnits:F2}模型单位");
LogManager.Info($"【阶段3完成】车辆膨胀后网格统计: {channelCoverage.GridMap.GetStatistics()}");
}
@ -195,7 +204,7 @@ namespace NavisworksTransport.PathPlanning
// 获取门的限高属性
string heightLimitStr = CategoryAttributeManager.GetLogisticsPropertyValue(doorItem, CategoryAttributeManager.LogisticsProperties.HEIGHT_LIMIT);
double configuredHeight = CategoryAttributeManager.ParseLogisticsLimitValue(heightLimitStr, "限高");
double configuredHeight = CategoryAttributeManager.ParseLogisticsLimitValue(heightLimitStr, "限高");
// 计算门的实际物理高度
double actualDoorHeight = bbox.Max.Z - bbox.Min.Z;
@ -270,14 +279,10 @@ namespace NavisworksTransport.PathPlanning
/// 为所有可通行网格设置PassableHeights确保高度约束检查
/// </summary>
/// <param name="gridMap">网格地图</param>
/// <param name="scanHeight">扫描高度(车辆高度+安全间隙</param>
private void SetChannelPassableHeights(GridMap gridMap, double scanHeight)
/// <param name="scanHeightInModelUnits">扫描高度(模型单位</param>
private void SetChannelPassableHeights(GridMap gridMap, double scanHeightInModelUnits)
{
// scanHeight是米需要转换为模型单位
double metersToModelUnits = UnitsConverter.GetMetersToUnitsConversionFactor(Application.ActiveDocument.Units);
double scanHeightInModelUnits = scanHeight * metersToModelUnits;
LogManager.Info($"【高度约束设置】开始为所有可通行网格设置高度约束,扫描高度: {scanHeight:F2}米 ({scanHeightInModelUnits:F2}模型单位)");
LogManager.Info($"【高度约束设置】开始为所有可通行网格设置高度约束,扫描高度: {scanHeightInModelUnits:F2}模型单位");
int processedCount = 0;
for (int x = 0; x < gridMap.Width; x++)
@ -563,17 +568,17 @@ namespace NavisworksTransport.PathPlanning
/// 在障碍物周围扩展不可通行区域,考虑车辆尺寸
/// </summary>
/// <param name="gridMap">网格地图</param>
/// <param name="vehicleRadius">车辆半径</param>
public void ApplyVehicleInflation(GridMap gridMap, double vehicleRadius)
/// <param name="vehicleRadiusInModelUnits">车辆半径(模型单位)</param>
private void ApplyVehicleInflation(GridMap gridMap, double vehicleRadiusInModelUnits)
{
if (vehicleRadius <= 0) return;
if (vehicleRadiusInModelUnits <= 0) return;
try
{
{
// 计算膨胀半径(网格单元格数)
int inflationRadius = (int)Math.Ceiling(vehicleRadius / gridMap.CellSize);
int inflationRadius = (int)Math.Ceiling(vehicleRadiusInModelUnits / gridMap.CellSize);
LogManager.Info($"[高效膨胀] 膨胀半径: {inflationRadius}个网格单元");
// 使用高效的距离变换算法
ApplyVehicleInflationOptimized(gridMap, inflationRadius);
}
@ -977,7 +982,7 @@ namespace NavisworksTransport.PathPlanning
List<ModelItem> geometryItems,
HashSet<ModelItem> channelItemsSet,
GridMap gridMap,
double scanHeight,
double scanHeightInModelUnits,
double minChannelTopZ)
{
LogManager.Info("[轻量级后处理] 开始处理Search API筛选结果");
@ -1038,7 +1043,7 @@ namespace NavisworksTransport.PathPlanning
}
// 快速计算高度范围检查纯数值计算无API调用
properties.IsInScanHeightRange = IsInScanHeightRange(properties.BoundingBox, minChannelTopZ, scanHeight);
properties.IsInScanHeightRange = IsInScanHeightRange(properties.BoundingBox, minChannelTopZ, scanHeightInModelUnits);
if (!properties.IsInScanHeightRange)
{
skippedByHeight++;
@ -1068,9 +1073,9 @@ namespace NavisworksTransport.PathPlanning
/// <param name="document">Navisworks文档</param>
/// <param name="gridMap">网格地图</param>
/// <param name="channelItems">通道模型项列表</param>
/// <param name="scanHeight">扫描高度范围</param>
/// <param name="scanHeightInModelUnits">扫描高度范围(模型单位)</param>
/// <param name="minChannelTopZ">最小通道顶面高度,用作扫描基准</param>
private void ProcessObstaclesWithBoundingBoxOptimized(Document document, GridMap gridMap, HashSet<ModelItem> channelItems, double scanHeight, double minChannelTopZ)
private void ProcessObstaclesWithBoundingBoxOptimized(Document document, GridMap gridMap, HashSet<ModelItem> channelItems, double scanHeightInModelUnits, double minChannelTopZ)
{
try
{
@ -1085,7 +1090,7 @@ namespace NavisworksTransport.PathPlanning
LogManager.Info($"[高性能障碍物处理] 输入统计 - 几何体项目: {geometryItems.Count}, 通道元素: {channelItemsSet.Count}");
// 阶段2轻量级后处理只对预筛选结果进行必要的API调用
var itemCache = PostProcessGeometryItems(geometryItems, channelItemsSet, gridMap, scanHeight, minChannelTopZ);
var itemCache = PostProcessGeometryItems(geometryItems, channelItemsSet, gridMap, scanHeightInModelUnits, minChannelTopZ);
// 阶段3条件过滤并行数值计算- 使用50%CPU核心优化
LogManager.Info("[高性能障碍物处理] 阶段3: 并行条件过滤");
@ -1354,16 +1359,16 @@ namespace NavisworksTransport.PathPlanning
/// 检查包围盒是否在扫描高度范围内
/// </summary>
/// <param name="bbox">包围盒</param>
/// <param name="minChannelTopZ">最小通道顶面高度,用作扫描基准</param>
/// <param name="scanHeight">扫描高度范围</param>
/// <param name="minChannelTopZ">最小通道顶面高度,用作扫描基准(模型单位)</param>
/// <param name="scanHeightInModelUnits">扫描高度范围(模型单位)</param>
/// <returns>是否在高度范围内</returns>
private bool IsInScanHeightRange(BoundingBox3D bbox, double minChannelTopZ, double scanHeight)
private bool IsInScanHeightRange(BoundingBox3D bbox, double minChannelTopZ, double scanHeightInModelUnits)
{
try
{
// 使用最低通道顶面高度作为扫描基准,避免门高度干扰
var scanMinZ = minChannelTopZ; // 最低通道顶面
var scanMaxZ = minChannelTopZ + scanHeight; // 从最低通道顶面向上扫描
var scanMinZ = minChannelTopZ; // 最低通道顶面(模型单位)
var scanMaxZ = minChannelTopZ + scanHeightInModelUnits; // 从最低通道顶面向上扫描(模型单位)
// 检查包围盒的Z范围是否与扫描范围有重叠
return !(bbox.Max.Z < scanMinZ || bbox.Min.Z > scanMaxZ);