# 当前工程状态

更新时间：2026-04-01

## 1. 当前稳定状态

- `Rail` 路径主链路已稳定：
  - `ZUp` 模型下，轨上/轨下路径的真实物体与虚拟物体起点、动画、终点贴合正确。
  - `YUp` 模型下，终端安装仿真、`Rail` 姿态、真实物体与虚拟物体通行空间、起点与动画主链路已基本跑通。
  - `Rail` “调整角度”窗口中的“平移”模式当前已重新收稳：
    - 以终点箱体当前原始位姿为真值；
    - 记录终点原位相对路径终点参考点的固定残差；
    - 把这份残差整体搬运到路径起点；
    - 动画全程保持终点原始姿态；
    - 动画结束时应精确回到终点箱体原位。
- 地面路径在 `YUp` 模型下：
  - 虚拟物体起点姿态、动画姿态、转弯姿态已恢复正常。
  - 真实物体地面路径当前已恢复到可用状态：
    - 起点落位补偿已接入；
    - 逐帧补偿会随当前目标姿态一起旋转，不再使用固定世界补偿矢量；
    - 动画结束后不再因恢复链或重复落最后一帧而再次跳动。
  - `Ground + 真实物体` 的逐帧姿态约束已经明确：
    - 动画播放阶段只允许绕宿主 `up` 轴转动；
    - 不再在播放阶段每帧重建完整三维姿态。
  - `Ground/Hoisting + 真实物体` 的前进轴语义当前已固定：
    - 对象级前进轴统一按 `PositiveX` 解释；
    - 不再因为路径初始方向更偏 `Z` 就把对象前进轴自动切换成 `PositiveZ`。
- 当前已禁止地面/吊装路径偷偷退回旧 `yaw` 链路。
- 吊装路径真实物体的角度调整链路已重新稳定：
  - 起点“调整角度”后，预览、生成动画、播放前重置都复用同一份真实起点基姿态；
  - 清除并重新选择物体时，旧角度修正必须被清空，不能继承上一次调整状态。
- 碰撞检测/恢复主链路已稳定：
  - `ClashDetective` 三维恢复不能再先 `ResetPermanentTransform`。
  - 碰撞恢复、自动报告、自动截图已重新对齐到动画主链路。
- 虚拟物体资源问题已确认并修复：
  - 旧 `unit_cube.nwc` 局部几何中心不在原点，会导致虚拟物体中心偏差。
  - 新 `unit_cube.nwc` 已替换为几何中心在原点的版本。
- 旋转适配入口当前稳定分流：
  - 虚拟物体继续走 `HostCoordinateAdapter` 的 `Legacy` 入口；
  - 真实物体走 `Direct` 入口；
  - 两者不能再强行共用同一条旋转转换链。
- `Rail` 终端安装仿真创建/编辑区当前已完成第一轮工作流拆分：
  - 新建 Rail 与编辑选中 Rail 不再共用同一套按钮命令入口；
  - 新建区和编辑区有独立的 `找端面 / 选安装点 / 取起点` 可用条件；
  - 两个区域都已有明确的“取消装配”退出入口；
  - 上方“路径编辑 -> 结束”在 Rail 装配工作流活跃时，也必须能真正退出 Rail 装配流程。

## 2. 当前坐标系架构

- 外部坐标：
  - `Navisworks` 世界坐标，统一视为外部输入坐标。
- 内部统一坐标：
  - `Canonical Space`，固定 `Z-up`。
- 业务基准层：
  - `ProjectReferenceFrame`
  - 球心、项目 `up`、默认模型轴约定
- 模型局部轴约定：
  - `ModelAxisConvention`
  - 明确 `ForwardAxis / UpAxis`
- `Rail` 局部坐标系：
  - `RailLocalFrame`
  - `Forward / Normal / Lateral`

## 3. 当前关键基础工具

- `src/Utils/CoordinateSystem/HostCoordinateAdapter.cs`
- `src/Utils/CoordinateSystem/ProjectReferenceFrame.cs`
- `src/Utils/CoordinateSystem/ModelAxisConvention.cs`
- `src/Utils/CoordinateSystem/CanonicalRailPoseBuilder.cs`
- `src/Utils/CoordinateSystem/RailLocalFrame.cs`
- `src/Utils/CoordinateSystem/CanonicalRailOffsetResolver.cs`
- `src/Utils/CoordinateSystem/CanonicalTrackedPositionResolver.cs`
- `src/Utils/CoordinateSystem/CanonicalPlanarPoseBuilder.cs`

## 4. 当前必须记住的根因与规则

### 4.0 真实物体参考姿态与 Fragment默认Up

