优化剖面盒导,提高性能,解决漏算的问题
This commit is contained in:
parent
e495ea4620
commit
f596935c76
@ -334,6 +334,7 @@
|
||||
<Compile Include="src\Utils\CoordinateSystem\CoordinateSystemManager.cs" />
|
||||
<Compile Include="src\Utils\ViewpointHelper.cs" />
|
||||
<Compile Include="src\Utils\VisibilityHelper.cs" />
|
||||
<Compile Include="src\Utils\NwdExportHelper.cs" />
|
||||
<Compile Include="src\Utils\ModelItemTransformHelper.cs" />
|
||||
<Compile Include="src\Utils\CachedTriangle3D.cs" />
|
||||
<Compile Include="src\Utils\PathHelper.cs" />
|
||||
|
||||
@ -6,6 +6,7 @@ using System.Windows.Forms;
|
||||
using Autodesk.Navisworks.Api;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NavisworksTransport.Utils;
|
||||
using NavisApplication = Autodesk.Navisworks.Api.Application;
|
||||
|
||||
namespace NavisworksTransport.Core
|
||||
@ -80,21 +81,21 @@ namespace NavisworksTransport.Core
|
||||
|
||||
try
|
||||
{
|
||||
// 4. 获取剖面盒内的对象
|
||||
var objectsInSectionBox = GetObjectsInSectionBox(document, sectionBoxBounds);
|
||||
// 4. 【优化】一次遍历同时获取剖面盒内对象和需要隐藏的节点
|
||||
var traversalResult = GetObjectsAndHiddenItems(document, sectionBoxBounds);
|
||||
|
||||
if (exportAsNwd)
|
||||
{
|
||||
// 导出为NWD格式
|
||||
return ExportToNwd(document, objectsInSectionBox, filePath);
|
||||
// 导出为NWD格式(使用预计算结果)
|
||||
return ExportToNwd(document, traversalResult, filePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 导出为JSON格式(原有逻辑)
|
||||
var exportData = BuildExportData(sectionBoxBounds, objectsInSectionBox, document);
|
||||
var exportData = BuildExportData(sectionBoxBounds, traversalResult.ObjectsInBox, document);
|
||||
string json = JsonConvert.SerializeObject(exportData, Formatting.Indented);
|
||||
File.WriteAllText(filePath, json);
|
||||
LogManager.Info($"剖面盒导出完成: {objectsInSectionBox.Count} 个对象 -> {filePath}");
|
||||
LogManager.Info($"剖面盒导出完成: {traversalResult.ObjectsInBox.Count} 个对象 -> {filePath}");
|
||||
return filePath;
|
||||
}
|
||||
}
|
||||
@ -142,37 +143,56 @@ namespace NavisworksTransport.Core
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取剖面盒内的所有对象(公开方法供外部调用)
|
||||
/// 剖面盒遍历结果:同时包含盒内对象和需要隐藏的节点
|
||||
/// </summary>
|
||||
public List<ModelItem> GetObjectsInSectionBox(Document document, BoundingBox3D sectionBox)
|
||||
public class SectionBoxTraversalResult
|
||||
{
|
||||
var result = new List<ModelItem>();
|
||||
/// <summary>
|
||||
/// 剖面盒内的对象
|
||||
/// </summary>
|
||||
public List<ModelItem> ObjectsInBox { get; set; } = new List<ModelItem>();
|
||||
|
||||
// 手动遍历所有模型
|
||||
/// <summary>
|
||||
/// 需要隐藏的节点(子树完全不在盒内的根节点)
|
||||
/// </summary>
|
||||
public ModelItemCollection ItemsToHide { get; set; } = new ModelItemCollection();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 【优化】一次遍历同时获取剖面盒内对象和可见节点集合
|
||||
/// 然后使用原来的兄弟节点算法计算隐藏节点
|
||||
/// </summary>
|
||||
public SectionBoxTraversalResult GetObjectsAndHiddenItems(Document document, BoundingBox3D sectionBox)
|
||||
{
|
||||
var result = new SectionBoxTraversalResult();
|
||||
var visibleSet = new HashSet<ModelItem>(); // 收集需要保留的节点(对象+祖先)
|
||||
|
||||
// 第一遍:遍历整个模型树,收集盒内对象和可见节点
|
||||
foreach (var model in document.Models)
|
||||
{
|
||||
var rootItem = model.RootItem;
|
||||
if (rootItem != null)
|
||||
{
|
||||
TraverseModelItem(rootItem, sectionBox, result);
|
||||
TraverseAndCollect(model.RootItem, sectionBox, result.ObjectsInBox, visibleSet);
|
||||
}
|
||||
}
|
||||
|
||||
// 第二遍(局部):使用原来的兄弟节点算法计算隐藏节点
|
||||
// 只遍历 uniqueParents 的子节点,不是整个模型
|
||||
CalculateHiddenItems(visibleSet, result.ItemsToHide);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 递归遍历模型项 - 剪枝策略:遇到几何体就停止向下遍历
|
||||
/// 递归遍历收集盒内对象和可见节点
|
||||
/// </summary>
|
||||
public void TraverseModelItem(ModelItem item, BoundingBox3D sectionBox, List<ModelItem> result)
|
||||
private void TraverseAndCollect(ModelItem item, BoundingBox3D sectionBox,
|
||||
List<ModelItem> objectsInBox, HashSet<ModelItem> visibleSet)
|
||||
{
|
||||
if (item == null) return;
|
||||
if (item == null || item.IsHidden) return;
|
||||
|
||||
// 如果节点隐藏,跳过
|
||||
if (item.IsHidden)
|
||||
return;
|
||||
|
||||
// 如果有几何体信息,检查并添加,然后停止遍历该分支(剪枝)
|
||||
// 如果有几何体,检查是否在盒内
|
||||
if (item.HasGeometry)
|
||||
{
|
||||
var bbox = item.BoundingBox();
|
||||
@ -183,22 +203,74 @@ namespace NavisworksTransport.Core
|
||||
double sizeZ = bbox.Max.Z - bbox.Min.Z;
|
||||
bool hasVolume = sizeX > 0.0001 && sizeY > 0.0001 && sizeZ > 0.0001;
|
||||
|
||||
// 有体积且与剖面盒相交才添加
|
||||
// 有体积且与剖面盒相交 → 是目标对象
|
||||
if (hasVolume && BoundingBoxesIntersect(bbox, sectionBox))
|
||||
{
|
||||
result.Add(item);
|
||||
objectsInBox.Add(item);
|
||||
|
||||
// 将该对象及其所有祖先标记为可见
|
||||
foreach (var ancestor in item.AncestorsAndSelf)
|
||||
{
|
||||
visibleSet.Add(ancestor);
|
||||
}
|
||||
}
|
||||
// 找到几何体,停止向下遍历(无论是否相交)
|
||||
|
||||
// 找到几何体,停止向下遍历(原逻辑)
|
||||
return;
|
||||
}
|
||||
|
||||
// 没有几何体,继续遍历子节点
|
||||
foreach (var child in item.Children)
|
||||
{
|
||||
TraverseModelItem(child, sectionBox, result);
|
||||
TraverseAndCollect(child, sectionBox, objectsInBox, visibleSet);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 【使用原来的兄弟节点算法】计算需要隐藏的节点
|
||||
/// </summary>
|
||||
private void CalculateHiddenItems(HashSet<ModelItem> visibleSet, ModelItemCollection itemsToHide)
|
||||
{
|
||||
// 1. 收集唯一的父节点
|
||||
var uniqueParents = new HashSet<ModelItem>();
|
||||
foreach (var visibleItem in visibleSet)
|
||||
{
|
||||
if (visibleItem.Parent != null)
|
||||
{
|
||||
uniqueParents.Add(visibleItem.Parent);
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 收集这些父节点的所有子节点(兄弟节点)
|
||||
var hiddenSet = new HashSet<ModelItem>();
|
||||
foreach (var parent in uniqueParents)
|
||||
{
|
||||
foreach (var sibling in parent.Children)
|
||||
{
|
||||
hiddenSet.Add(sibling);
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 从隐藏集合中移除可见项
|
||||
hiddenSet.ExceptWith(visibleSet);
|
||||
|
||||
// 4. 转换为 ModelItemCollection
|
||||
foreach (var item in hiddenSet)
|
||||
{
|
||||
itemsToHide.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取剖面盒内的所有对象(公开方法供外部调用)
|
||||
/// 【已优化】内部使用 GetObjectsAndHiddenItems 实现一次遍历
|
||||
/// </summary>
|
||||
public List<ModelItem> GetObjectsInSectionBox(Document document, BoundingBox3D sectionBox)
|
||||
{
|
||||
var result = GetObjectsAndHiddenItems(document, sectionBox);
|
||||
return result.ObjectsInBox;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查两个包围盒是否相交
|
||||
/// </summary>
|
||||
@ -338,36 +410,33 @@ namespace NavisworksTransport.Core
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导出为NWD文件(公开方法供外部调用)
|
||||
/// 导出为NWD文件(委托给 NwdExportHelper)
|
||||
/// 适用于通用场景(如保存选择项)
|
||||
/// </summary>
|
||||
/// <param name="document">Navisworks文档</param>
|
||||
/// <param name="objects">要导出的对象列表</param>
|
||||
/// <param name="filePath">导出文件路径</param>
|
||||
/// <returns>导出文件路径,失败返回null</returns>
|
||||
public string ExportToNwd(Document document, List<ModelItem> objects, string filePath)
|
||||
{
|
||||
// 必须在主线程执行Navisworks API操作
|
||||
string result = null;
|
||||
System.Windows.Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
// 准备要显示的项目
|
||||
var itemsToShow = new ModelItemCollection();
|
||||
foreach (var item in objects)
|
||||
itemsToShow.Add(item);
|
||||
return NwdExportHelper.ExportToNwd(objects, filePath);
|
||||
}
|
||||
|
||||
// 在隔离模式下执行导出,自动保存和恢复可见性
|
||||
result = VisibilityHelper.ExecuteInIsolation(itemsToShow, () =>
|
||||
{
|
||||
// 创建导出选项
|
||||
var exportOptions = new NwdExportOptions
|
||||
{
|
||||
ExcludeHiddenItems = true
|
||||
};
|
||||
|
||||
// 执行导出
|
||||
document.ExportToNwd(filePath, exportOptions);
|
||||
LogManager.Info($"[SectionBoxExporter] NWD导出完成: {objects.Count} 个对象 -> {filePath}");
|
||||
return filePath;
|
||||
});
|
||||
});
|
||||
|
||||
return result;
|
||||
/// <summary>
|
||||
/// 【优化】导出为NWD文件,使用预计算的遍历结果
|
||||
/// 适用于剖面盒导出场景,避免重复遍历模型树
|
||||
/// </summary>
|
||||
/// <param name="document">Navisworks文档</param>
|
||||
/// <param name="traversalResult">预计算的遍历结果(包含对象和隐藏节点)</param>
|
||||
/// <param name="filePath">导出文件路径</param>
|
||||
/// <returns>导出文件路径,失败返回null</returns>
|
||||
public string ExportToNwd(Document document, SectionBoxTraversalResult traversalResult, string filePath)
|
||||
{
|
||||
return NwdExportHelper.ExportToNwdWithPrecomputedHiddenItems(
|
||||
traversalResult.ObjectsInBox,
|
||||
traversalResult.ItemsToHide,
|
||||
filePath,
|
||||
"剖面盒导出");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -1866,12 +1866,10 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
bool exportResult = false;
|
||||
string errorMessage = "";
|
||||
|
||||
// 使用 SectionBoxExporter 进行导出
|
||||
var exporter = new SectionBoxExporter();
|
||||
|
||||
if (exportAsJson)
|
||||
{
|
||||
// JSON导出
|
||||
// JSON导出(使用 SectionBoxExporter)
|
||||
var exporter = new SectionBoxExporter();
|
||||
await Task.Run(() =>
|
||||
{
|
||||
var result = exporter.ExportToJson(document, items, saveFilePath);
|
||||
@ -1880,10 +1878,10 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
}
|
||||
else
|
||||
{
|
||||
// NWD导出
|
||||
// NWD导出(使用 NwdExportHelper)
|
||||
await Task.Run(() =>
|
||||
{
|
||||
var result = exporter.ExportToNwd(document, items, saveFilePath);
|
||||
var result = NwdExportHelper.ExportToNwd(items, saveFilePath);
|
||||
exportResult = !string.IsNullOrEmpty(result);
|
||||
});
|
||||
}
|
||||
@ -1985,29 +1983,30 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
new Point3D(box.Max.X, box.Max.Y, box.Max.Z)
|
||||
);
|
||||
|
||||
// 异步获取剖面盒内的对象
|
||||
// 【优化】异步获取剖面盒内的对象和需要隐藏的节点(一次遍历完成)
|
||||
CurrentOperationText = "正在查找剖面盒内的对象...";
|
||||
List<ModelItem> objectsInSectionBox = null;
|
||||
SectionBoxExporter.SectionBoxTraversalResult traversalResult = null;
|
||||
|
||||
await Task.Run(() =>
|
||||
{
|
||||
objectsInSectionBox = GetObjectsInSectionBox(document, sectionBoxBounds);
|
||||
var exporter = new SectionBoxExporter();
|
||||
traversalResult = exporter.GetObjectsAndHiddenItems(document, sectionBoxBounds);
|
||||
});
|
||||
|
||||
if (objectsInSectionBox.Count == 0)
|
||||
if (traversalResult.ObjectsInBox.Count == 0)
|
||||
{
|
||||
MessageBox.Show("剖面盒内没有找到对象!", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
return;
|
||||
}
|
||||
|
||||
LogManager.Info($"[LayerManagementViewModel] 剖面盒内找到 {objectsInSectionBox.Count} 个对象");
|
||||
LogManager.Info($"[LayerManagementViewModel] 剖面盒内找到 {traversalResult.ObjectsInBox.Count} 个对象,可隐藏 {traversalResult.ItemsToHide.Count} 个节点");
|
||||
|
||||
// 生成默认文件名
|
||||
string timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
|
||||
string defaultFileName = $"SectionBox_Export_{timestamp}";
|
||||
|
||||
// 调用通用导出方法
|
||||
await ExportItemsToNwdAsync(objectsInSectionBox, "导出剖面盒", defaultFileName, false);
|
||||
// 【优化】使用预计算结果的导出方法
|
||||
await ExportSectionBoxToNwdAsync(traversalResult, "导出剖面盒", defaultFileName);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -2030,6 +2029,99 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
return exporter.GetObjectsInSectionBox(document, sectionBox);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 【优化】导出剖面盒到NWD,使用预计算的遍历结果
|
||||
/// 避免重复遍历模型树
|
||||
/// </summary>
|
||||
private async Task ExportSectionBoxToNwdAsync(
|
||||
SectionBoxExporter.SectionBoxTraversalResult traversalResult,
|
||||
string dialogTitle,
|
||||
string defaultFileName)
|
||||
{
|
||||
if (traversalResult?.ObjectsInBox == null || traversalResult.ObjectsInBox.Count == 0)
|
||||
{
|
||||
MessageBox.Show("没有要导出的对象", "导出提示", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
LogManager.Info($"[LayerManagementViewModel] 开始导出 {traversalResult.ObjectsInBox.Count} 个对象,预计算隐藏节点 {traversalResult.ItemsToHide.Count} 个");
|
||||
IsProcessing = true;
|
||||
CurrentOperationText = "准备导出...";
|
||||
|
||||
var document = Autodesk.Navisworks.Api.Application.ActiveDocument;
|
||||
|
||||
// 获取保存路径
|
||||
string saveFilePath = null;
|
||||
System.Windows.Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
var saveDialog = new Microsoft.Win32.SaveFileDialog
|
||||
{
|
||||
Title = dialogTitle,
|
||||
Filter = "Navisworks文件 (*.nwd)|*.nwd",
|
||||
DefaultExt = "nwd",
|
||||
FileName = defaultFileName
|
||||
};
|
||||
|
||||
if (saveDialog.ShowDialog() == true)
|
||||
{
|
||||
saveFilePath = saveDialog.FileName;
|
||||
}
|
||||
});
|
||||
|
||||
if (string.IsNullOrEmpty(saveFilePath))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool exportResult = false;
|
||||
string errorMessage = "";
|
||||
|
||||
// 【优化】使用预计算结果直接导出,无需再次计算隐藏节点
|
||||
await Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = NwdExportHelper.ExportToNwdWithPrecomputedHiddenItems(
|
||||
traversalResult.ObjectsInBox,
|
||||
traversalResult.ItemsToHide,
|
||||
saveFilePath,
|
||||
"剖面盒导出");
|
||||
exportResult = !string.IsNullOrEmpty(result);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
errorMessage = ex.Message;
|
||||
LogManager.Error($"[LayerManagementViewModel] 导出失败: {ex.Message}");
|
||||
}
|
||||
});
|
||||
|
||||
// 显示结果
|
||||
if (exportResult && File.Exists(saveFilePath))
|
||||
{
|
||||
var fileInfo = new FileInfo(saveFilePath);
|
||||
MessageBox.Show(
|
||||
$"NWD导出成功!\n\n文件: {saveFilePath}\n大小: {fileInfo.Length / 1024} KB\n对象数: {traversalResult.ObjectsInBox.Count}",
|
||||
"导出结果", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show($"NWD导出失败: {errorMessage}", "导出错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"[LayerManagementViewModel] 导出过程异常: {ex.Message}", ex);
|
||||
MessageBox.Show($"导出过程异常: {ex.Message}", "导出错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsProcessing = false;
|
||||
CurrentOperationText = "";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试ExportToNwd API - 专门的导出API
|
||||
/// </summary>
|
||||
|
||||
116
src/Utils/NwdExportHelper.cs
Normal file
116
src/Utils/NwdExportHelper.cs
Normal file
@ -0,0 +1,116 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows;
|
||||
using Autodesk.Navisworks.Api;
|
||||
using NavisApplication = Autodesk.Navisworks.Api.Application;
|
||||
|
||||
namespace NavisworksTransport.Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// NWD 文件导出工具类
|
||||
/// 提供通用的 NWD 导出功能,与具体业务场景解耦
|
||||
/// </summary>
|
||||
public static class NwdExportHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 导出指定对象到 NWD 文件
|
||||
/// 使用 ExecuteInIsolation 自动计算并隐藏无关节点
|
||||
/// </summary>
|
||||
/// <param name="objects">要导出的对象列表</param>
|
||||
/// <param name="filePath">导出文件路径</param>
|
||||
/// <param name="excludeHiddenItems">是否排除隐藏项,默认 true</param>
|
||||
/// <returns>导出文件路径,失败返回 null</returns>
|
||||
public static string ExportToNwd(List<ModelItem> objects, string filePath, bool excludeHiddenItems = true)
|
||||
{
|
||||
if (objects == null || objects.Count == 0)
|
||||
throw new ArgumentException("对象列表不能为空", nameof(objects));
|
||||
if (string.IsNullOrEmpty(filePath))
|
||||
throw new ArgumentException("文件路径不能为空", nameof(filePath));
|
||||
|
||||
var document = NavisApplication.ActiveDocument;
|
||||
if (document == null)
|
||||
{
|
||||
LogManager.Warning("[NwdExportHelper] 没有活动文档");
|
||||
return null;
|
||||
}
|
||||
|
||||
// 必须在主线程执行
|
||||
string result = null;
|
||||
System.Windows.Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
// 准备要显示的项目
|
||||
var itemsToShow = new ModelItemCollection();
|
||||
foreach (var item in objects)
|
||||
itemsToShow.Add(item);
|
||||
|
||||
// 在隔离模式下执行导出
|
||||
result = VisibilityHelper.ExecuteInIsolation(itemsToShow, () =>
|
||||
{
|
||||
var exportOptions = new NwdExportOptions
|
||||
{
|
||||
ExcludeHiddenItems = excludeHiddenItems
|
||||
};
|
||||
|
||||
document.ExportToNwd(filePath, exportOptions);
|
||||
LogManager.Info($"[NwdExportHelper] NWD导出完成: {objects.Count} 个对象 -> {filePath}");
|
||||
return filePath;
|
||||
});
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使用预计算的隐藏节点列表导出到 NWD 文件
|
||||
/// 适用于已经遍历并计算好隐藏节点的场景(如剖面盒导出)
|
||||
/// </summary>
|
||||
/// <param name="objects">要导出的对象列表</param>
|
||||
/// <param name="itemsToHide">预计算的隐藏节点集合</param>
|
||||
/// <param name="filePath">导出文件路径</param>
|
||||
/// <param name="operationName">操作名称(用于日志)</param>
|
||||
/// <returns>导出文件路径,失败返回 null</returns>
|
||||
public static string ExportToNwdWithPrecomputedHiddenItems(
|
||||
List<ModelItem> objects,
|
||||
ModelItemCollection itemsToHide,
|
||||
string filePath,
|
||||
string operationName = "NWD导出")
|
||||
{
|
||||
if (objects == null || objects.Count == 0)
|
||||
throw new ArgumentException("对象列表不能为空", nameof(objects));
|
||||
if (string.IsNullOrEmpty(filePath))
|
||||
throw new ArgumentException("文件路径不能为空", nameof(filePath));
|
||||
|
||||
var document = NavisApplication.ActiveDocument;
|
||||
if (document == null)
|
||||
{
|
||||
LogManager.Warning($"[NwdExportHelper] {operationName}失败:没有活动文档");
|
||||
return null;
|
||||
}
|
||||
|
||||
// 必须在主线程执行
|
||||
string result = null;
|
||||
System.Windows.Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
// 使用预计算隐藏节点的方法
|
||||
result = VisibilityHelper.ExecuteWithPrecomputedHiddenItems(
|
||||
itemsToHide,
|
||||
() =>
|
||||
{
|
||||
var exportOptions = new NwdExportOptions
|
||||
{
|
||||
ExcludeHiddenItems = true
|
||||
};
|
||||
|
||||
document.ExportToNwd(filePath, exportOptions);
|
||||
|
||||
LogManager.Info($"[NwdExportHelper] {operationName}完成: {objects.Count} 个对象,隐藏 {itemsToHide?.Count ?? 0} 个节点 -> {filePath}");
|
||||
return filePath;
|
||||
},
|
||||
operationName
|
||||
);
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -244,6 +244,60 @@ namespace NavisworksTransport
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 【新增】应用预计算的隐藏节点列表,并保存当前状态用于后续恢复
|
||||
/// 用于优化场景:遍历和计算隐藏节点已经完成,只需直接应用
|
||||
/// </summary>
|
||||
/// <param name="itemsToHide">预计算的隐藏节点集合</param>
|
||||
/// <param name="action">在应用隐藏后执行的操作</param>
|
||||
/// <param name="operationName">操作名称(用于日志)</param>
|
||||
/// <returns>操作结果</returns>
|
||||
public static T ExecuteWithPrecomputedHiddenItems<T>(ModelItemCollection itemsToHide, Func<T> action, string operationName = "预计算隐藏")
|
||||
{
|
||||
var document = NavisApplication.ActiveDocument;
|
||||
if (document == null)
|
||||
{
|
||||
LogManager.Warning($"[VisibilityHelper] {operationName}失败:没有活动文档");
|
||||
return default(T);
|
||||
}
|
||||
|
||||
// 保存当前状态
|
||||
var savedState = SaveVisibilityStateInternal(document);
|
||||
|
||||
try
|
||||
{
|
||||
// 1. 全部显示
|
||||
document.Models.ResetAllHidden();
|
||||
|
||||
// 2. 直接应用预计算的隐藏节点
|
||||
if (itemsToHide != null && itemsToHide.Count > 0)
|
||||
{
|
||||
document.Models.SetHidden(itemsToHide, true);
|
||||
LogManager.Debug($"[VisibilityHelper] {operationName}:应用 {itemsToHide.Count} 个预计算隐藏节点");
|
||||
}
|
||||
|
||||
// 3. 执行操作
|
||||
return action.Invoke();
|
||||
}
|
||||
finally
|
||||
{
|
||||
// 4. 恢复状态
|
||||
RestoreVisibilityStateInternal(document, savedState);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 【新增】应用预计算的隐藏节点列表(无返回值版本)
|
||||
/// </summary>
|
||||
public static void ExecuteWithPrecomputedHiddenItems(ModelItemCollection itemsToHide, Action action, string operationName = "预计算隐藏")
|
||||
{
|
||||
ExecuteWithPrecomputedHiddenItems<object>(itemsToHide, () =>
|
||||
{
|
||||
action?.Invoke();
|
||||
return null;
|
||||
}, operationName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在隔离模式下执行操作,自动恢复可见性
|
||||
/// </summary>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user