# 交接:VTK 三维视图(feat/vtk-3d-view) > 给下一个会话无缝接手用。更新日期 2026-06-18(#4 异常功能全部收口后)。分支 `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` 误纳、已撤回)。 > > **进度速览(2026-06-18)**:补充需求 #1 生成三维体 ✅、#2 切片交互 ✅、#3 切片生命周期 ✅、#4 异常(圈定/保存/列表/异常体/过滤/显隐/删除/选中高亮/属性对话框)✅、#6 体/切片数据详情对话框 ✅ 全部完成、编译绿、用户实测通过。最新提交 `b97ea68`(#6 详情对话框)。**剩下全是收尾/打磨项**(见 §4 末「下一步候选」),无进行中的半成品。下一会话应先问用户选哪个方向,或直接接其指定项。 > > **附**:Windows 安装包打包工具已落地(`installer/`,提交 `0504129`):`build.bat app` 后 `powershell -File installer\build_installer.ps1` 一键出 Inno Setup 安装包(自动 windeployqt 补 Qt 运行时+绕过 ADS 卡死、补 VC 运行时、中文向导)。 ## 1. 背景 - 项目:geopro 桌面客户端(Qt6 + VTK9 + Qt-ADS dock),Windows/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. 当前状态(2026-06-18 更新) - 底图/地形/剖面配准/增量渲染:**完成且可用**。编译绿。所有改动已提交到 `feat/vtk-3d-view`。 - **#1 客户端「生成三维体」流程:已实现并经本会话大量使用验证**(切片/异常都在生成的体上操作过,间接验收)。详见计划 `docs/superpowers/plans/2026-06-17-vtk-3d-volume-create-flow.md`。 - 已落地:`data::VolumeBuildParams`(不冻结 gridSpec,源 ds 锁定不变式);`core::buildVolume` 共享管线(LocalSample/Api 同源);`Api3dRepository` 内存体存储 + `createVolume/volumeRows/isVolumeDataset` + 多源 `loadVolume`(复用 `loadSection`,竖向=g.y 高程,与帘面对齐;`fitAxis` 按 extent 增大 cell 以覆盖跨 TM 全范围);`loadVolume` 回调交付 `(VolumeGrid, ColorScale)`;`Column3DDataset` 多选+右键「生成三维体」(按**勾选框**选中集,非行选)+ `VolumeParamsDialog`;**生成的体归三维分析栏**(`Column3DAnalysis`),main.cpp `refreshAnalysis` 合并注入 + `pushChecked` 两栏勾选聚合;`VtkSceneController` 按 `isVolumeDataset` 分流体素/帘面。 - **#2/#3 切片:完成且用户实测通过**(提交 afdd98f+d56e35f)。四向创建/滚轮推进/双击正视/翻转/关闭/选中高亮;VTK 右键菜单(创建异常/保存/导出▸图片·dat/正视/翻转/关闭);未保存↔已保存统一状态模型(保存按状态分派、无重复切片);精确三点几何持久化;场景↔列表勾选双向同步。导出 `SliceExport`。切片持久化=`Api3dRepository` 内存 mock。 - **#4 异常:完成且用户实测通过**(见 §4 第 4 项,4a→4c-3,最新 c83f63a)。圈定→保存→渲染→列表→异常体分组→过滤→显隐→删除→选中高亮→双击属性,全链 mock。 - **剩余 = 收尾/打磨项**(§4 末「下一步候选」表):体/切片详情面板、真实色阶编辑、三级树根层、坐标轴弹框、真实后端对接(阻塞)、收口 PR。**无进行中的半成品**。 ## 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上色 PNG;dat=重采样标量网格)。切片持久化=`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 ✅ 已提交(c83f63a)**:异常属性对话框(R83,双击异常列表项弹只读:名称/类型/标记类型/归属三维体/异常体/顶点世界坐标/备注);`AnomalyPropertiesDialog`。**截图字段:模型/端点均无,不展示**(保存对话框截图为 mock 未持久化)。 - **#4 异常功能收口** ✅(4a→4c-3 全做完,编译绿+用户实测通过)。**剩余已知限制**:① 反向(VTK 点异常→回选列表)未做(需异常 actor 拾取);② 单条显隐状态跨 refresh 不持久;③ 全链 mock(三维体/切片端点未就绪),端点就绪后切真实。 5. 分析栏右键接线:**已完成**(切片 保存/保存为/导出▸/删除 全接;体 切片▸/详情);`colorScaleRequested` 仍占位("色阶开发中")。已移除"显示/隐藏"(勾选即显隐)。 6. 三维体/切片/异常详情:**✅ 全部完成**——异常详情对话框(4c-3);体/切片详情对话框(#6,提交 b97ea68)。形态统一为只读属性对话框,非停靠面板。 - **其它小欠项**:三维分析栏完整三级树"对象→三维体→切片"里"对象"根层未套(体目前是顶层);真实色阶编辑。 **其它小项**:坐标轴「O点位置」「字体」弹框仍是 stub(main.cpp:382 TODO P4)。 ### 下一步候选(2026-06-18,主体功能已完结,以下均为收尾/打磨;下一会话先与用户确认方向) | 候选 | 性质 | 阻塞 | 要点 | |---|---|---|---| | ~~**#6 三维体/切片 数据详情**~~ ✅ 已完成 | 功能补全 | 否 | **已做(提交 b97ea68)**:只读属性对话框(非面板,仿异常详情)`VolumePropertiesDialog`/`SlicePropertiesDialog`,右键「数据详情」按 ddCode 分派。体=参数+统计(值域/网格/测点数/范围,仅 loaded 时显);切片=位姿/参数(不含统计,切面网格仓储不持久化)。`Api3dRepository::volumeInfo` getter + `StoredVolume.pointCount` 持久化;接口/LocalSample 零改。设计见 `specs/2026-06-18-vtk-3d-volume-slice-detail-dialog-design.md`。**已知限制**:切片采样分辨率/值域需渲染层回写仓储才有,当前不展示。 | | **真实色阶编辑** | 功能 | 否 | `colorScaleRequested` 现占位("色阶开发中")。做成色阶编辑器,影响 体/切片/帘面 渲染观感。 | | **收口提 PR 合 main** | 流程 | 否 | 分支已积大量提交。`git diff main...HEAD` 起草摘要+测试计划,`-u` 推送。注意勿纳未跟踪文件。 | | **三级树 对象→三维体→切片** | 结构打磨 | 否 | `Column3DAnalysis` 体目前是顶层,缺"对象"根层(R 结构)。 | | **坐标轴 O点/字体弹框** | 打磨 | 否 | main.cpp 内 stub(TODO P4)落实。 | | **真实后端对接** | 切真实 | **是** | 三维体/切片端点未就绪,现全 mock(`Api3dRepository` 内存)。端点就绪后只换 `I3dSceneRepository` 实现,接口不动。异常端点已挖到(§4 头),但其挂载目标(三维体)仍 mock,故异常也整链 mock。 | ## 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**)。