--- ## Navisworks Manage 动态碰撞检测插件开发文档 (Demo 版) ### 1. 引言 本插件旨在简化 Navisworks Manage 中移动模型沿确定路径进行物理碰撞或干涉检测的流程。通过自动化 Animator 动画创建、Clash Detective 碰撞测试配置与运行,并提供直观的图形化碰撞结果显示,本插件将大大提高工作效率,并为用户提供一个快速验证施工物流和设备移动可行性的工具。 本 Demo 版插件将实现以下核心功能: - 在 Navisworks Ribbon 界面添加自定义按钮。 - 用户选择一个要移动的模型。 - 用户通过选择一系列模型元素(例如,小球或方块)来定义非直线路径点。 - 插件自动在 Animator 中创建基于这些路径点的对象动画。 - 插件自动配置并运行一个链接到该动画的动态碰撞测试。 - 当检测到碰撞时,插件将通过颜色覆盖直观地高亮显示碰撞的物体,并弹出明确的提示信息。 ### 2. 先决条件 在开始开发之前,请确保您的开发环境满足以下要求: - **Navisworks Manage 2017:** 插件将针对此版本进行开发和测试。请确保已安装 Navisworks Manage 2017。 - **Visual Studio:** 推荐使用 Visual Studio 2019 或更高版本,但需确保其支持目标.NET Framework 版本。 - **.NET Framework 4.6 或 4.7.2 Developer Pack:** Navisworks Manage 2017 通常支持.NET Framework 4.6 或 4.7.2。请根据您的 Visual Studio 版本和 Navisworks 安装,安装相应的.NET Framework Developer Pack。 - **Navisworks SDK:** Navisworks SDK 通常随 Navisworks Manage 安装。它包含了开发插件所需的 API 文档和示例。默认安装路径通常在 `C:\Program Files\Autodesk\Navisworks Manage 2017\api\net\`。 - **C# 编程基础:** 熟悉 C# 语言和面向对象编程概念。 - **Navisworks 基本操作知识:** 了解 Navisworks 的界面、模型选择、Animator 和 Clash Detective 的基本概念。 ### 3. 项目设置 本节将指导您在 Visual Studio 中创建和配置插件项目。 #### 3.1 创建 Visual Studio 项目 1. 打开 **Visual Studio**。 2. 选择 **“创建新项目”**。 3. 在项目模板中,搜索并选择 **“C#”** 语言下的 **“类库 (.NET Framework)”**。点击 **“下一步”**。 4. 配置新项目: - **项目名称:** `DynamicClashDetector` - **位置:** 选择一个合适的文件夹来保存您的项目。 - **解决方案名称:** `DynamicClashDetector` - **框架:** 选择 **`.NET Framework 4.7.2`** (或与您的 Navisworks 2017 兼容的最高版本,通常 4.6 或 4.7.2 均可)。 5. 点击 **“创建”**。 #### 3.2 添加 Navisworks API 引用 1. 在 **“解决方案资源管理器”** 中,右键单击您的项目(`DynamicClashDetector`),然后选择 **“添加” > “引用...”**。 2. 在 **“引用管理器”** 对话框中,选择 **“浏览”** 选项卡。 3. 点击 **“浏览...”** 按钮。 4. 导航到您的 Navisworks Manage 2017 安装目录下的 `api\net\` 文件夹(例如:`C:\Program Files\Autodesk\Navisworks Manage 2017\Autodesk Navisworks Manage 2017 SDK\api\net\`)。 5. 选择以下 DLL 文件并点击 **“添加”**: - `Autodesk.Navisworks.Api.dll` - `Autodesk.Navisworks.Automation.dll` (虽然此 Demo 不直接使用自动化,但通常会引用) - `Autodesk.Navisworks.Interop.ComApi.dll` (用于某些低级或旧版 API 交互,此 Demo 尽量避免,但作为备用) 6. 点击 **“确定”** 关闭引用管理器。 #### 3.3 配置插件属性和 Ribbon 布局 Navisworks 插件通过特定的特性(Attributes)来定义其行为和在用户界面中的显示。 1. **重命名类文件:** 在“解决方案资源管理器”中,将默认的 `Class1.cs` 重命名为 `MainPlugin.cs`。 2. **添加插件特性:** 打开 `MainPlugin.cs` 文件,并添加以下 `using` 语句和插件特性。 C# ``` using Autodesk.Navisworks.Api; using Autodesk.Navisworks.Api.Plugins; using System.Windows.Forms; // 用于消息框 using System.Linq; // 用于 LINQ 查询 using Autodesk.Navisworks.Api.Animation; // 用于 Animator API using Autodesk.Navisworks.Api.Clash; // 用于 Clash Detective API using System.Collections.Generic; // 用于 List // 定义插件的唯一 ID、开发者 ID 和显示名称 // 定义插件在Ribbon界面中的位置和行为 // 快捷键适用的窗口类型 public class MainPlugin : AddInPlugin { // 插件的核心执行方法 public override int ExecuteCommand(string commandId, params string parameters) { // 获取当前 Navisworks 文档 Document doc = Application.ActiveDocument; if (doc == null | ``` | doc.Is='null') { MessageBox.Show("请先打开一个 Navisworks 模型。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); return 0; } ```` // 调用核心逻辑 RunDynamicClashDetection(doc); return 0; } // 核心逻辑方法 (将在下一节详细实现) private void RunDynamicClashDetection(Document doc) { // 此处将填充实际代码 MessageBox.Show("动态碰撞检测功能即将启动!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } } ``` * **图标文件:** 在您的项目根目录下创建一个名为 `Resources` 的文件夹,并将 `Icon16x16.png` 和 `Icon32x32.png` 两个图标文件放入其中。确保这些图标的 **“生成操作”** 属性设置为 **“内容”**,**“复制到输出目录”** 属性设置为 **“如果较新则复制”**。 ```` ### 4. 核心插件逻辑实现 (Demo 版) 本节将详细实现 `RunDynamicClashDetection` 方法中的核心逻辑。 #### 4.1 用户交互与选择 插件需要用户选择两个关键元素:要移动的模型和定义路径的模型元素(路径点)。 C# ``` //... (MainPlugin class) private void RunDynamicClashDetection(Document doc) { // 1. 获取用户选择的移动对象和路径对象 // 假设用户选择的第一个是移动对象,其余是路径点 ModelItemCollection selectedItems = doc.CurrentSelection.SelectedItems; if (selectedItems.Count < 2) { MessageBox.Show("请选择一个要移动的对象和至少一个路径点(例如,小球或方块)。", "选择错误", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } ModelItem movingObject = selectedItems.First(); List pathPointsModels = selectedItems.Skip(1).ToList(); // 确保路径点有几何体,可以提取中心点 if (pathPointsModels.Any(item => item.BoundingBox == null)) { MessageBox.Show("部分路径点没有有效的几何体(无法获取边界框)。请选择具有几何体的模型元素作为路径点。", "路径错误", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } // 提取路径点的中心坐标 List pathPoints = pathPointsModels.Select(item => item.BoundingBox.Center).ToList(); if (pathPoints.Count < 1) { MessageBox.Show("未能从选择中提取到有效的路径点。", "路径错误", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } // 确保移动对象不是路径点之一 if (pathPointsModels.Contains(movingObject)) { MessageBox.Show("移动对象不能同时作为路径点。请重新选择。", "选择错误", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } // 提示用户已选择 MessageBox.Show($"已选择移动对象: {movingObject.DisplayName}\n已选择 {pathPoints.Count} 个路径点。", "选择成功", MessageBoxButtons.OK, MessageBoxIcon.Information); //... (后续步骤) } ``` #### 4.2 动画创建 (基于路径点) 本节将根据用户选择的路径点,在 Navisworks Animator 中创建对象动画。 C# ``` //... (RunDynamicClashDetection 方法中) // 2. 创建 Animator 场景和动画集 DocumentAnimator animator = doc.GetAnimator(); if (animator == null) { MessageBox.Show("无法访问 Animator 工具。请确保 Navisworks Manage 已启用 Animator。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } // 创建一个新的动画场景 AnimationScene scene = new AnimationScene(); scene.DisplayName = "动态碰撞检测动画_" + DateTime.Now.ToString("yyyyMMdd_HHmmss"); animator.AnimationScenes.AddCopy(scene); // 将新场景添加到文档中 // 为移动对象创建动画集 AnimationSet animationSet = new AnimationSet(movingObject); scene.AnimationSets.Add(animationSet); // 计算动画总时长和每个路径段的时长 double totalDuration = 10.0; // 动画总时长,可根据需要调整 if (pathPoints.Count > 1) { double timePerSegment = totalDuration / (pathPoints.Count - 1); // 为每个路径点创建关键帧 for (int i = 0; i < pathPoints.Count; i++) { Point3D currentPoint = pathPoints[i]; // 创建一个平移变换,将对象移动到当前路径点 Transform3D transform = Transform3D.CreateTranslation(currentPoint.X, currentPoint.Y, currentPoint.Z); KeyFrame keyFrame = new KeyFrame(animationSet); keyFrame.Time = i * timePerSegment; // 设置关键帧时间 keyFrame.Transform = transform; // 设置关键帧的变换 animationSet.KeyFrames.Add(keyFrame); } } else // 只有一个路径点,则只创建一个关键帧 { Transform3D transform = Transform3D.CreateTranslation(pathPoints.X, pathPoints.Y, pathPoints.Z); KeyFrame keyFrame = new KeyFrame(animationSet); keyFrame.Time = 0.0; keyFrame.Transform = transform; animationSet.KeyFrames.Add(keyFrame); } MessageBox.Show($"已在 Animator 中创建动画场景 '{scene.DisplayName}'。", "动画创建成功", MessageBoxButtons.OK, MessageBoxIcon.Information); //... (后续步骤) ``` #### 4.3 动态碰撞测试配置与运行 本节将配置 Clash Detective,将其链接到刚刚创建的动画场景,并运行碰撞测试。 C# ``` //... (RunDynamicClashDetection 方法中) // 3. 设置并运行动态碰撞测试 DocumentClash documentClash = doc.GetClash(); if (documentClash == null) { MessageBox.Show("无法访问 Clash Detective 工具。请确保 Navisworks Manage 已启用 Clash Detective。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } ClashTest dynamicClashTest = new ClashTest(); dynamicClashTest.DisplayName = "动态路径碰撞测试_" + DateTime.Now.ToString("yyyyMMdd_HHmmss"); // 设置选择集 A (移动对象) ClashSelection selectionA = new ClashSelection(); selectionA.Selection.Add(movingObject); dynamicClashTest.SelectionA = selectionA; // 设置选择集 B (整个模型,除了移动对象本身和路径点) ClashSelection selectionB = new ClashSelection(); selectionB.Selection.SelectAll(); // 选择所有模型项 selectionB.Selection.Remove(movingObject); // 排除移动对象自身 foreach (ModelItem pathPointModel in pathPointsModels) { selectionB.Selection.Remove(pathPointModel); // 排除路径点 } dynamicClashTest.SelectionB = selectionB; // 链接动画场景 dynamicClashTest.SimulationType = ClashTestSimulationType.Animator; // 链接到 Animator 动画 dynamicClashTest.SimulationScene = scene; // 指定要链接的动画场景 dynamicClashTest.SimulationStep = 0.1; // 每 0.1 秒检查一次碰撞 // 设置碰撞类型和容差 dynamicClashTest.TestType = ClashTestType.Hard; // 硬碰撞 dynamicClashTest.Tolerance = 0.0; // 0 容差,表示任何物理重叠 // 将测试添加到文档中 (需要事务) using (Transaction trans = doc.BeginTransaction("创建动态碰撞测试")) { documentClash.TestsData.TestsAddCopy(dynamicClashTest); trans.Commit(); } // 运行测试 documentClash.TestsData.TestsRunTest(dynamicClashTest); MessageBox.Show("动态碰撞测试已运行。请查看碰撞检测器窗口中的结果。", "测试完成", MessageBoxButtons.OK, MessageBoxIcon.Information); //... (后续步骤) ``` #### 4.4 碰撞结果的图形化提示 本节将遍历碰撞结果,并使用颜色覆盖来直观地显示碰撞的物体。 C# ``` //... (RunDynamicClashDetection 方法中) // 4. 碰撞结果的图形化提示 DisplayClashResultsGraphically(doc, dynamicClashTest); } // End of RunDynamicClashDetection method private void DisplayClashResultsGraphically(Document doc, ClashTest test) { // 确保在显示前清除所有之前的颜色覆盖 doc.Models.ResetAllPermanentMaterials(); // doc.Models.ResetAllHidden(); // 确保所有模型可见 if (test.Children.Count == 0) { MessageBox.Show("未检测到任何碰撞。", "无碰撞", MessageBoxButtons.OK, MessageBoxIcon.Information); return; } MessageBox.Show($"检测到 {test.Children.Count} 处碰撞。将逐一显示。", "碰撞结果", MessageBoxButtons.OK, MessageBoxIcon.Information); foreach (ClashResult result in test.Children.OfType()) { ModelItem item1 = result.Item1; ModelItem item2 = result.Item2; if (item1 == null | | item2 == null) continue; // 应用自定义颜色:红色用于移动项,绿色用于静态/碰撞项 // 注意:这里假设 item1 是移动对象,item2 是静态对象。 // 在实际应用中,您可能需要根据对象的属性或其在 ClashSelection 中的角色来确定颜色。 doc.Models.OverridePermanentColor(new ModelItemCollection() { item1 }, Color.Red); // doc.Models.OverridePermanentColor(new ModelItemCollection() { item2 }, Color.Green); // // 聚焦到碰撞项 ModelItemCollection itemsToFocus = new ModelItemCollection(); itemsToFocus.Add(item1); itemsToFocus.Add(item2); doc.CurrentSelection.Clear(); doc.CurrentSelection.CopyFrom(itemsToFocus); // doc.ActiveView.FocusOnCurrentSelection(); // // 明确提示碰撞信息 string clashInfo = $"检测到碰撞:\n" + $"对象1: {item1.DisplayName}\n" + $"对象2: {item2.DisplayName}\n" + $"碰撞时间/步长: {result.CreatedTime?.ToString("HH:mm:ss.fff")?? "N/A"}\n" + // 碰撞发生的时间 [1] $"碰撞距离: {result.Distance:F3}m"; // 碰撞距离 [2] MessageBox.Show(clashInfo, "动态碰撞提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); // 每次显示完一个碰撞后,恢复颜色以便显示下一个 doc.Models.ResetAllPermanentMaterials(); // } MessageBox.Show("所有碰撞已显示完毕。", "完成", MessageBoxButtons.OK, MessageBoxIcon.Information); } ``` ### 5. 部署与测试 #### 5.1 编译插件 1. 在 Visual Studio 中,选择 **“生成” > “生成解决方案”**。 2. 如果生成成功,您将在项目输出目录(通常是 `DynamicClashDetector\bin\Debug` 或 `DynamicClashDetector\bin\Release`)中找到 `DynamicClashDetector.dll` 文件。 #### 5.2 部署插件 Navisworks 插件通常部署在特定的应用程序插件文件夹中。 1. 在 Navisworks 插件目录中创建一个新的文件夹,例如: `%AppData%\Autodesk\ApplicationPlugins\DynamicClashDetector.bundle\` (这通常解析为 `C:\Users\<您的用户名>\AppData\Roaming\Autodesk\ApplicationPlugins\DynamicClashDetector.bundle\`) 2. 在该 `DynamicClashDetector.bundle` 文件夹内,创建一个名为 `Contents` 的子文件夹。 3. 将您编译生成的 `DynamicClashDetector.dll` 文件以及 `Resources` 文件夹(包含图标文件)复制到 `Contents` 文件夹中。 最终结构应类似: ``` DynamicClashDetector.bundle/ ├── Contents/ │ ├── DynamicClashDetector.dll │ └── Resources/ │ ├── Icon16x16.png │ └── Icon32x32.png └── PackageContents.xml (可选,但推荐用于更复杂的插件部署) ``` _注意:_ 对于 Demo,`PackageContents.xml` 文件不是必需的,但对于生产级插件,它用于定义插件的元数据和加载行为。 #### 5.3 测试插件 1. **启动 Navisworks Manage 2017。** 2. **打开一个模型:** 加载一个包含一些结构、MEP 或其他固定模型的 Navisworks 文件(.nwc,.nwd,.nwf)。 3. **准备测试模型:** - **移动对象:** 确保模型中有一个可以作为“移动对象”的独立模型元素(例如,一个设备、一个方块或一个简单的几何体)。 - **路径点:** 在模型中创建或导入一系列小球、小方块或其他易于选择的几何体,它们将作为您的路径点,定义移动对象的非直线路径。确保这些路径点是独立的模型元素。 4. **执行插件:** - 在 Navisworks Ribbon 界面中,找到 **“附加模块”** 选项卡。 - 您应该会看到一个名为 **“动态碰撞检测”** 的新面板或按钮。 - **选择对象:** - 首先,在场景中选择您的 **“移动对象”**。 - 然后,按住 `Ctrl` 键,依次选择您定义的所有 **“路径点”** 模型元素。 - 确保只选择了这两个类别的对象(一个移动对象,多个路径点)。 - 点击 **“动态碰撞检测”** 按钮。 5. **观察结果:** - 插件将弹出消息框,提示选择成功、动画创建成功、测试运行完成。 - 如果检测到碰撞,插件将逐一弹出消息框提示碰撞信息,并在模型中将碰撞的两个对象高亮显示(通常为红色和绿色),并自动缩放到碰撞位置。 - 每次点击消息框的“确定”后,插件会重置颜色并显示下一个碰撞(如果存在)。 - 所有碰撞显示完毕后,会有一个完成提示。 - 您也可以手动打开 Navisworks 的 Clash Detective 窗口,查看新创建的动态碰撞测试及其结果。 ### 6. 全功能插件:后续完善功能和实现方式 本 Demo 版插件提供了一个核心功能的快速实现。要将其发展为生产级的全功能插件,需要考虑以下增强功能和实现方式: #### 6.1 增强的用户界面 (UI) - **自定义 Dockable Window:** 而不是简单的 `MessageBox` 提示,开发一个自定义的停靠窗口(继承自 `DockPanePlugin` 3)。 - **输入控件:** 包含用于选择移动对象和路径点(例如,通过选择集或搜索集名称)的文本框或按钮。 - **参数设置:** 允许用户配置碰撞类型(硬碰撞、软碰撞)、容差、动画时长和步长间隔的输入字段。 - **进度条:** 在运行动画和碰撞测试时显示进度条,以提供更好的用户体验。 - **结果显示:** 在窗口中列出碰撞结果,允许用户点击查看、过滤和分组。 - **实现方式:** 使用 WPF (Windows Presentation Foundation) 或 WinForms 来设计 Dockable Window 的 UI。通过 `Autodesk.Navisworks.Api.Plugins.DockPanePlugin` 类来创建和管理停靠窗口 3。 #### 6.2 高级路径定义 - **从 CAD 几何体提取路径:** - **支持线/多段线:** 编写更健壮的代码来从用户选择的 `ModelItem` 中提取线或多段线的顶点。这需要深入了解 `ModelItem.Geometry` 和 `PrimitiveTypes`。 - **支持样条曲线:** 对于复杂的样条曲线,可能需要通过 API 对其进行采样以获取一系列离散点,然后用于创建关键帧。这可能涉及更复杂的几何计算。 - **从外部文件导入路径:** - 允许用户导入 CSV 或 XML 文件,其中包含路径点的 XYZ 坐标和可选的旋转信息。 - 插件解析这些文件,并编程创建动画关键帧。 - **交互式路径绘制:** - 允许用户直接在 Navisworks 场景中通过点击来定义路径点,插件实时捕获这些点并生成动画。这需要更复杂的事件监听和图形交互逻辑。 - **实现方式:** 利用 `Autodesk.Navisworks.Api.Geometry` 命名空间下的类来处理几何体。对于文件导入,使用.NET 的文件 I/O 功能。 #### 6.3 增强的碰撞结果可视化 - **持久化颜色覆盖:** 允许用户选择在所有碰撞显示完毕后,保持碰撞对象的颜色覆盖,而不是每次都重置。 - **自定义高亮效果:** - 根据碰撞类型(硬碰撞、软碰撞)或严重程度应用不同的颜色方案。 - 在碰撞发生时,可以添加临时的视觉效果,例如闪烁或透明度变化。 - **碰撞信息叠加:** 在场景中直接在碰撞位置附近显示文本标签,显示碰撞 ID、距离、时间等关键信息。 - **自动生成碰撞视点:** 对于每个检测到的碰撞,自动创建并保存一个 Navisworks 视点,其中包含碰撞对象的颜色覆盖和合适的相机位置。 - **导出带高亮显示的动画视频:** Navisworks 本身无法直接导出包含实时碰撞高亮显示的动画视频 5。 - **变通方案:** 插件可以在每个碰撞发生的时间点暂停动画,捕获屏幕截图(`doc.ActiveView.CaptureImage()`),并应用颜色覆盖。然后,将这些图像序列与原始动画视频(无高亮)在外部视频编辑软件中进行合成。或者,使用第三方屏幕录制软件在插件运行过程中录制 Navisworks 界面 5。 - **实现方式:** 广泛使用 `Document.Models.OverridePermanentColor()` 和 `Document.Models.OverridePermanentTransparency()`。对于文本叠加,可能需要自定义图形绘制或利用 Navisworks 的注释功能。 #### 6.4 综合报告与问题管理 - **详细的 Excel 报告:** - 导出包含所有碰撞详细信息的 Excel 报告,包括碰撞 ID、动画时间戳、涉及对象名称、碰撞类型、距离、位置坐标等。 - 可以借鉴 `Navisworks.Clash.Exporter` 等开源项目在 Excel 报告方面的实现。 - **集成外部问题跟踪系统:** - 与 BIM 360 Model Coordination、BIM Track 或其他项目管理平台集成,自动将碰撞作为问题发布,并分配给相关团队成员进行解决。 - 支持导入和导出 Clash Test 为 XML 格式,以便在不同项目或团队之间共享标准化设置。 - **实现方式:** 使用 `Microsoft.Office.Interop.Excel` 库(如果需要直接操作 Excel 文件)或生成 CSV/XML 文件。对于外部系统集成,需要研究相应平台的 API。 #### 6.5 性能优化 - **异步操作:** 对于长时间运行的动画和碰撞测试,使用异步编程(`async/await`)来避免 UI 冻结,提高用户体验。 - **模型简化:** 插件可以提供选项,在运行动态碰撞测试之前,对模型进行简化(例如,移除不必要的细节、合并几何体),以减少计算量。 - **智能步长调整:** 根据模型复杂性、移动速度和所需精度,动态调整 `SimulationStep` 间隔。 - **内存管理:** 优化内存使用,尤其是在处理大量碰撞结果或大型模型时,避免内存泄漏。 - **实现方式:** 遵循.NET 异步编程最佳实践。利用 Navisworks API 提供的模型优化功能。 #### 6.6 健壮性与错误处理 - **全面的错误处理:** 捕获并处理各种潜在的异常,例如用户选择错误、API 调用失败、文件读写问题等。 - **日志记录:** 实现详细的日志记录功能,将插件的运行状态、警告和错误信息写入日志文件,便于调试和问题排查。 - **用户反馈:** 提供清晰的用户反馈,告知用户操作的当前状态、成功或失败原因。 - **实现方式:** 使用 `try-catch` 块进行异常处理,并集成.NET 的日志框架(如 NLog 或 Serilog)。 ### 7. 总结 本开发文档提供了一个 Navisworks 动态碰撞检测插件的 Demo 级实现方案,旨在帮助您快速入门并构建一个功能演示。通过利用 Navisworks.NET API,您可以自动化复杂的动画和碰撞检测流程,并提供直观的视觉反馈。 未来的全功能插件将需要更高级的 UI、更灵活的路径定义、更丰富的可视化选项、更强大的报告功能以及全面的性能优化和错误处理。通过迭代开发和持续改进,这个插件将成为 Navisworks 用户在施工物流和设备移动规划中不可或缺的强大工具。