12 KiB
12 KiB
交接: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 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_+ DEMdemCache_,跨隐藏/重选保留 → 重选秒出。 - 合并渲染
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.cpplastAnalysisRows+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,按依赖排序):
三维体 mock 渲染✅ 已实现(编译绿,待 GUI 实测)——见 §3 与计划2026-06-17-vtk-3d-volume-create-flow.md。Api3dRepository::loadVolume已接通(多源复用 loadSection → IDW → VolumeGrid + 色阶交付);VolumeBuildParams必存参数、values 惰性重算+缓存(不冻结 gridSpec,改用源 ds 锁定不变式,留校验 TODO)。切片交互接通三维体✅ 已有(SliceTool/InteractionManager:四向创建/滚轮推进/双击正视/翻转/关闭/选中高亮全在)。- ✅ 已实现(3a,编译绿,未提交,待 GUI 实测)——VTK 视图切片右键菜单(
PickInteractorStyle右键→InteractionManager::onSliceContextMenuRequested→main.cpp 弹 QMenu):正视图/翻转/关闭(接现有)、导出图片(PNG)/导出dat(SliceExport.{hpp,cpp})、保存(Api3dRepository::createSlice内存 mock→dd_slice 行进三维分析栏、挂父体下,sliceRows()+refreshAnalysis合并)、创建异常(占位→#4)。deleteSlice亦改 mock。- 3b 待做(拆出):已保存切片在三维分析栏勾选后的重渲染(切片现仅为交互 widget,从 spec 重建需重构面内两轴 + 与父体加载排序 + 跨层编排);分析栏的保存/另存/导出(依赖重渲染)。
- 异常:切片右键创建异常(圈定+保存对话框含截图)→ 接真实端点。VTK 切片右键菜单的「创建异常」入口已占位。
- 分析栏右键接线:部分完成——
visibilityToggled(显隐,VtkSceneView::toggleDatasetVisibility)、sliceDeleteRequested(删 mock 切片+刷新) 已接;colorScaleRequested占位;sliceSave/SaveAs/Export(分析栏入口) 待 3b。 - 三维体/切片/异常详情面板(源数据/插值参数/色阶/测量点数体积/异常列表)。
其它小项:坐标轴「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,同原版,可提交)。
- 全部回复中文。
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(真实路径,多为 stubkNotReady,待按设计文档实现)。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)。