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

5.8 KiB
Raw Permalink Blame History

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/geoGeoLocalFrame(或复用 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。