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)
|
// 优化方案:递归遍历 (Top-Down Traversal)
|
||||||
// 原因:Search API 的 Hidden 属性不检查父级可见性,且 IsHidden 属性检查自身。
|
// 原因:Search API 的 Hidden 属性不检查父级可见性,且 IsHidden 属性检查自身。
|
||||||
// 解决方案:使用堆栈进行深度优先搜索(DFS),如果遭遇 Hidden 节点则停止深入该分支。
|
// 解决方案:统一走 ModelItemTreeWalker 深度遍历,如果遭遇 Hidden 节点则停止深入该分支。
|
||||||
// 这天然地利用了 Navisworks 的层级可见性规则。
|
// 这天然地利用了 Navisworks 的层级可见性规则。
|
||||||
_allGeometryItemsCache = new ModelItemCollection();
|
_allGeometryItemsCache = new ModelItemCollection();
|
||||||
int visibleCount = 0;
|
int visibleCount = 0;
|
||||||
|
|
||||||
// 使用 Stack 模拟递归避免栈溢出,并保持对 .NET 版本的兼容性
|
ModelItemTreeWalker.WalkModels(
|
||||||
// Stack 初始容量设为 1000 以减少扩容
|
Application.ActiveDocument.Models,
|
||||||
var stack = new Stack<ModelItem>(1000);
|
item =>
|
||||||
|
|
||||||
// 将所有模型的根节点压入栈
|
|
||||||
foreach (var model in Application.ActiveDocument.Models)
|
|
||||||
{
|
{
|
||||||
stack.Push(model.RootItem);
|
// 🔥 优化:只提取复合对象(IsComposite = true)或独立实体节点(HasGeometry)
|
||||||
}
|
|
||||||
|
|
||||||
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 会自动处理复合对象的子节点几何体
|
// Clash Detective API 会自动处理复合对象的子节点几何体
|
||||||
@ -1856,22 +1836,20 @@ namespace NavisworksTransport
|
|||||||
// 复合对象:添加到缓存,不继续遍历子节点
|
// 复合对象:添加到缓存,不继续遍历子节点
|
||||||
_allGeometryItemsCache.Add(item);
|
_allGeometryItemsCache.Add(item);
|
||||||
visibleCount++;
|
visibleCount++;
|
||||||
|
return ModelItemWalkAction.Prune;
|
||||||
}
|
}
|
||||||
else if (item.HasGeometry)
|
|
||||||
|
if (item.HasGeometry)
|
||||||
{
|
{
|
||||||
// 非复合对象但有几何数据(独立实体节点):添加到缓存
|
// 非复合对象但有几何数据(独立实体节点):添加到缓存
|
||||||
_allGeometryItemsCache.Add(item);
|
_allGeometryItemsCache.Add(item);
|
||||||
visibleCount++;
|
visibleCount++;
|
||||||
|
return ModelItemWalkAction.Prune;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// 空节点:继续遍历子节点
|
// 空节点:继续遍历子节点
|
||||||
foreach (var child in item.Children)
|
return ModelItemWalkAction.Continue;
|
||||||
{
|
});
|
||||||
stack.Push(child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cacheStopwatch.Stop();
|
cacheStopwatch.Stop();
|
||||||
LogManager.Info($"复合对象列表缓存构建完成 (DFS遍历 + 自动剪枝),耗时: {cacheStopwatch.ElapsedMilliseconds}ms");
|
LogManager.Info($"复合对象列表缓存构建完成 (DFS遍历 + 自动剪枝),耗时: {cacheStopwatch.ElapsedMilliseconds}ms");
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user