feat/vtk-3d-view #7

Merged
gaozheng merged 301 commits from feat/vtk-3d-view into main 2026-06-27 18:43:52 +08:00
3 changed files with 42 additions and 18 deletions
Showing only changes of commit 6e3c810dcc - Show all commits

View File

@ -64,7 +64,7 @@ f00a214 feat(data): VoxelGenerateRequest/SliceGenerateRequest DTO + toJson
2. **dict 填充**main 创建 `DatasetFieldDictionary` 并传 `new ColumnDrawer(centerWidget, &dict)`;对每个反演 dsType 调 `loadDatasetFormAsync`→`parseFieldMapping`→`dict.setFields`(装置/日期筛选才生效,现 dict=nullptr 退化不筛)。 2. **dict 填充**main 创建 `DatasetFieldDictionary` 并传 `new ColumnDrawer(centerWidget, &dict)`;对每个反演 dsType 调 `loadDatasetFormAsync`→`parseFieldMapping`→`dict.setFields`(装置/日期筛选才生效,现 dict=nullptr 退化不筛)。
3. **工具条接入**:实例化 `VtkViewToolbar` 叠加中央 QVTK信号接 sceneCtrlviewRequested/zoom/fit 接现有 c3 对应槽 :647 区axesSettingsRequested→弹 `AxesSettingsDialog`→应用坐标轴VE 控件迁工具条。 3. **工具条接入**:实例化 `VtkViewToolbar` 叠加中央 QVTK信号接 sceneCtrlviewRequested/zoom/fit 接现有 c3 对应槽 :647 区axesSettingsRequested→弹 `AxesSettingsDialog`→应用坐标轴VE 控件迁工具条。
4. **VolumeParamsDialog 扩展**:左侧勾选源 ds 树(按 GS 分组·可二次增删) + 右侧「生成位置」下拉(项目内 GS/TM默认 源单GS→该GS/跨GS→项目根)→ 填 `req.structParentId/structParentConfType` 4. **VolumeParamsDialog 扩展**:左侧勾选源 ds 树(按 GS 分组·可二次增删) + 右侧「生成位置」下拉(项目内 GS/TM默认 源单GS→该GS/跨GS→项目根)→ 填 `req.structParentId/structParentConfType`
5. **异常迁三维体段Task 11 本体)**:给 `CategorySection`(voxel 段)/`CategoryAnalysisTab` 加异常子区 + `setItemChecked`/sliceRequested/sliceDelete/sliceSave 等 API`Column3DAnalysis` :395 refreshAnomalies 控件main `refreshAnomalies`(:~397) 改用 analysisTab 5. **三维体段三级树 + 异常按归属挂体/切片Task 11 本体,已重新设计,见 spec §8 / plan Task 11****取消独立异常区**——异常作叶子挂归属实体(体/切片)下。归属链 `异常→所在切片→切片所属体`,挂载目标由「切片是否已保存成 dd_slice」决定已存挂切片、临时挂体。改 `Anomaly`(volumeDsId→remarkSourceId+remarkSourceType)、Api3d 异常 mock 按归属存查、main 创建逻辑判断切片是否保存、三维体段「体→切片/异常」三级树。多体渲染本就支持(`dsProps_` 按 dsId)`volumeOwnerDs_`=当前切片源体
6. **退役旧栏**:删 main 中 c3/ca 旧接线(:641/669-760 区)、col3D()/colAnalysis() 调用、`Column3D*` 实例;删 ColumnDrawer 的 col3D_/colAnalysis_ 成员+访问器;评估删 splitByDimensiondim2D 改轻量过滤)。 6. **退役旧栏**:删 main 中 c3/ca 旧接线(:641/669-760 区)、col3D()/colAnalysis() 调用、`Column3D*` 实例;删 ColumnDrawer 的 col3D_/colAnalysis_ 成员+访问器;评估删 splitByDimensiondim2D 改轻量过滤)。
- 切片保存/关闭(:584/623 setItemChecked)、createSlice projectId(:579/745) 随 #5/#1 一并处理。 - 切片保存/关闭(:584/623 setItemChecked)、createSlice projectId(:579/745) 随 #5/#1 一并处理。

