geopro/docs/superpowers/specs/2026-06-17-vtk-3d-volume-sl...

14 KiB
Raw Blame History

VTK 三维:三维体 / 切片 / 异常 —— 数据模型与客户端交互设计

  • 日期2026-06-17
  • 范围:桌面客户端 VTK 三维视图里的「三维体模型(体素) / 切片 / 异常」三类数据及其交互。是补充需求页"三维分析"栏的落地设计。
  • 依据①《Geopro3.0 需求表.xlsx》「补充需求」页行号见引用② 与产品方就 6 个设计问题的确认;③ 现有代码。
  • 原则:缺后端端点的先本地 mock(保证功能可见可用),端点就绪后切真实;能纯客户端做的先做。

⚠ 更正2026-06-18本文档以下异常部分已被修订以此为准——实现计划见 plans/2026-06-18-vtk-3d-anomaly.md,结构铁律见记忆 vtk-3d-persistence-structure

  1. 异常挂「三维体」remarkSourceId = 三维体 ds id不挂切片§1.3 的 parentSliceId 作废)——切片是临时圈定载体,业务语义上异常属于三维体(需求 R61
  2. remarkSourceType = 标注形态1点/2线/3面/4文字不是"来源实体类型"§3 原表述更正,实证 commercial-admin/contourPage.vue:386)。接口不限定挂载实体类型,remarkSourceId 放谁 id 挂谁。
  3. 异常请求体无截图字段;补充需求 **R88「增加截图属性」**证实截图是待新增属性 → 现 mock 本地存。
  4. 摆放3D 异常的"场景控制"(树+显示过滤 R86-87+VTK 选中联动 R84+显隐+删除)放三维分析区;右侧「对象异常」面板 = 异常全集 master暂连后端 2D整链就绪后并入 3D
  5. 异常独立显隐靠 R86-87 过滤(全部显示/随GS/随数据集/全部隐藏),不被三维体勾选绑死

1. 核心数据模型

三者都是可持久化的数据集,层级关系:三维体 → 切片 → 异常

1.1 三维体VolumeModel

