geopro/docs/superpowers/specs/2026-06-29-radar-bscan-deve...

27 KiB
Raw Blame History

雷达 B-Scan 详情页开发方案 — 2026-06-29

状态方案阶段待确认事项见第7节。确认后即可按第6节顺序开发。 基线分支:radar(基于 fix/3d-volume-blanking-mask)。


1. 一句话架构

B-Scan 详情页 = 独立 ADS Dock 工作区(非底部页签),内部自含:

  • 顶部控制栏23+ 处理参数 + 色阶/对比度/比例/模式切换)
  • 主体 B-Scan 剖面图(灰度/彩色/Wiggle 可切换,支持框选异常、滚轮缩放、悬停读值)
  • 右侧内嵌 A-Scan 单道波形(点击剖面任意位置联动)
  • 右侧面板对象属性(采集参数只读表)+ 对象异常(异常列表+操作)

数据流:本地文件/后端 → io/gpr 解析 → core/gpr_proc 信号处理管线 → BScanProfileView 自渲染QImage + QPainter非 Qwt/VTK→ 参数调整即时重绘


2. 关键决策与理由

决策 选择 理由
容器 独立 ADS CDockWidget(类似 MapViewPanel 底部 DatasetDetailPanel 空间(~200-300px高无法承载密集控制栏+大面积剖面交互+A-Scan波形。独立 dock 可最大化利用屏幕,且雷达分析是专业深度工作流,值得独占工作区。
B-Scan 渲染 QImage + QPainter 自绘(非 Qwt/VTK B-Scan 是二维 raster 图像traces × samples 的像素矩阵),非曲线/等值线。Qwt 的 QwtPlot 面向函数曲线,不适合 rasterVTK 过重且离屏渲染延迟高。QImage 直接操作像素,处理管线输出 std::vector<float> → 映射色阶 → setPixel/scanLine,足够快且可控。
A-Scan 渲染 QwtPlot 曲线(复用现有 Qwt 基础设施) A-Scan 是单道振幅-深度折线Qwt 的 QwtPlotCurve 完全匹配,且项目已链 Qwt。
处理管线 前端 C++ 实时计算(内存常驻 + 多线程) 用户明确要求"几分钟处理完公里级数据"。全量数据32MB/测线)驻内存,参数调整只重跑相关处理节点(脏链追踪),避免全量重算。重负载节点(滤波、偏移、反褶积)丢 QtConcurrent::run 后台线程,主线程保持 UI 响应。
数据入口 先本地文件(.iprb/.iprh/.ord后接后端 API API 和 ddCode 尚未设计。M1 先走本地文件入口验证处理管线和 UI后端契约确定后data 层补 loadAsync 分发即可,视图层不动。
异常标注 前端本地状态M1+ 后端同步接口M2 前端用 std::vector<GprAnomaly> 驻内存,支持增删改+截图关联;后端 API 就绪后,在 data 层补 saveAnomalies/loadAnomalies,控制器层补上传逻辑。

3. 数据流(端到端)

[用户双击雷达数据集]
  DatasetListPanel::itemDoubleClicked
    main.cpp ──► 判断 ddCode == "dd_gpr_data"(或雷达相关 ddCode
       │
       ▼ 走独立路由(不走 DatasetDetailController 的页签引擎)
    RadarWorkbenchController::openSurvey(dsId, ddCode, dsName, filePath)
       │
       ▼ 如果本地文件已缓存,直接取;否则发请求/读本地文件
    [io/gpr 层] readIprb / assembleGprSurvey / 未来 readRd3
       │ 输出core::GprSurveyntraces×samples×channels 的 double 值数组)
       ▼
    [core/gpr_proc 层] GprProcessingPipeline
       输入:原始 B-scan某通道的 traces×samples+ ProcessingParams
       节点链ZeroTime ──► ZeroDrift ──► BackgroundRemove ──► Gain ──► Bandpass
              ──► Smooth ──► TraceBalance ──► SampleBalance ──► Hilbert
              ──► Migration ──► TopoCorrect ──► Resample ──► PredictiveDecon
       输出processed B-scanfloat 矩阵,与输入同维度)
       │
       ▼ 参数变更时只重算脏节点下游(缓存各节点输出)
    [app/panels/radar/ BScanProfileView]
       - 原始/处理后数据各一份(或处理后实时生成)
       - ColorMapperfloat 值域 → ColorScale → RGBA 像素
       - QPainter画像素矩阵 + 网格线 + 异常框 + 十字准星
       - 交互:滚轮缩放/平移变换矩阵、框选QRectF 世界坐标、悬停mouseMove 转采样/道号)
       │
       ▼ 点击剖面位置
    [A-Scan 子视图] AScanWaveformViewQwtPlotCurve 实时更新)
       │
       ▼ 右侧面板
    [ObjectAttrPanel] 采集参数只读表(走现有 KeyValueView
    [ObjectExceptionPanel] 异常列表(复用现有异常列表面板逻辑)

注意:此路由绕过 DatasetDetailController / ChartStrategyRegistry / DetailViewFactory 的页签引擎。雷达详情页是独立专业工作区,非通用页签容器。未来若需把雷达也纳入底部页签(如只展示属性表格),可再补一个 Table 页签走现有引擎。


4. 分层设计

4.1 core/gpr_proc — 信号处理管线(纯 C++17零 Qt/VTK

设计目标可独立单元测试、可脏链追踪、SIMD/多线程友好。

核心抽象

// 处理节点接口
class IGprProcNode {
public:
    virtual ~IGprProcNode() = default;
    // 输入输出:行主序 float 矩阵 [trace][sample],尺寸由 meta 描述
    virtual void process(const float* in, float* out, const GprTraceMeta& meta) = 0;
    virtual QString name() const = 0;
};

// 管线:持有节点链,支持脏链追踪与缓存
class GprProcessingPipeline {
public:
    void setNodeEnabled(const QString& name, bool on);
    void setNodeParams(const QString& name, const QVariantMap& params);
    // 执行管线:从原始数据到处理后数据,只重算脏节点
    std::vector<float> run(const std::vector<float>& raw, const GprTraceMeta& meta);
    // 获取指定节点的输出(用于调试/中间结果展示)
    const std::vector<float>& nodeOutput(const QString& name) const;
private:
    std::vector<std::unique_ptr<IGprProcNode>> nodes_;
    std::unordered_map<QString, std::vector<float>> cache_;
    std::unordered_set<QString> dirty_;
};

节点清单(按用户需求的 20+ 种处理)

# 节点名 类名 复杂度 说明
1 时间零点校正 ZeroTimeCorrectionNode 自动/手动模式;自动:前 N 采样内噪声σ倍数阈值找起跳
2 去除零漂 ZeroDriftRemovalNode DC(整道均值) / Sliding(滑动窗口均值)
3 背景去除 BackgroundRemovalNode MeanAverage(多道平均) / SingularityFilter(SVD)
4 增益 GainNode AGC / SphericalDiffusion / AbsorptionCompensation 等
5 带通滤波 BandpassFilterNode FFT 实现(需 FFTW 或自实现 Cooley-Tukey自动/手动频带
6 剖面平滑 SmoothingNode 2D 均值/高斯滤波,可分别开关横向/纵向
7 道间均衡 TraceBalanceNode Global(全剖面RMS) / Local(滑动窗口RMS)
8 道内增益 SampleBalanceNode TVG-like深度方向滑动RMS均衡
9 希尔伯特变换 HilbertTransformNode 包络/瞬时相位/瞬时频率FFT-based 或时域 FIR
10 偏移处理 MigrationNode Kirchhoff / F-K 偏移;需速度模型
11 速度分析 VelocityAnalysisNode 双曲线拟合 → 速度谱;交互式拾取(后续迭代)
12 地形校正 TopoCorrectionNode 高程→时深转换,波形整体平移/拉伸
13 里程归一化 DistanceNormalizationNode 打标处插桩号,固定道间距重采样
14 数据重采样 ResamplingNode 横向/纵向独立,线性插值
15 预测反褶积 PredictiveDeconNode 自相关 → Levinson-Durbin → 预测误差滤波
16 道编辑 TraceEditNode 废道删除/置零(前端 UI 传入废道索引列表)
17 剖面反向 ReverseTraceNode 道序反转

M1 阶段实现优先级

  • P0必须1, 2, 4(基础增益), 5(简化版), 6, 7, 8, 14, 16, 17
  • P1重要3, 4(球面扩散), 9, 12, 13
  • P2后续迭代10, 11, 15计算密集需更多测试数据验证

性能策略

  • 节点输出缓存:run() 时比较参数 hash未变则直接返回缓存。
  • 并行化:各道独立处理(零漂、增益、均衡等)用 tbb::parallel_forstd::execution::parC++17
  • FFT带通滤波、希尔伯特变换需 FFT。可用 fftw3vcpkg 有或自实现基2-FFT数据量 516 采样点,很小,自实现也可接受)。推荐先自实现避免引入新依赖,性能不足再切 FFTW。

4.2 app/panels/radar/ — B-Scan 视图层QtWidgets

核心组件

BScanWorkbenchADS::CDockWidget 外壳)
├── BScanProfileViewQWidget自绘主体
│   ├── 顶部工具栏:测线选择/通道选择/色阶/对比度/XY比例/显示异常/各处理参数按钮
│   ├── BScanCanvasQWidget自绘核心
│   │   ├── 原始数据缓存std::vector<float> raw_
│   │   ├── 处理后数据缓存std::vector<float> proc_或实时从管线取
│   │   ├── ColorMapperfloat min/max → ColorScale → QRgb
│   │   ├── ViewTransform世界坐标 ↔ 屏幕坐标:平移/缩放矩阵)
│   │   ├── 交互状态机Idle / Panning / Zooming / MarqueeSelect / Hover
│   │   └── 异常标注列表std::vector<BScanAnomaly>,世界坐标存储)
│   └── AScanWaveformViewQWidget内嵌右侧
│       └── QwtPlot + QwtPlotCurve单道波形实时刷新
├── ObjectAttrPanel右侧面板上— 复用现有 KeyValueView
└── ObjectExceptionPanel右侧面板下— 复用现有异常列表逻辑

