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