From 543479ee654e211960d08f35bb9dc46dce7c0c2e Mon Sep 17 00:00:00 2001 From: tian <11429339@qq.com> Date: Mon, 13 Oct 2025 11:37:44 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=BA=E5=88=86=E5=B1=82=E5=AF=BC=E5=87=BA?= =?UTF-8?q?=E5=92=8C=E7=A2=B0=E6=92=9E=E6=A3=80=E6=B5=8B=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?Progress=20API=E8=BF=9B=E5=BA=A6=E6=9D=A1=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 分层导出(ExportLayerToNwd):增加三阶段进度条(隔离30%/导出70%/完成100%)和用户取消支持 - 碰撞检测(CreateAllAnimationCollisionTests):增加循环进度条和用户取消支持 - 清理LayerManagementCommands中未使用的辅助函数 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../Collision/ClashDetectiveIntegration.cs | 32 +- src/Core/ModelSplitterManager.cs | 297 +++--------------- .../WPF/Commands/LayerManagementCommands.cs | 82 ----- 3 files changed, 72 insertions(+), 339 deletions(-) diff --git a/src/Core/Collision/ClashDetectiveIntegration.cs b/src/Core/Collision/ClashDetectiveIntegration.cs index a87664f..1e38e23 100644 --- a/src/Core/Collision/ClashDetectiveIntegration.cs +++ b/src/Core/Collision/ClashDetectiveIntegration.cs @@ -249,6 +249,7 @@ namespace NavisworksTransport string pathName = "未知路径", string routeId = null, string animatedObjectName = null, int frameRate = 30, double duration = 10.0) { + Progress progress = null; try { LogManager.Info($"=== 使用预计算碰撞数据创建ClashDetective测试(容差: {detectionGap}米) ==="); @@ -355,11 +356,25 @@ namespace NavisworksTransport }; LogManager.Info($"[分组测试] 创建碰撞分组: {collisionGroup.DisplayName}"); - + + // 🎯 创建进度条 + progress = Application.BeginProgress("碰撞检测", + $"正在处理 {validCollisions.Count} 个碰撞点..."); + int resultCount = 0; foreach (var collision in validCollisions) { resultCount++; + + // 🎯 检查用户是否取消 + if (progress.IsCanceled) + { + LogManager.Info($"[碰撞检测] 用户取消操作,已处理 {resultCount - 1}/{validCollisions.Count}"); + break; + } + + // 🎯 更新进度 + progress.Update((double)resultCount / validCollisions.Count); try { @@ -610,6 +625,21 @@ namespace NavisworksTransport { LogManager.Error($"动画结束后创建测试失败: {ex.Message}"); } + finally + { + // 🎯 确保进度条被关闭 + if (progress != null) + { + try + { + Application.EndProgress(); + } + catch (Exception progressEx) + { + LogManager.Error($"[碰撞检测] 关闭进度条失败: {progressEx.Message}"); + } + } + } } /// diff --git a/src/Core/ModelSplitterManager.cs b/src/Core/ModelSplitterManager.cs index d56cbc3..64c384f 100644 --- a/src/Core/ModelSplitterManager.cs +++ b/src/Core/ModelSplitterManager.cs @@ -1706,6 +1706,7 @@ namespace NavisworksTransport return false; } + Progress progress = null; try { LogManager.Info($"[分层管理器] ========== ExportLayerToNwd开始 =========="); @@ -1726,16 +1727,20 @@ namespace NavisworksTransport // 检查线程状态 var apartmentState = System.Threading.Thread.CurrentThread.GetApartmentState(); LogManager.Info($"[分层管理器] 当前线程状态: {apartmentState}"); - + // 核心修复:确保在主 UI 线程中执行 Navisworks API 调用 bool exportResult = false; Exception exportException = null; - + // 使用 Application.Current.Dispatcher.Invoke 确保在主线程中执行 System.Windows.Application.Current.Dispatcher.Invoke(() => { try { + // 🎯 创建进度条 + progress = NavisApplication.BeginProgress("导出分层", + $"正在导出 {preview.LayerName}..."); + LogManager.Info($"[分层管理器] 在主线程中执行导出操作"); var document = NavisApplication.ActiveDocument; @@ -1746,23 +1751,37 @@ namespace NavisworksTransport try { + // 🎯 阶段1:隔离显示 (30%) + progress.Update(0.3); + // 直接使用预览结果中的项目,这些已经是展开的完整节点树 // 不添加任何祖先路径,让 IsolateSpecificItems 自己处理 var itemsToIsolate = preview.Items; - + LogManager.Info($"[分层管理器] 准备隔离显示 {itemsToIsolate.Count} 个节点"); - + // 使用 VisibilityManager.IsolateSpecificItems 隔离显示 // 这个方法会使用缓存优化,效率更高 bool isolateSuccess = VisibilityHelper.IsolateSpecificItems(itemsToIsolate); - + if (!isolateSuccess) { throw new InvalidOperationException("隔离显示失败"); } - + LogManager.Info($"[分层管理器] 隔离显示成功"); + // 🎯 检查用户是否取消 + if (progress.IsCanceled) + { + LogManager.Info("[分层管理器] 用户取消导出操作"); + exportResult = false; + return; // 跳过导出,直接到finally块恢复状态 + } + + // 🎯 阶段2:导出文件 (70%) + progress.Update(0.7); + // 创建导出选项 var exportOptions = new Autodesk.Navisworks.Api.NwdExportOptions { @@ -1778,10 +1797,26 @@ namespace NavisworksTransport document.ExportToNwd(outputPath, exportOptions); LogManager.Info($"[分层管理器] ExportToNwd API调用完成(主线程)"); + + // 🎯 完成 (100%) + progress.Update(1.0); exportResult = true; } finally { + // 🎯 确保进度条被关闭 + if (progress != null) + { + try + { + NavisApplication.EndProgress(); + } + catch (Exception progressEx) + { + LogManager.Error($"[分层管理器] 关闭进度条失败: {progressEx.Message}"); + } + } + // 恢复原始可见性状态(在主线程中) try { @@ -2230,152 +2265,6 @@ namespace NavisworksTransport } } - /// - /// 获取指定楼层的模型项 - /// - private ModelItemCollection GetFloorItems(ModelItemCollection allItems, string floorName, int maxDepth) - { - var floorItems = new ModelItemCollection(); - - try - { - LogManager.Info($"[分层管理器] ===== GetFloorItems开始 ====="); - LogManager.Info($"[分层管理器] 目标楼层名称: '{floorName}'"); - LogManager.Info($"[分层管理器] 输入模型项数: {allItems.Count}"); - - int checkedCount = 0; - int matchedCount = 0; - - // 这里需要实现根据楼层名称筛选模型项的逻辑 - // 暂时使用简化实现:遍历所有项目,检查其属性是否匹配楼层名称 - foreach (ModelItem item in allItems) - { - try - { - checkedCount++; - - // 检查项目的楼层属性 - bool hasMatch = HasFloorAttribute(item, floorName); - - if (hasMatch) - { - floorItems.Add(item); - matchedCount++; - - if (matchedCount <= 5) // 只记录前5个匹配的详细信息 - { - LogManager.Info($"[分层管理器] 找到匹配模型项 #{matchedCount}: {item.DisplayName}"); - } - } - - // 每处理1000个项记录进度 - if (checkedCount % 1000 == 0) - { - LogManager.Info($"[分层管理器] 已检查 {checkedCount}/{allItems.Count} 个模型项,找到 {matchedCount} 个匹配"); - } - } - catch (Exception ex) - { - LogManager.Warning($"[分层管理器] 检查模型项楼层属性时出错: {ex.Message}"); - } - } - - LogManager.Info($"[分层管理器] ===== GetFloorItems完成 ===== 检查了 {checkedCount} 个模型项,找到 {matchedCount} 个匹配的楼层项目"); - } - catch (Exception ex) - { - LogManager.Error($"[分层管理器] 获取楼层项目失败: {ex.Message}"); - } - - return floorItems; - } - - - /// - /// 检查模型项是否具有指定的楼层属性 - /// - private bool HasFloorAttribute(ModelItem item, string floorName) - { - try - { - // 检查常见的楼层属性名称 - string[] floorAttributeNames = { "Level", "Floor", "楼层", "层", "Story", "Storey" }; - - var categories = item.PropertyCategories; - if (categories != null) - { - foreach (PropertyCategory category in categories) - { - var properties = category.Properties; - if (properties != null) - { - foreach (DataProperty property in properties) - { - if (floorAttributeNames.Any(attr => - property.DisplayName.IndexOf(attr, StringComparison.OrdinalIgnoreCase) >= 0)) - { - string propValue = property.Value?.ToString() ?? ""; - bool isMatch = propValue.IndexOf(floorName, StringComparison.OrdinalIgnoreCase) >= 0; - - // 详细调试日志 - 当找到楼层相关属性时 - if (!string.IsNullOrEmpty(propValue)) - { - LogManager.Info($"[分层管理器] 楼层属性检查: 项目='{item.DisplayName}', 属性='{property.DisplayName}', 值='{propValue}', 目标='{floorName}', 匹配={isMatch}"); - } - - if (isMatch) - { - return true; - } - } - } - } - } - } - } - catch (Exception ex) - { - LogManager.Warning($"[分层管理器] 检查楼层属性时出错: {ex.Message}"); - } - - return false; - } - - /// - /// 检查模型项是否具有指定的属性值 - /// - private bool HasAttributeValue(ModelItem item, string attributeName, string targetValue) - { - try - { - var categories = item.PropertyCategories; - if (categories != null) - { - foreach (PropertyCategory category in categories) - { - var properties = category.Properties; - if (properties != null) - { - foreach (DataProperty property in properties) - { - if (property.DisplayName.Equals(attributeName, StringComparison.OrdinalIgnoreCase)) - { - string propValue = property.Value?.ToString() ?? ""; - return propValue.Equals(targetValue, StringComparison.OrdinalIgnoreCase); - } - } - } - } - } - } - catch (Exception ex) - { - LogManager.Warning($"[分层管理器] 检查属性值时出错: {ex.Message}"); - } - - return false; - } - /// /// 恢复可见性状态 /// @@ -2443,110 +2332,6 @@ namespace NavisworksTransport } } - - /// - /// 测试导出功能:导出少量模型项以验证基础功能 - /// - /// 测试文件输出路径 - /// 最大测试项目数(默认5个) - /// 测试是否成功 - public bool TestBasicExport(string outputPath, int maxItems = 5) - { - try - { - LogManager.Info($"[分层管理器] ========== 开始基础导出测试 =========="); - LogManager.Info($"[分层管理器] 测试文件路径: {outputPath}"); - LogManager.Info($"[分层管理器] 最大测试项目数: {maxItems}"); - - var document = NavisApplication.ActiveDocument; - if (document?.Models?.Count == 0) - { - LogManager.Error("[SimplifiedModelSplitter] 当前文档无效,无法进行测试"); - return false; - } - - // 获取少量模型项进行测试 - var allItems = GetAllModelItems(1); // 只获取第一层 - if (allItems.Count == 0) - { - LogManager.Error("[SimplifiedModelSplitter] 没有可用的模型项进行测试"); - return false; - } - - // 限制测试项目数量 - var testItems = new ModelItemCollection(); - int addedCount = 0; - foreach (ModelItem item in allItems) - { - if (addedCount >= maxItems) break; - - try - { - // 验证项目有效性 - string displayName = item.DisplayName; - testItems.Add(item); - addedCount++; - LogManager.Info($"[分层管理器] 添加测试项目 #{addedCount}: {displayName}"); - } - catch (Exception ex) - { - LogManager.Warning($"[分层管理器] 跳过无效测试项目: {ex.Message}"); - } - } - - if (testItems.Count == 0) - { - LogManager.Error("[SimplifiedModelSplitter] 没有有效的测试项目"); - return false; - } - - LogManager.Info($"[分层管理器] 准备测试导出 {testItems.Count} 个模型项"); - - // 确保输出目录存在 - string directory = Path.GetDirectoryName(outputPath); - if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory)) - { - Directory.CreateDirectory(directory); - LogManager.Info($"[分层管理器] 创建测试输出目录: {directory}"); - } - - // 创建测试预览结果 - var testPreview = new SplitPreviewResult - { - LayerName = "测试导出", - LayerAttribute = "测试", - Items = testItems - }; - - // 创建测试配置 - var testConfig = new SplitConfiguration - { - Strategy = SplitStrategy.BySmartFloorDetection, - OutputDirectory = directory, - ExportOptions = new NwdExportUserOptions() // 使用默认选项 - }; - - // 执行测试导出 - bool testResult = ExportLayerToNwd(testPreview, outputPath, testConfig); - - LogManager.Info($"[分层管理器] ========== 基础导出测试完成 ========== 结果: {testResult}"); - - if (testResult && File.Exists(outputPath)) - { - var fileInfo = new FileInfo(outputPath); - LogManager.Info($"[分层管理器] 测试文件生成成功,大小: {fileInfo.Length / 1024} KB"); - } - - return testResult; - } - catch (Exception ex) - { - LogManager.Error($"[分层管理器] 基础导出测试失败: {ex.Message}"); - LogManager.Error($"[分层管理器] 测试异常堆栈: {ex.StackTrace}"); - return false; - } - } - #endregion #region 辅助方法 diff --git a/src/UI/WPF/Commands/LayerManagementCommands.cs b/src/UI/WPF/Commands/LayerManagementCommands.cs index 3d11c8c..fbfb7ac 100644 --- a/src/UI/WPF/Commands/LayerManagementCommands.cs +++ b/src/UI/WPF/Commands/LayerManagementCommands.cs @@ -704,87 +704,5 @@ namespace NavisworksTransport.UI.WPF.Commands } } - /// - /// 测试导出命令 - 导出少量模型项验证基础功能 - /// - public class TestExportCommand : ILayerManagementCommand - { - private readonly ModelSplitterManager _modelSplitterManager; - private readonly string _outputPath; - private readonly int _maxItems; - - public TestExportCommand(ModelSplitterManager modelSplitterManager, string outputPath, int maxItems = 5) - { - _modelSplitterManager = modelSplitterManager ?? throw new ArgumentNullException(nameof(modelSplitterManager)); - _outputPath = outputPath ?? throw new ArgumentNullException(nameof(outputPath)); - _maxItems = Math.Max(1, Math.Min(20, maxItems)); // 限制在1-20个项目之间 - } - - public async Task ExecuteAsync() - { - return await Task.Run(() => - { - try - { - LogManager.Info("[TestExportCommand] 开始执行测试导出"); - LogManager.Info($"[TestExportCommand] 输出路径: {_outputPath}"); - LogManager.Info($"[TestExportCommand] 最大测试项目数: {_maxItems}"); - - // 调用SimplifiedModelSplitterManager的测试方法 - bool testResult = _modelSplitterManager.TestBasicExport(_outputPath, _maxItems); - - if (testResult) - { - // 检查生成的文件信息 - long fileSize = 0; - if (System.IO.File.Exists(_outputPath)) - { - var fileInfo = new System.IO.FileInfo(_outputPath); - fileSize = fileInfo.Length; - } - - string successMessage = $"测试导出成功!已导出{_maxItems}个模型项"; - LogManager.Info($"[TestExportCommand] {successMessage}"); - - return new TestExportResult - { - IsSuccess = true, - Message = successMessage, - OutputPath = _outputPath, - FileSizeBytes = fileSize, - ItemCount = _maxItems - }; - } - else - { - string errorMessage = "测试导出失败,请检查日志了解详细错误信息"; - LogManager.Error($"[TestExportCommand] {errorMessage}"); - - return new TestExportResult - { - IsSuccess = false, - ErrorMessage = errorMessage, - OutputPath = _outputPath, - ItemCount = _maxItems - }; - } - } - catch (Exception ex) - { - string errorMessage = $"测试导出异常: {ex.Message}"; - LogManager.Error($"[TestExportCommand] {errorMessage}", ex); - - return new TestExportResult - { - IsSuccess = false, - ErrorMessage = errorMessage, - OutputPath = _outputPath, - ItemCount = _maxItems - }; - } - }); - } - } - #endregion } \ No newline at end of file