优化剖面盒导出性能
This commit is contained in:
parent
3b801c6bd4
commit
8b4afcfe04
@ -737,6 +737,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
public ICommand SaveSelectedItemsCommand { get; private set; }
|
||||
public ICommand CancelOperationCommand { get; private set; }
|
||||
public ICommand TestExportToNwdCommand { get; private set; }
|
||||
public ICommand ExportSectionBoxCommand { get; private set; }
|
||||
|
||||
// 楼层属性相关命令
|
||||
public ICommand RefreshSelectionCommand { get; private set; }
|
||||
@ -894,6 +895,10 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
async () => await SaveSelectedItemsAsync(),
|
||||
() => HasSelectedItems);
|
||||
|
||||
ExportSectionBoxCommand = new RelayCommand(
|
||||
async () => await ExportSectionBoxAsync(),
|
||||
() => IsNotProcessing);
|
||||
|
||||
CancelOperationCommand = new RelayCommand(CancelOperation, () => IsProcessing);
|
||||
|
||||
TestExportToNwdCommand = new RelayCommand(
|
||||
@ -1792,27 +1797,42 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
/// </summary>
|
||||
private async Task SaveSelectedItemsAsync()
|
||||
{
|
||||
var document = Autodesk.Navisworks.Api.Application.ActiveDocument;
|
||||
if (document?.CurrentSelection?.SelectedItems == null || document.CurrentSelection.SelectedItems.Count == 0)
|
||||
{
|
||||
MessageBox.Show("请先选择要保存的项目", "保存提示", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
var items = document.CurrentSelection.SelectedItems.ToList();
|
||||
string defaultFileName = GenerateDefaultFileNameForMultipleItems(document, items);
|
||||
|
||||
await ExportItemsToNwdAsync(items, "保存当前选择项", defaultFileName, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通用导出方法 - 导出指定对象列表到NWD
|
||||
/// </summary>
|
||||
/// <param name="items">要导出的对象列表</param>
|
||||
/// <param name="dialogTitle">对话框标题</param>
|
||||
/// <param name="defaultFileName">默认文件名</param>
|
||||
/// <param name="restoreSelection">是否恢复原始选择</param>
|
||||
private async Task ExportItemsToNwdAsync(List<ModelItem> items, string dialogTitle, string defaultFileName, bool restoreSelection = false)
|
||||
{
|
||||
if (items == null || items.Count == 0)
|
||||
{
|
||||
MessageBox.Show("没有要导出的对象", "导出提示", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
LogManager.Info("[LayerManagementViewModel] 开始保存当前选择项");
|
||||
|
||||
LogManager.Info($"[LayerManagementViewModel] 开始导出 {items.Count} 个对象");
|
||||
IsProcessing = true;
|
||||
CurrentOperationText = "准备导出...";
|
||||
|
||||
var document = Autodesk.Navisworks.Api.Application.ActiveDocument;
|
||||
if (document?.Models?.Count == 0 || document.CurrentSelection.SelectedItems.Count == 0)
|
||||
{
|
||||
LogManager.Warning("[LayerManagementViewModel] 没有活动文档或未选择节点");
|
||||
MessageBox.Show("请先选择要保存的项目", "保存提示", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
// 保存当前选择状态
|
||||
var originalSelection = new List<ModelItem>(document.CurrentSelection.SelectedItems);
|
||||
|
||||
LogManager.Info($"[LayerManagementViewModel] 用户选中了 {originalSelection.Count} 个节点");
|
||||
|
||||
// 生成默认文件名
|
||||
string defaultFileName = GenerateDefaultFileNameForMultipleItems(document, originalSelection);
|
||||
var originalSelection = restoreSelection ? document.CurrentSelection.SelectedItems.ToList() : null;
|
||||
|
||||
// 获取保存路径
|
||||
string saveFilePath = null;
|
||||
@ -1820,7 +1840,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
{
|
||||
var saveDialog = new Microsoft.Win32.SaveFileDialog
|
||||
{
|
||||
Title = "保存当前选择项",
|
||||
Title = dialogTitle,
|
||||
Filter = "Navisworks文件 (*.nwd)|*.nwd",
|
||||
DefaultExt = "nwd",
|
||||
FileName = defaultFileName
|
||||
@ -1840,22 +1860,36 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
bool exportResult = false;
|
||||
string errorMessage = "";
|
||||
|
||||
// 在主线程执行导出
|
||||
// 在主线程执行导出,显示Navisworks系统进度条
|
||||
await Task.Run(() =>
|
||||
{
|
||||
System.Windows.Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
// 设置等待光标
|
||||
System.Windows.Input.Mouse.OverrideCursor = System.Windows.Input.Cursors.Wait;
|
||||
|
||||
// 开始Navisworks系统进度条
|
||||
var progress = Autodesk.Navisworks.Api.Application.BeginProgress(
|
||||
dialogTitle,
|
||||
$"正在导出 {items.Count} 个对象到 NWD 文件...");
|
||||
|
||||
try
|
||||
{
|
||||
// 收集要导出的项目 (仅根节点)
|
||||
CurrentOperationText = $"正在导出 {items.Count} 个对象...";
|
||||
progress.Update(0.2);
|
||||
|
||||
// 收集要导出的项目
|
||||
var itemsToExport = new ModelItemCollection();
|
||||
itemsToExport.AddRange(originalSelection);
|
||||
itemsToExport.AddRange(items);
|
||||
|
||||
LogManager.Info($"[LayerManagementViewModel] 准备导出 {itemsToExport.Count} 个节点");
|
||||
progress.Update(0.4);
|
||||
|
||||
// 在隔离模式下执行导出,自动恢复可见性
|
||||
VisibilityHelper.ExecuteInIsolation(itemsToExport, () =>
|
||||
{
|
||||
progress.Update(0.6);
|
||||
|
||||
// 导出选项
|
||||
var exportOptions = new Autodesk.Navisworks.Api.NwdExportOptions
|
||||
{
|
||||
@ -1864,10 +1898,13 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
PreventObjectPropertyExport = PreventObjectPropertyExport
|
||||
};
|
||||
|
||||
progress.Update(0.8);
|
||||
document.ExportToNwd(saveFilePath, exportOptions);
|
||||
exportResult = true;
|
||||
LogManager.Info("[LayerManagementViewModel] ExportToNwd API调用完成");
|
||||
});
|
||||
|
||||
progress.Update(1.0);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -1875,22 +1912,32 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
errorMessage = ex.Message;
|
||||
exportResult = false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
// 确保进度条被关闭
|
||||
Autodesk.Navisworks.Api.Application.EndProgress();
|
||||
// 恢复光标
|
||||
System.Windows.Input.Mouse.OverrideCursor = null;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 恢复原始选择 (需要在主线程)
|
||||
System.Windows.Application.Current.Dispatcher.Invoke(() =>
|
||||
// 恢复原始选择(如果需要)
|
||||
if (restoreSelection && originalSelection != null)
|
||||
{
|
||||
try
|
||||
System.Windows.Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
document.CurrentSelection.Clear();
|
||||
document.CurrentSelection.AddRange(originalSelection);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Warning($"[LayerManagementViewModel] 恢复选择失败: {ex.Message}");
|
||||
}
|
||||
});
|
||||
try
|
||||
{
|
||||
document.CurrentSelection.Clear();
|
||||
document.CurrentSelection.AddRange(originalSelection);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Warning($"[LayerManagementViewModel] 恢复选择失败: {ex.Message}");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 显示结果
|
||||
if (exportResult)
|
||||
@ -1899,23 +1946,163 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
{
|
||||
var fileInfo = new FileInfo(saveFilePath);
|
||||
MessageBox.Show(
|
||||
$"保存成功!\n\n文件: {saveFilePath}\n大小: {fileInfo.Length / 1024} KB",
|
||||
"保存结果", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
$"导出成功!\n\n文件: {saveFilePath}\n大小: {fileInfo.Length / 1024} KB",
|
||||
"导出结果", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show($"保存失败: {errorMessage}", "保存错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
MessageBox.Show($"导出失败: {errorMessage}", "导出错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"[LayerManagementViewModel] 保存选中项目过程异常: {ex.Message}", ex);
|
||||
MessageBox.Show($"保存过程异常: {ex.Message}", "保存错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
LogManager.Error($"[LayerManagementViewModel] 导出过程异常: {ex.Message}", ex);
|
||||
MessageBox.Show($"导出过程异常: {ex.Message}", "导出错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsProcessing = false;
|
||||
CurrentOperationText = "";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导出剖面盒内的对象
|
||||
/// </summary>
|
||||
private async Task ExportSectionBoxAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
IsProcessing = true;
|
||||
CurrentOperationText = "检查剖面盒...";
|
||||
|
||||
var document = NavisApplication.ActiveDocument;
|
||||
if (document == null)
|
||||
{
|
||||
MessageBox.Show("没有活动的文档!请先打开一个模型。", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查剖面盒
|
||||
var viewpoint = document.CurrentViewpoint.Value;
|
||||
var clipPlanes = viewpoint.ClipPlanes;
|
||||
|
||||
if (clipPlanes == null || !clipPlanes.Enabled)
|
||||
{
|
||||
MessageBox.Show(
|
||||
"当前没有活动的剖面盒!\n请先使用 Navisworks 的剖面工具创建剖面盒。",
|
||||
"提示", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
return;
|
||||
}
|
||||
|
||||
if (clipPlanes.Mode != ClipPlaneSetMode.Box)
|
||||
{
|
||||
MessageBox.Show(
|
||||
"当前是平面裁剪模式,请切换为剖面盒模式!\n在 Navisworks 剖面工具中选择'Box'模式。",
|
||||
"提示", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取剖面盒边界
|
||||
var box = clipPlanes.Box;
|
||||
if (box == null)
|
||||
{
|
||||
MessageBox.Show("无法获取剖面盒边界!", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
var sectionBoxBounds = new BoundingBox3D(
|
||||
new Point3D(box.Min.X, box.Min.Y, box.Min.Z),
|
||||
new Point3D(box.Max.X, box.Max.Y, box.Max.Z)
|
||||
);
|
||||
|
||||
// 异步获取剖面盒内的对象
|
||||
CurrentOperationText = "正在查找剖面盒内的对象...";
|
||||
List<ModelItem> objectsInSectionBox = null;
|
||||
|
||||
await Task.Run(() =>
|
||||
{
|
||||
objectsInSectionBox = GetObjectsInSectionBox(document, sectionBoxBounds);
|
||||
});
|
||||
|
||||
if (objectsInSectionBox.Count == 0)
|
||||
{
|
||||
MessageBox.Show("剖面盒内没有找到对象!", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
return;
|
||||
}
|
||||
|
||||
LogManager.Info($"[LayerManagementViewModel] 剖面盒内找到 {objectsInSectionBox.Count} 个对象");
|
||||
|
||||
// 生成默认文件名
|
||||
string timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
|
||||
string defaultFileName = $"SectionBox_Export_{timestamp}";
|
||||
|
||||
// 调用通用导出方法
|
||||
await ExportItemsToNwdAsync(objectsInSectionBox, "导出剖面盒", defaultFileName, false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"[LayerManagementViewModel] 导出剖面盒异常: {ex.Message}", ex);
|
||||
MessageBox.Show($"导出剖面盒异常: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsProcessing = false;
|
||||
CurrentOperationText = "";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取剖面盒内的所有对象
|
||||
/// </summary>
|
||||
private List<ModelItem> GetObjectsInSectionBox(Document document, BoundingBox3D sectionBox)
|
||||
{
|
||||
var result = new List<ModelItem>();
|
||||
|
||||
foreach (var model in document.Models)
|
||||
{
|
||||
var rootItem = model.RootItem;
|
||||
if (rootItem != null)
|
||||
{
|
||||
TraverseModelItem(rootItem, sectionBox, result);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 递归遍历模型项 - 剪枝策略
|
||||
/// </summary>
|
||||
private void TraverseModelItem(ModelItem item, BoundingBox3D sectionBox, List<ModelItem> result)
|
||||
{
|
||||
if (item == null) return;
|
||||
if (item.IsHidden) return;
|
||||
|
||||
// 如果有几何体信息,检查并添加
|
||||
if (item.HasGeometry)
|
||||
{
|
||||
var bbox = item.BoundingBox();
|
||||
|
||||
// 检查是否有体积
|
||||
double sizeX = bbox.Max.X - bbox.Min.X;
|
||||
double sizeY = bbox.Max.Y - bbox.Min.Y;
|
||||
double sizeZ = bbox.Max.Z - bbox.Min.Z;
|
||||
bool hasVolume = sizeX > 0.0001 && sizeY > 0.0001 && sizeZ > 0.0001;
|
||||
|
||||
// 有体积且与剖面盒相交才添加
|
||||
if (hasVolume && BoundingBoxGeometryUtils.BoundingBoxesIntersect(bbox, sectionBox))
|
||||
{
|
||||
result.Add(item);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 没有几何体,继续遍历子节点
|
||||
foreach (var child in item.Children)
|
||||
{
|
||||
TraverseModelItem(child, sectionBox, result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -174,7 +174,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
public ICommand TestVoxelPathFindingCommand { get; private set; }
|
||||
public ICommand ReadTransformTestCommand { get; private set; }
|
||||
public ICommand CoordinateSystemExplorerCommand { get; private set; }
|
||||
public ICommand ExportSectionBoxCommand { get; private set; }
|
||||
|
||||
|
||||
// 坐标系设置
|
||||
public ObservableCollection<string> CoordinateSystemOptions { get; private set; }
|
||||
@ -311,7 +311,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
TestVoxelPathFindingCommand = new RelayCommand(() => ExecuteTestVoxelPathFinding());
|
||||
ReadTransformTestCommand = new RelayCommand(() => ExecuteReadTransformTest());
|
||||
CoordinateSystemExplorerCommand = new RelayCommand(() => ExecuteCoordinateSystemExplorer());
|
||||
ExportSectionBoxCommand = new RelayCommand(() => ExecuteExportSectionBox());
|
||||
|
||||
|
||||
// 初始化坐标系选项
|
||||
CoordinateSystemOptions = new ObservableCollection<string> { "AutoDetect", "ZUp", "YUp" };
|
||||
@ -1658,68 +1658,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
}, "坐标系检测");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行导出剖面盒功能
|
||||
/// </summary>
|
||||
private void ExecuteExportSectionBox()
|
||||
{
|
||||
SafeExecute(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
UpdateMainStatus("正在导出剖面盒信息...");
|
||||
LogManager.Info("开始导出剖面盒信息");
|
||||
|
||||
var doc = Autodesk.Navisworks.Api.Application.ActiveDocument;
|
||||
if (doc == null || doc.IsClear)
|
||||
{
|
||||
System.Windows.MessageBox.Show(
|
||||
"没有活动的文档!请先打开一个模型。",
|
||||
"错误",
|
||||
System.Windows.MessageBoxButton.OK,
|
||||
System.Windows.MessageBoxImage.Error);
|
||||
UpdateMainStatus("导出剖面盒失败:无活动文档");
|
||||
return;
|
||||
}
|
||||
|
||||
// 使用导出功能类
|
||||
var exporter = new NavisworksTransport.Core.SectionBoxExporter();
|
||||
string filePath = exporter.ExportToJson(doc);
|
||||
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
var result = System.Windows.MessageBox.Show(
|
||||
$"剖面盒信息已导出到:\n{filePath}\n\n是否打开文件所在目录?",
|
||||
"导出成功",
|
||||
System.Windows.MessageBoxButton.YesNo,
|
||||
System.Windows.MessageBoxImage.Information);
|
||||
|
||||
if (result == System.Windows.MessageBoxResult.Yes)
|
||||
{
|
||||
System.Diagnostics.Process.Start("explorer.exe", $"/select,\"{filePath}\"");
|
||||
}
|
||||
|
||||
UpdateMainStatus($"剖面盒信息已导出: {filePath}");
|
||||
LogManager.Info($"剖面盒信息导出成功: {filePath}");
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateMainStatus("导出剖面盒被取消或失败");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"导出剖面盒异常: {ex.Message}", ex);
|
||||
System.Windows.MessageBox.Show(
|
||||
$"导出剖面盒出现异常:\n{ex.Message}",
|
||||
"错误",
|
||||
System.Windows.MessageBoxButton.OK,
|
||||
System.Windows.MessageBoxImage.Error);
|
||||
UpdateMainStatus($"导出剖面盒异常: {ex.Message}");
|
||||
}
|
||||
}, "导出剖面盒");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 辅助方法
|
||||
|
||||
@ -325,6 +325,28 @@ NavisworksTransport 分层管理页签视图 - 重构优化版本
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- 区域4: 剖面盒导出 -->
|
||||
<Border BorderBrush="#FFD4E7FF" BorderThickness="1" CornerRadius="0" Margin="0,0,0,15" Padding="12">
|
||||
<StackPanel>
|
||||
<Label Content="剖面盒导出" Style="{StaticResource SectionHeaderStyle}"/>
|
||||
|
||||
<!-- 说明文字 -->
|
||||
<TextBlock Text="导出剖面盒内的对象为NWD或JSON格式"
|
||||
Style="{StaticResource StatusTextStyle}"
|
||||
Margin="0,5,0,10"/>
|
||||
|
||||
<!-- 导出按钮 -->
|
||||
<StackPanel Orientation="Horizontal"
|
||||
HorizontalAlignment="Center"
|
||||
Margin="0,5,0,0">
|
||||
<Button Content="导出剖面盒"
|
||||
Style="{StaticResource ActionButtonStyle}"
|
||||
Command="{Binding ExportSectionBoxCommand}"
|
||||
IsEnabled="{Binding IsNotProcessing}"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
|
||||
@ -226,11 +226,6 @@ NavisworksTransport 系统管理页签视图 - 采用与其他页签一致的Nav
|
||||
Style="{StaticResource SecondaryButtonStyle}"
|
||||
Command="{Binding DiagnosticCommand}"
|
||||
ToolTip="检查运行环境和线程状态"/>
|
||||
|
||||
<Button Content="导出剖面盒"
|
||||
Command="{Binding ExportSectionBoxCommand}"
|
||||
Style="{StaticResource ActionButtonStyle}"
|
||||
ToolTip="导出当前剖面盒内的对象包围盒信息到JSON文件"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
@ -32,7 +32,7 @@ namespace NavisworksTransport
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 仅显示指定的模型项集合,隐藏其他所有项
|
||||
/// 仅显示指定的模型项集合,隐藏其他所有项(高性能版本)
|
||||
/// </summary>
|
||||
/// <param name="itemsToShow">要显示的模型项集合</param>
|
||||
/// <returns>操作是否成功</returns>
|
||||
@ -55,41 +55,66 @@ namespace NavisworksTransport
|
||||
return false;
|
||||
}
|
||||
|
||||
LogManager.Info($"[VisibilityManager] 开始隔离显示,共 {itemsToShow.Count} 个对象");
|
||||
|
||||
// 1. 重置所有隐藏状态
|
||||
document.Models.ResetAllHidden();
|
||||
|
||||
// 2. 创建可见项集合(要保证从根节点开始的路径完整)
|
||||
ModelItemCollection visible = new ModelItemCollection();
|
||||
|
||||
// 2. 使用 HashSet 收集需要显示的所有节点(包括祖先)
|
||||
var visibleSet = new HashSet<ModelItem>();
|
||||
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)
|
||||
var ancestors = item.AncestorsAndSelf;
|
||||
if (ancestors != null)
|
||||
{
|
||||
// 添加父节点的所有子节点
|
||||
hidden.AddRange(toShow.Parent.Children);
|
||||
foreach (var ancestor in ancestors)
|
||||
{
|
||||
visibleSet.Add(ancestor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 从隐藏集合中移除可见项
|
||||
foreach (ModelItem toShow in visible)
|
||||
LogManager.Info($"[VisibilityManager] 收集祖先完成,visibleSet={visibleSet.Count}");
|
||||
|
||||
// 3. 收集需要隐藏的节点(兄弟节点)
|
||||
// 优化:先收集唯一的父节点,避免重复遍历同一个Parent的Children
|
||||
var uniqueParents = new HashSet<ModelItem>();
|
||||
foreach (ModelItem visibleItem in visibleSet)
|
||||
{
|
||||
hidden.Remove(toShow);
|
||||
if (visibleItem.Parent != null)
|
||||
{
|
||||
uniqueParents.Add(visibleItem.Parent);
|
||||
}
|
||||
}
|
||||
|
||||
// 5. 执行隐藏操作
|
||||
if (hidden.Count > 0)
|
||||
LogManager.Info($"[VisibilityManager] 收集唯一父节点完成,uniqueParents={uniqueParents.Count}");
|
||||
|
||||
// 然后只遍历唯一的父节点的Children
|
||||
var hiddenSet = new HashSet<ModelItem>();
|
||||
foreach (var parent in uniqueParents)
|
||||
{
|
||||
document.Models.SetHidden(hidden, true);
|
||||
foreach (var sibling in parent.Children)
|
||||
{
|
||||
hiddenSet.Add(sibling);
|
||||
}
|
||||
}
|
||||
|
||||
LogManager.Info($"[VisibilityManager] 收集兄弟完成,hiddenSet={hiddenSet.Count}");
|
||||
|
||||
// 4. 从隐藏集合中移除可见项(HashSet.Remove 是 O(1))
|
||||
hiddenSet.ExceptWith(visibleSet);
|
||||
|
||||
LogManager.Info($"[VisibilityManager] 排除可见项后,hiddenSet={hiddenSet.Count}");
|
||||
|
||||
// 5. 执行隐藏操作
|
||||
if (hiddenSet.Count > 0)
|
||||
{
|
||||
var hiddenCollection = new ModelItemCollection();
|
||||
foreach (var item in hiddenSet)
|
||||
{
|
||||
hiddenCollection.Add(item);
|
||||
}
|
||||
document.Models.SetHidden(hiddenCollection, true);
|
||||
}
|
||||
|
||||
stopwatch.Stop();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user