From 6893b7efebd1f35c19efef32b012ff1b0ed5b143 Mon Sep 17 00:00:00 2001
From: tian <11429339@qq.com>
Date: Sun, 31 Aug 2025 15:45:21 +0800
Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E4=BA=86=E7=A2=B0=E6=92=9E?=
=?UTF-8?q?=E6=8A=A5=E5=91=8A?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/Commands/ViewCollisionReportCommand.cs | 258 ++++++++++++------
.../Collision/ClashDetectiveIntegration.cs | 40 +++
src/PathPlanning/VerticalScanProcessor.cs | 5 -
.../Converters/BoolToVisibilityConverter.cs | 62 ++++-
.../Converters/CountToVisibilityConverter.cs | 40 +++
.../ViewModels/AnimationControlViewModel.cs | 7 +-
.../ViewModels/CollisionReportViewModel.cs | 84 +++---
src/UI/WPF/Views/CollisionReportDialog.xaml | 50 ++--
src/Utils/NavisworksApiHelper.cs | 73 +++++
9 files changed, 441 insertions(+), 178 deletions(-)
diff --git a/src/Commands/ViewCollisionReportCommand.cs b/src/Commands/ViewCollisionReportCommand.cs
index 20ab4ce..363c628 100644
--- a/src/Commands/ViewCollisionReportCommand.cs
+++ b/src/Commands/ViewCollisionReportCommand.cs
@@ -12,6 +12,7 @@ using NavisworksTransport.Core;
using NavisworksTransport.PathPlanning;
using NavisworksTransport.Utils;
using NavisworksTransport.UI.WPF.Views;
+using NavisworksTransport.Core.Animation;
namespace NavisworksTransport.Commands
{
@@ -54,6 +55,17 @@ namespace NavisworksTransport.Commands
}
}
+ ///
+ /// 碰撞数据收集结果
+ ///
+ public class CollisionDataResult
+ {
+ public List AllCollisions { get; set; } = new List();
+ public int BoundingBoxTestCount { get; set; } // 包围盒测试数量
+ public int ClashDetectiveCollisionCount { get; set; } // Clash Detective结果数量
+ public string MovingObjectInfo { get; set; } = string.Empty;
+ }
+
///
/// 碰撞报告结果类
///
@@ -65,6 +77,7 @@ namespace NavisworksTransport.Commands
public int IndependentCollisions { get; set; }
public List AllCollisions { get; set; } = new List();
public long GenerationTimeMs { get; set; }
+ public string MovingObjectInfo { get; set; } = string.Empty;
}
///
@@ -99,33 +112,36 @@ namespace NavisworksTransport.Commands
{
UpdateProgress(30, "收集碰撞数据...");
- // 收集所有碰撞数据
- var allCollisions = CollectAllCollisionData();
- result.AllCollisions = allCollisions;
+ // 收集所有碰撞数据及统计信息
+ var collisionData = CollectAllCollisionData();
+ result.AllCollisions = collisionData.AllCollisions;
- // 分类统计
- result.AnimationCollisions = allCollisions.Count(c => c.DisplayName.Contains("动画") || c.DisplayName.Contains("精确碰撞"));
- result.IndependentCollisions = allCollisions.Count(c => c.DisplayName.Contains("独立检测"));
- result.TotalCollisions = allCollisions.Count;
+ // 直接使用收集到的统计数字,无需参数传递!
+ result.AnimationCollisions = collisionData.BoundingBoxTestCount; // 包围盒测试数量
+ result.IndependentCollisions = collisionData.ClashDetectiveCollisionCount; // Clash Detective结果数量
+ result.TotalCollisions = collisionData.ClashDetectiveCollisionCount; // 总数以权威结果为准
+ result.MovingObjectInfo = collisionData.MovingObjectInfo; // 运动物体信息
+
+ LogManager.Info($"碰撞报告计数 - 动画检测: {result.AnimationCollisions}, Clash Detective: {result.IndependentCollisions}, 总计: {result.TotalCollisions}");
UpdateProgress(60, "生成报告内容...");
// 生成报告内容
- result.ReportContent = GenerateReportContent(allCollisions, _parameters.Type, _parameters.IncludeDetails);
+ result.ReportContent = GenerateReportContent(collisionData, _parameters.Type, _parameters.IncludeDetails);
UpdateProgress(90, "处理报告显示...");
// 自动高亮(如果启用)
- if (_parameters.AutoHighlight && allCollisions.Count > 0)
+ if (_parameters.AutoHighlight && collisionData.AllCollisions.Count > 0)
{
try
{
- var clashIntegration = ClashDetectiveIntegration.Instance;
- if (clashIntegration != null)
+ var highlightIntegration = ClashDetectiveIntegration.Instance;
+ if (highlightIntegration != null)
{
var highlightColor = Color.Green; // 绿色 (Navisworks API中没有Orange)
- clashIntegration.ManageHighlightsByCategory("report", allCollisions, highlightColor, true);
- LogManager.Info($"自动高亮显示报告中的 {allCollisions.Count} 个碰撞对象");
+ highlightIntegration.ManageHighlightsByCategory("report", collisionData.AllCollisions, highlightColor, true);
+ LogManager.Info($"自动高亮显示报告中的 {collisionData.AllCollisions.Count} 个碰撞对象");
}
}
catch (Exception ex)
@@ -161,15 +177,19 @@ namespace NavisworksTransport.Commands
}
///
- /// 收集所有碰撞数据
+ /// 收集所有碰撞数据及统计信息
///
- private List CollectAllCollisionData()
+ private CollisionDataResult CollectAllCollisionData()
{
+ var result = new CollisionDataResult();
var allCollisions = new List();
try
{
- LogManager.Info("开始收集所有碰撞数据...");
+ LogManager.Info("开始收集所有碰撞数据及统计信息...");
+
+ // 收集运动物体信息
+ result.MovingObjectInfo = GetMovingObjectInfo();
var doc = Autodesk.Navisworks.Api.Application.ActiveDocument;
var documentClash = doc.GetClash();
@@ -177,16 +197,28 @@ namespace NavisworksTransport.Commands
if (documentClash == null)
{
LogManager.Warning("无法获取 Clash Detective 文档,无法收集碰撞数据");
- return allCollisions;
+ return result;
}
- // 遍历所有测试
+ int animationTestCount = 0; // 包围盒测试数量
+ int totalCollisionCount = 0; // Clash Detective总碰撞数
+
+ // 遍历所有测试,区分动画测试和统计信息
foreach (var test in documentClash.TestsData.Tests)
{
if (test is ClashTest clashTest)
{
var testCollisions = ExtractCollisionsFromTest(clashTest);
allCollisions.AddRange(testCollisions);
+
+ // 统计信息:如果是动画相关测试,记录包围盒测试数量
+ if (clashTest.DisplayName.Contains("动画路径碰撞"))
+ {
+ animationTestCount = documentClash.TestsData.Tests.Cast()
+ .Where(t => t.DisplayName.Contains("动画路径碰撞"))
+ .Count();
+ totalCollisionCount += clashTest.Children.Count;
+ }
}
}
@@ -196,14 +228,19 @@ namespace NavisworksTransport.Commands
.Select(g => g.First())
.ToList();
- LogManager.Info($"收集到 {allCollisions.Count} 个碰撞记录,去重后 {uniqueCollisions.Count} 个");
+ result.AllCollisions = uniqueCollisions;
+ result.BoundingBoxTestCount = animationTestCount;
+ result.ClashDetectiveCollisionCount = totalCollisionCount > 0 ? totalCollisionCount : uniqueCollisions.Count;
- return uniqueCollisions;
+ LogManager.Info($"收集完成 - 包围盒测试: {result.BoundingBoxTestCount}个, Clash Detective: {result.ClashDetectiveCollisionCount}个, 去重后碰撞: {uniqueCollisions.Count}个");
+
+ return result;
}
catch (Exception ex)
{
LogManager.Error($"收集碰撞数据失败: {ex.Message}");
- return allCollisions;
+ result.AllCollisions = allCollisions;
+ return result;
}
}
@@ -270,11 +307,12 @@ namespace NavisworksTransport.Commands
///
/// 生成报告内容
///
- private string GenerateReportContent(List collisions,
+ private string GenerateReportContent(CollisionDataResult collisionData,
CollisionReportParameters.ReportType reportType, bool includeDetails)
{
var report = new StringBuilder();
var now = DateTime.Now;
+ var collisions = collisionData.AllCollisions;
// 报告头部
report.AppendLine("========================================");
@@ -282,19 +320,21 @@ namespace NavisworksTransport.Commands
report.AppendLine("========================================");
report.AppendLine($"生成时间: {now:yyyy年MM月dd日 HH:mm:ss}");
report.AppendLine($"报告类型: {GetReportTypeName(reportType)}");
+
+ // 使用收集到的运动物体信息
+ if (!string.IsNullOrEmpty(collisionData.MovingObjectInfo))
+ {
+ report.AppendLine($"{collisionData.MovingObjectInfo}");
+ }
report.AppendLine();
// 总体统计
report.AppendLine("=== 总体统计 ===");
- report.AppendLine($"总碰撞数量: {collisions.Count}");
- var animationCollisions = collisions.Where(c => c.DisplayName.Contains("动画") || c.DisplayName.Contains("精确碰撞")).ToList();
- var independentCollisions = collisions.Where(c => c.DisplayName.Contains("独立检测")).ToList();
- var otherCollisions = collisions.Except(animationCollisions).Except(independentCollisions).ToList();
-
- report.AppendLine($"动画过程碰撞: {animationCollisions.Count}");
- report.AppendLine($"独立检测碰撞: {independentCollisions.Count}");
- report.AppendLine($"其他碰撞: {otherCollisions.Count}");
+ // 使用收集到的统计数字
+ report.AppendLine($"包围盒测试发现: {collisionData.BoundingBoxTestCount}个碰撞 (快速粗略检测结果)");
+ report.AppendLine($"Clash Detective确认: {collisionData.ClashDetectiveCollisionCount}个碰撞 (精确权威检测结果)");
+ report.AppendLine($"总碰撞数量: {collisionData.ClashDetectiveCollisionCount}个 (以权威结果为准)");
report.AppendLine();
// 按状态分类
@@ -317,56 +357,16 @@ namespace NavisworksTransport.Commands
{
report.AppendLine("=== 详细碰撞信息 ===");
- // 按类型分组显示
- if (reportType == CollisionReportParameters.ReportType.Comprehensive ||
- reportType == CollisionReportParameters.ReportType.Animation)
+ report.AppendLine("--- 碰撞详情 ---");
+ foreach (var collision in collisions.Take(10)) // 限制显示数量
{
- if (animationCollisions.Count > 0)
- {
- report.AppendLine("--- 动画过程碰撞 ---");
- foreach (var collision in animationCollisions.Take(10)) // 限制显示数量
- {
- AppendCollisionDetail(report, collision);
- }
- if (animationCollisions.Count > 10)
- {
- report.AppendLine($"... 还有 {animationCollisions.Count - 10} 个动画碰撞未显示");
- }
- report.AppendLine();
- }
+ AppendCollisionDetail(report, collision);
}
-
- if (reportType == CollisionReportParameters.ReportType.Comprehensive ||
- reportType == CollisionReportParameters.ReportType.Independent)
+ if (collisions.Count > 10)
{
- if (independentCollisions.Count > 0)
- {
- report.AppendLine("--- 独立检测碰撞 ---");
- foreach (var collision in independentCollisions.Take(10)) // 限制显示数量
- {
- AppendCollisionDetail(report, collision);
- }
- if (independentCollisions.Count > 10)
- {
- report.AppendLine($"... 还有 {independentCollisions.Count - 10} 个独立检测碰撞未显示");
- }
- report.AppendLine();
- }
- }
-
- if (otherCollisions.Count > 0)
- {
- report.AppendLine("--- 其他碰撞 ---");
- foreach (var collision in otherCollisions.Take(5))
- {
- AppendCollisionDetail(report, collision);
- }
- if (otherCollisions.Count > 5)
- {
- report.AppendLine($"... 还有 {otherCollisions.Count - 5} 个其他碰撞未显示");
- }
- report.AppendLine();
+ report.AppendLine($"... 还有 {collisions.Count - 10} 个碰撞未显示");
}
+ report.AppendLine();
}
// 建议和结论
@@ -383,14 +383,7 @@ namespace NavisworksTransport.Commands
report.AppendLine(" 3. 考虑增加临时障碍物标记");
report.AppendLine(" 4. 重新评估物流流程设计");
- if (animationCollisions.Count > independentCollisions.Count)
- {
- report.AppendLine(" 5. 动画过程碰撞较多,建议检查实时检测设置");
- }
- else if (independentCollisions.Count > animationCollisions.Count)
- {
- report.AppendLine(" 5. 独立检测发现更多碰撞,建议增强实时监控");
- }
+ report.AppendLine(" 5. 建议进行更详细的碰撞检测分析");
}
report.AppendLine();
@@ -409,9 +402,15 @@ namespace NavisworksTransport.Commands
var item1Name = collision.Item1?.DisplayName ?? "未知对象";
var item2Name = collision.Item2?.DisplayName ?? "未知对象";
+ // 转换距离单位为米
+ var distanceInMeters = ConvertDistanceToMeters(collision.Distance);
+
report.AppendLine($"• {item1Name} ↔ {item2Name}");
- report.AppendLine($" 状态: {GetStatusName(collision.Status)}, 距离: {collision.Distance:F3}m");
- report.AppendLine($" 位置: ({collision.Center.X:F2}, {collision.Center.Y:F2}, {collision.Center.Z:F2})");
+ 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();
}
@@ -593,5 +592,92 @@ namespace NavisworksTransport.Commands
AutoHighlight = autoHighlight
});
}
+
+ ///
+ /// 获取运动物体信息
+ ///
+ private string GetMovingObjectInfo()
+ {
+ try
+ {
+ LogManager.Debug("[GetMovingObjectInfo] 开始获取运动物体信息");
+
+ // 尝试获取当前选中的模型项作为运动对象
+ var doc = Autodesk.Navisworks.Api.Application.ActiveDocument;
+ LogManager.Debug($"[GetMovingObjectInfo] 文档: {doc != null}, 选择: {doc?.CurrentSelection != null}");
+
+ if (doc?.CurrentSelection?.SelectedItems?.Count > 0)
+ {
+ var selectedItems = doc.CurrentSelection.SelectedItems;
+ LogManager.Debug($"[GetMovingObjectInfo] 选中项数量: {selectedItems.Count}");
+
+ if (selectedItems.Count == 1)
+ {
+ var item = selectedItems.First();
+ var displayName = item?.DisplayName ?? "未知对象";
+ LogManager.Debug($"[GetMovingObjectInfo] 单个对象名称: '{displayName}'");
+ return $"运动对象: {displayName}";
+ }
+ else
+ {
+ var displayNames = selectedItems.Take(3).Select(item => item?.DisplayName ?? "未知对象");
+ var summary = string.Join(", ", displayNames);
+ if (selectedItems.Count > 3)
+ {
+ summary += $" 等{selectedItems.Count}个对象";
+ }
+ LogManager.Debug($"[GetMovingObjectInfo] 多个对象摘要: '{summary}'");
+ return $"运动对象: {summary}";
+ }
+ }
+
+ LogManager.Debug("[GetMovingObjectInfo] 未选择对象,返回默认信息");
+ return "运动对象: 物流运输对象 (建议先选择要运动的模型元素)";
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error($"获取运动物体信息失败: {ex.Message}");
+ return "运动对象: 获取信息失败";
+ }
+ }
+
+
+ ///
+ /// 将距离转换为米
+ ///
+ private double ConvertDistanceToMeters(double distance)
+ {
+ try
+ {
+ var conversionFactor = UnitsConverter.GetUnitsToMetersConversionFactor();
+ return distance * conversionFactor;
+ }
+ catch (Exception ex)
+ {
+ LogManager.Warning($"距离单位转换失败: {ex.Message},使用原始值");
+ return distance;
+ }
+ }
+
+ ///
+ /// 将3D点坐标转换为米
+ ///
+ 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;
+ }
+ }
}
}
\ No newline at end of file
diff --git a/src/Core/Collision/ClashDetectiveIntegration.cs b/src/Core/Collision/ClashDetectiveIntegration.cs
index ff99bef..9f79fef 100644
--- a/src/Core/Collision/ClashDetectiveIntegration.cs
+++ b/src/Core/Collision/ClashDetectiveIntegration.cs
@@ -29,6 +29,26 @@ namespace NavisworksTransport
// 几何对象列表缓存,用于避免重复获取对象列表
private static List _allGeometryItemsCache = null;
+
+ // 碰撞检测计数器
+ private int _animationCollisionCount = 0; // 动画过程中简单包围盒检测的碰撞数量
+ private int _clashDetectiveCollisionCount = 0; // Clash Detective最终检测的碰撞数量
+
+ ///
+ /// 动画过程中检测到的碰撞数量(仅供参考统计)
+ ///
+ public int AnimationCollisionCount
+ {
+ get { return _animationCollisionCount; }
+ }
+
+ ///
+ /// Clash Detective检测到的权威碰撞数量
+ ///
+ public int ClashDetectiveCollisionCount
+ {
+ get { return _clashDetectiveCollisionCount; }
+ }
///
/// 单例实例
@@ -839,6 +859,22 @@ namespace NavisworksTransport
LogManager.Error($"动画结束后自动高亮失败: {highlightEx.Message}");
}
+ // 更新Clash Detective碰撞计数器 - 统计实际创建的测试数量
+ var finalClashDetectiveCount = 0;
+ if (_documentClash != null)
+ {
+ // 计算所有动画相关测试的碰撞总数
+ var animationTests = _documentClash.TestsData.Tests.Cast()
+ .Where(t => t.DisplayName.Contains("动画路径碰撞") || t.DisplayName.Contains("动画碰撞"))
+ .ToList();
+
+ finalClashDetectiveCount = animationTests.Sum(t => t.Children.Count);
+ LogManager.Info($"统计Clash Detective最终碰撞数量: {animationTests.Count}个测试,总共{finalClashDetectiveCount}个碰撞");
+ }
+
+ _clashDetectiveCollisionCount = finalClashDetectiveCount;
+ LogManager.Info($"Clash Detective碰撞计数器已更新: {_clashDetectiveCollisionCount}");
+
// 清空缓存
_cachedResults.Clear();
LogManager.Info("=== 动画碰撞测试(位置恢复方案)完成 ===");
@@ -2247,6 +2283,10 @@ namespace NavisworksTransport
{
LogManager.Info($"未发现碰撞");
}
+
+ // 更新动画碰撞计数器
+ _animationCollisionCount = results.Count;
+ LogManager.Info($"动画碰撞计数器已更新: {_animationCollisionCount}");
}
catch (Exception ex)
{
diff --git a/src/PathPlanning/VerticalScanProcessor.cs b/src/PathPlanning/VerticalScanProcessor.cs
index d8aa550..d90cc25 100644
--- a/src/PathPlanning/VerticalScanProcessor.cs
+++ b/src/PathPlanning/VerticalScanProcessor.cs
@@ -95,11 +95,6 @@ namespace NavisworksTransport.PathPlanning
// 统计变量
var totalItems = modelItems?.Count() ?? 0;
- var itemsWithGeometry = 0;
- var channelItemsExcluded = 0;
- var itemsWithoutBounds = 0;
- var itemsOutOfBounds = 0;
- var itemsAddedToHash = 0;
LogManager.Info($"【垂直扫描处理器】 输入统计 - 总模型项: {totalItems}, 将排除通道元素: {channelItemsSet.Count}");
LogManager.Info($"【垂直扫描处理器】 扫描边界: [{bounds.Min.X:F1},{bounds.Min.Y:F1},{bounds.Min.Z:F1}] - [{bounds.Max.X:F1},{bounds.Max.Y:F1},{bounds.Max.Z:F1}]");
diff --git a/src/UI/WPF/Converters/BoolToVisibilityConverter.cs b/src/UI/WPF/Converters/BoolToVisibilityConverter.cs
index 058bde9..bcbe431 100644
--- a/src/UI/WPF/Converters/BoolToVisibilityConverter.cs
+++ b/src/UI/WPF/Converters/BoolToVisibilityConverter.cs
@@ -8,6 +8,13 @@ namespace NavisworksTransport.UI.WPF.Converters
///
/// 布尔值到可见性的转换器
///
+ ///
+ /// 通用值到可见性转换器
+ /// - 布尔值:true/false → Visible/Collapsed
+ /// - 字符串:非空非白字符 → Visible,空/null → Collapsed
+ /// - 数字:非零 → Visible,零 → Collapsed
+ /// - 对象:非null → Visible,null → Collapsed
+ ///
public class BoolToVisibilityConverter : IValueConverter
{
///
@@ -17,21 +24,52 @@ namespace NavisworksTransport.UI.WPF.Converters
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
+ bool isVisible = false;
+
+ // 处理布尔值
if (value is bool boolValue)
{
- // 检查是否需要反向转换
- bool isInverse = parameter?.ToString()?.Equals("Inverse", StringComparison.OrdinalIgnoreCase) == true;
-
- if (isInverse)
- {
- return boolValue ? Visibility.Collapsed : Visibility.Visible;
- }
- else
- {
- return boolValue ? Visibility.Visible : Visibility.Collapsed;
- }
+ isVisible = boolValue;
+ }
+ // 处理字符串 - 非空非白字符字符串为true
+ else if (value is string stringValue)
+ {
+ isVisible = !string.IsNullOrWhiteSpace(stringValue);
+ }
+ // 处理数字类型
+ else if (value is int intValue)
+ {
+ isVisible = intValue != 0;
+ }
+ else if (value is long longValue)
+ {
+ isVisible = longValue != 0;
+ }
+ else if (value is double doubleValue)
+ {
+ isVisible = Math.Abs(doubleValue) > double.Epsilon;
+ }
+ else if (value is float floatValue)
+ {
+ isVisible = Math.Abs(floatValue) > float.Epsilon;
+ }
+ // 处理其他对象 - 非null为true
+ else
+ {
+ isVisible = value != null;
+ }
+
+ // 检查是否需要反向转换
+ bool isInverse = parameter?.ToString()?.Equals("Inverse", StringComparison.OrdinalIgnoreCase) == true;
+
+ if (isInverse)
+ {
+ return isVisible ? Visibility.Collapsed : Visibility.Visible;
+ }
+ else
+ {
+ return isVisible ? Visibility.Visible : Visibility.Collapsed;
}
- return Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
diff --git a/src/UI/WPF/Converters/CountToVisibilityConverter.cs b/src/UI/WPF/Converters/CountToVisibilityConverter.cs
index c4f52ea..7980e91 100644
--- a/src/UI/WPF/Converters/CountToVisibilityConverter.cs
+++ b/src/UI/WPF/Converters/CountToVisibilityConverter.cs
@@ -82,4 +82,44 @@ namespace NavisworksTransport.UI.WPF.Converters
return true;
}
}
+
+ ///
+ /// 布尔值到可见性转换器(标准命名)
+ ///
+ ///
+ /// 严格布尔值到可见性转换器(只接受布尔值)
+ ///
+ public class BooleanToVisibilityConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ // 只接受严格的布尔值
+ if (value is bool boolValue)
+ {
+ // 检查是否需要反向转换
+ bool isInverse = parameter?.ToString()?.Equals("Inverse", StringComparison.OrdinalIgnoreCase) == true;
+
+ if (isInverse)
+ {
+ return boolValue ? Visibility.Collapsed : Visibility.Visible;
+ }
+ else
+ {
+ return boolValue ? Visibility.Visible : Visibility.Collapsed;
+ }
+ }
+
+ // 非布尔值直接返回Collapsed
+ return Visibility.Collapsed;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (value is Visibility visibility)
+ {
+ return visibility == Visibility.Visible;
+ }
+ return false;
+ }
+ }
}
\ No newline at end of file
diff --git a/src/UI/WPF/ViewModels/AnimationControlViewModel.cs b/src/UI/WPF/ViewModels/AnimationControlViewModel.cs
index a31469c..1a6ab83 100644
--- a/src/UI/WPF/ViewModels/AnimationControlViewModel.cs
+++ b/src/UI/WPF/ViewModels/AnimationControlViewModel.cs
@@ -963,7 +963,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
if (success)
{
var cacheStats = _logisticsAnimationManager.GetCacheStats();
- GenerationStatus = $"动画对象分析完成 - {cacheStats}";
+ GenerationStatus = $"动画对象分析完成";
LogManager.Info($"[缓存预计算] 预计算成功 - {cacheStats}");
}
else
@@ -1348,7 +1348,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
if (reportData.IsValid)
{
- CollisionSummary = $"共找到 {reportData.TotalTests} 个测试,{reportData.TotalCollisions} 个碰撞点";
+ // 直接使用报告数据统计
+ CollisionSummary = $"动画检测: {reportData.TotalTests}个 | Clash Detective权威结果: {reportData.TotalCollisions}个";
}
else
{
@@ -1362,7 +1363,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 调用ViewCollisionReportCommand显示详细报告窗口
try
{
- // 创建综合碰撞报告命令并执行
+ // 创建综合碰撞报告命令(现在不需要传递参数了!)
var reportCommand = NavisworksTransport.Commands.ViewCollisionReportCommand.CreateComprehensive(autoHighlight: false);
// 执行命令,UI显示会在正确的线程中处理
diff --git a/src/UI/WPF/ViewModels/CollisionReportViewModel.cs b/src/UI/WPF/ViewModels/CollisionReportViewModel.cs
index 0fb2354..e85eaf2 100644
--- a/src/UI/WPF/ViewModels/CollisionReportViewModel.cs
+++ b/src/UI/WPF/ViewModels/CollisionReportViewModel.cs
@@ -12,6 +12,7 @@ using System.IO;
using System.Text;
using Microsoft.Win32;
using System.Threading.Tasks;
+using Autodesk.Navisworks.Api;
namespace NavisworksTransport.UI.WPF.ViewModels
{
@@ -51,7 +52,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
public int TotalCollisions { get; set; }
public int AnimationCollisions { get; set; }
public int IndependentCollisions { get; set; }
- public int OtherCollisions { get; set; }
public int NewCollisions { get; set; }
public int ActiveCollisions { get; set; }
public int ReviewedCollisions { get; set; }
@@ -73,13 +73,13 @@ namespace NavisworksTransport.UI.WPF.ViewModels
private CollisionReportStatistics _statistics;
private ObservableCollection _animationCollisions;
private ObservableCollection _independentCollisions;
- private ObservableCollection _otherCollisions;
private string _progressMessage;
private int _progressPercentage;
private bool _isGenerating;
private bool _hasCollisions;
private string _summaryMessage;
private string _recommendationMessage;
+ private string _movingObjectInfo;
#endregion
@@ -130,14 +130,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
set => SetProperty(ref _independentCollisions, value);
}
- ///
- /// 其他碰撞列表
- ///
- public ObservableCollection OtherCollisions
- {
- get => _otherCollisions;
- set => SetProperty(ref _otherCollisions, value);
- }
///
/// 进度消息
@@ -193,6 +185,15 @@ namespace NavisworksTransport.UI.WPF.ViewModels
set => SetProperty(ref _recommendationMessage, value);
}
+ ///
+ /// 运动物体信息
+ ///
+ public string MovingObjectInfo
+ {
+ get => _movingObjectInfo;
+ set => SetProperty(ref _movingObjectInfo, value);
+ }
+
#endregion
#region 命令属性
@@ -226,7 +227,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 初始化集合
AnimationCollisions = new ObservableCollection();
IndependentCollisions = new ObservableCollection();
- OtherCollisions = new ObservableCollection();
Statistics = new CollisionReportStatistics();
@@ -269,7 +269,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 清空现有数据
AnimationCollisions.Clear();
IndependentCollisions.Clear();
- OtherCollisions.Clear();
+
+ // 设置运动物体信息
+ MovingObjectInfo = reportResult.MovingObjectInfo;
// 更新统计信息
UpdateStatistics(reportResult);
@@ -328,7 +330,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
TotalCollisions = reportResult.TotalCollisions,
AnimationCollisions = reportResult.AnimationCollisions,
IndependentCollisions = reportResult.IndependentCollisions,
- OtherCollisions = reportResult.TotalCollisions - reportResult.AnimationCollisions - reportResult.IndependentCollisions,
GenerationTime = $"{reportResult.GenerationTimeMs}ms",
ReportType = "综合碰撞报告"
};
@@ -352,39 +353,20 @@ namespace NavisworksTransport.UI.WPF.ViewModels
if (collisions == null || collisions.Count == 0)
return;
- var animationList = new List();
var independentList = new List();
- var otherList = new List();
foreach (var collision in collisions)
{
var item = CreateCollisionReportItem(collision);
-
- if (collision.DisplayName.Contains("动画") || collision.DisplayName.Contains("精确碰撞"))
- {
- animationList.Add(item);
- }
- else if (collision.DisplayName.Contains("独立检测"))
- {
- independentList.Add(item);
- }
- else
- {
- otherList.Add(item);
- }
+ independentList.Add(item);
}
// 更新UI集合
SafeExecute(() =>
{
- foreach (var item in animationList.OrderBy(i => i.Title))
- AnimationCollisions.Add(item);
-
foreach (var item in independentList.OrderBy(i => i.Title))
IndependentCollisions.Add(item);
- foreach (var item in otherList.OrderBy(i => i.Title))
- OtherCollisions.Add(item);
}, "更新碰撞报告项目列表", true);
}
@@ -393,20 +375,27 @@ namespace NavisworksTransport.UI.WPF.ViewModels
///
private CollisionReportItem CreateCollisionReportItem(CollisionResult collision)
{
- var item1Name = collision.Item1?.DisplayName ?? "未知对象";
- var item2Name = collision.Item2?.DisplayName ?? "未知对象";
- return new CollisionReportItem
+ // 获取元素名称 - 向上
+ var item1Name = NavisworksApiHelper.GetModelItemNameWithAncestorFallback(collision.Item1);
+ var item2Name = NavisworksApiHelper.GetModelItemNameWithAncestorFallback(collision.Item2);
+
+ var title = $"{item1Name} ↔ {item2Name}";
+
+ var item = new CollisionReportItem
{
- Title = $"{item1Name} ↔ {item2Name}",
- Description = collision.DisplayName,
+ Title = string.IsNullOrEmpty(title.Trim().Replace("↔", "").Trim()) ? "【空标题测试】" : title,
+ Description = collision.DisplayName ?? "【空描述测试】",
StatusText = GetStatusDisplayText(collision.Status),
StatusColor = GetStatusColor(collision.Status),
Details = $"距离: {collision.Distance:F3}m\n位置: ({collision.Center.X:F2}, {collision.Center.Y:F2}, {collision.Center.Z:F2})\nGUID: {collision.ClashGuid}",
CollisionData = collision
};
+
+ return item;
}
+
///
/// 获取状态显示文本
///
@@ -486,6 +475,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
}
+
///
/// 设置空报告状态
///
@@ -579,14 +569,12 @@ namespace NavisworksTransport.UI.WPF.ViewModels
report.AppendLine("========================================");
report.AppendLine($"生成时间: {now:yyyy年MM月dd日 HH:mm:ss}");
report.AppendLine($"报告类型: {Statistics.ReportType}");
- report.AppendLine();
-
+
// 总体统计
report.AppendLine("=== 总体统计 ===");
- report.AppendLine($"总碰撞数量: {Statistics.TotalCollisions}");
- report.AppendLine($"动画过程碰撞: {Statistics.AnimationCollisions}");
- report.AppendLine($"独立检测碰撞: {Statistics.IndependentCollisions}");
- report.AppendLine($"其他碰撞: {Statistics.OtherCollisions}");
+ report.AppendLine($"碰撞数量: {Statistics.TotalCollisions}");
+ report.AppendLine($"动画检测碰撞(参考): {Statistics.AnimationCollisions}");
+ report.AppendLine($"ClashDetective检测碰撞: {Statistics.IndependentCollisions}");
report.AppendLine();
// 按状态分类
@@ -598,12 +586,18 @@ namespace NavisworksTransport.UI.WPF.ViewModels
report.AppendLine($"已解决: {Statistics.ResolvedCollisions}");
report.AppendLine();
+ // 运动物体信息
+ if (!string.IsNullOrEmpty(MovingObjectInfo))
+ {
+ report.AppendLine($"{MovingObjectInfo}");
+ }
+ report.AppendLine();
+
// 详细碰撞信息
if (HasCollisions)
{
AddCollisionDetailsToTextReport(report, "动画过程碰撞", AnimationCollisions);
AddCollisionDetailsToTextReport(report, "独立检测碰撞", IndependentCollisions);
- AddCollisionDetailsToTextReport(report, "其他碰撞", OtherCollisions);
}
// 总结和建议
diff --git a/src/UI/WPF/Views/CollisionReportDialog.xaml b/src/UI/WPF/Views/CollisionReportDialog.xaml
index 71bc75e..bf15e62 100644
--- a/src/UI/WPF/Views/CollisionReportDialog.xaml
+++ b/src/UI/WPF/Views/CollisionReportDialog.xaml
@@ -135,7 +135,7 @@ NavisworksTransport 碰撞检测报告对话框 - 采用与主界面一致的Nav
-
+
@@ -191,7 +191,7 @@ NavisworksTransport 碰撞检测报告对话框 - 采用与主界面一致的Nav
-
+
@@ -222,16 +222,6 @@ NavisworksTransport 碰撞检测报告对话框 - 采用与主界面一致的Nav
-
-
-
-
-
-
-
-
-
-
@@ -269,6 +259,27 @@ NavisworksTransport 碰撞检测报告对话框 - 采用与主界面一致的Nav
+
+
+
+
+
+
+
+
@@ -288,14 +299,6 @@ NavisworksTransport 碰撞检测报告对话框 - 采用与主界面一致的Nav
-
-
-
-
-
-
@@ -304,13 +307,6 @@ NavisworksTransport 碰撞检测报告对话框 - 采用与主界面一致的Nav
Margin="0,0,0,10"/>
-
-
-
-
-
diff --git a/src/Utils/NavisworksApiHelper.cs b/src/Utils/NavisworksApiHelper.cs
index 9cd4401..d30be14 100644
--- a/src/Utils/NavisworksApiHelper.cs
+++ b/src/Utils/NavisworksApiHelper.cs
@@ -97,5 +97,78 @@ namespace NavisworksTransport.Utils
System.Windows.Application.Current.Dispatcher.Invoke(operation);
}
}
+
+ ///
+ /// 获取ModelItem的显示名称,支持向上溯源父节点
+ /// 如果当前节点没有名称,会向上查找父节点直到找到有名称的节点
+ ///
+ /// 要获取名称的ModelItem
+ /// 最大向上查找深度,防止无限递归
+ /// 元素的显示名称
+ public static string GetModelItemNameWithAncestorFallback(ModelItem item, int maxDepth = 10)
+ {
+ if (item == null) return "未知对象";
+
+ try
+ {
+ var current = item;
+ int depth = 0;
+
+ while (current != null && depth < maxDepth)
+ {
+ // 只查找DisplayName
+ if (!string.IsNullOrEmpty(current.DisplayName))
+ {
+ return current.DisplayName;
+ }
+
+ // 向上一级父节点继续查找
+ current = current.Parent;
+ depth++;
+ }
+
+ // 如果所有父节点都没有DisplayName,返回默认名称
+ LogManager.Debug($"[元素名称获取] 向上查找{depth}层后仍未找到DisplayName,返回默认名称");
+ return depth > 0 ? "未命名对象(已溯源)" : "未命名对象";
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error($"获取ModelItem DisplayName失败: {ex.Message}");
+ return "获取失败";
+ }
+ }
+
+ ///
+ /// 获取ModelItem的直接显示名称(不溯源父节点)
+ /// 仅从当前节点获取名称,适用于不需要父节点信息的场景
+ ///
+ /// 要获取名称的ModelItem
+ /// 元素的显示名称
+ public static string GetModelItemName(ModelItem item)
+ {
+ if (item == null) return "未知对象";
+
+ try
+ {
+ // 1. 尝试DisplayName
+ if (!string.IsNullOrEmpty(item.DisplayName))
+ {
+ return item.DisplayName;
+ }
+
+ // 2. 尝试ClassDisplayName
+ if (!string.IsNullOrEmpty(item.ClassDisplayName))
+ {
+ return item.ClassDisplayName;
+ }
+
+ return "未命名对象";
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error($"获取ModelItem名称失败: {ex.Message}");
+ return "获取失败";
+ }
+ }
}
}
\ No newline at end of file