diff --git a/NavisworksTransportPlugin.csproj b/NavisworksTransportPlugin.csproj
index 7b2864c..5496b1f 100644
--- a/NavisworksTransportPlugin.csproj
+++ b/NavisworksTransportPlugin.csproj
@@ -156,6 +156,8 @@
+
+
diff --git a/src/Commands/GenerateCollisionReportCommand.cs b/src/Commands/GenerateCollisionReportCommand.cs
index 97b6b5e..2468107 100644
--- a/src/Commands/GenerateCollisionReportCommand.cs
+++ b/src/Commands/GenerateCollisionReportCommand.cs
@@ -207,7 +207,7 @@ namespace NavisworksTransport.Commands
if (highlightIntegration != null)
{
var highlightColor = Color.Green; // 绿色 (Navisworks API中没有Orange)
- highlightIntegration.ManageHighlightsByCategory("report", collisionData.AllCollisions, highlightColor, true);
+ highlightIntegration.ManageHighlightsByCategory(ModelHighlightHelper.CollisionResultsCategory, collisionData.AllCollisions, highlightColor, true);
LogManager.Info($"自动高亮显示报告中的 {collisionData.AllCollisions.Count} 个碰撞对象");
}
}
diff --git a/src/Core/Animation/PathAnimationManager.cs b/src/Core/Animation/PathAnimationManager.cs
index 41dde67..b011f67 100644
--- a/src/Core/Animation/PathAnimationManager.cs
+++ b/src/Core/Animation/PathAnimationManager.cs
@@ -781,7 +781,7 @@ namespace NavisworksTransport.Core.Animation
}
else
{
- ClashDetectiveIntegration.Instance.ClearHighlights();
+ ModelHighlightHelper.ClearCategory("collisionresults");
LogManager.Info("动画停止,路径上无碰撞对象");
}
@@ -879,7 +879,7 @@ namespace NavisworksTransport.Core.Animation
}
else
{
- ClashDetectiveIntegration.Instance.ClearHighlights();
+ ModelHighlightHelper.ClearCategory("collisionresults");
LogManager.Info("动画完成,路径上无碰撞对象");
}
@@ -1928,7 +1928,7 @@ namespace NavisworksTransport.Core.Animation
else
{
// 从有碰撞到无碰撞:清除高亮
- ClashDetectiveIntegration.Instance.ClearHighlights();
+ ModelHighlightHelper.ClearCategory("collisionresults");
LogManager.Debug($"[高亮状态] 帧{_currentFrameIndex}: 清除高亮");
}
diff --git a/src/Core/Collision/ClashDetectiveIntegration.cs b/src/Core/Collision/ClashDetectiveIntegration.cs
index de97036..4cdefc6 100644
--- a/src/Core/Collision/ClashDetectiveIntegration.cs
+++ b/src/Core/Collision/ClashDetectiveIntegration.cs
@@ -15,6 +15,8 @@ namespace NavisworksTransport
public class ClashDetectiveIntegration
{
private static ClashDetectiveIntegration _instance;
+ private const string CollisionHighlightsCategory = ModelHighlightHelper.CollisionResultsCategory;
+
private DocumentClash _documentClash;
private List _currentCollisions;
// 通道对象缓存,用于优化碰撞检测性能
@@ -125,10 +127,7 @@ namespace NavisworksTransport
}
private List _cachedResults = new List();
-
- // 高亮管理字段
- private Dictionary _activeHighlights = new Dictionary();
- private readonly object _highlightLock = new object();
+ private readonly object _resultsLock = new object();
///
/// 缓存碰撞结果
@@ -580,7 +579,7 @@ namespace NavisworksTransport
{
// 使用类别管理的高亮方式
var darkRed = Color.Red; // 红色(暗红色在Navisworks API中不可用)
- ManageHighlightsByCategory("animation", validResults, darkRed, true);
+ ManageHighlightsByCategory(ModelHighlightHelper.CollisionResultsCategory, validResults, darkRed, true);
LogManager.Info($"自动高亮显示 {validResults.Count} 个动画结束后的碰撞结果(暗红色)");
}
}
@@ -742,29 +741,40 @@ namespace NavisworksTransport
{
try
{
- var doc = Application.ActiveDocument;
+ var validResults = results?.Where(r => r != null).ToList() ?? new List();
+
+ if (validResults.Count == 0)
+ {
+ if (clearPrevious)
+ {
+ ModelHighlightHelper.ClearCategory(CollisionHighlightsCategory);
+ }
+ return;
+ }
- // 根据参数决定是否清除之前的高亮
if (clearPrevious)
{
- doc.Models.ResetAllTemporaryMaterials();
+ ModelHighlightHelper.ClearCategory(CollisionHighlightsCategory);
}
- if (results != null && results.Count > 0)
+ var highlightItems = new List();
+ foreach (var collision in validResults)
{
- var collidingItems = new ModelItemCollection();
+ var item1 = collision.GetValidItem1();
+ var item2 = collision.GetValidItem2();
- foreach (var result in results)
+ if (IsModelItemValid(item1) && !highlightItems.Contains(item1))
{
- if (result.Item1 != null && !collidingItems.Contains(result.Item1))
- collidingItems.Add(result.Item1);
- if (result.Item2 != null && !collidingItems.Contains(result.Item2))
- collidingItems.Add(result.Item2);
+ highlightItems.Add(item1);
}
- // 高亮碰撞对象(使用指定颜色)
- doc.Models.OverrideTemporaryColor(collidingItems, highlightColor);
+ if (IsModelItemValid(item2) && !highlightItems.Contains(item2))
+ {
+ highlightItems.Add(item2);
+ }
}
+
+ ModelHighlightHelper.HighlightItems(CollisionHighlightsCategory, highlightItems, highlightColor);
}
catch (Exception ex)
{
@@ -779,13 +789,8 @@ namespace NavisworksTransport
{
try
{
- lock (_highlightLock)
- {
- var doc = Application.ActiveDocument;
- doc.Models.ResetAllTemporaryMaterials();
- _activeHighlights.Clear();
- LogManager.Debug("已清除所有碰撞高亮"); // 改为DEBUG级别,减少日志噪音
- }
+ ModelHighlightHelper.ClearAllHighlights();
+ LogManager.Debug("已清除所有碰撞高亮");
}
catch (Exception ex)
{
@@ -793,158 +798,42 @@ namespace NavisworksTransport
}
}
- ///
- /// 高亮任意模型对象集合
- ///
- public void HighlightModelItems(string category, IEnumerable items, Color highlightColor, bool clearOtherCategories = false)
- {
- if (string.IsNullOrWhiteSpace(category))
- {
- category = "custom";
- }
-
- try
- {
- lock (_highlightLock)
- {
- var doc = Application.ActiveDocument;
-
- if (clearOtherCategories)
- {
- doc.Models.ResetAllTemporaryMaterials();
- _activeHighlights.Clear();
- }
- else if (_activeHighlights.ContainsKey(category))
- {
- doc.Models.ResetAllTemporaryMaterials();
- _activeHighlights.Remove(category);
-
- foreach (var kvp in _activeHighlights)
- {
- var categoryColor = GetCategoryColor(kvp.Key);
- doc.Models.OverrideTemporaryColor(kvp.Value, categoryColor);
- }
- }
-
- var collection = new ModelItemCollection();
- if (items != null)
- {
- foreach (var item in items)
- {
- if (item != null && IsModelItemValid(item) && !collection.Contains(item))
- {
- collection.Add(item);
- }
- }
- }
-
- if (collection.Count == 0)
- {
- _activeHighlights.Remove(category);
- return;
- }
-
- doc.Models.OverrideTemporaryColor(collection, highlightColor);
- _activeHighlights[category] = collection;
- }
- }
- catch (Exception ex)
- {
- LogManager.Error($"高亮模型对象失败[{category}]: {ex.Message}");
- }
- }
-
- ///
- /// 清除指定类别的高亮
- ///
- public void ClearHighlightCategory(string category)
- {
- if (string.IsNullOrWhiteSpace(category))
- return;
-
- try
- {
- lock (_highlightLock)
- {
- if (!_activeHighlights.ContainsKey(category))
- return;
-
- _activeHighlights.Remove(category);
-
- var doc = Application.ActiveDocument;
- doc.Models.ResetAllTemporaryMaterials();
-
- foreach (var kvp in _activeHighlights)
- {
- var color = GetCategoryColor(kvp.Key);
- doc.Models.OverrideTemporaryColor(kvp.Value, color);
- }
- }
- }
- catch (Exception ex)
- {
- LogManager.Error($"清除高亮类别失败[{category}]: {ex.Message}");
- }
- }
-
///
/// 按类别管理高亮显示
///
/// 高亮类别(如"animation", "independent", "report"等)
/// 碰撞结果
/// 高亮颜色
- /// 是否清除其他类别的高亮
+ /// 是否在高亮前清除该类别以避免叠加
public void ManageHighlightsByCategory(string category, List results,
Color highlightColor, bool clearOtherCategories = false)
{
try
{
- lock (_highlightLock)
+ var collidingItems = new List();
+
+ if (results != null)
{
- var doc = Application.ActiveDocument;
-
- // 清除其他类别的高亮(如果需要)
- if (clearOtherCategories)
+ foreach (var result in results)
{
- doc.Models.ResetAllTemporaryMaterials();
- _activeHighlights.Clear();
- }
- else if (_activeHighlights.ContainsKey(category))
- {
- // 只清除当前类别的高亮
- var existingItems = _activeHighlights[category];
- // Navisworks不支持按对象清除高亮,需要全部重置后重新应用其他类别
- doc.Models.ResetAllTemporaryMaterials();
- _activeHighlights.Remove(category);
-
- // 重新应用其他类别的高亮
- foreach (var kvp in _activeHighlights)
+ if (result?.Item1 != null && !collidingItems.Contains(result.Item1) && IsModelItemValid(result.Item1))
{
- // 这里需要根据类别使用不同颜色重新高亮
- var categoryColor = GetCategoryColor(kvp.Key);
- doc.Models.OverrideTemporaryColor(kvp.Value, categoryColor);
- }
- }
-
- if (results != null && results.Count > 0)
- {
- var collidingItems = new ModelItemCollection();
-
- foreach (var result in results)
- {
- if (result.Item1 != null && !collidingItems.Contains(result.Item1))
- collidingItems.Add(result.Item1);
- if (result.Item2 != null && !collidingItems.Contains(result.Item2))
- collidingItems.Add(result.Item2);
+ collidingItems.Add(result.Item1);
}
- // 应用高亮
- doc.Models.OverrideTemporaryColor(collidingItems, highlightColor);
-
- // 记录活跃高亮
- _activeHighlights[category] = collidingItems;
+ if (result?.Item2 != null && !collidingItems.Contains(result.Item2) && IsModelItemValid(result.Item2))
+ {
+ collidingItems.Add(result.Item2);
+ }
}
}
+
+ if (clearOtherCategories)
+ {
+ ModelHighlightHelper.ClearCategory(category);
+ }
+
+ ModelHighlightHelper.HighlightItems(category, collidingItems, highlightColor);
}
catch (Exception ex)
{
@@ -952,30 +841,6 @@ namespace NavisworksTransport
}
}
- ///
- /// 根据类别获取默认颜色
- ///
- private Color GetCategoryColor(string category)
- {
- switch (category.ToLower())
- {
- case "animation":
- case "runtime":
- return Color.Red; // 动画过程:红色
- case "independent":
- case "static":
- return Color.Red; // 独立检测:红色 (Navisworks API中没有DarkRed)
- case "report":
- return Color.Green; // 报告查看:绿色 (Navisworks API中没有Orange)
- case "preview":
- return Color.Blue; // 预览:蓝色 (Navisworks API中没有Yellow)
- case "manualtargets":
- return Color.FromByteRGB(255, 170, 0); // 琥珀色手工目标
- default:
- return Color.White; // 未知类别:白色 (Navisworks API中没有Magenta)
- }
- }
-
///
/// 获取当前活跃高亮信息
///
@@ -983,30 +848,23 @@ namespace NavisworksTransport
{
try
{
- lock (_highlightLock)
+ var snapshot = ModelHighlightHelper.GetActiveHighlightSnapshot();
+ if (snapshot.Count == 0)
{
- if (_activeHighlights.Count == 0)
- {
- return "当前无活跃高亮";
- }
-
- var info = new StringBuilder();
- info.AppendLine("=== 当前活跃高亮 ===");
-
- foreach (var kvp in _activeHighlights)
- {
- var category = kvp.Key;
- var items = kvp.Value;
- var color = GetCategoryColor(category);
-
- info.AppendLine($"类别: {category}");
- info.AppendLine($" 对象数量: {items.Count}");
- info.AppendLine($" 颜色: {color}");
- info.AppendLine();
- }
-
- return info.ToString();
+ return "当前无活跃高亮";
}
+
+ var info = new StringBuilder();
+ info.AppendLine("=== 当前活跃高亮 ===");
+ foreach (var entry in snapshot)
+ {
+ info.AppendLine($"类别: {entry.Category}");
+ info.AppendLine($" 对象数量: {entry.Count}");
+ info.AppendLine($" 颜色: {entry.Color}");
+ info.AppendLine();
+ }
+
+ return info.ToString();
}
catch (Exception ex)
{
@@ -1246,7 +1104,7 @@ namespace NavisworksTransport
_currentCollisions?.Clear();
// 清空缓存的结果
- lock (_highlightLock)
+ lock (_resultsLock)
{
_cachedResults?.Clear();
}
@@ -1441,16 +1299,11 @@ namespace NavisworksTransport
return;
}
- // 清除临时高亮
try
{
- document.Models.ResetAllTemporaryMaterials();
+ ModelHighlightHelper.ClearAllHighlights();
LogManager.Info("已清除临时材质高亮");
}
- catch (ObjectDisposedException)
- {
- LogManager.Info("文档对象已释放,跳过材质清理");
- }
catch (Exception ex)
{
LogManager.Warning($"清除临时材质失败: {ex.Message}");
@@ -1458,12 +1311,9 @@ namespace NavisworksTransport
// 清空内存中的结果
_currentCollisions?.Clear();
- _cachedResults?.Clear();
-
- // 清理高亮管理器
- lock (_highlightLock)
+ lock (_resultsLock)
{
- _activeHighlights?.Clear();
+ _cachedResults?.Clear();
}
// 清理.NET API引用
diff --git a/src/Core/MainPlugin.cs b/src/Core/MainPlugin.cs
index 6bb81d9..eac9c24 100644
--- a/src/Core/MainPlugin.cs
+++ b/src/Core/MainPlugin.cs
@@ -5,6 +5,7 @@ using System.Windows.Forms;
using System.Windows.Forms.Integration;
using NavisworksTransport.Core;
using NavisworksTransport.Core.Animation;
+using NavisworksTransport.Utils;
using NavisApplication = Autodesk.Navisworks.Api.Application;
namespace NavisworksTransport
@@ -286,7 +287,7 @@ namespace NavisworksTransport
// 尝试清除临时高亮
if (NavisApplication.ActiveDocument?.Models != null)
{
- NavisApplication.ActiveDocument.Models.ResetAllTemporaryMaterials();
+ ModelHighlightHelper.ClearAllHighlights();
LogManager.Info("[全局异常] 已清除临时材质");
}
@@ -620,7 +621,7 @@ namespace NavisworksTransport
var activeDoc = NavisApplication.ActiveDocument;
if (activeDoc?.Models != null)
{
- activeDoc.Models.ResetAllTemporaryMaterials();
+ ModelHighlightHelper.ClearAllHighlights();
}
}
catch (Exception ex)
diff --git a/src/Core/PathPlanningModels.cs b/src/Core/PathPlanningModels.cs
index c9093ef..37e2c9f 100644
--- a/src/Core/PathPlanningModels.cs
+++ b/src/Core/PathPlanningModels.cs
@@ -5,6 +5,7 @@ using Autodesk.Navisworks.Api;
using System.Text;
using System.Linq;
using System.IO;
+using NavisworksTransport.Utils;
namespace NavisworksTransport
{
@@ -877,6 +878,7 @@ namespace NavisworksTransport
private ModelItemCollection _selectedChannels;
private ChannelSelectionMethod _selectionMethod;
private double _heightLimit;
+ private const string ChannelPreviewHighlightCategory = "channel_preview";
///
/// 选中的通道
@@ -1240,8 +1242,7 @@ namespace NavisworksTransport
{
// 高亮显示选中的通道
var navisColor = new Autodesk.Navisworks.Api.Color(0.0, 1.0, 0.0); // 绿色
- Application.ActiveDocument.Models.OverrideTemporaryColor(selectedItems, navisColor);
- Application.ActiveDocument.ActiveView.RequestDelayedRedraw(ViewRedrawRequests.All);
+ ModelHighlightHelper.HighlightItems(ChannelPreviewHighlightCategory, selectedItems, navisColor);
}
}
catch (Exception ex)
@@ -1258,8 +1259,7 @@ namespace NavisworksTransport
{
try
{
- Application.ActiveDocument.Models.ResetAllTemporaryMaterials();
- Application.ActiveDocument.ActiveView.RequestDelayedRedraw(ViewRedrawRequests.All);
+ ModelHighlightHelper.ClearCategory(ChannelPreviewHighlightCategory);
}
catch (Exception ex)
{
@@ -1291,8 +1291,7 @@ namespace NavisworksTransport
// 清除高亮
try
{
- Application.ActiveDocument.Models.ResetAllTemporaryMaterials();
- Application.ActiveDocument.ActiveView.RequestDelayedRedraw(ViewRedrawRequests.All);
+ ModelHighlightHelper.ClearCategory(ChannelPreviewHighlightCategory);
}
catch { }
}
diff --git a/src/UI/WPF/ViewModels/AnimationControlViewModel.cs b/src/UI/WPF/ViewModels/AnimationControlViewModel.cs
index 0a471cc..b43ed5b 100644
--- a/src/UI/WPF/ViewModels/AnimationControlViewModel.cs
+++ b/src/UI/WPF/ViewModels/AnimationControlViewModel.cs
@@ -127,9 +127,12 @@ namespace NavisworksTransport.UI.WPF.ViewModels
private ObservableCollection _manualCollisionTargets;
private string _manualCollisionTargetSummary = "未指定碰撞检测对象";
private DateTime? _manualTargetsLastSyncTime;
+ private List _latestCollisionResults = new List();
private const int ManualCollisionTargetLimit = 60;
- private const string ManualTargetsHighlightCategory = "manualTargets";
+ private const string ManualTargetsHighlightCategory = ModelHighlightHelper.ManualTargetsCategory;
+ private const string CollisionResultsHighlightCategory = ModelHighlightHelper.CollisionResultsCategory;
private static readonly Color ManualTargetHighlightColor = Color.FromByteRGB(255, 170, 0);
+ private static readonly Color CollisionResultHighlightColor = Color.Red;
#endregion
@@ -216,7 +219,13 @@ namespace NavisworksTransport.UI.WPF.ViewModels
public bool HasCollisionResults
{
get => _hasCollisionResults;
- set => SetProperty(ref _hasCollisionResults, value);
+ set
+ {
+ if (SetProperty(ref _hasCollisionResults, value))
+ {
+ System.Windows.Input.CommandManager.InvalidateRequerySuggested();
+ }
+ }
}
@@ -596,6 +605,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels
public ICommand RemoveManualTargetCommand { get; private set; }
public ICommand HighlightManualTargetsCommand { get; private set; }
public ICommand ClearManualHighlightsCommand { get; private set; }
+ public ICommand HighlightCollisionResultsCommand { get; private set; }
+ public ICommand ClearCollisionHighlightsCommand { get; private set; }
// 媒体控制命令
public ICommand PlayForwardCommand { get; private set; }
@@ -726,6 +737,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels
RemoveManualTargetCommand = new RelayCommand(ExecuteRemoveManualTarget, target => target != null);
HighlightManualTargetsCommand = new RelayCommand(ExecuteHighlightManualTargets, () => HasManualCollisionTargets);
ClearManualHighlightsCommand = new RelayCommand(ExecuteClearManualHighlights, () => HasManualCollisionTargets);
+ HighlightCollisionResultsCommand = new RelayCommand(ExecuteHighlightCollisionResults, () => HasCollisionResults);
+ ClearCollisionHighlightsCommand = new RelayCommand(ExecuteClearCollisionHighlights, () => HasCollisionResults);
PlayForwardCommand = new RelayCommand(ExecutePlayForward, CanExecuteMediaCommands);
PlayReverseCommand = new RelayCommand(ExecutePlayReverse, CanExecuteMediaCommands);
StepForwardCommand = new RelayCommand(ExecuteStepForward, CanExecuteMediaCommands);
@@ -1219,14 +1232,22 @@ namespace NavisworksTransport.UI.WPF.ViewModels
///
private async void OnCollisionDetected(object sender, CollisionDetectedEventArgs e)
{
- HasCollisionResults = e.Results.Count > 0;
+ _latestCollisionResults = e?.Results?.Where(r => r != null).ToList() ?? new List();
+ HasCollisionResults = _latestCollisionResults.Count > 0;
- if (e.Results.Count > 0)
+ if (!HasCollisionResults)
+ {
+ ModelHighlightHelper.ClearCategory(CollisionResultsHighlightCategory);
+ }
+
+ var collisionCount = _latestCollisionResults.Count;
+
+ if (collisionCount > 0)
{
try
{
- UpdateMainStatus($"发现 {e.Results.Count} 个碰撞点,正在生成报告...", -1, true);
- LogManager.Info($"碰撞检测完成,发现 {e.Results.Count} 个碰撞,开始自动生成报告");
+ UpdateMainStatus($"发现 {collisionCount} 个碰撞点,正在生成报告...", -1, true);
+ LogManager.Info($"碰撞检测完成,发现 {collisionCount} 个碰撞,开始自动生成报告");
// 自动生成碰撞报告
var generateReportCommand = NavisworksTransport.Commands.GenerateCollisionReportCommand.CreateComprehensive();
@@ -1240,19 +1261,19 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 保存到数据库
await SaveCollisionReportToDatabase(reportResult.Data);
- UpdateMainStatus($"✅ 碰撞报告已生成并保存:{e.Results.Count} 个碰撞");
+ UpdateMainStatus($"✅ 碰撞报告已生成并保存:{collisionCount} 个碰撞");
LogManager.Info("碰撞报告已自动生成并保存到数据库");
}
else
{
- UpdateMainStatus($"发现 {e.Results.Count} 个碰撞点(报告生成失败)");
+ UpdateMainStatus($"发现 {collisionCount} 个碰撞点(报告生成失败)");
LogManager.Error($"自动生成碰撞报告失败: {result.ErrorMessage}");
}
}
catch (Exception ex)
{
LogManager.Error($"处理碰撞检测事件失败: {ex.Message}", ex);
- UpdateMainStatus($"发现 {e.Results.Count} 个碰撞点(报告生成异常)");
+ UpdateMainStatus($"发现 {collisionCount} 个碰撞点(报告生成异常)");
}
}
else
@@ -1434,6 +1455,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 清理碰撞检测结果
HasCollisionResults = false;
+ _latestCollisionResults.Clear();
+ ModelHighlightHelper.ClearCategory(CollisionResultsHighlightCategory);
UpdateMainStatus("碰撞检测重置");
// 清除高亮构件
@@ -1543,7 +1566,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
_manualCollisionTargets.Clear();
_manualTargetsLastSyncTime = null;
- _clashIntegration?.ClearHighlightCategory(ManualTargetsHighlightCategory);
+ ModelHighlightHelper.ClearCategory(ManualTargetsHighlightCategory);
SyncManualCollisionTargetsToAnimationManager();
UpdateManualCollisionTargetSummary();
UpdateMainStatus("已清空手工碰撞对象");
@@ -1562,7 +1585,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
if (_manualCollisionTargets.Count == 0)
{
- _clashIntegration?.ClearHighlightCategory(ManualTargetsHighlightCategory);
+ ModelHighlightHelper.ClearCategory(ManualTargetsHighlightCategory);
}
else
{
@@ -1582,12 +1605,35 @@ namespace NavisworksTransport.UI.WPF.ViewModels
private void ExecuteClearManualHighlights()
{
- _clashIntegration?.ClearHighlightCategory(ManualTargetsHighlightCategory);
+ ModelHighlightHelper.ClearCategory(ManualTargetsHighlightCategory);
UpdateMainStatus("已清除手工对象高亮");
}
#endregion
+ #region 碰撞结果高亮命令
+
+ private void ExecuteHighlightCollisionResults()
+ {
+ if (_latestCollisionResults == null || _latestCollisionResults.Count == 0)
+ {
+ UpdateMainStatus("没有可高亮的碰撞结果对象");
+ return;
+ }
+
+ _clashIntegration?.HighlightCollisions(_latestCollisionResults, CollisionResultHighlightColor, false);
+ UpdateMainStatus($"已高亮 {_latestCollisionResults.Count} 个碰撞结果");
+ LogManager.Info($"[碰撞结果高亮] 已高亮 {_latestCollisionResults.Count} 个结果");
+ }
+
+ private void ExecuteClearCollisionHighlights()
+ {
+ ModelHighlightHelper.ClearCategory(CollisionResultsHighlightCategory);
+ UpdateMainStatus("已清除碰撞结果高亮");
+ }
+
+ #endregion
+
///
/// 异步预计算碰撞排除列表
///
@@ -1800,17 +1846,17 @@ namespace NavisworksTransport.UI.WPF.ViewModels
var validItems = GetValidManualCollisionTargets();
if (validItems.Count == 0)
{
- _clashIntegration.ClearHighlightCategory(ManualTargetsHighlightCategory);
+ ModelHighlightHelper.ClearCategory(ManualTargetsHighlightCategory);
return;
}
if (IsManualTargetModeActive || forceHighlight)
{
- _clashIntegration.HighlightModelItems(ManualTargetsHighlightCategory, validItems, ManualTargetHighlightColor);
+ ModelHighlightHelper.HighlightItems(ManualTargetsHighlightCategory, validItems, ManualTargetHighlightColor);
}
else
{
- _clashIntegration.ClearHighlightCategory(ManualTargetsHighlightCategory);
+ ModelHighlightHelper.ClearCategory(ManualTargetsHighlightCategory);
}
}
catch (Exception ex)
@@ -1984,6 +2030,11 @@ namespace NavisworksTransport.UI.WPF.ViewModels
LogManager.Info($"虚拟车辆尺寸: {VirtualVehicleLength:F1}×{VirtualVehicleWidth:F1}×{VirtualVehicleHeight:F1}m");
}
+ if (IsManualCollisionTargetEnabled)
+ {
+ RefreshManualTargetHighlights(forceHighlight: true);
+ }
+
// 更新状态
UpdateAnimationButtonStates();
UpdateMainStatus("动画生成成功");
@@ -2442,6 +2493,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 清空碰撞结果
HasCollisionResults = false;
+ _latestCollisionResults.Clear();
+ ModelHighlightHelper.ClearCategory(CollisionResultsHighlightCategory);
UpdateMainStatus("已重置");
}
@@ -2528,11 +2581,12 @@ namespace NavisworksTransport.UI.WPF.ViewModels
try
{
- _clashIntegration?.ClearHighlightCategory(ManualTargetsHighlightCategory);
+ ModelHighlightHelper.ClearCategory(ManualTargetsHighlightCategory);
+ ModelHighlightHelper.ClearCategory(CollisionResultsHighlightCategory);
}
catch (Exception highlightEx)
{
- LogManager.Warning($"清除手工碰撞高亮时出现警告: {highlightEx.Message}");
+ LogManager.Warning($"清除高亮时出现警告: {highlightEx.Message}");
}
// 3. 不再清理PathAnimationManager - 现在使用单例模式,由应用程序生命周期管理
diff --git a/src/UI/WPF/ViewModels/CollisionReportViewModel.cs b/src/UI/WPF/ViewModels/CollisionReportViewModel.cs
index 2ea0010..a538182 100644
--- a/src/UI/WPF/ViewModels/CollisionReportViewModel.cs
+++ b/src/UI/WPF/ViewModels/CollisionReportViewModel.cs
@@ -885,7 +885,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
var collisions = new List { item.CollisionData };
var highlightColor = Autodesk.Navisworks.Api.Color.Green; // 使用Navisworks API中可用的绿色
- clashIntegration.ManageHighlightsByCategory("selected", collisions, highlightColor, true);
+ clashIntegration.ManageHighlightsByCategory(ModelHighlightHelper.CollisionResultsCategory, collisions, highlightColor, true);
LogManager.Info($"高亮碰撞对象: {item.Title}");
}
}
diff --git a/src/UI/WPF/Views/AnimationControlView.xaml b/src/UI/WPF/Views/AnimationControlView.xaml
index 2c0ef02..5176cc9 100644
--- a/src/UI/WPF/Views/AnimationControlView.xaml
+++ b/src/UI/WPF/Views/AnimationControlView.xaml
@@ -377,7 +377,17 @@ NavisworksTransport 检测动画页签视图 - 采用与类别设置和分层管
+ Style="{StaticResource ActionButtonStyle}"
+ Margin="0,0,8,0"/>
+
+
diff --git a/src/Utils/ModelHighlightHelper.cs b/src/Utils/ModelHighlightHelper.cs
new file mode 100644
index 0000000..a180aa4
--- /dev/null
+++ b/src/Utils/ModelHighlightHelper.cs
@@ -0,0 +1,234 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Autodesk.Navisworks.Api;
+
+namespace NavisworksTransport.Utils
+{
+ ///
+ /// 统一管理 Navisworks 临时高亮的工具类,支持按类别高亮与清除。
+ ///
+ public static class ModelHighlightHelper
+ {
+ public const string CollisionResultsCategory = "collisionresults";
+ public const string ManualTargetsCategory = "manualTargets";
+ public const string ChannelPreviewCategory = "channel_preview";
+
+ private class HighlightEntry
+ {
+ public Color Color { get; set; }
+ public ModelItemCollection Items { get; set; }
+ }
+
+ public class HighlightInfo
+ {
+ public string Category { get; set; } = string.Empty;
+ public Color Color { get; set; }
+ public int Count { get; set; }
+ }
+
+ private static readonly object _syncRoot = new object();
+ private static readonly Dictionary _activeHighlights =
+ new Dictionary(StringComparer.OrdinalIgnoreCase);
+
+ private static readonly Dictionary _categoryColors =
+ new Dictionary(StringComparer.OrdinalIgnoreCase)
+ {
+ { "animation", Color.Red },
+ { "runtime", Color.Red },
+ { "independent", Color.Red },
+ { "static", Color.Red },
+ { "report", Color.Green },
+ { "preview", Color.Blue },
+ { ManualTargetsCategory, Color.FromByteRGB(255, 170, 0) },
+ { CollisionResultsCategory, Color.Red },
+ { ChannelPreviewCategory, Color.Green }
+ };
+
+ ///
+ /// 高亮指定对象集合。
+ ///
+ public static void HighlightItems(string category, IEnumerable items, Color color)
+ {
+ if (items == null)
+ return;
+
+ var document = Application.ActiveDocument;
+ if (document?.Models == null)
+ return;
+
+ if (string.IsNullOrWhiteSpace(category))
+ {
+ category = "default";
+ }
+
+ lock (_syncRoot)
+ {
+ if (_activeHighlights.ContainsKey(category))
+ {
+ _activeHighlights.Remove(category);
+ ResetAllHighlights(document);
+ ReapplyHighlights(document);
+ }
+
+ var collection = BuildCollection(items);
+ if (collection.Count == 0)
+ {
+ _activeHighlights.Remove(category);
+ return;
+ }
+
+ document.Models.OverrideTemporaryColor(collection, color);
+ _activeHighlights[category] = new HighlightEntry
+ {
+ Color = color,
+ Items = collection
+ };
+
+ RequestRedraw(document);
+ }
+ }
+
+ public static void HighlightItems(string category, IEnumerable items)
+ {
+ if (string.IsNullOrWhiteSpace(category))
+ {
+ category = "default";
+ }
+
+ var color = GetCategoryColor(category);
+ HighlightItems(category, items, color);
+ }
+
+ ///
+ /// 清除指定类别的高亮。
+ ///
+ public static void ClearCategory(string category)
+ {
+ if (string.IsNullOrWhiteSpace(category))
+ return;
+
+ var document = Application.ActiveDocument;
+ if (document?.Models == null)
+ return;
+
+ lock (_syncRoot)
+ {
+ if (!_activeHighlights.Remove(category))
+ return;
+
+ ResetAllHighlights(document);
+ ReapplyHighlights(document);
+ RequestRedraw(document);
+ }
+ }
+
+ ///
+ /// 清除全部高亮。
+ ///
+ public static void ClearAllHighlights()
+ {
+ var document = Application.ActiveDocument;
+ if (document?.Models == null)
+ return;
+
+ lock (_syncRoot)
+ {
+ ResetAllHighlights(document);
+ _activeHighlights.Clear();
+ RequestRedraw(document);
+ }
+ }
+
+ ///
+ /// 获取当前高亮快照。
+ ///
+ public static List GetActiveHighlightSnapshot()
+ {
+ lock (_syncRoot)
+ {
+ return _activeHighlights
+ .Select(kvp => new HighlightInfo
+ {
+ Category = kvp.Key,
+ Color = kvp.Value.Color,
+ Count = kvp.Value.Items?.Count ?? 0
+ })
+ .ToList();
+ }
+ }
+
+ public static Color GetCategoryColor(string category)
+ {
+ if (string.IsNullOrWhiteSpace(category))
+ {
+ category = "default";
+ }
+
+ if (_categoryColors.TryGetValue(category, out var color))
+ {
+ return color;
+ }
+
+ return Color.White;
+ }
+
+ private static ModelItemCollection BuildCollection(IEnumerable items)
+ {
+ var collection = new ModelItemCollection();
+ if (items == null)
+ return collection;
+
+ foreach (var item in items)
+ {
+ if (item == null)
+ continue;
+
+ try
+ {
+ // 访问属性以检测对象是否有效
+ _ = item.DisplayName;
+ }
+ catch
+ {
+ continue;
+ }
+
+ if (!collection.Contains(item))
+ {
+ collection.Add(item);
+ }
+ }
+
+ return collection;
+ }
+
+ private static void ResetAllHighlights(Document document)
+ {
+ document.Models.ResetAllTemporaryMaterials();
+ }
+
+ private static void ReapplyHighlights(Document document)
+ {
+ foreach (var entry in _activeHighlights.Values)
+ {
+ if (entry.Items == null || entry.Items.Count == 0)
+ continue;
+
+ document.Models.OverrideTemporaryColor(entry.Items, entry.Color);
+ }
+ }
+
+ private static void RequestRedraw(Document document)
+ {
+ try
+ {
+ document.ActiveView?.RequestDelayedRedraw(ViewRedrawRequests.All);
+ }
+ catch
+ {
+ // 忽略重绘异常
+ }
+ }
+ }
+}