- 真实物体不能再默认使用 `ModelItem.Transform` 或包围盒正交框架当“原始姿态”。
- 当前稳定做法是：
  - 先从 fragment 统计得到代表姿态
  - 再用当前文档级 `Fragment默认Up` 解释这组 fragment 参考轴
  - 最终得到当前宿主语义下的真实参考姿态
- `Fragment默认Up` 的真正用途不是“找一个竖直候选轴”，而是：
  - 解释 fragment 参考姿态的原始 `Y/Z` 语义
  - 把 fragment 参考姿态转换成当前宿主坐标语义下可用的真实姿态
- 当前文档如果 `Fragment默认Up` 设错，会直接导致：
  - 真实物体起点姿态错误
  - Ground / Hoisting / Rail 的参考姿态解释错误
  - 后续角度修正、通行空间、路径贴合全部建立在错误姿态上
- 当前规则：
  - 先解释真实物体参考姿态，再做路径对齐
  - 不能跳过这一步，直接拿 fragment 世界轴去猜业务姿态
 - 当前补充规则：
   - `Ground/Hoisting` 的真实物体“对象前进轴”与 fragment 参考姿态解释是两层语义；
   - fragment 负责解释真实参考姿态；
   - 对象前进轴当前在 `Ground/Hoisting` 上固定按 `PositiveX` 语义使用，不再做“按路径方向选最近轴”的自动切换。

### 4.1 Rotation / 矩阵语义

- `Rotation3D(a, b, c, d)` 的参数顺序是四元数 `x, y, z, w`。
- 不要再随意在 `System.Numerics` 矩阵、四元数、Navisworks `Rotation3D` 之间猜行列语义。
- 新的姿态构造应优先复用已经验证过的坐标框架工具，不要临时手拼矩阵。

### 4.2 碰撞恢复

- 对受 `PathAnimationManager` 控制的对象，`ClashDetective` 验证前绝不能先 `ResetPermanentTransform`。
- 否则宿主姿态会被清回单位姿态，后续增量恢复会错误地认为“不需要再旋转”。

### 4.3 动画跟踪点语义

- `AnimatedObjectTrackedPosition` 的唯一语义：
  - 当前动画主链路使用的跟踪点位置。
- `Ground + 真实物体` 当前必须明确区分两类“中心”：
  - 业务跟踪点应固定为物体**原始包围盒中心**
  - 不是旋转后的实时包围盒中心
- 实时包围盒中心的用途仅限于：
  - 诊断旋转后漂移
  - 计算当帧补偿
  - 验证补偿结果
- 不允许把实时包围盒中心直接回写成 `Ground` 路径的业务跟踪点定义。
- 这条规则的直接影响范围包括：
  - 起点落位
  - 逐帧补偿
  - 动画日志
  - 碰撞与结果记录语义
- 如果后续动画跟踪点再变，数据库和碰撞结果语义必须同步更新。

### 4.4 虚拟物体资源

- 虚拟物体资源的局部几何中心必须在原点。
- 如果资源局部原点不对，上层姿态和坐标框架再正确，也会表现为固定偏差。
- 日志里优先看：
  - 包围盒中心
  - 目标中心
  - 应用后偏差
- 不要再用虚拟物体 `Transform` 的即时读回值判断 override 后的真实姿态。

### 4.5 地面/吊装路径

- 地面/吊装路径已经开始走完整姿态链路，不再允许悄悄退回旧 `yaw` 方案。
- 如果完整姿态生成失败，应直接暴露错误，而不是 fallback。
- 当前已知边界：
  - 地面路径播放阶段，真实物体的多轴角度修正还没有完全收稳。
  - 目前稳定可用的是：`Y` 轴转动。
  - `X / Z` 轴在起点静态预览或直线段里可能看起来合理，但路径一旦拐弯，逐帧按宿主世界轴重算会让“俯仰/侧倾”语义发生耦合，表现成不符合现场直觉的侧旋。
  - 因此当前阶段，对地面路径应按“只稳定支持 `Y` 轴转动”使用；`X / Z` 轴播放链问题留待后续专项修复。
- 当前新增稳定规则（2026-03-25）：
  - `Ground + 真实物体` 的播放阶段不能再每帧应用完整三维姿态；
  - 必须以起点基姿态为基线，只叠加宿主 `up` 轴上的单轴旋转。
- 当前新增稳定规则（2026-03-25）：
  - `Ground + 真实物体` 的起点目标点语义仍然是路径跟踪点，不允许修改路径点本身；
  - 如真实物体起点落位存在固定偏差，应把补偿施加到物体位置，而不是回写路径点或路径跟踪点语义。
