diff --git a/CLAUDE.md b/CLAUDE.md
index 02d0d3d..7223d14 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -186,3 +186,4 @@ public class PathClickToolPlugin : ToolPlugin { }
- **Hot reload**: Restart Navisworks required after compilation to load new plugin version
- **Debugging**: Use LogManager for centralized logging and the built-in log viewer dialog for log analysis
- **2026 Features**: Test advanced animation capabilities, enhanced collision detection, and improved model handling
+- 在编码中,不要用回退或向后兼容的思路和步骤
\ No newline at end of file
diff --git a/src/PathPlanning/GridMapGenerator.cs b/src/PathPlanning/GridMapGenerator.cs
index 2912486..a6b9337 100644
--- a/src/PathPlanning/GridMapGenerator.cs
+++ b/src/PathPlanning/GridMapGenerator.cs
@@ -236,10 +236,10 @@ namespace NavisworksTransport.PathPlanning
var channelRelatedItems = CollectChannelRelatedItems(allChannelItems.ToList());
LogManager.Info($"[包围盒2.5D模式] 智能收集到 {channelRelatedItems.Count} 个通道相关节点");
- // 2. 直接遍历处理障碍物(包围盒检测)
- LogManager.Info("[包围盒2.5D模式] 步骤2: 包围盒遍历处理障碍物");
+ // 2. 直接遍历处理障碍物(包围盒检测) - 使用高性能优化版本
+ LogManager.Info("[包围盒2.5D模式] 步骤2: 高性能包围盒遍历处理障碍物");
double scanHeight = vehicleHeight + safetyMargin; // 扫描高度 = 车辆高度 + 安全间隙
- ProcessObstaclesWithBoundingBox(document, channelCoverage.GridMap, channelRelatedItems, scanHeight);
+ ProcessObstaclesWithBoundingBoxOptimized(document, channelCoverage.GridMap, channelRelatedItems, scanHeight);
LogManager.Info($"[阶段2完成] 障碍物处理后网格统计: {channelCoverage.GridMap.GetStatistics()}");
@@ -1087,7 +1087,361 @@ namespace NavisworksTransport.PathPlanning
///
- /// 使用包围盒遍历方式处理障碍物(优化版)
+ /// 数据预处理:提取所有模型项的属性到缓存(单线程API访问)
+ ///
+ /// 所有模型项
+ /// 通道项集合
+ /// 网格地图
+ /// 扫描高度
+ /// 模型项属性缓存
+ private Dictionary PreprocessItemProperties(
+ List allItems,
+ HashSet channelItemsSet,
+ GridMap gridMap,
+ double scanHeight)
+ {
+ LogManager.Info("[数据预处理] 开始提取模型项属性");
+ var startTime = DateTime.Now;
+ var itemCache = new Dictionary();
+
+ var apiCalls = 0;
+ foreach (var item in allItems)
+ {
+ try
+ {
+ var properties = new ItemProperties();
+
+ // API调用1: HasGeometry
+ properties.HasGeometry = item.HasGeometry;
+ apiCalls++;
+
+ // API调用2: Children.Any()
+ properties.IsContainer = item.Children?.Any() ?? false;
+ apiCalls++;
+
+ // API调用3: BoundingBox()
+ properties.BoundingBox = item.BoundingBox();
+ apiCalls++;
+
+ // 通道关系检查(HashSet查找,相对较快)
+ properties.IsChannelItem = channelItemsSet.Contains(item);
+ properties.IsChildOfChannel = !properties.IsChannelItem && IsChildOfChannelItems(item, channelItemsSet);
+
+ // 高度范围检查(纯数值计算)
+ if (properties.BoundingBox != null)
+ {
+ properties.IsInScanHeightRange = IsInScanHeightRange(properties.BoundingBox, gridMap, scanHeight);
+ }
+
+ itemCache[item] = properties;
+ }
+ catch (Exception ex)
+ {
+ LogManager.Debug($"[数据预处理] 处理模型项失败: {item?.DisplayName ?? "NULL"}, {ex.Message}");
+ }
+ }
+
+ var elapsed = (DateTime.Now - startTime).TotalMilliseconds;
+ LogManager.Info($"[数据预处理] 完成,处理 {allItems.Count} 个模型项,执行 {apiCalls} 次API调用,耗时: {elapsed:F1}ms");
+
+ return itemCache;
+ }
+
+ ///
+ /// 使用Search API一次性获取所有有几何体的模型项
+ /// 这比逐项调用HasGeometry快得多
+ ///
+ ///
+ /// 使用Search API + LINQ混合优化获取目标模型项
+ /// Search API预筛选 + LINQ精细过滤,最大化性能提升
+ ///
+ ///
+ /// 使用Search API + LINQ混合优化获取目标模型项
+ /// Search API预筛选 + LINQ精细过滤,最大化性能提升
+ ///
+ ///
+ /// 使用Search API + LINQ混合优化获取目标模型项
+ /// Search API预筛选 + LINQ精细过滤,最大化性能提升
+ ///
+ ///
+ /// 使用Search API + LINQ混合优化获取目标模型项
+ /// Search API预筛选 + LINQ精细过滤,最大化性能提升
+ ///
+ private List GetGeometryItemsUsingSearchAPI(Document document)
+ {
+ try
+ {
+ LogManager.Info("[Search API优化] 开始批量获取几何体项目");
+ var startTime = DateTime.Now;
+
+ // 统计模型总数
+ var totalModelItems = document.Models.RootItemDescendantsAndSelf.Count();
+ LogManager.Info($"[Search API优化] 模型总数统计: {totalModelItems} 个模型项");
+
+ var search = new Search();
+
+ // Search API阶段:批量筛选基础条件
+ search.SearchConditions.Add(
+ SearchCondition.HasCategoryByName(PropertyCategoryNames.Geometry));
+
+ search.Selection.SelectAll();
+ search.Locations = SearchLocations.DescendantsAndSelf;
+
+ // 一次性获取所有有几何体的项目
+ var geometryItems = search.FindAll(document, false);
+
+ var searchElapsed = (DateTime.Now - startTime).TotalMilliseconds;
+ var filteredByGeometry = totalModelItems - geometryItems.Count();
+ var geometryFilterRatio = (double)filteredByGeometry / totalModelItems;
+
+ LogManager.Info($"[Search API优化] Search API阶段完成: 获取 {geometryItems.Count()} 个几何体项目,耗时: {searchElapsed:F1}ms");
+ LogManager.Info($"[Search API优化] 几何体筛选效果: 过滤掉 {filteredByGeometry} 个无几何体项目,筛选率: {geometryFilterRatio:P1}");
+
+ // 🔥 关键优化:直接返回Search API结果,移除所有昂贵的LINQ统计调用
+ // 基于多模型测试验证,LINQ筛选条件(IsCollection, IsComposite, Children.Any)都返回0项
+ var filteredItems = geometryItems.ToList();
+
+ var totalElapsed = (DateTime.Now - startTime).TotalMilliseconds;
+ var totalFilteredCount = totalModelItems - filteredItems.Count;
+ var totalFilterRatio = (double)totalFilteredCount / totalModelItems;
+
+ LogManager.Info($"[Search API优化] 优化完成,总耗时: {totalElapsed:F1}ms");
+ LogManager.Info($"[Search API优化] 优化效果: 总模型项 {totalModelItems} → 几何体项目 {filteredItems.Count}");
+ LogManager.Info($"[Search API优化] 总优化率: 减少 {totalFilteredCount} 项 ({totalFilterRatio:P1})");
+
+ return filteredItems;
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error($"[Search API优化] 筛选失败: {ex.Message}");
+ throw;
+ }
+ }
+
+ ///
+ /// 轻量级后处理:只对Search API预筛选的几何体项目进行必要的属性提取
+ /// 大幅减少API调用次数
+ ///
+ ///
+ /// 轻量级后处理:只对Search API预筛选的几何体项目进行必要的属性提取
+ /// 大幅减少API调用次数
+ ///
+ private Dictionary PostProcessGeometryItems(
+ List geometryItems,
+ HashSet channelItemsSet,
+ GridMap gridMap,
+ double scanHeight)
+ {
+ LogManager.Info("[轻量级后处理] 开始处理Search API筛选结果");
+ var startTime = DateTime.Now;
+ var itemCache = new Dictionary();
+
+ var totalItems = geometryItems.Count;
+ var apiCalls = 0;
+ var skippedByChannel = 0;
+ var skippedByBoundingBox = 0;
+ var skippedByHeight = 0;
+
+ foreach (var item in geometryItems)
+ {
+ try
+ {
+ var properties = new ItemProperties();
+
+ // 已知条件:HasGeometry = true(Search API保证)
+ properties.HasGeometry = true;
+
+ // 快速筛除1:通道相关项目(HashSet查找,极快)
+ properties.IsChannelItem = channelItemsSet.Contains(item);
+ if (properties.IsChannelItem)
+ {
+ skippedByChannel++;
+ continue; // 跳过通道项目,不进行昂贵的API调用
+ }
+
+ properties.IsChildOfChannel = IsChildOfChannelItems(item, channelItemsSet);
+ if (properties.IsChildOfChannel)
+ {
+ skippedByChannel++;
+ continue; // 跳过通道子项目
+ }
+
+ // 移除容器检查:基于4个模型测试验证,所有几何体项目的容器检查结果都是0
+ // 注释:原有的容器检查代码
+ // API调用1: Children.Any() - 检查是否为容器
+ // properties.IsContainer = item.Children?.Any() ?? false;
+ // apiCalls++;
+ // if (properties.IsContainer) {
+ // skippedByContainer++;
+ // continue; // 跳过容器项目
+ // }
+
+ // 设为已知值(避免后续筛选中的判断错误)
+ properties.IsContainer = false; // 基于测试验证,几何体项目都不是容器
+
+ // API调用1: BoundingBox() - 获取边界框(唯一保留的API调用)
+ properties.BoundingBox = item.BoundingBox();
+ apiCalls++;
+
+ if (properties.BoundingBox == null)
+ {
+ skippedByBoundingBox++;
+ continue; // 跳过无边界框项目
+ }
+
+ // 快速计算:高度范围检查(纯数值计算,无API调用)
+ properties.IsInScanHeightRange = IsInScanHeightRange(properties.BoundingBox, gridMap, scanHeight);
+ if (!properties.IsInScanHeightRange)
+ {
+ skippedByHeight++;
+ continue; // 跳过高度范围外项目
+ }
+
+ // 只有通过所有筛选的项目才加入结果
+ itemCache[item] = properties;
+ }
+ catch (Exception ex)
+ {
+ LogManager.Debug($"[轻量级后处理] 处理模型项失败: {item?.DisplayName ?? "NULL"}, {ex.Message}");
+ }
+ }
+
+ var elapsed = (DateTime.Now - startTime).TotalMilliseconds;
+ LogManager.Info($"[轻量级后处理] 完成,输入 {totalItems} 项,有效结果 {itemCache.Count} 项,API调用 {apiCalls} 次,耗时: {elapsed:F1}ms");
+ LogManager.Info($"[轻量级后处理] 筛除统计 - 通道相关: {skippedByChannel}, 容器: 0 (已优化移除), 无边界框: {skippedByBoundingBox}, 高度范围外: {skippedByHeight}");
+ LogManager.Info($"[性能优化] 移除无效容器检查,每个几何体项目节省1次API调用");
+
+ return itemCache;
+ }
+
+ ///
+ /// 使用包围盒遍历方式处理障碍物(高性能优化版)
+ /// 分离API访问和数值计算,利用并行处理加速纯计算部分
+ ///
+ /// Navisworks文档
+ /// 网格地图
+ /// 通道模型项列表
+ /// 扫描高度范围
+ private void ProcessObstaclesWithBoundingBoxOptimized(Document document, GridMap gridMap, HashSet channelItems, double scanHeight)
+ {
+ try
+ {
+ LogManager.Info("[高性能障碍物处理] 开始处理障碍物 - Search API优化版本");
+ var startTime = DateTime.Now;
+
+ var channelItemsSet = channelItems ?? new HashSet();
+
+ // 阶段1:Search API预筛选(一次性批量获取几何体项目)
+ var geometryItems = GetGeometryItemsUsingSearchAPI(document);
+
+ LogManager.Info($"[高性能障碍物处理] 输入统计 - 几何体项目: {geometryItems.Count}, 通道元素: {channelItemsSet.Count}");
+
+ // 阶段2:轻量级后处理(只对预筛选结果进行必要的API调用)
+ var itemCache = PostProcessGeometryItems(geometryItems, channelItemsSet, gridMap, scanHeight);
+
+ // 阶段3:条件过滤(并行数值计算)- 使用50%CPU核心优化
+ LogManager.Info("[高性能障碍物处理] 阶段3: 并行条件过滤");
+ var filterStart = DateTime.Now;
+
+ // 🔥 性能优化:限制并行度为CPU核心数的50%,避免过度并行化
+ var optimalParallelism = Math.Max(1, Environment.ProcessorCount / 2);
+ LogManager.Info($"[并行优化] CPU核心: {Environment.ProcessorCount}, 使用并行度: {optimalParallelism}");
+
+ var validItems = itemCache.AsParallel()
+ .WithDegreeOfParallelism(optimalParallelism)
+ .Where(kvp => kvp.Value.HasGeometry &&
+ !kvp.Value.IsContainer &&
+ !kvp.Value.IsChannelItem &&
+ !kvp.Value.IsChildOfChannel &&
+ kvp.Value.BoundingBox != null &&
+ kvp.Value.IsInScanHeightRange)
+ .ToList();
+
+ var filterElapsed = (DateTime.Now - filterStart).TotalMilliseconds;
+ LogManager.Info($"[高性能障碍物处理] 阶段3完成: 从缓存中筛选出 {validItems.Count} 个有效项,耗时: {filterElapsed:F1}ms");
+
+ // 阶段4:网格覆盖计算(并行几何计算)- 使用50%CPU核心优化
+ LogManager.Info("[高性能障碍物处理] 阶段4: 并行网格覆盖计算");
+ var gridCalcStart = DateTime.Now;
+
+ var gridUpdates = validItems.AsParallel()
+ .WithDegreeOfParallelism(optimalParallelism)
+ .SelectMany(kvp =>
+ {
+ var coveredCells = CalculateBoundingBoxGridCoverage(kvp.Value.BoundingBox, gridMap);
+ return coveredCells.Select(cell => new GridUpdate
+ {
+ Item = kvp.Key,
+ X = cell.x,
+ Y = cell.y,
+ BoundingBox = kvp.Value.BoundingBox
+ });
+ })
+ .ToList();
+
+ var gridCalcElapsed = (DateTime.Now - gridCalcStart).TotalMilliseconds;
+ LogManager.Info($"[高性能障碍物处理] 阶段4完成: 生成 {gridUpdates.Count} 个网格更新操作,耗时: {gridCalcElapsed:F1}ms");
+
+ // 阶段5:网格状态更新(单线程写入)
+ LogManager.Info("[高性能障碍物处理] 阶段5: 单线程网格状态更新");
+ var updateStart = DateTime.Now;
+
+ var updatedCells = 0;
+ var obstacleItems = 0;
+
+ foreach (var update in gridUpdates)
+ {
+ var cell = gridMap.Cells[update.X, update.Y];
+
+ // 只更新通道网格,跳过已是障碍物的网格
+ if (cell.CellType == CategoryAttributeManager.LogisticsElementType.通道 && cell.IsInChannel)
+ {
+ // 标记为障碍物
+ cell.IsWalkable = false;
+ cell.CellType = CategoryAttributeManager.LogisticsElementType.障碍物;
+ cell.Cost = double.MaxValue;
+ cell.IsInChannel = false;
+ cell.RelatedModelItem = update.Item;
+
+ // 记录高度信息
+ if (cell.PassableHeights == null)
+ cell.PassableHeights = new List();
+
+ var groundHeight = cell.WorldPosition.Z;
+ cell.PassableHeights.Add(new HeightInterval(
+ update.BoundingBox.Min.Z - groundHeight,
+ update.BoundingBox.Max.Z - groundHeight
+ ));
+
+ gridMap.Cells[update.X, update.Y] = cell;
+ updatedCells++;
+ }
+ }
+
+ obstacleItems = gridUpdates.GroupBy(u => u.Item).Count();
+ var updateElapsed = (DateTime.Now - updateStart).TotalMilliseconds;
+ LogManager.Info($"[高性能障碍物处理] 阶段5完成: 更新 {updatedCells} 个网格单元,涉及 {obstacleItems} 个障碍物项,耗时: {updateElapsed:F1}ms");
+
+ // 输出总体统计
+ var totalElapsed = (DateTime.Now - startTime).TotalMilliseconds;
+ LogManager.Info($"[高性能障碍物处理] 处理完成,总耗时: {totalElapsed:F1}ms");
+
+ var searchTime = (DateTime.Now - startTime).TotalMilliseconds - filterElapsed - gridCalcElapsed - updateElapsed;
+ LogManager.Info($"[高性能障碍物处理] 性能分解 - Search API预筛选+后处理: {searchTime:F1}ms, 过滤: {filterElapsed:F1}ms, 计算: {gridCalcElapsed:F1}ms, 更新: {updateElapsed:F1}ms");
+
+ // 性能对比统计
+ LogManager.Info($"[性能优化统计] 处理几何体项目: {geometryItems.Count}, 最终有效项目: {validItems.Count}, 优化比率: {(1.0 - (double)validItems.Count / geometryItems.Count):P1}");
+ LogManager.Info($"[并行优化统计] 使用 {optimalParallelism}/{Environment.ProcessorCount} CPU核心,每核心处理 {Math.Ceiling((double)validItems.Count / optimalParallelism)} 个项目");
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error($"[高性能障碍物处理] 处理失败: {ex.Message}");
+ throw;
+ }
+ }
+
+ ///
+ /// 使用包围盒遍历方式处理障碍物(原版本-单线程)
/// 直接遍历所有模型项,使用包围盒检测替代空间索引+垂直扫描
///
/// Navisworks文档
@@ -1332,4 +1686,32 @@ namespace NavisworksTransport.PathPlanning
}
}
}
+
+ #region 性能优化数据结构
+
+ ///
+ /// 模型项缓存属性,存储昂贵API调用的结果
+ ///
+ internal class ItemProperties
+ {
+ public bool HasGeometry { get; set; }
+ public bool IsContainer { get; set; }
+ public BoundingBox3D BoundingBox { get; set; }
+ public bool IsChannelItem { get; set; }
+ public bool IsChildOfChannel { get; set; }
+ public bool IsInScanHeightRange { get; set; }
+ }
+
+ ///
+ /// 网格更新操作,用于并行计算后的批量更新
+ ///
+ internal class GridUpdate
+ {
+ public ModelItem Item { get; set; }
+ public int X { get; set; }
+ public int Y { get; set; }
+ public BoundingBox3D BoundingBox { get; set; }
+ }
+
+ #endregion
}
\ No newline at end of file