# 坐标系统一架构实施清单

## 1. 文档目的

本文档基于
[coordinate-system-canonical-space-design.md](/C:/Users/Tellme/apps/NavisworksTransport-rail-mount-modes/doc/design/2026/coordinate-system-canonical-space-design.md)
中的方案，拆解出一份可执行的实施清单。

目标不是一次性全项目重构，而是：

- 先建立“外部坐标 -> 内部统一坐标 -> 业务基准坐标”的边界
- 再优先改造当前最重要的非自动路径规划功能
- 逐步把历史 `Z-up` 假设收口

## 2. 总体原则

### 2.1 本轮范围

当前优先范围：

- 终端安装仿真
- Rail 三维姿态
- 动画播放
- 碰撞检测与碰撞恢复
- 辅助线、通行空间、碰撞点相关渲染

当前明确**不优先**处理：

- 自动路径规划
- 高度检测
- 坡度分析
- 旧网格高度/通道高度相关算法

### 2.2 内部统一坐标

当前实施目标固定为：

- **内部统一坐标 = Canonical Space = Z-up**

### 2.3 外部坐标定义

当前实施中，统一定义：

- **Navisworks API 返回的世界坐标 = 外部坐标**

即：

- `Point3D`
- `Vector3D`
- `BoundingBox3D`
- `Transform3D`
- `Document.UpVector`
- `ModelItem.BoundingBox()`
- 鼠标点击拾取点

都先视为外部输入。

## 3. 里程碑划分

### M1. 建立坐标边界层

目标：

- 引入统一的宿主坐标适配器
- 不再在业务代码里直接解释 Navisworks 坐标

### M2. 接入终端安装仿真

目标：

- 终端安装仿真不再直接依赖世界原点和世界 `Z`
- 球心与项目 up 都走统一边界层/业务基准层

### M3. 接入 Rail 三维姿态

目标：

- Rail 姿态和动画只认内部统一坐标
- 不再在姿态 helper 中写死 `(0,0,1)`

### M4. 接入碰撞恢复和可视化

目标：

- 碰撞报告、碰撞点恢复、自动截图、辅助线渲染统一使用同一套内部语义

## 4. 任务清单

## 4.1 M1 建立坐标边界层

### Task 1. 新增 `HostCoordinateAdapter`

目标：

- 建立 Navisworks 外部坐标与内部统一坐标之间的唯一适配入口

建议职责：

- `ToCanonicalPoint(...)`
- `ToCanonicalVector(...)`
- `ToCanonicalBounds(...)`
- `ToCanonicalTransform(...)`
- `FromCanonicalPoint(...)`
- `FromCanonicalVector(...)`
- `FromCanonicalBounds(...)`
- `FromCanonicalTransform(...)`

建议要求：

- 统一使用完整三维变换语义
- 不再停留在 `GetElevation()/GetHorizontalCoords()` 这种偏二维接口
- 点、向量、包围盒、旋转、变换都必须有明确变换规则
- 坐标定义中必须显式暴露：
  - `UpAxis`
  - `ElevationAxis`
  - `HorizontalPlane`

验收：

- 对同一组 Navisworks 输入，适配结果在 Y-up 和 Z-up 项目中都能稳定输出 Canonical Space 数据

### Task 2. 新增 `ProjectReferenceFrame`

目标：

- 承载业务基准点，不再把业务基准混进坐标系层

建议职责：

- `SphereCenterInCanonical`
- `ProjectUpInCanonical`
- 终端安装参考方向
- 轨道参考面

验收：

- 程序内不再把世界原点直接当球心使用

### Task 3. 约束边界：禁止业务代码直接解释宿主坐标

目标：

- 收口“谁可以直接碰 Navisworks 坐标”

需要收口的入口：

- 鼠标点击取点
- `ModelItem.BoundingBox()`
- `Transform3D`
- `Document.UpVector`
- 3D 渲染输入
- 动画对象位姿输出

验收：

- 新功能主链路中，业务代码不再直接从 `BoundingBox().Center` 开始做业务推导

## 4.2 M2 接入终端安装仿真

### Task 4. 改造 `PathEditingViewModel`

文件：

- [PathEditingViewModel.cs](/C:/Users/Tellme/apps/NavisworksTransport-rail-mount-modes/src/UI/WPF/ViewModels/PathEditingViewModel.cs)

目标：

- 终端安装辅助线全部改为基于 Canonical Space + ProjectReferenceFrame

重点修改点：

- `BuildAssemblyReferenceLine()`
- `GetAssemblyTerminalAnchorPoint()`
- 与辅助线、终点锚点、参考方向相关的计算

必须消除：

- `Vector3D direction = new Vector3D(centerPoint.X, centerPoint.Y, centerPoint.Z);`
- 直接把世界原点当球心

验收：

- Y-up 项目中，若球心配置正确，辅助线方向与业务预期一致
- Z-up 项目中，行为保持不退化

### Task 5. 明确 UI 和日志的坐标语义

目标：

- 终端安装相关 UI、日志输出不混淆内部坐标和外部坐标

建议：