- 当前新增稳定规则（2026-03-25）：
  - `Ground + 真实物体` 的补偿不是固定世界矢量；
  - 起点测得的偏差必须随当前目标姿态一起旋转后，再参与逐帧位置应用。
- `YUp` 吊装路径创建主链路已补齐到宿主坐标适配架构：
  - 提升、水平移动、下降、终点落地都不能再把世界 `Z` 硬编码成“向上”。
  - 终点必须使用用户最后一次点击的地面点，不能回填起点地面高程。
- 吊装路径相关的当前稳定约束：
  - 路径创建、终点补点、路径点修改、斜线正交化、通行空间识别，必须共用同一套“宿主坐标 -> Canonical -> 宿主坐标”的高度语义。
  - `高度过渡点` 这类自动生成点，本质上仍是吊装路径点，不能在渲染或可视化阶段再退回旧 `ZUp` 假设。
  - 通行空间如果遇到“纯垂直段却从前方空中偏出去一截、变成斜的”，优先检查：
  - 垂直段识别是否仍在比较 `dz`
  - 低点补物体高度是否仍在直接改 `Z`
  - 吊装水平参考方向是否仍在固定 `XY` 平面求
- 吊装路径这轮重构后，相关职责已经收束到：
  - `HoistingCoordinateHelper`
  - `PathPlanningManager`
  - `AerialPathGenerator`
  - `PathPointRenderPlugin`
- 当前规则：
  - 吊装“向上”只能通过宿主 `up` 语义表达，不能直接写 `point.Z +/- height`
  - 通行空间垂直延伸必须沿宿主 down 方向补物体高度
  - 吊装水平参考方向必须先剔除宿主 up 分量，再在宿主水平面内求方向
- 吊装路径“设为终点直接结束”如果出现：
  - 核心路径点数正确，但路径列表/路径点列表仍显示为 `0`
  - 切到别的路径再切回来后才恢复正常
  - 这类问题优先检查 `UIStateManager` 的 UI 队列消费，而不是先怀疑路径数据或坐标系。
- 本次真实根因已经确认：
  - `FinishEditing()` 期间会连续追加 `CurrentRouteChanged / PathPointsListUpdated / RouteGenerated` 等 UI 事件。
  - 旧的 `UIStateManager.ProcessQueuedUpdates()` 只消费“当前这一批”队列项，执行过程中新增的后续事件会滞留。
  - 所以路径数据其实已经完成，只是 UI 直到下一次路径切换时才把滞留事件顺带处理掉。
- 当前修复原则：
  - `UIStateManager` 必须持续消费后续批次，直到 UI 队列真正为空。
  - 不要用“手动切换路径”“先选空再选回”“强行补 OnPropertyChanged”这类 UI 和稀泥方式掩盖队列问题。
  - “设为终点直接结束”和“点结束按钮完成路径”都必须走到同样完整的收尾语义：
  - 路径数据完成
  - 当前路径切换完成
  - 路径列表与路径点列表同步完成
- 动画自然结束时，必须先显式应用最后一帧姿态，再进入后续碰撞检测/恢复链路。
  - 否则会出现：
  - 播放停下时视觉上离终点还差一点
  - 碰撞检测开始前又被后续姿态应用“往前补一下”
- 当前播放链路已经统一：
  - 逐帧播放和动画结束落点都复用同一套姿态应用入口
  - 地面/吊装路径如果缺少完整姿态，应直接报错，不能回退旧 `yaw`
- `Rail / Ground / Hoisting` 终点诊断日志的比较基准必须是：
  - 该路径类型真实使用的“期望跟踪点/几何中心”
  - 不能再把地面接触点或终点锚点直接拿来和动画跟踪中心比较

### 4.6 聚焦 / 视点

- `ViewpointHelper` 的聚焦/俯视逻辑不能再把世界 `Z` 硬编码成“上方向”。
- 在 `YUp` 模型里：
  - 相机位置必须沿宿主 `HostUpVector` 偏移
  - 屏幕上方向也必须通过宿主坐标适配得到
- 如果继续写死：
  - `cameraPosition = (x, y, z + distance)`
  - `upVector = (0, 1, 0)`
  - 那么 `YUp` 模型下聚焦就会跑到侧视图。
- 当前原则：
  - 聚焦输入/输出使用宿主坐标
- 方向语义通过 `HostCoordinateAdapter` 明确适配
- 不要在视点辅助逻辑里直接假设宿主一定是 `ZUp`

### 4.7 Rail 角度修正

