增加一个“无关项”的物流类型,用于过滤如地基、建筑结构等与物流无关的构件
This commit is contained in:
parent
8cd988279f
commit
f5d1361146
3
.claude/config.json
Normal file
3
.claude/config.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"primaryApiKey": "api"
|
||||
}
|
||||
@ -86,7 +86,12 @@ namespace NavisworksTransport
|
||||
/// <summary>
|
||||
/// 停车位 - 可通行,权重0.9
|
||||
/// </summary>
|
||||
停车位 = 9
|
||||
停车位 = 9,
|
||||
|
||||
/// <summary>
|
||||
/// 无关项 - 不参与网格生成的大型构件(如地基、结构基础等)
|
||||
/// </summary>
|
||||
无关项 = 10
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -111,16 +111,27 @@ namespace NavisworksTransport.PathPlanning
|
||||
LogManager.Info("【生成网格地图】步骤1.5: 智能收集通道相关节点");
|
||||
|
||||
// 直接获取所有可通行的物流模型项
|
||||
var allChannelItems = CategoryAttributeManager.GetAllTraversableLogisticsItems();
|
||||
LogManager.Info($"【生成网格地图】直接获取到 {allChannelItems.Count} 个可通行物流元素");
|
||||
var allTraversableItems = CategoryAttributeManager.GetAllTraversableLogisticsItems();
|
||||
LogManager.Info($"【生成网格地图】直接获取到 {allTraversableItems.Count} 个可通行物流元素");
|
||||
|
||||
// 智能收集可通行模型相关节点(包括父节点、同级节点等)
|
||||
var channelRelatedItems = CollectChannelRelatedItems(allChannelItems.ToList());
|
||||
LogManager.Info($"【生成网格地图】智能收集到 {channelRelatedItems.Count} 个通道相关节点");
|
||||
var traversableRelatedItems = CollectRelatedItems(allTraversableItems.ToList());
|
||||
LogManager.Info($"【生成网格地图】智能收集到 {traversableRelatedItems.Count} 个可通行元素相关节点");
|
||||
|
||||
// 1.6. 批量获取所有"无关项"(不参与网格生成的大型构件)
|
||||
LogManager.Info("【生成网格地图】步骤1.6: 批量获取无关项并收集相关节点");
|
||||
var irrelevantItems = CategoryAttributeManager.GetLogisticsItemsByType(
|
||||
CategoryAttributeManager.LogisticsElementType.无关项);
|
||||
LogManager.Info($"【生成网格地图】直接获取到 {irrelevantItems.Count} 个无关项");
|
||||
|
||||
// 智能收集无关项相关节点(包括子节点等)
|
||||
var irrelevantRelatedItems = CollectRelatedItems(irrelevantItems);
|
||||
LogManager.Info($"【生成网格地图】智能收集到 {irrelevantRelatedItems.Count} 个无关项相关节点(将被排除)");
|
||||
var irrelevantItemsSet = irrelevantRelatedItems; // 使用收集后的完整集合
|
||||
|
||||
// 2. 直接遍历处理障碍物(包围盒检测) - 使用高性能优化版本
|
||||
LogManager.Info("【生成网格地图】步骤2: 高性能包围盒遍历处理障碍物");
|
||||
ProcessObstaclesWithBoundingBox(channelCoverage.GridMap, channelRelatedItems, scanHeightInModelUnits, channelCoverage);
|
||||
ProcessObstaclesWithBoundingBox(channelCoverage.GridMap, traversableRelatedItems, scanHeightInModelUnits, channelCoverage, irrelevantItemsSet);
|
||||
|
||||
LogManager.Info($"【阶段2完成】障碍物处理后网格统计: {channelCoverage.GridMap.GetStatistics()}");
|
||||
|
||||
@ -131,7 +142,7 @@ namespace NavisworksTransport.PathPlanning
|
||||
|
||||
// 2.6. 单独处理门元素,设置为可通行,并设置通行高度
|
||||
LogManager.Info("【生成网格地图】步骤2.6: 处理门元素");
|
||||
ProcessDoorElements(channelCoverage.GridMap, allChannelItems);
|
||||
ProcessDoorElements(channelCoverage.GridMap, allTraversableItems);
|
||||
LogManager.Info($"【阶段2.6完成】门元素处理后网格统计: {channelCoverage.GridMap.GetStatistics()}");
|
||||
|
||||
// 3. 应用车辆尺寸膨胀(如果需要)
|
||||
@ -156,10 +167,10 @@ namespace NavisworksTransport.PathPlanning
|
||||
}
|
||||
|
||||
// 将通道数据设置到GridMap中,供后续PathPlanningManager使用
|
||||
if (channelRelatedItems != null && channelRelatedItems.Any())
|
||||
if (traversableRelatedItems != null && traversableRelatedItems.Any())
|
||||
{
|
||||
channelCoverage.GridMap.ChannelItems = channelRelatedItems.ToList();
|
||||
LogManager.Info($"【生成网格地图】已将 {channelRelatedItems.Count} 个通道数据设置到GridMap中");
|
||||
channelCoverage.GridMap.ChannelItems = traversableRelatedItems.ToList();
|
||||
LogManager.Info($"【生成网格地图】已将 {traversableRelatedItems.Count} 个通道数据设置到GridMap中");
|
||||
}
|
||||
else if (channelCoverage.ChannelItems != null && channelCoverage.ChannelItems.Any())
|
||||
{
|
||||
@ -214,12 +225,12 @@ namespace NavisworksTransport.PathPlanning
|
||||
/// <summary>
|
||||
/// 处理门元素,将其设置为可通行网格
|
||||
/// </summary>
|
||||
private void ProcessDoorElements(GridMap gridMap, ICollection<ModelItem> allChannelItems)
|
||||
private void ProcessDoorElements(GridMap gridMap, ICollection<ModelItem> allTraversableItems)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 过滤出门类型的元素
|
||||
var doorItems = FilterDoorItems(allChannelItems);
|
||||
var doorItems = FilterDoorItems(allTraversableItems);
|
||||
LogManager.Info($"【门元素处理】找到 {doorItems.Count} 个门元素");
|
||||
|
||||
if (!doorItems.Any())
|
||||
@ -920,23 +931,23 @@ namespace NavisworksTransport.PathPlanning
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 收集通道相关节点
|
||||
/// 收集物流项目的相关节点
|
||||
/// 根据节点类型决定收集策略:几何体节点收集父节点和同级节点,集合节点收集子节点
|
||||
/// </summary>
|
||||
/// <param name="channelItems">通道节点列表</param>
|
||||
/// <param name="items">物流项目节点列表</param>
|
||||
/// <returns>包含所有相关节点的集合</returns>
|
||||
private HashSet<ModelItem> CollectChannelRelatedItems(List<ModelItem> channelItems)
|
||||
private HashSet<ModelItem> CollectRelatedItems(List<ModelItem> items)
|
||||
{
|
||||
var relatedItems = new HashSet<ModelItem>();
|
||||
|
||||
foreach (var channelItem in channelItems)
|
||||
foreach (var item in items)
|
||||
{
|
||||
try
|
||||
{
|
||||
LogManager.Info($"[通道收集] 开始处理通道节点: '{channelItem.DisplayName}'");
|
||||
LogManager.Info($"[节点收集] 开始处理节点: '{item.DisplayName}'");
|
||||
|
||||
// 使用 ModelItemAnalysisHelper 的通用方法收集相关节点
|
||||
var itemRelatedNodes = ModelItemAnalysisHelper.CollectRelatedNodes(channelItem);
|
||||
var itemRelatedNodes = ModelItemAnalysisHelper.CollectRelatedNodes(item);
|
||||
|
||||
// 将结果添加到 HashSet 中
|
||||
foreach (var node in itemRelatedNodes)
|
||||
@ -944,17 +955,17 @@ namespace NavisworksTransport.PathPlanning
|
||||
relatedItems.Add(node);
|
||||
}
|
||||
|
||||
LogManager.Info($"[通道收集] 从 '{channelItem.DisplayName}' 收集到 {itemRelatedNodes.Count} 个相关节点");
|
||||
LogManager.Info($"[节点收集] 从 '{item.DisplayName}' 收集到 {itemRelatedNodes.Count} 个相关节点");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Warning($"[通道收集] 处理通道节点 '{channelItem?.DisplayName ?? "NULL"}' 时出错: {ex.Message}");
|
||||
// 出错时至少保证通道本身被添加
|
||||
relatedItems.Add(channelItem);
|
||||
LogManager.Warning($"[节点收集] 处理节点 '{item?.DisplayName ?? "NULL"}' 时出错: {ex.Message}");
|
||||
// 出错时至少保证节点本身被添加
|
||||
relatedItems.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
LogManager.Info($"[通道收集] 共收集到 {relatedItems.Count} 个通道相关节点");
|
||||
LogManager.Info($"[节点收集] 共收集到 {relatedItems.Count} 个相关节点");
|
||||
return relatedItems;
|
||||
}
|
||||
|
||||
@ -1088,9 +1099,10 @@ namespace NavisworksTransport.PathPlanning
|
||||
/// </summary>
|
||||
private Dictionary<ModelItem, ItemProperties> PostProcessGeometryItems(
|
||||
List<ModelItem> geometryItems,
|
||||
HashSet<ModelItem> channelItemsSet,
|
||||
HashSet<ModelItem> traversableItemsSet,
|
||||
GridMap gridMap,
|
||||
double scanHeightInModelUnits)
|
||||
double scanHeightInModelUnits,
|
||||
HashSet<ModelItem> irrelevantItemsSet)
|
||||
{
|
||||
LogManager.Info("[轻量级后处理] 开始处理Search API筛选结果");
|
||||
var startTime = DateTime.Now;
|
||||
@ -1099,6 +1111,7 @@ namespace NavisworksTransport.PathPlanning
|
||||
var totalItems = geometryItems.Count;
|
||||
var apiCalls = 0;
|
||||
var skippedByChannel = 0;
|
||||
var skippedByIrrelevant = 0;
|
||||
var skippedByBoundingBox = 0;
|
||||
|
||||
foreach (var item in geometryItems)
|
||||
@ -1111,7 +1124,7 @@ namespace NavisworksTransport.PathPlanning
|
||||
HasGeometry = true,
|
||||
|
||||
// 快速筛除1:通道相关项目(HashSet查找,极快)
|
||||
IsChannelItem = channelItemsSet.Contains(item)
|
||||
IsChannelItem = traversableItemsSet.Contains(item)
|
||||
};
|
||||
if (properties.IsChannelItem)
|
||||
{
|
||||
@ -1119,13 +1132,21 @@ namespace NavisworksTransport.PathPlanning
|
||||
continue; // 跳过通道项目,不进行昂贵的API调用
|
||||
}
|
||||
|
||||
properties.IsChildOfChannel = IsChildOfChannelItems(item, channelItemsSet);
|
||||
properties.IsChildOfChannel = IsChildOfChannelItems(item, traversableItemsSet);
|
||||
if (properties.IsChildOfChannel)
|
||||
{
|
||||
skippedByChannel++;
|
||||
continue; // 跳过通道子项目
|
||||
}
|
||||
|
||||
// 快速筛除2:无关项(不参与网格生成的大型构件)
|
||||
properties.IsIrrelevantItem = irrelevantItemsSet.Contains(item);
|
||||
if (properties.IsIrrelevantItem)
|
||||
{
|
||||
skippedByIrrelevant++;
|
||||
continue; // 跳过无关项,避免昂贵的BoundingBox API调用
|
||||
}
|
||||
|
||||
// 设为已知值(避免后续筛选中的判断错误)
|
||||
properties.IsContainer = false; // 基于测试验证,几何体项目都不是容器
|
||||
|
||||
@ -1153,7 +1174,7 @@ namespace NavisworksTransport.PathPlanning
|
||||
|
||||
var elapsed = (DateTime.Now - startTime).TotalMilliseconds;
|
||||
LogManager.Info($"[轻量级后处理] 完成,输入 {totalItems} 项,有效结果 {itemCache.Count} 项,API调用 {apiCalls} 次,耗时: {elapsed:F1}ms");
|
||||
LogManager.Info($"[轻量级后处理] 筛除统计 - 通道相关: {skippedByChannel}, 无边界框: {skippedByBoundingBox}");
|
||||
LogManager.Info($"[轻量级后处理] 筛除统计 - 通道相关: {skippedByChannel}, 无关项: {skippedByIrrelevant}, 无边界框: {skippedByBoundingBox}");
|
||||
LogManager.Info("[轻量级后处理] 已移除全局高度预过滤,将在障碍物遍历阶段进行精确高度检查");
|
||||
|
||||
return itemCache;
|
||||
@ -1167,22 +1188,23 @@ namespace NavisworksTransport.PathPlanning
|
||||
/// <param name="channelItems">通道模型项列表</param>
|
||||
/// <param name="scanHeightInModelUnits">扫描高度范围(模型单位)</param>
|
||||
/// <param name="channelCoverage">通道覆盖信息,包含通道边界</param>
|
||||
private void ProcessObstaclesWithBoundingBox(GridMap gridMap, HashSet<ModelItem> channelItems, double scanHeightInModelUnits, ChannelCoverage channelCoverage)
|
||||
/// <param name="irrelevantItemsSet">无关项集合(不参与网格生成的大型构件)</param>
|
||||
private void ProcessObstaclesWithBoundingBox(GridMap gridMap, HashSet<ModelItem> channelItems, double scanHeightInModelUnits, ChannelCoverage channelCoverage, HashSet<ModelItem> irrelevantItemsSet)
|
||||
{
|
||||
try
|
||||
{
|
||||
LogManager.Info("[高性能障碍物处理] 开始处理障碍物 - Search API优化版本");
|
||||
var startTime = DateTime.Now;
|
||||
|
||||
var channelItemsSet = channelItems ?? new HashSet<ModelItem>();
|
||||
var traversableItemsSet = channelItems ?? new HashSet<ModelItem>();
|
||||
|
||||
// 阶段1:Search API预筛选(一次性批量获取几何体项目)
|
||||
var geometryItems = GetGeometryItemsUsingSearchAPI();
|
||||
|
||||
LogManager.Info($"[高性能障碍物处理] 输入统计 - 几何体项目: {geometryItems.Count}, 通道元素: {channelItemsSet.Count}");
|
||||
LogManager.Info($"[高性能障碍物处理] 输入统计 - 几何体项目: {geometryItems.Count}, 通道元素: {traversableItemsSet.Count}");
|
||||
|
||||
// 阶段2:轻量级后处理(只对预筛选结果进行必要的API调用)
|
||||
var itemCache = PostProcessGeometryItems(geometryItems, channelItemsSet, gridMap, scanHeightInModelUnits);
|
||||
var itemCache = PostProcessGeometryItems(geometryItems, traversableItemsSet, gridMap, scanHeightInModelUnits, irrelevantItemsSet);
|
||||
|
||||
// 阶段3:条件过滤(并行数值计算)- 使用50%CPU核心优化
|
||||
LogManager.Info("[高性能障碍物处理] 阶段3: 并行条件过滤");
|
||||
@ -1490,16 +1512,16 @@ namespace NavisworksTransport.PathPlanning
|
||||
/// 检查模型项是否是通道项的子项
|
||||
/// </summary>
|
||||
/// <param name="item">要检查的模型项</param>
|
||||
/// <param name="channelItemsSet">通道项集合</param>
|
||||
/// <param name="traversableItemsSet">通道项集合</param>
|
||||
/// <returns>是否是通道项的子项</returns>
|
||||
private bool IsChildOfChannelItems(ModelItem item, HashSet<ModelItem> channelItemsSet)
|
||||
private bool IsChildOfChannelItems(ModelItem item, HashSet<ModelItem> traversableItemsSet)
|
||||
{
|
||||
try
|
||||
{
|
||||
var parent = item.Parent;
|
||||
while (parent != null)
|
||||
{
|
||||
if (channelItemsSet.Contains(parent))
|
||||
if (traversableItemsSet.Contains(parent))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -1526,6 +1548,7 @@ namespace NavisworksTransport.PathPlanning
|
||||
public BoundingBox3D BoundingBox { get; set; }
|
||||
public bool IsChannelItem { get; set; }
|
||||
public bool IsChildOfChannel { get; set; }
|
||||
public bool IsIrrelevantItem { get; set; }
|
||||
public bool IsInScanHeightRange { get; set; }
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user