重构了高亮显示的逻辑,统一处理流程。
This commit is contained in:
parent
adde6cbdf4
commit
2bd117ff8a
@ -156,6 +156,8 @@
|
||||
<Compile Include="src\Core\Properties\CategoryAttributeManager.cs" />
|
||||
<Compile Include="src\Core\Properties\NavisworksComPropertyManager.cs" />
|
||||
<Compile Include="src\Core\FloorAttributeManager.cs" />
|
||||
<!-- Utilities -->
|
||||
<Compile Include="src\Utils\ModelHighlightHelper.cs" />
|
||||
<!-- PathPlanning - Auto Path Planning -->
|
||||
<Compile Include="src\PathPlanning\GridMap.cs" />
|
||||
<Compile Include="src\PathPlanning\GridMapGenerator.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} 个碰撞对象");
|
||||
}
|
||||
}
|
||||
|
||||
@ -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}: 清除高亮");
|
||||
}
|
||||
|
||||
|
||||
@ -15,6 +15,8 @@ namespace NavisworksTransport
|
||||
public class ClashDetectiveIntegration
|
||||
{
|
||||
private static ClashDetectiveIntegration _instance;
|
||||
private const string CollisionHighlightsCategory = ModelHighlightHelper.CollisionResultsCategory;
|
||||
|
||||
private DocumentClash _documentClash;
|
||||
private List<ClashResult> _currentCollisions;
|
||||
// 通道对象缓存,用于优化碰撞检测性能
|
||||
@ -125,10 +127,7 @@ namespace NavisworksTransport
|
||||
}
|
||||
|
||||
private List<CollisionResult> _cachedResults = new List<CollisionResult>();
|
||||
|
||||
// 高亮管理字段
|
||||
private Dictionary<string, ModelItemCollection> _activeHighlights = new Dictionary<string, ModelItemCollection>();
|
||||
private readonly object _highlightLock = new object();
|
||||
private readonly object _resultsLock = new object();
|
||||
|
||||
/// <summary>
|
||||
/// 缓存碰撞结果
|
||||
@ -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<CollisionResult>();
|
||||
|
||||
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<ModelItem>();
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 高亮任意模型对象集合
|
||||
/// </summary>
|
||||
public void HighlightModelItems(string category, IEnumerable<ModelItem> 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}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清除指定类别的高亮
|
||||
/// </summary>
|
||||
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}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 按类别管理高亮显示
|
||||
/// </summary>
|
||||
/// <param name="category">高亮类别(如"animation", "independent", "report"等)</param>
|
||||
/// <param name="results">碰撞结果</param>
|
||||
/// <param name="highlightColor">高亮颜色</param>
|
||||
/// <param name="clearOtherCategories">是否清除其他类别的高亮</param>
|
||||
/// <param name="clearOtherCategories">是否在高亮前清除该类别以避免叠加</param>
|
||||
public void ManageHighlightsByCategory(string category, List<CollisionResult> results,
|
||||
Color highlightColor, bool clearOtherCategories = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (_highlightLock)
|
||||
var collidingItems = new List<ModelItem>();
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据类别获取默认颜色
|
||||
/// </summary>
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前活跃高亮信息
|
||||
/// </summary>
|
||||
@ -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引用
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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";
|
||||
|
||||
/// <summary>
|
||||
/// 选中的通道
|
||||
@ -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 { }
|
||||
}
|
||||
|
||||
@ -127,9 +127,12 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
private ObservableCollection<ManualCollisionTargetViewModel> _manualCollisionTargets;
|
||||
private string _manualCollisionTargetSummary = "未指定碰撞检测对象";
|
||||
private DateTime? _manualTargetsLastSyncTime;
|
||||
private List<CollisionResult> _latestCollisionResults = new List<CollisionResult>();
|
||||
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<ManualCollisionTargetViewModel>(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
|
||||
/// </summary>
|
||||
private async void OnCollisionDetected(object sender, CollisionDetectedEventArgs e)
|
||||
{
|
||||
HasCollisionResults = e.Results.Count > 0;
|
||||
_latestCollisionResults = e?.Results?.Where(r => r != null).ToList() ?? new List<CollisionResult>();
|
||||
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
|
||||
|
||||
/// <summary>
|
||||
/// 异步预计算碰撞排除列表
|
||||
/// </summary>
|
||||
@ -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 - 现在使用单例模式,由应用程序生命周期管理
|
||||
|
||||
@ -885,7 +885,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
{
|
||||
var collisions = new List<CollisionResult> { 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}");
|
||||
}
|
||||
}
|
||||
|
||||
@ -377,7 +377,17 @@ NavisworksTransport 检测动画页签视图 - 采用与类别设置和分层管
|
||||
<Button Content="查看碰撞报告"
|
||||
Command="{Binding ViewCollisionReportCommand}"
|
||||
IsEnabled="{Binding HasCollisionResults}"
|
||||
Style="{StaticResource ActionButtonStyle}"/>
|
||||
Style="{StaticResource ActionButtonStyle}"
|
||||
Margin="0,0,8,0"/>
|
||||
<Button Content="结果高亮"
|
||||
Command="{Binding HighlightCollisionResultsCommand}"
|
||||
IsEnabled="{Binding HasCollisionResults}"
|
||||
Style="{StaticResource SecondaryButtonStyle}"
|
||||
Margin="0,0,8,0"/>
|
||||
<Button Content="清除高亮"
|
||||
Command="{Binding ClearCollisionHighlightsCommand}"
|
||||
IsEnabled="{Binding HasCollisionResults}"
|
||||
Style="{StaticResource SecondaryButtonStyle}"/>
|
||||
</StackPanel>
|
||||
|
||||
|
||||
|
||||
234
src/Utils/ModelHighlightHelper.cs
Normal file
234
src/Utils/ModelHighlightHelper.cs
Normal file
@ -0,0 +1,234 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Autodesk.Navisworks.Api;
|
||||
|
||||
namespace NavisworksTransport.Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// 统一管理 Navisworks 临时高亮的工具类,支持按类别高亮与清除。
|
||||
/// </summary>
|
||||
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<string, HighlightEntry> _activeHighlights =
|
||||
new Dictionary<string, HighlightEntry>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
private static readonly Dictionary<string, Color> _categoryColors =
|
||||
new Dictionary<string, Color>(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 }
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// 高亮指定对象集合。
|
||||
/// </summary>
|
||||
public static void HighlightItems(string category, IEnumerable<ModelItem> 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<ModelItem> items)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(category))
|
||||
{
|
||||
category = "default";
|
||||
}
|
||||
|
||||
var color = GetCategoryColor(category);
|
||||
HighlightItems(category, items, color);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清除指定类别的高亮。
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清除全部高亮。
|
||||
/// </summary>
|
||||
public static void ClearAllHighlights()
|
||||
{
|
||||
var document = Application.ActiveDocument;
|
||||
if (document?.Models == null)
|
||||
return;
|
||||
|
||||
lock (_syncRoot)
|
||||
{
|
||||
ResetAllHighlights(document);
|
||||
_activeHighlights.Clear();
|
||||
RequestRedraw(document);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前高亮快照。
|
||||
/// </summary>
|
||||
public static List<HighlightInfo> 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<ModelItem> 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
|
||||
{
|
||||
// 忽略重绘异常
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user