简化可见性控制代码,改成工具类

This commit is contained in:
tian 2025-09-12 11:25:00 +08:00
parent 0195d3e8ad
commit fc0b6d6aaa
9 changed files with 164 additions and 1066 deletions

View File

@ -106,7 +106,6 @@
<Compile Include="src\Core\PathDataManager.cs" />
<Compile Include="src\Core\PathPlanningManager.cs" />
<Compile Include="src\Core\PathPlanningModels.cs" />
<Compile Include="src\Core\VisibilityManager.cs" />
<!-- Core - Events and Interfaces -->
<Compile Include="src\Core\IPathPlanningManagerEvents.cs" />
@ -247,6 +246,7 @@
<Compile Include="src\Utils\NavisworksApiHelper.cs" />
<Compile Include="src\Utils\NavisworksSelectionHelper.cs" />
<Compile Include="src\Utils\UnitsConverter.cs" />
<Compile Include="src\Utils\VisibilityHelper.cs" />
<!-- Assembly Info -->
<Compile Include="Properties\AssemblyInfo.cs" />

View File

@ -2,6 +2,16 @@
## 功能点
### [2025/09/12]
1. [x] (功能)给动画增加步进功能,同时提供反向功能(反向播放、反向步进)
2. [x] (功能) 自动生成的路径,贴合通道表面
### [2025/09/011]
1. [x] (性能优化)大模型文件分层和导出,不挂机不崩溃
2. [x] (性能优化) 提高显示/隐藏的性能
### [2025/09/09]
1. [x] (功能)增加安全优先路径策略

View File

@ -1766,15 +1766,14 @@ namespace NavisworksTransport
// 使用 VisibilityManager.IsolateSpecificItems 隔离显示
// 这个方法会使用缓存优化,效率更高
var isolateResult = VisibilityManager.IsolateSpecificItems(itemsToIsolate);
bool isolateSuccess = VisibilityHelper.IsolateSpecificItems(itemsToIsolate);
if (!isolateResult.Success)
if (!isolateSuccess)
{
throw new InvalidOperationException($"隔离显示失败: {isolateResult.Message}");
throw new InvalidOperationException("隔离显示失败");
}
LogManager.Info($"[分层管理器] 隔离显示成功: {isolateResult.Message}");
LogManager.Info($"[分层管理器] 隐藏了 {isolateResult.HiddenCount} 个项目,保持 {isolateResult.TotalCount - isolateResult.HiddenCount} 个项目可见");
LogManager.Info($"[分层管理器] 隔离显示成功");
// 创建导出选项
var exportOptions = new Autodesk.Navisworks.Api.NwdExportOptions

View File

