10 KiB
10 KiB
分层预览中自定义预览的分层实现逻辑分析
概述
本文档详细分析NavisworksTransport插件中分层预览功能的实现逻辑,特别是自定义预览的分层机制、节点遍历深度控制和界面交互方式。
核心架构分析
1. 节点遍历深度控制机制
深度选择界面设计
系统在UI层提供了灵活的深度控制选项:
// LayerManagementViewModel.cs - 深度选项定义
public ThreadSafeObservableCollection<string> DepthOptions { get; } =
new ThreadSafeObservableCollection<string>
{
"1级", "2级", "3级", "4级", "5级", "全部"
};
深度值转换逻辑
界面选择通过CurrentDepthValue属性转换为具体的遍历参数:
public int CurrentDepthValue
{
get
{
switch (SelectedDepth)
{
case "1级": return 1;
case "2级": return 2;
case "3级": return 3;
case "4级": return 4;
case "5级": return 5;
case "全部": return 0; // 0表示无限深度
default: return 1;
}
}
}
核心遍历算法
主遍历方法:GetItemsByDepthUnified(int maxDepth)
private ModelItemCollection GetItemsByDepthUnified(int maxDepth)
{
// 深度为0表示包含所有级别
if (maxDepth <= 0)
{
result.AddRange(document.Models.RootItemDescendantsAndSelf);
return result;
}
// 精确深度控制:从文档的根模型开始遍历
foreach (Model model in document.Models)
{
if (model.RootItem != null && maxDepth >= 1)
{
// 添加第一级节点(模型根的直接子节点)
foreach (ModelItem firstLevelItem in model.RootItem.Children)
{
result.Add(firstLevelItem);
// 递归添加更深层次的节点
AddChildrenToDepth(firstLevelItem, result, 2, maxDepth);
}
}
}
}
递归遍历方法:AddChildrenToDepth()
private void AddChildrenToDepth(ModelItem parentItem, ModelItemCollection result,
int currentDepth, int maxDepth)
{
if (currentDepth > maxDepth || parentItem?.Children == null)
return;
foreach (ModelItem child in parentItem.Children)
{
result.Add(child);
// 如果还没有达到最大深度,继续遍历子项
if (currentDepth < maxDepth)
{
AddChildrenToDepth(child, result, currentDepth + 1, maxDepth);
}
}
}
2. 分层预览处理流程
预览触发链路
用户界面操作
└── LayerManagementViewModel.PreviewSplitAsync()
├── 生成SplitConfiguration(包含MaxDepth参数)
└── SimplifiedModelSplitterManager.PreviewSplit(config)
├── GetAllModelItems(config.MaxDepth)
│ └── GetItemsByDepthUnified(maxDepth) // 深度控制核心
├── PreviewSplitByAttribute(allItems, config, strategy)
│ └── strategy.GroupItems() // 按选定策略分组
└── 返回List<SplitPreviewResult>
分层策略处理
支持的分层策略:
BySmartFloorDetection:智能楼层检测分层ByFloorAttribute:基于楼层属性分层ByZoneAttribute:基于分区属性分层BySubSystemAttribute:基于子系统属性分层
分层处理核心方法:PreviewSplitByAttribute()
private List<SplitPreviewResult> PreviewSplitByAttribute(
ModelItemCollection items, SplitConfiguration config, IGroupingStrategy strategy)
{
// 属性分组阶段 (35-70%)
var groups = strategy.GroupItems(items, config);
// 生成预览结果阶段 (70-85%)
foreach (var group in groups.Values)
{
var previewResult = new SplitPreviewResult
{
LayerName = SanitizeLayerName(group.GroupName),
ItemCount = group.Items.Count,
EstimatedFileSize = EstimateFileSize(group.Items.Count),
Status = "就绪",
Items = new ModelItemCollection() // 关键:保存分组的模型项
};
// 添加模型项到集合中(用于后续的隔离显示)
if (group.Items != null && group.Items.Count > 0)
{
previewResult.Items.AddRange(group.Items);
}
results.Add(previewResult);
}
}
3. 数据结构设计
预览结果数据模型
SplitPreviewItem类(已具备选择保存功能):
public class SplitPreviewItem : INotifyPropertyChanged
{
public string LayerName { get; set; } // 分层名称
public int ObjectCount { get; set; } // 对象数量
public string EstimatedSize { get; set; } // 预估文件大小
public string Status { get; set; } // 状态信息
// 重要:已存在的选择保存功能
private bool _isSelectedForSave = true;
public bool IsSelectedForSave { get; set; } // 是否选中用于保存,默认true
// 关联的模型项集合(用于隔离显示功能)
public ModelItemCollection Items { get; set; } = new ModelItemCollection();
}
UI数据绑定
ViewModel中的集合管理:
// 预览结果集合
public ThreadSafeObservableCollection<SplitPreviewItem> SplitPreviewResults { get; }
// 当前选中的预览项
public SplitPreviewItem SelectedPreviewResult { get; set; }
// 控制预览列表显示
public bool ShowPreviewResults { get; set; }
4. 可见性控制机制
参考实现:SaveSelectedItemsAsync方法
系统已有完整的节点隔离显示逻辑,核心步骤:
1. 收集需要保持可见的节点
var nodesToKeepVisible = new HashSet<ModelItem>();
foreach (var selectedItem in originalSelection)
{
// 添加选中节点本身
nodesToKeepVisible.Add(selectedItem);
// 添加所有祖先节点,确保选中节点的路径可见
var current = selectedItem.Parent;
while (current != null)
{
nodesToKeepVisible.Add(current);
current = current.Parent;
}
// 如果启用了包含子节点选项,添加所有子节点
if (IncludeChildNodes)
{
var childItems = selectedItem.DescendantsAndSelf.Where(x => x != selectedItem);
foreach (ModelItem child in childItems)
{
nodesToKeepVisible.Add(child);
}
}
}
2. 智能隐藏策略
// 收集所有顶级节点
var allTopLevelItems = new List<ModelItem>();
foreach (Model model in document.Models)
{
foreach (ModelItem topLevelItem in model.RootItem.Children)
{
allTopLevelItems.Add(topLevelItem);
}
}
// 决定哪些顶级分支需要隐藏
var itemsToHide = new ModelItemCollection();
foreach (ModelItem topLevelItem in allTopLevelItems)
{
bool shouldKeepTopLevel = false;
// 检查这个顶级节点或其任何子节点是否需要保持可见
if (nodesToKeepVisible.Contains(topLevelItem))
{
shouldKeepTopLevel = true;
}
else
{
// 检查是否有任何选中节点是这个顶级节点的后代
foreach (var selectedItem in originalSelection)
{
var current = selectedItem;
while (current != null)
{
if (current == topLevelItem)
{
shouldKeepTopLevel = true;
break;
}
current = current.Parent;
}
if (shouldKeepTopLevel) break;
}
}
// 如果这个顶级节点不需要保持可见,则隐藏它
if (!shouldKeepTopLevel)
{
itemsToHide.Add(topLevelItem);
}
}
3. 执行可见性操作
// 执行隐藏操作
if (itemsToHide.Count > 0)
{
document.Models.SetHidden(itemsToHide, true);
}
// 操作完成后恢复所有项目可见性
var allItems = new ModelItemCollection();
foreach (Model model in document.Models)
{
foreach (ModelItem item in model.RootItem.Children)
{
allItems.Add(item);
}
}
if (allItems.Count > 0)
{
document.Models.SetHidden(allItems, false);
}
深度遍历使用场景分析
遍历深度对分层效果的影响
| 深度级别 | 遍历范围 | 适用场景 | 性能特点 |
|---|---|---|---|
| 1级 | 只包含模型根节点的直接子节点 | 粗粒度分层,适合大型模型的快速概览 | 处理速度最快,内存占用最小 |
| 2级 | 包含二级子节点 | 中等粒度分层,平衡详细度与性能 | 适中的处理时间和内存使用 |
| 3-5级 | 包含更深层次的节点结构 | 细粒度分层,适合详细分析 | 处理时间较长,内存占用较大 |
| 全部 | 包含所有层级的节点 | 最详细的分层分析 | 处理时间最长,内存占用最大 |
深度设置的实际应用
楼层分析场景:
- 1-2级:适合按建筑主要结构分层
- 3-5级:适合按房间或具体构件分层
- 全部:适合最详细的构件级别分析
系统分析场景:
- 较低深度:按主要系统分类(如电气、暖通、给排水)
- 较高深度:按具体设备或管线分层
缓存机制
系统实现了分层结果的缓存机制,提高重复操作的性能:
// 生成缓存键
string cacheKey = GenerateCacheKey(config);
// 检查缓存
List<SplitPreviewResult> cachedResults = GetFromCache(config.Strategy, cacheKey);
if (cachedResults != null && cachedResults.Count > 0)
{
return cachedResults; // 直接返回缓存结果
}
// 处理完成后保存到缓存
SaveToCache(config.Strategy, cacheKey, previewResults);
总结
NavisworksTransport的分层预览功能具备以下关键特性:
- 灵活的深度控制:支持1-5级精确遍历和无限深度选项
- 完善的数据结构:
SplitPreviewItem已包含选择保存和模型项关联功能 - 成熟的可见性控制:基于
SaveSelectedItemsAsync的参考实现 - 多样的分层策略:支持楼层、分区、子系统等多种分层方式
- 高效的缓存机制:避免重复计算,提升用户体验
系统架构设计合理,为后续的功能扩展(如选择性保存、单独显示等)提供了良好的基础。