diff --git a/src/Core/Collision/ClashDetectiveIntegration.cs b/src/Core/Collision/ClashDetectiveIntegration.cs index 3211e45..1df4de3 100644 --- a/src/Core/Collision/ClashDetectiveIntegration.cs +++ b/src/Core/Collision/ClashDetectiveIntegration.cs @@ -1818,60 +1818,38 @@ namespace NavisworksTransport { // 优化方案:递归遍历 (Top-Down Traversal) // 原因:Search API 的 Hidden 属性不检查父级可见性,且 IsHidden 属性检查自身。 - // 解决方案:使用堆栈进行深度优先搜索(DFS),如果遭遇 Hidden 节点则停止深入该分支。 + // 解决方案:统一走 ModelItemTreeWalker 深度遍历,如果遭遇 Hidden 节点则停止深入该分支。 // 这天然地利用了 Navisworks 的层级可见性规则。 _allGeometryItemsCache = new ModelItemCollection(); int visibleCount = 0; - // 使用 Stack 模拟递归避免栈溢出,并保持对 .NET 版本的兼容性 - // Stack 初始容量设为 1000 以减少扩容 - var stack = new Stack(1000); - - // 将所有模型的根节点压入栈 - foreach (var model in Application.ActiveDocument.Models) - { - stack.Push(model.RootItem); - } - - while (stack.Count > 0) - { - var item = stack.Pop(); - - // 关键剪枝:如果节点显式隐藏,则跳过其整个分支(它的所有子节点都不可见) - if (item.IsHidden) - continue; - - // 🔥 优化移除:不再在构建时排除运动物体 - // 原因:运动物体排除移至查询阶段,通过 _animatedObjectAndDescendants 动态过滤 - // 这样基础缓存保持稳定,切换运动物体时无需重建 - // if (_animatedObject != null && item.Equals(_animatedObject)) - // continue; - - // 🔥 优化:只提取复合对象(IsComposite = true) - // 原因:复合对象(如窗户)包含多个实体节点(玻璃、框架、把手) - // 我们只需要检测复合对象,不需要检测其子节点 - // Clash Detective API 会自动处理复合对象的子节点几何体 - if (item.IsComposite) + ModelItemTreeWalker.WalkModels( + Application.ActiveDocument.Models, + item => { - // 复合对象:添加到缓存,不继续遍历子节点 - _allGeometryItemsCache.Add(item); - visibleCount++; - } - else if (item.HasGeometry) - { - // 非复合对象但有几何数据(独立实体节点):添加到缓存 - _allGeometryItemsCache.Add(item); - visibleCount++; - } - else - { - // 空节点:继续遍历子节点 - foreach (var child in item.Children) + // 🔥 优化:只提取复合对象(IsComposite = true)或独立实体节点(HasGeometry) + // 原因:复合对象(如窗户)包含多个实体节点(玻璃、框架、把手) + // 我们只需要检测复合对象,不需要检测其子节点 + // Clash Detective API 会自动处理复合对象的子节点几何体 + if (item.IsComposite) { - stack.Push(child); + // 复合对象:添加到缓存,不继续遍历子节点 + _allGeometryItemsCache.Add(item); + visibleCount++; + return ModelItemWalkAction.Prune; } - } - } + + if (item.HasGeometry) + { + // 非复合对象但有几何数据(独立实体节点):添加到缓存 + _allGeometryItemsCache.Add(item); + visibleCount++; + return ModelItemWalkAction.Prune; + } + + // 空节点:继续遍历子节点 + return ModelItemWalkAction.Continue; + }); cacheStopwatch.Stop(); LogManager.Info($"复合对象列表缓存构建完成 (DFS遍历 + 自动剪枝),耗时: {cacheStopwatch.ElapsedMilliseconds}ms");