BScanCanvas 渲染管线

void BScanCanvas::paintEvent(QPaintEvent*) {
    QPainter p(this);
    // 1. 背景
    p.fillRect(rect(), Qt::black);
    // 2. 根据当前标签(rawdata/proc_data_1)选择数据源
    const auto& data = (currentTab_ == Raw) ? raw_ : proc_;
    // 3. 可见区域裁剪:由 viewTransform_ 计算当前窗口对应的 [t0,t1)×[s0,s1)
    // 4. 逐像素/逐块映射float → ColorScale → QRgb
    //    - 若缩放比小(全景),聚合多采样取平均后上色(防混叠)
    //    - 若缩放比大(局部),单采样直接上色
    // 5. 画网格线(里程/深度刻度,根据缩放动态抽稀)
    // 6. 画异常框(世界坐标 → 屏幕坐标,红框+标签)
    // 7. 画十字准星(鼠标悬停位置)
    // 8. 画打标线(如果有打标数据)
}

交互设计细节

交互 实现 坐标系
左键拖动 平移(修改 viewTransform 的 offset 屏幕 delta → 世界 delta
滚轮 以鼠标位置为中心缩放(修改 viewTransform 的 scaleX/scaleY 屏幕锚点 → 世界锚点保持不动
左键框选 释放时生成 BScanAnomaly(世界坐标矩形) 屏幕 rect → 世界 rect
鼠标悬停 状态栏显示:道号、里程、深度、振幅值;同时更新 A-Scan 屏幕 pos → 道号 t + 采样 s
双击异常框 弹出异常编辑对话框(类型/深度/尺寸/备注)
右键菜单 切换 X 轴显示:道号 / 距离 / 里程;切换 Y 轴:时间 / 深度

Wiggle 模式:点击按钮切换。

  • Off正常灰度/彩色 raster 图。
  • On每道画波形线振幅→水平偏移正右负左填充正/负区域为不同颜色,背景透明/白色。参考地震勘探 wiggle trace 标准画法。

4.3 controller — 雷达工作区控制器

新增 RadarWorkbenchController(独立于 DatasetDetailController

class RadarWorkbenchController : public QObject {
    Q_OBJECT
public:
    void openSurvey(const std::string& dsId, const std::string& ddCode,
                    const QString& name, const QString& filePath);
    void switchChannel(int channelIndex);
    void setProcessingParams(const GprProcessingParams& params);
    void runProcessing();  // 触发管线,完成后 emit processedReady
    void saveAnomalies();  // M2调后端 API 上传异常
signals:
    void surveyLoaded(const GprSurveyInfo& info);      // 采集参数、通道列表
    void rawDataReady(const std::vector<float>& data, const GprTraceMeta& meta);
    void processedReady(const std::vector<float>& data, const GprTraceMeta& meta);
    void anomalyListChanged(const std::vector<GprAnomaly>& anomalies);
    void progress(int percent, const QString& stage);  // 长时间处理进度
};

5. 数据模型新增

5.1 core/model/gpr_proc/(新建目录)

// GprTraceMeta.hpp — 单通道剖面的元数据(纯 C++17
struct GprTraceMeta {
    int ntraces = 0;
    int samples = 0;
    double dx = 0;        // 道距 (m)
    double dz = 0;        // 采样间隔 (m 或 ns)
    double x0 = 0;
    double z0 = 0;
    bool zIsTime = false; // true=时间(ns), false=深度(m)
    double velocityMPerNs = 0.12; // 雷达波速,时深转换用
};

// GprProcessingParams.hpp — 全部处理参数的结构化定义
struct GprProcessingParams {
    // 零点校正
    struct ZeroTime { bool autoDetect=true; int cutSamples=30; int frontSearchWindow=180; double noiseSigmaMultiple=3.0; } zeroTime;
    // 零漂
    enum class ZeroDriftMode { DC, Sliding };
    struct ZeroDrift { ZeroDriftMode mode=ZeroDriftMode::Sliding; int slidingWindowSamples=100; } zeroDrift;
    // 背景去除
    enum class BgMode { MeanAverage, SingularityFilter };
    struct Background { BgMode mode=BgMode::MeanAverage; int averageTraceCount=301; double singularityThreshold=1.8; } background;
    // 增益(简化:先实现 SphericalDiffusion
    struct Gain { bool enableSpherical=true; bool enableAbsorption=true; double velocityMPerNs=0.12; double referenceDepthM=0.01; double exponent=1.5; double absorptionBeta=1.0; double maxGain=30.0; } gain;
    // 带通滤波
    struct Bandpass { bool autoFreq=true; double lowFreqHz=1000; double highFreqHz=100; double antennaFreqMHz=200.0; } bandpass;
    // 平滑
    struct Smooth { int smoothWindow=2; bool verticalSmooth=true; bool horizontalSmooth=true; } smooth;
    // 道间均衡
    enum class TraceBalanceMode { Global, Local };
    struct TraceBalance { TraceBalanceMode mode=TraceBalanceMode::Local; int horizontalWindowTraces=31; double targetRms=0.0; double maxGain=4.0; double epsilon=1.0; } traceBalance;
    // 道内增益
    struct SampleBalance { int windowSamples=120; double targetRms=0.0; double maxGain=6.0; double epsilon=1.0; } sampleBalance;
    // 希尔伯特
    struct Hilbert { bool computeEnvelope=true; } hilbert;
    // 偏移
    struct Migration { int sumWidth=64; double velocityMPerNs=0.12; } migration;
    // 地形校正
    struct Topo { bool useAverageElevation=true; double baseElevation=0.0; } topo;
    // 重采样
    struct Resample { bool resampleTraces=false; bool resampleSamples=false; int newTraces=0; int newSamples=0; } resample;
    // 预测反褶积
    struct PredictiveDecon { int predLag=1; int filterLen=10; } predictiveDecon;
};

// GprAnomaly.hpp — 雷达异常标注(前后端共用模型)
struct GprAnomaly {
    QString id;            // 后端返回或前端临时 UUID
    QString surveyLineName;
    int traceStart = 0, traceEnd = 0;      // 道号范围
    int sampleStart = 0, sampleEnd = 0;    // 采样范围
    double distanceStartM = 0, distanceEndM = 0; // 里程范围(m)
    double depthStartM = 0, depthEndM = 0; // 深度范围(m)
    QString typeCode;      // cavity / loose / void / pipe ...
    QString typeName;
    double widthM = 0, heightM = 0, lengthM = 0; // 异常尺寸
    double burialDepthM = 0; // 埋深
    double clearanceM = 0;   // 净空
    double confidence = 0;   // 置信度 0-1
    QString remark;
    QString sliceScreenshotPath;   // 切片截图本地路径M1 先本地文件)
    QString profileScreenshotPath; // 剖面截图本地路径
};

5.2 io/gpr/ — rd3 解析器(未来扩展)

在现有 IprbReader / IprHeader / GprSurveyAssembler 旁新增:

// Rd3Reader.hpp — MALA .rd3 / .rd7 三维雷达格式解析
namespace geopro::io::gpr {
struct Rd3Header { /* 天线频率、采样率、道数、通道数等 */ };
Rd3Header parseRd3Header(const std::string& headerText);
BScan readRd3(const std::string& path, const Rd3Header& h);
BScan readRd3Range(const std::string& path, const Rd3Header& h, std::int64_t t0, std::int64_t t1);
} // namespace geopro::io::gpr

注意.rd3 格式细节需用户提供样例文件或格式文档。当前先以 .iprb 验证管线。


6. 文件清单与开发顺序

Phase A基础设施无 UI可独立测试

顺序 文件 说明
A1 src/core/model/gpr_proc/GprTraceMeta.hpp 元数据模型
A2 src/core/model/gpr_proc/GprProcessingParams.hpp 参数结构体(对应用户需求的 20+ 参数)
A3 src/core/model/gpr_proc/GprAnomaly.hpp 异常标注模型
A4 src/core/gpr_proc/IGprProcNode.hpp 节点接口
A5 src/core/gpr_proc/GprProcessingPipeline.hpp/cpp 管线编排+脏链追踪
A6 src/core/gpr_proc/ZeroTimeCorrectionNode.cpp 零点校正
A7 src/core/gpr_proc/ZeroDriftRemovalNode.cpp 去零漂
A8 src/core/gpr_proc/GainNode.cpp 基础增益(球面扩散+吸收补偿)
A9 src/core/gpr_proc/BandpassFilterNode.cpp 带通滤波(自实现 FFT
A10 src/core/gpr_proc/SmoothingNode.cpp 剖面平滑
A11 src/core/gpr_proc/TraceBalanceNode.cpp 道间均衡
A12 src/core/gpr_proc/SampleBalanceNode.cpp 道内增益
A13 src/core/gpr_proc/ResamplingNode.cpp 数据重采样
A14 tests/core/gpr_proc/test_gpr_pipeline.cpp 管线集成测试(用 fixture 数据断言输出)
A15 tests/core/gpr_proc/test_*.cpp 各节点单元测试

Phase BB-Scan 视图UI 核心)

顺序 文件 说明
B1 src/app/panels/radar/BScanCanvas.hpp/cpp 自绘核心QImage raster + 交互状态机)
B2 src/app/panels/radar/ColorMapper.hpp/cpp float → ColorScale → QRgb复用 core::ColorScale
B3 src/app/panels/radar/ViewTransform.hpp/cpp 世界↔屏幕坐标变换(纯几何,可单测)
B4 src/app/panels/radar/AScanWaveformView.hpp/cpp A-Scan 波形QwtPlotCurve
B5 src/app/panels/radar/BScanProfileView.hpp/cpp 总装:工具栏 + BScanCanvas + AScanWaveformView
B6 src/app/panels/radar/BScanToolbar.hpp/cpp 顶部控制栏(参数按钮+滑块+下拉)
B7 src/app/panels/radar/GprColorScaleDialog.hpp/cpp 色阶选择对话框(可复用 ColorScaleConfigDialog
B8 src/app/panels/radar/GprParamsDialog.hpp/cpp 参数配置对话框(各处理参数的表单)
B9 src/app/panels/radar/BScanAnomalyDialog.hpp/cpp 异常编辑对话框(类型/深度/尺寸/备注)
B10 src/app/panels/radar/BScanWorkbench.hpp/cpp ADS DockWidget 外壳 + 右侧面板布局

Phase C控制器与集成

顺序 文件 说明
C1 src/controller/RadarWorkbenchController.hpp/cpp 控制器:数据加载/处理调度/异常管理
C2 src/app/main.cpp 修改新增雷达工作区路由、ADS dock 注册、信号接线
C3 src/app/CMakeLists.txt 新增 Phase B 所有 .cpp 文件
C4 src/core/CMakeLists.txt 新增 Phase A 所有 .cpp 文件gpr_proc 子目录)
C5 tests/... 补 UI 单元测试ViewTransform、ColorMapper和控制器测试

Phase D后端对接M2API 就绪后)

顺序 文件 说明
D1 src/data/api/ApiDatasetRepository.cpp 新增 loaderKey 分发:gpr.profilegpr.anomalies
D2 src/data/dto/GprDto.hpp/cpp 雷达采集参数、异常列表的 JSON DTO
D3 src/controller/RadarWorkbenchController.cpp saveAnomalies / loadAnomalies 后端调用

7. 待确认事项(阻塞开发或影响架构)

🔴 高优先级(阻塞 Phase C 及之后)

  1. ddCode 命名

    • 雷达数据集在后端的 ddCode 是什么?例如 dd_gpr_datadd_radar_profiledd_gpr_bscan
    • 是否按"三维雷达"vs"二维雷达"分不同 ddCode.rd3 是三维阵列雷达,.iprb 是二维单通道)
  2. 数据集入口方式

    • 用户双击数据集后,前端如何获取雷达文件的本地路径?
    • 方案A后端 /business/dataset/detail 返回 filePath 字段,前端直接读本地文件。
    • 方案B后端提供 /business/dd/gpr/download 接口,前端先下载到临时目录再读。
    • 方案C后端直接提供 /business/dd/gpr/profile 返回二进制 B-scan 数据,前端不碰文件系统。
    • 推荐 A 或 B(前端实时处理需要本地文件随机访问/seek
  3. 雷达采集参数的数据来源

    • 用户的"对象属性"表格Date/Time/Antenna/Frequency/Traces/Channels 等)来自哪里?
    • 方案A全从 .iprh / .rd3 头文件解析(已有 IprHeader 部分字段,需扩充)。
    • 方案B后端 /business/dd/gpr/info 返回结构化 JSON前端解析填表。
    • 推荐 AM1+ BM2 补充后端管理字段)
  4. 多通道数据模型

    • 阵列雷达16通道在界面上是"一次全载 16 通道到内存"还是"按需切换通道懒加载"
    • 16 通道 × 3778 道 × 516 采样 × 4字节(float) ≈ 120MB,全载可接受。
    • 但处理管线是"每个通道独立跑"还是"跨通道联合处理"?(背景去除的 MeanAverage 是跨道,但这里用户描述是按通道的"同通道道数量"平均)
    • 建议 M1 先全载,切换通道时即时换数据,处理管线按单通道跑