- `Rail` 的“调整角度”和 `Ground / Hoisting` 不是同一种实现语义。
- `Ground / Hoisting` 当前语义：
  - 在内部 `Canonical` 坐标系里，绕统一 `CanonicalUp` 做水平角度修正。
- `Rail` 当前正确语义：
  - 角度修正必须先作用在构件局部轴约定上，等价于“CAD 原位局部预旋转”
  - 然后再进入 `Rail` 的切向/法向姿态求解
  - 不能在物体已经落到起点后，再在宿主空间对最终 pose 补一个世界轴旋转
- 当前实现链路已经收束到：
  - `CanonicalRailPoseBuilder`
  - `RailPathPoseHelper`
  - `PathAnimationManager`
- 当前规则：
  - `Rail 0°` 时，必须严格保持当前稳定基线，不允许改变既有 `Rail` 姿态
  - `Rail` 有角度修正时，对齐到路径切向的是“修正后的 local forward”
  - `Rail` 路径切向/法向框架本身不能因为角度修正被改坏
  - `Rail` 通行空间和真实物体姿态必须共享同一套角度语义，不能一个改局部 footprint、一个改世界 pose
- 调试优先级：
  1. 先验证 `0°` 基线是否保持不变
  2. 再验证修正后 `forward` 是否仍沿 rail 切向
  3. 最后再看 Navisworks 应用层是否正确按三步增量姿态落位

### 4.7.1 Rail 平移模式

- `Rail` 的“平移”不是重新按轨上/轨下求一套新的安装姿态。
- 当前稳定语义：
  - 终点箱体当前原始位姿是唯一真值；
  - 先计算终点箱体相对“路径终点参考点”的固定残差；
  - 再把这份残差搬运到路径起点；
  - 动画全程保持这套终点原始姿态和固定残差。
- 当前规则：
  - 不能把“平移模式”误实现成重新按 `RailMountMode` 解目标 pose；
  - 不能锁到“参考姿态”而丢掉终点箱体当前真实几何姿态；
  - 终点保位误差如果异常，优先检查“残差是相对终点参考点采样，还是误相对起点参考点采样”。

### 4.8 Rail 真实物体必须复用统一姿态解释层

- `Rail` 不应再单独退回默认 `PositiveX / PositiveY` 轴约定。
- 当前稳定原则：
  - `Ground / Hoisting / Rail` 三类路径的真实物体，必须先共用同一个“真实参考姿态解释层”
  - 路径类型的差异只体现在目标路径框架：
    - `Ground / Hoisting`：`up = 宿主 up`
    - `Rail`：`up = rail 法向 / preferred normal`
- 当前 `Rail` 真实物体稳定链路：
  1. fragment 代表姿态
  2. `Fragment默认Up` 解释后的真实参考姿态
  3. `Rail` 路径框架（切向 / 法向）
  4. 宿主 `X/Y/Z` 角度修正
- 不要再让 `Rail` 真实物体单独维护一套与 `Ground / Hoisting` 不同的对象姿态来源。

### 4.9 Rail 真实物体的通行空间与路径偏移

- `Rail` 真实物体的通行空间、起点中心偏移、逐帧法向偏移，必须共享“最终姿态”的同一套尺寸语义。
- 当前稳定规则：
  - 不能只根据“宿主轴角度修正”单独投影尺寸
  - 必须同时吃到：
    - `Rail` 基姿态
    - 宿主 `X/Y/Z` 角度修正后的最终姿态
- 否则会出现典型错误：
  - 物体本体姿态正确，但起点偏离路径
  - 单轴旋转时通行空间看起来对，双轴旋转后只跟上一个角度
  - `Rail` 真实物体通行空间与物体本体方向不一致
- 当前消费规则：
  - `AnimationControlViewModel.UpdatePassageSpaceVisualization()` 中，真实物体的 `Rail` 和 `Hoisting` 必须分开消费
  - `Rail` 真实物体不能再复用 `Hoisting` 的法向/分段参数语义

### 4.10 Rail 终端安装仿真工作流

- 当前真实问题已经确认：
  - “创建 Rail 路径”区和“Rail 参数”编辑区之前共用同一套装配状态、命令入口和按钮可用条件；
  - 导致新建流程会误吃编辑态校验，或在切换路径后残留旧的装配状态。
