feat/vtk-3d-view #7
|
|
@ -1,74 +1,84 @@
|
||||||
# 交接:VTK 三维视图「补充需求」(feat/vtk-3d-view)
|
# 交接:VTK 三维视图(feat/vtk-3d-view)
|
||||||
|
|
||||||
> 给下一个会话无缝接手用。日期 2026-06-16。分支 `feat/vtk-3d-view`,HEAD `07f2f25`,工作树干净(仅根目录 grid-*.png/grid-snap.yml 是既有未跟踪文件,非本任务产物,勿动)。
|
> 给下一个会话无缝接手用。更新日期 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. 背景
|
## 1. 背景
|
||||||
- 项目:geopro 桌面客户端(Qt6 + VTK9 + ADS dock),Windows/MSVC+Ninja。
|
- 项目:geopro 桌面客户端(Qt6 + VTK9 + Qt-ADS dock),Windows/MSVC+Ninja,`build.bat`。
|
||||||
- 任务:实现需求表「补充需求」页签 = **VTK 三维视图的整套交互/结构**。需求源:`D:\Projects\GEOPRO\Geopro3.0 需求表.xlsx`「补充需求」(用 openpyxl 读,控制台中文乱码须导 UTF-8 文件再读;A1–C92)。
|
- 任务:实现需求表「补充需求」页 = VTK 三维视图整套结构/交互。需求源:`D:\Projects\GEOPRO\Geopro3.0 需求表.xlsx`「补充需求」页。
|
||||||
- 历史:做本需求前已有"基于本地样本数据的原型渲染"(帘面/体素/切片/地形/散点),但在 commit `6241eb3`"CentralScene 数据驱动重构"时**装配代码被摘除**——render 层 actor 完整且有测试,只是没接上。本任务从复活它起步。
|
- 原版 web 源码在 **`D:\Git\lanbingtech\commercial-admin`**(Vue + three-tile),是**复刻的权威参照**(threeMap.vue / mapSource.js / src/apis/)。
|
||||||
- 原版 web「数据视图」(`tenant.geomative.cn/#/projectSpace/dataView`) 已 Playwright 实地分析:3D = **ThreeTile(Three.js)地球**(非 Cesium)+多瓦片源;3D 结果=2D 反演剖面成竖直帘面。**三栏/切片是客户端新需求(web 无三栏)**。详见记忆 [[web-3d-view-threetile]]。
|
- 三栏结构(三维数据集 / 二维数据集 / 三维分析)+ 真实 ERT 反演剖面(帘面)+ 底图地形——这些**已完成**。本会话主要做了**底图/地形 + 剖面垂直配准 + 增量渲染**,并为下一阶段(三维体/切片/异常)做了**设计定稿**。
|
||||||
|
|
||||||
## 2. 关键约束(用户拍板)
|
## 2. 本会话已完成(均已编译绿 + 提交;用户验收"差不多了")
|
||||||
- **后端未就绪** → 本轮全部用 `LocalSampleRepository` 静态样本数据驱动;**但仓储接口必须按真实后端形态设计好**(`I3dSceneRepository` 异步),将来换 `Api3dRepository` 不动上层。
|
**底图 + 真实地形**(核心在 `src/app/TileBasemap.{hpp,cpp}`):
|
||||||
- **严格按需求,禁止砍功能/改需求**(教训:曾把 F25 砍掉、把双击正视改按钮,被用户纠正)。复刻不确定处必须实地学习(Playwright),禁猜测。
|
- 影像=**天地图卫星**(`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`。
|
||||||
|
- 下一阶段(三维体/切片/异常):**仅完成设计定稿**,未开始编码。
|
||||||
|
|
||||||
|
## 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 渲染:`Api3dRepository::loadVolume` 由 stub 改为"取源数据散点 → IDW → VolumeGrid → VoxelActor"。拆 `VolumeBuildParams`(含 GridSpec) 必存 / values 可选。
|
||||||
|
2. 切片交互接通三维体(现有 `SliceTool`/`InteractionManager` 已能切;补滚轮推进、双击正视)。
|
||||||
|
3. 切片保存/另存/导出/删除(保存删除 mock 内存;导出图片/dat 客户端做)+ VTK 视图切片右键菜单接线。
|
||||||
|
4. 异常:切片右键创建异常(圈定+保存对话框含截图)→ **接真实端点**。
|
||||||
|
5. 分析栏右键菜单接线:色阶/显示隐藏(客户端)+ 切片增删(接 #3)。`Column3DAnalysis` 信号已定义,main.cpp 目前**只接了 `sliceRequested`+`detailRequested`**,其余未连。
|
||||||
|
6. 三维体/切片/异常详情面板(源数据/插值参数/色阶/测量点数体积/异常列表)。
|
||||||
|
|
||||||
|
**其它小项**:坐标轴「O点位置」「字体」弹框仍是 stub(main.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,同原版,可提交)。
|
||||||
- 全部回复中文。
|
- 全部回复中文。
|
||||||
|
|
||||||
## 3. 权威文档
|
## 7. 代码地图(关键文件)
|
||||||
- spec:`docs/superpowers/specs/2026-06-15-vtk-3d-supplementary-design.md`(v2,已纳入架构评审 + web 实地分析;§4 是补充需求逐行映射表;§6 接口设计;§14 分期)。
|
- `src/app/TileBasemap.{hpp,cpp}` — 底图+地形(四叉树/剔除/限流/缓存/动态范围/半透明/合并渲染)。
|
||||||
- 计划:`plans/2026-06-15-vtk-3d-p1-revive-rendering.md`、`plans/2026-06-15-vtk-3d-p2-dataset3d-bar.md`、`plans/2026-06-16-vtk-3d-p3-slice-interaction.md`。
|
- `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)。
|
||||||
## 4. 已完成并经用户验收(commit 范围 faee28c..07f2f25)
|
- `src/render/actors/CurtainActor.cpp` — 帘面(Z=+g.y 真实高程)。
|
||||||
- **P1 复活渲染**(`0f521c5`+`53ccdc0`):`VtkSceneController`(编排,异步)+`I3dSceneRepository`/`LocalSample3dRepository`+`I3dSceneView`/`VtkSceneView`+`Scene::addViewProp`(体绘制 vtkVolume 入场)。勾选对象→样本数据→渲染帘面/体素/地形。
|
- `src/render/interact/{SliceTool,InteractionManager,SlicePlaneMath}.*` — 切片交互。
|
||||||
- **P2 三维数据集栏**(`3dea339`+样式 `73deb2b`/`86e0772`):坐标轴(标准/三维立体/不显示 vtkCubeAxesActor)、刻度(无/米/英尺/经纬度,GeoLocalFrame::toLatLon)、水平/垂直比例滑块、快捷视图6向、Zoom(In/Out/Fit)。右上工具条浮层(仅三维显示)。
|
- `src/render/{VoxelFromScatters,actors/VoxelActor}.*` + `src/core/algo/IdwInterpolator.*` — 体素插值/绘制(三维体复用)。
|
||||||
- **P3 切片交互**(`85d4ff5`..`07f2f25`):`src/render/interact/`(SlicePlaneMath/SliceTool/PickInteractorStyle/InteractionManager)。**已验收**:
|
- `src/data/repo/I3dSceneRepository.hpp` — 接口(loadVolume/createSlice/saveSlice/deleteSlice/loadAnomalyTree/saveAnomaly/.../loadTaskRecords)。
|
||||||
- 上下/前后/左右切片=固定角度可移动(G22-24);任意切片=拖边缘旋转(F25)+拖中间移动。
|
- `src/data/repo/LocalSample3dRepository.cpp`(内存 mock 参考实现)、`src/data/api/Api3dRepository.cpp`(真实路径,多为 stub `kNotReady`,待按设计文档实现)。
|
||||||
- 触碰切片→选中+**亮青边框**高亮(未选暗灰)。
|
- `src/app/panels/columns/{Column3DDataset,Column2DDataset,Column3DAnalysis,ColumnDrawer}.*` — 三栏 UI(信号定义全、main.cpp 未全接)。
|
||||||
- **双击切片→正视**(D40,靠 widget StartInteractionEvent 350ms 双击判定)。
|
- `src/app/main.cpp` — 装配/接线(搜 `basemap`/`colAnalysis`/`onCameraChanged`/`kVerticalExaggeration`)。
|
||||||
- 滚轮→推进**选中**切片(D46);关闭→移除选中;翻转(E55)。
|
- `src/data/dto/DatasetChartDto.cpp` — `parseInversionGrid`(x/y/v/lat/lon;**未解析 elevation/alt**)。
|
||||||
- **D39 以选中切片为中心旋转视图**:`PickInteractorStyle::Rotate()` 自定义——按下不动相机、拖动时绕选中切片中心(getRotateCenter)增量旋转整个相机(T(c)·R(up)·R(right)·T(-c))→不跳。
|
|
||||||
- **构建基建修复**(重要,见 §7):`build.bat` vswhere/ASCII/加 `rebuild`;`vcpkg.json` 加 `builtin-baseline`。
|
|
||||||
- ctest 全绿 **221/221**。
|
|
||||||
|
|
||||||
## 5. 当前 UI 是"过渡态",**不是 spec A1 的三栏**(已与用户讲明,属"功能先行、结构后做"的有意分期)
|
|
||||||
现状 = 旧「二维地图/三维视图」切换 + 三个浮层/工具条:
|
|
||||||
- 左上「视图详情」(layerPanel):帘面/体素/地形 复选框;
|
|
||||||
- 右上「三维数据集栏」(axisBar):坐标轴/刻度/比例/快捷视图/Zoom;
|
|
||||||
- 左下「切片」(sliceBar):上下/前后/左右/任意/翻转/关闭。
|
|
||||||
渲染由 LocalSample 样本驱动:对象树勾选任意 TM → 映射成样本 ds `"grid1"`(main.cpp checkedTmsChanged 处)。
|
|
||||||
|
|
||||||
## 6. 下一步(用户即将定方向;我已建议先做①)
|
|
||||||
**① 三栏结构重构(建议先做,A1 顶层框架)**:把界面重组为 三维数据集 / 二维数据集 / 三维分析 三栏,各栏含:
|
|
||||||
- 数据集列表(按 ds 维度 3D/2D 过滤勾选对象的 ds,C9/C15;维度映射见 `I3dSceneRepository::dimensionOf`);
|
|
||||||
- 三维分析栏的树(按 对象/三维体模型/切片 结构,C19);
|
|
||||||
- **右键菜单创建切片**(D21/F22-25:右键三维体→上下/前后/左右/任意切片;现在是用左下浮层按钮代替,须改成右键)。
|
|
||||||
**② P4 功能**(结构之后或并行):
|
|
||||||
- 切片 CRUD:保存/保存为/导出图片/导出dat/删除为数据集(F30-33/D47/E51-53)——`I3dSceneRepository` 已留 SliceSpec/createSlice 等接口位(spec §6.3),本轮内存态。
|
|
||||||
- 创建异常+异常体管理(D48/E49-50/A69-C88):异常=切片面上的 2D 多边形(复用 core::Anomaly);异常体树/删除/属性/VTK↔列表联动/显示过滤/截图属性。
|
|
||||||
- 三维体/切片详情(A58-C67):源数据/切片/异常/插值模型(IDW·克里金)/参数/色阶/测量(点数·体积);切片详情参照 dd_section。
|
|
||||||
- 任务管理(A90-C92):任务记录 + 可使用任务列表(按 ds 类型过滤 model/list)。
|
|
||||||
**③ P5 二维数据集栏**:底图(天地图/Google/隐藏)+2D视图位置(关闭/Z=0/顶部/底部/自定义Z)。VTK 瓦片层+EPSG:3857→GeoLocalFrame 配准(复用 TerrainActor 流程)。
|
|
||||||
- 待精修(需 Geopro **1.0** 实地参考,目前无):F26 色阶"参考1.0"、F50 异常保存框"参考1.0"。
|
|
||||||
|
|
||||||
## 7. ⚠️ 构建/验证铁律(务必遵守,否则重蹈本会话覆辙)
|
|
||||||
- 构建用 `build.bat`(已修好)。从 Git Bash 调:`cmd.exe /c "chcp 65001 >nul && cd /d D:\Git\lanbingtech\geopro && .\build.bat test"`。命令:`app`/`run`/`test`/`rebuild`(--clean-first 强制全量重编+启动)/`configure`。
|
|
||||||
- **ninja 增量偶发漏编** → 改了代码却"看不到效果"时,用 `build.bat rebuild` 或 `touch` 改过的源再编;验 exe 新鲜:`stat -c '%y' build/release/src/app/geopro_desktop.exe`。
|
|
||||||
- **切勿 `rm -rf build/release`**(vcpkg.json 虽已加 baseline,但重配会从源码重编 openssl/gdal/proj,慢;增量链接错用 `--clean-first`,别删目录)。
|
|
||||||
- **.bat 必须纯 ASCII**(中文 Windows cmd 按 GBK 解析 .bat,UTF-8 中文注释会让解析崩)。
|
|
||||||
- **Claude 工具跑 build 会间歇被一个 `Start-Process 'C:\Users\corey\...'` 钩子劫持**(环境问题、非项目;只影响 Claude 工具,不影响用户终端)→ 我的构建验证有时静默没跑,会误判"已更新";**交互类改动必须让用户在其终端 `build.bat rebuild` 实测**。
|
|
||||||
- **Claude 无法 GUI 测试**:VTK 交互(切片/旋转/拾取)的正确性只能靠用户实测——纯逻辑(几何/相机数学)抽成单测,widget 行为靠目视。
|
|
||||||
- app 启动需登录(真实 API,tenant.geomative.cn);勾"记住登录(30天)"可免登。
|
|
||||||
- 详见记忆 [[build-vs2026-vcpkg-gotchas]]、[[build-run-verify-gotchas]]、[[build-ninja-stale-shared-header]]。
|
|
||||||
|
|
||||||
## 8. 代码地图
|
|
||||||
- `src/render/actors/`:Scatter/GridContour/Voxel(GPU体绘制)/Anomaly(2D)/Terrain/Curtain/MapLine/Electrode/**AxesActor**(P2)。
|
|
||||||
- `src/render/`:Scene(addActor/addViewProp/clear=RemoveAllViewProps)、CameraPreset(Top2D/Free3D/applyView6向/zoomBy/fitView)、VoxelFromScatters、ColorLutBuilder、ContourBands。
|
|
||||||
- `src/render/interact/`(P3):SlicePlaneMath(纯几何,有单测)、SliceTool(封 vtkImagePlaneWidget;轴向 SetPlaneOrientationTo*+MarginSize0 禁旋转;任意 Origin/Pt1/Pt2 45°可旋转;SetLeftButtonAction(SLICE_MOTION);onInteract 选中回调)、PickInteractorStyle(自定义 Rotate 绕支点+滚轮+手动双击)、InteractionManager(切片增删/选中/滚轮/翻转/双击正视/getRotateCenter)。
|
|
||||||
- `src/controller/`:VtkSceneController(QObject 编排,异步回调 QPointer+generation 守护)、I3dSceneView(抽象,解耦 VTK)。
|
|
||||||
- `src/data/repo/`:I3dSceneRepository(异步接口:dimensionOf/loadVolume(VolumeGrid)/loadTerrainPaths,切片/异常/任务签名留位)、LocalSample3dRepository、IDatasetRepository、LocalSampleRepository。
|
|
||||||
- `src/app/`:VtkSceneView(I3dSceneView 实现)、main.cpp(buildWorkbench 内全部接线 + 三个浮层/工具条 + InteractionManager 创建于 ~309)。
|
|
||||||
- 测试:`tests/render/`(test_scene/test_camera_preset/test_axes/test_slice_plane_math)、`tests/data/`(test_3d_repo)、`tests/controller/`(test_vtk_scene_controller)。
|
|
||||||
|
|
||||||
## 9. 工作方式(用户偏好)
|
|
||||||
- 派 opus subagent 实现 → 完成后**我亲自**独立验证构建/测试 + 派 cpp-reviewer 审查 + 查 code 与 spec 符合度 → 修 CRITICAL/HIGH。
|
|
||||||
- 不要嘴上保证"编进去了"——用证据(ctest 输出、exe mtime、读改动文件)说话。
|
|
||||||
- 抠准每条需求(本会话因没抠准 G22-24/F25/D40 反复返工,务必先逐条读「补充需求」对应行)。
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue