NavisworksTransport/VisibilityManager.cs

625 lines
20 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 document = NavisApplication.ActiveDocument;
if (document == null || document.Models.Count == 0)
{
return new VisibilityOperationResult { Success = true, Message = "没有加载的模型" };
}
// 关键修复:在执行任何操作前,先将所有内容重置为可见,确保从一个已知的干净状态开始
document.Models.ResetAllHidden();
var rootItems = document.Models.SelectMany(model => model.RootItem.Children).ToList();
var itemsToHide = new List<ModelItem>();
// 遍历所有顶层模型
foreach (var item in rootItems)
{
if (!HasLogisticsAttributesRecursive(item))
{
itemsToHide.Add(item);
}
}
// 创建一个集合来执行隐藏操作
var collectionToHide = new ModelItemCollection();
collectionToHide.AddRange(itemsToHide);
if (collectionToHide.Count > 0)
{
document.Models.SetHidden(collectionToHide, true);
}
// 精确计算隐藏和总项目数
int totalItemsCount = rootItems.Sum(CountDescendantsAndSelf);
var visibleRootItems = rootItems.Except(itemsToHide);
int visibleItemsCount = visibleRootItems.Sum(CountDescendantsAndSelf);
int hiddenCount = totalItemsCount - visibleItemsCount;
return new VisibilityOperationResult
{
Success = true,
Message = $"成功隐藏 {hiddenCount} 个非物流项目",
HiddenCount = hiddenCount,
TotalCount = totalItemsCount
};
}
catch (Exception ex)
{
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 document = NavisApplication.ActiveDocument;
if (document == null || document.Models.Count == 0)
{
return new VisibilityOperationResult { Success = true, Message = "没有加载的模型" };
}
// 使用 ResetAllHidden 确保所有项目都被显示
document.Models.ResetAllHidden();
var rootItems = document.Models.SelectMany(model => model.RootItem.Children).ToList();
int totalItemsCount = rootItems.Sum(CountDescendantsAndSelf);
return new VisibilityOperationResult
{
Success = true,
Message = "所有项目已显示",
HiddenCount = 0, // 重置后隐藏数量必为0
TotalCount = totalItemsCount
};
}
catch (Exception ex)
{
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;
}
#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 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
}
}