@ -21,7 +21,6 @@ namespace NavisworksTransport
private readonly string _managerId;
private readonly CategoryAttributeManager _categoryManager;
private readonly VisibilityManager _visibilityManager;
private readonly UIStateManager _uiStateManager;
private CoordinateConverter _coordinateConverter;
@ -83,13 +82,11 @@ namespace NavisworksTransport
/// 构造函数
/// </summary>
/// <param name="categoryManager">类别属性管理器</param>
/// <param name="visibilityManager">可见性管理器</param>
/// <param name="uiStateManager">UI状态管理器可选</param>
public PathPlanningManager(CategoryAttributeManager categoryManager, VisibilityManager visibilityManager, UIStateManager uiStateManager = null)
public PathPlanningManager(CategoryAttributeManager categoryManager, UIStateManager uiStateManager = null)
{
_managerId = Guid.NewGuid().ToString("N").Substring(0, 8); // 前8位作为ID
_categoryManager = categoryManager ?? throw new ArgumentNullException(nameof(categoryManager));
_visibilityManager = visibilityManager ?? throw new ArgumentNullException(nameof(visibilityManager));
_uiStateManager = uiStateManager ?? UIStateManager.Instance;
InitializeManager();
@ -102,7 +99,6 @@ namespace NavisworksTransport
{
_managerId = Guid.NewGuid().ToString("N").Substring(0, 8);
_categoryManager = new CategoryAttributeManager();
_visibilityManager = new VisibilityManager();
_uiStateManager = UIStateManager.Instance;
InitializeManager();
@ -1988,9 +1984,6 @@ namespace NavisworksTransport
if (_categoryManager == null)
errors.Add("类别属性管理器未初始化");
if (_visibilityManager == null)
errors.Add("可见性管理器未初始化");
if (_uiStateManager == null)
errors.Add("UI状态管理器未初始化");

View File

@ -1,937 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using Autodesk.Navisworks.Api;
using NavisApplication = Autodesk.Navisworks.Api.Application;
namespace NavisworksTransport
{
/// <summary>
/// 可见性操作结果
/// </summary>
public class VisibilityOperationResult
{
/// <summary>
/// 操作是否成功
/// </summary>
public bool Success { get; set; }
/// <summary>
/// 结果消息
/// </summary>
public string Message { get; set; }
/// <summary>
/// 隐藏的项目数量
/// </summary>
public int HiddenCount { get; set; }
/// <summary>
/// 模型总项目数量
/// </summary>
public int TotalCount { get; set; }
/// <summary>
/// 错误信息列表
/// </summary>
public List<string> Errors { get; set; } = new List<string>();
}
/// <summary>
/// 可见性统计信息
/// </summary>
public class VisibilityStatistics
{
/// <summary>
/// 模型总项目数量
/// </summary>
public int TotalModelItems { get; set; }
/// <summary>
/// 具有物流分类的项目数量
/// </summary>
public int LogisticsItems { get; set; }
/// <summary>
/// 没有物流分类的项目数量
/// </summary>
public int NonLogisticsItems { get; set; }
/// <summary>
/// 当前隐藏的项目数量
/// </summary>
public int HiddenItems { get; set; }
/// <summary>
/// 当前可见的项目数量
/// </summary>
public int VisibleItems { get; set; }
}
/// <summary>
/// 可见性管理器
/// 负责ModelItem可见性控制的核心业务逻辑
/// </summary>
public class VisibilityManager
{
#region
private readonly Document _document;
private List<ModelItem> _lastHiddenItems; // 缓存最后一次隐藏的项目列表
#endregion
#region
/// <summary>
/// 进度报告事件
/// </summary>
public event EventHandler<ProgressChangedEventArgs> ProgressChanged;
/// <summary>
/// 操作完成事件
/// </summary>
public event EventHandler<VisibilityOperationResult> OperationCompleted;
#endregion
#region
/// <summary>
/// 初始化可见性管理器
/// </summary>
public VisibilityManager()
{
_document = NavisApplication.ActiveDocument;
_lastHiddenItems = new List<ModelItem>();
}
#endregion
#region
/// <summary>
/// 检查ModelItem或其任何子项是否包含物流属性
/// </summary>
/// <param name="item">要检查的ModelItem</param>
/// <returns>如果本身或任何子项包含物流属性则返回true</returns>
private static bool HasLogisticsAttributesRecursive(ModelItem item)
{
// 首先检查当前项目
if (CategoryAttributeManager.HasLogisticsAttributes(item))
{
return true;
}
// 然后递归检查子项目
if (item.Children != null && item.Children.Count() > 0)
{
foreach (ModelItem child in item.Children)
{
if (HasLogisticsAttributesRecursive(child))
{
return true;
}
}
}
return false;
}
/// <summary>
/// 静态方法:隐藏非物流分类项目(优化版,只处理顶级节点)
/// </summary>
/// <returns>操作结果</returns>
public static VisibilityOperationResult HideNonLogisticsItems()
{
try
{
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
var document = NavisApplication.ActiveDocument;
if (document == null || document.Models.Count == 0)
{
return new VisibilityOperationResult { Success = true, Message = "没有加载的模型" };
}
LogManager.Debug("[VisibilityManager] HideNonLogisticsItems - 开始隐藏非物流项目");
// 先重置所有内容为可见,确保从干净状态开始
document.Models.ResetAllHidden();
// 只处理顶级节点,大幅提升性能
var rootItems = new List<ModelItem>();
var itemsToHide = new ModelItemCollection();
int logisticsCount = 0;
int nonLogisticsCount = 0;
// 遍历所有模型的第一级子节点
foreach (Model model in document.Models)
{
if (model.RootItem != null && model.RootItem.Children != null)
{
foreach (ModelItem topLevelItem in model.RootItem.Children)
{
rootItems.Add(topLevelItem);
// 检查该顶级节点或其子节点是否包含物流属性
if (!HasLogisticsAttributesRecursive(topLevelItem))
{
itemsToHide.Add(topLevelItem);
nonLogisticsCount++;
LogManager.Debug($"[VisibilityManager] 隐藏非物流节点: {topLevelItem.DisplayName}");
}
else
{
logisticsCount++;
LogManager.Debug($"[VisibilityManager] 保持物流节点可见: {topLevelItem.DisplayName}");
}
}
}
}
// 执行隐藏操作
if (itemsToHide.Count > 0)
{
var hideStopwatch = System.Diagnostics.Stopwatch.StartNew();
document.Models.SetHidden(itemsToHide, true);
hideStopwatch.Stop();
LogManager.Debug($"[VisibilityManager] 隐藏操作耗时 {hideStopwatch.ElapsedMilliseconds}ms");
}
stopwatch.Stop();
// 使用已知的总节点数或估算
int totalItemsCount = 17699; // 使用已知值
int estimatedHiddenCount = nonLogisticsCount * 1000; // 估算每个顶级节点包含的子节点数
LogManager.Info($"[VisibilityManager] HideNonLogisticsItems完成: " +
$"顶级节点 {rootItems.Count} 个, " +
$"物流节点 {logisticsCount} 个, " +
$"隐藏节点 {nonLogisticsCount} 个, " +
$"耗时 {stopwatch.ElapsedMilliseconds}ms");
return new VisibilityOperationResult
{
Success = true,
Message = $"成功隐藏 {nonLogisticsCount} 个非物流顶级节点",
HiddenCount = estimatedHiddenCount,
TotalCount = totalItemsCount
};
}
catch (Exception ex)
{
LogManager.Error($"[VisibilityManager] HideNonLogisticsItems失败: {ex.Message}");
return new VisibilityOperationResult
{
Success = false,
Message = $"操作失败: {ex.Message}",
HiddenCount = 0,
TotalCount = 0,
Errors = { ex.Message }
};
}
}
/// <summary>
/// 统一的重置可见性方法 - 显示所有项目并清理缓存
/// </summary>
/// <param name="clearCache">是否清除缓存默认为true</param>
/// <returns>操作结果</returns>
public static VisibilityOperationResult ResetVisibility(bool clearCache = true)
{
try
{
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
var document = NavisApplication.ActiveDocument;
if (document == null || document.Models.Count == 0)
{
return new VisibilityOperationResult
{
Success = true,
Message = "没有加载的模型"
};
}
LogManager.Debug("[VisibilityManager] ResetVisibility - 重置所有可见性状态");
// 重置所有隐藏状态
document.Models.ResetAllHidden();
// 不再需要清除缓存
stopwatch.Stop();
LogManager.Info($"[VisibilityManager] ResetVisibility完成耗时 {stopwatch.ElapsedMilliseconds}ms");
return new VisibilityOperationResult
{
Success = true,
Message = "可见性已重置,所有项目已显示",
HiddenCount = 0,
TotalCount = 17699 // 使用已知值
};
}
catch (Exception ex)
{
LogManager.Error($"[VisibilityManager] ResetVisibility失败: {ex.Message}");
return new VisibilityOperationResult
{
Success = false,
Message = $"重置可见性失败: {ex.Message}",
HiddenCount = 0,
TotalCount = 0,
Errors = { ex.Message }
};
}
}
/// <summary>
/// 静态方法:显示所有项目(优化版,利用缓存)
/// </summary>
/// <returns>操作结果</returns>
public static VisibilityOperationResult ShowAllItems()
{
try
{
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
var document = NavisApplication.ActiveDocument;
if (document == null || document.Models.Count == 0)
{
return new VisibilityOperationResult { Success = true, Message = "没有加载的模型" };
}
// 使用 ResetAllHidden 确保所有项目都被显示
document.Models.ResetAllHidden();
// 快速统计
int totalItemsCount = 17699; // 已知的节点总数
stopwatch.Stop();
LogManager.Info($"[VisibilityManager] ShowAllItems完成耗时 {stopwatch.ElapsedMilliseconds}ms");
return new VisibilityOperationResult
{
Success = true,
Message = "所有项目已显示",
HiddenCount = 0, // 重置后隐藏数量必为0
TotalCount = totalItemsCount
};
}
catch (Exception ex)
{
LogManager.Error($"[VisibilityManager] ShowAllItems失败: {ex.Message}");
return new VisibilityOperationResult
{
Success = false,
Message = $"显示操作失败: {ex.Message}",
HiddenCount = 0,
TotalCount = 0,
Errors = { ex.Message }
};
}
}
/// <summary>
/// 仅显示指定的模型项集合,隐藏其他所有项
/// 针对分层场景优化当输入是少量根节点时不遍历Descendants
/// </summary>
/// <param name="itemsToShow">要显示的模型项集合</param>
/// <returns>操作结果</returns>
public static VisibilityOperationResult IsolateSpecificItems(ModelItemCollection itemsToShow)
{
try
{
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
var document = NavisApplication.ActiveDocument;
if (document == null || document.Models.Count == 0)
{
return new VisibilityOperationResult
{
Success = false,
Message = "没有加载的模型"
};
}
if (itemsToShow == null || !itemsToShow.Any())
{
return new VisibilityOperationResult
{
Success = false,
Message = "没有指定要显示的项目"
};
}
LogManager.Debug($"[VisibilityManager] 开始隔离显示 {itemsToShow.Count} 个项目");
// 1. 重置所有隐藏状态 - 必须从全部可见开始
document.Models.ResetAllHidden();
// 2. 创建可见项集合
ModelItemCollection visible = new ModelItemCollection();
foreach (ModelItem item in itemsToShow)
{
// 添加祖先路径(确保能看到)
if (item.AncestorsAndSelf != null)
visible.AddRange(item.AncestorsAndSelf);
// 不添加Descendants - 父节点可见时子节点会自动可见
}
LogManager.Debug($"[VisibilityManager] 收集可见项完成,共 {visible.Count} 个");
// 3. 创建隐藏集合 - 收集所有可见项的兄弟节点
ModelItemCollection hidden = new ModelItemCollection();
foreach (ModelItem toShow in visible)
{
if (toShow.Parent != null)
{
// 添加父节点的所有子节点
hidden.AddRange(toShow.Parent.Children);
}
}
// 4. 从隐藏集合中移除可见项
foreach (ModelItem toShow in visible)
{
hidden.Remove(toShow);
}
LogManager.Debug($"[VisibilityManager] 需要隐藏 {hidden.Count} 个项目");
// 5. 执行隐藏操作
if (hidden.Count > 0)
{
document.Models.SetHidden(hidden, true);
}
stopwatch.Stop();
LogManager.Info($"[VisibilityManager] 隔离显示完成,耗时 {stopwatch.ElapsedMilliseconds}ms");
return new VisibilityOperationResult
{
Success = true,
Message = $"已隔离显示 {itemsToShow.Count} 个项目",
HiddenCount = hidden.Count,
TotalCount = visible.Count
};
}
catch (Exception ex)
{
LogManager.Error($"[VisibilityManager] 隔离显示失败: {ex.Message}");
return new VisibilityOperationResult
{
Success = false,
Message = $"隔离显示操作失败: {ex.Message}",
HiddenCount = 0,
TotalCount = 0,
Errors = { ex.Message }
};
}
}
/// <summary>
/// 静态方法:根据物流类型显示特定项目
/// </summary>
/// <param name="elementType">要显示的物流元素类型</param>
/// <returns>操作结果</returns>
public static VisibilityOperationResult ShowLogisticsItemsOnly(CategoryAttributeManager.LogisticsElementType elementType)
{
try
{
var document = NavisApplication.ActiveDocument;
var allItems = GetAllModelItemsStatic();
var itemsToHide = new List<ModelItem>();
foreach (var item in allItems)
{
string typeValue = CategoryAttributeManager.GetLogisticsPropertyValue(item, CategoryAttributeManager.LogisticsProperties.TYPE);
if (typeValue != elementType.ToString() && !string.IsNullOrEmpty(typeValue))
{
itemsToHide.Add(item);
}
}
// 首先显示所有项目
document.Models.ResetAllHidden();
// 然后隐藏非目标类型的项目
if (itemsToHide.Count > 0)
{
var collection = new ModelItemCollection();
foreach (var item in itemsToHide)
{
collection.Add(item);
}
document.Models.SetHidden(collection, true);
}
return new VisibilityOperationResult
{
Success = true,
Message = $"仅显示 {elementType} 类型的项目,隐藏了 {itemsToHide.Count} 个其他项目",
HiddenCount = itemsToHide.Count,
TotalCount = allItems.Count
};
}
catch (Exception ex)
{
return new VisibilityOperationResult
{
Success = false,
Message = $"操作失败: {ex.Message}",
HiddenCount = 0,
TotalCount = 0,
Errors = { ex.Message }
};
}
}
/// <summary>
/// 静态方法获取模型中的所有ModelItem
/// </summary>
/// <returns>ModelItem列表</returns>
private static List<ModelItem> GetAllModelItemsStatic()
{
var collection = new List<ModelItem>();
var doc = NavisApplication.ActiveDocument;
if (doc != null)
{
foreach (var model in doc.Models)
{
// 从根模型的子项开始收集,以避免包含不可见的根节点
foreach (var item in model.RootItem.Children)
{
CollectModelItemsStatic(item, collection);
}
}
}
return collection;
}
/// <summary>
/// 静态方法递归收集ModelItem及其所有子项
/// </summary>
/// <param name="item">当前ModelItem</param>
/// <param name="collection">收集列表</param>
private static void CollectModelItemsStatic(ModelItem item, List<ModelItem> collection)
{
collection.Add(item);
foreach (ModelItem child in item.Children)
{
CollectModelItemsStatic(child, collection);
}
}
/// <summary>
/// 递归计算一个模型项及其所有后代的总数
/// </summary>
/// <param name="item">要计算的模型项</param>
/// <returns>总数</returns>
private static int CountDescendantsAndSelf(ModelItem item)
{
var items = new List<ModelItem>();
CollectModelItemsStatic(item, items);
return items.Count;
}
/// <summary>
/// 为所有子元素(包括深层嵌套)添加到可见集合中
/// </summary>
/// <param name="parent">父级ModelItem</param>
/// <param name="visibleItems">要更新的可见项集合</param>
public static void AddAllChildren(ModelItem parent, HashSet<ModelItem> visibleItems)
{
if (parent?.Children != null)
{
foreach (ModelItem child in parent.Children)
{
visibleItems.Add(child);
// 递归添加子元素的子元素
AddAllChildren(child, visibleItems);
}
}
}
/// <summary>
/// 向上遍历添加所有父节点到可见集合中(到根节点)
/// </summary>
/// <param name="item">起始ModelItem</param>
/// <param name="visibleItems">要更新的可见项集合</param>
public static void AddAllParents(ModelItem item, HashSet<ModelItem> visibleItems)
{
var parent = item?.Parent;
while (parent != null)
{
visibleItems.Add(parent);
parent = parent.Parent;
}
}
/// <summary>
/// 构建完整的保护集合,包括指定项目、其父节点路径和所有子节点
/// </summary>
/// <param name="itemsToShow">需要保持可见的核心项目集合</param>
/// <returns>包含完整可见性保护路径的集合</returns>
public static HashSet<ModelItem> BuildProtectionSet(IEnumerable<ModelItem> itemsToShow)
{
var protectionSet = new HashSet<ModelItem>();
foreach (var item in itemsToShow)
{
if (item != null)
{
// 添加项目本身
protectionSet.Add(item);
// 添加所有父节点路径(向上到根节点)
AddAllParents(item, protectionSet);
// 添加所有子节点(向下递归)
AddAllChildren(item, protectionSet);
}
}
return protectionSet;
}
#endregion
#region
/// <summary>
/// 异步隐藏非物流分类项目
/// </summary>
public void HideNonLogisticsItemsAsync()
{
BackgroundWorker worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.WorkerSupportsCancellation = true;
worker.DoWork += (sender, e) =>
{
try
{
var allItems = GetAllModelItems();
var itemsToHide = new List<ModelItem>();
for (int i = 0; i < allItems.Count; i++)
{
if (worker.CancellationPending)
{
e.Cancel = true;
break;
}
if (!CategoryAttributeManager.HasLogisticsAttributes(allItems[i]))
{
itemsToHide.Add(allItems[i]);
}
// 报告进度
int progress = (i * 100) / allItems.Count;
worker.ReportProgress(progress);
}
e.Result = new VisibilityOperationResult
{
Success = !e.Cancel,
HiddenCount = itemsToHide.Count,
TotalCount = allItems.Count,
Message = e.Cancel ? "操作已取消" : $"成功隐藏 {itemsToHide.Count} 个非物流分类项目"
};
// 缓存隐藏的项目列表
if (!e.Cancel)
{
_lastHiddenItems = itemsToHide;
}
}
catch (Exception ex)
{
e.Result = new VisibilityOperationResult
{
Success = false,
Message = $"操作失败: {ex.Message}",
HiddenCount = 0,
TotalCount = 0
};
}
};
worker.ProgressChanged += (sender, e) =>
{
ProgressChanged?.Invoke(this, e);
};
worker.RunWorkerCompleted += (sender, e) =>
{
var result = (VisibilityOperationResult)e.Result;
if (result.Success && result.HiddenCount > 0)
{
// 执行隐藏操作
try
{
var collection = new ModelItemCollection();
foreach (var item in _lastHiddenItems)
{
collection.Add(item);
}
_document.Models.SetHidden(collection, true);
}
catch (Exception ex)
{
result.Success = false;
result.Message = $"隐藏操作失败: {ex.Message}";
result.Errors.Add(ex.Message);
}
}
OperationCompleted?.Invoke(this, result);
};
worker.RunWorkerAsync();
}
/// <summary>
/// 实例方法:同步隐藏非物流分类项目(用于小型模型)
/// </summary>
/// <returns>操作结果</returns>
public VisibilityOperationResult HideNonLogisticsItemsInstance()
{
try
{
var allItems = GetAllModelItems();
var itemsToHide = new List<ModelItem>();
foreach (var item in allItems)
{
if (!CategoryAttributeManager.HasLogisticsAttributes(item))
{
itemsToHide.Add(item);
}
}
if (itemsToHide.Count > 0)
{
var collection = new ModelItemCollection();
foreach (var item in itemsToHide)
{
collection.Add(item);
}
_document.Models.SetHidden(collection, true);
_lastHiddenItems = itemsToHide;
}
return new VisibilityOperationResult
{
Success = true,
Message = $"成功隐藏 {itemsToHide.Count} 个非物流分类项目",
HiddenCount = itemsToHide.Count,
TotalCount = allItems.Count
};
}
catch (Exception ex)
{
return new VisibilityOperationResult
{
Success = false,
Message = $"操作失败: {ex.Message}",
HiddenCount = 0,
TotalCount = 0,
Errors = { ex.Message }
};
}
}
/// <summary>
/// 实例方法:显示所有项目
/// </summary>
/// <returns>操作结果</returns>
public VisibilityOperationResult ShowAllItemsInstance()
{
try
{
_document.Models.ResetAllHidden();
var totalCount = GetAllModelItems().Count;
_lastHiddenItems.Clear();
return new VisibilityOperationResult
{
Success = true,
Message = "所有项目已显示",
HiddenCount = 0,
TotalCount = totalCount
};
}
catch (Exception ex)
{
return new VisibilityOperationResult
{
Success = false,
Message = $"显示操作失败: {ex.Message}",
HiddenCount = _lastHiddenItems.Count,
TotalCount = 0,
Errors = { ex.Message }
};
}
}
/// <summary>
/// 获取当前可见性统计信息(静态方法)
/// </summary>
/// <returns>可见性统计信息</returns>
public static VisibilityStatistics GetCurrentStatisticsStatic()
{
try
{
var document = NavisApplication.ActiveDocument;
if (document == null || document.Models.Count == 0)
{
return new VisibilityStatistics();
}
// 快速统计可见/隐藏项
int hiddenCount = 0;
int visibleCount = 0;
int logisticsCount = 0;
// 只检查顶级节点(性能优化)
foreach (Model model in document.Models)
{
if (model.RootItem != null && model.RootItem.Children != null)
{
foreach (ModelItem topLevelItem in model.RootItem.Children)
{
if (topLevelItem.IsHidden)
{
hiddenCount++;
}
else
{
visibleCount++;
if (HasLogisticsAttributesRecursive(topLevelItem))
{
logisticsCount++;
}
}
}
}
}
int totalItems = 17699; // 使用已知值
LogManager.Debug($"[VisibilityManager] 统计信息: 总计{totalItems}, 可见{visibleCount}, 隐藏{hiddenCount}, 物流{logisticsCount}");
return new VisibilityStatistics
{
TotalModelItems = totalItems,
LogisticsItems = logisticsCount * 1000, // 估算值
NonLogisticsItems = totalItems - logisticsCount * 1000,
HiddenItems = hiddenCount * 1000, // 估算值
VisibleItems = visibleCount * 1000 // 估算值
};
}
catch (Exception ex)
{
LogManager.Error($"[VisibilityManager] 获取统计信息失败: {ex.Message}");
return new VisibilityStatistics();
}
}
/// <summary>
/// 获取当前可见性统计信息(实例方法)
/// </summary>
/// <returns>可见性统计信息</returns>
public VisibilityStatistics GetCurrentStatistics()
{
try
{
var allItems = GetAllModelItems();
var logisticsCount = 0;
foreach (var item in allItems)
{
if (CategoryAttributeManager.HasLogisticsAttributes(item))
{
logisticsCount++;
}
}
return new VisibilityStatistics
{
TotalModelItems = allItems.Count,
LogisticsItems = logisticsCount,
NonLogisticsItems = allItems.Count - logisticsCount,
HiddenItems = _lastHiddenItems.Count,
VisibleItems = allItems.Count - _lastHiddenItems.Count
};
}
catch (Exception)
{
// 异常情况返回空统计
return new VisibilityStatistics();
}
}
#endregion
#region
/// <summary>
/// 获取模型中的所有ModelItem
/// </summary>
/// <returns>ModelItem列表</returns>
private List<ModelItem> GetAllModelItems()
{
var allItems = new List<ModelItem>();
try
{
// 遍历所有根级ModelItem
foreach (ModelItem rootItem in _document.Models.RootItems)
{
CollectModelItems(rootItem, allItems);
}
}
catch (Exception)
{
// 如果遍历失败,返回空列表
return new List<ModelItem>();
}
return allItems;
}
/// <summary>
/// 递归收集ModelItem及其所有子项
/// </summary>
/// <param name="item">当前ModelItem</param>
/// <param name="collection">收集列表</param>
private void CollectModelItems(ModelItem item, List<ModelItem> collection)
{
if (item == null) return;
// 添加当前项目
collection.Add(item);
// 递归添加子项目
if (item.Children != null && item.Children.Count() > 0)
{
foreach (ModelItem child in item.Children)
{
CollectModelItems(child, collection);
}
}
}
#endregion
}
}

View File

@ -3654,11 +3654,11 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
// 调用可见性管理器的公共工具函数
var result = VisibilityManager.IsolateSpecificItems(SelectedPreviewResult.Items);
bool success = VisibilityHelper.IsolateSpecificItems(SelectedPreviewResult.Items);
LogManager.Info($"[LayerManagementViewModel] 单独显示执行结果: {result.Success}, {result.Message}");
isolateResult = result.Success;
resultMessage = result.Message;
LogManager.Info($"[LayerManagementViewModel] 单独显示执行结果: {success}");
isolateResult = success;
resultMessage = success ? "已隔离显示项目" : "隔离显示失败";
}
catch (Exception ex)
{
@ -3732,11 +3732,11 @@ namespace NavisworksTransport.UI.WPF.ViewModels
try
{
// 调用可见性管理器的公共工具函数
var result = VisibilityManager.ShowAllItems();
bool success = VisibilityHelper.ShowAllItems();
LogManager.Info($"[LayerManagementViewModel] 恢复显示执行结果: {result.Success}, {result.Message}");
restoreResult = result.Success;
resultMessage = result.Message;
LogManager.Info($"[LayerManagementViewModel] 恢复显示执行结果: {success}");
restoreResult = success;
resultMessage = success ? "所有项目已显示" : "显示失败";
}
catch (Exception ex)
{

View File

@ -539,9 +539,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels
/// </summary>
private void ShowAllInternal()
{
var result = VisibilityManager.ShowAllItems();
bool success = VisibilityHelper.ShowAllItems();
if (result.Success)
if (success)
{
// 更新物流模型列表中的可见性状态
foreach (var model in LogisticsModels)
@ -554,8 +554,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
else
{
StatusText = $"显示全部失败: {result.Message}";
LogManager.Error($"显示全部失败: {result.Message}");
StatusText = "显示全部失败";
LogManager.Error("显示全部失败");
}
}
@ -567,82 +567,35 @@ namespace NavisworksTransport.UI.WPF.ViewModels
var document = NavisApplication.ActiveDocument;
if (document?.Models != null)
{
// 先重置所有隐藏状态
document.Models.ResetAllHidden();
// 查找所有具有物流属性的元素
var logisticsItems = FindAllLogisticsModels();
// 获取所有具有物流属性的元素
var logisticsItems = new HashSet<ModelItem>();
var allItems = GetAllModelItems();
foreach (var item in allItems)
if (logisticsItems.Count > 0)
{
if (CategoryAttributeManager.HasLogisticsAttributes(item))
{
logisticsItems.Add(item);
}
}
// 获取所有需要保持可见的元素
var itemsToKeepVisible = new HashSet<ModelItem>();
foreach (var logisticsItem in logisticsItems)
{
// 添加物流元素本身
itemsToKeepVisible.Add(logisticsItem);
// 使用 VisibilityHelper 来隔离显示物流元素
bool success = VisibilityHelper.IsolateSpecificItems(logisticsItems);
// 添加所有父元素路径(向上)
var parent = logisticsItem.Parent;
while (parent != null)
if (success)
{
itemsToKeepVisible.Add(parent);
parent = parent.Parent;
// 更新物流模型列表中的可见性状态
foreach (var model in LogisticsModels)
{
model.IsVisible = true;
}
StatusText = $"仅显示物流元素 ({logisticsItems.Count} 个物流节点)";
LogManager.Info($"切换到仅显示物流模式: 找到 {logisticsItems.Count} 个物流节点");
}
// 添加所有子元素(向下)- 物流属性继承给子元素
AddAllChildren(logisticsItem, itemsToKeepVisible);
}
// 找出需要隐藏的元素(不在保持可见列表中的元素)
var itemsToHide = new List<ModelItem>();
foreach (var item in allItems)
{
if (!itemsToKeepVisible.Contains(item))
else
{
itemsToHide.Add(item);
StatusText = "隔离显示物流元素失败";
LogManager.Error("隔离显示物流元素失败");
}
}
// 执行隐藏操作
if (itemsToHide.Count > 0)
else
{
var collectionToHide = new ModelItemCollection();
collectionToHide.AddRange(itemsToHide);
document.Models.SetHidden(collectionToHide, true);
}
// 更新物流模型列表中的可见性状态
foreach (var model in LogisticsModels)
{
model.IsVisible = true;
}
var totalVisibleItems = itemsToKeepVisible.Count;
StatusText = $"仅显示物流元素 ({logisticsItems.Count} 个物流节点,{totalVisibleItems} 个可见元素)";
LogManager.Info($"切换到仅显示物流模式: 找到 {logisticsItems.Count} 个物流节点,{totalVisibleItems} 个可见元素");
}
}
/// <summary>
/// 递归添加所有子元素到可见列表
/// </summary>
private void AddAllChildren(ModelItem parent, HashSet<ModelItem> visibleItems)
{
if (parent.Children != null)
{
foreach (ModelItem child in parent.Children)
{
visibleItems.Add(child);
// 递归添加子元素的子元素
AddAllChildren(child, visibleItems);
StatusText = "未找到物流元素";
LogManager.Info("未找到任何物流元素");
}
}
}
@ -868,22 +821,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
}
/// <summary>
/// 异步设置物流属性命令使用UIStateManager和Command Pattern
/// </summary>

View File

@ -896,9 +896,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels
/// </summary>
private void ShowAllInternal()
{
var result = VisibilityManager.ShowAllItems();
bool success = VisibilityHelper.ShowAllItems();
if (result.Success)
if (success)
{
foreach (var model in LogisticsModels)
{
@ -910,8 +910,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
else
{
UpdateMainStatus($"显示全部失败: {result.Message}");
LogManager.Error($"显示全部失败: {result.Message}");
UpdateMainStatus("显示全部失败");
LogManager.Error("显示全部失败");
}
}
@ -945,9 +945,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels
LogManager.Info($"[UI-ModelSettings] 使用 Search API 找到 {logisticsItems.Count} 个物流元素");
// 使用 VisibilityManager 的优化隔离显示方法带缓存4-148ms
var result = VisibilityManager.IsolateSpecificItems(logisticsItems);
bool success = VisibilityHelper.IsolateSpecificItems(logisticsItems);
if (result.Success)
if (success)
{
// 更新物流模型列表中的可见性状态
foreach (var model in LogisticsModels)
@ -955,13 +955,13 @@ namespace NavisworksTransport.UI.WPF.ViewModels
model.IsVisible = true;
}
LogManager.Info($"[UI-ModelSettings] 成功隔离显示物流元素:显示 {logisticsItems.Count} 个核心项,隐藏 {result.HiddenCount} 个非物流项");
UpdateMainStatus($"仅显示物流元素 ({logisticsItems.Count} 个物流节点{result.TotalCount - result.HiddenCount} 个可见元素)");
LogManager.Info($"[UI-ModelSettings] 成功隔离显示物流元素:显示 {logisticsItems.Count} 个核心项");
UpdateMainStatus($"仅显示物流元素 ({logisticsItems.Count} 个物流节点)");
}
else
{
LogManager.Error($"[UI-ModelSettings] 隔离显示失败{result.Message}");
UpdateMainStatus($"操作失败{result.Message}");
LogManager.Error("[UI-ModelSettings] 隔离显示失败");
UpdateMainStatus("操作失败");
}
}
catch (Exception ex)
@ -971,16 +971,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
}
/// <summary>
/// 递归添加所有子元素到可见列表
/// </summary>
// 注意此方法已被VisibilityManager.AddAllChildren公共方法取代保留仅为兼容性
// 建议使用 VisibilityManager.BuildProtectionSet 或 VisibilityManager.AddAllChildren
private void AddAllChildren(ModelItem parent, HashSet<ModelItem> visibleItems)
{
VisibilityManager.AddAllChildren(parent, visibleItems);
}
/// <summary>
/// 查找所有具有物流属性的模型项
/// </summary>

View File

@ -0,0 +1,106 @@
using System;
using System.Linq;
using Autodesk.Navisworks.Api;
using NavisApplication = Autodesk.Navisworks.Api.Application;
namespace NavisworksTransport
{
/// <summary>
/// 可见性管理器
/// 负责ModelItem可见性控制的核心业务逻辑
/// </summary>
public static class VisibilityHelper
{
/// <summary>
/// 显示所有项目
/// </summary>
/// <returns>操作是否成功</returns>
public static bool ShowAllItems()
{
try
{
NavisApplication.ActiveDocument?.Models?.ResetAllHidden();
return true;
}
catch (Exception ex)
{
LogManager.Error($"[VisibilityManager] 显示所有项目失败: {ex.Message}");
return false;
}
}
/// <summary>
/// 仅显示指定的模型项集合,隐藏其他所有项
/// </summary>
/// <param name="itemsToShow">要显示的模型项集合</param>
/// <returns>操作是否成功</returns>
public static bool IsolateSpecificItems(ModelItemCollection itemsToShow)
{
try
{
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
var document = NavisApplication.ActiveDocument;
if (document == null || document.Models.Count == 0)
{
LogManager.Warning("[VisibilityManager] 没有加载的模型");
return false;
}
if (itemsToShow == null || !itemsToShow.Any())
{
LogManager.Warning("[VisibilityManager] 没有指定要显示的项目");
return false;
}
// 1. 重置所有隐藏状态
document.Models.ResetAllHidden();
// 2. 创建可见项集合(要保证从根节点开始的路径完整)
ModelItemCollection visible = new ModelItemCollection();
foreach (ModelItem item in itemsToShow)
{
// 添加祖先路径
if (item.AncestorsAndSelf != null)
visible.AddRange(item.AncestorsAndSelf);
}
// 3. 创建候选隐藏集合 - 收集所有可见项的兄弟节点
ModelItemCollection hidden = new ModelItemCollection();
foreach (ModelItem toShow in visible)
{
if (toShow.Parent != null)
{
// 添加父节点的所有子节点
hidden.AddRange(toShow.Parent.Children);
}
}
// 4. 从隐藏集合中移除可见项
foreach (ModelItem toShow in visible)
{
hidden.Remove(toShow);
}
// 5. 执行隐藏操作
if (hidden.Count > 0)
{
document.Models.SetHidden(hidden, true);
}
stopwatch.Stop();
LogManager.Info($"[VisibilityManager] 隔离显示完成,耗时 {stopwatch.ElapsedMilliseconds}ms");
return true;
}
catch (Exception ex)
{
LogManager.Error($"[VisibilityManager] 隔离显示失败: {ex.Message}");
return false;
}
}
}
}