🟡 中优先级(影响 UI 细节,不阻塞架构)

  1. 异常标注的数据模型确认

    • 异常的世界坐标系:用 道号+采样点(原始索引)还是 里程+深度(物理坐标)?
    • 用户说"上传点坐标,对应测线名称,距离和深度等"——建议双存:前端用道号/采样点(抗重采样不变性),显示和上传时转里程/深度。
    • 异常类型枚举:用户提到"空洞/疏松/脱空/管线"——是否还有其他?需要完整列表。
    • 截图要求:"切片截图和剖面截图"——M1 阶段用 QWidget::grab() 生成 QPixmap 存本地临时文件M2 上传时作为 multipart/form-data 附件?
  2. 色阶方案

    • 用户提到"灰度图、彩虹色阶、冷暖色阶、振幅色阶"——这些是否已有定义?
    • 复用现有 core::ColorScale(阶梯色阶)+ 预置几套默认 stopsGray/Rainbow/Seismic/Amplitude
    • 是否支持与 2D/3D 视图色阶联动?(跨视图色阶真源 DatasetViewState)——建议 M1 先独立M2 视需求接入联动
  3. 处理参数默认值

    • 用户给出了大量默认值(如 cutSamples=30slidingWindowSamples=100 等)。
    • 这些默认值是"写死在前端代码"还是"后端 /business/dd/gpr/defaultParams 返回"
    • 建议 M1 写死M2 后端可覆盖
  4. Wiggle 模式细节

    • Wiggle 画的波形线:正半周填充什么颜色?负半周填充什么颜色?线宽?背景色?
    • 参考标准:地震勘探通常正半周填黑/红,负半周填白/蓝,背景白色。
  5. 打标Marker数据格式

    • 用户说"第一列是道号,第二列是采样点,第三列是类型,第四列是可以插入的里程号"。
    • 这个数据存在哪里?.mrk 文件?后端 API需要样例。
  6. rd3 格式文档/样例

    • .rd3 是 MALA 三维探地雷达格式,需要头文件结构说明或样例文件,才能写解析器。
    • 是否与 .iprb 布局类似int16 道序存储)?

