# AGENTS.md 本文件为AI编码助手提供 NavisworksTransport 项目的完整开发指南。阅读本文件前,请确保你已经了解项目的基本结构和目标。 ## 项目概述 **NavisworksTransport** 是专为 Autodesk Navisworks Manage 2026 开发的物流路径规划插件,用于BIM模型中的运输冲突检测和路径规划。 ### 核心功能 - **物流属性管理**: 为模型分配类别属性(门、电梯、楼梯、通道、障碍物) - **自动路径规划**: 基于A*算法的2.5D网格路径规划,支持通道优先策略 - **碰撞检测**: 与Navisworks ClashDetective集成,实现动态碰撞检测 - **动画仿真**: TimeLiner集成,支持路径动画播放和仿真 - **吊装路径**: 支持空中吊装路径规划(两次点击模式) - **数据导出**: 支持XML、JSON、CSV格式的路径数据导出,以及DELMIA数据格式 ### 技术栈 | 组件 | 版本/说明 | |------|----------| | 目标平台 | Navisworks Manage 2026 | | 框架 | .NET Framework 4.8 | | 语言 | C# 7.3 | | 架构 | x64 | | UI框架 | WPF (MVVM模式) + Windows Forms集成 | ### 项目文件 | 文件 | 说明 | |------|------| | `TransportPlugin.csproj` | 主插件项目(旧式csproj格式) | | `NavisworksTransport.UnitTests.csproj` | 单元测试项目 | | `TransportPlugin.sln` | Visual Studio 解决方案 | | `packages.config` | NuGet包配置(旧式包管理) | | `default_config.toml` | 默认配置文件模板 | | `compile.bat` | 构建脚本 | | `run-unit-tests.bat` | 测试脚本 | | `deploy-plugin.bat` | 部署脚本 | ## 构建命令 ### 环境要求 - Windows 10 或更高版本 - Visual Studio 2022(Community/Professional) - Navisworks Manage 2026(已安装) - .NET Framework 4.8 Developer Pack ### 主要构建 ```bash ./compile.bat ``` - 自动检测 Visual Studio 2022 的 MSBuild - 构建 Release 配置的 x64 平台 - 输出目录: `bin\x64\Release\` ### 手动构建 ```bash # 设置MSBuild路径 set MSBUILD_PATH="C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\MSBuild.exe" # 构建主项目 %MSBUILD_PATH% "TransportPlugin.csproj" /p:Configuration=Release /p:Platform=x64 # 构建测试项目 %MSBUILD_PATH% "NavisworksTransport.UnitTests.csproj" /p:Configuration=Release /p:Platform=x64 ``` ### 运行测试 ```bash ./run-unit-tests.bat ``` 该脚本将: 1. 构建主项目 2. 构建测试项目 3. 使用 VSTest.Console 运行单元测试 ### 部署插件 ```bash ./deploy-plugin.bat ``` 自动复制插件文件到 Navisworks 插件目录: `C:\ProgramData\Autodesk\Navisworks Manage 2026\plugins\TransportPlugin\` ## 项目架构 ### 目录结构 ``` src/ ├── Core/ # 核心插件和业务逻辑 │ ├── MainPlugin.cs # DockPanePlugin - Ribbon UI + 停靠面板 │ ├── PathClickToolPlugin.cs # ToolPlugin - 3D鼠标交互工具 │ ├── PathPointRenderPlugin.cs # RenderPlugin - 3D可视化渲染 │ ├── PathPlanningManager.cs # 路径规划管理器(与UI解耦) │ ├── PathDataManager.cs # 路径数据管理 │ ├── PathDatabase.cs # SQLite数据库操作 │ ├── PathCurveEngine.cs # 路径曲线化引擎 │ ├── UIStateManager.cs # 线程安全的UI状态管理 │ ├── Animation/ # 动画系统 │ │ ├── PathAnimationManager.cs │ │ └── TimeLinerIntegrationManager.cs │ ├── Collision/ # 碰撞检测 │ │ ├── ClashDetectiveIntegration.cs │ │ └── BatchCollisionProcessor.cs │ ├── Spatial/ # 空间索引 │ │ ├── SpatialHashGrid.cs │ │ └── SpatialIndexManager.cs │ ├── Properties/ # 属性管理 │ │ ├── CategoryAttributeManager.cs │ │ └── NavisworksComPropertyManager.cs │ └── Config/ # 配置管理 │ ├── SystemConfig.cs │ └── ConfigManager.cs ├── Commands/ # 命令模式实现 │ ├── CommandBase.cs │ ├── CommandManager.cs │ ├── AutoPathPlanningCommand.cs │ └── ... ├── PathPlanning/ # A*算法和网格地图 │ ├── GridMap.cs # 网格地图定义 │ ├── GridMapGenerator.cs # 网格生成器 │ ├── AutoPathFinder.cs # A*寻路实现 │ ├── ChannelBasedGridBuilder.cs # 通道优先网格构建 │ ├── VoxelGrid.cs # 3D体素网格(实验性) │ └── PathOptimizer.cs # 路径优化 ├── UI/WPF/ # WPF用户界面 │ ├── Views/ # XAML视图 │ ├── ViewModels/ # MVVM视图模型 │ ├── Models/ # 数据模型 │ ├── Converters/ # 值转换器 │ ├── Commands/ # WPF命令 │ └── Services/ # UI服务 └── Utils/ # 工具类 ├── UnitsConverter.cs # 单位转换(关键!) ├── LogManager.cs # 日志管理 ├── GeometryHelper.cs # 几何计算 └── ... UnitTests/ # 单元测试 ├── Core/ # 核心功能测试 ├── Commands/ # 命令测试 └── Utils/ # 工具类测试 ``` ### 插件类型说明 | 插件类 | 类型 | 功能 | |--------|------|------| | `MainPlugin.cs` | DockPanePlugin | 主UI面板,包含WPF控件宿主 | | `PathClickToolPlugin.cs` | ToolPlugin | 鼠标点击工具,获取精确的3D坐标 | | `PathPointRenderPlugin.cs` | RenderPlugin | 3D渲染,显示路径点和连线 | ### 关键依赖 **Navisworks API(必须安装Navisworks 2026):** - `Autodesk.Navisworks.Api.dll` - `Autodesk.Navisworks.ComApi.dll` - `Autodesk.Navisworks.Interop.ComApi.dll` - `Autodesk.Navisworks.Timeliner.dll` - `Autodesk.Navisworks.Clash.dll` - `Autodesk.Navisworks.Controls.dll` **NuGet包:** - `RoyT.AStar 3.0.2` - A*寻路算法 - `geometry4Sharp 1.0.0` - 3D几何计算(体素路径规划) - `System.Data.SQLite.Core 1.0.118.0` - SQLite数据库 - `Tomlyn 0.19.0` - TOML配置文件解析 - `MSTest.TestFramework 3.0.4` - 单元测试框架 ## 代码规范 ### 导入顺序 ```csharp // 1. System命名空间 using System; using System.Collections.Generic; using System.Linq; // 2. 第三方库 using RoyT.AStar; // 3. Navisworks API using Autodesk.Navisworks.Api; using Autodesk.Navisworks.ComApi; using Autodesk.Navisworks.Api.Plugins; // 4. 项目命名空间(按字母顺序) using NavisworksTransport.Commands; using NavisworksTransport.Core; using NavisworksTransport.PathPlanning; using NavisworksTransport.UI.WPF.ViewModels; using NavisworksTransport.Utils; ``` ### 命名约定 | 类型 | 命名规则 | 示例 | |------|----------|------| | 类 | PascalCase | `PathPlanningManager` | | 接口 | PascalCase + 'I'前缀 | `IPathPlanningCommand` | | 方法 | PascalCase | `GenerateGridMap` | | 属性 | PascalCase | `CellSize` | | 字段 | camelCase + 下划线前缀 | `_uiStateManager` | | 常量 | PascalCase | `MaxHeightDiff` | | 枚举 | PascalCase | `GridGenerationMode` | ### 代码开发原则 #### 1. 禁止硬编码默认值 函数的参数和初始化时不要使用硬编码的默认值,应从配置读取或使用命名常量: ```csharp // ❌ 错误:硬编码默认值 public GridMap Generate(double cellSize = 0.5) { } // ❌ 错误:构造函数中硬编码 public PathPlanner() { _cellSize = 0.5; _maxSlope = 15.0; } // ✅ 正确:从配置读取 public GridMap Generate(double cellSize) { cellSize = cellSize > 0 ? cellSize : ConfigManager.Instance.Current.PathEditing.CellSizeMeters; // ... } // ✅ 正确:使用命名常量 private const double DEFAULT_CELL_SIZE_METERS = 0.5; public PathPlanner(double cellSize = DEFAULT_CELL_SIZE_METERS) { } ``` #### 2. 不向后兼容 本项目专门针对 Navisworks 2026 开发,**程序中不要写向后兼容代码**: ```csharp // ❌ 错误:向后兼容代码 #if NAVISWORKS_2025 // 2025 specific code #elif NAVISWORKS_2026 // 2026 specific code #endif // ❌ 错误:运行时版本检查 if (NavisworksVersion.Major < 2026) { // 兼容旧版本的代码 } // ✅ 正确:直接针对2026编写 var clashResult = Autodesk.Navisworks.Api.Clash.ClashResult.GetAllResults(); ``` #### 3. 不随意加回退逻辑 程序中不要随意加回退逻辑,避免过度防御性编程导致隐藏问题: ```csharp // ❌ 错误:过度回退逻辑 public double GetCellSize() { try { return ConfigManager.Instance.Current.PathEditing.CellSizeMeters; } catch { return 0.5; // 隐藏了配置读取失败的问题! } } // ❌ 错误:静默回退 double value = GetConfigValue("cellSize"); if (value <= 0) value = 0.5; // 为什么<=0?配置验证应该保证这一点 // ✅ 正确:让问题暴露出来 public double GetCellSize() { return ConfigManager.Instance.Current.PathEditing.CellSizeMeters; // 如果配置有问题,让它抛出异常,在源头解决 } ``` #### 4. 代码复用优先 规划和编写新功能或新模块时,**尽量复用项目中的代码,尤其是工具和辅助类**: ```csharp // ❌ 错误:重复造轮子 public static double MyConvertUnits(double value) { // 自己写一套单位转换逻辑... } // ✅ 正确:复用现有的 UnitsConverter using NavisworksTransport.Utils; double meters = UnitsConverter.ConvertToMeters(distance); // ❌ 错误:自己实现集合通知 public class MyCollection : ObservableCollection { // 重写一大堆线程安全代码... } // ✅ 正确:复用 ThreadSafeObservableCollection using NavisworksTransport.UI.WPF.Collections; var collection = new ThreadSafeObservableCollection(); // ❌ 错误:自己写几何计算 public double Distance(Point3D a, Point3D b) { return Math.Sqrt(Math.Pow(a.X - b.X, 2) + ...); } // ✅ 正确:复用 GeometryHelper using NavisworksTransport.Utils; double distance = GeometryHelper.Distance(pointA, pointB); ``` **复用检查清单:** - 需要单位转换?→ 使用 `UnitsConverter` - 需要几何计算?→ 使用 `GeometryHelper` - 需要日志记录?→ 使用 `LogManager` - 需要线程安全的集合?→ 使用 `ThreadSafeObservableCollection` - 需要坐标转换?→ 使用 `CoordinateConverter` - 需要路径相关工具?→ 使用 `PathHelper` ### 单位系统 - 极其重要 **所有网格地图和路径规划计算必须使用模型单位,严禁混用米制单位。** #### 变量命名铁律(强制执行) | 单位类型 | 命名规则 | 示例 | |---------|---------|------| | **米单位** | 变量名必须以 `InMeters` 结尾 | `lengthInMeters`, `heightInMeters` | | **模型单位** | 变量名**无后缀** | `length`, `height`, `cellSize` | ```csharp // ✅ 正确:严格遵循命名规范 public void SetSize(double lengthInMeters, double widthInMeters, double heightInMeters) { double metersToUnits = UnitsConverter.GetMetersToUnitsConversionFactor(...); // 米单位 → 模型单位(无后缀) double length = lengthInMeters * metersToUnits; double width = widthInMeters * metersToUnits; double height = heightInMeters * metersToUnits; // 后续计算使用模型单位(无后缀) boundingBox = new BoundingBox3D(0, 0, 0, length, width, height); } // ❌ 错误:命名不规范,导致单位混乱 public void SetSize(double length, double width, double height) // 参数是米还是模型单位? { double scale = length / baseSize; // 单位不明确! } // ❌ 错误:后缀使用不一致 public void SetSize(double lengthMeters, double widthMeters, double heightMeters) // 不要用Meters后缀 { double lengthInModelUnits = lengthMeters * factor; // 不要用InModelUnits后缀 } ``` #### 单位转换方法 `UnitsConverter` 提供以下方法: - `GetUnitsToMetersConversionFactor()` - 文档单位转米 - `GetMetersToUnitsConversionFactor()` - 米转文档单位 - `ConvertToMeters(distance)` - 转换距离为米 - `ConvertFromMeters(distanceInMeters)` - 从米转换距离 #### 完整示例 ```csharp // ✅ 正确:在函数入口统一转换,严格遵循命名规范 public GridMap GenerateFromBIM(BoundingBox3D bounds, double cellSizeInMeters, ...) { double factor = UnitsConverter.GetMetersToUnitsConversionFactor(Application.ActiveDocument.Units); double cellSize = cellSizeInMeters * factor; // 模型单位,无后缀 // 后续所有计算使用 cellSize(模型单位) } // ❌ 错误:混用单位 private const double MAX_HEIGHT_DIFF = 0.35; // 这是米! if (heightDiff > MAX_HEIGHT_DIFF) // 单位不匹配,严重Bug! ``` ### 错误处理 ```csharp // ✅ 正确:记录并适当处理异常 try { var result = SomeOperation(); return result; } catch (Exception ex) { LogManager.Error($"Operation failed: {ex.Message}"); throw; // 或适当处理 } // ❌ 错误:静默吞掉异常 try { var result = SomeOperation(); return result; } catch { return null; // 隐藏了问题! } ``` ### 线程安全和UI更新 所有UI操作必须编组到主线程: ```csharp // ✅ 正确:使用UIStateManager进行线程安全更新 _uiStateManager.UpdateStatus("正在处理..."); // ✅ 正确:异步事件触发避免死锁 private void OnStatusChanged(string status) { Task.Run(() => { try { StatusChanged?.Invoke(this, status); } catch (Exception ex) { LogManager.Error($"StatusChanged事件失败: {ex.Message}"); } }); } ``` ### WPF UI开发注意事项 #### 必须检查:XAML资源引用有效性 **问题**:使用未在XAML中定义的Converter/Style资源会导致窗口无法显示 ```xml Visibility="{Binding HasItems, Converter={StaticResource InverseBoolToVisibilityConverter}}" Visibility="{Binding HasItems, Converter={StaticResource BoolToVisibilityConverter}, ConverterParameter=Inverse}" ``` **项目中已定义的资源(AnimationControlView.xaml)**: | 资源名 | 类型 | 说明 | |--------|------|------| | `BoolToVisibilityConverter` | BoolToVisibilityConverter | 布尔转可见性,支持Inverse参数 | **XAML开发工作流程(必须遵守)**: 1. **每添加一个资源引用,立即确认其存在** ``` ❌ 错误做法: - 复制其他文件的XAML代码 - 一次性写大量XAML再测试 ✅ 正确做法: - 每写一行 {StaticResource xxx},立即检查 xxx 是否已定义 - 使用 Ctrl+F 搜索 xxx 确认在当前文件或合并字典中存在 ``` 2. **资源定义位置优先级**: - 本文件 `` 或 `` 内定义 - 引用的外部资源字典(如 `NavisworksStyles.xaml`) - 必须在 XAML 顶部检查 `MergedDictionaries` 是否正确合并 3. **新增XAML文件时必做检查清单**: ``` □ 所有 {StaticResource xxx} 引用都有定义 □ 所有 xmlns:local 命名空间映射正确 □ 所有 ValueConverter 在 xaml.cs 中已实现 □ 合并的资源字典路径正确(pack://application:,,,/...) □ 编译通过后立即运行测试,验证窗口能正常打开 ``` 4. **常见错误模式与修正**: | 错误写法 | 问题 | 正确写法 | |---------|------|---------| | `InverseBoolToVisibilityConverter` | 未定义 | `BoolToVisibilityConverter` + `ConverterParameter=Inverse` | | `VisibilityConverter` | 未定义 | `BoolToVisibilityConverter` | | `BooleanToVisibilityConverter` (键名) | 引用时使用 `BoolToVisibilityConverter` | 键名和引用保持一致 | | 拼写错误的Style名 | 找不到资源 | 检查资源字典中的精确定义 | 5. **调试XAML资源错误**: - 错误信息:`无法在资源字典中找到名为 xxx 的资源` - 定位方法:从堆栈跟踪找到最后加载的XAML元素 - 快速修复:临时注释掉报错元素,添加简化版本测试 - 预防措施:小步增量开发,每步验证窗口可正常显示 #### AI助手强制执行机制(防止再次犯错) **写XAML前,必须大声说出以下承诺:** > "我承诺:本次XAML开发将严格遵守渐进式验证原则,每添加一个资源引用立即验证,绝不一次性写大量代码。" **编写过程中的强制检查点:** | 步骤 | 强制动作 | 验证命令/方法 | |-----|---------|--------------| | 1. 写完XAML结构 | 列出所有 `{StaticResource xxx}` | `grep -n "StaticResource" File.xaml` | | 2. 检查每个引用 | 在文件中搜索资源定义 | 确认 `x:Key="xxx"` 存在 | | 3. 检查Converter | 确认 xaml.cs 中有实现 | `grep "class.*Converter.*:" File.xaml.cs` | | 4. 首次编译 | 必须通过 | `compile.bat` | | 5. 运行时验证 | 窗口能正常打开无异常 | 实际运行测试 | **如果违反规则的后果:** - 必须立即停止当前工作 - 回滚到上一个可运行的版本 - 重新开始,严格按照检查点执行 **自检话术(每次保存前自问):** ``` □ 我是否复制了其他文件的XAML代码而没有检查资源? □ 我是否一次性写了超过50行XAML才测试? □ 我能否确定每个 {StaticResource} 都在当前文件或合并字典中定义? □ 如果现在运行,窗口会崩溃吗? ``` **历史错误记录(警示):** - 2025-02-14: PathAnalysisDialog.xaml 使用了 `BoolToVisibilityConverter` 但定义的是 `BooleanToVisibilityConverter`,导致窗口崩溃 - 根本原因:没有逐条执行检查清单,过度自信 #### UI色彩规范 - Material Design **项目整体使用 Google Material Design 色系**,确保视觉一致性。 **常用颜色定义**(来自 `PathPointRenderPlugin.cs`): | 用途 | 颜色名称 | RGB值 | 十六进制 | |------|---------|-------|---------| | 起点 | Material Green | (76, 175, 80) | #4CAF50 | | 通行空间 | Material Light Green | (129, 199, 132) | #81C784 | | 排除对象 | Material Light Green | (129, 199, 132) | #81C784 | **其他高亮颜色**(来自 `ModelHighlightHelper.cs`): | 类别 | 颜色 | RGB值 | |------|------|-------| | 预计算碰撞 | Material Purple | (156, 39, 176) | | 手工指定对象 | 橙色 | (255, 170, 0) | | 动画物体 | Amber/Yellow | (255, 193, 7) | | ClashDetective结果 | 红色 | Color.Red | | 通道预览 | 绿色 | Color.Green | **使用规范**: 1. 新增UI元素时优先使用上述Material色系 2. 如需新颜色,参考 [Material Design Color Palette](https://material.io/resources/color/) 3. 使用 `Color.FromByteRGB(r, g, b)` 定义颜色(Navisworks API) 4. 保持透明度一致:通行空间类用 0.8-0.9,碰撞类用不透明 ## 配置系统 配置文件使用 TOML 格式,默认配置位于 `default_config.toml`: ```toml [path_editing] cell_size_meters = 0.5 # 网格单元大小(米) max_height_diff_meters = 0.35 # 最大高度差(米) object_length_meters = 1.5 # 物体长度 object_width_meters = 1.0 # 物体宽度 object_height_meters = 2.0 # 物体高度 safety_margin_meters = 0.1 # 安全间隙 default_path_turn_radius = 2.5 # 默认转弯半径 arc_sampling_step = 0.05 # 圆弧采样步长 [visualization] margin_ratio = 0.1 # 地图边距比例 [animation] frame_rate = 30 # 动画帧率 duration_seconds = 10.0 # 动画持续时间 detection_tolerance_meters = 0.05 # 检测容差 spatial_index_cell_size = 1.0 # 空间索引格子大小 [logistics] traversable = true # 默认可通行性 priority = 5 # 优先级(1-5) height_limit_meters = 3.0 # 高度限制 speed_limit_meters_per_second = 0.8 # 速度限制 width_limit_meters = 3.0 # 宽度限制 ``` 运行时通过 `ConfigManager.Instance.Current` 访问配置。 ## 测试策略 ### 测试项目结构 ``` UnitTests/ ├── Core/ │ ├── PathCurveEngineTests.cs │ └── UIStateManagerBasicTests.cs ├── Commands/ │ └── CommandBaseTests.cs ├── Collections/ │ └── ThreadSafeObservableCollectionBasicTests.cs └── Utils/ └── UnitsConverterTests.cs ``` ### 测试框架 - **框架**: MSTest 3.0.4 - **运行器**: VSTest.Console.exe - **目标框架**: .NET Framework 4.8 ### 编写测试 ```csharp using Microsoft.VisualStudio.TestTools.UnitTesting; namespace NavisworksTransport.UnitTests { [TestClass] public class ExampleTests { [TestMethod] public void TestMethod_ShouldDoSomething() { // Arrange var input = "test"; // Act var result = SomeMethod(input); // Assert Assert.AreEqual("expected", result); } } } ``` ### 注意事项 - 独立测试:不依赖Navisworks环境,测试核心算法逻辑 - 集成测试:需要完整的Navisworks 2026环境 - 日志位置: `C:\ProgramData\Autodesk\Navisworks Manage 2026\plugins\TransportPlugin\logs\debug.log` ## 开发工作流 ### 添加新功能的标准流程 1. **定义接口**(如果需要) - 在 `src/Commands/` 或 `src/Core/` 中定义接口 2. **实现核心逻辑** - 业务逻辑放在 `src/Core/` 或 `src/PathPlanning/` - 确保单位转换正确 3. **添加命令封装**(如果需要) - 在 `src/Commands/` 中实现命令类 - 继承 `CommandBase` 或实现 `IPathPlanningCommand` 4. **更新UI** - ViewModel 在 `src/UI/WPF/ViewModels/` - View 在 `src/UI/WPF/Views/` 5. **注册到主插件** - 在 `MainPlugin.cs` 或相关管理器中集成 6. **添加测试** - 在 `UnitTests/` 对应目录添加测试 ### 调试技巧 1. **查看日志**: 日志文件位于 `C:\ProgramData\Autodesk\Navisworks Manage 2026\plugins\TransportPlugin\logs\` 2. **使用 LogManager**: 所有重要操作都应记录日志 3. **Navisworks插件调试**: - 附加到 `Roamer.exe` 进程 - 使用 `LogManager.Debug()` 输出调试信息 ## 常见问题 ### 构建失败 - **错误**: "MSBuild not found" - **解决**: 安装 Visual Studio 2022 或 Build Tools - **错误**: "无法找到 Autodesk.Navisworks.Api" - **解决**: 安装 Navisworks Manage 2026 ### 运行时错误 - **错误**: "单位不匹配导致的计算错误" - **解决**: 检查 `UnitsConverter` 使用是否正确 - **错误**: "跨线程UI操作异常" - **解决**: 使用 `UIStateManager` 或 `Dispatcher.Invoke` - **错误**: "插件未加载" - **解决**: 检查插件是否部署到正确目录,检查依赖项是否存在 ## 文档资源 - **API文档**: `doc/navisworks_api/NET/documentation/NET API.chm` - **COM API文档**: `doc/navisworks_api/COM/documentation/NavisWorksCOM.chm` - **设计文档**: `doc/design/2026/` - **架构设计**: `doc/architecture/` - **迁移指南**: `doc/migration/`(2017到2026的API变更) ## 版本信息 - **当前版本**: 2.0.0.0 - **程序集**: TransportPlugin - **作者**: Tian - **版权**: Copyright © 2024 --- **注意**: 本插件专门针对 Navisworks 2026 开发,不考虑向后兼容。