- 内部计算使用 Canonical
- 对用户显示时，明确是否转回 Navisworks 外部坐标

验收：

- 日志中坐标语义一致，不再出现“内部算的是一种，打印的是另一种”

## 4.3 M3 接入 Rail 三维姿态

### Task 6. 改造 `RailPathPoseHelper`

文件：

- [RailPathPoseHelper.cs](/C:/Users/Tellme/apps/NavisworksTransport-rail-mount-modes/src/Utils/RailPathPoseHelper.cs)

目标：

- Rail 姿态计算统一基于 Canonical Space

必须消除：

- `new Vector3D(0, 0, 1)`
- `worldUp = new Vector3D(0, 0, 1)`

替换方式：

- 改用适配层提供的 Canonical up
- 或由 `ProjectReferenceFrame` 提供项目参考 up

验收：

- Y-up 项目与 Z-up 项目中，Rail 参考方向一致、俯仰/侧倾逻辑一致

### Task 7. 清理 Rail 动画输入边界

涉及文件：

- [PathAnimationManager.cs](/C:/Users/Tellme/apps/NavisworksTransport-rail-mount-modes/src/Core/Animation/PathAnimationManager.cs)
- [VirtualObjectManager.cs](/C:/Users/Tellme/apps/NavisworksTransport-rail-mount-modes/src/Core/VirtualObjectManager.cs)
- [ModelItemTransformHelper.cs](/C:/Users/Tellme/apps/NavisworksTransport-rail-mount-modes/src/Utils/ModelItemTransformHelper.cs)

目标：

- 动画内部只消费 Canonical 姿态
- 输出到 Navisworks 时再做反向转换

验收：

- Rail 虚拟物体与真实模型在 Y-up / Z-up 项目中的姿态语义一致
- 真实物体起点贴合和动画第一帧使用同一份固定物理尺寸语义
- 不再允许从“已旋转后的当前 AABB”重新推导 Rail 物体高度
- Rail 动画不再直接在业务层手写 `forward/up/offset`，而是复用基础工具
- `ClashDetective` 三维候选验证必须直接复用 `PathAnimationManager` 主链路恢复，不允许先 `ResetPermanentTransform` 再复用 `PAM`

### Task 7.2 新增 `RailLocalFrame`

目标：

- 将 `Rail` 局部坐标系正式提升为基础框架对象

最低要求：

- `Forward`
- `Normal`
- `Lateral`

实施要求：

- 先在纯数学层构建并测试
- 再由 `RailPathPoseHelper`、动画、通行空间复用

验收：

- 不再由业务代码自己拼切向/法向/侧向
- `Rail` 的姿态、法向偏移、通行空间统一使用同一套局部坐标系

### Task 7.3 新增“参考点 -> 跟踪中心点”偏移解析器

目标：

- 将路径参考点到动画跟踪中心点的偏移，从业务代码中抽离成基础工具

实施要求：

- 先以几何中心为统一动画跟踪点
- 地面/吊装路径使用宿主 up 语义
- Rail 路径使用 `RailLocalFrame.Normal`
- 先补单测再接业务

验收：

- `PathAnimationManager` 不再直接散落手写半高偏移
- `AnimatedObjectTrackedPosition` 明确表示动画跟踪中心点

### Task 7.1 明确模型局部轴约定

目标：

- 将“模型本地哪个轴代表 forward/up”从隐含假设提升为显式定义

需要覆盖：

- 虚拟物体资源
- 终端安装辅助杆资源
- 真实模型在 `Y-up` / `Z-up` 项目中的默认局部轴约定

最低要求：

- 至少明确 `LocalForwardAxis`
- 至少明确 `LocalUpAxis`

验收：

- 不再出现“路径方向和通行空间都正确，但真实模型仍按错误本地 up 站立”的现象
- `Y-up` 真实模型与 `Z-up` 真实模型都能通过显式局部轴约定接入 Rail 姿态链路

## 4.4 M4 接入碰撞恢复和渲染

### Task 8. 改造碰撞恢复链路

涉及文件：

- [CollisionSceneHelper.cs](/C:/Users/Tellme/apps/NavisworksTransport-rail-mount-modes/src/Utils/CollisionSceneHelper.cs)
- [GenerateCollisionReportCommand.cs](/C:/Users/Tellme/apps/NavisworksTransport-rail-mount-modes/src/Commands/GenerateCollisionReportCommand.cs)
- [ClashDetectiveIntegration.cs](/C:/Users/Tellme/apps/NavisworksTransport-rail-mount-modes/src/Core/Collision/ClashDetectiveIntegration.cs)

目标：

- 碰撞点恢复、报告截图、碰撞点回看全部使用统一的内部姿态语义

验收：

- Rail 碰撞报告恢复位置和动画实际姿态一致
- 二维路径不被三维逻辑污染

实施提示：

- 对真实物体，碰撞恢复和动画播放必须共用同一份固定物理尺寸语义
- 不允许恢复链路偷偷退回“重新读取当前 AABB 再算高度/底面”

### Task 9. 改造渲染层

文件：