- 当前第一轮稳定修复：
  - 新建 Rail 与编辑 Rail 已拆成独立命令入口；
  - “找端面”在新建 Rail 时不再要求先选中一条现有 Rail 路径；
  - 新建区的“选安装点”不再受 `IsRailRouteSelected` 编辑态条件限制；
  - 安装点拾取完成后，拾取点、安装点、安装参考面、中心线必须保留可视化，不能在收尾时被一并清掉；
  - “隐藏辅助线”必须同时清理：
    - 参考杆与锚点
    - 球心到光轴参考点基准线
    - 端面分析可视化
    - 安装点、安装中心线、安装参考面
  - 新建区和编辑区都必须有明确的“取消装配”；
  - “路径编辑 -> 结束”在 Rail 装配流程活跃时，也必须能触发同一条取消/清理链路；
  - 切换路径时必须自动清空旧的 Rail 装配上下文，不能把旧状态带到下一条路径。
- 当前仍要记住：
  - 这块只是“第一轮工作流拆分”，还不是彻底的数据结构重构；
  - 如果后续继续扩 Rail 终端安装仿真，优先方向应是把“创建态上下文”和“编辑态上下文”进一步拆成独立 context，而不是继续在 ViewModel 顶层堆共享字段和布尔分支。

### 4.11 吊装路径角度调整

- 当前真实根因已经确认：
  - 吊装真实物体在“起点调整角度后生成动画”时，如果基姿态缓存不跟着角度修正一起重建，就会出现：
    - 动画里没有沿用调整后的角度；
    - 甚至被错误立起或只抬高一点的异常现象。
- 当前稳定规则：
  - 吊装路径必须缓存“真实起点基姿态 + 起始 yaw”；
  - 起点预览、动画生成、播放前重置，都要复用同一份基线；
  - 只要角度修正变化，就必须清掉旧缓存并重新 `MoveObjectToPathStart()`；
  - 清除物体或重新选择物体时，角度修正状态必须归零，不允许继承上一轮对象的角度状态。

## 5. 当前保留的日志策略

- 保留：
  - 终点诊断
  - 保存/恢复姿态
  - 关键碰撞恢复
  - 虚拟物体应用后中心/偏差
  - 真实物体地面路径：
    - `[路径起点诊断]`
    - `[路径起点补偿]`
    - `[Ground路径补偿]`
- 已降级或删除：
  - 大量重复逐帧宿主姿态轴日志
  - 虚拟物体 `Transform` 即时读回日志（容易误导）
  - `Hoisting` 真实物体起点姿态与平面前进轴的刷屏 `Info` 日志，已降为 `Debug`

## 6. 最近关键提交

- `c3b103c` `Add explicit exit for rail assembly workflow`
- `c974469` `Separate rail creation and edit assembly flows`
- `d4c49fc` `Stabilize hoisting pose adjustment flow`
- `cb56737` `Preserve terminal pose when translating rail objects to path start`

## 7. 当前 Navisworks 变换 API 结论

- `ModelItem.Transform`
  - 只表示原始设计文件变换；
  - 不反映 `OverridePermanentTransform` 后的当前显示姿态。
- `ModelGeometry.ActiveTransform`
  - 是当前几何实际生效的变换；
  - 当前项目里，凡是要读“当前姿态/当前位置”，优先使用这一层。
- `ModelGeometry`
  - 关键四层语义：
    - `OriginalTransform`
    - `PermanentOverrideTransform`
    - `PermanentTransform`
    - `ActiveTransform`
- `OverridePermanentTransform(...)`
  - 官方语义是增量变换；
  - 不是“直接设成最终世界姿态”。
- `ResetPermanentTransform(...)`
  - 清掉的是永久增量层；
  - 不会修改原始设计文件变换。

## 8. 当前还值得继续观察的点

- 空轨路径里仍有一个旧 warning：
  - `[空轨] 双轨几何中心线提取失败，退回 OBB 主轴中线`
- 这与当前 `YUp` 地面路径问题无关，但后续可以单独处理。

## 9. 下一步建议

- 继续按“先框架、先测试、后接业务”的方式推进。
- 新问题优先：
  1. 先看日志
  2. 若日志不足，先补日志
  3. 再补针对性的回归测试
  4. 最后再改业务代码
- `Rail` 终端安装仿真的下一轮优化优先级：
  1. 把创建态/编辑态从 ViewModel 顶层共享字段继续拆成独立 context
  2. 为“取消装配 / 切换路径 / 中途退出后重新开始”补单元测试或更轻量的状态回归验证
  3. 再考虑是否需要把创建区与编辑区在 UI 上做更明确的视觉分隔

## 10. 当前阶段的工作边界

- 不要回到“直接补旧 `yaw` 链路”的方式。
- 不要再增加隐藏错误的 fallback。
- 不要再混淆：
  - 外部宿主坐标
  - 内部 `Canonical` 坐标
  - 业务参考点
  - 模型局部轴约定
