修复碰撞报告无结果的问题(碰撞需要找到容器节点)
This commit is contained in:
parent
0943637f5a
commit
2d1c835398
@ -359,7 +359,18 @@ namespace NavisworksTransport
|
||||
return;
|
||||
}
|
||||
|
||||
// 使用精确的碰撞检测算法
|
||||
// 🔧 智能容器映射:将几何体子对象映射到有名称的容器对象
|
||||
var mappedAnimatedObject = GetCollisionObjectWithValidIdentity(animatedObject);
|
||||
var mappedCollisionObject = GetCollisionObjectWithValidIdentity(collisionObject);
|
||||
|
||||
// 检查是否进行了容器映射
|
||||
bool hasMapping1 = !mappedAnimatedObject.Equals(animatedObject);
|
||||
bool hasMapping2 = !mappedCollisionObject.Equals(collisionObject);
|
||||
|
||||
LogManager.Info($"[容器映射] 动画对象: '{animatedObject.DisplayName}' -> '{mappedAnimatedObject.DisplayName}' (映射: {hasMapping1})");
|
||||
LogManager.Info($"[容器映射] 碰撞对象: '{collisionObject.DisplayName}' -> '{mappedCollisionObject.DisplayName}' (映射: {hasMapping2})");
|
||||
|
||||
// 使用精确的碰撞检测算法(基于原始几何体)
|
||||
var animatedBoundingBox = animatedObject.BoundingBox();
|
||||
var collisionBoundingBox = collisionObject.BoundingBox();
|
||||
|
||||
@ -386,7 +397,7 @@ namespace NavisworksTransport
|
||||
LogManager.Warning($"[诊断-位置警告] 两个对象位置几乎相同 (距离: {positionDistance:F6}),这可能是自碰撞的标志!");
|
||||
}
|
||||
|
||||
// 创建精确的碰撞结果
|
||||
// 创建精确的碰撞结果(使用原始几何体计算,但记录容器对象)
|
||||
var collisionDistance = CalculateDistance(animatedBoundingBox, collisionBoundingBox);
|
||||
var collisionCenter = CalculateCenter(animatedBoundingBox, collisionBoundingBox);
|
||||
|
||||
@ -396,10 +407,13 @@ namespace NavisworksTransport
|
||||
var collision = new CollisionResult
|
||||
{
|
||||
ClashGuid = Guid.NewGuid(),
|
||||
DisplayName = $"精确碰撞: {animatedObject.DisplayName} <-> {collisionObject.DisplayName}",
|
||||
DisplayName = $"精确碰撞: {mappedAnimatedObject.DisplayName} <-> {mappedCollisionObject.DisplayName}",
|
||||
Status = ClashResultStatus.New,
|
||||
Item1 = animatedObject,
|
||||
Item2 = collisionObject,
|
||||
Item1 = mappedAnimatedObject, // 记录容器对象
|
||||
Item2 = mappedCollisionObject, // 记录容器对象
|
||||
OriginalItem1 = animatedObject, // 保存原始几何体对象
|
||||
OriginalItem2 = collisionObject, // 保存原始几何体对象
|
||||
HasContainerMapping = hasMapping1 || hasMapping2, // 标记是否进行了映射
|
||||
CreatedTime = DateTime.Now,
|
||||
Distance = collisionDistance,
|
||||
Center = collisionCenter,
|
||||
@ -413,26 +427,30 @@ namespace NavisworksTransport
|
||||
LogManager.Debug($" DisplayName: {collision.DisplayName}");
|
||||
LogManager.Debug($" Item1: {collision.Item1?.DisplayName ?? "NULL"}");
|
||||
LogManager.Debug($" Item2: {collision.Item2?.DisplayName ?? "NULL"}");
|
||||
LogManager.Debug($" OriginalItem1: {collision.OriginalItem1?.DisplayName ?? "NULL"}");
|
||||
LogManager.Debug($" OriginalItem2: {collision.OriginalItem2?.DisplayName ?? "NULL"}");
|
||||
LogManager.Debug($" HasContainerMapping: {collision.HasContainerMapping}");
|
||||
LogManager.Debug($" Distance: {collision.Distance:F4}");
|
||||
LogManager.Debug($" HasPositionInfo: {collision.HasPositionInfo}");
|
||||
|
||||
// 去重处理:避免重复缓存相同的碰撞对
|
||||
// 去重处理:避免重复缓存相同的碰撞对(基于容器对象)
|
||||
var existing = _cachedResults.FirstOrDefault(r =>
|
||||
r.Item1.Equals(animatedObject) && r.Item2.Equals(collisionObject));
|
||||
r.Item1.Equals(mappedAnimatedObject) && r.Item2.Equals(mappedCollisionObject));
|
||||
|
||||
if (existing == null)
|
||||
{
|
||||
_cachedResults.Add(collision);
|
||||
LogManager.Info($"[碰撞缓存-成功] 缓存精确碰撞: {animatedObject.DisplayName} <-> {collisionObject.DisplayName}");
|
||||
LogManager.Info($"[碰撞缓存-成功] 缓存精确碰撞: {mappedAnimatedObject.DisplayName} <-> {mappedCollisionObject.DisplayName}");
|
||||
LogManager.Info($" 时间: {collision.CreatedTime:HH:mm:ss}");
|
||||
LogManager.Info($" 动画位置: ({collision.Item1Position.X:F3},{collision.Item1Position.Y:F3},{collision.Item1Position.Z:F3})");
|
||||
LogManager.Info($" 碰撞位置: ({collision.Item2Position.X:F3},{collision.Item2Position.Y:F3},{collision.Item2Position.Z:F3})");
|
||||
LogManager.Info($" 包围盒距离: {collision.Distance:F4}");
|
||||
LogManager.Info($" 容器映射: {collision.HasContainerMapping}");
|
||||
LogManager.Info($" 当前缓存总数: {_cachedResults.Count}");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.Debug($"[碰撞缓存-跳过] 重复碰撞: {animatedObject.DisplayName} <-> {collisionObject.DisplayName}");
|
||||
LogManager.Debug($"[碰撞缓存-跳过] 重复碰撞: {mappedAnimatedObject.DisplayName} <-> {mappedCollisionObject.DisplayName}");
|
||||
LogManager.Debug($" 原有记录时间: {existing.CreatedTime:HH:mm:ss}");
|
||||
LogManager.Debug($" 本次尝试时间: {DateTime.Now:HH:mm:ss}");
|
||||
}
|
||||
@ -2165,20 +2183,34 @@ namespace NavisworksTransport
|
||||
// 只有真正相交(距离为0)或在检测间隙内的才算碰撞
|
||||
if (distance <= tolerance)
|
||||
{
|
||||
// 🔧 智能容器映射:使用有名称的容器对象而非几何体子对象
|
||||
var mappedAnimatedObject = GetCollisionObjectWithValidIdentity(animatedObject);
|
||||
var mappedCollisionObject = GetCollisionObjectWithValidIdentity(item);
|
||||
|
||||
// 检查是否进行了容器映射
|
||||
bool hasMapping1 = !mappedAnimatedObject.Equals(animatedObject);
|
||||
bool hasMapping2 = !mappedCollisionObject.Equals(item);
|
||||
|
||||
LogManager.Info($"[容器映射] 原始对象: {animatedObject.DisplayName} -> 容器对象: {mappedAnimatedObject.DisplayName} (映射: {hasMapping1})");
|
||||
LogManager.Info($"[容器映射] 原始对象: {item.DisplayName} -> 容器对象: {mappedCollisionObject.DisplayName} (映射: {hasMapping2})");
|
||||
|
||||
var result = new CollisionResult
|
||||
{
|
||||
ClashGuid = Guid.NewGuid(),
|
||||
DisplayName = $"纯碰撞检测: {animatedObject.DisplayName} <-> {item.DisplayName}",
|
||||
DisplayName = $"纯碰撞检测: {mappedAnimatedObject.DisplayName} <-> {mappedCollisionObject.DisplayName}",
|
||||
Status = ClashResultStatus.New,
|
||||
Item1 = animatedObject,
|
||||
Item2 = item,
|
||||
Item1 = mappedAnimatedObject, // 使用映射后的容器对象
|
||||
Item2 = mappedCollisionObject, // 使用映射后的容器对象
|
||||
OriginalItem1 = animatedObject, // 保存原始几何体对象
|
||||
OriginalItem2 = item, // 保存原始几何体对象
|
||||
HasContainerMapping = hasMapping1 || hasMapping2, // 标记是否进行了映射
|
||||
CreatedTime = DateTime.Now,
|
||||
Distance = distance,
|
||||
Center = CalculateCenter(animatedBoundingBox, itemBoundingBox)
|
||||
};
|
||||
|
||||
results.Add(result);
|
||||
LogManager.Info($"检测到碰撞: {animatedObject.DisplayName} <-> {item.DisplayName},距离: {result.Distance:F2}");
|
||||
LogManager.Info($"检测到碰撞: {mappedAnimatedObject.DisplayName} <-> {mappedCollisionObject.DisplayName},距离: {result.Distance:F2}");
|
||||
}
|
||||
}
|
||||
|
||||
@ -2297,20 +2329,39 @@ namespace NavisworksTransport
|
||||
|
||||
try
|
||||
{
|
||||
// 一次性获取所有对象
|
||||
var allItems = Application.ActiveDocument.Models.RootItemDescendantsAndSelf
|
||||
.Where(item => item.HasGeometry);
|
||||
// 🔥 修复:搜索所有对象,不过滤HasGeometry,以支持容器型通道节点
|
||||
LogManager.Debug("[通道缓存] 开始搜索所有模型对象(包括容器节点)");
|
||||
var allItems = Application.ActiveDocument.Models.RootItemDescendantsAndSelf;
|
||||
var allItemsList = allItems.ToList();
|
||||
LogManager.Debug($"[通道缓存] 总对象数量: {allItemsList.Count}");
|
||||
|
||||
// 第一轮:找出所有标记为通道的对象
|
||||
foreach (var item in allItems)
|
||||
int checkedCount = 0;
|
||||
int channelFound = 0;
|
||||
|
||||
// 第一轮:找出所有标记为通道的对象(包括容器节点)
|
||||
foreach (var item in allItemsList)
|
||||
{
|
||||
try
|
||||
{
|
||||
checkedCount++;
|
||||
|
||||
// 添加调试信息
|
||||
if (item.DisplayName == "Plaza Surround" || item.DisplayName.Contains("Plaza"))
|
||||
{
|
||||
LogManager.Debug($"[通道缓存-调试] 检查对象: {item.DisplayName}, HasGeometry: {item.HasGeometry}");
|
||||
}
|
||||
|
||||
var elementType = CategoryAttributeManager.GetLogisticsElementType(item);
|
||||
if (elementType == CategoryAttributeManager.LogisticsElementType.通道)
|
||||
{
|
||||
channelFound++;
|
||||
tempChannelObjects.Add(item);
|
||||
_channelObjectsCache.Add(item);
|
||||
LogManager.Info($"[通道缓存] 发现通道对象: {item.DisplayName}, HasGeometry: {item.HasGeometry}");
|
||||
}
|
||||
else if (item.DisplayName == "Plaza Surround" || item.DisplayName.Contains("Plaza"))
|
||||
{
|
||||
LogManager.Debug($"[通道缓存-调试] {item.DisplayName} 的物流类型: {elementType}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -2319,16 +2370,22 @@ namespace NavisworksTransport
|
||||
}
|
||||
}
|
||||
|
||||
// 第二轮:添加通道对象的所有子对象
|
||||
LogManager.Info($"[通道缓存] 第一轮搜索完成: 检查了 {checkedCount} 个对象,找到 {channelFound} 个通道根对象");
|
||||
|
||||
// 第二轮:添加通道对象的所有子对象(只添加有几何体的子对象到缓存)
|
||||
int childrenAdded = 0;
|
||||
foreach (var channelObject in tempChannelObjects)
|
||||
{
|
||||
try
|
||||
{
|
||||
LogManager.Debug($"[通道缓存] 处理通道对象的子对象: {channelObject.DisplayName}");
|
||||
|
||||
foreach (var descendant in channelObject.DescendantsAndSelf)
|
||||
{
|
||||
if (descendant.HasGeometry)
|
||||
if (descendant.HasGeometry && _channelObjectsCache.Add(descendant))
|
||||
{
|
||||
_channelObjectsCache.Add(descendant);
|
||||
childrenAdded++;
|
||||
LogManager.Debug($"[通道缓存] 添加通道子对象: {descendant.DisplayName}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2341,7 +2398,22 @@ namespace NavisworksTransport
|
||||
cacheStopwatch.Stop();
|
||||
LogManager.Info($"通道对象缓存构建完成,耗时: {cacheStopwatch.ElapsedMilliseconds}ms");
|
||||
LogManager.Info($" - 通道根对象: {tempChannelObjects.Count} 个");
|
||||
LogManager.Info($" - 新增子对象: {childrenAdded} 个");
|
||||
LogManager.Info($" - 缓存总对象: {_channelObjectsCache.Count} 个");
|
||||
|
||||
// 列出找到的通道根对象
|
||||
if (tempChannelObjects.Count > 0)
|
||||
{
|
||||
LogManager.Info("[通道缓存] 找到的通道根对象列表:");
|
||||
for (int i = 0; i < tempChannelObjects.Count; i++)
|
||||
{
|
||||
LogManager.Info($" {i + 1}. {tempChannelObjects[i].DisplayName} (HasGeometry: {tempChannelObjects[i].HasGeometry})");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.Warning("[通道缓存] ⚠️ 未找到任何通道根对象,请检查模型中的物流属性设置");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -2411,6 +2483,68 @@ namespace NavisworksTransport
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 查找具有有效名称的父级容器对象,用于解决几何体子对象无名称问题
|
||||
/// </summary>
|
||||
/// <param name="geometryItem">几何体对象(可能无名称)</param>
|
||||
/// <returns>有名称的容器对象,如果找不到则返回原对象</returns>
|
||||
private static ModelItem FindNamedParentContainer(ModelItem geometryItem)
|
||||
{
|
||||
if (geometryItem == null) return null;
|
||||
|
||||
try
|
||||
{
|
||||
var current = geometryItem;
|
||||
int levels = 0; // 防止无限递归
|
||||
|
||||
while (current != null && levels < 10) // 最多向上查找10层
|
||||
{
|
||||
// 检查当前对象是否有有效名称
|
||||
if (!string.IsNullOrEmpty(current.DisplayName) && current.DisplayName.Trim().Length > 0)
|
||||
{
|
||||
LogManager.Debug($"[容器映射] 几何体 -> 容器: '{geometryItem.DisplayName}' -> '{current.DisplayName}' (向上{levels}层)");
|
||||
return current;
|
||||
}
|
||||
|
||||
current = current.Parent;
|
||||
levels++;
|
||||
}
|
||||
|
||||
// 如果没有找到有名称的父级,返回原对象
|
||||
LogManager.Warning($"[容器映射] 未找到有名称的父级容器,使用原对象: {geometryItem.DisplayName}");
|
||||
return geometryItem;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Warning($"[容器映射] 查找父级容器时出错: {ex.Message}");
|
||||
return geometryItem; // 出错时返回原对象
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 增强的碰撞对象信息,包含容器映射
|
||||
/// </summary>
|
||||
/// <param name="originalItem">原始碰撞对象(可能是几何体子对象)</param>
|
||||
/// <returns>包含完整标识信息的对象</returns>
|
||||
private static ModelItem GetCollisionObjectWithValidIdentity(ModelItem originalItem)
|
||||
{
|
||||
if (originalItem == null) return null;
|
||||
|
||||
// 如果原对象已经有有效名称,直接返回
|
||||
if (!string.IsNullOrEmpty(originalItem.DisplayName) && originalItem.DisplayName.Trim().Length > 0)
|
||||
{
|
||||
return originalItem;
|
||||
}
|
||||
|
||||
// 否则查找有名称的父级容器
|
||||
var containerObject = FindNamedParentContainer(originalItem);
|
||||
|
||||
LogManager.Info($"[碰撞对象映射] 原对象: '{originalItem.DisplayName}' -> 容器对象: '{containerObject?.DisplayName}'");
|
||||
|
||||
return containerObject ?? originalItem;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算两个包围盒之间的最短距离(真实碰撞距离)
|
||||
/// </summary>
|
||||
@ -2551,6 +2685,89 @@ namespace NavisworksTransport
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试容器映射功能是否正常工作
|
||||
/// </summary>
|
||||
public void TestContainerMapping()
|
||||
{
|
||||
try
|
||||
{
|
||||
LogManager.Info("=== [容器映射测试] 开始测试容器映射功能 ===");
|
||||
|
||||
var testResults = new List<string>();
|
||||
|
||||
// 获取一些测试对象
|
||||
var allItems = Application.ActiveDocument.Models.RootItemDescendantsAndSelf
|
||||
.Where(item => item.HasGeometry).Take(10).ToList();
|
||||
|
||||
LogManager.Info($"[容器映射测试] 找到 {allItems.Count} 个几何体对象进行测试");
|
||||
|
||||
foreach (var item in allItems)
|
||||
{
|
||||
try
|
||||
{
|
||||
var originalName = item.DisplayName ?? "无名称";
|
||||
var mappedObject = GetCollisionObjectWithValidIdentity(item);
|
||||
var mappedName = mappedObject?.DisplayName ?? "无名称";
|
||||
|
||||
bool hasMapping = !mappedObject.Equals(item);
|
||||
|
||||
testResults.Add($"原始: '{originalName}' -> 映射: '{mappedName}' (映射: {hasMapping})");
|
||||
|
||||
LogManager.Info($"[容器映射测试] {testResults.Last()}");
|
||||
|
||||
// 验证映射对象的有效性
|
||||
if (hasMapping)
|
||||
{
|
||||
var isValidOriginal = IsModelItemValid(item);
|
||||
var isValidMapped = IsModelItemValid(mappedObject);
|
||||
LogManager.Info($" - 原始对象有效性: {isValidOriginal}");
|
||||
LogManager.Info($" - 映射对象有效性: {isValidMapped}");
|
||||
LogManager.Info($" - 原始对象GUID: {item.InstanceGuid}");
|
||||
LogManager.Info($" - 映射对象GUID: {mappedObject.InstanceGuid}");
|
||||
}
|
||||
}
|
||||
catch (Exception itemEx)
|
||||
{
|
||||
LogManager.Warning($"[容器映射测试] 测试单个对象失败: {itemEx.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
LogManager.Info("=== [容器映射测试] 测试结果汇总 ===");
|
||||
int mappingCount = testResults.Count(r => r.Contains("映射: True"));
|
||||
LogManager.Info($"测试对象总数: {testResults.Count}");
|
||||
LogManager.Info($"发生映射的对象: {mappingCount}");
|
||||
LogManager.Info($"映射成功率: {(mappingCount * 100.0 / Math.Max(testResults.Count, 1)):F1}%");
|
||||
|
||||
// 测试碰撞结果数据结构
|
||||
var testCollision = new CollisionResult
|
||||
{
|
||||
ClashGuid = Guid.NewGuid(),
|
||||
DisplayName = "测试碰撞",
|
||||
Item1 = allItems.FirstOrDefault(),
|
||||
Item2 = allItems.Skip(1).FirstOrDefault(),
|
||||
OriginalItem1 = allItems.FirstOrDefault(),
|
||||
OriginalItem2 = allItems.Skip(1).FirstOrDefault(),
|
||||
HasContainerMapping = true,
|
||||
HasPositionInfo = true
|
||||
};
|
||||
|
||||
LogManager.Info($"[容器映射测试] CollisionResult数据结构测试:");
|
||||
LogManager.Info($" - GetValidItem1: {testCollision.GetValidItem1()?.DisplayName ?? "NULL"}");
|
||||
LogManager.Info($" - GetValidItem2: {testCollision.GetValidItem2()?.DisplayName ?? "NULL"}");
|
||||
LogManager.Info($" - GetOriginalItem1: {testCollision.GetOriginalItem1()?.DisplayName ?? "NULL"}");
|
||||
LogManager.Info($" - GetOriginalItem2: {testCollision.GetOriginalItem2()?.DisplayName ?? "NULL"}");
|
||||
LogManager.Info($" - HasContainerMapping: {testCollision.HasContainerMapping}");
|
||||
|
||||
LogManager.Info("=== [容器映射测试] 测试完成 ===");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"[容器映射测试] 测试失败: {ex.Message}");
|
||||
LogManager.Error($"[容器映射测试] 堆栈跟踪: {ex.StackTrace}");
|
||||
}
|
||||
}
|
||||
|
||||
// 已删除:ForceShowTestResults 和 CreateDemoTest - 不再需要这些已废弃的方法
|
||||
|
||||
/// <summary>
|
||||
@ -2639,10 +2856,23 @@ namespace NavisworksTransport
|
||||
public double Distance { get; set; }
|
||||
public DateTime CreatedTime { get; set; }
|
||||
|
||||
// 新增:位置信息用于恢复测试
|
||||
// 位置信息用于恢复测试
|
||||
public Point3D Item1Position { get; set; }
|
||||
public Point3D Item2Position { get; set; }
|
||||
public bool HasPositionInfo { get; set; }
|
||||
|
||||
// 📦 容器映射信息:记录原始几何体对象引用
|
||||
public ModelItem OriginalItem1 { get; set; } // 原始几何体对象
|
||||
public ModelItem OriginalItem2 { get; set; } // 原始几何体对象
|
||||
public bool HasContainerMapping { get; set; } // 标识是否进行了容器映射
|
||||
|
||||
// 📍 获取最终用于ClashDetective的有效对象
|
||||
public ModelItem GetValidItem1() => Item1; // 容器对象,用于ClashDetective选择集
|
||||
public ModelItem GetValidItem2() => Item2; // 容器对象,用于ClashDetective选择集
|
||||
|
||||
// 📍 获取原始几何体对象(用于精确位置信息)
|
||||
public ModelItem GetOriginalItem1() => OriginalItem1 ?? Item1;
|
||||
public ModelItem GetOriginalItem2() => OriginalItem2 ?? Item2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user