24 KiB
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 项目
- 打开 Visual Studio。
- 选择 “创建新项目”。
- 在项目模板中,搜索并选择 “C#” 语言下的 “类库 (.NET Framework)”。点击 “下一步”。
- 配置新项目:
- 项目名称:
DynamicClashDetector - 位置: 选择一个合适的文件夹来保存您的项目。
- 解决方案名称:
DynamicClashDetector - 框架: 选择
.NET Framework 4.7.2(或与您的 Navisworks 2017 兼容的最高版本,通常 4.6 或 4.7.2 均可)。
- 项目名称:
- 点击 “创建”。
3.2 添加 Navisworks API 引用
- 在 “解决方案资源管理器” 中,右键单击您的项目(
DynamicClashDetector),然后选择 “添加” > “引用...”。 - 在 “引用管理器” 对话框中,选择 “浏览” 选项卡。
- 点击 “浏览...” 按钮。
- 导航到您的 Navisworks Manage 2017 安装目录下的
api\net\文件夹(例如:C:\Program Files\Autodesk\Navisworks Manage 2017\Autodesk Navisworks Manage 2017 SDK\api\net\)。 - 选择以下 DLL 文件并点击 “添加”:
Autodesk.Navisworks.Api.dllAutodesk.Navisworks.Automation.dll(虽然此 Demo 不直接使用自动化,但通常会引用)Autodesk.Navisworks.Interop.ComApi.dll(用于某些低级或旧版 API 交互,此 Demo 尽量避免,但作为备用)
- 点击 “确定” 关闭引用管理器。
3.3 配置插件属性和 Ribbon 布局
Navisworks 插件通过特定的特性(Attributes)来定义其行为和在用户界面中的显示。
-
重命名类文件: 在“解决方案资源管理器”中,将默认的
Class1.cs重命名为MainPlugin.cs。 -
添加插件特性: 打开
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<T> // 定义插件的唯一 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<ModelItem> pathPointsModels = selectedItems.Skip(1).ToList();
// 确保路径点有几何体,可以提取中心点
if (pathPointsModels.Any(item => item.BoundingBox == null))
{
MessageBox.Show("部分路径点没有有效的几何体(无法获取边界框)。请选择具有几何体的模型元素作为路径点。", "路径错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
// 提取路径点的中心坐标
List<Point3D> 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<ClashResult>())
{
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 编译插件
- 在 Visual Studio 中,选择 “生成” > “生成解决方案”。
- 如果生成成功,您将在项目输出目录(通常是
DynamicClashDetector\bin\Debug或DynamicClashDetector\bin\Release)中找到DynamicClashDetector.dll文件。
5.2 部署插件
Navisworks 插件通常部署在特定的应用程序插件文件夹中。
-
在 Navisworks 插件目录中创建一个新的文件夹,例如:
%AppData%\Autodesk\ApplicationPlugins\DynamicClashDetector.bundle\(这通常解析为C:\Users\<您的用户名>\AppData\Roaming\Autodesk\ApplicationPlugins\DynamicClashDetector.bundle\) -
在该
DynamicClashDetector.bundle文件夹内,创建一个名为Contents的子文件夹。 -
将您编译生成的
DynamicClashDetector.dll文件以及Resources文件夹(包含图标文件)复制到Contents文件夹中。 最终结构应类似:DynamicClashDetector.bundle/ ├── Contents/ │ ├── DynamicClashDetector.dll │ └── Resources/ │ ├── Icon16x16.png │ └── Icon32x32.png └── PackageContents.xml (可选,但推荐用于更复杂的插件部署)注意: 对于 Demo,
PackageContents.xml文件不是必需的,但对于生产级插件,它用于定义插件的元数据和加载行为。
5.3 测试插件
- 启动 Navisworks Manage 2017。
- 打开一个模型: 加载一个包含一些结构、MEP 或其他固定模型的 Navisworks 文件(.nwc,.nwd,.nwf)。
- 准备测试模型:
- 移动对象: 确保模型中有一个可以作为“移动对象”的独立模型元素(例如,一个设备、一个方块或一个简单的几何体)。
- 路径点: 在模型中创建或导入一系列小球、小方块或其他易于选择的几何体,它们将作为您的路径点,定义移动对象的非直线路径。确保这些路径点是独立的模型元素。
- 执行插件:
- 在 Navisworks Ribbon 界面中,找到 “附加模块” 选项卡。
- 您应该会看到一个名为 “动态碰撞检测” 的新面板或按钮。
- 选择对象:
- 首先,在场景中选择您的 “移动对象”。
- 然后,按住
Ctrl键,依次选择您定义的所有 “路径点” 模型元素。 - 确保只选择了这两个类别的对象(一个移动对象,多个路径点)。
- 点击 “动态碰撞检测” 按钮。
- 观察结果:
- 插件将弹出消息框,提示选择成功、动画创建成功、测试运行完成。
- 如果检测到碰撞,插件将逐一弹出消息框提示碰撞信息,并在模型中将碰撞的两个对象高亮显示(通常为红色和绿色),并自动缩放到碰撞位置。
- 每次点击消息框的“确定”后,插件会重置颜色并显示下一个碰撞(如果存在)。
- 所有碰撞显示完毕后,会有一个完成提示。
- 您也可以手动打开 Navisworks 的 Clash Detective 窗口,查看新创建的动态碰撞测试及其结果。
6. 全功能插件:后续完善功能和实现方式
本 Demo 版插件提供了一个核心功能的快速实现。要将其发展为生产级的全功能插件,需要考虑以下增强功能和实现方式:
6.1 增强的用户界面 (UI)
- 自定义 Dockable Window: 而不是简单的
MessageBox提示,开发一个自定义的停靠窗口(继承自DockPanePlugin3)。- 输入控件: 包含用于选择移动对象和路径点(例如,通过选择集或搜索集名称)的文本框或按钮。
- 参数设置: 允许用户配置碰撞类型(硬碰撞、软碰撞)、容差、动画时长和步长间隔的输入字段。
- 进度条: 在运行动画和碰撞测试时显示进度条,以提供更好的用户体验。
- 结果显示: 在窗口中列出碰撞结果,允许用户点击查看、过滤和分组。
- 实现方式: 使用 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 用户在施工物流和设备移动规划中不可或缺的强大工具。