diff --git a/src/Core/Animation/PathAnimationManager.cs b/src/Core/Animation/PathAnimationManager.cs index af71c55..d12d6c6 100644 --- a/src/Core/Animation/PathAnimationManager.cs +++ b/src/Core/Animation/PathAnimationManager.cs @@ -2440,7 +2440,7 @@ namespace NavisworksTransport.Core.Animation else { // 无碰撞:清除碰撞高亮(保留车辆高亮) - ModelHighlightHelper.ClearCategory(ModelHighlightHelper.CollisionResultsCategory); + ModelHighlightHelper.ClearCategory(ModelHighlightHelper.PrecomputeCollisionResultsCategory); LogManager.Debug($"[高亮状态] 帧{_currentFrameIndex}: 清除碰撞高亮"); } diff --git a/src/Core/Collision/ClashDetectiveIntegration.cs b/src/Core/Collision/ClashDetectiveIntegration.cs index f1e3d38..a435709 100644 --- a/src/Core/Collision/ClashDetectiveIntegration.cs +++ b/src/Core/Collision/ClashDetectiveIntegration.cs @@ -17,7 +17,7 @@ namespace NavisworksTransport public class ClashDetectiveIntegration { private static ClashDetectiveIntegration _instance; - private const string CollisionHighlightsCategory = ModelHighlightHelper.CollisionResultsCategory; + private const string CollisionHighlightsCategory = ModelHighlightHelper.PrecomputeCollisionResultsCategory; private DocumentClash _documentClash; private List _currentCollisions; diff --git a/src/UI/WPF/ViewModels/AnimationControlViewModel.cs b/src/UI/WPF/ViewModels/AnimationControlViewModel.cs index c5ab126..d21bc62 100644 --- a/src/UI/WPF/ViewModels/AnimationControlViewModel.cs +++ b/src/UI/WPF/ViewModels/AnimationControlViewModel.cs @@ -77,30 +77,78 @@ namespace NavisworksTransport.UI.WPF.ViewModels public Guid InstanceGuid { get; } } + /// + /// 碰撞构件ViewModel + /// + public class CollisionObjectViewModel + { + public int Index { get; set; } + public string DisplayName { get; set; } + public string ObjectName { get; set; } + public string ModelPath { get; set; } + public int ResultId { get; set; } + public string TestName { get; set; } + public int? ModelIndex { get; set; } + public string PathId { get; set; } + public ModelItem ModelItem { get; set; } + public ICommand HighlightCommand { get; set; } + public ICommand ClearHighlightCommand { get; set; } + } + /// /// ClashDetective碰撞检测结果视图模型 /// public class ClashDetectiveResultViewModel - { - private readonly Action _refreshCallback; - - public ClashDetectiveResultViewModel(ClashDetectiveResultRecord record, Action refreshCallback) { - Record = record ?? throw new ArgumentNullException(nameof(record)); - _refreshCallback = refreshCallback ?? throw new ArgumentNullException(nameof(refreshCallback)); - ViewCommand = new RelayCommand(() => ExecuteView()); - ReportCommand = new RelayCommand(() => ExecuteReport()); - DeleteCommand = new RelayCommand(() => ExecuteDelete()); - } + private readonly Action _refreshCallback; + + public ClashDetectiveResultViewModel(ClashDetectiveResultRecord record, Action refreshCallback) + { + Record = record ?? throw new ArgumentNullException(nameof(record)); + _refreshCallback = refreshCallback ?? throw new ArgumentNullException(nameof(refreshCallback)); + ViewCommand = new RelayCommand(() => ExecuteView()); + ReportCommand = new RelayCommand(() => ExecuteReport()); + DeleteCommand = new RelayCommand(() => ExecuteDelete()); + CollisionObjects = new ObservableCollection(); + } + + public ClashDetectiveResultRecord Record { get; } + public string TestTimeDisplay => Record.TestTime.ToString("MM-dd HH:mm:ss"); + public string CollisionCountDisplay => $"{Record.CollisionCount}个"; + public ICommand ViewCommand { get; } + public ICommand ReportCommand { get; } + public ICommand DeleteCommand { get; } + public ObservableCollection CollisionObjects { get; } + + public void ExecuteHighlightCollisionObject(CollisionObjectViewModel collisionObject) + { + if (collisionObject == null) return; - public ClashDetectiveResultRecord Record { get; } - public string TestTimeDisplay => Record.TestTime.ToString("MM-dd HH:mm:ss"); - public string CollisionCountDisplay => $"{Record.CollisionCount}个"; - public ICommand ViewCommand { get; } - public ICommand ReportCommand { get; } - public ICommand DeleteCommand { get; } + try + { + LogManager.Info($"[碰撞构件] 高亮显示构件: {collisionObject.DisplayName}"); - private void ExecuteView() + // 清除之前的高亮 + ModelHighlightHelper.ClearAllHighlights(); + + // 直接使用ModelItem高亮 + if (collisionObject.ModelItem != null && ModelItemAnalysisHelper.IsModelItemValid(collisionObject.ModelItem)) + { + ModelHighlightHelper.HighlightItems( + ModelHighlightHelper.ClashDetectiveResultsCategory, + new[] { collisionObject.ModelItem }); + LogManager.Info($"[碰撞构件] 已高亮构件: {collisionObject.DisplayName}"); + } + else + { + LogManager.Warning($"[碰撞构件] ModelItem无效或为空: {collisionObject.DisplayName}"); + } + } + catch (Exception ex) + { + LogManager.Error($"[碰撞构件] 高亮显示失败: {ex.Message}", ex); + } + } private void ExecuteView() { // 高亮显示该次检测的碰撞对象 var clashIntegration = ClashDetectiveIntegration.Instance; @@ -191,7 +239,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels private DateTime? _manualTargetsLastSyncTime; private const int ManualCollisionTargetLimit = 60; private const string ManualTargetsHighlightCategory = ModelHighlightHelper.ManualTargetsCategory; - private const string CollisionResultsHighlightCategory = ModelHighlightHelper.CollisionResultsCategory; + private const string CollisionResultsHighlightCategory = ModelHighlightHelper.PrecomputeCollisionResultsCategory; #endregion @@ -596,13 +644,29 @@ namespace NavisworksTransport.UI.WPF.ViewModels #region ClashDetective结果管理 private ObservableCollection _clashDetectiveResults = new ObservableCollection(); + private ClashDetectiveResultViewModel _selectedClashDetectiveResult; public ObservableCollection ClashDetectiveResults => _clashDetectiveResults; + public ClashDetectiveResultViewModel SelectedClashDetectiveResult + { + get => _selectedClashDetectiveResult; + set + { + if (_selectedClashDetectiveResult != value) + { + _selectedClashDetectiveResult = value; + OnPropertyChanged(); + } + } + } + public ICommand RefreshClashDetectiveResultsCommand { get; private set; } #endregion + + #region 媒体控制属性 /// @@ -753,6 +817,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels DocumentStateManager.Instance.DocumentInvalidated += OnDocumentInvalidated; DocumentStateManager.Instance.DocumentReady += OnDocumentReady; + // 设置静态实例 + _instance = this; + LogManager.Info("AnimationControlViewModel初始化完成 - 支持统一状态栏"); } catch (Exception ex) @@ -1770,7 +1837,61 @@ namespace NavisworksTransport.UI.WPF.ViewModels foreach (var record in records) { - _clashDetectiveResults.Add(new ClashDetectiveResultViewModel(record, RefreshClashDetectiveResultsList)); + var resultViewModel = new ClashDetectiveResultViewModel(record, RefreshClashDetectiveResultsList); + + // 同时加载该结果的碰撞构件清单 + var collisionObjectRecords = pathDatabase.GetClashDetectiveCollisionObjects(record.Id); + if (collisionObjectRecords != null) + { + int index = 1; + foreach (var objRecord in collisionObjectRecords) + { + CollisionObjectViewModel objViewModel = null; + ModelItem modelItem = null; + string modelPath = "路径获取失败"; + + // 通过 ModelIndex 和 PathId 重建 ModelItem + if (objRecord.ModelIndex.HasValue && !string.IsNullOrEmpty(objRecord.PathId)) + { + try + { + var pathIdObj = new Autodesk.Navisworks.Api.DocumentParts.ModelItemPathId + { + ModelIndex = objRecord.ModelIndex.Value, + PathId = objRecord.PathId + }; + modelItem = Application.ActiveDocument.Models.ResolvePathId(pathIdObj); + + // 获取完整的节点树路径 + if (modelItem != null) + { + modelPath = BuildModelPath(modelItem); + } + } + catch (Exception ex) + { + LogManager.Warning($"[碰撞构件] 无法通过 PathId 找到 ModelItem: ModelIndex={objRecord.ModelIndex}, PathId={objRecord.PathId}, 错误: {ex.Message}"); + } + } + + objViewModel = new CollisionObjectViewModel + { + Index = index++, + DisplayName = objRecord.DisplayName, + ObjectName = objRecord.ObjectName, + ModelPath = modelPath, + ResultId = objRecord.ResultId, + TestName = record.TestName, + ModelIndex = objRecord.ModelIndex, + PathId = objRecord.PathId, + ModelItem = modelItem, + HighlightCommand = new RelayCommand(() => resultViewModel.ExecuteHighlightCollisionObject(objViewModel)) + }; + resultViewModel.CollisionObjects.Add(objViewModel); + } + } + + _clashDetectiveResults.Add(resultViewModel); } // 更新HasClashDetectiveResults属性 diff --git a/src/UI/WPF/Views/AnimationControlView.xaml b/src/UI/WPF/Views/AnimationControlView.xaml index 7035e0e..959eb28 100644 --- a/src/UI/WPF/Views/AnimationControlView.xaml +++ b/src/UI/WPF/Views/AnimationControlView.xaml @@ -432,7 +432,9 @@ NavisworksTransport 检测动画页签视图 - 采用与类别设置和分层管 MinHeight="120" MaxHeight="200" BorderBrush="#FFE2E8F0" - BorderThickness="1"> + BorderThickness="1" + SelectionMode="Single" + SelectionChanged="OnClashDetectiveResultSelectionChanged"> @@ -461,7 +463,7 @@ NavisworksTransport 检测动画页签视图 - 采用与类别设置和分层管 - + @@ -495,7 +497,73 @@ NavisworksTransport 检测动画页签视图 - 采用与类别设置和分层管 - + + + + + + + + + + public static class ModelHighlightHelper { - public const string CollisionResultsCategory = "collisionResults"; + public const string PrecomputeCollisionResultsCategory = "collisionResults"; public const string ManualTargetsCategory = "manualTargets"; public const string ChannelPreviewCategory = "channelPreview"; public const string ClashDetectiveResultsCategory = "clashDetectiveResults"; @@ -43,7 +43,7 @@ namespace NavisworksTransport.Utils { "report", Color.Green }, { "preview", Color.Blue }, { ManualTargetsCategory, Color.FromByteRGB(255, 170, 0) }, - { CollisionResultsCategory, Color.FromByteRGB(244, 67, 54) }, // Material Red(预计算碰撞) + { PrecomputeCollisionResultsCategory, Color.FromByteRGB(244, 67, 54) }, // Material Red(预计算碰撞) { ChannelPreviewCategory, Color.Green }, { ClashDetectiveResultsCategory, Color.Red }, { AnimatedObjectCategory, Color.FromByteRGB(76, 175, 80) } // Material Green(动画车辆) @@ -125,7 +125,7 @@ namespace NavisworksTransport.Utils { lock (_syncRoot) { - ClearCategory(CollisionResultsCategory); + ClearCategory(PrecomputeCollisionResultsCategory); ClearCategory(ClashDetectiveResultsCategory); } } @@ -255,14 +255,14 @@ namespace NavisworksTransport.Utils { if (clearPrevious) { - ClearCategory(CollisionResultsCategory); + ClearCategory(PrecomputeCollisionResultsCategory); } return; } if (clearPrevious) { - ClearCategory(CollisionResultsCategory); + ClearCategory(PrecomputeCollisionResultsCategory); } var highlightItems = new List(); @@ -279,7 +279,7 @@ namespace NavisworksTransport.Utils } } - HighlightItems(CollisionResultsCategory, highlightItems); + HighlightItems(PrecomputeCollisionResultsCategory, highlightItems); } catch (Exception ex) {