refactor: ClashDetectiveIntegration 几何缓存构建迁移 ModelItemTreeWalker
BuildNonHidddenGeometryItemsCache 栈式 DFS → ModelItemTreeWalker.WalkModels: - IsHidden 剪枝 / IsComposite、HasGeometry 收集 / 空节点深入 / visibleCount 统计 / 双重检查锁 / 异常空缓存 全部语义保持 业务等价验证(Ground 虚拟物体碰撞测试,干净 NW): - 新旧版 totalCollisions 均为 12(stash 前后对比,对象集合一致) - 消费方(GetNonChannelGeometryItemsCache → SpatialHashGrid)为集合语义,顺序无关 - 集成测试 25/25(含 3 个碰撞测试) 注:脏 NW 状态(集成测试残留)下碰撞数会波动(5 vs 12)——非迁移引入,重启后稳定
This commit is contained in:
parent
818a5e0ad7
commit
f13e60c979
@ -1818,36 +1818,16 @@ 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<ModelItem>(1000);
|
||||
|
||||
// 将所有模型的根节点压入栈
|
||||
foreach (var model in Application.ActiveDocument.Models)
|
||||
ModelItemTreeWalker.WalkModels(
|
||||
Application.ActiveDocument.Models,
|
||||
item =>
|
||||
{
|
||||
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)
|
||||
// 🔥 优化:只提取复合对象(IsComposite = true)或独立实体节点(HasGeometry)
|
||||
// 原因:复合对象(如窗户)包含多个实体节点(玻璃、框架、把手)
|
||||
// 我们只需要检测复合对象,不需要检测其子节点
|
||||
// Clash Detective API 会自动处理复合对象的子节点几何体
|
||||
@ -1856,22 +1836,20 @@ namespace NavisworksTransport
|
||||
// 复合对象:添加到缓存,不继续遍历子节点
|
||||
_allGeometryItemsCache.Add(item);
|
||||
visibleCount++;
|
||||
return ModelItemWalkAction.Prune;
|
||||
}
|
||||
else if (item.HasGeometry)
|
||||
|
||||
if (item.HasGeometry)
|
||||
{
|
||||
// 非复合对象但有几何数据(独立实体节点):添加到缓存
|
||||
_allGeometryItemsCache.Add(item);
|
||||
visibleCount++;
|
||||
return ModelItemWalkAction.Prune;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// 空节点:继续遍历子节点
|
||||
foreach (var child in item.Children)
|
||||
{
|
||||
stack.Push(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ModelItemWalkAction.Continue;
|
||||
});
|
||||
|
||||
cacheStopwatch.Stop();
|
||||
LogManager.Info($"复合对象列表缓存构建完成 (DFS遍历 + 自动剪枝),耗时: {cacheStopwatch.ElapsedMilliseconds}ms");
|
||||
|
||||
Loading…
Reference in New Issue
Block a user