geopro/docs/superpowers/plans/2026-06-07-m1-view-redesign.md

61 lines
5.8 KiB
Markdown
Raw Permalink 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.

# M1 视图重构:按目标用户(物探工程师)与原型对齐的正确模型
> **背景**:前几版把"单数据集反演剖面"当成主视图、把 2D/3D 做成相机角度(平面剖面下无意义)、把体素塞成树兄弟节点 —— 均为脚手架,偏离产品。本计划按**原型 + 目标用户工作流**重建。REQUIRED SUB-SKILL: subagent-driven-development。
---
## ✅ 实施结果与关键修正2026-06-07经离屏 PNG 核对,已合入 feat/m1-core
**Task A、Task B 均已完成并接入 app**(详见 STATUS §1)。实施中**修正了本计划最初一处错误模型**,以下为**最终正确做法**(下次照此,勿回退):
- ❌ 原设想"二维地图 = 俯视帘面顶边" **不成立**:竖直帘面俯视只剩一条发丝线 → 俯视图基本空白(已用 `verify_curtain_top.png` 证实)。
-**正确**:**二维地图 与 三维视图 是两种不同渲染内容**(不是同一物体换相机):
- **二维地图** = `render::buildSurveyLine`(`MapLineActor`):测线 `lat/lon` 轨迹画成**红色折线**俯视(浅底)。
- **三维视图** = `render::buildCurtain`(`CurtainActor`):竖直断面墙,**z 取负**(深度向下不倒置)、**纵向夸张 actor->SetScale(1,1,3)**、**分段色带**(colorBar 真实分段值,非连续插值)。墙沿弯曲测线弯属真实。
- **数据详情** = `render::buildGridContour`:#18 平面剖面,**y 取负 + 显式 structuredGrid(不假设等距)+ colorBar 真实分段值 + 纵向夸张 SetScale(1,1.5,1)**。
- ✅ 坐标统一:三者共用 `core::GeoLocalFrame`(lat/lon→局部米)。体素(projX/Y,CRS 未确认)暂不接入。
-**验证手段**:`tests/spike/render_verify.cpp` 离屏渲 PNG 肉眼核对(本会话教训:必须看像素)。
---
## 目标用户与工作流(物探/地质工程师)
看测区/测线/数据集 → 在**地图**看测线布在哪 → 看某测线的**反演剖面**圈定异常 → 在**三维**看断面空间结构/体素/地形。
## 正确模型(对齐原型四区)
- **左 对象树**:GS→TM→DS,复选框勾选 → 控制在中央场景显示哪些测线。
- **中央 二维地图 / 三维视图**:**同一个 VTK 3D 场景 + 一个相机开关**(spec §5.3/K-1「VTK 一统」):
- 关键:**剖面渲染成"竖直帘面"**——沿测线 `lat/lon` 立在世界坐标,纵向为深度 `y`,面上按 `colorBar` 着色 `v[j][i]`
- **二维地图** = 俯视正交相机 → 看到测线(帘面顶边)俯视布局,像地图(底图瓦片 M1.5,M1 先浅底+经纬/比例)。
- **三维视图** = 透视相机 → 看到立体的断面墙、空间关系。
- 因内容是立体的,2D/3D **真有区别**(俯视=线、透视=墙)。
- **下方 数据详情**:选中数据集 → 该数据集**专业分析图**(ERT 反演剖面 #18:平面 banded 等值面+等值线,带色阶;异常标注后续)。独立 QVTK,**不是中央主图**。
- **右 异常列表 / 属性**。
## 坐标统一(帘面/地图共用世界系)
- 世界系 = **lat/lon → 局部米(等距圆柱投影)**:`x=(lon-lon0)*111320*cos(lat0)`, `y=(lat-lat0)*110540`,原点取测区中心。`core/geo` 加 `GeoLocalFrame`(或复用 CrsTransform EPSG:4326→局部)。
- 网格有 `lat[100]/lon[100]`(测线水平迹线)+ `y[22]`(深度/高程)→ 帘面点 `(x_i,y_i, y[j])`,值 `v[j][i]`。多条测线共用同一世界系 → 自动配准。
- **体素搁置**:散点只有 `projX/projY`(真实 CRS 未确认,§5),无法与 lat/lon 帘面配准 → 本次不做;CRS 确认后回归(STATUS §5)。
---
## Task Arender — 地理局部系 + 帘面 Actor
**Files:** `src/core/geo/GeoLocalFrame.{hpp,cpp}`、`src/render/actors/CurtainActor.{hpp,cpp}`、`tests/...`
- [ ] `GeoLocalFrame(lat0, lon0)`:`Xy toLocal(lat, lon)`(等距圆柱);单测一两个点。
- [ ] `CurtainActor::build(const core::Grid& g, const core::ColorScale& cs, const GeoLocalFrame& frame)→vtkActor`:`vtkStructuredGrid`,点 `(i,j)` = `frame.toLocal(g.lat[i], g.lon[i])` 的 (x,y) + z = `g.y[j]`(深度,向下可取负或按高程);标量 `v[j][i]`;`vtkDataSetMapper` + LUT(复用 `buildLut`);返回 actor(竖直帘面)。单测构建不崩 + 点数 = nx*ny。
- [ ] render CMake 按需加 VTK 组件(已有的够则不加)。提交 `feat(render): GeoLocalFrame + CurtainActor(测线竖直帘面)`
## Task B工作台布局重建(中央地图/3D 单场景 + 下方数据详情)
**Files:** `src/app/main.cpp`(重构布局)
- [ ] 布局:左 对象树(复选框)/ 中 单一 QVTK 场景(帘面)/ **下 数据详情 QVTK(平面 #18)** / 右 属性。中央工具条只保留「二维」「三维」相机开关(去掉体素按钮)。
- [ ] 中央场景:勾选 DS(dd_section)→ 用 `GeoLocalFrame`(由该测区 lat/lon 范围定原点)构建 `CurtainActor` 加入场景;取消勾选移除;多测线共存。「二维/三维」切相机(`applyTop2D`=俯视正交、`applyFree3D`=透视),作用整场景。
- [ ] 下方数据详情:选中(单击)DS → 在独立 QVTK 用 `buildGridContour`(平面 banded #18)显示该数据集剖面 + 属性(nx×ny/vmin/vmax)。
- [ ] 去掉树里的「三维体素」节点(repo loadStructure 改回只含网格 DS)+ 去掉 voxel 相关 UI(代码可保留 VoxelActor/buildVoxelFromScatters 备用,但不接入 UI)。
- [ ] 构建(先 taskkill)+ 冒烟。提交 `refactor(app): 中央地图/3D 单场景(竖直帘面)+ 下方数据详情(#18), 去除混乱模式与体素节点`
## 验收(登录后人工)
- 勾选测线 → 三维视图里出现**立着的彩色断面墙**;
- 切「二维」→ 俯视看到测线(墙顶边)布局(像地图);「三维」→ 立体墙,**二者明显不同**;
- 单击数据集 → 下方"数据详情"出现平面反演剖面(#18);
- 不再有"三维体素"兄弟节点、不再有内容/相机混淆。
## Self-Review
- 对齐原型四区 + spec §5.3/K-1 单场景相机;剖面=竖直帘面使 2D/3D 有真实区别。
- 体素搁置(CRS 未确认),诚实记录,非省略。
- 回写 spec §4/§9 + STATUS。