geopro/docs/superpowers/HANDOFF-vtk-3d.md

100 lines
14 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.

# 交接VTK 三维视图feat/vtk-3d-view
> 给下一个会话无缝接手用。更新日期 2026-06-17。分支 `feat/vtk-3d-view`,工作树:仅根目录 `grid-list-original.png`/`grid-list-small.png`/`grid-snap.yml`/`orig-dataview.png` 及 `docs/superpowers/specs/2026-06-17-web-embed-subpage-mount-design.md` 是**既有未跟踪文件,非本任务产物,勿动/勿提交**(曾被 `git add -A` 误纳、已撤回)。
## 1. 背景
- 项目geopro 桌面客户端Qt6 + VTK9 + Qt-ADS dockWindows/MSVC+Ninja`build.bat`。
- 任务:实现需求表「补充需求」页 = VTK 三维视图整套结构/交互。需求源:`D:\Projects\GEOPRO\Geopro3.0 需求表.xlsx`「补充需求」页。
- 原版 web 源码在 **`D:\Git\lanbingtech\commercial-admin`**Vue + three-tile是**复刻的权威参照**threeMap.vue / mapSource.js / src/apis/)。
- 三栏结构(三维数据集 / 二维数据集 / 三维分析)+ 真实 ERT 反演剖面(帘面)+ 底图地形——这些**已完成**。本会话主要做了**底图/地形 + 剖面垂直配准 + 增量渲染**,并为下一阶段(三维体/切片/异常)做了**设计定稿**。
## 2. 本会话已完成(均已编译绿 + 提交;用户验收"差不多了"
**底图 + 真实地形**(核心在 `src/app/TileBasemap.{hpp,cpp}`
- 影像=**天地图卫星**(`img_w`tk 内嵌);地形=**Mapbox terrain-RGB DEM**(原版同源pk token 内嵌;`elev=-10000+(R*65536+G*256+B)*0.1`)。
- **四叉树多级 LOD**(按瓦片屏幕像素误差递归细分,近细远粗)。根 `kRootZoom=9`、阈值 `kTargetPx=384`、叶上限 `kMaxLeaves=200`
- **视锥剔除只用 4 个侧面**(不用近/远裁剪面——远裁剪面随已加载几何变化会误剔除远块)。`frustum_[24]` 用焦点自校正法向。
- **并发限流** `kMaxConcurrent=12`(请求队列 `netQueue_`/`pumpNetQueue`)。
- **缓存**:影像纹理 `texCache_` + DEM `demCache_`,跨隐藏/重选保留 → 重选秒出。
- **合并渲染** `requestRender()`Qt 队列合并同轮多次渲染请求为一帧;并在渲染前 `ResetCameraClippingRange`)。
- **动态范围**:底图最大距离 = 剖面合并范围半径×10夹 [2km,30km],随勾选增删自动伸缩(`dataRadiusProvider_` 查 `VtkSceneView::dataHorizontalRadius()`)。**超过范围的粗瓦也强制细分**(否则一块巨瓦盖住中心、绕过距离剔除)。
- **地形半透明 0.55**`kTerrainOpacity`)——地下剖面可从任意角度透过地面看到(地球物理标准做法;解决"前后左右预设看不到剖面=不透明地形遮挡地下")。
- **近裁剪容差 1e-5**`SetNearClippingPlaneTolerance`VtkSceneView 构造)——远处底图把近裁剪面顶出去会切掉近处剖面,调小修复。
- **就近优先加载**(离相机近的瓦片先拉)。
- 瓦片纹理 mipmap + 各向异性 16x + edgeClamp。
**剖面垂直配准 + VE**
- 剖面 Z = **`+g.y`(真实高程)**——与原版一致(实证 `threeMap.vue:676`:剖面世界竖向 = data.y。地形也用真实高程 → 同系对齐、剖面顶≈地表露出。(早期错把 y 当深度 `-y`,已改。)
- 垂直夸张默认 **1.0**,收敛为**单一来源** `kVerticalExaggeration`main.cpp下发控制器/底图/UI。剖面与地形用同一 VE。
**增量渲染**`VtkSceneController` + `VtkSceneView`
- 勾选/取消 = **按 dsId 增删图元**,不再整场 clear + 全量重建;`clear()` 保留底图;增量不重置相机(视角不跳);首批数据/全量重建才 `fitView`
- `computeDataBounds()` 只算数据图元(不含底图)→ 坐标轴/取景/预设(前后左右)不被公里级底图撑大/推远。
- `onCameraChanged` 回调:相机程序化变化(取景/预设/缩放)后通知底图按新视锥重算覆盖(治"首帧部分瓦片要微动才出")。
- 默认底图=天地图;首个剖面重锚 frame 后经 `onFrameReanchored` 在数据位置加载底图。
- VTK 全屏含左侧三栏drawer 在 vtkDock 内 + 进入全屏展开)。
## 3. 当前状态
- 底图/地形/剖面配准/增量渲染:**完成且可用**。编译绿。所有改动已提交到 `feat/vtk-3d-view`
- **#1 客户端「生成三维体」流程已实现编译链接绿exit 0未提交、未 GUI 实测**Claude 无法验 VTK 渲染,待用户启动 app 实测)。详见计划 `docs/superpowers/plans/2026-06-17-vtk-3d-volume-create-flow.md`
- 已落地:`data::VolumeBuildParams`(不冻结 gridSpec源 ds 锁定不变式);`core::buildVolume` 共享管线LocalSample/Api 同源,消 TODO 漂移);`Api3dRepository` 内存体存储 + `createVolume/volumeRows/isVolumeDataset` + 多源 `loadVolume`(复用 `loadSection`,竖向=g.y 高程,与帘面构造性对齐);`loadVolume` 回调改交付 `(VolumeGrid, ColorScale)`(体色阶=源剖面色阶);`Column3DDataset`(源数据栏) 多选+右键「生成三维体」+ `VolumeParamsDialog`**生成的体归三维分析栏**(`Column3DAnalysis`,设计 §2.1,非数据集栏)main.cpp `lastAnalysisRows`+`refreshAnalysis` 合并注入(体行不被后端刷新冲掉)+ **两栏勾选聚合** `pushChecked`(剖面+体/切片并集下发,避免互相清除)`VtkSceneController` 按 `isVolumeDataset` 分流体素/帘面(取代全局 showVoxel/showCurtain
- **待实测**:在**三维数据集栏**多选反演剖面→右键「生成三维体」→参数→新体行出现在**三维分析栏**→在三维分析栏勾选→渲染体;体是否与帘面对齐;色阶是否正确;剖面与体可同时勾选共存。
- 下一阶段(切片/异常 #2#6**仅完成设计定稿**,未开始编码。
## 4. 下一步计划(三维体 / 切片 / 异常)
**权威设计文档**`docs/superpowers/specs/2026-06-17-vtk-3d-volume-slice-anomaly-design.md`(数据模型 + 交互流 + 后端vs mock + 代码现状 + 实现拆解 + 持久化策略)。已与用户拍板的关键决策:
- **创建三维体 = 客户端**:「三维数据集」栏多选剖面 → 选插值模型/参数 → `core::IdwInterpolator` 生成体素。
- **异常 = 接真实后端端点**(已从 web 源码挖到,见设计文档 §3`POST/PUT/DELETE /business/exception` + `exceptionType/*` + `exceptionConsortium/*` + 读 `queryException*`/`queryExceptionTree`。`remarkSourceId/Type` 填切片数据集。
- **三维体网格 / 切片持久化 / 三维分析任务 = 后端无端点 → 先本地 mock**(保持 `I3dSceneRepository` 接口不变,端点就绪只换实现)。
- **持久化策略**(设计文档 §7三维体保存时 **参数(源数据+插值模型/参数+色阶) + 网格规格 GridSpec 必存,明细 values 可选**;加载时有明细直接渲染、无明细按参数重算填入固定 GridSpec锚定切片/异常坐标)。带切片/异常或大/慢的体建议存明细。
- 数据模型层级:**三维体(源数据+插值参数) → 切片(属于体,保存后成 dd_slice) → 异常(画在切片平面,圈定保存)**,三者皆可持久化。
**实现拆解(设计文档 §6按依赖排序**
1. ~~三维体 mock 渲染~~ **✅ 已实现(编译绿,待 GUI 实测)**——见 §3 与计划 `2026-06-17-vtk-3d-volume-create-flow.md`。`Api3dRepository::loadVolume` 已接通(多源复用 loadSection → IDW → VolumeGrid + 色阶交付);`VolumeBuildParams` 必存参数、values 惰性重算+缓存(**不冻结 gridSpec**,改用源 ds 锁定不变式,留校验 TODO
2. ~~切片交互接通三维体~~ **✅ 已有**`SliceTool`/`InteractionManager`:四向创建/滚轮推进/双击正视/翻转/关闭/选中高亮全在)。
3. **✅ 完成(3a/3b/3c已提交 afdd98f+d56e35f用户实测通过)**——切片完整生命周期(未保存↔已保存统一状态模型)
- VTK 视图切片右键菜单(`PickInteractorStyle`右键→`InteractionManager`高优先级(1.0)交互器观察者抢右键→`onSliceContextMenuRequested`→main 弹 QMenu):创建异常(占位#4)/保存/导出▸(图片·dat)/正视图/翻转/关闭。
- **保存按状态分派**:未保存→`createSlice`+`tagSelectedSlice`链接当前切片+列表自动勾选(`setItemChecked`);已保存→`saveSlice`覆盖位姿。**无重复切片**。
- **精确几何持久化**`SliceSpec`存 axis+Origin/Point1/Point2 三点;`SliceTool`还原构造逐点重建→重渲染尺寸/朝向一致。
- **已保存切片重渲染**:分析栏勾选→`syncSlices`在当前活动体上还原(`showSavedSlice`),取消→移除;靠`onVolumeChanged→syncSlices`解决父体异步到场。dd_slice 不进控制器(避免 loadSection 失败)main 编排走 InteractionManager。
- **场景↔列表同步**VTK「关闭」已保存切片→`onSliceClosed`→列表取消勾选。`Column3DAnalysis::setDatasets`按 dsId 保留勾选+仅勾选集变化才发信号(修"保存切片连带取消体勾选/列表重置")。
- 导出:`SliceExport.{hpp,cpp}`(图片=切片上采样2048上色 PNGdat=重采样标量网格)。切片持久化=`Api3dRepository` createSlice/saveSlice/deleteSlice 内存 mock + sliceRows/isSliceDataset/sliceSpec。
4. 异常(**进行中**,全量含异常体/列表/过滤,计划见 `plans/2026-06-18-vtk-3d-anomaly.md`)。**异常挂三维体**(非切片非源ds见记忆 vtk-3d-persistence-structure)mock 持久化(三维体/切片端点未就绪)。
- **4a ✅ 已提交(4e1b8e7)**`core::Anomaly` 补 3D(id/volumeDsId/consortiumId/worldPts/plane)`buildAnomaly3D``I3dSceneView`+`VtkSceneView` addAnomaly/removeAnomaly/clearAnomalies/setAnomalyVisible(按id跟踪actor)`Api3dRepository` 异常 mock(saveAnomaly/loadAnomalyTree按volumeDsId+consortiumId分组/delete)。**附带修复测试漂移→228/228 绿**。地基、尚不可见。
- **4b ✅ 已提交**:圈定工具(切片平面画多边形,黄点+橡皮筋虚线,双击/右键/Enter 闭合,Esc 取消,屏幕提示)+保存对话框(名称/类型 mock/备注/截图预览)+切片右键「创建异常」接通 → 画→存→显示→删闭环。修复:闭合手势误触切片(abort 先于 finish/teardown)。
- **4c-1 ✅ 已提交**:三维分析栏「异常」组(QSplitter:数据集树 + 异常 QGroupBox);过滤下拉(全部显示/随GS/随数据集/全部隐藏,默认随数据集);删除按 consortiumId 分组;`refreshAnomalies` 各路径补 `renderWindow->Render()`(修过滤勾选与 VTK 显隐脱节)。
- **4c-2 ✅ 已提交(44d31a8)**列表选中异常→VTK 高亮联动(R84,list→VTK)`setSelectedAnomaly`(选中 actor 加粗线宽/点尺寸,其余恢复);anomalyProps_ 改 vtkActor。**反向(VTK点异常→回选列表)未做**(需异常 actor 拾取)。
- **4c-3 待做**:异常属性面板(R83,选中异常显示名称/类型/坐标/截图/备注);以及 4c-1 已知限制(单条显隐状态跨 refresh 不持久)。
5. 分析栏右键接线:**已完成**(切片 保存/保存为/导出▸/删除 全接;体 切片▸/详情)`colorScaleRequested` 仍占位("色阶开发中")。已移除"显示/隐藏"(勾选即显隐)。
6. 三维体/切片/异常详情面板(源数据/插值参数/色阶/测量点数体积/异常列表)。
- **其它小欠项**:三维分析栏完整三级树"对象→三维体→切片"里"对象"根层未套(体目前是顶层);真实色阶编辑。
**其它小项**坐标轴「O点位置」「字体」弹框仍是 stubmain.cpp:382 TODO P4
## 5. 相关文档
- **`docs/superpowers/specs/2026-06-17-vtk-3d-volume-slice-anomaly-design.md`** ← 下一阶段主依据。
- `docs/questions/2026-06-16-反演剖面竖向字段(y-z-elevation)语义待确认.md` ← 已解y=高程z=+y 与原版一致;跨数据集 y 不一致是数据层问题(原版同样存在),非客户端 bug。
- `docs/questions/2026-06-17-3D地球改造-现状与约束评估.md` ← 已决:维持局部平面方案,不做真 3D 地球opus 评审:球面=根本性重构)。
- 旧 spec/plans`2026-06-15-vtk-3d-*`、`three-column-refactor*`)为历史,留档。
## 6. 关键铁律 / 坑(务必遵守)
- **构建**`build.bat rebuild` 会**自动启动 app**(后台命令不返回);编译验证用 **`build.bat app`**。Claude 无法 GUI 验证 VTK 渲染。
- **不能靠猜**:渲染/裁剪类问题用**日志取证**`%LOCALAPPDATA%\Geomative\Geopro3\logs\geopro_YYYYMMDD.log`,含 `[basemap]`/`[view]` 的 qInfo/qWarning或读真实数据/原版源码。本会话多次因臆测被用户纠正——**贴源码/日志,别凭印象**。
- **勿动未跟踪文件**(见顶部);**勿用 `git add -A`**(会误纳)。逐个文件 `git add`
- **API 凭证不得提交**(探测脚本用完即删)。
- 原版 web 源码 `D:\Git\lanbingtech\commercial-admin` 是复刻权威;需求 xlsx 用 `python openpyxl` 读到 UTF-8 临时文件再看(控制台中文乱码)。
- 内嵌 token天地图 tk + Mapbox pk公开客户端 token同原版可提交
- 全部回复中文。
## 7. 代码地图(关键文件)
- `src/app/TileBasemap.{hpp,cpp}` — 底图+地形(四叉树/剔除/限流/缓存/动态范围/半透明/合并渲染)。
- `src/app/VtkSceneView.{hpp,cpp}` — I3dSceneView 实现clear/addCurtain(dsId)/addVolume(dsId)/removeDataset/render/renderIncremental/computeDataBounds/dataHorizontalRadius近裁剪容差onCameraChanged/onFrameReanchored 回调。
- `src/controller/VtkSceneController.{hpp,cpp}` — 增量渲染编排setCheckedDatasets diff、addDatasetAsync、fitOnArrival
- `src/render/actors/CurtainActor.cpp` — 帘面Z=+g.y 真实高程)。
- `src/render/interact/{SliceTool,InteractionManager,SlicePlaneMath}.*` — 切片交互。
- `src/render/{VoxelFromScatters,actors/VoxelActor}.*` + `src/core/algo/IdwInterpolator.*` — 体素插值/绘制(三维体复用)。
- `src/data/repo/I3dSceneRepository.hpp` — 接口loadVolume/createSlice/saveSlice/deleteSlice/loadAnomalyTree/saveAnomaly/.../loadTaskRecords
- `src/data/repo/LocalSample3dRepository.cpp`(内存 mock 参考实现)、`src/data/api/Api3dRepository.cpp`(真实路径,多为 stub `kNotReady`,待按设计文档实现)。
- `src/app/panels/columns/{Column3DDataset,Column2DDataset,Column3DAnalysis,ColumnDrawer}.*` — 三栏 UI信号定义全、main.cpp 未全接)。
- `src/app/main.cpp` — 装配/接线(搜 `basemap`/`colAnalysis`/`onCameraChanged`/`kVerticalExaggeration`)。
- `src/data/dto/DatasetChartDto.cpp``parseInversionGrid`x/y/v/lat/lon**未解析 elevation/alt**)。