From f5d1361146ab57f9276230a96a104fb42ced9ef7 Mon Sep 17 00:00:00 2001 From: tian <11429339@qq.com> Date: Mon, 6 Oct 2025 21:31:09 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=B8=80=E4=B8=AA=E2=80=9C?= =?UTF-8?q?=E6=97=A0=E5=85=B3=E9=A1=B9=E2=80=9D=E7=9A=84=E7=89=A9=E6=B5=81?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=EF=BC=8C=E7=94=A8=E4=BA=8E=E8=BF=87=E6=BB=A4?= =?UTF-8?q?=E5=A6=82=E5=9C=B0=E5=9F=BA=E3=80=81=E5=BB=BA=E7=AD=91=E7=BB=93?= =?UTF-8?q?=E6=9E=84=E7=AD=89=E4=B8=8E=E7=89=A9=E6=B5=81=E6=97=A0=E5=85=B3?= =?UTF-8?q?=E7=9A=84=E6=9E=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .claude/config.json | 3 + .../Properties/CategoryAttributeManager.cs | 7 +- src/PathPlanning/GridMapGenerator.cs | 105 +++++++++++------- 3 files changed, 73 insertions(+), 42 deletions(-) create mode 100644 .claude/config.json diff --git a/.claude/config.json b/.claude/config.json new file mode 100644 index 0000000..b82eeec --- /dev/null +++ b/.claude/config.json @@ -0,0 +1,3 @@ +{ + "primaryApiKey": "api" +} \ No newline at end of file diff --git a/src/Core/Properties/CategoryAttributeManager.cs b/src/Core/Properties/CategoryAttributeManager.cs index a73479e..2e94c11 100644 --- a/src/Core/Properties/CategoryAttributeManager.cs +++ b/src/Core/Properties/CategoryAttributeManager.cs @@ -86,7 +86,12 @@ namespace NavisworksTransport /// /// 停车位 - 可通行,权重0.9 /// - 停车位 = 9 + 停车位 = 9, + + /// + /// 无关项 - 不参与网格生成的大型构件(如地基、结构基础等) + /// + 无关项 = 10 } /// diff --git a/src/PathPlanning/GridMapGenerator.cs b/src/PathPlanning/GridMapGenerator.cs index 495f785..66db9d7 100644 --- a/src/PathPlanning/GridMapGenerator.cs +++ b/src/PathPlanning/GridMapGenerator.cs @@ -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 /// /// 处理门元素,将其设置为可通行网格 /// - private void ProcessDoorElements(GridMap gridMap, ICollection allChannelItems) + private void ProcessDoorElements(GridMap gridMap, ICollection allTraversableItems) { try { // 过滤出门类型的元素 - var doorItems = FilterDoorItems(allChannelItems); + var doorItems = FilterDoorItems(allTraversableItems); LogManager.Info($"【门元素处理】找到 {doorItems.Count} 个门元素"); if (!doorItems.Any()) @@ -920,41 +931,41 @@ namespace NavisworksTransport.PathPlanning } /// - /// 收集通道相关节点 + /// 收集物流项目的相关节点 /// 根据节点类型决定收集策略:几何体节点收集父节点和同级节点,集合节点收集子节点 /// - /// 通道节点列表 + /// 物流项目节点列表 /// 包含所有相关节点的集合 - private HashSet CollectChannelRelatedItems(List channelItems) + private HashSet CollectRelatedItems(List items) { var relatedItems = new HashSet(); - - 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) { 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 /// private Dictionary PostProcessGeometryItems( List geometryItems, - HashSet channelItemsSet, + HashSet traversableItemsSet, GridMap gridMap, - double scanHeightInModelUnits) + double scanHeightInModelUnits, + HashSet 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 /// 通道模型项列表 /// 扫描高度范围(模型单位) /// 通道覆盖信息,包含通道边界 - private void ProcessObstaclesWithBoundingBox(GridMap gridMap, HashSet channelItems, double scanHeightInModelUnits, ChannelCoverage channelCoverage) + /// 无关项集合(不参与网格生成的大型构件) + private void ProcessObstaclesWithBoundingBox(GridMap gridMap, HashSet channelItems, double scanHeightInModelUnits, ChannelCoverage channelCoverage, HashSet irrelevantItemsSet) { try { LogManager.Info("[高性能障碍物处理] 开始处理障碍物 - Search API优化版本"); var startTime = DateTime.Now; - var channelItemsSet = channelItems ?? new HashSet(); + var traversableItemsSet = channelItems ?? new HashSet(); // 阶段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 /// 检查模型项是否是通道项的子项 /// /// 要检查的模型项 - /// 通道项集合 + /// 通道项集合 /// 是否是通道项的子项 - private bool IsChildOfChannelItems(ModelItem item, HashSet channelItemsSet) + private bool IsChildOfChannelItems(ModelItem item, HashSet 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; } }