向上查找复合节点,处理clashdetective碰撞结果,优化碰撞报告生成逻辑
This commit is contained in:
parent
c044be57c0
commit
d473065025
@ -6,7 +6,7 @@
|
||||
|
||||
1. [ ] (BUG)虚拟车辆模型每次点击都重建
|
||||
2. [x] (BUG)碰撞结果高亮,应该显示clashdetective检测的结果
|
||||
3. [ ] (优化)对clashdetective的检测结果,进行向上合并,找到集合对象。
|
||||
3. [x] (优化)对clashdetective的检测结果,进行向上合并,找到集合对象。
|
||||
|
||||
### [2025/12/25]
|
||||
|
||||
|
||||
@ -58,6 +58,7 @@ namespace NavisworksTransport.Commands
|
||||
public List<CollisionResult> AllCollisions { get; set; } = new List<CollisionResult>();
|
||||
public int BoundingBoxTestCount { get; set; } // 包围盒测试数量
|
||||
public int ClashDetectiveCollisionCount { get; set; } // Clash Detective结果数量
|
||||
public int AnimationCollisions { get; set; } // 动画过程碰撞数量
|
||||
public string MovingObjectInfo { get; set; } = string.Empty;
|
||||
|
||||
// 新增:被撞物体去重统计
|
||||
@ -126,15 +127,17 @@ namespace NavisworksTransport.Commands
|
||||
UpdateProgress(10, "开始生成碰撞报告...");
|
||||
|
||||
// 检查缓存
|
||||
var testNameKey = GetLatestTestNameForCache();
|
||||
if (!string.IsNullOrEmpty(testNameKey))
|
||||
var clashIntegration = ClashDetectiveIntegration.Instance;
|
||||
var currentTestName = clashIntegration?.CurrentTestName;
|
||||
|
||||
if (!string.IsNullOrEmpty(currentTestName))
|
||||
{
|
||||
lock (_cacheLock)
|
||||
{
|
||||
if (_reportCache.ContainsKey(testNameKey))
|
||||
if (_reportCache.ContainsKey(currentTestName))
|
||||
{
|
||||
var cachedResult = _reportCache[testNameKey];
|
||||
LogManager.Info($"使用缓存的碰撞报告: {testNameKey}");
|
||||
var cachedResult = _reportCache[currentTestName];
|
||||
LogManager.Info($"使用缓存的碰撞报告: {currentTestName}");
|
||||
|
||||
UpdateProgress(100, "使用缓存报告");
|
||||
|
||||
@ -149,7 +152,7 @@ namespace NavisworksTransport.Commands
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.Info($"未找到缓存报告,开始生成新报告: {testNameKey}");
|
||||
LogManager.Debug($"缓存中未找到测试: {currentTestName}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -169,8 +172,7 @@ namespace NavisworksTransport.Commands
|
||||
result.AllCollisions = collisionData.AllCollisions;
|
||||
|
||||
// 修改统计数据
|
||||
var clashIntegration = ClashDetectiveIntegration.Instance;
|
||||
result.AnimationCollisions = clashIntegration?.AnimationCollisionCount ?? 0; // 检测点数量
|
||||
result.AnimationCollisions = collisionData.AnimationCollisions;
|
||||
result.TotalCollisions = collisionData.ClashDetectiveCollisionCount;
|
||||
result.MovingObjectInfo = collisionData.MovingObjectInfo;
|
||||
|
||||
@ -223,12 +225,12 @@ namespace NavisworksTransport.Commands
|
||||
ShowReport(result);
|
||||
|
||||
// 将报告结果缓存起来
|
||||
if (!string.IsNullOrEmpty(testNameKey))
|
||||
if (!string.IsNullOrEmpty(currentTestName))
|
||||
{
|
||||
lock (_cacheLock)
|
||||
{
|
||||
_reportCache[testNameKey] = result;
|
||||
LogManager.Info($"碰撞报告已缓存: {testNameKey}, 缓存总数: {_reportCache.Count}");
|
||||
_reportCache[currentTestName] = result;
|
||||
LogManager.Info($"碰撞报告已缓存: {currentTestName}, 缓存总数: {_reportCache.Count}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -253,56 +255,6 @@ namespace NavisworksTransport.Commands
|
||||
|
||||
#region 缓存相关方法
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前最新的物流碰撞检测测试名称作为缓存键
|
||||
/// </summary>
|
||||
/// <returns>测试名称,如果未找到则返回 null</returns>
|
||||
private string GetLatestTestNameForCache()
|
||||
{
|
||||
try
|
||||
{
|
||||
var doc = Autodesk.Navisworks.Api.Application.ActiveDocument;
|
||||
var documentClash = doc.GetClash();
|
||||
|
||||
if (documentClash == null)
|
||||
{
|
||||
LogManager.Warning("无法获取 Clash Detective 文档,无法生成缓存键");
|
||||
return null;
|
||||
}
|
||||
|
||||
// 从动画管理器获取当前路径名称
|
||||
var animationManager = Core.Animation.PathAnimationManager.GetInstance();
|
||||
var currentPathName = animationManager?.PathName;
|
||||
|
||||
if (string.IsNullOrEmpty(currentPathName))
|
||||
{
|
||||
throw new InvalidOperationException("无法获取当前路径名称");
|
||||
}
|
||||
|
||||
// 精确匹配当前路径的测试
|
||||
var matchedTest = documentClash.TestsData.Tests.Cast<ClashTest>()
|
||||
.Where(t => t.DisplayName.StartsWith("物流碰撞检测_") &&
|
||||
t.DisplayName.Contains(currentPathName))
|
||||
.OrderByDescending(t => t.DisplayName) // 同一路径可能有多个测试,取最新的
|
||||
.FirstOrDefault();
|
||||
|
||||
if (matchedTest != null)
|
||||
{
|
||||
LogManager.Info($"找到当前路径的测试: {matchedTest.DisplayName}");
|
||||
return matchedTest.DisplayName;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException($"未找到路径 '{currentPathName}' 的碰撞测试");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"获取测试名称作为缓存键失败: {ex.Message}");
|
||||
throw; // 让错误暴露出来
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清理过期缓存(可选功能)
|
||||
/// </summary>
|
||||
@ -339,94 +291,65 @@ namespace NavisworksTransport.Commands
|
||||
// 从动画管理器获取当前路径名称
|
||||
var animationManager = Core.Animation.PathAnimationManager.GetInstance();
|
||||
var currentPathName = animationManager?.PathName;
|
||||
var currentTestName = clashIntegration?.CurrentTestName;
|
||||
|
||||
if (string.IsNullOrEmpty(currentPathName))
|
||||
if (string.IsNullOrEmpty(currentTestName))
|
||||
{
|
||||
throw new InvalidOperationException("无法获取当前路径名称");
|
||||
throw new InvalidOperationException("无法获取当前测试名称,请先运行碰撞检测");
|
||||
}
|
||||
|
||||
// 直接从缓存获取ClashDetective结果
|
||||
var testCollisionsRaw = clashIntegration.GetCurrentPathClashResults(currentPathName);
|
||||
var testCollisionsRaw = clashIntegration.GetCurrentPathClashResults(currentTestName);
|
||||
|
||||
if (testCollisionsRaw == null || testCollisionsRaw.Count == 0)
|
||||
{
|
||||
throw new InvalidOperationException($"未找到路径 '{currentPathName}' 的ClashDetective碰撞结果");
|
||||
throw new InvalidOperationException($"未找到测试 '{currentTestName}' 的ClashDetective碰撞结果");
|
||||
}
|
||||
|
||||
LogManager.Info($"从缓存获取ClashDetective结果: {testCollisionsRaw.Count}个碰撞");
|
||||
LogManager.Info($"从缓存获取ClashDetective结果: {testCollisionsRaw.Count}个碰撞,测试名称:{currentTestName}");
|
||||
|
||||
// 转换为CollisionResult对象
|
||||
foreach (var clash in testCollisionsRaw)
|
||||
{
|
||||
var collision = new CollisionResult
|
||||
{
|
||||
ClashGuid = clash.Guid,
|
||||
DisplayName = $"[{currentPathName}] {clash.DisplayName}",
|
||||
Status = clash.Status,
|
||||
Item1 = clash.Item1,
|
||||
Item2 = clash.Item2,
|
||||
Center = clash.Center,
|
||||
Distance = clash.Distance,
|
||||
CreatedTime = DateTime.Now
|
||||
};
|
||||
allCollisions.Add(collision);
|
||||
}
|
||||
// 直接使用缓存中的CollisionResult对象(已经过复合对象处理和去重)
|
||||
allCollisions.AddRange(testCollisionsRaw);
|
||||
|
||||
// 统计匹配测试的碰撞总数
|
||||
var totalCollisionCount = testCollisionsRaw.Count;
|
||||
result.ClashDetectiveCollisionCount = totalCollisionCount;
|
||||
LogManager.Debug($"路径 '{currentPathName}' 包含 {totalCollisionCount} 个碰撞");
|
||||
// 统计碰撞总数
|
||||
result.ClashDetectiveCollisionCount = testCollisionsRaw.Count;
|
||||
LogManager.Debug($"测试 '{currentTestName}' 包含 {testCollisionsRaw.Count} 个碰撞");
|
||||
|
||||
// 去重处理
|
||||
var uniqueCollisions = allCollisions
|
||||
.GroupBy(c => new { c.Item1, c.Item2, c.Center })
|
||||
.Select(g => g.First())
|
||||
.ToList();
|
||||
// 统计被撞物体(缓存中已经是复合对象,不需要再去重)
|
||||
var nameCountDict = new Dictionary<string, int>();
|
||||
var uniqueCollidedObjectsList = new List<string>();
|
||||
|
||||
// 新增:统计去重后的被撞物体
|
||||
// 使用Dictionary,ModelItem作为键会自动调用Equals进行比较
|
||||
var uniqueCollidedObjectsDict = new Dictionary<ModelItem, string>();
|
||||
foreach (var collision in uniqueCollisions)
|
||||
foreach (var collision in testCollisionsRaw)
|
||||
{
|
||||
if (collision.Item2 != null)
|
||||
{
|
||||
// ModelItem作为字典的键,会使用其Equals方法进行比较
|
||||
if (!uniqueCollidedObjectsDict.ContainsKey(collision.Item2))
|
||||
var item2Name = NavisworksApiHelper.GetModelItemNameWithAncestorFallback(collision.Item2) ?? "未知对象";
|
||||
|
||||
// 为相同名称的对象添加编号区分
|
||||
if (nameCountDict.ContainsKey(item2Name))
|
||||
{
|
||||
var item2Name = NavisworksApiHelper.GetModelItemNameWithAncestorFallback(collision.Item2);
|
||||
uniqueCollidedObjectsDict[collision.Item2] = item2Name ?? "未知对象";
|
||||
nameCountDict[item2Name]++;
|
||||
uniqueCollidedObjectsList.Add($"{item2Name} #{nameCountDict[item2Name]}");
|
||||
}
|
||||
else
|
||||
{
|
||||
nameCountDict[item2Name] = 1;
|
||||
uniqueCollidedObjectsList.Add(item2Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 修复:保留所有碰撞对象,为相同名称的对象添加编号区分
|
||||
var nameCountDict = new Dictionary<string, int>();
|
||||
var uniqueCollidedObjectsList = new List<string>();
|
||||
|
||||
foreach (var name in uniqueCollidedObjectsDict.Values)
|
||||
{
|
||||
if (nameCountDict.ContainsKey(name))
|
||||
{
|
||||
nameCountDict[name]++;
|
||||
uniqueCollidedObjectsList.Add($"{name} #{nameCountDict[name]}");
|
||||
}
|
||||
else
|
||||
{
|
||||
nameCountDict[name] = 1;
|
||||
uniqueCollidedObjectsList.Add(name);
|
||||
}
|
||||
}
|
||||
|
||||
var uniqueCollidedObjectsSet = new HashSet<string>(uniqueCollidedObjectsList);
|
||||
|
||||
result.AllCollisions = uniqueCollisions;
|
||||
result.UniqueCollidedObjects = uniqueCollidedObjectsSet;
|
||||
result.AllCollisions = allCollisions;
|
||||
result.UniqueCollidedObjects = new HashSet<string>(uniqueCollidedObjectsList);
|
||||
result.BoundingBoxTestCount = 0;
|
||||
|
||||
// 设置动画碰撞数量
|
||||
result.AnimationCollisions = clashIntegration?.AnimationCollisionCount ?? 0;
|
||||
|
||||
// 从碰撞结果的Item1中获取运动构件信息
|
||||
if (uniqueCollisions.Count > 0 && uniqueCollisions[0].Item1 != null)
|
||||
if (allCollisions.Count > 0 && allCollisions[0].Item1 != null)
|
||||
{
|
||||
var movingItem = uniqueCollisions[0].Item1;
|
||||
var movingItem = allCollisions[0].Item1;
|
||||
var movingItemName = NavisworksApiHelper.GetModelItemNameWithAncestorFallback(movingItem) ?? "未知运动构件";
|
||||
result.MovingObjectInfo = $"运动构件: {movingItemName}";
|
||||
}
|
||||
@ -435,7 +358,7 @@ namespace NavisworksTransport.Commands
|
||||
result.MovingObjectInfo = "运动构件: 未知";
|
||||
}
|
||||
|
||||
LogManager.Info($"收集完成 - Clash Detective权威结果: {result.ClashDetectiveCollisionCount}个, 去重后碰撞对象: {uniqueCollisions.Count}个, 去重后被撞构件: {uniqueCollidedObjectsSet.Count}个");
|
||||
LogManager.Info($"收集完成 - Clash Detective权威结果: {result.ClashDetectiveCollisionCount}个, 碰撞对象: {allCollisions.Count}个, 被撞构件: {uniqueCollidedObjectsList.Count}个");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -50,6 +50,16 @@ namespace NavisworksTransport
|
||||
get { return _clashDetectiveCollisionCount; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当前ClashDetective测试名称
|
||||
/// </summary>
|
||||
public string CurrentTestName
|
||||
{
|
||||
get { return _currentTestName; }
|
||||
}
|
||||
|
||||
private string _currentTestName;
|
||||
|
||||
/// <summary>
|
||||
/// 单例实例
|
||||
/// </summary>
|
||||
@ -129,8 +139,9 @@ namespace NavisworksTransport
|
||||
private List<CollisionResult> _cachedResults = new List<CollisionResult>();
|
||||
private readonly object _resultsLock = new object();
|
||||
|
||||
// ClashDetective测试结果缓存:pathName -> List<ClashResult>
|
||||
private Dictionary<string, List<ClashResult>> _clashDetectiveResultsCache = new Dictionary<string, List<ClashResult>>();
|
||||
// ClashDetective测试结果缓存:pathName -> List<CollisionResult>
|
||||
// 使用自定义的CollisionResult类型,支持修改Item1和Item2
|
||||
private Dictionary<string, List<CollisionResult>> _clashDetectiveResultsCache = new Dictionary<string, List<CollisionResult>>();
|
||||
private readonly object _clashResultsCacheLock = new object();
|
||||
|
||||
/// <summary>
|
||||
@ -325,6 +336,7 @@ namespace NavisworksTransport
|
||||
|
||||
// 创建主测试名称
|
||||
var mainTestName = $"物流碰撞检测_{pathName}_{DateTime.Now:yyyyMMdd_HHmmss}";
|
||||
_currentTestName = mainTestName;
|
||||
LogManager.Info($"[分组测试] 创建主测试: {mainTestName}");
|
||||
|
||||
Progress progress = null;
|
||||
@ -370,26 +382,6 @@ namespace NavisworksTransport
|
||||
|
||||
LogManager.Info($"[分组测试] 智能去重: {validCollisions.Count} 个检测点 -> {groupedCollisions.Count} 个唯一碰撞对");
|
||||
|
||||
// 调试:打印所有去重后的碰撞对信息
|
||||
LogManager.Debug($"[分组测试] 去重后的碰撞对列表:");
|
||||
int debugIndex = 0;
|
||||
foreach (var group in groupedCollisions)
|
||||
{
|
||||
var firstCollision = group.First();
|
||||
var item1 = firstCollision.Item1;
|
||||
var item2 = firstCollision.Item2;
|
||||
|
||||
// 使用 GetModelItemWithAncestorFallback 获取名称(向上查找父节点)
|
||||
var item1Name = item1 != null ? NavisworksApiHelper.GetModelItemNameWithAncestorFallback(item1) : "null";
|
||||
var item2Name = item2 != null ? NavisworksApiHelper.GetModelItemNameWithAncestorFallback(item2) : "null";
|
||||
var item1Hash = item1?.GetHashCode() ?? -1;
|
||||
var item2Hash = item2?.GetHashCode() ?? -1;
|
||||
var frameCount = group.Count();
|
||||
|
||||
LogManager.Debug($" [{debugIndex}] Item1={item1Name}(Hash:{item1Hash}), Item2={item2Name}(Hash:{item2Hash}), 帧数={frameCount}");
|
||||
debugIndex++;
|
||||
}
|
||||
|
||||
var collisionGroup = new ClashResultGroup
|
||||
{
|
||||
DisplayName = $"物流碰撞检测组 ({groupedCollisions.Count} 个唯一碰撞对)"
|
||||
@ -546,44 +538,58 @@ namespace NavisworksTransport
|
||||
|
||||
LogManager.Info($"[分组测试] ClashDetective检测完成: 确认碰撞 {confirmedCount} 组, 跳过 {skippedCount} 个冗余检测点");
|
||||
|
||||
// 调试:打印所有确认的碰撞对信息
|
||||
LogManager.Debug($"[分组测试] 确认的碰撞对列表:");
|
||||
int confirmedIndex = 0;
|
||||
foreach (var result in collisionGroup.Children)
|
||||
{
|
||||
if (result is ClashResult clashResult)
|
||||
{
|
||||
var item1 = clashResult.Item1;
|
||||
var item2 = clashResult.Item2;
|
||||
// 第三步:处理碰撞结果并缓存
|
||||
var mergedResults = new Dictionary<string, CollisionResult>();
|
||||
int mergedCount = 0;
|
||||
|
||||
// 使用 GetModelItemWithAncestorFallback 获取名称(向上查找父节点)
|
||||
var item1Name = item1 != null ? NavisworksApiHelper.GetModelItemNameWithAncestorFallback(item1) : "null";
|
||||
var item2Name = item2 != null ? NavisworksApiHelper.GetModelItemNameWithAncestorFallback(item2) : "null";
|
||||
var item1Hash = item1?.GetHashCode() ?? -1;
|
||||
var item2Hash = item2?.GetHashCode() ?? -1;
|
||||
|
||||
LogManager.Debug($" [{confirmedIndex}] Item1={item1Name}(Hash:{item1Hash}), Item2={item2Name}(Hash:{item2Hash})");
|
||||
confirmedIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
// 直接从collisionGroup.Children提取结果并缓存
|
||||
var clashResults = new List<ClashResult>();
|
||||
foreach (var child in collisionGroup.Children)
|
||||
{
|
||||
if (child is ClashResult clashResult)
|
||||
{
|
||||
clashResults.Add(clashResult);
|
||||
// 向上查找复合对象
|
||||
var compositeItem1 = NavisworksApiHelper.FindCompositeAncestor(clashResult.Item1);
|
||||
var compositeItem2 = NavisworksApiHelper.FindCompositeAncestor(clashResult.Item2);
|
||||
|
||||
// 创建自定义的CollisionResult对象
|
||||
var collisionResult = new CollisionResult
|
||||
{
|
||||
ClashGuid = clashResult.Guid,
|
||||
DisplayName = clashResult.DisplayName,
|
||||
Status = clashResult.Status,
|
||||
Item1 = compositeItem1,
|
||||
Item2 = compositeItem2,
|
||||
Center = clashResult.Center,
|
||||
Distance = clashResult.Distance,
|
||||
CreatedTime = DateTime.Now,
|
||||
OriginalItem1 = clashResult.Item1,
|
||||
OriginalItem2 = clashResult.Item2,
|
||||
HasContainerMapping = true
|
||||
};
|
||||
|
||||
// 使用复合对象的HashCode作为key去重
|
||||
var key = $"{compositeItem1.GetHashCode()}_{compositeItem2.GetHashCode()}";
|
||||
|
||||
if (!mergedResults.ContainsKey(key))
|
||||
{
|
||||
mergedResults[key] = collisionResult;
|
||||
mergedCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var clashResults = mergedResults.Values.ToList();
|
||||
LogManager.Info($"复合对象处理完成:原始{collisionGroup.Children.Count}个碰撞,合并后{clashResults.Count}个碰撞");
|
||||
|
||||
lock (_clashResultsCacheLock)
|
||||
{
|
||||
_clashDetectiveResultsCache[pathName] = clashResults;
|
||||
_clashDetectiveResultsCache[_currentTestName] = clashResults;
|
||||
}
|
||||
LogManager.Info($"已缓存ClashDetective结果:{clashResults.Count}个碰撞");
|
||||
LogManager.Info($"已缓存ClashDetective结果:{clashResults.Count}个碰撞,测试名称:{_currentTestName}");
|
||||
|
||||
// 第三步:将分组添加到主测试
|
||||
// 更新碰撞计数器
|
||||
_clashDetectiveCollisionCount = clashResults.Count;
|
||||
|
||||
// 第四步:将分组添加到主测试
|
||||
if (collisionGroup.Children.Count > 0)
|
||||
{
|
||||
_documentClash.TestsData.TestsAddCopy(addedMainTest, collisionGroup);
|
||||
@ -610,13 +616,11 @@ namespace NavisworksTransport
|
||||
}
|
||||
}
|
||||
|
||||
// 关键修复:碰撞测试完成后,将物体恢复到动画终点位置
|
||||
// 碰撞测试完成后,将物体恢复到动画终点位置
|
||||
if (animatedObject != null && IsModelItemValid(animatedObject))
|
||||
{
|
||||
try
|
||||
{
|
||||
LogManager.Info("=== 开始恢复物体到动画终点位置 ===");
|
||||
|
||||
var modelItems = new ModelItemCollection { animatedObject };
|
||||
|
||||
// 计算当前位置到动画终点的偏移
|
||||
@ -637,7 +641,6 @@ namespace NavisworksTransport
|
||||
doc.Models.OverridePermanentTransform(modelItems, restoreTransform, false);
|
||||
|
||||
LogManager.Info($"已将 {animatedObject.DisplayName} 恢复到动画终点位置: ({animationEndPosition.X:F2},{animationEndPosition.Y:F2},{animationEndPosition.Z:F2})");
|
||||
LogManager.Info("=== 物体位置恢复完成 ===");
|
||||
}
|
||||
catch (Exception restoreEx)
|
||||
{
|
||||
@ -645,8 +648,6 @@ namespace NavisworksTransport
|
||||
}
|
||||
}
|
||||
|
||||
LogManager.Info($"=== 分组方案完成:成功创建分组碰撞测试(容差: {detectionGap}米) ===");
|
||||
|
||||
// 检查是否成功创建了主测试
|
||||
var finalMainTest = _documentClash.TestsData.Tests.FirstOrDefault(t => t.DisplayName.Contains("物流碰撞检测")) as ClashTest;
|
||||
if (finalMainTest != null)
|
||||
@ -657,7 +658,7 @@ namespace NavisworksTransport
|
||||
// 自动高亮ClashDetective结果
|
||||
try
|
||||
{
|
||||
HighlightClashDetectiveResults(pathName);
|
||||
HighlightClashDetectiveResults(_currentTestName);
|
||||
LogManager.Info("自动高亮ClashDetective检测结果完成");
|
||||
}
|
||||
catch (Exception clashHighlightEx)
|
||||
@ -665,47 +666,9 @@ namespace NavisworksTransport
|
||||
LogManager.Error($"自动高亮ClashDetective结果失败: {clashHighlightEx.Message}");
|
||||
}
|
||||
|
||||
// 更新Clash Detective碰撞计数器 - 统计分组测试中的碰撞数量
|
||||
var finalClashDetectiveCount = 0;
|
||||
if (_documentClash != null)
|
||||
{
|
||||
// 计算物流碰撞检测测试的碰撞总数
|
||||
var logisticsTests = _documentClash.TestsData.Tests.Cast<ClashTest>()
|
||||
.Where(t => t.DisplayName.Contains("物流碰撞检测") ||
|
||||
t.DisplayName.Contains("物流碰撞"))
|
||||
.ToList();
|
||||
|
||||
finalClashDetectiveCount = logisticsTests.Sum(t => GetTotalClashResultCount(t));
|
||||
LogManager.Info($"统计Clash Detective最终碰撞数量: {logisticsTests.Count}个测试,总共{finalClashDetectiveCount}个碰撞");
|
||||
|
||||
// 详细分析主测试结构
|
||||
if (finalMainTest != null)
|
||||
{
|
||||
LogManager.Info($"[分组统计] 主测试: {finalMainTest.DisplayName}");
|
||||
LogManager.Info($"[分组统计] 主测试直接子项数量: {finalMainTest.Children.Count}");
|
||||
|
||||
foreach (var child in finalMainTest.Children)
|
||||
{
|
||||
if (child is ClashResultGroup group)
|
||||
{
|
||||
LogManager.Info($"[分组统计] 分组: {group.DisplayName}, 包含 {group.Children.Count} 个结果");
|
||||
}
|
||||
else if (child is ClashResult result)
|
||||
{
|
||||
LogManager.Info($"[分组统计] 直接结果: {result.DisplayName}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_clashDetectiveCollisionCount = finalClashDetectiveCount;
|
||||
LogManager.Info($"=== 碰撞统计最终结果 ===");
|
||||
LogManager.Info($"动画过程包围盒检测: {_animationCollisionCount}个碰撞 (参考值)");
|
||||
LogManager.Info($"Clash Detective权威结果: {_clashDetectiveCollisionCount}个碰撞 (最终权威数据)");
|
||||
LogManager.Info($"统计说明: 动画过程使用简单包围盒检测,Clash Detective使用精确几何体检测");
|
||||
LogManager.Info($"=== 统计分离完成 ===");
|
||||
|
||||
LogManager.Info("=== 动画碰撞测试(分组方案)完成 ===");
|
||||
LogManager.Info($"Clash Detective权威结果: {_clashDetectiveCollisionCount}个碰撞 (权威数据)");
|
||||
|
||||
// 触发碰撞检测完成事件,通知生成报告
|
||||
if (validCollisions.Count > 0)
|
||||
@ -862,16 +825,16 @@ namespace NavisworksTransport
|
||||
/// <summary>
|
||||
/// 高亮ClashDetective测试结果
|
||||
/// </summary>
|
||||
public void HighlightClashDetectiveResults(string pathName)
|
||||
public void HighlightClashDetectiveResults(string testName)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 使用公共方法获取指定路径的碰撞结果
|
||||
var clashResults = GetCurrentPathClashResults(pathName);
|
||||
// 使用公共方法获取指定测试的碰撞结果
|
||||
var clashResults = GetCurrentPathClashResults(testName);
|
||||
|
||||
if (clashResults.Count == 0)
|
||||
{
|
||||
LogManager.Info("[ClashDetective高亮] 指定路径测试中未找到碰撞结果");
|
||||
LogManager.Info("[ClashDetective高亮] 指定测试中未找到碰撞结果");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -994,36 +957,27 @@ namespace NavisworksTransport
|
||||
/// </summary>
|
||||
/// <param name="pathName">路径名称</param>
|
||||
/// <returns>当前路径的碰撞结果列表</returns>
|
||||
public List<ClashResult> GetCurrentPathClashResults(string pathName)
|
||||
public List<CollisionResult> GetCurrentPathClashResults(string testName)
|
||||
{
|
||||
// 优先从缓存获取
|
||||
lock (_clashResultsCacheLock)
|
||||
{
|
||||
if (_clashDetectiveResultsCache.TryGetValue(pathName, out var cachedResults))
|
||||
if (_clashDetectiveResultsCache.TryGetValue(testName, out var cachedResults))
|
||||
{
|
||||
LogManager.Debug($"[ClashDetective结果] 从缓存获取 '{pathName}' 的结果:{cachedResults.Count}个碰撞");
|
||||
LogManager.Debug($"[ClashDetective结果] 从缓存获取 '{testName}' 的结果:{cachedResults.Count}个碰撞");
|
||||
return cachedResults;
|
||||
}
|
||||
}
|
||||
|
||||
// 缓存中没有,从API获取
|
||||
var matchedTest = GetCurrentPathClashTest(pathName);
|
||||
throw new InvalidOperationException($"未找到测试 '{testName}' 的ClashDetective缓存结果,请先运行碰撞检测");
|
||||
}
|
||||
|
||||
if (matchedTest == null)
|
||||
{
|
||||
throw new InvalidOperationException($"未找到路径 '{pathName}' 的ClashDetective测试");
|
||||
}
|
||||
|
||||
var results = ExtractClashResultsFromTest(matchedTest);
|
||||
|
||||
// 缓存结果
|
||||
lock (_clashResultsCacheLock)
|
||||
{
|
||||
_clashDetectiveResultsCache[pathName] = results;
|
||||
}
|
||||
|
||||
LogManager.Debug($"[ClashDetective结果] 从API获取并缓存 '{pathName}' 的结果:{results.Count}个碰撞");
|
||||
return results;
|
||||
/// <summary>
|
||||
/// 获取当前测试的碰撞结果(便捷方法)
|
||||
/// </summary>
|
||||
/// <returns>当前测试的碰撞结果列表</returns>
|
||||
public List<CollisionResult> GetCurrentTestResults()
|
||||
{
|
||||
return GetCurrentPathClashResults(_currentTestName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -1329,21 +1329,13 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
{
|
||||
try
|
||||
{
|
||||
var animationManager = Core.Animation.PathAnimationManager.GetInstance();
|
||||
var pathName = animationManager?.PathName;
|
||||
|
||||
if (string.IsNullOrEmpty(pathName))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查是否有该路径的ClashDetective结果
|
||||
var clashResults = _clashIntegration?.GetCurrentPathClashResults(pathName);
|
||||
// 检查是否有当前测试的ClashDetective结果
|
||||
var clashResults = _clashIntegration?.GetCurrentTestResults();
|
||||
|
||||
if (clashResults != null && clashResults.Count > 0)
|
||||
{
|
||||
// 有ClashDetective结果,高亮显示
|
||||
_clashIntegration?.HighlightClashDetectiveResults(pathName);
|
||||
_clashIntegration?.HighlightClashDetectiveResults(_clashIntegration.CurrentTestName);
|
||||
HasClashDetectiveResults = true;
|
||||
LogManager.Info($"动画结束,已高亮ClashDetective检测结果:{clashResults.Count}个碰撞");
|
||||
}
|
||||
@ -1393,9 +1385,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
LogManager.Info("碰撞报告已自动生成并保存到数据库");
|
||||
|
||||
// 高亮ClashDetective结果
|
||||
var animationManager = Core.Animation.PathAnimationManager.GetInstance();
|
||||
var pathName = animationManager?.PathName ?? "未知路径";
|
||||
_clashIntegration?.HighlightClashDetectiveResults(pathName);
|
||||
_clashIntegration?.HighlightClashDetectiveResults(_clashIntegration.CurrentTestName);
|
||||
HasClashDetectiveResults = true;
|
||||
LogManager.Info("已自动高亮ClashDetective检测结果");
|
||||
}
|
||||
@ -1648,9 +1638,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
|
||||
private void ExecuteHighlightClashDetectiveResults()
|
||||
{
|
||||
var animationManager = Core.Animation.PathAnimationManager.GetInstance();
|
||||
var pathName = animationManager?.PathName ?? "未知路径";
|
||||
_clashIntegration?.HighlightClashDetectiveResults(pathName);
|
||||
_clashIntegration?.HighlightClashDetectiveResults(_clashIntegration.CurrentTestName);
|
||||
UpdateMainStatus("已高亮ClashDetective检测结果");
|
||||
}
|
||||
|
||||
|
||||
@ -128,7 +128,6 @@ namespace NavisworksTransport.Utils
|
||||
}
|
||||
|
||||
// 如果所有父节点都没有DisplayName,返回默认名称
|
||||
LogManager.Debug($"[元素名称获取] 向上查找{depth}层后仍未找到DisplayName,返回默认名称");
|
||||
return depth > 0 ? "未命名对象(已溯源)" : "未命名对象";
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -170,5 +169,56 @@ namespace NavisworksTransport.Utils
|
||||
return "获取失败";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 向上查找IsComposite为true的复合对象祖先节点
|
||||
/// </summary>
|
||||
/// <param name="item">要查找的ModelItem</param>
|
||||
/// <param name="maxDepth">最大向上查找深度,防止无限递归</param>
|
||||
/// <returns>找到的复合对象祖先节点,如果未找到则返回当前节点</returns>
|
||||
public static ModelItem FindCompositeAncestor(ModelItem item, int maxDepth = 10)
|
||||
{
|
||||
if (item == null) return null;
|
||||
|
||||
try
|
||||
{
|
||||
var current = item;
|
||||
int depth = 0;
|
||||
|
||||
// 首先检查当前节点是否已经是复合对象
|
||||
if (current.IsComposite)
|
||||
{
|
||||
return current;
|
||||
}
|
||||
|
||||
// 向上查找复合对象
|
||||
while (current != null && depth < maxDepth)
|
||||
{
|
||||
// 向上一级父节点继续查找
|
||||
current = current.Parent;
|
||||
|
||||
if (current == null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
depth++;
|
||||
|
||||
// 检查是否是复合对象
|
||||
if (current.IsComposite)
|
||||
{
|
||||
return current;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有找到复合对象,返回原始节点
|
||||
return item;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"查找复合对象祖先失败: {ex.Message}");
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user