View File

@ -1028,23 +1028,36 @@ git commit -m "feat(data): createVolume/createSlice 扩参+请求体DTO组装(mo
--- ---
### Task 11: 三维体/切片/异常段呈现(异常迁三维体段) ### Task 11: 三维体段「体→切片/异常」三级树 + 异常按归属挂体/切片spec §8
> **设计修订2026-06-24**:取消「独立异常区」的旧设计。异常不再单列、不再"随当前活动体"展示,而是作为叶子挂在它**归属的实体节点**(体 或 切片)下。归属按 `异常→所在切片→切片所属体` 链确定,挂载目标由「切片是否已保存成 dd_slice」决定见 spec §8。多体渲染本就支持`VtkSceneView::dsProps_` 按 dsId 各存 actor`volumeOwnerDs_`/`currentVolumeImage_` = 当前切片操作所基于的体(非"唯一可渲体")。
**Files:** **Files:**
- Modify: `src/app/panels/columns/CategorySection.cpp`(三维体段:异常子区)、`CategoryAnalysisTab.cpp` - Modify: `src/core/model/Anomaly.hpp``volumeDsId` → `remarkSourceId` + `remarkSourceType`
- Modify: `src/app/main.cpp`refreshAnalysis 改注入三维体段/切片段) - Modify: `src/data/api/Api3dRepository.{hpp,cpp}``saveAnomaly`/`loadAnomalyTree` mock 按 remarkSource 存/查anomalyRows 供树注入)
- Modify: `src/app/main.cpp`(创建异常时判断所在切片是否已保存 → 设 remarkSourceId/TyperefreshAnomalies 改注入三维体段树)
- Modify: `src/app/panels/columns/CategorySection.cpp` / `CategoryAnalysisTab.{hpp,cpp}`(三维体段三级树 + 切片/异常勾选·详情·删除转发)
- Test: `tests/...`remarkSource 归属判定纯函数 + Api3d 异常 mock 存查)
**实现要点:** 三维体段(`spec.id=="voxel"`)的段体下,复用现 `Column3DAnalysis` 的 3D 异常列表/显示过滤档位/单条显隐控件(迁入本段,随当前活动体展示,逻辑沿用 main.cpp:394-427 refreshAnomalies切片段`id=="slice"`)按 `parentId`=父体分组。三维体「正在生成」本期不做异步态spec §8 **Interfaces / 数据模型:**
- `enum class RemarkSourceType { Volume = 1, Slice = 2 };`(对齐后端 remark 概念)
- `Anomaly`:删 `volumeDsId`,加 `std::string remarkSourceId;`(体 dsId 或 切片 dsId+ `RemarkSourceType remarkSourceType;`
- 纯函数(可单测):`struct AnomalyMount { std::string remarkSourceId; RemarkSourceType type; };`
`AnomalyMount resolveAnomalyMount(bool sliceIsSaved, const std::string& savedSliceDsId, const std::string& volumeDsId);`
—— 已保存切片→{sliceDsId, Slice};否则→{volumeDsId, Volume}。
- [ ] **Step 1: 三维体段加异常子区**(迁 Column3DAnalysis 异常控件) - [ ] **Step 1逻辑层可单测: Anomaly 模型 + resolveAnomalyMount**
- [ ] **Step 2: 切片段按父体分组**populateDatasetList 的 parentId 建树天然支持) `Anomaly`remarkSourceId/Type全量改其引用点VtkSceneView addAnomaly/removeAnomaly 按 id 跟踪不受影响,仅 main 创建处赋值变);写 `resolveAnomalyMount` 纯函数 + 单测(已保存切片挂切片 / 临时切片挂体 两例)。**build test 绿**。
- [ ] **Step 3: build + 手动验证**(生成体→出现在三维体段;保存切片→切片段挂父体下;异常→三维体段异常子区) - [ ] **Step 2逻辑层: Api3dRepository 异常 mock 按归属存查**
- [ ] **Step 4: 提交** `StoredAnomaly` 按 remarkSourceId/Type 存;`loadAnomalyTree(sourceId)` 或新增 `anomalyRows(remarkSourceId)` 返回该体/切片下异常行DsRow 形态ddCode 自定如 `dd_anomaly`parentId=remarkSourceId供树注入`saveAnomaly` 存 remarkSource。单测挂体/挂切片分别能查回。
- [ ] **Step 3: main 创建异常逻辑**main:~502 区)
画异常时从 `interactionMgr` 取当前选中切片状态:已保存切片→其 dsId`selectSavedSlice`/`selectedSavedSliceId` 核实接口);临时切片→`volumeOwnerDs_`。调 `resolveAnomalyMount``a.remarkSourceId/remarkSourceType`。(**先核实 interactionMgr 如何区分"当前切片已保存 vs 临时"+取其 dsId**,不凭印象。)
- [ ] **Step 4UI需真实验证: 三维体段三级树**
`refreshAnomalies` 改:把异常行按 remarkSourceId 注入三维体段树——挂体异常作体节点子、挂切片异常作切片节点子切片作体节点子parentId=volumeDsId。`CategoryAnalysisTab`/`CategorySection`voxel 段)补:体/切片/异常三级建树 + 异常/切片勾选·详情·删除信号转发(迁 `Column3DAnalysis` 对应控件逻辑)。
- [ ] **Step 5: build + 手动验证**(生成体→体节点;体上画异常(切片未存)→异常挂体下;保存切片→切片挂体下;切片上画异常→异常挂该切片下;勾选/详情/删除各级生效)
- [ ] **Step 6: 提交**(分逻辑层[Step1-3] 与 UI[Step4] 两 commit前者可 build test 绿,后者 build app + 真实验证)
```bash > **波及**`Anomaly.volumeDsId` 改名会触及现有所有读取点VtkSceneView 渲染按 worldPts/plane不读 volumeDsIdmain saveAnomaly 赋值Api3dRepository StoredAnomaly——Step 1 一并改全。切片保存/关闭main setItemChecked随三级树勾选 API 一并迁。
git add src/app/panels/columns/CategorySection.cpp src/app/panels/columns/CategoryAnalysisTab.cpp
git commit -m "feat(ui): 三维体/切片/异常段呈现(异常迁三维体段)"
```
--- ---

