docs(vtk): 视图导航与坐标轴改进 spec(贴合轴/可点gnomon/双击适配+详情)
This commit is contained in:
parent
94d0ac9c3b
commit
d991faa1ee
|
|
@ -0,0 +1,67 @@
|
||||||
|
# VTK 视图导航与坐标轴改进 — Spec(2026-07-01)
|
||||||
|
|
||||||
|
> 分支 `feat/vtk-merged-dataset-column`(合并数据集单栏重构之后的增量)。职责:渲染区坐标轴、方向标、相机导航、列表双击联动。全部决策已与用户逐条确认。
|
||||||
|
|
||||||
|
## 0. 背景与动机
|
||||||
|
|
||||||
|
合并单栏 + 单一自由场景后,2D 平面与 3D 体/帘面共存于一个世界坐标系。现状渲染坐标轴是**全场景合并包围盒**的一套 cube axes(`AxesActor`/`rebuildAxes`)。用户痛点:多个渲染物相距很远/尺度悬殊时,全场景轴只贴近某一个物体,**离轴远的物体读不出真实尺寸**。业界通行解法不是「每物体一套常驻轴」,而是「全场景一套参考 + 选中物体单独出其贴合轴 + 可点击方向标 + 按需测量」。本 spec 落地导航侧改进。
|
||||||
|
|
||||||
|
## 1. 已确认决策(逐条)
|
||||||
|
|
||||||
|
1. **坐标轴(空间)全场景一套是对的**——坐标轴量的是空间位置(一个世界 CS),物理量差异由逐数据集色阶承担,尺度悬殊用统一 VE,不拆轴。
|
||||||
|
2. **选中物体 → 隐全景轴、只显该物体贴合轴**(Q1)。
|
||||||
|
3. **贴合轴按层级子树归一到一个包围盒**:选中三维体(或其下切片、切片下异常)→ 包围盒覆盖「该三维体 + 其切片 + 其异常」整棵子树,合成**一个**盒;选谁都归到该子树同一个盒。
|
||||||
|
4. **角落三向标(gnomon)常驻 + 可点击**(Q2);点击某方向轴 → 相机**绕支点转到该轴、保留当前缩放距离**(ViewCube 手感,选项1)。
|
||||||
|
5. **绕轴支点规则**:有选中 → 选中物体**子树包围盒中心**;无选中 → **全场景合并包围盒中心**。两者都保留当前缩放。
|
||||||
|
6. **列表双击 DS →(a)视图适配到该 DS 的空间范围 +(b)联动打开中下方数据集详情页**;三维体等**详情页未做**的类型要**容错静默**(找不到对应详情页不报错、不弹窗,仅完成适配)。
|
||||||
|
|
||||||
|
## 2. 术语:子树包围盒
|
||||||
|
|
||||||
|
- 一个 ds 的「子树」= 该 ds 自身 + 其所有后代 ds(三维体 → 其切片 → 切片的异常),仅计入**当前已渲染**的成员。
|
||||||
|
- 子树包围盒 = 子树内所有已渲染 ds 的 actor 包围盒并集(`dsProps_` 按 dsId 取 actor bounds)。
|
||||||
|
- 后代关系来源:数据模型的父子(切片 parentId=体、异常 parentId=切片/体)——由控制器/仓储或面板树提供 dsId→后代集。渲染侧只需拿到「要并集的 dsId 列表」。
|
||||||
|
|
||||||
|
## 3. 设计
|
||||||
|
|
||||||
|
### 3.1 相机/包围盒基元(`VtkSceneView` + `CameraPreset`)
|
||||||
|
- `bool datasetBounds(const std::vector<std::string>& dsIds, double outB[6]) const`:并集给定 dsIds 的已渲染 actor 包围盒;无有效则返回 false。
|
||||||
|
- `void fitToBounds(const double b[6])`:把相机适配到指定包围盒(保持朝向,`ResetCamera(b)`)。用于双击适配、贴合。
|
||||||
|
- `void orbitToAxis(ViewDir dir, const double pivot[3])`:相机**绕 pivot** 转到沿 dir 轴看向 pivot,**保留当前 focal-to-camera 距离**(即当前缩放)。区别于 `applyCameraView`(正视重置)与 6 视图按钮(重置+fit)。实现:取当前 |cam−focal| 距离 d;focal 设为 pivot;按 dir 设 cam=pivot+dir_offset*d、view-up 按预设;`ResetCameraClippingRange`。
|
||||||
|
|
||||||
|
### 3.2 贴合轴 + 隐全景轴(决策 2/3)
|
||||||
|
- `VtkSceneView` 维护两态:`rebuildAxes()`(全场景,现状)与新 `showFittedAxes(const double b[6])`/`showSceneAxes()`。
|
||||||
|
- 选中某 ds(`datasetSelected` 到达)→ 上层算该 ds 子树的 dsIds → `datasetBounds` → `showFittedAxes(box)`(把 cube axes 的 bounds 设为子树盒)+ 隐全景轴。
|
||||||
|
- 取消选中(空选中)→ `showSceneAxes()`(恢复全场景轴)。
|
||||||
|
- 实现可复用 `AxesActor`:新增「按外部 bounds 显示」的模式(不再固定用全场景 bounds),选中/取消在两种 bounds 间切换。
|
||||||
|
|
||||||
|
### 3.3 可点击方向标 gnomon(决策 4/5)
|
||||||
|
- 新增角落三向标:`vtkOrientationMarkerWidget` + `vtkAxesActor`(XYZ 三向 + 轴标签),常驻右下(或右上,避开现有工具栏)。
|
||||||
|
- **可点击**:`vtkOrientationMarkerWidget` 默认不透传点击到轴。需在其上做拾取——用一个 `vtkPropPicker`/自定义,把点击落到 +X/−X/+Y/−Y/+Z/−Z 六向之一 → 调 `orbitToAxis(dir, pivot)`。pivot 按决策 5(选中子树中心 / 全场景中心)。
|
||||||
|
- 六向 → `ViewDir` 映射:+Z=Top、−Z=Bottom、+Y=Back(北望反)/−Y=Front… 与 `CameraPreset` 现有 ViewDir 语义对齐(复用,不新造方向定义)。
|
||||||
|
|
||||||
|
### 3.4 双击 DS → 适配 + 详情(决策 6)
|
||||||
|
- 列表双击现已发 `detailRequested(dsId, ddCode, name)`(`CategorySection::itemDoubleClicked`)。扩展双击行为:**并发**触发
|
||||||
|
1. **适配**:算该 dsId 子树 dsIds → `datasetBounds` → `fitToBounds`(相机适配到该 DS 空间范围,保持朝向)。
|
||||||
|
2. **详情联动**:沿用现有 `detailRequested → DatasetDetailController` 链打开中下方 `DatasetDetailPanel`。
|
||||||
|
- **容错静默**:对详情页未实现的类型(三维体 `dd_voxel`/`dd_radar_3d` 等),详情链找不到对应页时**静默**——不弹错、不打断,适配照常完成。实现:详情控制器/面板在无匹配详情页时走「无操作」分支(或双击前按 ddCode 判定「有详情页才发 detailRequested」)。优先在联动入口按「该 ddCode 是否有详情页」gate,无则只做适配。
|
||||||
|
|
||||||
|
## 4. 影响文件(预估)
|
||||||
|
- `src/app/VtkSceneView.{hpp,cpp}`:`datasetBounds`/`fitToBounds`/`orbitToAxis`/`showFittedAxes`/`showSceneAxes` + gnomon widget。
|
||||||
|
- `src/render/CameraPreset.{hpp,cpp}` 或 `src/render/actors/AxesActor.*`:orbit-to-axis 相机数学、按外部 bounds 的轴。
|
||||||
|
- `src/controller/VtkSceneController.*` + `I3dSceneView`:转发新相机/轴/适配接口;子树 dsIds 解析(或由 main 用面板树/仓储父子算)。
|
||||||
|
- `src/app/main.cpp`:选中→贴合轴、双击→适配+详情 gate、gnomon 点击接线。
|
||||||
|
- `src/app/panels/columns/CategorySection.*`/`CategoryAnalysisTab.*`:双击透传(已有 detailRequested;可能加「fitRequested(dsId)」或复用 datasetSelected)。
|
||||||
|
|
||||||
|
## 5. 分期/任务
|
||||||
|
- **T1(基元)**:`datasetBounds`/`fitToBounds`/`orbitToAxis`(相机+包围盒基元,纯渲染,可单测 orbit 数学)。
|
||||||
|
- **T2(贴合轴)**:选中→子树盒→贴合轴+隐全景轴;取消→恢复全景轴。含「子树 dsIds 解析」。
|
||||||
|
- **T3(gnomon)**:常驻可点击三向标 → orbitToAxis(pivot 规则)。
|
||||||
|
- **T4(双击)**:双击→适配到子树盒 + 详情联动 gate(无详情页静默)。
|
||||||
|
- 顺序:T1 先(T2/T3/T4 都依赖 T1 的基元);T2/T4 依赖「子树 dsIds 解析」(T2 引入,T4 复用)。
|
||||||
|
|
||||||
|
## 6. 验收
|
||||||
|
1. 无选中:显示全场景总览轴 + 右下角三向标。
|
||||||
|
2. 选中某体/切片/异常:全景轴隐去,出现覆盖「该体+其切片+异常」子树的一个贴合包围盒轴,能读该子树真实尺寸;取消选中恢复全景轴。
|
||||||
|
3. 点击三向标某方向轴:相机绕支点(选中子树中心/无选中则全场景中心)转到该轴、**缩放不变**、数据仍居中。
|
||||||
|
4. 双击列表某 DS:视图适配到该 DS(子树)空间范围;有详情页的类型联动打开中下方详情页;三维体等无详情页类型**静默**(只适配、不报错)。
|
||||||
|
5. VE 对全部渲染物一致;坐标轴仍是空间位置度量、逐数据集色阶不变。
|
||||||
Loading…
Reference in New Issue