NavisworksTransport/doc/design/2026/auto-object-rotation-min-passage-projection-design.md
tian 7187bcf622 自动最优朝向: 黑盒实测模式
- 新增 ObjectPassageProjectionOptimizer(SO(3)粗搜索+Nelder-Mead)
- EditRotationWindow 加入"自动调整"按钮
- AnimationControlViewModel 实现黑盒实测评估(临时摆位→读BoundingBox→恢复)
- 设计文档和实现计划
2026-05-27 12:24:01 +08:00

196 lines
7.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 自动调整物体姿态以最小化通行截面投影面积
更新时间2026-05-27
## 1. 背景
动画检测中的“调整物体”窗口目前支持手工输入 X/Y/Z 三轴角度修正。用户希望增加一个“自动调整”按钮:对任意动画物体,在路径起点处自动寻找一个合适姿态,让物体经过路径上的门洞、狭窄通道时具有最大通过性。
Navisworks 当前主要提供 AABB 包围盒,真实物体的 fragment 代表姿态只能大概判断方向,不足以作为自动调整的精确依据。因此本功能不能依赖 fragment 推断“物体真实方向”,也不能只做绕宿主 up 轴的单轴旋转。单轴 yaw 调整手工即可完成,不满足目标。
## 2. 目标
在“调整物体”窗口增加自动调整能力:
- 支持三轴联动搜索,允许任意三维旋转。
- 允许物体横放、倒放、斜放,不施加运输姿态限制。
- 以路径起点方向为基准,最小化物体在门洞截面上的投影面积。
- 在投影面积相同或接近时,优先选择投影高度更小的姿态,让物体尽量平放。
- 结果写回现有 X/Y/Z 三个角度输入框,用户可继续手工微调。
- 不依赖 fragment 方向作为优化真值。
- 遵守宿主坐标系 / 内部坐标系 / 资产坐标系语义,不硬编码世界 Z 为 up。
## 3. 非目标
- 不在本阶段判断真实门洞尺寸,也不保证某条路径一定可通过。
- 不修改路径规划算法。
- 不重建物体 mesh 或 OBB。
- 不引入姿态限制,例如“保持底面朝下”或“禁止倒置”。
- 不用静默 fallback 掩盖优化失败;失败应明确提示。
## 4. 坐标系语义
UI 输入、日志、用户看到的 X/Y/Z 角度仍按宿主坐标系解释。
路径起点方向使用宿主坐标系点计算:
1. 取路径起点到下一个有效路径点的方向。
2. 剔除宿主 up 分量,得到水平路径前进方向 `HostPathForward`
3. 通过 `HostCoordinateAdapter` 获取宿主 up`HostUp`。
4. 截面横向方向为 `HostSide = normalize(cross(HostPathForward, HostUp))`
如果路径起始段过短或剔除 up 后方向退化,应继续查找后续有效路径段;若仍无法得到方向,则自动调整失败并提示用户。
## 5. 目标函数
自动调整的主目标函数是门洞截面投影面积:
```text
Score(rotation) = ProjectedWidthAcrossPath(rotation) * ProjectedHeightAlongHostUp(rotation)
```
其中:
- `ProjectedWidthAcrossPath`:物体在 `HostSide` 方向上的投影宽度。
- `ProjectedHeightAlongHostUp`:物体在 `HostUp` 方向上的投影高度。
- 路径前进方向上的长度不参与目标函数。
该目标符合“穿门”语义:门洞主要限制的是横向净宽和竖向净高,而不是物体沿路径方向占多长。
在工程现场中,门洞通常“宽度大于高度”,因此仅比较面积不够。两个姿态可能具有相同或非常接近的面积,但一个姿态更高、更窄,另一个姿态更低、更宽;实际通行时应优先选择更低、更平放的姿态。
因此最终排序应采用词典序或近似平局策略:
1. 先最小化 `ProjectedArea`
2. 当面积差异小于容差时,选择 `ProjectedHeightAlongHostUp` 更小的姿态。
3. 当面积和高度都接近时,再选择 `ProjectedWidthAcrossPath` 更小的姿态。
面积容差建议使用相对容差,例如 `1%`,避免因为 AABB 或浮点误差导致高度明显更优的姿态被面积微小差异淘汰。
## 6. 推荐算法
采用业界常见的黑盒无导数优化路线:
### 6.1 全局粗搜索
在完整三维旋转空间中生成候选姿态,避免只绕某一轴或只优化 yaw。
候选生成应满足:
- 覆盖三维姿态空间。
- 结果确定性,不依赖随机数。
- 粗搜索粒度可配置,默认优先保证交互速度。
可选实现:
- 均匀方向采样加 roll 角采样。
- Fibonacci sphere / icosphere 风格方向采样。
- 固定欧拉角网格作为初始版本,但需要避免只覆盖少量手工角度。
### 6.2 局部精修
对粗搜索评分最好的若干候选执行无导数局部优化,例如:
- Powell method。
- Nelder-Mead simplex。
Navisworks AABB 目标函数不平滑,也不可求导,因此不使用梯度法。局部优化的终止条件应包含:
- 最大迭代次数。
- 角度步长阈值。
- 评分改善阈值。
### 6.3 输出角度
优化器内部可用四元数表示候选姿态,最终需要转换为当前窗口使用的宿主 X/Y/Z 三轴角度修正,并写回:
- `RotationXDegrees`
- `RotationYDegrees`
- `RotationZDegrees`
角度顺序必须遵守项目当前约束X -> Y -> Z对应 `qz * qy * qx`
## 7. 评估方式
第一阶段建议实现为纯几何优化器:
- 输入物体三轴尺寸。
- 输入宿主坐标系下的 `HostPathForward` / `HostSide` / `HostUp`
- 输入候选旋转。
- 输出截面投影宽度、高度、面积。
这样可以用单元测试充分锁定算法,不需要启动 Navisworks。
真实物体的 fragment 代表姿态不作为优化真值。若后续发现数学预测与 Navisworks 实际 AABB 存在明显偏差,再增加“慢速精确模式”:
1. 保存当前动画物体状态。
2. 临时应用候选姿态到路径起点。
3. 读取 Navisworks 更新后的 AABB。
4. 计算截面投影面积。
5. 恢复状态。
慢速模式必须复用 `PathAnimationManager` / `ModelItemTransformHelper` 的现有姿态链路,不能绕过主链路直接写入临时补丁。
## 8. UI 行为
“调整物体”窗口增加一个“自动调整”按钮。
建议行为:
1. 用户打开“调整物体”窗口。
2. 点击“自动调整”。
3. 系统根据当前路径起点方向、当前物体尺寸和宿主坐标系执行优化。
4. 将最优 X/Y/Z 角度写入输入框。
5. 用户可继续修改角度。
6. 点击“确认”后沿用现有 `ObjectStartPlacementRequest.CreateRotationCorrection(...)` 链路。
自动调整失败时,窗口不关闭,并显示明确错误:
- 未选择路径。
- 路径点不足。
- 起点方向退化。
- 未选择动画物体。
- 物体尺寸无效。
- 优化器未找到有效姿态。
## 9. 测试计划
新增纯几何单元测试,建议放在 `UnitTests/CoordinateSystem/`
必须覆盖:
- 长方体通过三轴旋转得到比初始姿态更小的截面面积。
- 三轴优化能找到单轴 yaw 无法达到的更小截面面积。
- `YUp``ZUp``HostUp` 高度语义正确。
- 路径横向宽度和宿主 up 高度共同参与目标函数。
- 面积接近时优先选择投影高度更小的平放姿态。
- 任意旋转允许倒置,不强制保持原 up 方向。
- 优化结果确定性:同一输入多次运行输出一致。
- 退化路径方向会失败而不是回退默认方向。
后续接入 UI 后,补充 ViewModel 或窗口级测试:
- 点击自动调整后会更新 X/Y/Z 输入值。
- 自动调整后确认仍走现有角度修正请求。
- 失败时保留原输入值。
## 10. 实现落点
候选落点:
- `src/Utils/CoordinateSystem/ObjectPassageProjectionOptimizer.cs`
- `UnitTests/CoordinateSystem/ObjectPassageProjectionOptimizerTests.cs`
- `src/UI/WPF/Views/EditRotationWindow.xaml`
- `src/UI/WPF/Views/EditRotationWindow.xaml.cs`
- `src/UI/WPF/ViewModels/AnimationControlViewModel.cs`
如果需要从 ViewModel 提供路径和尺寸上下文,可新增一个小的请求对象,避免窗口直接依赖大型 ViewModel。
## 11. 风险与注意事项
- Euler 角存在多解和万向节锁风险优化内部应优先用四元数Euler 只作为 UI 输出格式。
- AABB 只能近似真实几何,通过性结果应理解为基于包围盒的保守估计。
- 对真实物体fragment 仅可作为现有动画链路的弱参考,不作为自动调整的优化真值。
- 对 Ground / Hoisting / Rail 的路径姿态链路不得引入旧 yaw fallback。
- 若候选姿态会改变落位补偿,必须同步更新通行空间尺寸和起点预览。