ddCodedd_voxel / dd_Structual3D / dd_Property3D(需求行 245/290/291

  • id / name
  • sourceDatasetIds[](源数据):一组输入数据集,用于插值生成本体(需求行 401
  • interpModel:插值模型,克里金 / IDW需求行 404
  • interpParams插值参数cellXY/cellZ/power/maxDist 等,需求行 405
  • colorScale(色阶参数,行 406
  • grid:体素网格 = ScalarVolume + origin/spacing/vmin/vmax= 现有 VolumeGrid)。
  • measure:测量数据,点数/体积(行 407派生量
  • 派生:slices[]anomalies[](汇总该体下所有切片圈定的异常,行 403

来源(行业经验):① 多条 2D 反演剖面/散点/钻孔点 → IDW/克里金插成 3D 体(最常见);② 直接 3D 采集(三维高密度等,本身即 3D单数据集sourceDatasetIds 为 1 个或多个。

1.2 切片Slice

ddCodedd_slice

  • id / name
  • parentVolumeId:所属三维体(行 389切片对象=所属三维体模型)。
  • plane:切面 = SliceSpec(轴向/原点/法向/偏移)。
  • colorScale
  • 生命周期:交互式"切片工具"是临时的(在体上实时切);保存后才成为持久化的 dd_slice 数据集,进入三维分析栏列表(行 390

1.3 异常Anomaly

  • id / name
  • parentSliceId:异常画在某切片平面上、附着于该切片(行 392 创建异常在切片右键)。
  • polygon:圈定多边形(切片平面内的坐标)。
  • screenshot + 元信息(截图大小、异常坐标,行 393
  • 向上归属:三维体详情的"异常"= 汇总该体下所有切片圈定的异常(行 403

2. 客户端交互流(需求"三维分析"栏 + VTK 视图右键)

2.1 三维分析栏(列表)

  • 按「对象 / 三维体模型 / 切片」三级树显示(行 366
  • 勾选一个或多个三维体或切片 → 显示在三维视图(行 367
  • 三维体右键(行 368375切片▸上下/前后/左右/任意)、色阶、显示/隐藏、数据详情。
  • 切片右键(行 376383保存、保存为、导出、删除、色阶、显示/隐藏、数据详情。

2.2 切片工具(行 369372, 387389

  • 上下/前后/左右切片:在三维体中心或光标位置打开水平切片工具,角度不可调
  • 任意切片:初始角度 = 当前视图 45°可任意调整。
  • 选中切片滚轮 → 沿法向往内/外推进;切片对象 = 所属三维体(行 389
  • 双击切片 → 视角调正为正视该切片(行 386/388

2.3 VTK 视图里对切片的右键(行 391399

  • 创建异常:弹异常工具,以光标拾取点为起点圈定;结束保存时弹对话框(截图大小、异常坐标),参考 Geopro1.0。
  • 保存:保存为数据集(切片数据集)。
  • 导出为图片 / 导出到 dat
  • 正视图 / 视图翻转(水平 180°) / 关闭

2.4 创建三维体(已定:客户端创建

产品确认创建三维体在客户端侧。

  • 「三维数据集」栏多选若干 3D 数据集(反演剖面)→ 菜单「生成三维体」→ 选插值模型/参数 → 客户端 IdwInterpolator 插值 → 三维体。
  • 持久化:后端无三维体端点(见 §3→ 先本地 mock内存/本地文件),端点就绪后切真实。

3. 后端依赖 vs 本地 mock已核对 web 源码 commercial-admin/src/apis

能力 现有端点 方案
展示已有三维体(取网格) 无(/model/* 只有 ResIPy 反演/雷达,无三维体网格) mock:以源数据集散点 IDW 出体(IdwInterpolator
创建三维体(插值) 无(无三维空间插值端点) 客户端做IdwInterpolator持久化 mock
三维体/切片持久化 无写端点 mock:内存/本地存;端点就绪后切真实
切片创建/交互 — 纯客户端 已有(SliceTool/InteractionManager
切片保存/另存/导出/删除 无切片端点 保存/删除 → mock(内存);导出图片/dat → 客户端做(截图/写文件)
异常读取 POST /exception/queryExceptionTreequeryException/queryExceptionByTmObjectId 接真实
异常新增 POST /business/exception 接真实
异常更新 PUT /business/exception 接真实
异常删除 DELETE /business/exception/{exceptionId} 接真实
异常类型 GET /exceptionType/queryExceptionTypeByProjectIdAndType/{projectId}/{remarkSourceType}/exceptionType/getDetail/{id} 接真实
异常体(exceptionConsortium) POST/PUT /exceptionConsortium/page/export/getDetail/{id} 接真实
任务记录/可用任务 /model/task/page 是反演任务,非三维分析任务) mock

异常新增请求体web 实证 datasetInfo/index.js:212

POST /business/exception

{ exceptionName, exceptionTypeId, location:{...圈定坐标...},
  projectId, remarkSourceId, remarkSourceType, remark }
  • remarkSourceId / remarkSourceType:异常所附着的对象(本场景=切片数据集 id + 其类型)。
  • location:圈定多边形坐标。截图:保存对话框含截图(行 393上传方式参考 exceptionInfos/modalNewException.vue
  • 更新:PUT /business/exception { id, exceptionName, remark };删除:DELETE /business/exception/{exceptionId};详情:GET /business/exception/getDetail/{exceptionId}

4. 代码现状(落点)

  • 维度归类:LocalSample3dRepository::dimensionOfdd_voxel/Structual3D/Property3D/section/inversion → 3Ddd_slice → Analysis
  • 体素:core::IdwInterpolatorIDW 现成)、render::buildVoxel/VoxelActor(体绘制)、VoxelFromScatters(散点→体)。
  • 切片交互:render::interact::SliceTool + InteractionManager(已可在体素 image 上切,含上下/前后/左右/任意)。
  • 仓储接口:I3dSceneRepository 已定义 loadVolume / createSlice / saveSlice / deleteSlice / loadAnomalyTree / saveAnomaly / deleteAnomaly / deleteAnomalyGroup / loadTaskRecords / loadUsableTasks
    • LocalSample3dRepository:以上多为内存 mockslices_/anomalies_ map
    • Api3dRepository:以上多为 stub(kNotReady) — 真实数据未接。
  • UIColumn3DAnalysis 已定义信号sliceRequested/colorScaleRequested/visibilityToggled/detailRequested/sliceSave|SaveAs|Export|Deletemain.cpp 仅接了 sliceRequested + detailRequested,其余未连。

5. 待产品确认(更新 2026-06-17

  1. 创建三维体在客户端还是平台?已定:客户端§2.4)。
  2. 后端三维体/切片/任务端点时间表? → 暂未知。当前 web 源码三维体网格、三维插值、切片、三维分析任务端点 → 这些先 mock(保持 I3dSceneRepository 接口不变,端点就绪后仅换实现)。
  3. 异常写端点?已找到§3POST/PUT/DELETE /business/exception + 类型/异常体一整套 → 异常接真实,不 mock。

剩余待确认(次要):

  • 异常保存对话框的截图上传方式/字段(参考 exceptionInfos/modalNewException.vue,落地时细化)。
  • 三维体/切片本地 mock 的持久化形态(纯内存 vs 本地文件,影响重启后是否还在)。

6. 实现拆解(对应"剩余工作" #2#6缺端点先 mock

按依赖与价值排序:

  1. 三维体mock 渲染):把当前勾选/源数据反演剖面散点 → IdwInterpolatorVolumeGridVoxelActorApi3dRepository::loadVolume 由 stub 改为"取源数据散点 + IDW"mock。→ 解锁三维体显示 + 切片有可切对象。
  2. 切片交互接通三维体:体素就位后,三维体右键"切片▸"已能创建切片(现有 SliceTool。补选中切片滚轮推进、双击正视。
  3. 切片保存/另存/导出/删除:保存/删除 → Api3dRepository 改内存 mock同 LocalSample导出图片(截图)/dat(写文件) → 客户端实现。VTK 视图切片右键菜单接线。
  4. 异常:切片右键"创建异常"→ 圈定工具 + 保存对话框(截图/坐标)。全套接真实端点:新增 POST /business/exception、更新 PUT /business/exception、删除 DELETE /business/exception/{id}、读 queryException*/queryExceptionTree、类型 exceptionType/*、异常体 exceptionConsortium/*remarkSourceId/Type 填切片数据集。
  5. 分析栏右键菜单接线:色阶、显示/隐藏(纯客户端)、切片保存/另存/导出/删除(接 #3
  6. 三维体/切片/异常详情:数据详情栏展示源数据/插值参数/色阶/测量(点数·体积)/异常列表。

每步:客户端能做的先做、缺端点的内存 mock 留出可替换缝(保持 I3dSceneRepository 接口不变,仅换实现)。


7. 三维体持久化策略与存储结构2026-06-17 定)

7.1 策略:参数为准 + 明细可选缓存 + 缺则惰性重算

  • 保存
    • 必存:插值参数(源数据引用 + 插值模型/参数 + 色阶)+ 网格规格 GridSpec(origin/spacing/dims)。
    • 可选存网格明细值体素标量nx·ny·nz
  • 加载
    • 有明细 → 直接渲染明细。
    • 无明细 → 按参数把值重算填入已存的 GridSpec(坐标系固定),再渲染。
  • 理由:参数小且可复现(详情面板要展示);明细贵、但稳定一致;GridSpec 必存以锚定切片/异常坐标(它们定义在体网格坐标系上,重算必须落在同一规格里,否则错位)。

7.2 何时建议存明细

体的情形 建议
带切片/异常 存明细(与源数据生命周期解耦,重算变形风险归零)
网格大 / 插值慢 存明细(避免每次加载实时重算的卡顿)
纯展示、源数据稳定、网格小 可只存参数(省存储),加载时重算

7.3 重算路径的两个前提UI/逻辑需兜住)

  1. 源数据仍在且可取:源数据集被删/改 → 重算失败或结果变 → 应回退提示 / 阻止。
  2. 算法确定性:同参数同输入 → 同结果IDW 确定);算法升级时旧体优先用已存明细,避免变形。

7.4 存储结构(字段定义,驱动实现)

三维体元数据(必存,进数据集元数据)VolumeBuildParams

  • sourceDatasetIds[]:源数据集 id 列表。
  • interpModel:枚举 IDW / Kriging。
  • interpParams{ cellXY, cellZ, power, maxDist, ... }(按模型)。
  • colorScaleId 或内联色阶。
  • gridSpec{ ox, oy, oz, dx, dy, dz, nx, ny, nz }必存,锚定坐标)。
  • vmin, vmaxmeasure{ points, volume }(派生,可缓存)。

三维体明细(可选,进数据集数据文件)

  • valuesScalarVolumenx·ny·nz 标量maxDist 外为 NaN=空)。

与现有代码的关系

  • data::VolumeGrid = { ScalarVolume vol; origin[3]; spacing[3]; vmin; vmax } ≈ "明细 + 规格(部分)"。
  • 落地改造:拆出 VolumeBuildParams(含 GridSpec)为必存元数据;volvalues为可选。I3dSceneRepository::loadVolume 返回时:若有 values 直接给 VolumeGrid;若无,则用 VolumeBuildParams 现场 IdwInterpolator 重算出 vol 再给(坐标用存好的 gridSpec)。
  • mock 阶段:客户端 IDW 同时产出 params(含 spec) 与 values两者本地存接口签名不变后端就绪后元数据走数据集属性、values 走数据文件。