From a304191b1396e9d6231e65d231163991796907e7 Mon Sep 17 00:00:00 2001
From: tian <11429339@qq.com>
Date: Tue, 17 Feb 2026 10:21:35 +0800
Subject: [PATCH] =?UTF-8?q?=E7=A2=B0=E6=92=9E=E6=8A=A5=E5=91=8A=E8=87=AA?=
=?UTF-8?q?=E5=8A=A8=E5=AF=B9=E7=A2=B0=E6=92=9E=E7=82=B9=E6=88=AA=E5=9B=BE?=
=?UTF-8?q?=EF=BC=9B=E7=BA=A0=E6=AD=A3=E6=8F=92=E4=BB=B6=E6=94=B9=E5=90=8D?=
=?UTF-8?q?=E9=80=A0=E6=88=90=E7=9A=84=E8=B7=AF=E5=BE=84=E9=94=99=E8=AF=AF?=
=?UTF-8?q?=E3=80=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.claude/settings.local.json | 8 +-
IFLOW.md | 4 +-
QWEN.md | 12 +-
TransportPlugin.csproj | 1 +
.../System_Architecture_Design.md | 4 +-
doc/design/2017/navisworks_api_analysis.md | 2 +-
doc/design/2026/Idea.md | 2 +-
doc/design/2026/MSI_Installation_Guide.md | 26 ++--
doc/design/Design_Plan.md | 10 +-
doc/design/logistics_path.xml | 2 +-
doc/requirement/todo_features.md | 2 +-
doc/working/2017/动画创建功能开发任务.md | 2 +-
doc/working/2017/类别属性功能开发任务.md | 2 +-
doc/working/2017/路径构建功能开发任务.md | 2 +-
doc/working/cleanup_summary.md | 2 +-
..._import_implementation_summary_20251107.md | 2 +-
...deo_export_ffmpegcore_solution_20250929.md | 2 +-
doc/working/第二阶段优化计划_20250814.md | 2 +-
.../GenerateCollisionReportCommand.cs | 123 +++++++++++++++--
src/Core/Config/ConfigManager.cs | 2 +-
.../ViewModels/CollisionReportViewModel.cs | 103 ++-------------
src/Utils/CollisionSceneHelper.cs | 124 ++++++++++++++++++
src/Utils/LogManager.cs | 2 +-
src/Utils/PathHelper.cs | 38 ++++--
24 files changed, 321 insertions(+), 158 deletions(-)
create mode 100644 src/Utils/CollisionSceneHelper.cs
diff --git a/.claude/settings.local.json b/.claude/settings.local.json
index 68d8de7..2142e15 100644
--- a/.claude/settings.local.json
+++ b/.claude/settings.local.json
@@ -12,8 +12,8 @@
"Bash(compile.bat)",
"Bash(./compile.bat)",
"Bash(./tool/compile.bat:*)",
- "Bash(\"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Current\\Bin\\MSBuild.exe\" NavisworksTransportPlugin.csproj /p:Configuration=Debug /p:Platform=AnyCPU /verbosity:minimal)",
- "Bash(\"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Current\\Bin\\MSBuild.exe\" NavisworksTransportPlugin.csproj /p:Configuration=Debug /p:Platform=AnyCPU)",
+ "Bash(\"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Current\\Bin\\MSBuild.exe\" TransportPlugin.csproj /p:Configuration=Debug /p:Platform=AnyCPU /verbosity:minimal)",
+ "Bash(\"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Current\\Bin\\MSBuild.exe\" TransportPlugin.csproj /p:Configuration=Debug /p:Platform=AnyCPU)",
"WebFetch(domain:forums.autodesk.com)",
"mcp__serena__search_for_pattern",
"mcp__serena__find_symbol",
@@ -42,13 +42,13 @@
"Bash(./nuget.exe install:*)",
"Bash(dotnet test:*)",
"Bash(msbuild:*)",
- "Bash(\"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Current\\Bin\\MSBuild.exe\" \"C:\\Users\\Tellme\\apps\\NavisworksTransport\\NavisworksTransportPlugin.csproj\" /p:Configuration=Debug /p:Platform=AnyCPU /verbosity:minimal)",
+ "Bash(\"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Current\\Bin\\MSBuild.exe\" \"C:\\Users\\Tellme\\apps\\NavisworksTransport\\TransportPlugin.csproj\" /p:Configuration=Debug /p:Platform=AnyCPU /verbosity:minimal)",
"Bash(grep:*)",
"Bash(find:*)",
"mcp__context7__get-library-docs",
"Bash(powershell:*)",
"mcp__serena__insert_before_symbol",
- "Bash(\"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Current\\Bin\\MSBuild.exe\" NavisworksTransportPlugin.csproj /p:Configuration=Debug /p:Platform=AnyCPU /verbosity:normal)",
+ "Bash(\"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Current\\Bin\\MSBuild.exe\" TransportPlugin.csproj /p:Configuration=Debug /p:Platform=AnyCPU /verbosity:normal)",
"Bash(cmd:*)",
"WebFetch(domain:twentytwo.space)",
"Bash(git add:*)",
diff --git a/IFLOW.md b/IFLOW.md
index 2771c83..bc016ad 100644
--- a/IFLOW.md
+++ b/IFLOW.md
@@ -273,7 +273,7 @@ deploy-plugin.bat
1. 编译生成 `TransportPlugin.dll`
2. 将输出目录内容复制到Navisworks插件目录:
- `[Navisworks安装路径]\Plugins\NavisworksTransportPlugin\`
+ `[Navisworks安装路径]\Plugins\TransportPlugin\`
3. 重启Navisworks即可使用
### 安装包生成
@@ -558,7 +558,7 @@ detection_gap_meters = 0.05
### 日志位置
日志文件位于:
-`[Navisworks安装路径]\Plugins\NavisworksTransportPlugin\logs\debug.log`
+`[Navisworks安装路径]\Plugins\TransportPlugin\logs\debug.log`
### 文档资源
diff --git a/QWEN.md b/QWEN.md
index 5129752..ff8e467 100644
--- a/QWEN.md
+++ b/QWEN.md
@@ -46,7 +46,7 @@ NavisworksTransport 是一个针对 Autodesk Navisworks Manage 2026 开发的插
### 项目结构
```
-NavisworksTransportPlugin/
+TransportPlugin/
├── src/
│ ├── Core/ # 核心业务逻辑
│ │ ├── Animation/ # 动画管理 (LogisticsAnimationManager, TimeLinerIntegrationManager)
@@ -67,7 +67,7 @@ NavisworksTransportPlugin/
│ └── Legacy/ # 为兼容性保留的旧代码
├── Properties/
│ └── AssemblyInfo.cs
-├── NavisworksTransportPlugin.csproj # 项目文件
+├── TransportPlugin.csproj # 项目文件
└── ...
```
@@ -126,19 +126,19 @@ NavisworksTransportPlugin/
2. 确保项目引用指向正确的 Navisworks 2026 API DLL 文件(路径在 `.csproj` 文件中定义)。
3. 选择 "Debug" 或 "Release" 配置。
4. 构建项目 (`Ctrl+Shift+B`)。
-5. 输出文件为 `NavisworksTransportPlugin.dll`,位于 `bin\Debug\` 或 `bin\Release\` 目录下。
+5. 输出文件为 `TransportPlugin.dll`,位于 `bin\Debug\` 或 `bin\Release\` 目录下。
### 部署与安装
-1. 编译生成 `NavisworksTransportPlugin.dll`。
+1. 编译生成 `TransportPlugin.dll`。
2. 插件会自动安装到 Navisworks 插件目录:
- `[Navisworks安装路径]\Plugins\NavisworksTransportPlugin\`
+ `[Navisworks安装路径]\Plugins\TransportPlugin\`
3. 重启 Navisworks 即可在 "附加模块" 选项卡中找到插件。
### 运行与调试
* 在 Visual Studio 中可以直接调试插件,方法是设置 Navisworks 可执行文件(如 `NwAddinDev.exe` 或 `Navisworks.exe`)为启动外部程序。
-* 插件运行时会在 `%AppData%\Autodesk Navisworks Manage 2026\PluginsData\NavisworksTransportPlugin` 目录下生成日志文件。
+* 插件运行时会在 `%AppData%\Autodesk Navisworks Manage 2026\PluginsData\TransportPlugin` 目录下生成日志文件。
## 开发约定与实践
diff --git a/TransportPlugin.csproj b/TransportPlugin.csproj
index bc7dc70..1f0a6fd 100644
--- a/TransportPlugin.csproj
+++ b/TransportPlugin.csproj
@@ -331,6 +331,7 @@
+
diff --git a/doc/architecture/System_Architecture_Design.md b/doc/architecture/System_Architecture_Design.md
index a6a0827..3f0f100 100644
--- a/doc/architecture/System_Architecture_Design.md
+++ b/doc/architecture/System_Architecture_Design.md
@@ -553,8 +553,8 @@ public class NavisworksIntegration
```
%ProgramFiles%\Autodesk\Navisworks Manage 2026\Plugins\
-└── NavisworksTransportPlugin\
- ├── NavisworksTransportPlugin.dll # 主程序集
+└── TransportPlugin\
+ ├── TransportPlugin.dll # 主程序集
├── RoyT.AStar.dll # A*算法库
├── Newtonsoft.Json.dll # JSON处理库
├── Resources\ # 资源文件
diff --git a/doc/design/2017/navisworks_api_analysis.md b/doc/design/2017/navisworks_api_analysis.md
index c9a6e20..dbe0b67 100644
--- a/doc/design/2017/navisworks_api_analysis.md
+++ b/doc/design/2017/navisworks_api_analysis.md
@@ -654,7 +654,7 @@ public class PluginInstaller
private static readonly string NavisworksPath =
@"%PROGRAMFILES%\Autodesk\Navisworks Manage 2017";
private static readonly string PluginTargetPath =
- @"%PROGRAMFILES%\Autodesk\Navisworks Manage 2017\Plugins\NavisworksTransportPlugin";
+ @"%PROGRAMFILES%\Autodesk\Navisworks Manage 2017\Plugins\TransportPlugin";
public static bool InstallPlugin()
{
diff --git a/doc/design/2026/Idea.md b/doc/design/2026/Idea.md
index 6770153..90d2205 100644
--- a/doc/design/2026/Idea.md
+++ b/doc/design/2026/Idea.md
@@ -40,5 +40,5 @@
## 编译命令
```
-& "C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\MSBuild.exe" NavisworksTransportPlugin.csproj /p:Configuration=Debug /p:Platform=AnyCPU /verbosity:minimal
+& "C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\MSBuild.exe" TransportPlugin.csproj /p:Configuration=Debug /p:Platform=AnyCPU /verbosity:minimal
```
\ No newline at end of file
diff --git a/doc/design/2026/MSI_Installation_Guide.md b/doc/design/2026/MSI_Installation_Guide.md
index 087e86c..b14082d 100644
--- a/doc/design/2026/MSI_Installation_Guide.md
+++ b/doc/design/2026/MSI_Installation_Guide.md
@@ -95,7 +95,7 @@
在 `添加项目输出组` 对话框中:
-- 项目:`NavisworksTransportPlugin`
+- 项目:`TransportPlugin`
- 选择配置:`Release`
- 平台:`x64`(**重要:必须与项目平台一致,否则会出现平台不兼容错误**)
- 输出类型:选择 `Primary output`
@@ -142,7 +142,7 @@
**排除方法:**
1. **通过文件系统编辑器排除**
- - 在文件系统编辑器中,展开 `Application Folder` → `Primary output from NavisworksTransportPlugin (Active)`
+ - 在文件系统编辑器中,展开 `Application Folder` → `Primary output from TransportPlugin (Active)`
- 找到需要排除的DLL(如System.Net.Http.dll)
- 右键点击该DLL → `属性窗口`
- 将 `Exclude` 属性设置为 `TRUE`
@@ -190,7 +190,7 @@
插件需要安装到 Navisworks 的插件目录:
-默认路径: C:\ProgramData\Autodesk\Navisworks Manage 2026\plugins\NavisworksTransportPlugin\
+默认路径: C:\ProgramData\Autodesk\Navisworks Manage 2026\plugins\TransportPlugin\
### 设置方法
@@ -199,7 +199,7 @@
3. 将AlwaysCreate属性设置为`TRUE`
4. 在属性窗口中设置 `DefaultLocation`:
-DefaultLocation = [CommonAppDataFolder]\Autodesk\Navisworks Manage 2026\plugins\NavisworksTransportPlugin
+DefaultLocation = [CommonAppDataFolder]\Autodesk\Navisworks Manage 2026\plugins\TransportPlugin
### 目录结构说明
@@ -328,8 +328,8 @@ Visual Studio Installer Projects 会生成两个安装文件,它们各有不
- `{ProductCode}`: 安装日志中的产品代码
3. **验证安装**:
- - 检查目录:`C:\ProgramData\Autodesk\Navisworks Manage 2026\plugins\NavisworksTransportPlugin\`
- - 确认文件存在:`NavisworksTransportPlugin.dll`
+ - 检查目录:`C:\ProgramData\Autodesk\Navisworks Manage 2026\plugins\TransportPlugin\`
+ - 确认文件存在:`TransportPlugin.dll`
- 启动Navisworks 2026,检查插件是否加载
---
@@ -397,7 +397,7 @@ pause
msiexec /i "bin\Release\NavisworksTransport.Setup.msi" /qn /l*v "logs\install.log"
@echo 检查安装结果...
-if exist "C:\ProgramData\Autodesk\Navisworks Manage 2026\plugins\NavisworksTransportPlugin\NavisworksTransportPlugin.dll" (
+if exist "C:\ProgramData\Autodesk\Navisworks Manage 2026\plugins\TransportPlugin\TransportPlugin.dll" (
echo ✅ 部署成功!
) else (
echo ❌ 部署失败,请检查安装日志:logs\install.log
@@ -416,7 +416,7 @@ pause
**解决**:
-1. 检查项目引用:`NavisworksTransportPlugin.csproj`
+1. 检查项目引用:`TransportPlugin.csproj`
2. 确保所有NuGet包已还原
3. 清理解决方案:`Build` → `Clean Solution`
4. 重新构建:`Build` → `Rebuild Solution`
@@ -433,7 +433,7 @@ pause
1. 检查安装目录:
- C:\ProgramData\Autodesk\Navisworks Manage 2026\plugins\NavisworksTransportPlugin\
+ C:\ProgramData\Autodesk\Navisworks Manage 2026\plugins\TransportPlugin\
2. 检查Navisworks加载日志:
@@ -492,8 +492,8 @@ pause
### 1. 项目组织
NavisworksTransport/
-├── NavisworksTransportPlugin.sln
-├── NavisworksTransportPlugin/ # 插件项目
+├── TransportPlugin.sln
+├── TransportPlugin/ # 插件项目
├── NavisworksTransport.Setup/ # 安装项目
├── doc/design/2026/
│ └── MSI_Installation_Guide.md
@@ -529,7 +529,7 @@ NavisworksTransport/
**仅包含必要的文件:**
-- 自定义应用程序DLL(NavisworksTransportPlugin.dll)
+- 自定义应用程序DLL(TransportPlugin.dll)
- 第三方库DLL(如SQLite.NET.dll等)
- 配置文件(config.json等)
- 资源文件(图标、文档等)
@@ -590,7 +590,7 @@ NavisworksTransport/
NavisworksTransport.Setup/
├── 文件系统编辑器
│ ├── Application Folder/
-│ │ ├── Primary output from NavisworksTransportPlugin (Active)
+│ │ ├── Primary output from TransportPlugin (Active)
│ │ └── license.txt
└── 系统必备组件
├── Microsoft .NET Framework 4.8 (x86 and x64)
diff --git a/doc/design/Design_Plan.md b/doc/design/Design_Plan.md
index c6dc5cf..348a60a 100644
--- a/doc/design/Design_Plan.md
+++ b/doc/design/Design_Plan.md
@@ -203,22 +203,22 @@
4.2 构建与产物
- 解决方案:NavisworksTransport.sln;
-- 项目:NavisworksTransportPlugin.csproj;
-- 产物:NavisworksTransportPlugin.dll(bin/Debug 或 bin/Release)。
+- 项目:TransportPlugin.csproj;
+- 产物:TransportPlugin.dll(bin/Debug 或 bin/Release)。
4.3 安装与部署流程
- 自动安装(一键安装):
1) 识别 Navisworks 安装目录;
- 2) 将插件 DLL 与必要资源复制到 [Navisworks安装路径]\Plugins\NavisworksTransportPlugin\;
+ 2) 将插件 DLL 与必要资源复制到 [Navisworks安装路径]\Plugins\TransportPlugin\;
3) 注册菜单/配置(如需);
- 手动安装:
- 1) 复制 NavisworksTransportPlugin.dll 至上述目录;
+ 1) 复制 TransportPlugin.dll 至上述目录;
2) 重启 Navisworks,在“附加模块”中查看“物流路径规划”。
4.4 运行配置
-- 日志输出:%AppData%\Autodesk Navisworks Manage 2017\PluginsData\NavisworksTransportPlugin(按 QWEN 中 2026 路径作适配);
+- 日志输出:%AppData%\Autodesk Navisworks Manage 2017\PluginsData\TransportPlugin(按 QWEN 中 2026 路径作适配);
- 配置切换:
- 自动路径规划模式网格参数(cellSize、objectSize、safetyMargin、objectHeight);
- 2.5D/BoundingBox 模式选择(自动/强制选项)。
diff --git a/doc/design/logistics_path.xml b/doc/design/logistics_path.xml
index 295ef83..0e0c0ad 100644
--- a/doc/design/logistics_path.xml
+++ b/doc/design/logistics_path.xml
@@ -1,7 +1,7 @@
PRJ-12345
Main Hospital Construction Path for Delivery Truck #1 and Crane #2
diff --git a/doc/requirement/todo_features.md b/doc/requirement/todo_features.md
index b7cb2c5..ecb23c1 100644
--- a/doc/requirement/todo_features.md
+++ b/doc/requirement/todo_features.md
@@ -15,7 +15,7 @@
3. [ ] (优化)考虑是否给截图按碰撞记录组织成子文件夹
4. [ ] (优化)研究如何利用ClashDetective的多线程(支持打开多线程)
5. [x] (优化)给每个检测到的碰撞对象增加单独视角(45度,右上方)
-6. [ ] (优化)点击碰撞列表的碰撞详情时,要把运动物体移动到位,查看碰撞情况
+6. [x] (优化)点击碰撞列表的碰撞详情时,要把运动物体移动到位,查看碰撞情况
### [2026/2/6]
diff --git a/doc/working/2017/动画创建功能开发任务.md b/doc/working/2017/动画创建功能开发任务.md
index 55a2846..827768a 100644
--- a/doc/working/2017/动画创建功能开发任务.md
+++ b/doc/working/2017/动画创建功能开发任务.md
@@ -28,7 +28,7 @@ NavisworksTransport是一个Navisworks 2017插件项目,旨在实现物流路
2. **关键文件发现**:
- `PathAnimationManager.cs`:已实现但使用了不可用的API
- `NavigationMapWindow.cs`:已集成动画控制面板和事件处理
- - `NavisworksTransportPlugin.csproj`:已包含PathAnimationManager.cs
+ - `TransportPlugin.csproj`:已包含PathAnimationManager.cs
3. **API限制发现**:
- Navisworks 2017项目引用:`Autodesk.Navisworks.Api.dll`、`Autodesk.Navisworks.ComApi.dll`等
diff --git a/doc/working/2017/类别属性功能开发任务.md b/doc/working/2017/类别属性功能开发任务.md
index 5e32ef5..9a94ab9 100644
--- a/doc/working/2017/类别属性功能开发任务.md
+++ b/doc/working/2017/类别属性功能开发任务.md
@@ -302,7 +302,7 @@ cpropcates.SetUserDefined(0, "物流分类", "Logistics_InternalName", newcate);
* [2025-01-11 当前时间]
* 步骤:4. 更新项目引用
- * 修改:在NavisworksTransportPlugin.csproj中添加System.Drawing引用
+ * 修改:在TransportPlugin.csproj中添加System.Drawing引用
* 更改摘要:验证现有COM API引用完整性,添加缺失的System.Drawing引用以支持UI控件的Font、Color等类型,确保编译所需的所有引用都已包含
* 原因:执行计划步骤4
* 阻碍:无
diff --git a/doc/working/2017/路径构建功能开发任务.md b/doc/working/2017/路径构建功能开发任务.md
index 0ad4d90..1c4fd83 100644
--- a/doc/working/2017/路径构建功能开发任务.md
+++ b/doc/working/2017/路径构建功能开发任务.md
@@ -156,7 +156,7 @@ public class PathRoute
* [2024-12-22 01:32:15]
* 步骤:9. 添加路径验证/优化功能
- * 修改:PathPlanningManager.cs(添加路径验证和优化方法、无参构造函数、ShowPathPlanningInterface和AddRoute方法)、PathPlanningModels.cs(添加验证优化数据结构)、NavigationMapWindow.cs(添加验证优化UI)、NavisworksTransportPlugin.csproj(添加源文件引用)
+ * 修改:PathPlanningManager.cs(添加路径验证和优化方法、无参构造函数、ShowPathPlanningInterface和AddRoute方法)、PathPlanningModels.cs(添加验证优化数据结构)、NavigationMapWindow.cs(添加验证优化UI)、TransportPlugin.csproj(添加源文件引用)
* 更改摘要:成功实现路径验证和优化功能,包括基本结构验证、几何有效性验证、通道约束验证、碰撞检测、可达性验证,以及路径优化算法(移除重复点、路径平滑、角度优化、通道中心调整)。修复了MainPlugin.cs兼容性问题,确保项目能正确编译
* 原因:执行计划步骤 9(包含微小修正)
* 阻碍:无
diff --git a/doc/working/cleanup_summary.md b/doc/working/cleanup_summary.md
index d860470..36af9e4 100644
--- a/doc/working/cleanup_summary.md
+++ b/doc/working/cleanup_summary.md
@@ -76,7 +76,7 @@
### 最终编译结果
```
-NavisworksTransportPlugin -> bin\Debug\NavisworksTransportPlugin.dll
+TransportPlugin -> bin\Debug\TransportPlugin.dll
Build successful!
```
diff --git a/doc/working/json_import_implementation_summary_20251107.md b/doc/working/json_import_implementation_summary_20251107.md
index a765a22..0712fbd 100644
--- a/doc/working/json_import_implementation_summary_20251107.md
+++ b/doc/working/json_import_implementation_summary_20251107.md
@@ -69,7 +69,7 @@
**编译结果**: ✅ 成功
- 仅有警告,无错误
-- 生成的DLL: `bin/Debug/NavisworksTransportPlugin.dll`
+- 生成的DLL: `bin/Debug/TransportPlugin.dll`
---
diff --git a/doc/working/video_export_ffmpegcore_solution_20250929.md b/doc/working/video_export_ffmpegcore_solution_20250929.md
index cee1d47..6aa2ddf 100644
--- a/doc/working/video_export_ffmpegcore_solution_20250929.md
+++ b/doc/working/video_export_ffmpegcore_solution_20250929.md
@@ -268,7 +268,7 @@ private async void OnExportVideoButtonClick(object sender, RoutedEventArgs e)
### 文件分发清单
```
NavisworksTransport插件目录/
-├── NavisworksTransportPlugin.dll(主插件)
+├── TransportPlugin.dll(主插件)
├── FFMpegCore.dll(NuGet自动处理)
├── Instances.dll(依赖项)
├── System.Text.Json.dll(依赖项)
diff --git a/doc/working/第二阶段优化计划_20250814.md b/doc/working/第二阶段优化计划_20250814.md
index 6c26b79..6df2427 100644
--- a/doc/working/第二阶段优化计划_20250814.md
+++ b/doc/working/第二阶段优化计划_20250814.md
@@ -325,7 +325,7 @@ public class ChannelSlopeInfo
#### **编译验证** ✅
-- ✅ 项目编译成功:`NavisworksTransportPlugin.dll`
+- ✅ 项目编译成功:`TransportPlugin.dll`
- ✅ 新文件已添加到项目文件中
- ✅ 语法错误已修复
- ✅ 依赖关系正确配置
diff --git a/src/Commands/GenerateCollisionReportCommand.cs b/src/Commands/GenerateCollisionReportCommand.cs
index 94e5730..d7a8c3b 100644
--- a/src/Commands/GenerateCollisionReportCommand.cs
+++ b/src/Commands/GenerateCollisionReportCommand.cs
@@ -6,6 +6,8 @@ using System.Threading;
using System.Threading.Tasks;
using Autodesk.Navisworks.Api;
using Autodesk.Navisworks.Api.Clash;
+using NavisworksTransport.Core;
+using NavisworksTransport.Core.Animation;
using NavisworksTransport.Utils;
using NavisworksTransport.UI.WPF.Views;
@@ -278,6 +280,7 @@ namespace NavisworksTransport.Commands
UpdateProgress(95, "加载碰撞报告截图...");
// 加载多截图数据(从新的截图表)
+ bool loadedScreenshotsFromDatabase = false;
var pathDatabase = PathPlanningManager.Instance?.GetPathDatabase();
if (pathDatabase != null)
{
@@ -306,6 +309,7 @@ namespace NavisworksTransport.Commands
Description = r.Description,
SortOrder = r.SortOrder
}).ToList();
+ loadedScreenshotsFromDatabase = true;
LogManager.Info($"从数据库加载了 {result.Screenshots.Count} 张截图 (ResultId={testRecord.Id})");
}
@@ -331,17 +335,25 @@ namespace NavisworksTransport.Commands
}
}
- // 如果没有加载到任何截图,生成一张默认截图
+ // 检查并创建路径子目录(用于存放该路径的所有截图)
+ string pathDir = System.IO.Path.Combine(PathHelper.GetScreenshotDirectory(),
+ string.Format("{0}_{1}", result.RouteId.Substring(0, 8), result.PathName ?? "collision"));
+ PathHelper.EnsureDirectoryExists(pathDir);
+
+ // 先生成默认截图(整条路径的概览)
if (result.Screenshots == null || result.Screenshots.Count == 0)
{
try
{
- string screenshotPath = PathHelper.GenerateSceneScreenshot(
- result.PathName ?? "collision",
+ UpdateProgress(92, "生成默认路径截图...");
+
+ string screenshotPath = PathHelper.GenerateSceneScreenshotToDirectory(
+ pathDir,
+ "path",
1920,
1080,
System.Drawing.Imaging.ImageFormat.Jpeg,
- "collision"
+ "overview"
);
if (screenshotPath != null)
@@ -354,17 +366,18 @@ namespace NavisworksTransport.Commands
Format = "JPG",
Width = 1920,
Height = 1080,
- CaptureTime = DateTime.Now
+ CaptureTime = DateTime.Now,
+ Description = "路径概览",
+ SortOrder = 0
}
};
- LogManager.Info($"自动生成默认截图: {screenshotPath}");
+ LogManager.Info(string.Format("生成默认截图: {0}", screenshotPath));
- // 保存截图到数据库(新表支持多截图)
+ // 保存截图到数据库
if (pathDatabase != null && result.ResultId > 0)
{
try
{
- // 保存到新表 CollisionReportScreenshots
int screenshotId = pathDatabase.SaveCollisionReportScreenshot(
result.ResultId,
screenshotPath,
@@ -372,20 +385,106 @@ namespace NavisworksTransport.Commands
1920,
1080,
0,
- "默认场景截图"
+ "路径概览"
);
- LogManager.Info($"默认截图已保存到数据库: ScreenshotId={screenshotId}, ResultId={result.ResultId}, Path={screenshotPath}");
+ LogManager.Info(string.Format("默认截图已保存到数据库: ScreenshotId={0}", screenshotId));
}
catch (Exception dbEx)
{
- LogManager.Error($"保存默认截图到数据库失败: {dbEx.Message}");
+ LogManager.Error(string.Format("保存默认截图到数据库失败: {0}", dbEx.Message));
}
}
}
}
catch (Exception ex)
{
- LogManager.Error($"自动生成碰撞场景截图失败: {ex.Message}");
+ LogManager.Error(string.Format("生成默认截图失败: {0}", ex.Message));
+ }
+ }
+
+ // 再生成每个碰撞对的单独截图(需要移动物体到碰撞位置)
+ // 只有未从数据库加载截图时才生成
+ if (!loadedScreenshotsFromDatabase && collisionData.AllCollisions?.Count > 0)
+ {
+ try
+ {
+ UpdateProgress(94, string.Format("正在为 {0} 个碰撞对生成视角截图...", collisionData.AllCollisions.Count));
+
+ int sortOrder = result.Screenshots?.Count ?? 0;
+ int successCount = 0;
+
+ // 保存动画物体原始状态(用于截图后恢复)
+ ModelItem animatedObject = null;
+ ModelItemTransformHelper.ObjectStateSnapshot savedObjectState = null;
+
+ // 找到第一个有位置信息的碰撞来获取动画物体
+ foreach (var c in collisionData.AllCollisions)
+ {
+ if (c.Item1 != null && c.HasPositionInfo)
+ {
+ animatedObject = c.Item1;
+ savedObjectState = CollisionSceneHelper.SaveAnimatedObjectState(animatedObject);
+ break;
+ }
+ }
+
+ for (int i = 0; i < collisionData.AllCollisions.Count; i++)
+ {
+ var collision = collisionData.AllCollisions[i];
+ try
+ {
+ // 使用通用方法移动物体到碰撞位置并聚焦
+ CollisionSceneHelper.MoveToCollisionAndFocus(collision, animatedObject, waitForViewUpdate: true);
+
+ // 生成截图
+ string screenshotPath = PathHelper.GenerateSceneScreenshotToDirectory(
+ pathDir, "collision", 1920, 1080,
+ System.Drawing.Imaging.ImageFormat.Jpeg, string.Format("collision_{0:D3}", i + 1));
+
+ if (screenshotPath != null)
+ {
+ string item1Name = collision.Item1 != null ? collision.Item1.DisplayName : "物体1";
+ string item2Name = collision.Item2 != null ? collision.Item2.DisplayName : "物体2";
+ string description = string.Format("碰撞对 {0}/{1}: {2} vs {3}", i + 1, collisionData.AllCollisions.Count, item1Name, item2Name);
+
+ var screenshot = new CollisionReportScreenshot
+ {
+ FilePath = screenshotPath,
+ Format = "JPG",
+ Width = 1920,
+ Height = 1080,
+ CaptureTime = DateTime.Now,
+ Description = description,
+ SortOrder = sortOrder++
+ };
+ result.Screenshots.Add(screenshot);
+
+ // 保存到数据库
+ if (pathDatabase != null && result.ResultId > 0)
+ {
+ pathDatabase.SaveCollisionReportScreenshot(result.ResultId, screenshotPath, "JPG",
+ 1920, 1080, screenshot.SortOrder, description);
+ }
+
+ successCount++;
+ }
+
+ Thread.Sleep(50); // 短暂延迟
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error(string.Format("生成碰撞对 {0} 截图失败: {1}", i + 1, ex.Message));
+ }
+ }
+
+ // 恢复动画物体到原始状态
+ CollisionSceneHelper.RestoreAnimatedObjectState(animatedObject, savedObjectState);
+
+ LogManager.Info(string.Format("已生成 {0}/{1} 个碰撞对视角截图", successCount, collisionData.AllCollisions.Count));
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error(string.Format("生成碰撞对视角截图失败: {0}", ex.Message));
}
}
diff --git a/src/Core/Config/ConfigManager.cs b/src/Core/Config/ConfigManager.cs
index d5a3df5..02b8e6f 100644
--- a/src/Core/Config/ConfigManager.cs
+++ b/src/Core/Config/ConfigManager.cs
@@ -107,7 +107,7 @@ namespace NavisworksTransport.Core.Config
"Autodesk",
"Navisworks Manage 2026",
"plugins",
- "NavisworksTransportPlugin",
+ "TransportPlugin",
"config.toml"
);
}
diff --git a/src/UI/WPF/ViewModels/CollisionReportViewModel.cs b/src/UI/WPF/ViewModels/CollisionReportViewModel.cs
index 5c94831..84b171b 100644
--- a/src/UI/WPF/ViewModels/CollisionReportViewModel.cs
+++ b/src/UI/WPF/ViewModels/CollisionReportViewModel.cs
@@ -1244,52 +1244,18 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
var collisionData = collisionItem.CollisionData;
- // 获取被撞对象(Item2是运动物体碰撞的静态对象)
- var hitObject = collisionData.Item2;
- if (hitObject == null)
- {
- // 如果没有Item2,使用Item1
- hitObject = collisionData.Item1;
- }
-
- if (hitObject != null)
- {
- // 清除之前的高亮
- ModelHighlightHelper.ClearAllHighlights();
-
- // 高亮被撞对象(使用碰撞检测结果专用红色)
- ModelHighlightHelper.HighlightItems(ModelHighlightHelper.ClashDetectiveResultsCategory, new[] { hitObject });
-
- // 聚焦到被撞对象
- ViewpointHelper.FocusOnModelItem(hitObject, viewAngleDegrees: 60.0, targetViewRatio: 0.25);
-
- LogManager.Info($"聚焦到被撞对象: {collisionItem.Title}");
- }
-
- // 还原运动物体到碰撞时的位置和朝向
- LogManager.Debug($"[碰撞详情点击] Item1={collisionData.Item1?.DisplayName}, HasPositionInfo={collisionData.HasPositionInfo}, Item1Position={collisionData.Item1Position}");
+ // 首次查看碰撞时保存运动物体状态
if (collisionData.Item1 != null && collisionData.HasPositionInfo && collisionData.Item1Position != null)
{
- // 首次查看碰撞时保存运动物体状态
if (_savedAnimatedObjectState == null || _currentAnimatedObject != collisionData.Item1)
{
_currentAnimatedObject = collisionData.Item1;
- // 🔥 关键:从 PathAnimationManager 获取当前实际朝向
- // 因为 Transform 返回的是CAD原始朝向,不是当前实际朝向
- var pam = PathAnimationManager.GetInstance();
- var currentYaw = pam.CurrentYaw;
- var transformYaw = ModelItemTransformHelper.GetYawFromTransform(collisionData.Item1.Transform);
- LogManager.Debug($"[碰撞查看调试] PathAnimationManager.CurrentYaw={currentYaw * 180 / Math.PI:F2}°, Transform.Yaw={transformYaw * 180 / Math.PI:F2}°");
- _savedAnimatedObjectState = ModelItemTransformHelper.SaveObjectState(collisionData.Item1, currentYaw);
- LogManager.Info($"[碰撞查看] 已保存运动物体原始状态: pos=({_savedAnimatedObjectState.Position.X:F2},{_savedAnimatedObjectState.Position.Y:F2},{_savedAnimatedObjectState.Position.Z:F2}), yaw={currentYaw * 180 / Math.PI:F2}°");
+ _savedAnimatedObjectState = CollisionSceneHelper.SaveAnimatedObjectState(collisionData.Item1);
}
-
- RestoreAnimatedObjectToCollisionPosition(collisionData);
- }
- else
- {
- LogManager.Warning($"[碰撞详情点击] 无法还原运动物体位置: Item1={(collisionData.Item1 != null ? "有" : "无")}, HasPositionInfo={collisionData.HasPositionInfo}, Item1Position={(collisionData.Item1Position != null ? "有" : "无")}");
}
+
+ // 使用通用方法移动并聚焦到碰撞位置
+ CollisionSceneHelper.MoveToCollisionAndFocus(collisionData, _currentAnimatedObject, waitForViewUpdate: false);
}
catch (Exception ex)
{
@@ -1297,65 +1263,16 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
}
- ///
- /// 将运动物体还原到碰撞时的位置和朝向
- /// 使用ModelItemTransformHelper.MoveItemToPositionAndYaw从CAD原始状态精确定位
- ///
- private void RestoreAnimatedObjectToCollisionPosition(CollisionResult collisionData)
- {
- try
- {
- var animatedObject = collisionData.Item1;
- var targetPosition = collisionData.Item1Position;
- var targetYaw = collisionData.Item1YawRadians;
-
- if (animatedObject == null || targetPosition == null)
- {
- LogManager.Warning("[还原碰撞位置] 运动物体或位置信息为空");
- return;
- }
-
- // 计算目标底面位置(Item1Position存储的是包围盒中心,需要转换为底面)
- var currentBounds = animatedObject.BoundingBox();
- double halfHeight = (currentBounds.Max.Z - currentBounds.Min.Z) / 2.0;
- var targetGroundPosition = new Point3D(
- targetPosition.X,
- targetPosition.Y,
- targetPosition.Z - halfHeight
- );
-
- // 使用工具方法从CAD原始状态移动到目标位置
- ModelItemTransformHelper.MoveItemToPositionAndYaw(animatedObject, targetGroundPosition, targetYaw);
-
- LogManager.Info($"[还原碰撞位置] 运动物体已移动到碰撞位置: ({targetGroundPosition.X:F2}, {targetGroundPosition.Y:F2}, {targetGroundPosition.Z:F2}), 朝向: {targetYaw * 180 / Math.PI:F2}°");
- }
- catch (Exception ex)
- {
- LogManager.Error($"[还原碰撞位置] 失败: {ex.Message}", ex);
- }
- }
-
///
/// 恢复运动物体到原始状态(查看碰撞前保存的状态)
///
public void RestoreAnimatedObjectToOriginalState()
{
- try
- {
- if (_currentAnimatedObject != null && _savedAnimatedObjectState != null)
- {
- ModelItemTransformHelper.RestoreObjectState(_currentAnimatedObject, _savedAnimatedObjectState);
- LogManager.Info("[碰撞查看] 运动物体已恢复到原始状态");
-
- // 清除保存的状态
- _savedAnimatedObjectState = null;
- _currentAnimatedObject = null;
- }
- }
- catch (Exception ex)
- {
- LogManager.Error($"[恢复运动物体状态] 失败: {ex.Message}", ex);
- }
+ CollisionSceneHelper.RestoreAnimatedObjectState(_currentAnimatedObject, _savedAnimatedObjectState);
+
+ // 清除保存的状态
+ _savedAnimatedObjectState = null;
+ _currentAnimatedObject = null;
}
#endregion
diff --git a/src/Utils/CollisionSceneHelper.cs b/src/Utils/CollisionSceneHelper.cs
new file mode 100644
index 0000000..1178eaa
--- /dev/null
+++ b/src/Utils/CollisionSceneHelper.cs
@@ -0,0 +1,124 @@
+using System;
+using Autodesk.Navisworks.Api;
+using NavisworksTransport.Core;
+using NavisworksTransport.Core.Animation;
+
+namespace NavisworksTransport.Utils
+{
+ ///
+ /// 碰撞场景辅助类
+ /// 提供碰撞场景还原和截图的通用功能
+ ///
+ public static class CollisionSceneHelper
+ {
+ ///
+ /// 将动画物体移动到碰撞位置并聚焦到碰撞场景
+ ///
+ /// 碰撞结果
+ /// 动画物体(运动物体)
+ /// 是否等待视图更新
+ public static void MoveToCollisionAndFocus(CollisionResult collision, ModelItem animatedObject, bool waitForViewUpdate = true)
+ {
+ if (collision == null) return;
+
+ try
+ {
+ // 获取被撞对象(Item2是运动物体碰撞的静态对象)
+ var hitObject = collision.Item2 ?? collision.Item1;
+
+ if (hitObject != null)
+ {
+ // 清除之前的高亮
+ ModelHighlightHelper.ClearAllHighlights();
+
+ // 高亮被撞对象(使用碰撞检测结果专用红色)
+ ModelHighlightHelper.HighlightItems(ModelHighlightHelper.ClashDetectiveResultsCategory, new[] { hitObject });
+
+ // 聚焦到被撞对象
+ ViewpointHelper.FocusOnModelItem(hitObject, viewAngleDegrees: 60.0, targetViewRatio: 0.25);
+
+ LogManager.Info(string.Format("聚焦到被撞对象: {0}", hitObject.DisplayName));
+ }
+
+ // 移动动画物体到碰撞位置
+ if (animatedObject != null && collision.Item1 == animatedObject && collision.HasPositionInfo && collision.Item1Position != null)
+ {
+ // 计算目标底面位置(Item1Position存储的是包围盒中心,需要转换为底面)
+ var bounds = animatedObject.BoundingBox();
+ double halfHeight = (bounds.Max.Z - bounds.Min.Z) / 2.0;
+ var targetGroundPosition = new Point3D(
+ collision.Item1Position.X,
+ collision.Item1Position.Y,
+ collision.Item1Position.Z - halfHeight
+ );
+
+ // 使用工具方法从CAD原始状态移动到目标位置
+ ModelItemTransformHelper.MoveItemToPositionAndYaw(animatedObject, targetGroundPosition, collision.Item1YawRadians);
+
+ LogManager.Info(string.Format("运动物体已移动到碰撞位置: ({0:F2}, {1:F2}, {2:F2}), 朝向: {3:F2}°",
+ targetGroundPosition.X, targetGroundPosition.Y, targetGroundPosition.Z,
+ collision.Item1YawRadians * 180 / Math.PI));
+ }
+
+ // 等待视图更新
+ if (waitForViewUpdate)
+ {
+ ViewpointHelper.WaitForViewUpdate();
+ }
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error(string.Format("移动并聚焦到碰撞位置失败: {0}", ex.Message), ex);
+ }
+ }
+
+ ///
+ /// 保存动画物体当前状态
+ ///
+ /// 动画物体
+ /// 状态快照
+ public static ModelItemTransformHelper.ObjectStateSnapshot SaveAnimatedObjectState(ModelItem animatedObject)
+ {
+ if (animatedObject == null) return null;
+
+ try
+ {
+ // 从PathAnimationManager获取当前实际朝向
+ var pam = PathAnimationManager.GetInstance();
+ var currentYaw = pam.CurrentYaw;
+ var state = ModelItemTransformHelper.SaveObjectState(animatedObject, currentYaw);
+
+ LogManager.Info(string.Format("已保存动画物体状态: {0}, 位置=({1:F2},{2:F2},{3:F2}), 朝向={4:F2}°",
+ animatedObject.DisplayName, state.Position.X, state.Position.Y, state.Position.Z,
+ currentYaw * 180 / Math.PI));
+
+ return state;
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error(string.Format("保存动画物体状态失败: {0}", ex.Message), ex);
+ return null;
+ }
+ }
+
+ ///
+ /// 恢复动画物体到保存的状态
+ ///
+ /// 动画物体
+ /// 状态快照
+ public static void RestoreAnimatedObjectState(ModelItem animatedObject, ModelItemTransformHelper.ObjectStateSnapshot state)
+ {
+ if (animatedObject == null || state == null) return;
+
+ try
+ {
+ ModelItemTransformHelper.RestoreObjectState(animatedObject, state);
+ LogManager.Info(string.Format("动画物体已恢复到原始状态: {0}", animatedObject.DisplayName));
+ }
+ catch (Exception ex)
+ {
+ LogManager.Error(string.Format("恢复动画物体状态失败: {0}", ex.Message), ex);
+ }
+ }
+ }
+}
diff --git a/src/Utils/LogManager.cs b/src/Utils/LogManager.cs
index 865f0ab..ef74992 100644
--- a/src/Utils/LogManager.cs
+++ b/src/Utils/LogManager.cs
@@ -22,7 +22,7 @@ namespace NavisworksTransport
{
private static readonly string _logFilePath = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData),
- "Autodesk", "Navisworks Manage 2026", "plugins", "NavisworksTransportPlugin", "logs", "debug.log");
+ "Autodesk", "Navisworks Manage 2026", "plugins", "TransportPlugin", "logs", "debug.log");
private static readonly object _lockObject = new object();
diff --git a/src/Utils/PathHelper.cs b/src/Utils/PathHelper.cs
index 2ea2007..8f0c53e 100644
--- a/src/Utils/PathHelper.cs
+++ b/src/Utils/PathHelper.cs
@@ -21,7 +21,7 @@ namespace NavisworksTransport.Utils
"Autodesk",
"Navisworks Manage 2026",
"plugins",
- "NavisworksTransportPlugin"
+ "TransportPlugin"
);
}
@@ -147,20 +147,42 @@ namespace NavisworksTransport.Utils
/// 文件名前缀
/// 截图文件路径,失败返回null
public static string GenerateSceneScreenshot(string sceneName, int width, int height, ImageFormat format, string prefix = "scene")
+ {
+ return GenerateSceneScreenshotInternal(GetScreenshotDirectory(), sceneName, width, height, format, prefix);
+ }
+
+ ///
+ /// 生成场景截图到指定目录
+ ///
+ /// 输出目录
+ /// 场景名称
+ /// 图像宽度
+ /// 图像高度
+ /// 图像格式
+ /// 文件名前缀
+ /// 截图文件路径,失败返回null
+ public static string GenerateSceneScreenshotToDirectory(string outputDirectory, string sceneName, int width, int height, ImageFormat format, string prefix = "scene")
+ {
+ return GenerateSceneScreenshotInternal(outputDirectory, sceneName, width, height, format, prefix);
+ }
+
+ ///
+ /// 生成场景截图内部实现
+ ///
+ private static string GenerateSceneScreenshotInternal(string outputDirectory, string sceneName, int width, int height, ImageFormat format, string prefix)
{
try
{
- LogManager.Info($"开始生成场景截图: {prefix}_{sceneName}, 尺寸={width}x{height}, 格式={ImageFormatToExtension(format)}");
+ LogManager.Info(string.Format("开始生成场景截图: {0}_{1}, 尺寸={2}x{3}, 目录={4}", prefix, sceneName, width, height, outputDirectory));
// 1. 确保截图目录存在
- string screenshotDir = GetScreenshotDirectory();
- EnsureDirectoryExists(screenshotDir);
+ EnsureDirectoryExists(outputDirectory);
// 2. 生成文件名
string extension = ImageFormatToExtension(format);
string sanitizedName = SanitizeFileName(sceneName);
- string filename = GenerateTimestampedFileName($"{prefix}_{sanitizedName}", extension);
- string screenshotPath = Path.Combine(screenshotDir, filename);
+ string filename = GenerateTimestampedFileName(string.Format("{0}_{1}", prefix, sanitizedName), extension);
+ string screenshotPath = Path.Combine(outputDirectory, filename);
// 3. 调用截图生成器(复用 NavigationMapGenerator)
var generator = new Core.NavigationMapGenerator();
@@ -174,12 +196,12 @@ namespace NavisworksTransport.Utils
// 4. 保存截图
generator.SaveNavigationMapImage(bitmap, screenshotPath, format);
- LogManager.Info($"场景截图已生成: {screenshotPath}");
+ LogManager.Info(string.Format("场景截图已生成: {0}", screenshotPath));
return screenshotPath;
}
catch (Exception ex)
{
- LogManager.Error($"生成场景截图失败: {ex.Message}", ex);
+ LogManager.Error(string.Format("生成场景截图失败: {0}", ex.Message), ex);
return null;
}
}