🟢 低优先级(可开发中迭代)

  1. 独立工作区 vs 底部页签

    • 当前方案是独立 ADS Dock。如果产品坚持要走底部 DatasetDetailPanel 页签,需要大幅压缩 UI控制栏收进折叠面板A-Scan 弹窗或取消)。请确认
  2. 性能基准

    • "几分钟处理完公里级三维探地雷达数据"——具体数据量?
    • 10km 测线 × 20道/米 × 516 采样 × 16 通道 ≈ 3.2GB 原始数据int16。这个量级全内存+实时处理是否可行是否需要逐段流式处理Slab
    • 建议先以单测线(~2MB/通道)验证管线性能,再评估大数据量策略

8. 与现有架构的衔接点

现有组件 衔接方式
io/gpr/IprbReader 直接复用 readIprb / readIprbRange 读原始 B-scan
io/gpr/IprHeader 解析采集参数frequency、samples、traces、timeWindow、distanceInterval需扩展字段date、time、antenna 型号等,如果头文件里有)
io/gpr/GprSurveyAssembler 多通道时复用 assembleGprSurvey 装配 core::GprSurvey
core::ColorScale B-Scan 上色直接复用,支持全局透明度和 under/over/nan
core::GeoLocalFrame / GpsTrack 里程归一化、地形校正需要 GPS 轨迹 → 复用 GpsTrack 解析 .gps 文件
app/panels/KeyValueView 对象属性面板直接复用
app/panels/ObjectExceptionPanel / AnomalyTablePanel 异常列表 UI 复用,数据模型从 core::Anomaly 扩展为 core::GprAnomaly
ads::CDockWidget BScanWorkbench 继承或封装 ADS 停靠
DatasetViewState M2 可选接入跨视图色阶联动
net::ApiClient / ApiBatch M2 后端对接复用现有网络基础设施

9. 风险评估

风险 等级 缓解措施
FFT 实现性能不足(带通/希尔伯特) 先自实现基2-FFT516点很小实测不足再引入 FFTW
偏移/反褶积算法复杂M1 难以正确实现 M1 不实现P2先留接口占位用简化版本或后端预处理过渡
大数据量(公里级)内存/性能不达标 单测线验证通过后,评估是否需要:① 分块加载Slab② 处理管线也分块 ③ 降采样预览 + 全精度导出
rd3 格式无文档,解析器开发受阻 向用户/厂商索要格式说明或样例M1 先用 iprb 验证全链路
UI 复杂度高,开发周期长 按 Phase A→B→C 分阶段交付每阶段可独立验证BScanCanvas 自绘虽然工作量大但可控
API 未设计,后端对接延期 M1 全走本地文件视图和控制器与后端解耦API 就绪后只改 data 层

本文档为雷达 B-Scan 详情页的完整开发方案。待第 7 节高优先级事项确认后,按第 6 节 Phase A→B→C 顺序进入开发。