diff --git a/NavisworksTransportPlugin.csproj b/NavisworksTransportPlugin.csproj
index 1eb33ea..8658304 100644
--- a/NavisworksTransportPlugin.csproj
+++ b/NavisworksTransportPlugin.csproj
@@ -106,7 +106,6 @@
-
@@ -247,6 +246,7 @@
+
diff --git a/doc/requirement/todo_features.md b/doc/requirement/todo_features.md
index bd6bacb..c862e21 100644
--- a/doc/requirement/todo_features.md
+++ b/doc/requirement/todo_features.md
@@ -2,6 +2,16 @@
## 功能点
+### [2025/09/12]
+
+1. [x] (功能)给动画增加步进功能,同时提供反向功能(反向播放、反向步进)
+2. [x] (功能) 自动生成的路径,贴合通道表面
+
+### [2025/09/011]
+
+1. [x] (性能优化)大模型文件分层和导出,不挂机不崩溃
+2. [x] (性能优化) 提高显示/隐藏的性能
+
### [2025/09/09]
1. [x] (功能)增加安全优先路径策略
diff --git a/src/Core/ModelSplitterManager.cs b/src/Core/ModelSplitterManager.cs
index 2b34724..4d17d0e 100644
--- a/src/Core/ModelSplitterManager.cs
+++ b/src/Core/ModelSplitterManager.cs
@@ -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
diff --git a/src/Core/PathPlanningManager.cs b/src/Core/PathPlanningManager.cs
index b4f47c3..053073b 100644
--- a/src/Core/PathPlanningManager.cs
+++ b/src/Core/PathPlanningManager.cs
@@ -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
/// 构造函数
///
/// 类别属性管理器
- /// 可见性管理器
/// UI状态管理器(可选)
- 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状态管理器未初始化");
diff --git a/src/Core/VisibilityManager.cs b/src/Core/VisibilityManager.cs
deleted file mode 100644
index 30e0c25..0000000
--- a/src/Core/VisibilityManager.cs
+++ /dev/null
@@ -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
-{
- ///
- /// 可见性操作结果
- ///
- public class VisibilityOperationResult
- {
- ///
- /// 操作是否成功
- ///
- public bool Success { get; set; }
-
- ///
- /// 结果消息
- ///
- public string Message { get; set; }
-
- ///
- /// 隐藏的项目数量
- ///
- public int HiddenCount { get; set; }
-
- ///
- /// 模型总项目数量
- ///
- public int TotalCount { get; set; }
-
- ///
- /// 错误信息列表
- ///
- public List Errors { get; set; } = new List();
- }
-
- ///
- /// 可见性统计信息
- ///
- public class VisibilityStatistics
- {
- ///
- /// 模型总项目数量
- ///
- public int TotalModelItems { get; set; }
-
- ///
- /// 具有物流分类的项目数量
- ///
- public int LogisticsItems { get; set; }
-
- ///
- /// 没有物流分类的项目数量
- ///
- public int NonLogisticsItems { get; set; }
-
- ///
- /// 当前隐藏的项目数量
- ///
- public int HiddenItems { get; set; }
-
- ///
- /// 当前可见的项目数量
- ///
- public int VisibleItems { get; set; }
- }
-
- ///
- /// 可见性管理器
- /// 负责ModelItem可见性控制的核心业务逻辑
- ///
- public class VisibilityManager
- {
- #region 私有字段
-
- private readonly Document _document;
- private List _lastHiddenItems; // 缓存最后一次隐藏的项目列表
-
- #endregion
-
- #region 事件
-
- ///
- /// 进度报告事件
- ///
- public event EventHandler ProgressChanged;
-
- ///
- /// 操作完成事件
- ///
- public event EventHandler OperationCompleted;
-
- #endregion
-
- #region 构造函数
-
- ///
- /// 初始化可见性管理器
- ///
- public VisibilityManager()
- {
- _document = NavisApplication.ActiveDocument;
- _lastHiddenItems = new List();
- }
-
- #endregion
-
- #region 静态方法
-
- ///
- /// 检查ModelItem或其任何子项是否包含物流属性
- ///
- /// 要检查的ModelItem
- /// 如果本身或任何子项包含物流属性则返回true
- 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;
- }
-
- ///
- /// 静态方法:隐藏非物流分类项目(优化版,只处理顶级节点)
- ///
- /// 操作结果
- 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();
- 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 }
- };
- }
- }
-
- ///
- /// 统一的重置可见性方法 - 显示所有项目并清理缓存
- ///
- /// 是否清除缓存,默认为true
- /// 操作结果
- 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 }
- };
- }
- }
-
- ///
- /// 静态方法:显示所有项目(优化版,利用缓存)
- ///
- /// 操作结果
- 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 }
- };
- }
- }
-
- ///
- /// 仅显示指定的模型项集合,隐藏其他所有项
- /// 针对分层场景优化:当输入是少量根节点时,不遍历Descendants
- ///
- /// 要显示的模型项集合
- /// 操作结果
- 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 }
- };
- }
- }
-
- ///
- /// 静态方法:根据物流类型显示特定项目
- ///
- /// 要显示的物流元素类型
- /// 操作结果
- public static VisibilityOperationResult ShowLogisticsItemsOnly(CategoryAttributeManager.LogisticsElementType elementType)
- {
- try
- {
- var document = NavisApplication.ActiveDocument;
- var allItems = GetAllModelItemsStatic();
- var itemsToHide = new List();
-
- 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 }
- };
- }
- }
-
- ///
- /// 静态方法:获取模型中的所有ModelItem
- ///
- /// ModelItem列表
- private static List GetAllModelItemsStatic()
- {
- var collection = new List();
- 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;
- }
-
- ///
- /// 静态方法:递归收集ModelItem及其所有子项
- ///
- /// 当前ModelItem
- /// 收集列表
- private static void CollectModelItemsStatic(ModelItem item, List collection)
- {
- collection.Add(item);
- foreach (ModelItem child in item.Children)
- {
- CollectModelItemsStatic(child, collection);
- }
- }
-
- ///
- /// 递归计算一个模型项及其所有后代的总数
- ///
- /// 要计算的模型项
- /// 总数
- private static int CountDescendantsAndSelf(ModelItem item)
- {
- var items = new List();
- CollectModelItemsStatic(item, items);
- return items.Count;
- }
-
- ///
- /// 为所有子元素(包括深层嵌套)添加到可见集合中
- ///
- /// 父级ModelItem
- /// 要更新的可见项集合
- public static void AddAllChildren(ModelItem parent, HashSet visibleItems)
- {
- if (parent?.Children != null)
- {
- foreach (ModelItem child in parent.Children)
- {
- visibleItems.Add(child);
- // 递归添加子元素的子元素
- AddAllChildren(child, visibleItems);
- }
- }
- }
-
- ///
- /// 向上遍历添加所有父节点到可见集合中(到根节点)
- ///
- /// 起始ModelItem
- /// 要更新的可见项集合
- public static void AddAllParents(ModelItem item, HashSet visibleItems)
- {
- var parent = item?.Parent;
- while (parent != null)
- {
- visibleItems.Add(parent);
- parent = parent.Parent;
- }
- }
-
- ///
- /// 构建完整的保护集合,包括指定项目、其父节点路径和所有子节点
- ///
- /// 需要保持可见的核心项目集合
- /// 包含完整可见性保护路径的集合
- public static HashSet BuildProtectionSet(IEnumerable itemsToShow)
- {
- var protectionSet = new HashSet();
-
- foreach (var item in itemsToShow)
- {
- if (item != null)
- {
- // 添加项目本身
- protectionSet.Add(item);
-
- // 添加所有父节点路径(向上到根节点)
- AddAllParents(item, protectionSet);
-
- // 添加所有子节点(向下递归)
- AddAllChildren(item, protectionSet);
- }
- }
-
- return protectionSet;
- }
-
- #endregion
-
- #region 实例方法
-
- ///
- /// 异步隐藏非物流分类项目
- ///
- 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();
-
- 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();
- }
-
- ///
- /// 实例方法:同步隐藏非物流分类项目(用于小型模型)
- ///
- /// 操作结果
- public VisibilityOperationResult HideNonLogisticsItemsInstance()
- {
- try
- {
- var allItems = GetAllModelItems();
- var itemsToHide = new List();
-
- 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 }
- };
- }
- }
-
- ///
- /// 实例方法:显示所有项目
- ///
- /// 操作结果
- 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 }
- };
- }
- }
-
- ///
- /// 获取当前可见性统计信息(静态方法)
- ///
- /// 可见性统计信息
- 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();
- }
- }
-
- ///
- /// 获取当前可见性统计信息(实例方法)
- ///
- /// 可见性统计信息
- 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 私有方法
-
- ///
- /// 获取模型中的所有ModelItem
- ///
- /// ModelItem列表
- private List GetAllModelItems()
- {
- var allItems = new List();
-
- try
- {
- // 遍历所有根级ModelItem
- foreach (ModelItem rootItem in _document.Models.RootItems)
- {
- CollectModelItems(rootItem, allItems);
- }
- }
- catch (Exception)
- {
- // 如果遍历失败,返回空列表
- return new List();
- }
-
- return allItems;
- }
-
- ///
- /// 递归收集ModelItem及其所有子项
- ///
- /// 当前ModelItem
- /// 收集列表
- private void CollectModelItems(ModelItem item, List 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
- }
-}
\ No newline at end of file
diff --git a/src/UI/WPF/ViewModels/LayerManagementViewModel.cs b/src/UI/WPF/ViewModels/LayerManagementViewModel.cs
index 10025ad..4fbdb87 100644
--- a/src/UI/WPF/ViewModels/LayerManagementViewModel.cs
+++ b/src/UI/WPF/ViewModels/LayerManagementViewModel.cs
@@ -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)
{
diff --git a/src/UI/WPF/ViewModels/LogisticsControlViewModel.cs b/src/UI/WPF/ViewModels/LogisticsControlViewModel.cs
index b7f33a9..8a02349 100644
--- a/src/UI/WPF/ViewModels/LogisticsControlViewModel.cs
+++ b/src/UI/WPF/ViewModels/LogisticsControlViewModel.cs
@@ -539,9 +539,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels
///
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();
- var allItems = GetAllModelItems();
-
- foreach (var item in allItems)
+ if (logisticsItems.Count > 0)
{
- if (CategoryAttributeManager.HasLogisticsAttributes(item))
- {
- logisticsItems.Add(item);
- }
- }
-
- // 获取所有需要保持可见的元素
- var itemsToKeepVisible = new HashSet();
- 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();
- 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} 个可见元素");
- }
- }
-
- ///
- /// 递归添加所有子元素到可见列表
- ///
- private void AddAllChildren(ModelItem parent, HashSet 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
}
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
///
/// 异步设置物流属性命令(使用UIStateManager和Command Pattern)
///
diff --git a/src/UI/WPF/ViewModels/ModelSettingsViewModel.cs b/src/UI/WPF/ViewModels/ModelSettingsViewModel.cs
index 62ddcbd..6e31f7a 100644
--- a/src/UI/WPF/ViewModels/ModelSettingsViewModel.cs
+++ b/src/UI/WPF/ViewModels/ModelSettingsViewModel.cs
@@ -896,9 +896,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels
///
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
}
}
- ///
- /// 递归添加所有子元素到可见列表
- ///
- // 注意:此方法已被VisibilityManager.AddAllChildren公共方法取代,保留仅为兼容性
- // 建议使用 VisibilityManager.BuildProtectionSet 或 VisibilityManager.AddAllChildren
- private void AddAllChildren(ModelItem parent, HashSet visibleItems)
- {
- VisibilityManager.AddAllChildren(parent, visibleItems);
- }
-
///
/// 查找所有具有物流属性的模型项
///
diff --git a/src/Utils/VisibilityHelper.cs b/src/Utils/VisibilityHelper.cs
new file mode 100644
index 0000000..a4c193e
--- /dev/null
+++ b/src/Utils/VisibilityHelper.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Linq;
+using Autodesk.Navisworks.Api;
+using NavisApplication = Autodesk.Navisworks.Api.Application;
+
+namespace NavisworksTransport
+{
+ ///
+ /// 可见性管理器
+ /// 负责ModelItem可见性控制的核心业务逻辑
+ ///
+ public static class VisibilityHelper
+ {
+
+ ///
+ /// 显示所有项目
+ ///
+ /// 操作是否成功
+ public static bool ShowAllItems()
+ {
+ try
+ {
+ NavisApplication.ActiveDocument?.Models?.ResetAllHidden();
+ return true;
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error($"[VisibilityManager] 显示所有项目失败: {ex.Message}");
+ return false;
+ }
+ }
+
+ ///
+ /// 仅显示指定的模型项集合,隐藏其他所有项
+ ///
+ /// 要显示的模型项集合
+ /// 操作是否成功
+ 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;
+ }
+ }
+ }
+}
\ No newline at end of file