From e495ea462087b6391706e2274f3499573151a1ee Mon Sep 17 00:00:00 2001 From: tian <11429339@qq.com> Date: Wed, 11 Mar 2026 23:48:01 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=E5=89=96=E9=9D=A2=E7=9B=92?= =?UTF-8?q?=E5=AF=BC=E5=87=BA=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Core/SectionBoxExporter.cs | 44 +++++- .../ViewModels/LayerManagementViewModel.cs | 142 ++++-------------- 2 files changed, 72 insertions(+), 114 deletions(-) diff --git a/src/Core/SectionBoxExporter.cs b/src/Core/SectionBoxExporter.cs index d9554d6..c825443 100644 --- a/src/Core/SectionBoxExporter.cs +++ b/src/Core/SectionBoxExporter.cs @@ -142,9 +142,9 @@ namespace NavisworksTransport.Core } /// - /// 获取剖面盒内的所有对象 + /// 获取剖面盒内的所有对象(公开方法供外部调用) /// - private List GetObjectsInSectionBox(Document document, BoundingBox3D sectionBox) + public List GetObjectsInSectionBox(Document document, BoundingBox3D sectionBox) { var result = new List(); @@ -164,7 +164,7 @@ namespace NavisworksTransport.Core /// /// 递归遍历模型项 - 剪枝策略:遇到几何体就停止向下遍历 /// - private void TraverseModelItem(ModelItem item, BoundingBox3D sectionBox, List result) + public void TraverseModelItem(ModelItem item, BoundingBox3D sectionBox, List result) { if (item == null) return; @@ -338,9 +338,9 @@ namespace NavisworksTransport.Core } /// - /// 导出为NWD文件 + /// 导出为NWD文件(公开方法供外部调用) /// - private string ExportToNwd(Document document, List objects, string filePath) + public string ExportToNwd(Document document, List objects, string filePath) { // 必须在主线程执行Navisworks API操作 string result = null; @@ -370,6 +370,40 @@ namespace NavisworksTransport.Core return result; } + /// + /// 导出为JSON文件(公开方法供外部调用) + /// + public string ExportToJson(Document document, List objects, string filePath) + { + try + { + // 获取当前剖面盒边界(用于JSON中的元数据) + var viewpoint = document.CurrentViewpoint.Value; + var clipPlanes = viewpoint.ClipPlanes; + BoundingBox3D sectionBox = default; + + if (clipPlanes?.Enabled == true && clipPlanes.Mode == ClipPlaneSetMode.Box && clipPlanes.Box != null) + { + var box = clipPlanes.Box; + sectionBox = new BoundingBox3D( + new Point3D(box.Min.X, box.Min.Y, box.Min.Z), + new Point3D(box.Max.X, box.Max.Y, box.Max.Z) + ); + } + + var exportData = BuildExportData(sectionBox, objects, document); + string json = JsonConvert.SerializeObject(exportData, Formatting.Indented); + File.WriteAllText(filePath, json); + LogManager.Info($"[SectionBoxExporter] JSON导出完成: {objects.Count} 个对象 -> {filePath}"); + return filePath; + } + catch (Exception ex) + { + LogManager.Error($"[SectionBoxExporter] JSON导出失败: {ex.Message}"); + return null; + } + } + /// /// 显示保存文件对话框 /// diff --git a/src/UI/WPF/ViewModels/LayerManagementViewModel.cs b/src/UI/WPF/ViewModels/LayerManagementViewModel.cs index 4396f4f..121325a 100644 --- a/src/UI/WPF/ViewModels/LayerManagementViewModel.cs +++ b/src/UI/WPF/ViewModels/LayerManagementViewModel.cs @@ -16,6 +16,8 @@ using Autodesk.Navisworks.Api; using NavisApplication = Autodesk.Navisworks.Api.Application; using NavisworksTransport.Utils; using NavisworksTransport.Core; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; namespace NavisworksTransport.UI.WPF.ViewModels { @@ -1834,14 +1836,15 @@ namespace NavisworksTransport.UI.WPF.ViewModels var document = Autodesk.Navisworks.Api.Application.ActiveDocument; var originalSelection = restoreSelection ? document.CurrentSelection.SelectedItems.ToList() : null; - // 获取保存路径 + // 获取保存路径和导出格式 string saveFilePath = null; + bool exportAsJson = false; System.Windows.Application.Current.Dispatcher.Invoke(() => { var saveDialog = new Microsoft.Win32.SaveFileDialog { Title = dialogTitle, - Filter = "Navisworks文件 (*.nwd)|*.nwd", + Filter = "Navisworks文件 (*.nwd)|*.nwd|JSON文件 (*.json)|*.json", DefaultExt = "nwd", FileName = defaultFileName }; @@ -1849,6 +1852,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels if (saveDialog.ShowDialog() == true) { saveFilePath = saveDialog.FileName; + // 如果用户选择了JSON(FilterIndex为2或文件扩展名为json) + exportAsJson = (saveDialog.FilterIndex == 2 || + saveFilePath.EndsWith(".json", StringComparison.OrdinalIgnoreCase)); } }); @@ -1860,67 +1866,27 @@ namespace NavisworksTransport.UI.WPF.ViewModels bool exportResult = false; string errorMessage = ""; - // 在主线程执行导出,显示Navisworks系统进度条 - await Task.Run(() => + // 使用 SectionBoxExporter 进行导出 + var exporter = new SectionBoxExporter(); + + if (exportAsJson) { - System.Windows.Application.Current.Dispatcher.Invoke(() => + // JSON导出 + await Task.Run(() => { - // 设置等待光标 - 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(items); - - LogManager.Info($"[LayerManagementViewModel] 准备导出 {itemsToExport.Count} 个节点"); - progress.Update(0.4); - - // 在隔离模式下执行导出,自动恢复可见性 - VisibilityHelper.ExecuteInIsolation(itemsToExport, () => - { - progress.Update(0.6); - - // 导出选项 - var exportOptions = new Autodesk.Navisworks.Api.NwdExportOptions - { - ExcludeHiddenItems = true, - EmbedXrefs = EmbedXrefs, - PreventObjectPropertyExport = PreventObjectPropertyExport - }; - - progress.Update(0.8); - document.ExportToNwd(saveFilePath, exportOptions); - exportResult = true; - LogManager.Info("[LayerManagementViewModel] ExportToNwd API调用完成"); - }); - - progress.Update(1.0); - } - catch (Exception ex) - { - LogManager.Error($"[LayerManagementViewModel] 导出异常: {ex.Message}", ex); - errorMessage = ex.Message; - exportResult = false; - } - finally - { - // 确保进度条被关闭 - Autodesk.Navisworks.Api.Application.EndProgress(); - // 恢复光标 - System.Windows.Input.Mouse.OverrideCursor = null; - } + var result = exporter.ExportToJson(document, items, saveFilePath); + exportResult = !string.IsNullOrEmpty(result); }); - }); + } + else + { + // NWD导出 + await Task.Run(() => + { + var result = exporter.ExportToNwd(document, items, saveFilePath); + exportResult = !string.IsNullOrEmpty(result); + }); + } // 恢复原始选择(如果需要) if (restoreSelection && originalSelection != null) @@ -1945,14 +1911,16 @@ namespace NavisworksTransport.UI.WPF.ViewModels if (File.Exists(saveFilePath)) { var fileInfo = new FileInfo(saveFilePath); + string format = exportAsJson ? "JSON" : "NWD"; MessageBox.Show( - $"导出成功!\n\n文件: {saveFilePath}\n大小: {fileInfo.Length / 1024} KB", + $"{format}导出成功!\n\n文件: {saveFilePath}\n大小: {fileInfo.Length / 1024} KB", "导出结果", MessageBoxButton.OK, MessageBoxImage.Information); } } else { - MessageBox.Show($"导出失败: {errorMessage}", "导出错误", MessageBoxButton.OK, MessageBoxImage.Error); + string format = exportAsJson ? "JSON" : "NWD"; + MessageBox.Show($"{format}导出失败: {errorMessage}", "导出错误", MessageBoxButton.OK, MessageBoxImage.Error); } } catch (Exception ex) @@ -2054,56 +2022,12 @@ namespace NavisworksTransport.UI.WPF.ViewModels } /// - /// 获取剖面盒内的所有对象 + /// 获取剖面盒内的所有对象 - 委托给 SectionBoxExporter /// private List GetObjectsInSectionBox(Document document, BoundingBox3D sectionBox) { - var result = new List(); - - foreach (var model in document.Models) - { - var rootItem = model.RootItem; - if (rootItem != null) - { - TraverseModelItem(rootItem, sectionBox, result); - } - } - - return result; - } - - /// - /// 递归遍历模型项 - 剪枝策略 - /// - private void TraverseModelItem(ModelItem item, BoundingBox3D sectionBox, List 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); - } + var exporter = new SectionBoxExporter(); + return exporter.GetObjectsInSectionBox(document, sectionBox); } ///