geopro/docs/superpowers/specs/2026-06-23-gpr-volume-A-who...

100 lines
7.4 KiB
Markdown
Raw Permalink 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.

# GPR 三维体 · 方案 A整卷上纹理不用金字塔复用现有管线最简基线
- 日期2026-06-23
- 范围:把 GPR探地雷达阵列数据插值成三维体并在 VTK 中渲染/切片,**直接复用现有剖面三维体管线**,整卷一次性进显存,不做分块/金字塔/核外。
- 定位:三选一中的**最小改动基线**。用于评估"现有架构原样接雷达,能做到什么、卡在哪"。
- **⚠ 评审结论2026-06-23opusA 不应作为独立交付步,建议并入 B。** 唯一值得从 A 单独先做的是"三方案共有的地基"§2。`double`+400³+暴力 IDW 三条硬约束使 A 产出的 GPR 体既无业务分辨率(沿线被强制粗化到 5.5m vs 物理 5cm、又无法落盘秒开。详见 §5/§6。
- 测试数据明星路450MHz 阵列 GPR14 通道,每道 821 采样,单线 ~45306 道20 线int16合计 13.6GB;路长 2223m测幅 1.37m,深 ~8m。
---
## 1. 设计意图
不引入任何新渲染/存储机制。把雷达数据**喂进现有体素管线**,让它走和反演剖面三维体完全一样的路:
```
.iprb/.iprh → PointSet → core::IdwInterpolator → ScalarVolume(double)
→ data::VolumeGrid → render::buildVoxel → vtkSmartVolumeMapper整卷进显存
切片render::interact::SliceToolvtkImagePlaneWidget / vtkImageResliceCPU 重采样)
持久化VolumeBuildParams参数必存+ 可选明细缓存(现内存 mock
```
现有落点(实证):
- `core::ScalarVolume` = `std::vector<double>`,行优先(`src/core/model/Field.hpp:8-26`)。
- `render::buildVoxel``vtkImageData`+`vtkDoubleArray`+`vtkSmartVolumeMapper`,整卷上传(`src/render/actors/VoxelActor.cpp:41-79`)。
- 体素维度上限 `kMaxVolumeDim = 400``src/core/algo/VolumeBuilder.hpp:8`)。
- 切片 CPU 重采样(`src/render/interact/SliceTool.cpp:24-39`)。
- 插值 `IdwInterpolator`,单线程三重循环,且**无空间索引——每体素全点集线性扫描O(体素数×点数) 暴力**`src/core/algo/IdwInterpolator.cpp:15-33`,评审实证)。雷达级点集下即便 400³ 也是分钟级甚至卡死,不只是"偏慢"。
- 持久化 `Api3dRepository::StoredVolume`,纯内存(`src/data/api/Api3dRepository.hpp:112-119`),重算逻辑已就绪(`Api3dRepository.cpp:212-225`)。
- **注意(评审)**:现有 `loadVolume` 的散点来源硬绑 `loadSection`/`appendGridPoints`ERT 反演帘面,`Api3dRepository.cpp:146-171`**雷达没有现成喂入路径**。"复用现有管线"实际仍须新写 GPR→`buildVolume` 接入§2 已含§1 流程图的"原样复用"措辞偏乐观。
---
## 2. 新增工作(雷达接入,三方案共有的地基)
A/B/C 都绕不开这块A 用最朴素实现:
1. **`.iprb`/`.iprh` 解析器**(新):`.iprh` 文本头取 `SAMPLES/LAST TRACE/CHANNELS/TIMEWINDOW/SOIL VELOCITY/DISTANCE INTERVAL``.iprb` 读 int16 B-scan`samples × traces`,校验 `samples×traces×2 == 文件大小`)。
2. **地理配准**`.ord` 取 14 通道横向偏移;`.gps`/`.cor` 取每道经纬度/RTK深度 = `time × soilVelocity / 2`
3. **GPR→PointSet 适配器**:把"14 通道 × N 道 × 821 采样"摊成 `PointSet{x,y,z,v}`(局部坐标)。**注意横向只有 14 个真实样本**,是稀疏维。
4. **数据集接入**:新增 ddCode`dd_gpr_volume`),在维度分类(`Api3dRepository.cpp:30-45`、`LocalSample3dRepository.cpp:43-58`)归 3DDTO 解析器放 `src/data/dto/`
---
## 3. 关键约束与后果A 的硬边界)
现有管线是 **double + 400³ 上限**。这两条直接决定 A 能做什么:
| 约束 | 数值 | 后果 |
|---|---|---|
| 标量 dtype | `double`8 字节/体素) | 同样体素数,内存是 int16 的 **4 倍** |
| 维度上限 | 400³ | 整卷 ≤ 400³×8 ≈ **512MB**;放不下全路段 |
| 整卷进显存 | 一次性 | 体大小受限于显存 |
| IDW | 单线程 + 无空间索引暴力 | 大点集插值分钟级/卡死(明星路单线 ~5亿采样点级 |
> **`fitAxis` 行为(评审实证 `VolumeBuilder.cpp:16-26`**:格数超 400 时**不裁剪范围**,而是 `outCell=ext/(400-1)` 把 400 格摊满整个包络。所以 A 不是"丢掉远端",而是"强制粗化"——沿线细节被低分辨率抹平。
**全路段在 A 下做不到原始分辨率。** 明星路需 ~22000(沿线)×270(横)×400(深),远超 400³。在 A 下只能:
- **重度降采样到 ≤400³**:沿线 2223m/400 ≈ 5.5m 网格 → 沿线细节全毁;或
- **按单条测线/短段分别建小体**(单线降到 400³ 仍偏粗),多体并排显示(类似现有 2D 足迹平铺)。**但**评审20 体 × 400³ × double ≈ 10GB 整卷同驻显存,比单大体更易爆显存;且各体独立 `GridSpec`/origin**跨体的全路段连续切片做不到**(用户想沿全路一刀切无法实现)。
---
## 4. 持久化(沿用 2026-06-17 §7 策略)
- **必存**`VolumeBuildParams`(源数据引用 + 插值模型/参数 + 色阶)+ `GridSpec`origin/spacing/dims锚定切片/异常坐标)。
- **可选明细**`ScalarVolume`(double)。A 阶段仍是内存 mock`StoredVolume.cachedGrid`**未真实落盘**——这是 A 与用户"保存插值后体"诉求的**主要差距**。
- 用户要的两种保存:①参数 ②插值后明细 —— A 的 ②目前只有内存缓存,需补一段最朴素的 double 体落盘raw + sidecar才算满足但 double 全路段落盘巨大,不实用。
---
## 5. 评估
**优点**
- 改动最小:渲染/切片/异常/详情**全部现成**,只加雷达解析与适配。
- 路径已验证,风险低,可最快出"雷达能进三维场景"的可见效果。
**缺点/限制**
- `double` + 400³ → **撑不起全路段原始分辨率**,只能粗览或分段小体。
- 明细落盘不实用double 体积过大),用户"算一次秒开"诉求难真正成立。
- 单线程 IDW 在雷达量级偏慢。
- 把结构化的雷达数据(沿线/深度本就规则)当无结构散点做 3D IDW**算力浪费**(见方案 B 的结构化插值优化)。
**适用**
- 单条短测线 / 粗分辨率概览 / 快速打通链路的第一步。
- **不适合**作为全路段完整体验的最终方案。
---
## 6. 工作量与落地顺序
1. `.iprb`/`.iprh` 解析 + 地理配准 + GPR→PointSet地基~中)。
2. 雷达 ddCode 接入维度分类 + DTO~小)。
3. 直接复用 `IdwInterpolator`/`buildVoxel`/`SliceTool`,按 ≤400³ 降采样建体(~小)。
4. 可选double 明细落盘最朴素实现(~小,但不推荐用于全路段)。
**结论(修订,评审定)****no-go作为独立交付步并入 B。** A 没有任何 B 不需要的独立资产,渲染/切片/异常/持久化骨架 A、B 共享地基§2也共享。`double`+400³+暴力 IDW 三条硬约束使 A 的 GPR 产物既无业务分辨率、又无法落盘秒开,连"最小基线该兑现的可用产物"都达不到。
- **唯一抽出先做的独立里程碑 = §2 共有地基**`.iprb`/`.iprh` 解析 + 14 通道配准 + GPR→PointSet + ddCode 接入A/B/C 都要。
- "复用 double+400³ 管线建退化体"这一步**不单独交付**,直接在 B 的 int16+结构化建体上落地,避免做一遍注定被 B 推翻的降级体。
- **全路段完整体验走 B。**