diff --git a/src/Commands/GenerateCollisionReportCommand.cs b/src/Commands/GenerateCollisionReportCommand.cs
index 8b42bf1..29b5f29 100644
--- a/src/Commands/GenerateCollisionReportCommand.cs
+++ b/src/Commands/GenerateCollisionReportCommand.cs
@@ -99,20 +99,6 @@ namespace NavisworksTransport.Commands
///
public class GenerateCollisionReportCommand : CommandBase
{
- #region 静态缓存机制
-
- ///
- /// 碰撞报告结果缓存 - 使用测试名称作为键
- ///
- private static readonly Dictionary _reportCache = new Dictionary();
-
- ///
- /// 缓存操作锁对象
- ///
- private static readonly object _cacheLock = new object();
-
- #endregion
-
private readonly CollisionReportParameters _parameters;
private string _specificTestName = null; // 指定的测试名称(用于历史报告)
@@ -152,31 +138,6 @@ namespace NavisworksTransport.Commands
return PathPlanningResult.Failure("无法确定测试名称,请先运行碰撞检测或选择历史记录");
}
- // 检查缓存
- lock (_cacheLock)
- {
- if (_reportCache.ContainsKey(targetTestName))
- {
- var cachedResult = _reportCache[targetTestName];
- LogManager.Info($"使用缓存的碰撞报告: {targetTestName}");
-
- UpdateProgress(100, "使用缓存报告");
-
- // 显示缓存的报告
- ShowReport(cachedResult);
-
- var cachedMessage = cachedResult.TotalCollisions > 0 ?
- $"碰撞报告显示完成(缓存):发现 {cachedResult.TotalCollisions} 个碰撞" :
- "碰撞报告显示完成(缓存):未发现碰撞";
-
- return PathPlanningResult.Success(cachedResult, cachedMessage);
- }
- else
- {
- LogManager.Debug($"缓存中未找到测试: {targetTestName}");
- }
- }
-
var result = new CollisionReportResult();
try
@@ -266,13 +227,6 @@ namespace NavisworksTransport.Commands
// 显示报告(UI线程)
ShowReport(result);
-
- // 将报告结果缓存起来
- lock (_cacheLock)
- {
- _reportCache[targetTestName] = result;
- LogManager.Info($"碰撞报告已缓存: {targetTestName}, 缓存总数: {_reportCache.Count}");
- }
}
catch (OperationCanceledException)
{
@@ -293,56 +247,7 @@ namespace NavisworksTransport.Commands
return PathPlanningResult.Success(result, message);
}
- #region 缓存相关方法
-
- ///
- /// 从缓存获取报告
- ///
- public static CollisionReportResult GetReportFromCache(string testName)
- {
- if (string.IsNullOrEmpty(testName))
- return null;
-
- lock (_cacheLock)
- {
- if (_reportCache.ContainsKey(testName))
- {
- LogManager.Info($"从缓存获取报告: {testName}");
- return _reportCache[testName];
- }
- }
- return null;
- }
-
- ///
- /// 缓存报告
- ///
- public static void CacheReport(string testName, CollisionReportResult reportResult)
- {
- if (string.IsNullOrEmpty(testName) || reportResult == null)
- return;
-
- lock (_cacheLock)
- {
- _reportCache[testName] = reportResult;
- LogManager.Info($"报告已缓存: {testName}, 缓存总数: {_reportCache.Count}");
- }
- }
-
- ///
- /// 清理过期缓存(可选功能)
- ///
- public static void ClearReportCache()
- {
- lock (_cacheLock)
- {
- var count = _reportCache.Count;
- _reportCache.Clear();
- LogManager.Info($"已清理碰撞报告缓存,共清理 {count} 个缓存项");
- }
- }
-
- #endregion
+
///
/// 收集所有碰撞数据及统计信息
@@ -379,7 +284,14 @@ namespace NavisworksTransport.Commands
if (testCollisionsRaw == null || testCollisionsRaw.Count == 0)
{
- throw new InvalidOperationException($"未找到测试 '{targetTestName}' 的ClashDetective碰撞结果");
+ LogManager.Info($"测试 '{targetTestName}' 没有碰撞结果,返回空数据");
+ result.AllCollisions = allCollisions;
+ result.ClashDetectiveCollisionCount = 0;
+ result.AnimationCollisions = 0;
+ result.UniqueCollidedObjects = new HashSet();
+ result.BoundingBoxTestCount = 0;
+ result.MovingObjectInfo = "无碰撞";
+ return result;
}
LogManager.Info($"从缓存获取ClashDetective结果: {testCollisionsRaw.Count}个碰撞,测试名称:{targetTestName}");
diff --git a/src/Core/Animation/PathAnimationManager.cs b/src/Core/Animation/PathAnimationManager.cs
index 590aea9..f854b47 100644
--- a/src/Core/Animation/PathAnimationManager.cs
+++ b/src/Core/Animation/PathAnimationManager.cs
@@ -2398,6 +2398,11 @@ namespace NavisworksTransport.Core.Animation
///
public int AnimationFrameRate => _animationFrameRate;
+ ///
+ /// 获取所有碰撞结果(不去重)
+ ///
+ public List AllCollisionResults => _allCollisionResults;
+
///
/// 获取当前碰撞检测精度
///
diff --git a/src/Core/Collision/ClashDetectiveIntegration.cs b/src/Core/Collision/ClashDetectiveIntegration.cs
index c688ff3..b1ad333 100644
--- a/src/Core/Collision/ClashDetectiveIntegration.cs
+++ b/src/Core/Collision/ClashDetectiveIntegration.cs
@@ -905,15 +905,15 @@ namespace NavisworksTransport
LogManager.Info($"=== 碰撞统计最终结果 ===");
LogManager.Info($"动画过程包围盒检测: {_animationCollisionCount}个碰撞 (参考值)");
LogManager.Info($"Clash Detective权威结果: {_clashDetectiveCollisionCount}个碰撞 (权威数据)");
-
- // 触发碰撞检测完成事件,通知生成报告
- // 使用ClashDetective权威结果,而不是预计算结果
- // 如果权威结果为0个碰撞,传入空列表以触发祝贺对话框
- var finalCollisions = _clashDetectiveCollisionCount > 0 ? validCollisions : new List();
- LogManager.Info($"触发CollisionDetected事件,通知生成报告({_clashDetectiveCollisionCount}个碰撞,权威数据)");
- var eventArgs = new CollisionDetectedEventArgs(finalCollisions);
- OnCollisionDetected(eventArgs);
}
+
+ // 🔥 无论是否有主测试,都触发碰撞检测完成事件,通知生成报告
+ // 使用ClashDetective权威结果,而不是预计算结果
+ // 如果权威结果为0个碰撞,传入空列表以触发祝贺对话框
+ var finalCollisions = _clashDetectiveCollisionCount > 0 ? validCollisions : new List();
+ LogManager.Info($"触发CollisionDetected事件,通知生成报告({_clashDetectiveCollisionCount}个碰撞,权威数据)");
+ var eventArgs = new CollisionDetectedEventArgs(finalCollisions);
+ OnCollisionDetected(eventArgs);
}
catch (Exception ex)
{
@@ -1013,7 +1013,7 @@ namespace NavisworksTransport
/// 获取当前路径的Clash结果
///
/// 路径名称
- /// 当前路径的碰撞结果列表
+ /// 当前路径的碰撞结果列表(如果没有结果返回空列表)
public List GetCurrentPathClashResults(string testName)
{
lock (_clashResultsCacheLock)
@@ -1036,9 +1036,11 @@ namespace NavisworksTransport
LogManager.Info($"[ClashDetective结果] 已从数据库加载 '{testName}' 的结果并缓存:{loadedResults.Count}个碰撞");
return loadedResults;
}
+
+ // 没有找到结果,返回空列表
+ LogManager.Info($"[ClashDetective结果] 未找到测试 '{testName}' 的碰撞结果,返回空列表");
+ return new List();
}
-
- throw new InvalidOperationException($"未找到测试 '{testName}' 的ClashDetective结果(缓存和数据库中都没有)");
}
///
@@ -1050,6 +1052,47 @@ namespace NavisworksTransport
return GetCurrentPathClashResults(_currentTestName);
}
+ ///
+ /// 清理当前测试的缓存
+ ///
+ public void ClearCurrentTestCache()
+ {
+ if (string.IsNullOrEmpty(_currentTestName))
+ {
+ return;
+ }
+
+ lock (_clashResultsCacheLock)
+ {
+ if (_clashDetectiveResultsCache.ContainsKey(_currentTestName))
+ {
+ _clashDetectiveResultsCache.Remove(_currentTestName);
+ LogManager.Info($"[ClashDetective缓存] 已清理当前测试 '{_currentTestName}' 的缓存");
+ }
+ }
+ }
+
+ ///
+ /// 清空当前测试名称
+ ///
+ public void ClearCurrentTestName()
+ {
+ if (!string.IsNullOrEmpty(_currentTestName))
+ {
+ LogManager.Info($"[ClashDetective] 清空当前测试名称: {_currentTestName}");
+ _currentTestName = null;
+ }
+ }
+
+ ///
+ /// 设置当前测试名称
+ ///
+ public void SetCurrentTestName(string testName)
+ {
+ _currentTestName = testName;
+ LogManager.Info($"[ClashDetective] 设置当前测试名称: {_currentTestName}");
+ }
+
///
/// 从测试中提取碰撞结果
///
diff --git a/src/Core/PathPointRenderPlugin.cs b/src/Core/PathPointRenderPlugin.cs
index 959393a..273171b 100644
--- a/src/Core/PathPointRenderPlugin.cs
+++ b/src/Core/PathPointRenderPlugin.cs
@@ -2094,8 +2094,7 @@ namespace NavisworksTransport
return new RenderStyle(Color.FromByteRGB(255, 152, 0), 0.8); // Material Orange连线,20%透明
case RenderStyleName.VehicleSpace:
- return new RenderStyle(Color.FromByteRGB(158, 158, 158), 0.4); // Material Grey车辆空间,60%透明
-
+ return new RenderStyle(Color.FromByteRGB(129, 199, 132), 0.4); // Material Light Green通行空间,60%透明
case RenderStyleName.PreviewPoint:
return new RenderStyle(Color.White, 0.7); // 白色预览点,30%透明
diff --git a/src/UI/WPF/ViewModels/AnimationControlViewModel.cs b/src/UI/WPF/ViewModels/AnimationControlViewModel.cs
index f937b70..b29d499 100644
--- a/src/UI/WPF/ViewModels/AnimationControlViewModel.cs
+++ b/src/UI/WPF/ViewModels/AnimationControlViewModel.cs
@@ -1520,8 +1520,10 @@ namespace NavisworksTransport.UI.WPF.ViewModels
UpdateMediaControlProperties(); // 更新媒体控制属性
// 先清除所有碰撞高亮(包括预计算和ClashDetective)
ModelHighlightHelper.ClearCollisionHighlights();
- // 检查并高亮ClashDetective结果(只在动画自然完成时进行)
- CheckAndHighlightClashDetectiveResults();
+ // 生成碰撞报告(无论有无碰撞)
+ GenerateAndSaveCollisionReport();
+ // 高亮ClashDetective结果(只在动画自然完成时进行)
+ HighlightClashDetectiveResults();
break;
case NavisworksTransport.Core.Animation.AnimationState.Stopped:
CanStartAnimation = true;
@@ -1542,9 +1544,73 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
///
- /// 检查并高亮ClashDetective结果
+ /// 生成并保存碰撞报告(无论有无碰撞都生成)
///
- private void CheckAndHighlightClashDetectiveResults()
+ private async void GenerateAndSaveCollisionReport()
+ {
+ try
+ {
+ var animationManager = Core.Animation.PathAnimationManager.GetInstance();
+ var hasAnimationCollisions = animationManager?.AllCollisionResults?.Count > 0;
+
+ // 如果当前动画没有碰撞数据,但CurrentTestName存在,说明是旧数据
+ // 需要清空CurrentTestName,避免使用上一次的测试数据
+ if (!hasAnimationCollisions && !string.IsNullOrEmpty(_clashIntegration?.CurrentTestName))
+ {
+ LogManager.Info("当前动画无碰撞数据,清空ClashDetectiveIntegration的CurrentTestName");
+ _clashIntegration.ClearCurrentTestName();
+ }
+
+ // 如果没有测试名称,创建一个临时的测试名称(用于无碰撞情况)
+ if (string.IsNullOrEmpty(_clashIntegration?.CurrentTestName))
+ {
+ var tempTestName = $"无碰撞_{DateTime.Now:yyyyMMdd_HHmmss}";
+ LogManager.Info($"创建临时测试名称用于无碰撞报告: {tempTestName}");
+ _clashIntegration.SetCurrentTestName(tempTestName);
+ }
+
+ // 统一使用GenerateCollisionReportCommand生成报告(无论有无碰撞)
+ UpdateMainStatus($"正在生成碰撞报告...", -1, true);
+
+ var generateReportCommand = NavisworksTransport.Commands.GenerateCollisionReportCommand.CreateComprehensive();
+ var result = await generateReportCommand.ExecuteAsync();
+
+ if (result.IsSuccess && result is PathPlanningResult reportResult)
+ {
+ // 缓存报告结果,供后续查看使用
+ _lastGeneratedReport = reportResult.Data;
+
+ // 保存到数据库
+ await SaveCollisionReportToDatabase(reportResult.Data);
+
+ var collisionCount = reportResult.Data.TotalCollisions;
+ if (collisionCount > 0)
+ {
+ UpdateMainStatus($"✅ 碰撞报告已生成并保存:{collisionCount} 个碰撞");
+ LogManager.Info("碰撞报告已自动生成并保存到数据库");
+ }
+ else
+ {
+ UpdateMainStatus($"✅ 碰撞报告已生成并保存:0 个碰撞");
+ LogManager.Info("碰撞报告已自动生成并保存到数据库(无碰撞)");
+ }
+ }
+ else
+ {
+ UpdateMainStatus($"碰撞报告生成失败: {result.ErrorMessage}");
+ LogManager.Error($"自动生成碰撞报告失败: {result.ErrorMessage}");
+ }
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error($"生成碰撞报告失败: {ex.Message}");
+ }
+ }
+
+ ///
+ /// 高亮ClashDetective结果
+ ///
+ private void HighlightClashDetectiveResults()
{
try
{
@@ -1576,58 +1642,26 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
catch (Exception ex)
{
- LogManager.Error($"检查并高亮ClashDetective结果失败: {ex.Message}");
+ LogManager.Error($"高亮ClashDetective结果失败: {ex.Message}");
}
}
///
- /// 处理ClashDetective的碰撞检测事件 - 自动生成报告并保存数据库
+ /// 处理ClashDetective的碰撞检测事件 - 已废弃,报告生成统一在CheckAndHighlightClashDetectiveResults中处理
///
- private async void OnCollisionDetected(object sender, CollisionDetectedEventArgs e)
+ private void OnCollisionDetected(object sender, CollisionDetectedEventArgs e)
{
+ // 报告生成已统一在CheckAndHighlightClashDetectiveResults中处理
+ // 此事件保留用于日志记录和未来扩展
try
{
- // 获取ClashDetective结果
var clashResults = _clashIntegration?.GetCurrentTestResults();
var collisionCount = clashResults?.Count ?? 0;
-
- if (collisionCount > 0)
- {
- UpdateMainStatus($"发现 {collisionCount} 个碰撞点,正在生成报告...", -1, true);
- LogManager.Info($"碰撞检测完成,发现 {collisionCount} 个碰撞,开始自动生成报告");
-
- // 自动生成碰撞报告
- var generateReportCommand = NavisworksTransport.Commands.GenerateCollisionReportCommand.CreateComprehensive();
- var result = await generateReportCommand.ExecuteAsync();
-
- if (result.IsSuccess && result is PathPlanningResult reportResult)
- {
- // 缓存报告结果,供后续查看使用
- _lastGeneratedReport = reportResult.Data;
-
- // 保存到数据库
- await SaveCollisionReportToDatabase(reportResult.Data);
-
- UpdateMainStatus($"✅ 碰撞报告已生成并保存:{collisionCount} 个碰撞");
- LogManager.Info("碰撞报告已自动生成并保存到数据库");
-
- // 高亮ClashDetective结果
- ModelHighlightHelper.HighlightClashDetectiveResults(_clashIntegration.CurrentTestName, _clashIntegration.GetCurrentPathClashResults);
- HasClashDetectiveResults = true;
- LogManager.Info("已自动高亮ClashDetective检测结果");
- }
- else
- {
- UpdateMainStatus($"发现 {collisionCount} 个碰撞点(报告生成失败)");
- LogManager.Error($"自动生成碰撞报告失败: {result.ErrorMessage}");
- }
- }
- // 无碰撞的情况由OnAnimationCollisionDetected方法处理,这里不做任何操作
+ LogManager.Info($"[OnCollisionDetected] 碰撞检测事件触发,碰撞数量: {collisionCount}");
}
catch (Exception ex)
{
LogManager.Error($"处理碰撞检测事件失败: {ex.Message}", ex);
- UpdateMainStatus("处理碰撞检测事件失败");
}
}