根本原因:新代码在循环中调用了 AddPoint() 方法,该方法每次都会触发 UpdateTotalLength(),导致: 算法复杂度:从 O(n) 变成 O(n² log n) 排序次数:12,480 个点 = 78,000,000 次排序 性能损失:从 76 毫秒 → 12.5 秒(130倍慢) 修复方案:直接使用 Points.Add() 绕过昂贵的 UpdateTotalLength() 调用
217 lines
5.6 KiB
Markdown
217 lines
5.6 KiB
Markdown
# AGENTS.md
|
||
|
||
本文件包含在 NavisworksTransport 仓库中工作的代理编码助手所需的构建/测试命令和代码风格指南。
|
||
|
||
## 构建命令
|
||
|
||
### 主要构建
|
||
|
||
```bash
|
||
./compile.bat
|
||
```
|
||
|
||
- 使用 Visual Studio 2022 的 MSBuild
|
||
- 构建 Release 配置的 x64 平台
|
||
- 目标框架:.NET Framework 4.8
|
||
|
||
### 测试命令
|
||
|
||
```bash
|
||
./run-unit-tests.bat
|
||
```
|
||
|
||
- 首先构建主项目
|
||
- 构建测试项目(Release/x64)
|
||
- 使用 VSTest 控制台运行单元测试
|
||
- 测试框架:MSTest 3.0.4
|
||
|
||
### 手动测试执行
|
||
|
||
```bash
|
||
# 仅构建测试项目
|
||
MSBuild.exe NavisworksTransport.UnitTests.csproj /p:Configuration=Release /p:Platform=x64
|
||
|
||
# 运行特定测试(使用 Release 路径匹配构建输出)
|
||
VSTest.Console.exe "bin\x64\Release\NavisworksTransport.UnitTests.dll" /Framework:".NETFramework,Version=v4.8" /TestAdapterPath:"packages\MSTest.TestAdapter.3.0.4\build\net462"
|
||
```
|
||
|
||
## 项目结构
|
||
|
||
### 目标环境
|
||
|
||
- **平台**: Navisworks 2026 (Windows 10+)
|
||
- **框架**: .NET Framework 4.8
|
||
- **语言**: C# 7.3
|
||
- **架构**: x64
|
||
|
||
### 关键目录
|
||
|
||
- `src/Core/` - 主插件文件和业务逻辑
|
||
- `src/Commands/` - 命令模式实现
|
||
- `src/PathPlanning/` - A* 算法和网格地图生成
|
||
- `src/UI/WPF/` - WPF MVVM UI 组件
|
||
- `src/Utils/` - 工具类和助手
|
||
- `UnitTests/` - 测试文件
|
||
|
||
### 插件架构
|
||
|
||
- **MainPlugin.cs**: AddInPlugin - Ribbon UI + 停靠面板
|
||
- **PathClickToolPlugin.cs**: ToolPlugin - 3D 鼠标交互
|
||
- **PathPointRenderPlugin.cs**: RenderPlugin - 3D 可视化
|
||
|
||
### API 使用
|
||
|
||
- **Native API** (`Autodesk.Navisworks.Api`): 核心功能
|
||
- **COM API** (`Autodesk.Navisworks.ComApi`): 属性持久化, TimeLiner
|
||
- 在 MainPlugin 构造函数中初始化 `GlobalExceptionHandler`
|
||
|
||
## 代码风格指南
|
||
|
||
### 导入和命名空间
|
||
|
||
```csharp
|
||
// System 命名空间优先
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Threading.Tasks;
|
||
|
||
// 第三方库
|
||
using RoyT.AStar;
|
||
|
||
// Navisworks API 命名空间
|
||
using Autodesk.Navisworks.ComApi;
|
||
using Autodesk.Navisworks.Api;
|
||
using Autodesk.Navisworks.Api.Plugins;
|
||
|
||
// 项目命名空间(按字母顺序)
|
||
using NavisworksTransport.Core;
|
||
using NavisworksTransport.Utils;
|
||
using NavisworksTransport.UI.WPF.ViewModels;
|
||
```
|
||
|
||
### 命名约定
|
||
|
||
- **类**: PascalCase (例如: `PathPlanningManager`)
|
||
- **方法**: PascalCase (例如: `GenerateGridMap`)
|
||
- **属性**: PascalCase (例如: `CellSize`)
|
||
- **字段**: camelCase 带下划线前缀 (例如: `_uiStateManager`)
|
||
- **常量**: PascalCase (例如: `MaxHeightDiff`)
|
||
- **接口**: PascalCase 带 'I' 前缀 (例如: `IPathPlanningCommand`)
|
||
- **枚举**: PascalCase (例如: `LogLevel`)
|
||
|
||
### 单位系统 - 极其重要
|
||
|
||
所有网格地图和路径规划计算**必须使用模型单位**,不要用米制单位。
|
||
|
||
```csharp
|
||
// ✅ 正确:在函数入口转换
|
||
public GridMap GenerateFromBIM(BoundingBox3D bounds, double cellSizeMeters, ...)
|
||
{
|
||
double factor = UnitsConverter.GetMetersToUnitsConversionFactor(Application.ActiveDocument.Units);
|
||
double cellSizeInModelUnits = cellSizeMeters * factor;
|
||
// 使用模型单位进行所有计算
|
||
}
|
||
|
||
// ❌ 错误:在计算中混用单位
|
||
private const double MAX_HEIGHT_DIFF = 0.35; // 米!
|
||
if (heightDiff > MAX_HEIGHT_DIFF) // Bug!
|
||
```
|
||
|
||
### 错误处理
|
||
|
||
- **防御性编程**: 检测并报告错误,不要隐藏它们
|
||
- **日志记录**: 使用 `LogManager` 进行所有错误报告
|
||
- **异常**: 不要仅仅为了吞噬异常而捕获它们
|
||
|
||
```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更新
|
||
|
||
- 使用 `UIStateManager` 进行线程安全的UI更新
|
||
- UI操作必须编组到主线程
|
||
- 使用异步事件触发避免死锁
|
||
|
||
```csharp
|
||
// ✅ 正确:异步事件触发
|
||
private void OnStatusChanged(string status)
|
||
{
|
||
Task.Run(() =>
|
||
{
|
||
try
|
||
{
|
||
StatusChanged?.Invoke(this, status);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"StatusChanged事件失败: {ex.Message}");
|
||
}
|
||
});
|
||
}
|
||
```
|
||
|
||
### 包管理
|
||
|
||
- 使用旧式 csproj 与 `<Reference Include>` 和 HintPath
|
||
- packages.config 用于手动包管理
|
||
- **不要** 使用 `dotnet add package`
|
||
- 包路径: `packages\{PackageId}.{Version}\lib\{TargetFramework}\{Assembly}.dll`
|
||
|
||
### 文档和注释
|
||
|
||
- 对公共 API 使用 XML 文档
|
||
- 业务逻辑可以使用中文注释
|
||
- 注释重点说明"为什么"而不是"什么"
|
||
|
||
### 性能考虑
|
||
|
||
- 缓存频繁访问的几何数据
|
||
- 使用空间索引进行碰撞检测
|
||
- 使用 `SmartDataBindingOptimizer` 优化 UI 更新
|
||
- 最小化跨线程操作
|
||
|
||
## 常见错误避免
|
||
|
||
1. **单位混淆**: 绝不要在计算中混用米制和模型单位
|
||
2. **线程违规**: 始终将UI操作编组到主线程
|
||
3. **异常吞噬**: 正确记录和处理错误
|
||
4. **内存泄漏**: 释放资源并取消事件订阅
|
||
5. **API兼容性**: 专门针对 Navisworks 2026,不考虑向后兼容
|
||
|
||
## 验证
|
||
|
||
运行命令前,代理应该验证:
|
||
|
||
- 构建输出存在: `dir bin\x64\Release\NavisworksTransportPlugin.dll`
|
||
- 测试程序集存在: `dir bin\x64\Release\NavisworksTransport.UnitTests.dll`
|
||
- 依赖项在预期的包路径中
|
||
- MSBuild 和 VSTest 在预期位置可用
|
||
|
||
## 调试
|
||
|
||
- 调试日志位置: `"C:\ProgramData\Autodesk\Navisworks Manage 2026\plugins\NavisworksTransportPlugin\logs\debug.log"`
|
||
- 使用 `LogManager` 进行结构化日志记录
|
||
- 在 Navisworks 2026 环境中测试以进行完整集成测试
|