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

6.0 KiB
Raw Permalink Blame History

设计:三维体/切片 数据详情(只读属性对话框)

日期 2026-06-18。分支 feat/vtk-3d-view。收尾/打磨项 #6docs/superpowers/HANDOFF-vtk-3d.md §4 末「下一步候选」)。 异常详情已用对话框做掉(AnomalyPropertiesDialog),本设计为三维体 / 切片补同类只读详情。

1. 目标与范围

三维分析栏右键「数据详情」时,弹出只读属性对话框展示该三维体 / 切片的元数据与统计。

  • 形态:只读 QDialog(仿 AnomalyPropertiesDialog),非停靠面板页签。
    • 取舍理由:现成 DatasetDetailController/Panel 绑定 2D 的 IAsyncDatasetRepository + chartRegistry而体/切片数据在 Api3dRepository(独立 3D 仓储),硬接需跨仓储桥接 + 新策略/视图,代价大、动共享设施风险高。对话框与刚落地的异常详情 UX 一致、零侵入 2D 管线。
  • 内容范围:参数/位姿随时可取;三维体统计(值域/测点数/范围体被生成loadVolume 缓存)后才显示,未生成显「—(生成/渲染后可见)」。

2. 架构与新增文件

仿 src/app/AnomalyPropertiesDialog.{hpp,cpp}QFormLayout + QLabel 只读表:

文件 职责
src/app/VolumePropertiesDialog.{hpp,cpp} 三维体属性(参数 + 统计)
src/app/SlicePropertiesDialog.{hpp,cpp} 切片属性(位姿 + 参数)

两个对话框各自独立、构造即填充、exec() 模态,无网络、无加载态。

3. 数据获取

只改具体类 src/data/api/Api3dRepository.{hpp,cpp}接口 I3dSceneRepositoryLocalSample3dRepository 不动main.cpp 持有具体 scene3dRepo,见 main.cpp:266全程直接用

3.1 三维体 getter新增

// Api3dRepository.hpp 内嵌结构 + 方法
struct VolumeInfo {
    VolumeBuildParams params;
    std::string name;
    bool loaded = false;            // cachedGrid 是否已就绪(= loadVolume 跑过)
    // 以下仅 loaded 时有效:
    double vmin = 0.0, vmax = 0.0;  // 来自 cachedGrid
    int nx = 0, ny = 0, nz = 0;     // 网格维度
    double dx = 0, dy = 0, dz = 0;  // 单元间距(来自 cachedGrid.spacing
    std::size_t pointCount = 0;     // 聚合后参与插值的散点数
};
bool volumeInfo(const std::string& dsId, VolumeInfo& out) const;  // 非体返回 false
  • loadedStoredVolume::cachedGrid.has_value();统计字段从 cachedGridvmin/vmax、vol.nx()/ny()/nz()spacing)填。
  • 测点数持久化StoredVolumestd::optional<std::size_t> pointCount,在 finalizeVolume(散点聚合完成处)写入 pts.v.size()volumeInfo 透出。

3.2 切片数据

复用已有 bool sliceSpec(const std::string& dsId, SliceSpec& out) constmain.cpp 已在用)取位姿;名称用 detailRequested 信号已携带的 name,不新增 getter。

4. 触发与接线(main.cpp

detailRequested 仅来自三维分析栏(Column3DAnalysis,项非体即切片;右键菜单「数据详情」已接,无需改 Column3DAnalysis现连接 detailCtrl.openDataset(对 3D dsId 会降级失败)。改为按 ddCode 分派:

QObject::connect(ca, &Column3DAnalysis::detailRequested, &window,
    [&window, scene3dRepo](const QString& dsId, const QString& ddCode, const QString& name) {
        if (ddCode == QStringLiteral("dd_slice")) {
            I3dSceneRepository::SliceSpec sp;
            if (scene3dRepo->sliceSpec(dsId.toStdString(), sp)) {
                SlicePropertiesDialog dlg(name, sp, &window); dlg.exec();
            }
        } else {  // dd_voxel
            Api3dRepository::VolumeInfo info;
            if (scene3dRepo->volumeInfo(dsId.toStdString(), info)) {
                VolumePropertiesDialog dlg(name, info, &window); dlg.exec();
            }
        }
    });

src/app/CMakeLists.txt 加两个新 .cpp

5. 内容字段

三维体(VolumePropertiesDialog

  • 名称
  • 源数据集(sourceDatasetIds,逗号连接)
  • 插值模型IDW / Kriging+ 幂指数IDW 时显 power
  • 网格间距(XY=cellXY m Z=cellZ m
  • 超距(maxDist m
  • 色阶来源(colorScaleId,空显「首个源数据集」)
  • 统计loaded 才有,否则全显「—(生成/渲染后可见)」):
    • 值域(vmin ~ vmax
    • 网格(nx × ny × nz
    • 测点数(pointCount
    • 范围(nx·dx × ny·dy × nz·dz 米)

切片(SlicePropertiesDialog

  • 名称
  • 所属三维体(volumeDsId
  • 轴向0 上下 / 1 前后 / 2 左右 / 3 任意)
  • 平面三点 Origin / Point1 / Point2(x, y, z)2 位小数)
  • 色阶来源(colorScaleId,空显「首个源数据集」)

切片不含统计项:采样分辨率/值域来自渲染时的切面网格,仓储层不持久化(StoredSlice 仅存 spec+name)。回写渲染产物属额外 plumbing守 YAGNI 不做。位姿/参数已完整。

6. 错误处理

  • volumeInfo / sliceSpec 取不到(非体/非切片)→ 返回 false不弹空对话框理论不发生触发来自该行
  • 统计未就绪 → 占位「—(生成/渲染后可见)」,不报错。

7. 测试

  • 新增 gtesttests/ 内 Api3dRepository 测套,若无则新建)覆盖 volumeInfo
    • createVolume 后、loadVolume 前:volumeInfo 返回 true、params/name 正确、loaded=falsepointCount=0
    • loadVolume 成功后:loaded=truevmin<vmaxnx/ny/nz>0pointCount>0
    • 非体 dsId返回 false。
  • 对话框为纯只读 UI无逻辑分支不做单测靠 GUI 实测Claude 无法 GUI 验证,交用户)。

8. 影响面 / 不变量

  • 接口 I3dSceneRepositoryLocalSample3dRepository 零改动 → 真实后端就绪后切换不受影响。
  • finalizeVolume 仅多写一个 pointCount,不改插值/渲染行为。
  • 不与 VTK 三维视图交互(详情只读查阅,职责清晰)。