View File

@ -59,8 +59,12 @@
│ ▾ ☐ ERT2 (GS) [右键:生成体]│ │ ▾ ☐ ERT2 (GS) [右键:生成体]│
│ ▼ 视电阻率数据 [日期▾][装置类型▾]│ │ ▼ 视电阻率数据 [日期▾][装置类型▾]│
│ ▼ 瞬变电磁数据 [日期▾] │ 无装置类型筛选 │ ▼ 瞬变电磁数据 [日期▾] │ 无装置类型筛选
│ ▼ 三维体 [日期▾] │ 已生成体(+正在生成态)+异常 │ ▼ 三维体 [日期▾] │ 体→[切片们 + 直接挂体的异常]三级树
│ ▼ 切片 [日期▾] │ 已保存切片(挂父体下) │ ▾ 体A │
│ ▾ 切片S1(挂体A) │
│ 异常a1(挂S1) │
│ 异常a2(挂体A,临时切片上画) │
│ ▼ 切片 [日期▾] │ 已保存切片(挂父体下,与三维体段切片同源)
└──────────────────────────────────────┘ └──────────────────────────────────────┘
``` ```
@ -130,9 +134,16 @@ checkedSourcesChanged
复用现有 `Api3dRepository`mock`refreshAnalysis` 合并注入机制,仅重新组织到段: 复用现有 `Api3dRepository`mock`refreshAnalysis` 合并注入机制,仅重新组织到段:
> 三维体归属由「生成位置」选择决定:默认单 GS→该 GS、跨 GS→项目根用户可改为项目内任意 **GS / TM**`structParentConfType` 可 1 或 2。后端契约 `docs/api/vtk-3d-openapi.json` 已同步至 v0.6-draft`structParentConfType` 放开 1/2 + 默认规则);客户端 `createVolume` 接真实端点时需补 `structParentId/structParentConfType`,并新增按三维体 id 查异常的 `queryException/{remarkSourceId}` 调用。 > 三维体归属由「生成位置」选择决定:默认单 GS→该 GS、跨 GS→项目根用户可改为项目内任意 **GS / TM**`structParentConfType` 可 1 或 2。后端契约 `docs/api/vtk-3d-openapi.json` 已同步至 v0.6-draft`structParentConfType` 放开 1/2 + 默认规则);客户端 `createVolume` 接真实端点时需补 `structParentId/structParentConfType`,并新增按归属实体 id 查异常的 `queryException/{remarkSourceId}` 调用。
- **三维体段**:列已生成的体(客户端 mock + 后端 `dd_voxel`),按归属(项目/GS/TM分组。**「正在生成…」状态**:现 `createVolume` 同步登记、首次 `loadVolume` 惰性插值,本期**不引入异步生成态机**、体即时出行;如需占位仅作纯展示文案、不做进度。)异常挂三维体(记忆 `vtk-3d-persistence-structure`):现 `Column3DAnalysis` 的 3D 异常列表 / 显示过滤档位 / 单条显隐,迁入三维体段内(随当前活动体展示)。
- **切片段**:列已保存切片(`dd_slice`),按父体分组(`parentId` = 所属体)。 **三维体段是「体 → 切片 / 异常」三级树****取消独立异常区**——异常不再单列,而是作为叶子挂在它归属的实体节点下):
- **三维体段**:列已生成的体(客户端 mock + 后端 `dd_voxel`),按归属(项目/GS/TM分组。**「正在生成…」状态**:现 `createVolume` 同步登记、首次 `loadVolume` 惰性插值,本期**不引入异步生成态机**、体即时出行。)体节点下挂:① 基于该体生成的**切片**子节点;② **直接挂体的异常**(见归属规则)。多体可同时勾选渲染(`dsProps_` 按 dsId 各存 actor切片/异常操作针对「当前激活体」`volumeOwnerDs_`=切片源体 `currentVolumeImage_`)。
- **异常归属(核心规则)**:异常**必基于切片**(在某切片平面上画),切片**必基于体**`SliceSpec.volumeDsId`)。查找链 `异常 → 所在切片 → 切片所属体`。挂载目标按**该切片是否已保存成 `dd_slice`** 决定:
- 切片**已保存**(是 `dd_slice` 实体)→ 异常挂**该切片**`remarkSourceType=切片``remarkSourceId=切片dsId`)。
- 切片**未保存**(临时圈定平面)→ 异常挂**切片所属体**`remarkSourceType=体``remarkSourceId=体dsId=volumeOwnerDs_`)。
- 数据模型:`Anomaly` 由原写死的 `volumeDsId` 改为 `remarkSourceId` + `remarkSourceType`(体/切片二选一),对齐后端 remark 概念。仍 mock 存储。
- **切片段**:列已保存切片(`dd_slice`),按父体分组(`parentId` = 所属体)。与三维体段内的切片子节点同源(同一批 `sliceRows`)。
体素 / 切片 / 异常的渲染、生成、保存路径不变(`VtkSceneController` / `InteractionManager` / `Api3dRepository`),只改列表的承载位置。 体素 / 切片 / 异常的渲染、生成、保存路径不变(`VtkSceneController` / `InteractionManager` / `Api3dRepository`),只改列表的承载位置。