geopro/docs/superpowers/HANDOFF-dataset-detail-char...

98 lines
9.4 KiB
Markdown
Raw 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.

# 交接文档数据集详情图表dataset-detail-chart
> 给下一个会话:读完本文件 + 文末"立即要做的事"即可无缝接手。日期 2026-06-11。
## 1. 背景
geopro 是 **Qt6 / C++ 离线桌面客户端**,目标是**像素级 1:1 复刻** web 系统
`http://tenant.geomative.cn/#/projectSpace/datasetMange/datasetInfo`(赛盈地空)的「数据集详情」视图。
本轮专做 ERT 反演数据(`ddCode=dd_inversion_data`)的详情视图。
**硬约束**:禁止 QWebEngine/Chromium离线要求。图表用本地 **QwtPlot轴/交互/图例)+ VTK 算法层(等值线几何)+ 连续/离散色阶**,不是 web 渲染。验收标准是**视觉等价 + 交互一致**(非字节级像素 diff
**标准测试 ds**`id=1458990939709440`ddCode=dd_inversion_data。原版网格视图参考截图仓库根 `web-grid-E3b.png`(未入库,可重新用 Playwright 截)。
## 2. 目标
数据详情含两个页签,均已完成:
- **原数据**Plotly scattergl 风格散点(方形点/白描边/连续色阶/x 轴顶部)。
- **网格数据**:填充等值面 + 黑色等值线 + 沿线数值标注 + 不规则白边NaN 裁剪)+ 底部异常表/描述。
## 3. 技术栈与构建
- Qt6 Widgets**Qwt 6.2**(源码在 `external/qwt-src/`**用 `cmake/qwt.cmake` 以 CMake 构建**静态库,不要用 qmake——本机 VS2026 缺 vswhereqmake 不可用)。
- 关键qwt.cmake 必须 `target_compile_definitions(qwt PRIVATE QWT_MOC_INCLUDE=1)`,否则 61 个链接错误;需链接 Qt6 Widgets/Concurrent/PrintSupport/Svg。
- **VTK 9.6 仅用算法层**`vtkBandedPolyDataContourFilter` / `vtkStripper` / `vtkSplineFilter` / `vtkDataSetSurfaceFilter`),不做 VTK 渲染。
- CMakeVS 自带 4.2.3+ Ninja + MSVC 14.51GoogleTest/CTestvcpkg仅非 Qt 依赖)。
- **构建**`powershell.exe -ExecutionPolicy Bypass -File scripts/dev-build.ps1`
- ⚠️ 若报 `LNK1104 无法打开 geopro_desktop.exe`,是 exe 正在运行:先 `Get-Process geopro_desktop | Stop-Process -Force` 再构建。
- **测试**`powershell.exe -ExecutionPolicy Bypass -File scripts/dev-test.ps1`(当前 **75/75 绿**)。
- 单测过滤:`build/release/tests/geopro_tests.exe --gtest_filter=ContourBands.*`
## 4. 数据 API均经 Playwright 实测)
Auth header`geomativeauthorization: Geomative <token>`。ApiClient 把非 object 的 `data` 包成 `{"value": <data>}`
**原版也是分页懒加载**(客户端已对齐):
| 页 | 接口 | 说明 |
|---|---|---|
| 原数据 | `lvl/colorGradation/getDetail`(type1) + `dd/ert/inversion/getErtRawDataScatterGraph/{id}` | 2 个请求,~0.8s |
| 网格数据 | `dd/ert/inversion/rows/{id}` + `lvl/colorGradation/getDetail`(type2) + `exception/queryException/{id}` | 3 个rows 服务端网格化**波动 14s** |
- `rows``x[nx]`、`y[ny]`、`v[ny][nx]`(电阻率,含 NaN=无数据)、`z[ny][nx]`(高程)、vmin/vmax。标准 ds 为 nx=300,ny=100。
- `colorGradation``properties.colorBar=[[值,"rgba()"],…]`type1 散点连续/type2 网格离散,~17 段)+ `lineConfig{showLines,color,lineType}` + `labelConfig{showLabels,color}`
- **配色机制(实测纠正过)**:不是 log**colorBar 值线性归一化到 [0,1] + 非均匀色阶停靠点 + 连续插值(散点)/离散分带(网格)**
## 5. 架构与关键文件
数据流:`DatasetListPanel` 双击 → `DatasetDetailController.openDataset`(同步阻塞拉原数据 2 请求)→ `chartReady(ChartData)``DatasetDetailPanel`(多 ds 的 QTabWidget) → `DatasetDetailPage`(buildTabbedPanel 原数据/网格 两页签) → 两个 View。切到网格页签 → `gridDataNeeded` 冒泡 → `loadGridData`(懒加载 3 请求)→ `gridReady(GridData)``GridDataChartView.setGridData`
- `src/controller/DatasetDetailController.{hpp,cpp}` — openDataset / **loadGridData**懒加载busy_ 重入守卫 + catch(...) 防死锁。signal: chartReady/gridReady/loadFailed/focusRequested。
- `src/app/panels/chart/`
- `RawDataChartView.*` — 散点视图模板(白底浅 palette、QwtPlotGrid 网格线、过原点 QwtPlotMarker 零线、**QwtPlotRescaler 锁定 x:y 真实比尺(aspect=1, ref=xTop)**、**LivePanner**、x 轴在 **xTop**、独立 ColorBarWidget。析构 delete colorSvc_。
- `GridDataChartView.*` — 网格视图。x 轴在 **xBottom**。布局toolbar(固定) + **QScrollArea(setWidgetResizable)** 内含 **QSplitter(竖直)**{ chartArea(plot+colorBar, minH280) | 异常表/描述(minH160) }。→ 页签内滚动 + 可拖分割条。
- `ContourPlotItem.*`QwtPlotItem**填充走栅格**QImage(ARGB32, K=4 上采样, 双线性插值 + `colorAtDiscrete` 离散着色 + 任一邻格 NaN→像素透明=白边裁剪)draw 时 blit**等值线走矢量**`buildContourBands` 取 lines标注`resolveLineLevels` 采样吸附级别,**每条线只标一个**(弧长中点,旋转)。异常叠加(点/线/面)。
- `ScatterPlotItem.*` — 散点项xTop/yLeft7px 方块白描边连续配色n=min(x,y) 防越界)。
- `ColorMapService.*` — colorAtContinuous(线性插值)/colorAtDiscrete(阶梯)from core::ColorScale。
- `ColorBarWidget.*` — 独立色阶条,**居中约 74% 宽**(非满宽)、等宽色带、白底深字。
- `LivePanner.*` — canvas 事件过滤器:**左键实时平移**(连续平移两轴+replot) + **滚轮缩放**(以光标为中心,上滚=放大,**消费事件**避免冒泡触发外层滚动条)。取代了 QwtPlotPanner/QwtPlotMagnifier。
- `src/render/ContourBands.{hpp,cpp}``buildContourBands(Grid, ColorScale, ContourOptions{upsample=2,smooth=0.3,makeLines})``{bands, lines}`。VTK网格→上采样→平滑→toCellGrid(剔 NaN 格)→surface→banded→(lines: **vtkStripper 连段 + vtkSplineFilter 样条平滑**, 不再 DP 简化)。
- `src/data/dto/DatasetChartDto.*`、`src/data/api/ApiDatasetRepository.*` — JSON 解析v 行数校验 qWarning、markType 钳制)。
- `src/app/main.cpp` — 装配detailDock `setWidget(..., ads::CDockWidget::ForceNoScrollArea)`**禁 ADS 把标题/页签卷入整体滚动条**gridDataNeeded→loadGridData、gridReady→setGridData 接线。
## 6. 关键设计决策(及为什么)
- **真实比尺锁定**用户选定区别于原版的响应式填充QwtPlotRescaler aspect=1剖面呈真实"宽扁"。
- **填充用栅格而非多边形**300×100 网格 banded 多边形约 3 万个,逐帧+实时拖动会卡QImage 一次成图 + blit 流畅。
- **等值线样条平滑**banded 边是大量 2 点短线段→ vtkStripper 连接 + vtkSplineFilter 拟合平滑曲线(贴近原版圆滑)。
- **滚轮事件必须消费**:否则冒泡触发 ADS/外层滚动条。
- **页签内滚动**ForceNoScrollArea(dock) + 视图内 QScrollArea(裹 splitter),使标题/页签/工具条固定、仅内容区滚动。
- **同步阻塞是全 App 共性问题**ApiClient 用 QEventLoop 死等→每次请求冻 UI。已定**单独立项异步化**(见下)。
## 7. 当前进度
- 分支 **`feat/dataset-detail-chart`**,领先 main **37 commits**,工作区干净(除未入库的 `web-grid-E3b.png`)。
- 两个视图 + 交互 + 懒加载 + 布局**全部完成并经用户逐项验收通过**。
- **cpp-reviewer 审查已做**HIGH 全修(散点越界 / colorSvc 析构泄漏 / QwtPlot autoDelete 注释 / 控制器 catch(...) 防 busy 死锁)+ 值得的 MEDIUM/LOW清死代码、填充等比限幅、DTO 校验/枚举钳制、ContourLine.level 默认 NaN。提交 `78f96db`。75/75 测试绿。
## 8. 立即要做的事(接手第一步)
**收尾本分支**——已问用户"如何收尾"4 选项待其回答:①合并回 main(本地) ②推送建 PR(origin=gitea) ③保持现状 ④丢弃。
合并/PR 前先清掉未入库的 `web-grid-E3b.png`(保持工作区干净)。**等用户给出选择后执行**(用 superpowers:finishing-a-development-branch
## 9. 后续计划(本分支之后)
1. **工具条编辑类功能**(网格页占位按钮):白化 / 滤波处理 / 色阶配置 / 异常框注 / 自动标注 / 网格 / 另存为 / 导出。交互较重,建议先 brainstorm 拆解。
2. **ApiClient 异步化(已单独立项)**:把全局同步阻塞 ApiClient 改异步QNetworkReply 信号,去 QEventLoop+ Repository/控制器信号化→全 App 不冻 UI、可并发。架构改动建议单独 spec+plan。
3. **更广项目**:数据详情只是一个特性;原型/`D:\Projects\GEOPRO\Geopro3.0 菜单.xlsx`(客户端 tab) 里还有其他数据类型、三维视图、其他菜单。
## 10. 相关文档与记忆
- 设计/计划:`docs/superpowers/specs/2026-06-11-dataset-detail-view-design.md`、`docs/superpowers/plans/2026-06-11-dataset-detail-chart-v2-qwt.md`v2 QwtPlot 返工方案,权威)、`docs/superpowers/plans/2026-06-11-dataset-detail-chart.md`。
- 外部返工方案:`docs/Geopro3.0_二维图表返工技术方案.md`。
- API 文档:`docs/apis`business_OpenAPI.json
- **记忆(务必遵守)**`~/.claude/projects/D--Git-lanbingtech-geopro/memory/`
- `reply-in-chinese` — 全程中文回复。
- `study-original-via-playwright`**任何不确定必须用 Playwright 实地看原版,禁止联想猜测**
- `no-embellishment-replicate-exactly` — 严格 1:1不加原版没有的特性曾因等值线"周期重复标注"被纠正,原版每条线只标一个)。