- [PathPointRenderPlugin.cs](/C:/Users/Tellme/apps/NavisworksTransport-rail-mount-modes/src/Core/PathPointRenderPlugin.cs)
- [AssemblyReferencePathManager.cs](/C:/Users/Tellme/apps/NavisworksTransport-rail-mount-modes/src/Core/AssemblyReferencePathManager.cs)

目标：

- 辅助线、通行空间、点标记、碰撞点渲染，不再直接写死 `Normal = (0,0,1)`
- 渲染层不仅要改“中心点/偏移量”，还要统一渲染几何的局部轴语义

验收：

- Y-up 项目中，渲染法向和可视化朝向不再依赖世界 Z
- Y-up 项目中，默认通行空间和 `SP` 模式通行空间的高度轴与宿主 up 一致
- 不再出现“中心点位置正确，但长方体/杆体本体仍按 Z-up 构造”的现象

实施提示：

- 长方体、圆柱体、辅助杆这类几何渲染，必须同时检查：
  - 中心点是否正确
  - `right/up/height` 局部轴是否正确
  - `Normal` 是否仍偷用世界 `Z`
- 不能只修改 `ApplyVerticalOffset(...)` 或中心点偏移，而保留旧的 `XY + Z` 轴构造公式

### Task 9.1 通行空间与物体贴合语义统一

涉及文件：

- [AnimationControlViewModel.cs](/C:/Users/Tellme/apps/NavisworksTransport-rail-mount-modes/src/UI/WPF/ViewModels/AnimationControlViewModel.cs)
- [PathAnimationManager.cs](/C:/Users/Tellme/apps/NavisworksTransport-rail-mount-modes/src/Core/Animation/PathAnimationManager.cs)

目标：

- 通行空间显示、起点贴合、动画帧贴合使用统一尺寸语义
- Rail 轨上/轨下模式下，贴合面与留缝面保持一致

经验约束：

- `轨下安装`：顶面贴路径，底面留单侧间隙
- `轨上安装`：底面贴路径，顶面留单侧间隙
- 真实物体尺寸必须在选择物体时固定下来，并传入动画管理器

验收：

- 起点贴合正确后，动画第一帧不再出现固定间隙
- 通行空间与真实物体的贴合面语义一致

## 5. 已知问题与注意事项

### 5.1 当前不应优先展开的模块

以下模块虽然也存在坐标系写死问题，但暂不作为本轮主线：

- [ChannelHeightDetector.cs](/C:/Users/Tellme/apps/NavisworksTransport-rail-mount-modes/src/PathPlanning/ChannelHeightDetector.cs)
- [SlopeAnalyzer.cs](/C:/Users/Tellme/apps/NavisworksTransport-rail-mount-modes/src/PathPlanning/SlopeAnalyzer.cs)
- [OptimizedHeightCalculator.cs](/C:/Users/Tellme/apps/NavisworksTransport-rail-mount-modes/src/PathPlanning/OptimizedHeightCalculator.cs)

原因：

- 它们主要服务于自动路径规划
- 当前项目主线优先级不在这里

### 5.2 不能依赖 fallback 掩盖问题

实施过程中禁止：

- 三维路径恢复失败时偷偷退回 `yaw`
- 外部坐标转换失败时偷偷按世界 `Z` 继续算
- 业务基准点缺失时默认球心为 `(0,0,0)`

必须让错误显式暴露。

### 5.3 不能使用不完整构建产物部署 WPF 插件

实施过程中必须区分：

- 单元测试所需的程序集产物
- 可用于 Navisworks 运行的完整 WPF 插件产物

对于本项目：

- 仅有 `TransportPlugin.dll` 被复制成功，不代表插件可用
- 还必须确保 `TransportPlugin.g.resources` 中包含完整的主视图 `.baml`

最低要求：

- 主项目构建成功后再部署
- 如遇异常，应检查关键资源是否存在：
  - `LogisticsControlPanel.baml`
  - `PathEditingView.baml`
  - `AnimationControlView.baml`
  - `LayerManagementView.baml`

否则可能出现：

- 插件布局恢复失败
- 手工打开插件窗口即崩溃

## 6. 当前实施优先顺序

建议实际推进顺序如下：

1. `HostCoordinateAdapter`
2. `ProjectReferenceFrame`
3. `PathEditingViewModel`
4. `RailPathPoseHelper`
5. `PathAnimationManager`
6. `CollisionSceneHelper`
7. `PathPointRenderPlugin`

## 7. 完成判定

当以下条件同时满足时，可认为本轮非自动路径规划坐标系统一改造达到阶段目标：

- 终端安装仿真在 Y-up / Z-up 项目中语义一致
- Rail 三维姿态在 Y-up / Z-up 项目中语义一致
- 动画播放与碰撞恢复姿态一致
- 碰撞报告截图与实际动画姿态一致
- 主链路业务代码中不再直接写死世界原点和世界 `Z`

## 8. 备注

本清单服务于“先稳定非自动路径规划主线”的目标，不代表自动路径规划相关模块不重要。

后续如要继续推进全项目坐标系统一，应单独启动自动路径规划相关的第二阶段清理计划。
