715 lines
28 KiB
C#
715 lines
28 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using System.Threading;
|
||
using System.Threading.Tasks;
|
||
using Autodesk.Navisworks.Api;
|
||
using Autodesk.Navisworks.Api.Clash;
|
||
using NavisworksTransport.Utils;
|
||
using NavisworksTransport.UI.WPF.Views;
|
||
|
||
namespace NavisworksTransport.Commands
|
||
{
|
||
/// <summary>
|
||
/// 碰撞报告参数类
|
||
/// </summary>
|
||
public class CollisionReportParameters
|
||
{
|
||
/// <summary>
|
||
/// 报告类型
|
||
/// </summary>
|
||
public enum ReportType
|
||
{
|
||
/// <summary>动画碰撞报告</summary>
|
||
Animation,
|
||
/// <summary>独立碰撞检测报告</summary>
|
||
Independent,
|
||
/// <summary>综合报告(包含所有类型)</summary>
|
||
Comprehensive
|
||
}
|
||
|
||
/// <summary>
|
||
/// 要生成的报告类型
|
||
/// </summary>
|
||
public ReportType Type { get; set; } = ReportType.Comprehensive;
|
||
|
||
/// <summary>
|
||
/// 是否包含详细信息
|
||
/// </summary>
|
||
public bool IncludeDetails { get; set; } = true;
|
||
|
||
/// <summary>
|
||
/// 是否自动高亮报告中的碰撞对象
|
||
/// </summary>
|
||
public bool AutoHighlight { get; set; } = false;
|
||
|
||
public PathPlanningResult ValidateParameters()
|
||
{
|
||
return PathPlanningResult.Success("参数验证通过");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 碰撞数据收集结果
|
||
/// </summary>
|
||
public class CollisionDataResult
|
||
{
|
||
public List<CollisionResult> AllCollisions { get; set; } = new List<CollisionResult>();
|
||
public int BoundingBoxTestCount { get; set; } // 包围盒测试数量
|
||
public int ClashDetectiveCollisionCount { get; set; } // Clash Detective结果数量
|
||
public string MovingObjectInfo { get; set; } = string.Empty;
|
||
|
||
// 新增:被撞物体去重统计
|
||
public HashSet<string> UniqueCollidedObjects { get; set; } = new HashSet<string>();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 碰撞报告结果类
|
||
/// </summary>
|
||
public class CollisionReportResult
|
||
{
|
||
public string ReportContent { get; set; }
|
||
public int TotalCollisions { get; set; }
|
||
public int AnimationCollisions { get; set; } // 检测点数量
|
||
public List<CollisionResult> AllCollisions { get; set; } = new List<CollisionResult>();
|
||
public long GenerationTimeMs { get; set; }
|
||
public string MovingObjectInfo { get; set; } = string.Empty;
|
||
|
||
// 新增:被撞物体清单
|
||
public List<string> CollidedObjectsList { get; set; } = new List<string>();
|
||
public int UniqueCollidedObjectsCount { get; set; }
|
||
|
||
// 新增:动画参数
|
||
public string PathName { get; set; } = "未知路径";
|
||
public int FrameRate { get; set; } = 30;
|
||
public double Duration { get; set; } = 10.0;
|
||
public double DetectionGap { get; set; } = 0.05;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 生成碰撞报告Command
|
||
/// </summary>
|
||
public class GenerateCollisionReportCommand : CommandBase
|
||
{
|
||
#region 静态缓存机制
|
||
|
||
/// <summary>
|
||
/// 碰撞报告结果缓存 - 使用测试名称作为键
|
||
/// </summary>
|
||
private static readonly Dictionary<string, CollisionReportResult> _reportCache = new Dictionary<string, CollisionReportResult>();
|
||
|
||
/// <summary>
|
||
/// 缓存操作锁对象
|
||
/// </summary>
|
||
private static readonly object _cacheLock = new object();
|
||
|
||
#endregion
|
||
|
||
private readonly CollisionReportParameters _parameters;
|
||
|
||
public GenerateCollisionReportCommand(CollisionReportParameters parameters = null)
|
||
: base("GenerateCollisionReport", "生成碰撞报告", "生成并显示详细的碰撞检测报告")
|
||
{
|
||
_parameters = parameters ?? new CollisionReportParameters();
|
||
}
|
||
|
||
protected override PathPlanningResult ValidateParameters()
|
||
{
|
||
return _parameters.ValidateParameters();
|
||
}
|
||
|
||
protected override async Task<PathPlanningResult> ExecuteInternalAsync(CancellationToken cancellationToken)
|
||
{
|
||
var startTime = DateTime.UtcNow;
|
||
|
||
UpdateProgress(10, "开始生成碰撞报告...");
|
||
|
||
// 检查缓存
|
||
var testNameKey = GetLatestTestNameForCache();
|
||
if (!string.IsNullOrEmpty(testNameKey))
|
||
{
|
||
lock (_cacheLock)
|
||
{
|
||
if (_reportCache.ContainsKey(testNameKey))
|
||
{
|
||
var cachedResult = _reportCache[testNameKey];
|
||
LogManager.Info($"使用缓存的碰撞报告: {testNameKey}");
|
||
|
||
UpdateProgress(100, "使用缓存报告");
|
||
|
||
// 显示缓存的报告
|
||
ShowReport(cachedResult);
|
||
|
||
var cachedMessage = cachedResult.TotalCollisions > 0 ?
|
||
$"碰撞报告显示完成(缓存):发现 {cachedResult.TotalCollisions} 个碰撞" :
|
||
"碰撞报告显示完成(缓存):未发现碰撞";
|
||
|
||
return PathPlanningResult<CollisionReportResult>.Success(cachedResult, cachedMessage);
|
||
}
|
||
else
|
||
{
|
||
LogManager.Info($"未找到缓存报告,开始生成新报告: {testNameKey}");
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
LogManager.Warning("无法获取测试名称,跳过缓存检查");
|
||
}
|
||
|
||
var result = new CollisionReportResult();
|
||
|
||
try
|
||
{
|
||
UpdateProgress(30, "收集碰撞数据...");
|
||
|
||
// 收集所有碰撞数据及统计信息(同步执行,避免 COM 线程问题)
|
||
var collisionData = CollectAllCollisionData();
|
||
result.AllCollisions = collisionData.AllCollisions;
|
||
|
||
// 修改统计数据
|
||
var clashIntegration = ClashDetectiveIntegration.Instance;
|
||
result.AnimationCollisions = clashIntegration?.AnimationCollisionCount ?? 0; // 检测点数量
|
||
result.TotalCollisions = collisionData.ClashDetectiveCollisionCount;
|
||
result.MovingObjectInfo = collisionData.MovingObjectInfo;
|
||
|
||
// 新增:被撞物体清单
|
||
result.CollidedObjectsList = collisionData.UniqueCollidedObjects.OrderBy(x => x).ToList();
|
||
result.UniqueCollidedObjectsCount = collisionData.UniqueCollidedObjects.Count;
|
||
|
||
// 新增:从动画管理器获取动画参数
|
||
var animationManager = Core.Animation.PathAnimationManager.GetInstance();
|
||
if (animationManager != null)
|
||
{
|
||
result.FrameRate = animationManager.AnimationFrameRate;
|
||
result.Duration = animationManager.AnimationDuration;
|
||
result.DetectionGap = animationManager.DetectionGap;
|
||
// PathName需要从动画管理器获取
|
||
result.PathName = animationManager.PathName ?? "未知路径";
|
||
}
|
||
|
||
LogManager.Info($"碰撞报告计数 - 检查点: {result.AnimationCollisions}, Clash Detective: {result.TotalCollisions}");
|
||
|
||
UpdateProgress(70, "生成报告内容...");
|
||
|
||
// 生成报告内容
|
||
result.ReportContent = GenerateReportContent(collisionData, _parameters.Type, _parameters.IncludeDetails);
|
||
|
||
UpdateProgress(90, "处理报告显示...");
|
||
|
||
// 自动高亮(如果启用)
|
||
if (_parameters.AutoHighlight && collisionData.AllCollisions.Count > 0)
|
||
{
|
||
try
|
||
{
|
||
var highlightIntegration = ClashDetectiveIntegration.Instance;
|
||
if (highlightIntegration != null)
|
||
{
|
||
var highlightColor = Color.Green; // 绿色 (Navisworks API中没有Orange)
|
||
highlightIntegration.ManageHighlightsByCategory(ModelHighlightHelper.CollisionResultsCategory, collisionData.AllCollisions, highlightColor, true);
|
||
LogManager.Info($"自动高亮显示报告中的 {collisionData.AllCollisions.Count} 个碰撞对象");
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"自动高亮报告对象失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
UpdateProgress(100, "报告生成完成");
|
||
|
||
// 显示报告(UI线程)
|
||
ShowReport(result);
|
||
|
||
// 将报告结果缓存起来
|
||
if (!string.IsNullOrEmpty(testNameKey))
|
||
{
|
||
lock (_cacheLock)
|
||
{
|
||
_reportCache[testNameKey] = result;
|
||
LogManager.Info($"碰撞报告已缓存: {testNameKey}, 缓存总数: {_reportCache.Count}");
|
||
}
|
||
}
|
||
}
|
||
catch (OperationCanceledException)
|
||
{
|
||
return PathPlanningResult.Failure("报告生成被取消");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"生成碰撞报告失败: {ex.Message}");
|
||
return PathPlanningResult.Failure($"报告生成失败: {ex.Message}");
|
||
}
|
||
|
||
result.GenerationTimeMs = (long)(DateTime.UtcNow - startTime).TotalMilliseconds;
|
||
|
||
var message = result.TotalCollisions > 0 ?
|
||
$"碰撞报告生成完成:发现 {result.TotalCollisions} 个碰撞" :
|
||
"碰撞报告生成完成:未发现碰撞";
|
||
|
||
return PathPlanningResult<CollisionReportResult>.Success(result, message);
|
||
}
|
||
|
||
#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>
|
||
public static void ClearReportCache()
|
||
{
|
||
lock (_cacheLock)
|
||
{
|
||
var count = _reportCache.Count;
|
||
_reportCache.Clear();
|
||
LogManager.Info($"已清理碰撞报告缓存,共清理 {count} 个缓存项");
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
/// <summary>
|
||
/// 收集所有碰撞数据及统计信息
|
||
/// </summary>
|
||
private CollisionDataResult CollectAllCollisionData()
|
||
{
|
||
var result = new CollisionDataResult();
|
||
var allCollisions = new List<CollisionResult>();
|
||
|
||
try
|
||
{
|
||
LogManager.Info("开始收集所有碰撞数据及统计信息...");
|
||
|
||
var clashIntegration = ClashDetectiveIntegration.Instance;
|
||
if (clashIntegration == null)
|
||
{
|
||
throw new InvalidOperationException("无法获取ClashDetectiveIntegration实例");
|
||
}
|
||
|
||
// 从动画管理器获取当前路径名称
|
||
var animationManager = Core.Animation.PathAnimationManager.GetInstance();
|
||
var currentPathName = animationManager?.PathName;
|
||
|
||
if (string.IsNullOrEmpty(currentPathName))
|
||
{
|
||
throw new InvalidOperationException("无法获取当前路径名称");
|
||
}
|
||
|
||
// 使用公共方法获取当前路径的测试
|
||
var matchedTest = clashIntegration.GetCurrentPathClashTest(currentPathName);
|
||
|
||
if (matchedTest == null)
|
||
{
|
||
throw new InvalidOperationException($"未找到路径 '{currentPathName}' 的碰撞测试");
|
||
}
|
||
|
||
LogManager.Info($"找到当前路径的测试: {matchedTest.DisplayName}");
|
||
|
||
// 使用ClashDetectiveIntegration的方法提取碰撞数据
|
||
var testCollisionsRaw = clashIntegration.ExtractClashResultsFromTest(matchedTest);
|
||
|
||
// 转换为CollisionResult对象
|
||
foreach (var clash in testCollisionsRaw)
|
||
{
|
||
var collision = new CollisionResult
|
||
{
|
||
ClashGuid = clash.Guid,
|
||
DisplayName = $"[{matchedTest.DisplayName}] {clash.DisplayName}",
|
||
Status = clash.Status,
|
||
Item1 = clash.Item1,
|
||
Item2 = clash.Item2,
|
||
Center = clash.Center,
|
||
Distance = clash.Distance,
|
||
CreatedTime = DateTime.Now
|
||
};
|
||
allCollisions.Add(collision);
|
||
}
|
||
|
||
// 统计匹配测试的碰撞总数
|
||
var totalCollisionCount = testCollisionsRaw.Count;
|
||
result.ClashDetectiveCollisionCount = totalCollisionCount;
|
||
LogManager.Debug($"匹配测试 '{matchedTest.DisplayName}' 包含 {totalCollisionCount} 个碰撞");
|
||
|
||
// 去重处理
|
||
var uniqueCollisions = allCollisions
|
||
.GroupBy(c => new { c.Item1, c.Item2, c.Center })
|
||
.Select(g => g.First())
|
||
.ToList();
|
||
|
||
// 新增:统计去重后的被撞物体
|
||
// 使用Dictionary,ModelItem作为键会自动调用Equals进行比较
|
||
var uniqueCollidedObjectsDict = new Dictionary<ModelItem, string>();
|
||
foreach (var collision in uniqueCollisions)
|
||
{
|
||
if (collision.Item2 != null)
|
||
{
|
||
// ModelItem作为字典的键,会使用其Equals方法进行比较
|
||
if (!uniqueCollidedObjectsDict.ContainsKey(collision.Item2))
|
||
{
|
||
var item2Name = NavisworksApiHelper.GetModelItemNameWithAncestorFallback(collision.Item2);
|
||
uniqueCollidedObjectsDict[collision.Item2] = 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.BoundingBoxTestCount = 0;
|
||
|
||
// 从碰撞结果的Item1中获取运动构件信息
|
||
if (uniqueCollisions.Count > 0 && uniqueCollisions[0].Item1 != null)
|
||
{
|
||
var movingItem = uniqueCollisions[0].Item1;
|
||
var movingItemName = NavisworksApiHelper.GetModelItemNameWithAncestorFallback(movingItem) ?? "未知运动构件";
|
||
result.MovingObjectInfo = $"运动构件: {movingItemName}";
|
||
}
|
||
else
|
||
{
|
||
result.MovingObjectInfo = "运动构件: 未知";
|
||
}
|
||
|
||
LogManager.Info($"收集完成 - Clash Detective权威结果: {result.ClashDetectiveCollisionCount}个, 去重后碰撞对象: {uniqueCollisions.Count}个, 去重后被撞构件: {uniqueCollidedObjectsSet.Count}个");
|
||
|
||
return result;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"收集碰撞数据失败: {ex.Message}");
|
||
result.AllCollisions = allCollisions;
|
||
return result;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 生成报告内容
|
||
/// </summary>
|
||
private string GenerateReportContent(CollisionDataResult collisionData,
|
||
CollisionReportParameters.ReportType reportType, bool includeDetails)
|
||
{
|
||
var report = new StringBuilder();
|
||
var now = DateTime.Now;
|
||
var collisions = collisionData.AllCollisions;
|
||
|
||
// 报告头部
|
||
report.AppendLine("========================================");
|
||
report.AppendLine(" NavisworksTransport 碰撞检测报告");
|
||
report.AppendLine("========================================");
|
||
report.AppendLine($"生成时间: {now:yyyy年MM月dd日 HH:mm:ss}");
|
||
report.AppendLine($"报告类型: {GetReportTypeName(reportType)}");
|
||
|
||
// 运动构件信息(原运动物体信息)
|
||
if (!string.IsNullOrEmpty(collisionData.MovingObjectInfo))
|
||
{
|
||
var movingInfo = collisionData.MovingObjectInfo.Replace("运动对象", "运动构件");
|
||
report.AppendLine($"{movingInfo}");
|
||
}
|
||
report.AppendLine();
|
||
|
||
// 总体统计
|
||
report.AppendLine("=== 总体统计 ===");
|
||
var clashIntegration = ClashDetectiveIntegration.Instance;
|
||
var animationCollisionCount = clashIntegration?.AnimationCollisionCount ?? 0;
|
||
|
||
report.AppendLine($"总碰撞数: {collisionData.ClashDetectiveCollisionCount}个");
|
||
report.AppendLine($"碰撞构件: {collisionData.UniqueCollidedObjects.Count}个");
|
||
report.AppendLine($"检测点: {animationCollisionCount}个");
|
||
report.AppendLine();
|
||
|
||
// 碰撞构件清单(新增)
|
||
if (collisionData.UniqueCollidedObjects?.Count > 0)
|
||
{
|
||
report.AppendLine("=== 碰撞构件清单 ===");
|
||
int index = 1;
|
||
foreach (var objName in collisionData.UniqueCollidedObjects.OrderBy(x => x).Take(20)) // 限制显示前20个
|
||
{
|
||
report.AppendLine($" {index}. {objName}");
|
||
index++;
|
||
}
|
||
if (collisionData.UniqueCollidedObjects.Count > 20)
|
||
{
|
||
report.AppendLine($" ... 还有 {collisionData.UniqueCollidedObjects.Count - 20} 个构件");
|
||
}
|
||
report.AppendLine();
|
||
}
|
||
|
||
// 详细信息
|
||
if (includeDetails && collisions.Count > 0)
|
||
{
|
||
report.AppendLine("=== 详细碰撞信息 ===");
|
||
|
||
report.AppendLine("--- 碰撞详情 ---");
|
||
foreach (var collision in collisions.Take(10)) // 限制显示数量
|
||
{
|
||
AppendCollisionDetail(report, collision);
|
||
}
|
||
if (collisions.Count > 10)
|
||
{
|
||
report.AppendLine($"... 还有 {collisions.Count - 10} 个碰撞未显示");
|
||
}
|
||
report.AppendLine();
|
||
}
|
||
|
||
// 建议和结论
|
||
report.AppendLine("=== 建议与结论 ===");
|
||
if (collisions.Count == 0)
|
||
{
|
||
report.AppendLine("✅ 未发现碰撞问题,路径规划良好。");
|
||
}
|
||
else
|
||
{
|
||
report.AppendLine($"⚠️ 发现 {collisions.Count} 个碰撞问题,建议采取以下措施:");
|
||
report.AppendLine(" 1. 调整路径规划,避开碰撞区域");
|
||
report.AppendLine(" 2. 检查车辆尺寸和安全边距设置");
|
||
report.AppendLine(" 3. 考虑增加临时障碍物标记");
|
||
report.AppendLine(" 4. 重新评估物流流程设计");
|
||
|
||
report.AppendLine(" 5. 建议进行更详细的碰撞检测分析");
|
||
}
|
||
|
||
report.AppendLine();
|
||
report.AppendLine("========================================");
|
||
report.AppendLine($"报告生成完成 - {now:HH:mm:ss}");
|
||
report.AppendLine("========================================");
|
||
|
||
return report.ToString();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 添加碰撞详细信息到报告中
|
||
/// </summary>
|
||
private void AppendCollisionDetail(StringBuilder report, CollisionResult collision)
|
||
{
|
||
var item1Name = collision.Item1?.DisplayName ?? "未知对象";
|
||
var item2Name = collision.Item2?.DisplayName ?? "未知对象";
|
||
|
||
// 转换距离单位为米
|
||
var distanceInMeters = ConvertDistanceToMeters(collision.Distance);
|
||
|
||
report.AppendLine($"• {item1Name} ↔ {item2Name}");
|
||
report.AppendLine($" 状态: {GetStatusName(collision.Status)}, 距离: {distanceInMeters:F3}m");
|
||
|
||
// 转换位置坐标单位为米
|
||
var centerInMeters = ConvertPointToMeters(collision.Center);
|
||
report.AppendLine($" 位置: ({centerInMeters.X:F2}, {centerInMeters.Y:F2}, {centerInMeters.Z:F2})m");
|
||
report.AppendLine($" GUID: {collision.ClashGuid}");
|
||
report.AppendLine();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取报告类型名称
|
||
/// </summary>
|
||
private string GetReportTypeName(CollisionReportParameters.ReportType reportType)
|
||
{
|
||
switch (reportType)
|
||
{
|
||
case CollisionReportParameters.ReportType.Animation:
|
||
return "动画碰撞报告";
|
||
case CollisionReportParameters.ReportType.Independent:
|
||
return "独立检测报告";
|
||
case CollisionReportParameters.ReportType.Comprehensive:
|
||
return "综合碰撞报告";
|
||
default:
|
||
return "未知类型";
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取碰撞状态名称
|
||
/// </summary>
|
||
private string GetStatusName(ClashResultStatus status)
|
||
{
|
||
switch (status)
|
||
{
|
||
case ClashResultStatus.New:
|
||
return "新发现";
|
||
case ClashResultStatus.Active:
|
||
return "活跃";
|
||
case ClashResultStatus.Reviewed:
|
||
return "已审阅";
|
||
case ClashResultStatus.Approved:
|
||
return "已批准";
|
||
case ClashResultStatus.Resolved:
|
||
return "已解决";
|
||
default:
|
||
return "未知";
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 显示报告
|
||
/// </summary>
|
||
private void ShowReport(CollisionReportResult reportResult)
|
||
{
|
||
try
|
||
{
|
||
// 确保在UI线程中执行
|
||
if (System.Windows.Application.Current != null)
|
||
{
|
||
if (System.Windows.Application.Current.Dispatcher.CheckAccess())
|
||
{
|
||
// 已在UI线程上
|
||
ShowReportInternal(reportResult);
|
||
}
|
||
else
|
||
{
|
||
// 切换到UI线程
|
||
System.Windows.Application.Current.Dispatcher.Invoke(() => ShowReportInternal(reportResult));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// 如果WPF Application不存在,回退到原来的方式
|
||
ShowReportInternal(reportResult);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"显示报告失败: {ex.Message}");
|
||
System.Windows.MessageBox.Show($"显示报告失败: {ex.Message}", "错误",
|
||
System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 内部报告显示方法
|
||
/// </summary>
|
||
private void ShowReportInternal(CollisionReportResult reportResult)
|
||
{
|
||
try
|
||
{
|
||
// 使用新的WPF碰撞报告对话框
|
||
var reportDialog = CollisionReportDialog.ShowReport(reportResult);
|
||
|
||
if (reportDialog != null)
|
||
{
|
||
LogManager.Info("WPF碰撞报告对话框显示成功");
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"显示WPF报告对话框失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建综合报告命令
|
||
/// </summary>
|
||
public static GenerateCollisionReportCommand CreateComprehensive(bool autoHighlight = false)
|
||
{
|
||
return new GenerateCollisionReportCommand(new CollisionReportParameters
|
||
{
|
||
Type = CollisionReportParameters.ReportType.Comprehensive,
|
||
IncludeDetails = true,
|
||
AutoHighlight = autoHighlight
|
||
});
|
||
}
|
||
|
||
/// <summary>
|
||
/// 将距离转换为米
|
||
/// </summary>
|
||
private double ConvertDistanceToMeters(double distance)
|
||
{
|
||
try
|
||
{
|
||
var conversionFactor = UnitsConverter.GetUnitsToMetersConversionFactor();
|
||
return distance * conversionFactor;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Warning($"距离单位转换失败: {ex.Message},使用原始值");
|
||
return distance;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 将3D点坐标转换为米
|
||
/// </summary>
|
||
private Point3D ConvertPointToMeters(Point3D point)
|
||
{
|
||
try
|
||
{
|
||
var conversionFactor = UnitsConverter.GetUnitsToMetersConversionFactor();
|
||
return new Point3D(
|
||
point.X * conversionFactor,
|
||
point.Y * conversionFactor,
|
||
point.Z * conversionFactor
|
||
);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Warning($"坐标单位转换失败: {ex.Message},使用原始值");
|
||
return point;
|
||
}
|
||
}
|
||
}
|
||
} |