diff --git a/.serena/cache/csharp/document_symbols_cache_v23-06-25.pkl b/.serena/cache/csharp/document_symbols_cache_v23-06-25.pkl
index 0b29118..e1f17f2 100644
Binary files a/.serena/cache/csharp/document_symbols_cache_v23-06-25.pkl and b/.serena/cache/csharp/document_symbols_cache_v23-06-25.pkl differ
diff --git a/NavisworksTransportPlugin.csproj b/NavisworksTransportPlugin.csproj
index 67c32b8..fb302f4 100644
--- a/NavisworksTransportPlugin.csproj
+++ b/NavisworksTransportPlugin.csproj
@@ -218,7 +218,6 @@
-
diff --git a/src/Core/ModelSplitterManager.cs b/src/Core/ModelSplitterManager.cs
index b6e4897..0ca0d79 100644
--- a/src/Core/ModelSplitterManager.cs
+++ b/src/Core/ModelSplitterManager.cs
@@ -139,7 +139,6 @@ namespace NavisworksTransport
private readonly FloorDetector _floorDetector;
private readonly AttributeGrouper _attributeGrouper;
- private readonly NavisworksFileExporter _fileExporter;
private bool _isSplitting = false;
#endregion
@@ -150,7 +149,6 @@ namespace NavisworksTransport
{
_floorDetector = new FloorDetector();
_attributeGrouper = new AttributeGrouper();
- _fileExporter = new NavisworksFileExporter();
LogManager.Info("[ModelSplitter] 模型分层管理器已初始化");
}
@@ -597,7 +595,60 @@ namespace NavisworksTransport
LogManager.Info("[ModelSplitter] 开始导出文件...");
LogManager.Info($"[ModelSplitter] 目标文件: {result.OutputFilePath}");
- bool exportSuccess = await _fileExporter.ExportModelItemsAsync(preview.Items, result.OutputFilePath);
+ // 直接使用 Navisworks API 导出
+ bool exportSuccess = false;
+ try
+ {
+ var document = NavisApplication.ActiveDocument;
+
+ // 保存当前可见性状态并重置
+ document.Models.ResetAllHidden();
+
+ // 隐藏不需要的项目
+ var allItems = new ModelItemCollection();
+ allItems.AddRange(document.Models.RootItemDescendantsAndSelf);
+
+ var itemsToHide = new ModelItemCollection();
+ foreach (ModelItem item in allItems)
+ {
+ bool shouldKeep = false;
+ foreach (ModelItem exportItem in preview.Items)
+ {
+ if (item.Equals(exportItem))
+ {
+ shouldKeep = true;
+ break;
+ }
+ }
+
+ if (!shouldKeep)
+ {
+ itemsToHide.Add(item);
+ }
+ }
+
+ if (itemsToHide.Count > 0)
+ {
+ document.Models.SetHidden(itemsToHide, true);
+ }
+
+ // 创建导出选项并导出
+ var exportOptions = new Autodesk.Navisworks.Api.NwdExportOptions();
+ exportOptions.ExcludeHiddenItems = true;
+ exportOptions.EmbedXrefs = false;
+ exportOptions.PreventObjectPropertyExport = false;
+
+ document.ExportToNwd(result.OutputFilePath, exportOptions);
+ exportSuccess = true;
+
+ // 恢复可见性
+ document.Models.ResetAllHidden();
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error($"[ModelSplitter] 导出异常: {ex.Message}");
+ exportSuccess = false;
+ }
LogManager.Info($"[ModelSplitter] 文件导出结果: {exportSuccess}");
diff --git a/src/Core/SimplifiedModelSplitterManager.cs b/src/Core/SimplifiedModelSplitterManager.cs
index 53b6748..ff791d4 100644
--- a/src/Core/SimplifiedModelSplitterManager.cs
+++ b/src/Core/SimplifiedModelSplitterManager.cs
@@ -110,7 +110,6 @@ namespace NavisworksTransport
private readonly FloorDetector _floorDetector;
private readonly AttributeGrouper _attributeGrouper;
- private readonly NavisworksFileExporter _fileExporter;
// 楼层检测结果缓存
private readonly Dictionary> _floorCache;
@@ -125,7 +124,6 @@ namespace NavisworksTransport
{
_floorDetector = new FloorDetector();
_attributeGrouper = new AttributeGrouper();
- _fileExporter = new NavisworksFileExporter();
// 初始化缓存
_floorCache = new Dictionary>();
@@ -974,20 +972,158 @@ namespace NavisworksTransport
var itemsToExport = preview.Items;
LogManager.Info($"[SimplifiedModelSplitter] 将导出 {itemsToExport.Count} 个模型项");
- // 使用异步方法导出
- var exportTask = _fileExporter.ExportModelItemsAsync(itemsToExport, outputPath);
- bool exportSuccess = exportTask.Result;
+ // 检查线程状态
+ var apartmentState = System.Threading.Thread.CurrentThread.GetApartmentState();
+ LogManager.Info($"[SimplifiedModelSplitter] 当前线程状态: {apartmentState}");
- if (exportSuccess)
+ // 核心修复:确保在主 UI 线程中执行 Navisworks API 调用
+ bool exportResult = false;
+ Exception exportException = null;
+
+ // 使用 Application.Current.Dispatcher.Invoke 确保在主线程中执行
+ System.Windows.Application.Current.Dispatcher.Invoke(() =>
{
- LogManager.Info($"[SimplifiedModelSplitter] ========== ExportLayerToNwd完成 ========== 成功导出到: {outputPath}");
- return true;
- }
- else
+ try
+ {
+ LogManager.Info($"[SimplifiedModelSplitter] 在主线程中执行导出操作");
+ var document = NavisApplication.ActiveDocument;
+
+ // 保存当前可见性状态(在主线程中)
+ LogManager.Info($"[SimplifiedModelSplitter] 开始保存当前可见性状态");
+ var originalVisibilityState = SaveCurrentVisibilityState(document);
+ LogManager.Info($"[SimplifiedModelSplitter] 已保存 {originalVisibilityState.Count} 个项目的可见性状态");
+
+ try
+ {
+ // 采用智能隐藏策略:只操作顶级节点,避免遍历所有项目
+ var allTopLevelItems = new List();
+
+ // 只获取顶级节点,不遍历全部项目
+ foreach (Model model in document.Models)
+ {
+ foreach (ModelItem topLevelItem in model.RootItem.Children)
+ {
+ allTopLevelItems.Add(topLevelItem);
+ }
+ }
+
+ LogManager.Info($"[SimplifiedModelSplitter] 收集到 {allTopLevelItems.Count} 个顶级节点");
+
+ // 智能隐藏策略:如果顶级节点包含要导出的项目,则保持可见;否则隐藏整个顶级分支
+ var itemsToHide = new ModelItemCollection();
+ int hiddenCount = 0;
+
+ foreach (ModelItem topLevelItem in allTopLevelItems)
+ {
+ bool shouldKeepTopLevel = false;
+
+ // 检查这个顶级节点本身是否在导出列表中
+ foreach (ModelItem exportItem in itemsToExport)
+ {
+ if (topLevelItem.Equals(exportItem))
+ {
+ shouldKeepTopLevel = true;
+ LogManager.Info($"[SimplifiedModelSplitter] 顶级节点 {topLevelItem.DisplayName} 本身被选中,保持可见");
+ break;
+ }
+ }
+
+ // 如果顶级节点本身不在导出列表中,检查是否有任何导出项是它的后代
+ if (!shouldKeepTopLevel)
+ {
+ foreach (var exportItem in itemsToExport)
+ {
+ var current = exportItem;
+ while (current != null)
+ {
+ if (current == topLevelItem)
+ {
+ shouldKeepTopLevel = true;
+ LogManager.Info($"[SimplifiedModelSplitter] 顶级节点 {topLevelItem.DisplayName} 包含导出项目,保持可见");
+ break;
+ }
+ current = current.Parent;
+ }
+ if (shouldKeepTopLevel) break;
+ }
+ }
+
+ // 如果这个顶级节点不需要保持可见,则隐藏它
+ if (!shouldKeepTopLevel)
+ {
+ try
+ {
+ itemsToHide.Add(topLevelItem);
+ hiddenCount++;
+ LogManager.Info($"[SimplifiedModelSplitter] 隐藏顶级节点: {topLevelItem.DisplayName}");
+ }
+ catch (Exception ex)
+ {
+ LogManager.Warning($"[SimplifiedModelSplitter] 添加隐藏项目失败: {topLevelItem.DisplayName} - {ex.Message}");
+ }
+ }
+ }
+
+ // 执行隐藏操作
+ if (itemsToHide.Count > 0)
+ {
+ try
+ {
+ document.Models.SetHidden(itemsToHide, true);
+ LogManager.Info($"[SimplifiedModelSplitter] 成功隐藏 {hiddenCount} 个顶级节点,保留导出项目可见");
+ }
+ catch (Exception ex)
+ {
+ LogManager.Warning($"[SimplifiedModelSplitter] 隐藏操作失败: {ex.Message}");
+ }
+ }
+
+ // 创建导出选项
+ var exportOptions = new Autodesk.Navisworks.Api.NwdExportOptions
+ {
+ ExcludeHiddenItems = true, // 只导出可见项目
+ EmbedXrefs = false,
+ PreventObjectPropertyExport = false
+ };
+
+ LogManager.Info($"[SimplifiedModelSplitter] 开始调用ExportToNwd API(主线程)");
+
+ // 在主线程中执行导出
+ document.ExportToNwd(outputPath, exportOptions);
+
+ LogManager.Info($"[SimplifiedModelSplitter] ExportToNwd API调用完成(主线程)");
+ exportResult = true;
+ }
+ finally
+ {
+ // 恢复原始可见性状态(在主线程中)
+ try
+ {
+ RestoreVisibilityState(document, originalVisibilityState);
+ LogManager.Info($"[SimplifiedModelSplitter] 已恢复原始可见性状态");
+ }
+ catch (Exception restoreEx)
+ {
+ LogManager.Error($"[SimplifiedModelSplitter] 恢复可见性失败: {restoreEx.Message}");
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ exportException = ex;
+ }
+ });
+
+ // 检查导出结果
+ if (exportException != null)
{
- LogManager.Error($"[SimplifiedModelSplitter] 导出失败: {outputPath}");
+ LogManager.Error($"[SimplifiedModelSplitter] 主线程导出异常: {exportException.Message}");
+ LogManager.Error($"[SimplifiedModelSplitter] 异常堆栈: {exportException.StackTrace}");
return false;
}
+
+ LogManager.Info($"[SimplifiedModelSplitter] ========== ExportLayerToNwd完成 ========== 成功导出到: {outputPath}");
+ return exportResult;
}
catch (Exception ex)
{
@@ -997,157 +1133,41 @@ namespace NavisworksTransport
}
}
-
///
- /// 根据分层结果获取该层包含的模型项
+ /// 保存当前可见性状态(参考"保存当前选择项"的方法)
///
- private ModelItemCollection GetLayerModelItems(SplitPreviewResult preview, SplitConfiguration config)
+ private Dictionary SaveCurrentVisibilityState(Document document)
{
+ var visibilityState = new Dictionary();
+
try
{
- LogManager.Info($"[SimplifiedModelSplitter] ========== GetLayerModelItems开始 ==========");
- LogManager.Info($"[SimplifiedModelSplitter] 目标分层: {preview.LayerName}, 策略: {config.Strategy}");
-
- // 优先使用预览结果中已缓存的模型项
- if (preview.Items != null && preview.Items.Count > 0)
+ // 获取所有顶级项目并记录它们的可见性状态
+ foreach (Model model in document.Models)
{
- LogManager.Info($"[SimplifiedModelSplitter] 使用预览结果中的缓存模型项,数量: {preview.Items.Count}");
-
- // 关键修复:展开楼层顶层节点,收集所有子节点
- LogManager.Info($"[SimplifiedModelSplitter] 开始展开楼层节点,收集完整的子节点内容...");
- var expandedItems = ExpandFloorItems(preview.Items);
- LogManager.Info($"[SimplifiedModelSplitter] 楼层节点展开完成: 原始{preview.Items.Count}个 -> 展开后{expandedItems.Count}个");
-
- return expandedItems;
+ foreach (ModelItem topLevelItem in model.RootItem.Children)
+ {
+ try
+ {
+ // 记录是否隐藏(IsHidden为true表示隐藏,我们存储可见性所以取反)
+ visibilityState[topLevelItem] = !topLevelItem.IsHidden;
+ }
+ catch
+ {
+ // 如果无法获取状态,默认为可见
+ visibilityState[topLevelItem] = true;
+ }
+ }
}
- LogManager.Info($"[SimplifiedModelSplitter] 预览结果中没有模型项,开始重新检测");
-
- var document = NavisApplication.ActiveDocument;
- if (document?.Models?.Count == 0)
- {
- LogManager.Warning($"[SimplifiedModelSplitter] 文档无效或没有模型");
- return new ModelItemCollection();
- }
-
- var allItems = GetAllModelItems(config.MaxDepth);
- LogManager.Info($"[SimplifiedModelSplitter] 获取到总模型项数: {allItems.Count},深度: {config.MaxDepth}");
- var layerItems = new ModelItemCollection();
-
- switch (config.Strategy)
- {
- case SplitStrategy.ByFloor:
- LogManager.Info($"[SimplifiedModelSplitter] 使用楼层策略,开始重新检测楼层");
- // 按楼层分层:使用FloorDetector重新检测并匹配层名
- var floors = _floorDetector.DetectFloors(allItems, null, config.MaxDepth);
- LogManager.Info($"[SimplifiedModelSplitter] 检测到楼层数: {floors?.Count ?? 0}");
-
- if (floors != null)
- {
- foreach (var floor in floors)
- {
- string sanitizedFloorName = SanitizeLayerName(floor.FloorName);
- LogManager.Info($"[SimplifiedModelSplitter] 楼层匹配检查: 原始名称='{floor.FloorName}' -> 清理后='{sanitizedFloorName}', 目标='{preview.LayerName}', 匹配={sanitizedFloorName == preview.LayerName}");
- }
- }
-
- var matchingFloor = floors?.FirstOrDefault(f => SanitizeLayerName(f.FloorName) == preview.LayerName);
- if (matchingFloor != null)
- {
- LogManager.Info($"[SimplifiedModelSplitter] 找到匹配楼层: 原始名称='{matchingFloor.FloorName}', 清理后名称='{preview.LayerName}', 包含模型项: {matchingFloor.ItemCount}");
-
- // 关键修复:直接使用FloorDetector检测结果,并展开所有子节点
- if (matchingFloor.Items != null && matchingFloor.Items.Count > 0)
- {
- LogManager.Info($"[SimplifiedModelSplitter] 直接使用FloorDetector的模型项结果,数量: {matchingFloor.Items.Count}");
- LogManager.Info($"[SimplifiedModelSplitter] 开始展开楼层节点,收集完整的子节点内容...");
-
- // 展开楼层顶层节点,收集所有子节点
- var expandedItems = ExpandFloorItems(matchingFloor.Items);
- LogManager.Info($"[SimplifiedModelSplitter] 楼层节点展开完成: 原始{matchingFloor.Items.Count}个 -> 展开后{expandedItems.Count}个");
-
- layerItems = expandedItems;
- }
- else
- {
- LogManager.Info($"[SimplifiedModelSplitter] FloorDetector结果中没有模型项,使用原始名称重新查找: '{matchingFloor.FloorName}'");
- var foundItems = GetFloorItems(allItems, matchingFloor.FloorName, config.MaxDepth);
- LogManager.Info($"[SimplifiedModelSplitter] 重新查找结果: {foundItems.Count}个模型项");
-
- // 同样展开找到的楼层项目
- if (foundItems.Count > 0)
- {
- var expandedItems = ExpandFloorItems(foundItems);
- LogManager.Info($"[SimplifiedModelSplitter] 重新查找的楼层项目展开完成: 原始{foundItems.Count}个 -> 展开后{expandedItems.Count}个");
- layerItems = expandedItems;
- }
- else
- {
- layerItems = foundItems;
- }
- }
- }
- else
- {
- LogManager.Warning($"[SimplifiedModelSplitter] 未找到匹配的楼层: {preview.LayerName}");
- }
- break;
-
- case SplitStrategy.ByAttribute:
- LogManager.Info($"[SimplifiedModelSplitter] 使用属性策略: {config.AttributeName}");
- // 按属性分层:使用AttributeGrouper重新分组并匹配层名
- var groups = _attributeGrouper.GroupByAttribute(allItems, config.AttributeName);
- LogManager.Info($"[SimplifiedModelSplitter] 检测到属性组数: {groups?.Count ?? 0}");
-
- if (groups != null)
- {
- foreach (var group in groups)
- {
- string sanitizedGroupName = SanitizeLayerName(group.GroupName);
- LogManager.Info($"[SimplifiedModelSplitter] 属性组匹配检查: 原始名称='{group.GroupName}' -> 清理后='{sanitizedGroupName}', 目标='{preview.LayerName}', 匹配={sanitizedGroupName == preview.LayerName}");
- }
- }
-
- var matchingGroup = groups?.FirstOrDefault(g => SanitizeLayerName(g.GroupName) == preview.LayerName);
- if (matchingGroup != null)
- {
- LogManager.Info($"[SimplifiedModelSplitter] 找到匹配属性组: 原始名称='{matchingGroup.GroupName}', 清理后名称='{preview.LayerName}', 包含模型项: {matchingGroup.ItemCount}");
-
- // 直接使用AttributeGrouper检测结果中的模型项,避免重新检测
- if (matchingGroup.Items != null && matchingGroup.Items.Count > 0)
- {
- LogManager.Info($"[SimplifiedModelSplitter] 直接使用AttributeGrouper的模型项结果,数量: {matchingGroup.Items.Count}");
- // 属性分组通常已经是完整的构件,不需要展开,但为了保持一致性,仍然检查
- var expandedItems = ExpandFloorItems(matchingGroup.Items);
- LogManager.Info($"[SimplifiedModelSplitter] 属性组项目展开完成: 原始{matchingGroup.Items.Count}个 -> 展开后{expandedItems.Count}个");
- layerItems = expandedItems;
- }
- else
- {
- LogManager.Info($"[SimplifiedModelSplitter] AttributeGrouper结果中没有模型项,使用原始名称重新查找: '{matchingGroup.GroupName}'");
- layerItems = GetAttributeGroupItems(allItems, config.AttributeName, matchingGroup.GroupName);
- }
- }
- else
- {
- LogManager.Warning($"[SimplifiedModelSplitter] 未找到匹配的属性组: {preview.LayerName}");
- }
- break;
-
- default:
- LogManager.Warning($"[SimplifiedModelSplitter] 不支持的分层策略: {config.Strategy}");
- break;
- }
-
- LogManager.Info($"[SimplifiedModelSplitter] ========== GetLayerModelItems完成 ========== 获取到 {layerItems.Count} 个分层模型项");
- return layerItems;
+ LogManager.Info($"[SimplifiedModelSplitter] 保存可见性状态完成,记录了 {visibilityState.Count} 个顶级项目");
}
catch (Exception ex)
{
- LogManager.Error($"[SimplifiedModelSplitter] 获取分层模型项失败: {ex.Message}");
- LogManager.Error($"[SimplifiedModelSplitter] 异常堆栈: {ex.StackTrace}");
- return new ModelItemCollection();
+ LogManager.Error($"[SimplifiedModelSplitter] 保存可见性状态失败: {ex.Message}");
}
+
+ return visibilityState;
}
///
@@ -1598,42 +1618,6 @@ namespace NavisworksTransport
return false;
}
- ///
- /// 保存当前可见性状态
- ///
- private Dictionary SaveVisibilityState(Document document)
- {
- var visibilityState = new Dictionary();
-
- try
- {
- // 这里需要保存所有模型项的可见性状态
- // 简化实现:记录隐藏的项目
- var allItems = new ModelItemCollection();
- allItems.AddRange(document.Models.RootItemDescendantsAndSelf);
-
- foreach (ModelItem item in allItems)
- {
- try
- {
- // Navisworks中检查项目是否隐藏的方法
- visibilityState[item] = !item.IsHidden;
- }
- catch
- {
- // 如果无法获取状态,默认为可见
- visibilityState[item] = true;
- }
- }
- }
- catch (Exception ex)
- {
- LogManager.Error($"[SimplifiedModelSplitter] 保存可见性状态失败: {ex.Message}");
- }
-
- return visibilityState;
- }
-
///
/// 恢复可见性状态
///
@@ -1701,84 +1685,6 @@ namespace NavisworksTransport
}
}
- ///
- /// 隐藏除指定项目外的其他所有项目 - 使用成熟的可见性控制模式
- ///
- private void HideOtherItems(Document document, ModelItemCollection keepVisible)
- {
- try
- {
- LogManager.Info($"[SimplifiedModelSplitter] 开始隐藏其他项目,保持可见: {keepVisible.Count} 个项目");
-
- // 获取所有项目 - 使用安全的AddRange方法
- var allItems = new ModelItemCollection();
- allItems.AddRange(document.Models.RootItemDescendantsAndSelf);
- LogManager.Info($"[SimplifiedModelSplitter] 总共 {allItems.Count} 个模型项目");
-
- // 先重置所有项目为可见状态,确保从干净状态开始
- document.Models.ResetAllHidden();
- LogManager.Info("[SimplifiedModelSplitter] 已重置所有项目为可见状态");
-
- // 收集需要隐藏的项目 - 不在keepVisible集合中的项目
- var itemsToHide = new ModelItemCollection();
-
- foreach (ModelItem item in allItems)
- {
- try
- {
- // 检查该项目是否在keepVisible集合中
- bool shouldKeepVisible = false;
- foreach (ModelItem visibleItem in keepVisible)
- {
- if (item.Equals(visibleItem))
- {
- shouldKeepVisible = true;
- break;
- }
- }
-
- // 如果不在保持可见的集合中,则需要隐藏
- if (!shouldKeepVisible)
- {
- itemsToHide.Add(item);
- }
- }
- catch (Exception ex)
- {
- LogManager.Warning($"[SimplifiedModelSplitter] 检查项目可见性时出错: {ex.Message}");
- }
- }
-
- LogManager.Info($"[SimplifiedModelSplitter] 需要隐藏 {itemsToHide.Count} 个项目");
-
- // 执行隐藏操作 - 使用成熟的SetHidden方法
- if (itemsToHide.Count > 0)
- {
- document.Models.SetHidden(itemsToHide, true);
- LogManager.Info($"[SimplifiedModelSplitter] 成功隐藏 {itemsToHide.Count} 个项目");
- }
- else
- {
- LogManager.Info("[SimplifiedModelSplitter] 没有项目需要隐藏");
- }
- }
- catch (Exception ex)
- {
- LogManager.Error($"[SimplifiedModelSplitter] 隐藏其他项目失败: {ex.Message}");
-
- // 异常处理:确保至少显示所有项目
- try
- {
- document.Models.ResetAllHidden();
- LogManager.Info("[SimplifiedModelSplitter] 异常恢复:重置为全部可见");
- }
- catch (Exception resetEx)
- {
- LogManager.Error($"[SimplifiedModelSplitter] 异常恢复也失败: {resetEx.Message}");
- }
- }
- }
-
///
/// 简化的环境诊断方法 - 快速检查API是否可用
///
diff --git a/src/Utils/NavisworksFileExporter.cs b/src/Utils/NavisworksFileExporter.cs
deleted file mode 100644
index b7650f9..0000000
--- a/src/Utils/NavisworksFileExporter.cs
+++ /dev/null
@@ -1,1014 +0,0 @@
-using Autodesk.Navisworks.Api;
-using System;
-using System.IO;
-using System.Threading.Tasks;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace NavisworksTransport
-{
- ///
- /// Navisworks文件导出器 - 负责将模型元素导出为独立的Navisworks文件
- ///
- public class NavisworksFileExporter
- {
- #region 枚举和常量
-
- ///
- /// 导出策略枚举
- ///
- public enum ExportStrategy
- {
- VisibilityControl, // 通过可见性控制
- SelectionBased, // 基于选择集
- CopyToNewDocument // 复制到新文档
- }
-
- ///
- /// 导出配置
- ///
- public class ExportConfiguration
- {
- public ExportStrategy Strategy { get; set; } = ExportStrategy.VisibilityControl;
- public bool PreserveViewpoints { get; set; } = false;
- public bool PreserveAnimations { get; set; } = false;
- public bool PreserveClashTests { get; set; } = false;
- public bool CompressOutput { get; set; } = true;
- public string FileFormat { get; set; } = "nwd"; // nwd, nwf, nwc
- public int TimeoutSeconds { get; set; } = 300;
- public bool CreateBackup { get; set; } = true;
- }
-
- #endregion
-
- #region 事件定义
-
- public event EventHandler StatusChanged;
- public event EventHandler ProgressChanged;
- public event EventHandler ErrorOccurred;
-
- #endregion
-
- #region 私有字段
-
- private readonly VisibilityManager _visibilityManager;
- private bool _isExporting = false;
-
- #endregion
-
- #region 构造函数
-
- public NavisworksFileExporter()
- {
- _visibilityManager = new VisibilityManager();
- LogManager.Info("[FileExporter] Navisworks文件导出器已初始化");
- }
-
- #endregion
-
- #region 公共方法
-
- ///
- /// 异步导出模型元素到文件
- ///
- /// 要导出的模型元素
- /// 输出文件路径
- /// 导出配置
- /// 导出是否成功
- public async Task ExportModelItemsAsync(ModelItemCollection items, string outputPath, ExportConfiguration config = null)
- {
- if (_isExporting)
- {
- throw new InvalidOperationException("导出操作正在进行中");
- }
-
- try
- {
- _isExporting = true;
- config = config ?? new ExportConfiguration();
-
- LogManager.WriteSessionSeparator();
- LogManager.Info($"[FileExporter] ========== 开始文件导出 ==========");
- LogManager.Info($"[FileExporter] 元素数量: {items.Count}");
- LogManager.Info($"[FileExporter] 输出路径: {outputPath}");
- LogManager.Info($"[FileExporter] 导出策略: {config.Strategy}");
- LogManager.Info($"[FileExporter] 文件格式: {config.FileFormat}");
-
- OnStatusChanged($"开始导出 {items.Count} 个元素到 {Path.GetFileName(outputPath)}");
-
- // 记录系统状态
- LogManager.Info($"[FileExporter] 导出前内存使用: {GC.GetTotalMemory(false) / 1024 / 1024} MB");
-
- // 验证输入参数
- LogManager.Info("[FileExporter] 开始验证输入参数...");
- ValidateExportParameters(items, outputPath);
- LogManager.Info("[FileExporter] 输入参数验证完成");
-
- // 创建输出目录
- LogManager.Info("[FileExporter] 开始创建输出目录...");
- EnsureOutputDirectory(outputPath);
- LogManager.Info("[FileExporter] 输出目录创建完成");
-
- // 使用分层导出逻辑(参考保存当前选择项的验证方法)
- LogManager.Info("[FileExporter] 开始分层导出逻辑...");
- bool success = await ExportWithLayerLogicAsync(items, outputPath, config);
- LogManager.Info($"[FileExporter] 分层导出完成,结果: {success}");
-
- if (success)
- {
- LogManager.Info($"[FileExporter] 导出成功: {outputPath}");
- OnStatusChanged("导出完成");
- }
- else
- {
- LogManager.Error($"[FileExporter] 导出失败: {outputPath}");
- OnStatusChanged("导出失败");
- }
-
- return success;
- }
- catch (Exception ex)
- {
- LogManager.Error($"[FileExporter] 导出异常: {ex.Message}");
- OnErrorOccurred(ex);
- return false;
- }
- finally
- {
- _isExporting = false;
- }
- }
-
- ///
- /// 使用分层逻辑导出(参考保存当前选择项的验证方法)
- /// 业务逻辑:选择当前层,隐藏其他层,导出,恢复隐藏
- ///
- private async Task ExportWithLayerLogicAsync(ModelItemCollection items, string outputPath, ExportConfiguration config)
- {
- try
- {
- LogManager.Info("[FileExporter] 开始分层导出逻辑");
-
- var document = Application.ActiveDocument;
- if (document?.Models?.Count == 0)
- {
- LogManager.Error("[FileExporter] 没有活动文档或模型");
- return false;
- }
-
- // 保存当前选择状态
- var originalSelection = new List();
- foreach (ModelItem item in document.CurrentSelection.SelectedItems)
- {
- originalSelection.Add(item);
- }
- LogManager.Info($"[FileExporter] 已保存原始选择状态,包含 {originalSelection.Count} 个元素");
-
- try
- {
- // 1. 收集所有顶级节点(参考保存当前选择项的方法)
- var allTopLevelItems = new List();
- foreach (Model model in document.Models)
- {
- foreach (ModelItem topLevelItem in model.RootItem.Children)
- {
- allTopLevelItems.Add(topLevelItem);
- }
- }
- LogManager.Info($"[FileExporter] 收集到 {allTopLevelItems.Count} 个顶级节点");
-
- // 2. 智能隐藏策略:隐藏不包含目标元素的顶级节点
- var itemsToHide = new ModelItemCollection();
- int hiddenCount = 0;
-
- foreach (ModelItem topLevelItem in allTopLevelItems)
- {
- bool shouldKeepTopLevel = false;
-
- // 检查是否有任何目标元素属于这个顶级节点
- foreach (ModelItem targetItem in items)
- {
- var current = targetItem;
- while (current != null)
- {
- if (current == topLevelItem)
- {
- shouldKeepTopLevel = true;
- LogManager.Info($"[FileExporter] 顶级节点 {topLevelItem.DisplayName} 包含目标元素,保持可见");
- break;
- }
- current = current.Parent;
- }
- if (shouldKeepTopLevel) break;
- }
-
- // 如果这个顶级节点不需要保持可见,则隐藏它
- if (!shouldKeepTopLevel)
- {
- try
- {
- itemsToHide.Add(topLevelItem);
- hiddenCount++;
- LogManager.Info($"[FileExporter] 隐藏顶级节点: {topLevelItem.DisplayName}");
- }
- catch (Exception ex)
- {
- LogManager.Warning($"[FileExporter] 添加隐藏项目失败: {topLevelItem.DisplayName} - {ex.Message}");
- }
- }
- }
-
- // 3. 执行隐藏操作
- if (itemsToHide.Count > 0)
- {
- try
- {
- document.Models.SetHidden(itemsToHide, true);
- LogManager.Info($"[FileExporter] 成功隐藏 {hiddenCount} 个顶级节点");
- }
- catch (Exception ex)
- {
- LogManager.Warning($"[FileExporter] 隐藏操作失败: {ex.Message}");
- }
- }
-
- // 4. 确保选择目标元素
- document.CurrentSelection.Clear();
- foreach (ModelItem item in items)
- {
- try
- {
- document.CurrentSelection.Add(item);
- }
- catch (Exception ex)
- {
- LogManager.Warning($"[FileExporter] 添加选择元素失败: {item.DisplayName} - {ex.Message}");
- }
- }
- LogManager.Info($"[FileExporter] 已选择 {items.Count} 个目标元素");
-
- // 5. 使用正确的导出方法
- OnStatusChanged("正在保存文件...");
- LogManager.Info("[FileExporter] 开始调用SaveDocument...");
- bool saveSuccess = SaveDocument(document, outputPath, config);
- LogManager.Info($"[FileExporter] SaveDocument调用结果: {saveSuccess}");
-
- // 6. 恢复所有隐藏项目的可见性(参考保存当前选择项的方法)
- try
- {
- if (document?.Models != null && itemsToHide.Count > 0)
- {
- // 恢复所有顶级节点的可见性
- 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);
- LogManager.Info("[FileExporter] 已恢复所有项目可见性");
- }
- }
- }
- catch (Exception ex)
- {
- LogManager.Warning($"[FileExporter] 恢复可见性失败: {ex.Message}");
- }
-
- return saveSuccess;
- }
- finally
- {
- // 7. 恢复原始选择
- try
- {
- document.CurrentSelection.Clear();
- foreach (ModelItem item in originalSelection)
- {
- try
- {
- document.CurrentSelection.Add(item);
- }
- catch (Exception ex)
- {
- LogManager.Warning($"[FileExporter] 恢复选择项时出错: {ex.Message}");
- }
- }
- LogManager.Info("[FileExporter] 已恢复原始选择");
- }
- catch (Exception ex)
- {
- LogManager.Warning($"[FileExporter] 恢复选择失败: {ex.Message}");
- }
- }
- }
- catch (Exception ex)
- {
- LogManager.Error($"[FileExporter] 分层导出逻辑异常: {ex.Message}");
- throw;
- }
- }
-
- ///
- /// 同步导出模型元素到文件
- ///
- /// 要导出的模型元素
- /// 输出文件路径
- /// 导出配置
- /// 导出是否成功
- public bool ExportModelItems(ModelItemCollection items, string outputPath, ExportConfiguration config = null)
- {
- try
- {
- var task = ExportModelItemsAsync(items, outputPath, config);
- task.Wait();
- return task.Result;
- }
- catch (Exception ex)
- {
- LogManager.Error($"[FileExporter] 同步导出失败: {ex.Message}");
- return false;
- }
- }
-
- ///
- /// 批量导出多个分组
- ///
- /// 导出任务列表
- /// 导出配置
- /// 导出结果列表
- public async Task> BatchExportAsync(List exportTasks, ExportConfiguration config = null)
- {
- try
- {
- LogManager.Info($"[FileExporter] 开始批量导出,任务数量: {exportTasks.Count}");
-
- var results = new List();
- int completedCount = 0;
-
- foreach (var task in exportTasks)
- {
- try
- {
- OnStatusChanged($"正在导出: {task.LayerName} ({completedCount + 1}/{exportTasks.Count})");
- OnProgressChanged((int)((double)completedCount / exportTasks.Count * 100));
-
- bool success = await ExportModelItemsAsync(task.Items, task.OutputPath, config);
-
- var result = new ExportResult
- {
- LayerName = task.LayerName,
- OutputPath = task.OutputPath,
- Success = success,
- ItemCount = task.Items.Count,
- ProcessTime = DateTime.Now
- };
-
- if (success && File.Exists(task.OutputPath))
- {
- result.FileSizeBytes = new FileInfo(task.OutputPath).Length;
- }
- else if (!success)
- {
- result.ErrorMessage = "导出失败";
- }
-
- results.Add(result);
- completedCount++;
-
- LogManager.Info($"[FileExporter] 批量导出进度: {completedCount}/{exportTasks.Count}");
- }
- catch (Exception ex)
- {
- var errorResult = new ExportResult
- {
- LayerName = task.LayerName,
- OutputPath = task.OutputPath,
- Success = false,
- ErrorMessage = ex.Message,
- ItemCount = task.Items.Count,
- ProcessTime = DateTime.Now
- };
- results.Add(errorResult);
-
- LogManager.Error($"[FileExporter] 批量导出任务失败: {task.LayerName}, 错误: {ex.Message}");
- }
- }
-
- OnProgressChanged(100);
- OnStatusChanged($"批量导出完成,成功: {results.Count(r => r.Success)}, 失败: {results.Count(r => !r.Success)}");
-
- LogManager.Info($"[FileExporter] 批量导出完成,总计: {results.Count}, 成功: {results.Count(r => r.Success)}");
- return results;
- }
- catch (Exception ex)
- {
- LogManager.Error($"[FileExporter] 批量导出异常: {ex.Message}");
- throw;
- }
- }
-
- #endregion
-
- #region 数据结构
-
- ///
- /// 导出任务
- ///
- public class ExportTask
- {
- public string LayerName { get; set; }
- public ModelItemCollection Items { get; set; }
- public string OutputPath { get; set; }
- }
-
- ///
- /// 导出结果
- ///
- public class ExportResult
- {
- public string LayerName { get; set; }
- public string OutputPath { get; set; }
- public bool Success { get; set; }
- public string ErrorMessage { get; set; }
- public int ItemCount { get; set; }
- public long FileSizeBytes { get; set; }
- public DateTime ProcessTime { get; set; }
- }
-
- #endregion
-
- #region 私有方法 - 导出执行
-
- private async Task ExecuteExportAsync(ModelItemCollection items, string outputPath, ExportConfiguration config)
- {
- switch (config.Strategy)
- {
- case ExportStrategy.VisibilityControl:
- return await ExportByVisibilityControlAsync(items, outputPath, config);
-
- case ExportStrategy.SelectionBased:
- return await ExportBySelectionAsync(items, outputPath, config);
-
- case ExportStrategy.CopyToNewDocument:
- return await ExportByCopyToNewDocumentAsync(items, outputPath, config);
-
- default:
- throw new NotSupportedException($"不支持的导出策略: {config.Strategy}");
- }
- }
-
- private Task ExportByVisibilityControlAsync(ModelItemCollection items, string outputPath, ExportConfiguration config)
- {
- try
- {
- LogManager.Info("[FileExporter] 使用纯选择集策略导出(完全避免可见性操作)");
-
- var document = Application.ActiveDocument;
- if (document == null)
- {
- throw new InvalidOperationException("没有活动的Navisworks文档");
- }
-
- // 关键修复:完全避免任何可见性操作,只使用选择集
- try
- {
- OnStatusChanged("正在准备导出...");
- LogManager.Info("[FileExporter] 开始纯选择集导出流程");
-
- // 保存原始选择状态
- var originalSelection = new ModelItemCollection();
- originalSelection.CopyFrom(document.CurrentSelection.SelectedItems);
- LogManager.Info($"[FileExporter] 已保存原始选择状态,包含 {originalSelection.Count} 个元素");
-
- try
- {
- // 设置新的选择集
- OnStatusChanged("正在设置选择集...");
- LogManager.Info("[FileExporter] 清除当前选择...");
- document.CurrentSelection.Clear();
-
- LogManager.Info($"[FileExporter] 开始逐个添加 {items.Count} 个目标元素到选择集...");
-
- // 关键修复:逐个添加元素,避免批量操作导致的崩溃
- int addedCount = 0;
- foreach (ModelItem item in items)
- {
- try
- {
- document.CurrentSelection.Add(item);
- addedCount++;
-
- // 每添加50个元素记录一次进度
- if (addedCount % 50 == 0)
- {
- LogManager.Info($"[FileExporter] 已添加 {addedCount}/{items.Count} 个元素到选择集");
- }
- }
- catch (Exception addEx)
- {
- LogManager.Warning($"[FileExporter] 添加元素到选择集失败: {addEx.Message}");
- // 继续处理其他元素,不因单个元素失败而中断
- }
- }
-
- LogManager.Info($"[FileExporter] 选择集添加完成,成功添加 {addedCount}/{items.Count} 个元素");
-
- LogManager.Info("[FileExporter] 选择集设置完成");
-
- // 等待状态稳定
- LogManager.Info("[FileExporter] 等待系统稳定...");
- System.Threading.Thread.Sleep(200);
-
- // 直接导出文件,不进行任何可见性操作
- OnStatusChanged("正在保存文件...");
- LogManager.Info("[FileExporter] 开始保存文档...");
- bool saveSuccess = SaveDocument(document, outputPath, config);
- LogManager.Info($"[FileExporter] 文档保存结果: {saveSuccess}");
-
- return Task.FromResult(saveSuccess);
- }
- finally
- {
- // 恢复原始选择状态
- try
- {
- LogManager.Info("[FileExporter] 开始恢复原始选择状态...");
- document.CurrentSelection.Clear();
- if (originalSelection.Count > 0)
- {
- document.CurrentSelection.AddRange(originalSelection);
- LogManager.Info($"[FileExporter] 已恢复 {originalSelection.Count} 个原始选择元素");
- }
- else
- {
- LogManager.Info("[FileExporter] 原始选择为空,保持清空状态");
- }
- }
- catch (Exception restoreEx)
- {
- LogManager.Warning($"[FileExporter] 恢复原始选择失败: {restoreEx.Message}");
- }
- }
- }
- catch (Exception ex)
- {
- LogManager.Error($"[FileExporter] 选择集导出过程中发生异常: {ex.Message}");
- LogManager.Error($"[FileExporter] 异常堆栈: {ex.StackTrace}");
-
- // 只进行最安全的清理操作
- try
- {
- document.CurrentSelection.Clear();
- LogManager.Info("[FileExporter] 异常恢复:已清除选择集");
- }
- catch (Exception safeEx)
- {
- LogManager.Warning($"[FileExporter] 异常恢复中的安全操作也失败: {safeEx.Message}");
- }
- throw;
- }
- }
- catch (Exception ex)
- {
- LogManager.Error($"[FileExporter] 纯选择集导出失败: {ex.Message}");
- throw;
- }
- }
-
- private Task ExportBySelectionAsync(ModelItemCollection items, string outputPath, ExportConfiguration config)
- {
- try
- {
- LogManager.Info("[FileExporter] 使用选择集策略导出");
-
- var document = Application.ActiveDocument;
- if (document == null)
- {
- throw new InvalidOperationException("没有活动的Navisworks文档");
- }
-
- // 保存当前选择
- var originalSelection = new ModelItemCollection();
- originalSelection.CopyFrom(document.CurrentSelection.SelectedItems);
-
- try
- {
- // 设置新的选择集
- OnStatusChanged("正在设置选择集...");
- document.CurrentSelection.Clear();
- document.CurrentSelection.AddRange(items);
-
- // 等待选择更新
- System.Threading.Thread.Sleep(200);
-
- // 导出选中的元素
- OnStatusChanged("正在导出选中元素...");
- bool exportSuccess = ExportSelectedItems(document, outputPath, config);
-
- return Task.FromResult(exportSuccess);
- }
- finally
- {
- // 恢复原始选择
- document.CurrentSelection.Clear();
- if (originalSelection.Count > 0)
- {
- document.CurrentSelection.AddRange(originalSelection);
- }
- }
- }
- catch (Exception ex)
- {
- LogManager.Error($"[FileExporter] 选择集导出失败: {ex.Message}");
- throw;
- }
- }
-
- private async Task ExportByCopyToNewDocumentAsync(ModelItemCollection items, string outputPath, ExportConfiguration config)
- {
- try
- {
- LogManager.Info("[FileExporter] 使用新文档策略导出");
-
- // 注意:Navisworks API不直接支持创建新文档并复制元素
- // 这里使用可见性控制作为替代方案
- LogManager.Warning("[FileExporter] 新文档策略不被直接支持,使用可见性控制替代");
-
- return await ExportByVisibilityControlAsync(items, outputPath, config);
- }
- catch (Exception ex)
- {
- LogManager.Error($"[FileExporter] 新文档导出失败: {ex.Message}");
- throw;
- }
- }
-
- #endregion
-
- #region 私有方法 - 文件操作
-
- private bool SaveDocument(Document document, string outputPath, ExportConfiguration config)
- {
- try
- {
- LogManager.Info($"[FileExporter] 开始保存文档到: {outputPath}");
-
- // 创建备份
- if (config.CreateBackup && File.Exists(outputPath))
- {
- string backupPath = outputPath + ".backup";
- File.Copy(outputPath, backupPath, true);
- LogManager.Info($"[FileExporter] 已创建备份文件: {backupPath}");
- }
-
- // 使用正确的ExportToNwd API(参考文档5.2节)
- try
- {
- LogManager.Info("[FileExporter] 开始使用ExportToNwd API保存文档");
-
- // 确保文档处于稳定状态
- if (document.Models.Count == 0)
- {
- throw new InvalidOperationException("文档中没有模型数据");
- }
-
- // 等待一小段时间确保状态稳定
- System.Threading.Thread.Sleep(100);
-
- // 创建导出选项 - 参考保存当前选择项的正确做法
- var exportOptions = new Autodesk.Navisworks.Api.NwdExportOptions();
- exportOptions.ExcludeHiddenItems = true; // 只导出可见项目
- exportOptions.EmbedXrefs = false;
- exportOptions.PreventObjectPropertyExport = false;
-
- // 使用ExportToNwd API导出
- document.ExportToNwd(outputPath, exportOptions);
-
- LogManager.Info("[FileExporter] ExportToNwd API调用完成");
-
- // 验证文件是否成功保存
- if (File.Exists(outputPath))
- {
- var fileInfo = new FileInfo(outputPath);
- if (fileInfo.Length > 0)
- {
- LogManager.Info($"[FileExporter] 文档保存成功: {outputPath}, 大小: {fileInfo.Length} 字节");
- return true;
- }
- else
- {
- LogManager.Warning($"[FileExporter] 保存的文件大小为0: {outputPath}");
- File.Delete(outputPath); // 删除空文件
- return false;
- }
- }
- else
- {
- LogManager.Warning($"[FileExporter] 保存后文件不存在: {outputPath}");
- return false;
- }
- }
- catch (Exception ex)
- {
- LogManager.Error($"[FileExporter] ExportToNwd保存失败: {ex.Message}");
- return false;
- }
- }
- catch (Exception ex)
- {
- LogManager.Error($"[FileExporter] 保存文档异常: {ex.Message}");
- return false;
- }
- }
-
- private bool ExportSelectedItems(Document document, string outputPath, ExportConfiguration config)
- {
- try
- {
- // 对于选择集导出,我们仍然需要使用可见性控制
- // 因为Navisworks不支持直接导出选中的元素
-
- var selectedItems = document.CurrentSelection.SelectedItems;
- var task = ExportByVisibilityControlAsync(selectedItems, outputPath, config);
- task.Wait();
- return task.Result;
- }
- catch (Exception ex)
- {
- LogManager.Error($"[FileExporter] 导出选中元素失败: {ex.Message}");
- return false;
- }
- }
-
- private void SaveAsNwfFormat(Document document, string outputPath)
- {
- try
- {
- // NWF是Navisworks的工作文件格式
- // 需要使用COM API进行特殊处理
- LogManager.Info("[FileExporter] 保存为NWF格式");
- document.SaveFile(outputPath);
- }
- catch (Exception ex)
- {
- LogManager.Error($"[FileExporter] 保存NWF格式失败: {ex.Message}");
- throw;
- }
- }
-
- private void SaveAsNwcFormat(Document document, string outputPath)
- {
- try
- {
- // NWC是Navisworks的缓存文件格式
- LogManager.Info("[FileExporter] 保存为NWC格式");
- document.SaveFile(outputPath);
- }
- catch (Exception ex)
- {
- LogManager.Error($"[FileExporter] 保存NWC格式失败: {ex.Message}");
- throw;
- }
- }
-
- #endregion
-
- #region 私有方法 - 可见性状态管理
-
- private Dictionary SaveCurrentVisibilityState()
- {
- try
- {
- LogManager.Info("[FileExporter] 保存当前可见性状态");
-
- var visibilityState = new Dictionary();
- var document = Application.ActiveDocument;
-
- if (document?.Models != null)
- {
- // 安全获取所有模型项 - 使用AddRange避免挂起
- var allItems = new ModelItemCollection();
- allItems.AddRange(document.Models.RootItemDescendantsAndSelf);
-
- // 遍历ModelItemCollection而不是直接遍历RootItemDescendantsAndSelf
- foreach (ModelItem item in allItems)
- {
- try
- {
- visibilityState[item] = !item.IsHidden;
- }
- catch
- {
- // 忽略无法访问的元素
- }
- }
- }
-
- LogManager.Info($"[FileExporter] 已保存 {visibilityState.Count} 个元素的可见性状态");
- return visibilityState;
- }
- catch (Exception ex)
- {
- LogManager.Error($"[FileExporter] 保存可见性状态失败: {ex.Message}");
- return new Dictionary();
- }
- }
-
- private void RestoreVisibilityState(Dictionary visibilityState)
- {
- try
- {
- LogManager.Info("[FileExporter] 恢复可见性状态");
-
- if (visibilityState == null || visibilityState.Count == 0)
- {
- LogManager.Warning("[FileExporter] 没有可见性状态需要恢复");
- return;
- }
-
- // 直接执行,避免异步复杂性(.NET Framework 4.6兼容)
- var itemsToShow = new ModelItemCollection();
- var itemsToHide = new ModelItemCollection();
-
- foreach (var kvp in visibilityState)
- {
- try
- {
- if (kvp.Value) // 原来是可见的
- {
- itemsToShow.Add(kvp.Key);
- }
- else // 原来是隐藏的
- {
- itemsToHide.Add(kvp.Key);
- }
- }
- catch
- {
- // 忽略无法访问的元素
- }
- }
-
- // 批量恢复可见性 - 使用Document的SetHidden方法
- var document = Application.ActiveDocument;
- if (document != null)
- {
- if (itemsToShow.Count > 0)
- {
- document.Models.SetHidden(itemsToShow, false);
- }
-
- if (itemsToHide.Count > 0)
- {
- document.Models.SetHidden(itemsToHide, true);
- }
- }
-
- LogManager.Info("[FileExporter] 可见性状态恢复完成");
- }
- catch (Exception ex)
- {
- LogManager.Error($"[FileExporter] 恢复可见性状态失败: {ex.Message}");
- }
- }
-
- #endregion
-
- #region 私有方法 - 验证和辅助
-
- private void ValidateExportParameters(ModelItemCollection items, string outputPath)
- {
- if (items == null || items.Count == 0)
- {
- throw new ArgumentException("要导出的模型元素集合不能为空", nameof(items));
- }
-
- if (string.IsNullOrEmpty(outputPath))
- {
- throw new ArgumentException("输出路径不能为空", nameof(outputPath));
- }
-
- string directory = Path.GetDirectoryName(outputPath);
- if (!string.IsNullOrEmpty(directory) && !Directory.Exists(Path.GetDirectoryName(directory)))
- {
- throw new DirectoryNotFoundException($"输出目录的父目录不存在: {Path.GetDirectoryName(directory)}");
- }
-
- var document = Application.ActiveDocument;
- if (document?.Models == null || document.Models.Count == 0)
- {
- throw new InvalidOperationException("当前没有打开的Navisworks文档");
- }
- }
-
- private void EnsureOutputDirectory(string outputPath)
- {
- string directory = Path.GetDirectoryName(outputPath);
- if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
- {
- Directory.CreateDirectory(directory);
- LogManager.Info($"[FileExporter] 已创建输出目录: {directory}");
- }
- }
-
- ///
- /// 检查一个模型项或其子项是否包含目标元素中的任何一个
- ///
- /// 要检查的根模型项
- /// 目标元素集合
- /// 如果包含则返回true
- private bool ContainsAnyTargetItem(ModelItem rootItem, ModelItemCollection targetItems)
- {
- try
- {
- // 首先检查根项目本身
- if (targetItems.Contains(rootItem))
- {
- return true;
- }
-
- // 递归检查子项目(使用深度优先搜索,但限制深度避免栈溢出)
- return ContainsAnyTargetItemRecursive(rootItem, targetItems, 0, 10);
- }
- catch (Exception ex)
- {
- LogManager.Error($"[FileExporter] 检查目标元素时出错: {ex.Message}");
- // 出错时保守处理,假设包含目标元素
- return true;
- }
- }
-
- ///
- /// 递归检查子项目,带深度限制
- ///
- /// 当前检查的项目
- /// 目标元素集合
- /// 当前深度
- /// 最大深度
- /// 如果包含则返回true
- private bool ContainsAnyTargetItemRecursive(ModelItem item, ModelItemCollection targetItems, int currentDepth, int maxDepth)
- {
- try
- {
- // 防止递归过深
- if (currentDepth > maxDepth)
- {
- return false;
- }
-
- // 检查当前项目的所有子项
- if (item.Children != null)
- {
- foreach (ModelItem child in item.Children)
- {
- // 检查子项目本身
- if (targetItems.Contains(child))
- {
- return true;
- }
-
- // 递归检查子项目的子项
- if (ContainsAnyTargetItemRecursive(child, targetItems, currentDepth + 1, maxDepth))
- {
- return true;
- }
- }
- }
-
- return false;
- }
- catch (Exception)
- {
- // 出错时保守处理
- return false;
- }
- }
-
- #endregion
-
- #region 事件触发方法
-
- protected virtual void OnStatusChanged(string status)
- {
- StatusChanged?.Invoke(this, status);
- }
-
- protected virtual void OnProgressChanged(int progress)
- {
- ProgressChanged?.Invoke(this, progress);
- }
-
- protected virtual void OnErrorOccurred(Exception ex)
- {
- ErrorOccurred?.Invoke(this, ex);
- }
-
- #endregion
- }
-}
\ No newline at end of file