From 51be24161d99daabcdb5ac3b1100a21a8d80b84d Mon Sep 17 00:00:00 2001 From: tian <11429339@qq.com> Date: Mon, 13 Oct 2025 09:34:52 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=B8=89=E8=A7=92=E5=BD=A2?= =?UTF-8?q?=E6=8F=90=E5=8F=96=E6=80=A7=E8=83=BD=20-=20=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E6=89=B9=E9=87=8FCOM=20Selection=E5=88=9B=E5=BB=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题分析: - 当前逐个ModelItem创建COM Selection(290次) - 从290个模型项提取776140个三角形耗时较长 - COM对象创建/销毁开销大 优化方案: 1. 新增 GeometryHelper.ExtractTrianglesBatch 方法 - 批量创建COM Selection(290次 → 1次) - 一次性提取所有模型项的三角形 - 添加进度日志(每100个片段输出一次) 2. 修改 NavisworksToDMesh3Converter.ConvertFromModelItems - 从逐个调用 ExtractTriangles 改为批量调用 ExtractTrianglesBatch - 添加详细的耗时统计(毫秒和秒) - 添加 System.Linq 引用支持ToList() 3. 保留原有 ExtractTriangles 方法 - 向后兼容单个模型项提取场景 - 用于小规模提取或特殊场景 预期效果: - COM Selection创建:290次 → 1次 - 预计性能提升:50-70% - 日志更详细,便于性能分析 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/Utils/GeometryHelper.cs | 103 ++++++++++++++++++++++- src/Utils/NavisworksToDMesh3Converter.cs | 30 ++----- 2 files changed, 108 insertions(+), 25 deletions(-) diff --git a/src/Utils/GeometryHelper.cs b/src/Utils/GeometryHelper.cs index 2a0e0e0..e2f81ed 100644 --- a/src/Utils/GeometryHelper.cs +++ b/src/Utils/GeometryHelper.cs @@ -124,7 +124,104 @@ namespace NavisworksTransport } /// - /// 提取三角形 + /// 批量提取三角形(优化版本) + /// + /// 模型项集合 + /// 三角形集合 + public static List ExtractTrianglesBatch(IEnumerable modelItems) + { + var triangles = new List(); + + ComApi.InwOpSelection comSelection = null; + try + { + // 批量转换为 COM 选择 - 性能优化关键 + var modelCollection = new ModelItemCollection(); + int itemCount = 0; + foreach (var item in modelItems) + { + modelCollection.Add(item); + itemCount++; + } + + LogManager.Info($"[批量提取] 开始批量提取 {itemCount} 个模型项的三角形"); + + var comState = ComStateManager.GetState(); + comSelection = ComApiBridge.ToInwOpSelection(modelCollection); + + LogManager.Debug($"[批量提取] COM 选择创建成功,路径数: {comSelection.Paths().Count}"); + + // 获取所有片段 + var allFragments = GetAllFragments(comSelection); + LogManager.Info($"[批量提取] 获取到 {allFragments.Count} 个片段"); + + try + { + int processedFragments = 0; + foreach (var fragmentInfo in allFragments) + { + try + { + var callback = new OptimizedGeometryCallback(fragmentInfo.TransformMatrix); + fragmentInfo.Fragment.GenerateSimplePrimitives( + ComApi.nwEVertexProperty.eNORMAL, + callback); + + var fragmentTriangles = callback.GetTriangles(); + triangles.AddRange(fragmentTriangles); + processedFragments++; + + // 每处理100个片段输出一次进度 + if (processedFragments % 100 == 0) + { + LogManager.Debug($"[批量提取] 已处理 {processedFragments}/{allFragments.Count} 个片段,累计三角形: {triangles.Count}"); + } + } + catch (Exception ex) + { + LogManager.Error($"[批量提取] 处理片段失败: {ex.Message}"); + } + } + + LogManager.Info($"[批量提取] 片段处理完成,共提取 {triangles.Count} 个三角形"); + } + finally + { + // 释放所有片段COM对象 + foreach (var fragmentInfo in allFragments) + { + try + { + if (fragmentInfo.Fragment != null) + { + Marshal.ReleaseComObject(fragmentInfo.Fragment); + } + } + catch (Exception ex) + { + LogManager.Warning($"[批量提取] 释放片段COM对象失败: {ex.Message}"); + } + } + } + } + catch (Exception ex) + { + LogManager.Error($"[批量提取] 提取三角形失败: {ex.Message}"); + } + finally + { + // 释放COM对象,避免内存泄漏 + if (comSelection != null) + { + Marshal.ReleaseComObject(comSelection); + } + } + + return triangles; + } + + /// + /// 提取三角形(单个模型项) /// /// 模型项 /// 三角形集合 @@ -146,7 +243,7 @@ namespace NavisworksTransport LogManager.Debug($"COM 选择创建成功,路径数: {comSelection.Paths().Count}"); - // 获取所有片段(已移除错误的去重逻辑) + // 获取所有片段 var allFragments = GetAllFragments(comSelection); LogManager.Debug($"获取到 {allFragments.Count} 个片段"); @@ -208,7 +305,7 @@ namespace NavisworksTransport } /// - /// 获取所有片段(移除错误的去重逻辑) + /// 获取所有片段 /// /// COM 选择 /// 所有片段信息集合 diff --git a/src/Utils/NavisworksToDMesh3Converter.cs b/src/Utils/NavisworksToDMesh3Converter.cs index 14d61bf..4e3e770 100644 --- a/src/Utils/NavisworksToDMesh3Converter.cs +++ b/src/Utils/NavisworksToDMesh3Converter.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using Autodesk.Navisworks.Api; using NavisworksTransport.Utils; using g4; @@ -138,33 +139,18 @@ namespace NavisworksTransport LogManager.Info("[DMesh3转换] 开始从 ModelItem 批量提取和转换"); - // 收集所有三角形 - var allTriangles = new List(); - int itemCount = 0; - + // 批量提取所有三角形 - 性能优化 var extractStopwatch = System.Diagnostics.Stopwatch.StartNew(); - foreach (var item in items) - { - try - { - itemCount++; - var triangles = GeometryHelper.ExtractTriangles(item); + var itemsList = items.ToList(); + int itemCount = itemsList.Count; - if (triangles != null && triangles.Count > 0) - { - allTriangles.AddRange(triangles); - LogManager.Debug($"[DMesh3转换] 从 {item.DisplayName} 提取了 {triangles.Count} 个三角形"); - } - } - catch (Exception ex) - { - LogManager.Warning($"[DMesh3转换] 从 ModelItem {item.DisplayName} 提取几何体失败: {ex.Message}"); - } - } + LogManager.Info($"[DMesh3转换] 共 {itemCount} 个模型项,使用批量提取方式"); + + var allTriangles = GeometryHelper.ExtractTrianglesBatch(itemsList); extractStopwatch.Stop(); - LogManager.Info($"[DMesh3转换] 从 {itemCount} 个模型项共提取 {allTriangles.Count} 个三角形,耗时: {extractStopwatch.ElapsedMilliseconds} ms"); + LogManager.Info($"[DMesh3转换] 从 {itemCount} 个模型项共提取 {allTriangles.Count} 个三角形,耗时: {extractStopwatch.ElapsedMilliseconds} ms ({extractStopwatch.Elapsed.TotalSeconds:F2}秒)"); // 转换为 DMesh3 return Convert(allTriangles);