增加通过PathId查找匹配原始对象的方法,优化ClashDetective碰撞结果处理

This commit is contained in:
tian 2026-02-03 22:40:33 +08:00
parent 971c993bb7
commit 2930ea71da

View File

@ -497,6 +497,80 @@ namespace NavisworksTransport
return new Point3D(0, 0, 0);
}
}
/// <summary>
/// 通过PathId向上查找匹配的原始对象
/// 从ClashDetective返回的几何体组件开始向上遍历父节点
/// 直到找到与预计算记录中任一对象PathId匹配的父节点
/// </summary>
private ModelItem FindMatchingObjectByPathId(ModelItem clashItem2, List<CollisionResult> precomputedCollisions)
{
try
{
if (precomputedCollisions == null || precomputedCollisions.Count == 0 || clashItem2 == null)
return null;
var doc = Application.ActiveDocument;
if (doc?.Models == null) return null;
// 1. 收集所有预计算记录中Item2的PathId作为HashSet提高查找效率
var precomputedPathIds = new HashSet<(int ModelIndex, string PathId)>();
foreach (var precomputed in precomputedCollisions)
{
if (precomputed.Item2 != null)
{
try
{
var pathId = doc.Models.CreatePathId(precomputed.Item2);
precomputedPathIds.Add((pathId.ModelIndex, pathId.PathId));
}
catch { /* 忽略获取PathId失败的记录 */ }
}
}
if (precomputedPathIds.Count == 0)
{
LogManager.Debug($"[PathId匹配] 预计算记录中没有有效的PathId");
return null;
}
// 2. 从ClashDetective返回的Item2开始向上遍历父节点
var current = clashItem2;
int levels = 0;
while (current != null && levels < 20) // 最多向上查找20层
{
try
{
var currentPathId = doc.Models.CreatePathId(current);
// 检查PathId是否在预计算记录中
if (precomputedPathIds.Contains((currentPathId.ModelIndex, currentPathId.PathId)))
{
LogManager.Debug($"[PathId匹配] 成功找到匹配的父节点: {ModelItemAnalysisHelper.GetSafeDisplayName(current)} (向上{levels}层)");
return current;
}
// 继续向上查找
current = current.Parent;
levels++;
}
catch
{
// 如果当前节点无法获取PathId继续向上
current = current.Parent;
levels++;
}
}
LogManager.Debug($"[PathId匹配] 未找到匹配的父节点,向上查找了{levels}层");
return null;
}
catch (Exception ex)
{
LogManager.Warning($"[PathId匹配] 查找失败: {ex.Message}");
return null;
}
}
/// <summary>
/// 运行ClashDetective测试并保存到数据库公共方法供批处理和非批处理调用
@ -758,22 +832,28 @@ namespace NavisworksTransport
// 第三步:处理碰撞结果
// 🔥 重要ClashDetective 返回的是几何体级别的碰撞结果
// Item1 是移动物体的组件名(如"车轮1"、"车轮2"),需要统一为移动物体本身
// Item2 是被撞物体,需要向上查找有意义的父级容器
// Item2 是被撞物体,通过PathId向上查找匹配预计算中的原始对象
var clashResults = new List<CollisionResult>();
foreach (var child in collisionGroup.Children)
{
if (child is ClashResult clashResult)
{
var compositeItem1 = animatedObject;
var compositeItem2 = ModelItemAnalysisHelper.FindNamedParentContainer(clashResult.Item2);
// 🔥 通过PathId向上查找匹配的原始对象
// 从ClashDetective返回的几何体组件开始向上遍历父节点
// 直到找到与预计算记录中任一对象PathId匹配的父节点
ModelItem originalItem2 = FindMatchingObjectByPathId(clashResult.Item2, precomputedCollisions);
if (originalItem2 == null)
{
originalItem2 = clashResult.Item2; // 回退到原始对象
}
var collisionResult = new CollisionResult
{
ClashGuid = clashResult.Guid,
DisplayName = clashResult.DisplayName,
Status = clashResult.Status,
Item1 = compositeItem1,
Item2 = compositeItem2,
Item1 = animatedObject,
Item2 = originalItem2,
Center = clashResult.Center,
Distance = clashResult.Distance,
CreatedTime = DateTime.Now