Commit Graph

74 Commits

Author SHA1 Message Date
gaozheng eef8188bcb feat(3d): 色阶跨视图同步真源 + 三维体/切片白化与不透明度重做
- 跨视图色阶单一真源 DatasetViewState:2D详情/3D帘面体共用按dsId的色阶,编辑→真源
  →各视图实时联动且无信号回环;散点(type1) load-then-save 回写,避免覆盖网格的
  lineConfig/层级方案(共享同一条 businessCode="" 后端记录)。
- 色阶两级透明度:ColorScale.globalOpacity 独立存储不烘焙、渲染时与每色 alpha 相乘;
  对话框回显真实值、单色独立;properties 补全 lvlSchemeType/logLinesCount/
  equalAreaLayerCount,避免整条覆盖写清空;"整体透明度"改名"不透明度"、显示 0~100。
- 切片白化:SetWindowLevel 钉死 [vmin,vmax] + LUT 0号白化槽,哨兵真透明
  (tests/spike/slice_alpha_probe.cpp 真 widget 离屏实测);同时纠正切片颜色映射。
- 切片不透明度:与三维体解耦的独立模型(100%/三维体+50%/跟随),默认100%;保存切片建
  自己的色阶对象(颜色快照+不透明度),已保存切片走列表右键"色阶"编辑自身。
- 三维体白化:二值 mask 真白化(NoData 排除出插值,符合 ESRI/GDAL/Surfer 标准);改体
  色阶改为原地更新传函(不重建image),未保存切片不再被刷掉且跟随改色;GPU 探测+CPU
  回退;体不透明度归一为色阶"不透明度"单一控制(去 kMaxOpacity、移除工具条"透"滑块)。
- 持久化:网格视图补 saveColorGradation;DatasetChartDto.parseColorBar 回读 opacity。

详见 docs/superpowers/specs/2026-06-27-inversion-3d-volume-surfer-method-and-gaps.md §7。
2026-06-28 22:14:46 +08:00
gaozheng 4f6abf0c83 feat(3d-view): 三维体渲染稳定性修复 + 透明度可调/交互优化
- 修偶发"不渲染/淡蓝/很实"根因:合并体值域取"首个到达源色阶"随网络到达
  顺序抖动→改取所有源色阶 vmax 中位者(确定性+抗单线离群)
- 体素标量 double→float:GPU 体绘制对 double 处理不稳/间歇出空,float 更稳且省显存
- 源剖面加载瞬时失败(如后端 502)自动重试,避免一条抖动致整体建不出;失败弹 toast 不再静默
- 退化薄体(共面剖面 ny/nz=1)网格每维补到≥2,避免 vtkGPUVolumeRayCastMapper 拒绝渲染
- 三维体透明度可调:工具条「透」按钮+弹出滑块(默认 0.30,实时改已渲染体)
- 工具条 z 序修复:引导层挂 vtkWidget 并 raise,工具条/提示再 raise 其上(缩小渲染区不再被挡)
- 收起左栏同步 QSplitter 尺寸,消除残留空白
- 切换项目清空三维体/切片/异常列表
- VTK 警告/错误转 Qt 日志,不再弹独立 vtkOutputWindow 窗口
- 勾选非三维体 ds 首次加载也显示等待动画(复选框↔spinner)
- 新建三维体后该行多拍重试滚动到分析栏顶部
2026-06-27 18:32:07 +08:00
gaozheng 9b4f172809 fix(3d-view): 二维/三维分析切换时取消前视图选中
三维分析选中切片后切到二维分析,残留的selected_使InteractionManager::onWheel
持续消费滚轮(二维下无法缩放),且切回三维仍残留高亮。setMode2D进入二维时清切片
选中+高亮,并经onSliceSelectionChanged("")联动清三维分析列表选中行与异常高亮。
与VtkSceneView::setAnalysisMode2D离开二维时clearMapLineSelection清足迹选中相对称。
2026-06-26 23:43:26 +08:00
gaozheng bdebe54859 feat(3d-view): 二维分析B期(足迹高程Z拖动)+选择联动/滚轮升降/工具条禁用
- B期:二维分析里选中足迹(单击/Ctrl 多选)→ 竖向拖动只改世界 Z(锁 XY)、
  顶部实时高程读数浮层;Z 偏移按 dsId 持久(切走再回/全量重建保留)。
  VtkSceneView 加 pickMapLineAt/nudgeSelectedMapLinesZ/selectedMapLineZ(vtkCellPicker
  +PickFromList 只拾可见足迹、选中黄高亮加粗、mapLineZOffset_ 持久);PickInteractorStyle
  lock2D 下命中足迹→Z 拖动(onPick2D/onDrag2D/onDrag2DEnd + worldPerPixelZ 像素→世界Z);
  InteractionManager::pickStyle() 暴露样式;main.cpp 接回调 + 读数浮层。
- 列表↔VTK 双向选择联动:Column2DDataset 多选行 + selectedDatasetsChanged/setSelectedDsIds;
  VtkSceneView onMapLineSelectionChanged/setSelectedMapLines;两向各自断环。
- 滚轮升降:onWheel2D——有选中足迹时滚轮改其 Z(一格≈拖动24px)、消费滚轮,否则缩放;
  读数浮层滚轮后 1.2s 自动隐藏。
- 工具条:二维分析激活禁用 6 向快捷视图(会改朝向破坏近俯视锁定),切回三维恢复。
2026-06-26 21:56:45 +08:00
gaozheng 6a10975b6b feat(3d-view): 二维分析A期(一场景两相机)+视图切换/底图/增量修复
- 切「二维分析」tab:锁近俯视(下压12°≈78°)、禁旋转(左键平移=仅平移+缩放)、
  按维度翻 actor 可见(轨迹↔体/帘面/异常,不清空)、切片 SetEnabled 显隐、坐标轴在二维移除;
  地形+底图常驻。ColumnDrawer 新增 analysisModeChanged 信号串起三处协作。
- 修复切回三维数据不取景:按目标维度重置取景基线(VtkSceneController::onAnalysisModeChanged),
  computeDataBounds 只计可见 prop,render 朝向认 analysisMode2D_。
- 修复底图在远离锚点的数据处为空(如台湾,frame 锚深圳):底图取瓦片中心+距离剔除
  改用相机焦点(cenX_/cenY_)而非坐标系原点。
- 修复删到空不重锚致底图错位:removeDataset 清空 dsProps_ 时复位 frameAnchoredToData_。
- 修复二维分析列表非增量:对象树勾选刷新保留已勾选足迹(对齐 CategorySection::rebuildList),
  不再清空渲染/丢失列表选中。
- 新增控制器回归测试 2 项(切模式取景基线)。
2026-06-26 20:53:53 +08:00
gaozheng f230ca8dd1 fix(3d): 异常绘制提示中文乱码(改 QLabel 浮层) + 列表切到别对象清切片选中
1) 提示"乱码":vtkTextActor 用 VTK 内置字体不含中文字形 → 中文渲染不出(只剩 ASCII)。
   移除 VTK 文本提示,改 app 层右上角 QLabel 浮层:Qt 渲染中文 + QSS(深底/accent描边/圆角),
   绘制开始按形态显示结束方式、结束/取消隐藏;不挡画布鼠标。
2) 列表选中切片后切到别的对象(三维体/异常),VTK 切片仍高亮:datasetSelected 选非切片对象时
   未清切片选中。加 InteractionManager::deselectSlice();选异常/其它对象均清切片高亮(异常↔切片互斥)。

测试:439/439 通过
2026-06-26 16:06:07 +08:00
gaozheng 306d7bc46e fix(3d): 异常绘制提示移右上角美化 + 线双击结束含双击位置
1) 操作提示从左上角(被工具条挡)移到右上角:深底+accent描边+右对齐+分行(标题/结束方式/取消),
   按当前形态显示对应结束方式。
2) 线双击结束改为"含双击位置"(同地图工具):去掉之前的回滚——双击第一下的落点即为末顶点。
   单/双击不再需要回滚隔离(双击第二下只 finish 不加点,无重复顶点)。
2026-06-26 15:41:12 +08:00
gaozheng d7ab7705c9 feat(3d): 切片保存后定稿锁定(不可移动/旋转)+ 菜单去保存·另存
按用户口径:切片保存后即定稿,不可再改。
- SliceTool::setInteractive(false) 关 widget 鼠标交互(锁移动/旋转,纹理仍显示;拾取选中/右键由
  PickInteractorStyle 独立处理不受影响)。tagSelectedSlice(临时→保存)与 showSavedSlice(重显已保存)均锁定。
- VTK 右键「保存」仅对未保存(临时)切片显示;已保存切片无保存项。
- 数据列表切片右键去掉「保存/另存」(列表中切片均为已保存=锁定),留 详情/导出/色阶/删除。

测试:439/439 通过
2026-06-26 15:17:54 +08:00
gaozheng 91a71064b2 feat(3d): 创建异常结束手势按业界通用做法重做(点单击/线双击/面点起点闭合)
双击作主手势别扭(与单击天然冲突)。按业界通用改:
- 点:左键单击即落点并完成(无需双击/回车)。
- 线:双击完成(保留)。
- 面:点回起点闭合(≥3点,屏幕邻近 12px 吸附);光标近起点时橡皮筋指向起点预览闭合,提示文案更新。
Esc 取消 / Backspace 撤点不变。
2026-06-26 15:17:53 +08:00
gaozheng 4ae8286bb0 fix(3d): 异常截图配色与切面一致——取 widget 同源着色输出(非另建 LUT)
用户实测异常截图与切面渲染配色差异极大(切面暖色彩虹、截图偏冷蓝绿)。根因:selectedSliceColorImage
另建 buildLut(v->cs,vmin,vmax) 上色, 与屏幕切片 widget 的实际着色可能分歧(范围/血缘处理不同)。
改:SliceTool 暴露 coloredResliceImage() = widget->GetColorMap()->GetOutput()(屏幕切片所贴的同一
RGBA 像素, 逐像素一致, 外区 alpha=0); selectedSliceColorImage 改取它再双线性上采样到 2048。
captureAnomalyShotFromSlice 处理 RGBA → 外区透明(顺带消除截图蓝边)。导出图片同样受益(与屏幕一致)。

测试:439/439 通过
2026-06-26 11:56:33 +08:00
gaozheng d470dc8154 fix(3d): 双击与单击隔离 + 异常类型下拉误显「暂无数据」
双击结束时"第一下"会先触发单击(点会移/线多一段/面多一条边)。修:每次单击前快照 pts_,双击时
先回滚那一下(pts_=快照)再 finish → 双击纯结束,不再附带加点/移点。

EmptyAwareComboBox::realItemCount 用 itemData(i,UserRole-1) 取 flags 是错的(非 Qt flags 角色),
对正常项恒判不可选 → 计数恒 0 → 有真实项(异常区)也误插「暂无数据」。改用 model()->flags()。

构建:app 链接通过
2026-06-26 11:49:14 +08:00
gaozheng 04af569b7d fix(3d): 创建异常返工(点交互/点渲染/截图/类型空态)——前一轮质量不过关
#1 点模式还拉线:updateRubber 点模式直接 return,不画末点→光标橡皮筋。
#3 点不是小球:AnomalyActor 点分支 + 绘制预览均开 RenderPointsAsSpheres,点径 13px → 真小球(非扁平方点)。
#4 截图整窗方框→改对:captureAnomalyShotFromSlice 只从切片 2D 剖面彩图、按异常几何向外缓冲一圈裁剪
   (GIS buffer+掩膜:点→圆/线→胶囊带/面→外扩多边形,缓冲外透明,再描轮廓);worldPts 经平面 o/e1/e2
   归一映射到图像像素(Qt QPainterPath/Stroker)。无切片图时回退相机框景。
#2 类型/样式选择"消失":异常类型下拉补占位「请选择异常类型」,空(该形态平台无类型)时显灰占位+「暂无数据」。

注:本项目平台「点」类型为空,故点的类型下拉确实无项——需平台先建点类异常类型。

测试:439/439 通过
2026-06-26 11:31:04 +08:00
gaozheng 58544ffb3c feat(3d): 创建异常支持点/线/面三态(子菜单+统一双击·回车提交)
按原型「创建异常→点/线/面」改造:
- 右键菜单单项「创建异常」→ 点/线/面 子菜单;形态(1/2/3)同时驱动绘制 mode、a.markType、
  对话框查平台类型的 remarkSourceType(core::AnomalyMarkType 与 remarkSourceType 同值,一个 shape 贯通)
- AnomalyDrawTool 泛化 DrawMode{Point,Line,Face}:点≥1(再点重定位微调)/线≥2(开放)/面≥3(闭合);
  最少点数按模式;分形态屏幕提示
- 交互按锁定规范:**双击/回车 提交**(去掉右键提交,右键绘制中消费不响应保留菜单语义);
  **Backspace/Delete 撤上一点**;Esc 取消
- AnomalyActor 已支持点(verts)/折线/闭合多边形三态渲染,无需改

测试:439/439 通过
2026-06-26 10:36:38 +08:00
gaozheng 69e8790810 feat(vtk): 多三维体并发切片渲染重构(OPT-002:issue2+③+反向②)
核心:InteractionManager 单 image_ → 按 volumeDsId 的多体 map;各切片附着到各自体的 image。
- issue2 选第二个体→第一个体切片消失:setVolumeImage 不再 closeAll 全部切片;改 upsert 某体(同体重建
  才关该体切片)。syncSlices 改为「勾选 + 父体已渲染」即显示(不再限当前体)→ 多体切片并存
- ③ 右键体却建到 current 体:sliceRequested 带目标体 dsId;addSlice(axis,volumeDsId) 用该体 image;
  保存切片/创建异常的 volumeDsId 改用 selectedSliceVolumeDsId(选中切片所属体)而非 currentVolume
- 反向② VTK→树:InteractionManager.onSliceSelectionChanged(selectByTool/onPicked 触发)→
  CategorySection::selectItem 程序化选中(屏蔽信号防环路)
- VtkSceneView 按 dsId 存 volumes_(image/cs/vmin/vmax);addVolume 登记/removeDataset 移除并回退
  current/clear 清空;volume(dsId) 取指定体→色阶编辑支持非当前体;SliceTool 加 volumeDsId 标签
- nearestSlice 阈值/onWheel 步长/导出上色 改用切片所属体的 bounds/色阶

未解:④ 切片拾取串选(nearestSlice 启发式,VTK9.6 不暴露切片 actor 难精确化;widget 交互选中是精确的)

构建:app 链接通过;434/434 测试通过
2026-06-25 20:36:43 +08:00
gaozheng a2770ba49d fix(vtk): 坐标轴设置交互修复(批1/#5)-增量渲染+VE滑块+隐藏轴全隐+关闭按钮
- 5.1 关闭按钮空白:全局 QPushButton padding(6px14px) 挤掉 ×,显式 setStyleSheet padding:0
- 5.2 取消某轴「显示」时禁用其 min/max 编辑框(show toggled→lo/hi setEnabled,回灌同步)
- 5.3 隐藏轴后刻度数字仍在:SetXAxisVisibility 只关线,补 SetXAxisLabelVisibility/TickVisibility
- 5.4 应用即全量重绘→改增量:setAxesConfig 不再 rebuildInternal(clear场景),改
       view_.setAxes+setAxesRanges+renderIncremental(仅重建坐标轴 prop,不动数据/相机)
- 5.5 放大系数下拉→滑块(1~10×,恢复重构前交互):拖动实时改标签,sliderReleased 才发
       verticalExaggerationChanged 触发一次重建(VE 改几何须重建但不在拖动中连续重建)
       main.cpp 接 applied(去scale) + verticalExaggerationChanged(→控制器+底图)

构建:app 链接通过
2026-06-25 16:39:48 +08:00
gaozheng 6c8069b87d feat(vtk): 坐标轴设置真正生效-单位(米/英尺)换算+每轴显示开关+自定义刻度范围 打通 render→controller→view→面板 2026-06-25 14:16:27 +08:00
gaozheng fb944f706f feat(vtk): 常驻粗底图+局部高清叠加(永不空白)
ViewAdaptiveVolumeSource 构造时一次性在主线程建整卷最粗「各轴≤16384」层
单纹理底图 baseImage(),永远持有、永不释放、绝不被异步路径触碰——任何视角/
任何运动中底图都盖住整个体,拖动/缩放绝不空白。高清(currentImages)异步重组
当前视野后叠在底图之上局部覆盖,未就绪时只显底图。gpr_poc view 用两个 vtkVolume
(底图先渲、高清叠加),新增 --preview --base 出整卷概览底图截图。为 morph(C3-4)/
运动跟踪(C3-7)打两层结构。
2026-06-24 12:03:10 +08:00
gaozheng ced2ca7811 feat(render): AsyncRegionBuilder 就绪缓存LRU+预取+相同目标短路
C3-3:为 AsyncRegionBuilder 加按 RegionTarget 键的有界 LRU 就绪缓存
(容量N默认6)、prefetch 后台低优先预取(不抢占主目标)、getReady 非阻塞
缓存命中,并短路 requestTarget 相同目标(修 C3-2 LOW)。worker 每轮主
目标优先,否则建预取队列最新;缓存/refcount 增减全在锁内,析构干净 join。
ViewAdaptiveVolumeSource:updateView 提交主目标后预测下一目标(细一层
同区+沿相机方向平移一格 brick 列)并 prefetch;currentImages 走
getReady(主目标)命中即用否则沿用上一张。线程安全延续 C3-1。
2026-06-24 10:37:12 +08:00
gaozheng cec41e3539 feat(vtk): ViewAdaptive 接异步重组(update 不阻塞,view 拖动不卡)+修 C2 维度用 store.dims
把 C3-1 AsyncRegionBuilder 接进 ViewAdaptiveVolumeSource:updateView 只提交目标
(selectLod→RegionTarget→requestTarget),不在主线程重组、立即返回;currentImages/
sliceSource 经 builder.takeLatest 取最新已就绪(没新结果用上一张),空选区不提交、
保留上一张。新增 AsyncRegionBuilder::takeLatest(int&) 非破坏式重载随结果回传 level,
供 lastLevel 同步。

C2 MEDIUM:RegionReorganizer 维度改用 store.dims(level)(单一真源),弃自算
ceil(n/2^level),防 store 降采样规则漂移。

gpr_poc view 切异步:拖动中 InteractionEvent 持续提交目标(非阻塞)+33ms 重复定时器
非阻塞拉取后台就绪纹理换上→主线程不被重组卡住(跟手);preview/smoke/默认取景用
阻塞轮询保证拿到首图。

测试:ViewAdaptive 9 测(原 6 调为异步轮询版+新增 3:AsyncUpdateEventuallyReady/
UpdateDoesNotBlock(<50ms)/UsesStoreDimsNotSelfComputed),AsyncRegionBuilder 5 测仍绿;
全量 382 测通过。
2026-06-24 10:22:22 +08:00
gaozheng fa34cb0bc3 feat(render): C3-1 AsyncRegionBuilder 后台异步重组 + 双缓冲交接
抽公共重组核 reorganizeRegion(RegionReorganizer.{hpp,cpp})为单一真源:
C2 ViewAdaptiveVolumeSource 改委托、C3 AsyncRegionBuilder 也调它(真 DRY)。

AsyncRegionBuilder:后台 worker 调重组核构建 vtkImageData,主线程非阻塞
takeLatest 取最新就绪;requestTarget supersede 收敛最新不堆积。线程安全:
vtkImageData refcount 增减全在 mutex 内/单线程独占,析构置 stop 唤醒干净 join。

测试:5 个异步用例(同步一致/supersede 收敛/析构忙时干净 join/并发 400 次不崩
不死锁/takeLatest 非阻塞)全绿;C1+C2 的 17 个 ViewAdaptive* 抽核后回归全绿。
2026-06-24 09:56:55 +08:00
gaozheng fc9ea58cb5 feat(vtk): ViewAdaptiveVolumeSource 视野区域单纹理重组(C2)
用 C1 selectLod 选层选区,从 ChunkedVolumeStore 把当前视野区域重组为单张
VTK_SHORT vtkImageData(各轴 ≤16384,世界 origin/spacing 按 level+exagg),实现
IVolumeRenderSource。核心 updateView(CameraView,VolumeView) headless 可测。
gpr_poc view 切到该源(退掉 MultiBlock/budget 简化路径),--preview 渲默认视角存
PNG,--smoke 离屏不崩且 LOD 随缩放切换。
2026-06-24 09:24:31 +08:00
gaozheng 0da5accebe fix(lod): selectLod 最粗层兜底裁剪,保证返回区间恒不超 maxTextureDim
最粗层 fits||maxLevel 分支原先无条件返回,不校验 fits;合并体最粗层
全可见区间仍 >maxTextureDim 时返回区间会突破单纹理硬上限,C2 重组撞
GL 16384 纹理墙退回慢路。

新增 clampAxisToMaxTexture,在所有返回路径前按可见中心对称裁三轴到
重组单纹理各轴 <= maxTextureDim 的子区间;brick 本身 > maxTextureDim
的退化情形返回单块并由 C2 体素级再裁(契约见 hpp)。补 3 例边界测试
(brick>maxTextureDim、最粗层整卷超限、改写 RespectsMaxTextureDimAlways
为 brick!=maxTextureDim),原有用例全绿。
2026-06-24 09:09:01 +08:00
gaozheng fa348a2a9f feat(render): C1 视野自适应 LOD 选层(纯逻辑 headless)
selectLod(VolumeView,CameraView,maxTextureDim=16384)→LodSelection:
透视相机参数构 5 视锥面(左/右/上/下/近),保守 p-vertex 裁剪求该层可见
brick 区间;按 worldPerPixel 定最细不过采样层 Lmin,再逐级变粗直到区间
重组单纹理各轴 ≤maxTextureDim。远观→粗层整卷、近观→细层小块、视锥外→empty。
零 VTK/Qt 依赖,与 OutOfCoreSource 几何约定一致(level L 间距×2^L、维度 ceil(n/2^L))。
10 例 headless 单测覆盖远/近/侧/视锥外/极小 maxTextureDim/视距-层单调。
2026-06-24 08:57:32 +08:00
gaozheng 2beb97fa73 feat(vtk): 核外分块体绘制 OutOfCoreSource + renderC 基准(POC-C 命门探针)
OutOfCoreSource 实现 IVolumeRenderSource:相机选 LOD + 视锥裁剪选视野块 →
BrickPager(LRU,内存恒定)→ 每块 ≤64³ vtkImageData(带世界坐标)。renderC 用
vtkMultiBlockVolumeMapper 渲染工作集,绕开 GL_MAX_3D_TEXTURE_SIZE(16384)单轴墙。

实测(单线 store nx=44476>16384,renderB INVALID):
- 分块核外真渲出(非空像素,无纹理维度错),对照 renderB 整卷上传失败。
- 内存恒定:budget=64 驻留 64 块 / 220MB,与体总量无关。
- 静态工作集 9.5 fps;动态换页 1.45 fps(qUncompress 解压+每帧重建 mapper 177ms/帧,
  撞墙);fps 随块数近似反比劣化(256 块 0.47 fps)。结论与缓解见 poc-results-C.md。

含单元测试(纹理安全/budget 恒定/块世界坐标)。
2026-06-23 15:07:09 +08:00
gaozheng 5dbbb2576c feat(render): brick 分页器(LRU 工作集,内存恒定核外渲染)
实现 geopro::render::BrickPager:驻留 ≤ budget 个解压块,
按 LRU 淘汰,与体总大小无关。requestVisible 按请求顺序更新
LRU 并淘汰至预算;get 命中返回数据指针、不改 LRU。
键为完整 BrickId(含 level);std::list 记录 recency +
unordered_map 存数据与迭代器,touch/淘汰均 O(1)。
TDD:test_brick_pager 验证恒定驻留与最早块淘汰。
2026-06-23 12:08:29 +08:00
gaozheng cc3c5bf755 feat(render): IVolumeRenderSource 接缝 + WholeVolumeSource(B) 整卷重组
新增 B/C 共用的体渲染数据源接口 IVolumeRenderSource(meta/update/
currentImages/sliceSource),并实现 B 的 WholeVolumeSource:构造时读
ChunkedVolumeStore,遍历所有 brick 按全局坐标(vtkIdType 64 位)重组为
整卷 VTK_SHORT vtkImageData(含边缘块),供整卷体绘制与切片 reslice。

VoxelActor 新增 buildVoxelI16FromImage 重载:直接以预构建 VTK_SHORT
图像成体,传函/着色复用量化域逻辑(抽出 assembleVolumeI16),不改动
Task 7 现有 buildVoxel/buildVoxelI16 行为。

geopro_render 链 geopro_store;新增 test_whole_volume_source 校验
dims/类型/边缘块重组位置。
2026-06-23 11:23:37 +08:00
gaozheng b362156364 feat(render): VoxelActor 新增 buildVoxelI16 量化域体绘制
int16 量化体经 vtkShortArray 填 vtkImageData,vtkSmartVolumeMapper GPU 体绘制。
传递函数在量化域取控制点:qmin/qmax=q.toQ(vmin/vmaxPhys),颜色对每量化级用
q.toPhys 反查物理值再经 ColorScale 取色;kBlank→不透明度0(透明)。抽 assembleVolume
公用 mapper/property 配置,double 版 buildVoxel 行为不变。附无窗冒烟测试。
2026-06-23 11:12:25 +08:00
gaozheng 5e60446210 feat(vtk): 色阶编辑器(2D/3D共享)+模板库后端+剖面着色修正+二维数据集足迹
本会话主要交付:
- 色阶配置对话框 1:1 复刻原版(colorLevel/contourLevel/contourLine/colorEditor + colorUtils):
  左三列⚙表格(层级/线形/颜色) + 层级⚙/线形⚙/颜色⚙ 子对话框 + 连续渐变(直方图/读出/min-max/反转)
  + .lvl/.clr 导入导出;文案/校验对齐原版精确 i18n。
- lvl/clr 模板库接真实后端:IColorTemplateRepository + ApiColorTemplateRepository,
  另存/打开/新建色阶/配色方案下拉 经仓储注入 2D(GridDataChartView)与 3D(主对话框)。
- 剖面帘面着色对齐原版 threeContour.js getTerrainColor:上界 stop 取色 + 满 RGB,
  修正"色带整体下移一格 / 发浅发灰 / 丢 alpha"导致与原版差异大的问题。
- 二维数据集视图首切片:勾选轨迹类数据集 → 足迹平铺进 View3D 地图
  (Api3dRepository::loadMapLine 走 dd/ert/trajectory/line + MapLineActor + col2D 接线),
  view2DMode 控摆放高度,顶/底锚真实地表高程(zRefElev)。
- 测试 252 全绿。

并含本分支前序未提交的 UI 工作(ToastOverlay/TopBar/Theme/DynamicForm/若干 panel),
经 CMakeLists/main.cpp 纠缠,随此 checkpoint 一并提交。未纳入未跟踪的 png/yml 及审查报告 txt。
2026-06-22 12:48:45 +08:00
gaozheng 6210d615f3 feat(vtk): 异常圈定+保存闭环(#4b)+多项交互修复
#4b 异常圈定→保存→渲染→持久 闭环(异常挂三维体,mock 持久化):
- AnomalyDrawTool:切片平面上圈定多边形(屏幕射线-平面求交落点);左键加点(醒目黄圆点)、
  鼠标移动虚线橡皮筋(末点→光标跟手)、双击/右键/回车闭合、Esc 取消、左上屏幕提示;高优先级观察者绘制期独占输入
- AnomalySaveDialog:名称/异常类型(mock)/备注 + 截图预览及尺寸(R50)
- 切片右键「创建异常」接通:圈定→草稿渲染→截图→保存对话框→saveAnomaly(挂三维体)→红色多边形渲染
- onVolumeChanged→reloadAnomalies:体到场重载其异常(= 显示过滤"随数据集"默认档)
- SliceExport 加 captureRenderWindowPng(异常截图,带尺寸);Anomaly 补 exceptionTypeId/remark

交互修复(用户实测确认):
- 生成三维体**按勾选集合**(checkbox)收集源,不再受行高亮/右键项影响(撤销错误的多选子类)
- buildVolume 网格**覆盖全程**:包络过大时放大间距(fitAxis)而非截断 → 跨 TM 多剖面不再丢远端剖面
- 滚轮回退为"推进当前选中切片";点击切片外**取消选中**(取消后滚轮恢复相机缩放)
- 修圈定闭合误触切片:闭合事件提前 abort,避免漏给切片 widget 触发 slice-motion

文档:plans/2026-06-18-vtk-3d-anomaly.md §6 摆放决策(3D异常控制在三维分析区/右侧总表为全集)+§7/§8 状态;
  design spec 顶部更正块(异常挂三维体/remarkSourceType=标注形态/无截图字段/独立显隐);HANDOFF 更新到 4a/4b。

编译链接绿(build.bat app exit 0);4b 闭环 + 交互修复已用户实测通过。下一步 4c:三维分析区 3D 异常控制(树+过滤R86-87+VTK选中联动R84+显隐+删除)。
2026-06-18 18:31:46 +08:00
gaozheng 4e1b8e7635 feat(vtk): 异常3D基础(#4a)-Anomaly补3D几何+buildAnomaly3D+视图异常方法+Api mock持久化(挂三维体)
异常功能地基(对象→三维体→异常;异常挂三维体非切片,见记忆 vtk-3d-persistence-structure):
- core::Anomaly 补 id/volumeDsId(=remarkSourceId)/consortiumId/worldPts(3D世界点)/planeNormal·planeOrigin,
  保留 2D localPts(剖面详情兼容)
- render::buildAnomaly3D(单异常→世界坐标 点/折线/闭合多边形 actor,不翻y/不压z;抽 buildActor 共享 2D/3D)
- I3dSceneView + VtkSceneView:addAnomaly/removeAnomaly/clearAnomalies/setAnomalyVisible(按 id 跟踪 actor,
  worldPts 已含VE 故不再 SetScale;clear 一并清异常)
- Api3dRepository:StoredAnomaly + saveAnomaly/loadAnomalyTree(按 volumeDsId 过滤+consortiumId 分组异常体)/
  deleteAnomaly/deleteAnomalyGroup 内存 mock(取代 stub onErr)

同时修复测试漂移(此前 3a 加 isVolumeDataset 纯虚 + 3c 改 loadVolume 回调签名后,geopro_tests 一直未随之更新):
- FakeView 补异常方法;FakeSceneRepo 补 isVolumeDataset(可配置 volumeIds)+修 loadVolume 签名
- test_3d_repo loadVolume 回调改 (VolumeGrid,ColorScale)
- 控制器测试 View3DWithVoxelAddsVolume 按新"类型分流"语义重写为 View3DVolumeDatasetAddsVolume(体素XOR帘面)

编译全绿(build.bat all);228/228 单元测试通过。4a 为地基(无 UI 接线、尚不可见),圈定/保存见 4b。
2026-06-18 13:04:14 +08:00
gaozheng d56e35f93d feat(vtk): 切片生命周期重构(3b/3c)-已存切片重渲染+保存链接+场景列表同步
切片"未保存↔已保存"统一状态模型,修复多项交互不一致(用户实测通过):
- 保存=链接当前切片到新 dd_slice(不重绘)+三维分析栏自动展开勾选(syncSlices 按 dsId 去重)→
  不再出现"保存后旧渲染还在、再勾选出现两个"的重复切片
- 持久化存精确三点(Origin/Point1/Point2)+axis(SliceSpec),重渲染逐点精确还原 → 尺寸/朝向一致
  (修"重渲染切片明显变大")
- VTK视图「关闭」已保存切片 → onSliceClosed → 取消列表勾选(场景↔列表双向同步)
- VTK视图「保存」按"未保存/已保存"分派:未保存→createSlice+link+autocheck;已保存→saveSlice 覆盖位姿
- 已保存切片在三维分析栏勾选→在当前活动体上按 spec 还原渲染;取消→移除;靠 onVolumeChanged→syncSlices
  解决"父体异步到场"排序(SliceTool 还原构造/dsId 标签;InteractionManager showSavedSlice/hideSavedSlice/
  selectSavedSlice;Api isSliceDataset/sliceSpec)
- 菜单统一/精简:VTK视图与列表导出统一为「导出▸(图片·dat)」;移除列表(三维体/切片)的"显示/隐藏"(勾选即显隐);
  列表保存=覆盖位姿、保存为=另存新切片
- 修 Column3DAnalysis::setDatasets:按 dsId 保留勾选态 + 仅勾选集变化才发信号 →
  保存切片不再连带取消三维体勾选/重置列表

编译链接绿(build.bat app exit 0);上述场景已用户实测通过。
2026-06-18 09:40:19 +08:00
gaozheng afdd98f416 feat(vtk): 切片右键菜单(VTK视图)+切片持久化mock+导出图片(切片本身,高清)/dat (#3a)
- VTK视图切片右键菜单(设计§2.3):正视图/翻转/关闭(接现有交互)、导出图片/导出dat、保存、创建异常(占位→#4)
  - 右键经 InteractionManager 高优先级(1.0)交互器观察者实现:先于 vtkImagePlaneWidget 消费右键
    (widget 会抢右键并 abort,故 InteractorStyle::OnRightButtonDown 不触发);命中切片或回退选中切片→弹菜单
- 切片持久化 mock:Api3dRepository createSlice/saveSlice/deleteSlice 内存态 + sliceRows()
  (ddCode=dd_slice,parentId=所属体→三维分析栏树中挂父体下,符合需求 R19 对象/三维体/切片结构)
- 导出为图片=导出切片本身(需求 R52):切片重采样 2D → 上采样至最长边2048(保长宽比) → 切片色阶LUT上色 → PNG
  (非整窗截图);导出dat=切片重采样标量网格
- 三维分析栏接线(#5部分):显示/隐藏(VtkSceneView::toggleDatasetVisibility)、切片删除、色阶占位
- main.cpp refreshAnalysis 合并 volumeRows+sliceRows 注入三维分析栏

编译链接绿(build.bat app exit 0);右键菜单/保存/导出图片(切片·高清)已用户实测通过。
3b 待做:已保存切片在分析栏勾选后的重渲染(从 spec 重建)、分析栏保存/另存/导出;#4 异常接真实后端。
2026-06-18 08:09:15 +08:00
gaozheng c3f72fdc8d fix(vtk): A-复刻原版垂直配准.剖面z用真实高程+g.y(原版data.y=高程,非深度);地形改真实高程(去基准减法)x同一VE;剖面与地形同系对齐,剖面顶≈地表露出地面 2026-06-17 16:00:14 +08:00
gaozheng 8684e52939 feat(vtk): 底图瓦片坐标数学 TileMath(EPSG:3857 经纬↔z/x/y+瓦片边界)+单测(P5基石) 2026-06-16 21:29:59 +08:00
gaozheng 37b433208e fix(vtk): 帘面消隐无数据(NaN)格,根治真实反演剖面渲染崩溃(0xc0000005)
真实反演 v 矩阵大量 null→Grid 存 NaN→vtkBandedPolyDataContourFilter 裁剪运算崩(经真实API数据+崩溃栈定位)。
消隐含 NaN 的点(ghost)使其不入表面/色带滤镜+标量填0兜底;顺带清洗色带等值线值(去非有限/去重)。保留色带功能。
2026-06-16 20:41:13 +08:00
gaozheng 07f2f25b58 fix(vtk): 选中切片边框改亮青(0,0.95,1)+加粗, 未选暗灰, 拉开对比 2026-06-16 11:38:53 +08:00
gaozheng 5809b88a44 fix(vtk): D39 改为自定义 Rotate 绕支点增量旋转(真不跳)
前法错: 设焦点=切片中心会把相机位置挪走(透视视差)→画面平移=跳; 诊断只验了视向、漏看位置。
正确: 按下完全不动相机(不跳); 重写 Rotate(): 有选中物时, 用 T(c)R(up)R(right)T(-c) 把
相机 position/focal/up 绕选中切片中心 c 增量旋转→c 在世界/屏幕都不动、场景绕它转、无跳。
无选中回退默认绕焦点。ctest 221/221
2026-06-16 11:33:03 +08:00
gaozheng 8d94247dd9 feat(vtk): D39 以选中三维体/切片为中心旋转视图(不跳)
正确做法: 点击只选中(不动相机)→切换点选不跳; 在'按下开始拖动'那刻才把焦点设到
选中切片中心(焦点+位置同步补偿 delta→视向/距离不变、画面不跳), 之后默认 TrackballCamera
即绕该中心旋转。PickInteractorStyle 加 getRotateCenter 回调, InteractionManager 提供
选中切片中心; 无选中则绕默认焦点。ctest 221/221
2026-06-16 11:27:42 +08:00
gaozheng 2e5cc4e6db chore(vtk): 移除未用的 InteractionManager::faceSelected(正视按钮已删, 双击走 faceSlice) 2026-06-16 11:19:03 +08:00
gaozheng a7edfa5c78 fix(vtk): 轴向切片禁用旋转(G22-24 角度不能再调整),仅任意切片可转(F25)
上一版让所有切片都能拖边缘旋转,违反 G22-24(上下/前后/左右角度不能再调整)。
修: 轴向切片 SetMarginSizeX/Y(0) 去掉旋转抓取区→只能移动不能转;
任意切片(Oblique)保留默认 margin→可拖边缘旋转(F25)。ctest 221/221
2026-06-16 11:14:05 +08:00
gaozheng f3a1ba9f99 fix(vtk): 恢复原型切片可拖动配置(SLICE_MOTION)+双击正视(去按钮)
据用户指出'原型阶段切片可拖动调整',查 git(f57291a)原型配置:
  SetLeftButtonAction(VTK_SLICE_MOTION_ACTION) + SetMiddleButtonAction(VTK_CURSOR_ACTION)
我的 SliceTool 漏了这两行→默认左键是窗位调整(无用)→拖切片面无反应=用户的'不能调'。
- 补回两行: 左键拖动=移动切面; 切面边缘 margins 拖动=旋转角度(F25 任意切片可调)。
- 双击正视(D40)改用 widget StartInteractionEvent 检测(同一切片350ms内两次=双击→正视),
  恢复 spec 的双击交互, 去掉上一版擅自加的'正视'按钮(改了需求, 错)。
- 选中=触碰(onInteract); 滚轮/关闭=选中切片; 相机旋转=空白处拖动。ctest 221/221
2026-06-16 11:07:30 +08:00
gaozheng 87c5cc910e fix(vtk): 恢复任意切片可调(F25)+触碰选中+正视按钮(不再砍功能)
之前用 InteractionOff 砍掉了切片可调(F25),错。改回:
- widget 交互保持开启 → 任意切片可拖动调整角度/位置(F25 恢复); 拖切面=widget 处理。
- 选中改为监听 widget StartInteractionEvent(SliceTool::onInteract → selectByTool):
  触碰某切片即选中+高亮(widget 开交互后独占切面事件,拾取式选中失效,故改观察式)。
- 正视(E54)从双击改为工具条「正视」按钮(faceSelected): 双击会被 widget 抢、QVTK 上本不稳。
- 滚轮推进/关闭 仍作用于选中切片; 相机旋转=空白处拖动(默认 trackball)。
- ctest 221/221
2026-06-16 10:50:05 +08:00
gaozheng 43f8228e49 fix(vtk): 切片单击仅选中+高亮,不动相机(终态) — 切换切片不再跳
据用户实测: '按切片中心移焦点'(eb8cb9e)在切换两切片时仍跳(两次焦点跳动), 且切片中心≈体中心
→ 与默认绕中心旋转视觉等价、价值低。终态: 单击=仅选中+高亮, 拖动=默认 TrackballCamera 绕
场景/体中心旋转(稳定、永不跳)。spec C38 '以体为中心' 由此满足; 切片本身不自转(符合语义)。
2026-06-16 10:34:11 +08:00
gaozheng eb8cb9e7ee fix(vtk): 切片旋转支点用切片中心而非点击点(根因修复,据日志证据)
诊断日志证据: onPicked 改相机后 dir(视向) before==after, 补偿正确、点击瞬间画面不变;
但命中点 world 明显偏离体中心 → 之前以'点击点'为焦点, 拖动绕偏心点旋转→大幅摆动(=用户的'跳')。
根因修复: 旋转焦点设为**切片中心**(slices_[idx]->center(), ≈体中心, spec C38 '以切片为中心'),
焦点+位置同步平移保持画面不变 → 点击不跳、拖动绕切片中心居中旋转、不甩。
未命中切片则不动相机。
2026-06-16 10:26:29 +08:00
gaozheng 8a06014e0b fix(vtk): 切片单击=仅选中(不动相机,去跳)+高亮反馈
- onPicked 去掉改相机焦点/位置(实测仍致点击跳变)→ 单击仅选中命中切片;
  拖动旋转回归默认 TrackballCamera(绕场景中心,不跳)。'以切片为中心旋转'(C38)
  因致跳且预期不清,暂去, 后续用更稳方式再加。
- SliceTool::setSelected: 选中切片边框高亮(亮黄粗线)、其余暗灰; InteractionManager
  在 单击/新增/关闭/双击 后 updateSelectionVisual → 解决'选中无视觉反馈'。
- ctest 221/221
2026-06-16 10:12:20 +08:00
gaozheng ff3ce27978 fix(vtk): 切片 widget InteractionOff —— 修点击选中/双击/绕点旋转全失效
实测根因: vtkImagePlaneWidget 默认消费落在切片面上的左键(窗位/光标), 自定义
PickInteractorStyle 收不到 → 单击选中/双击正视/绕点旋转/滚轮推进选中项 全失效;
滚轮看似只对最后新增切片有效, 实为选中从未改变(addSlice 设的 last)。
关掉 widget 自身交互(Interaction off): 其事件回调提前 return 不设 AbortFlag →
事件穿透到样式; 切片面 actor 可被 cellPicker 拾取 → 选中/双击/旋转恢复。切面移动由滚轮 advance 驱动。
2026-06-16 09:57:34 +08:00
gaozheng 87b90a2022 fix(vtk): P3 切片交互手感修复(用户实测反馈)
- 删左上「视图详情」遗留的禁用「切片」复选框(P1占位,已被P3工具条取代)
- 点击跳变 + 绕点旋转无效: onPicked 焦点与相机位置同步平移同一delta,
  图像不跳、旋转中心移到命中点(原来只改焦点致视图突变)
- 双击正视无效: 弃 vtkRenderHWindowInteractor::GetRepeatCount(QVTK+Win不可靠),
  改 std::chrono 手动判双击(间隔<350ms且位置相近); 避开 vtkTimerLog 依赖
- 选中移除: 随上面拾取修复,单击切片可选中→关闭移除选中项(不再只能倒序)
2026-06-16 09:09:38 +08:00
gaozheng 85d4ff57df feat(vtk): P3 三维分析切片交互(核心) — 轴向/任意切片+滚轮+拾取+正视
interact/ 交互层(README早规划,本期落地):
- SlicePlaneMath: 纯几何(法向/45°/滚轮平移/双击正视相机含竖直兜底/最近切片), 25 单测
- SliceTool: 封装 vtkImagePlaneWidget — 轴向(上下/前后/左右,角度固定)+任意45°(Origin/Pt1/Pt2),
  套色阶LUT, reslice着色(非cutter), close幂等
- PickInteractorStyle: 继承TrackballCamera+vtkCellPicker, 拾取/双击/滚轮回调
- InteractionManager: 活动切片/选中态/滚轮分发/拾取联动/翻转, 体素变更先closeAll再附着
- VtkSceneView 暴露 currentVolumeImage_(含VE) + onVolumeChanged; main.cpp 切片工具条(上下/前后/左右/任意/翻转/关闭)
- ctest 221/221

评审修复:
- H1 vtkTrivialProducer 提为成员(局部变量构造后析构→管线断裂崩溃)
- H2 uninstallStyle 向 interactor 注销 style
- H3 safeRender 统一守 destroying_ 跳过析构期 Render
- M1 advance 刚性平移 origin+point1+point2(只移origin致轴向切面变形)
- M2 closeSelected 选中位就近不跳0; M4 sliceBar 加 BottomLeftAnchor 随resize

范围外(P4): 切片保存/导出/删除为数据集/三维分析树/右键菜单/异常圈定/详情
2026-06-16 08:23:16 +08:00
gaozheng 3dea339ddc feat(vtk): P2 三维数据集栏 — 坐标轴/比例/快捷视图/Zoom
- CameraPreset 扩 6 向快捷视图(前后左右上下) + zoomBy(透视改视角/正交改parallelScale) + fitView
- AxesActor(新, vtkCubeAxesActor): 显示模式 标准(外缘)/三维立体(静态边+网格线)/不显示;
  刻度 无/米/英尺(×3.28084)/经纬度(GeoLocalFrame反算); 字号12(字体待1.0确认)
- GeoLocalFrame 补 toLatLon 反算(等距圆柱)
- I3dSceneView 扩 setAxes/applyCameraView/zoom/fitView; VtkSceneController 加对应槽
  (坐标轴随场景重建; 快捷视图/zoom 仅改相机不重建)
- main.cpp 三维视图工具条: 坐标轴/刻度下拉(枚举绑itemData)+比例滑块(1-10)+6向钮+Zoom钮, 仅3D显示
- 测试 +24(toLatLon往返/相机6向/坐标轴单位换算/控制器编排), ctest 196/196

评审修复:
- HIGH rebuildAxes 异步路径坐标轴 prop 累积 → 持 currentAxes_ 重建前先移除(幂等)
- MEDIUM combo index 魔数 → itemData/currentData 取枚举值(防项序调整静默错位)

注: 坐标轴标准/立体语义 + 字体 + O点 为合理近似, 待 Geopro 1.0 实地确认精修
2026-06-15 21:54:48 +08:00
gaozheng 0f521c5b24 feat(vtk): P1 复活中央渲染 — VtkSceneController + I3dSceneRepository + Scene加vtkProp
复活被 6241eb3 摘除的中央 VTK 数据驱动渲染:
- Scene 新增 addViewProp(vtkProp*):体绘制 vtkVolume(非 vtkActor)经此进场
- I3dSceneRepository(异步回调契约) + LocalSample3dRepository:dimensionOf 维度映射 /
  loadVolume→VolumeGrid(std::array 去裸数组) / loadTerrainPaths;data 层零 VTK 依赖
- VtkSceneController(QObject) 取代 main.cpp 死掉的 rebuildCentral lambda + 裸 show* 标志:
  勾选数据集/视图模式/图层/比例 → 经仓储取 core::* → I3dSceneView 重建场景;
  QPointer+generation 守异步回调生命周期与新鲜度;inRebuild_ 避免同步路径双 render
- I3dSceneView 抽象解耦编排与 VTK(VtkSceneView 真实现 + 测试 fake)
- 删除被取代的 CentralScene;main.cpp 接线 对象勾选/2D-3D/图层/主题(主题 context 用 sceneCtrl 防悬垂)
- 新增测试 14(Scene/3d-repo/VtkSceneController),ctest 172/172 全绿

构建基建修复(本就潜在缺陷,任何 clean 构建/新人 checkout 都会撞):
- vcpkg.json 加 builtin-baseline:新版 vcpkg manifest 模式必需,否则全新 checkout 无法 configure
- build.bat 修 vswhere(VS2026 预览 -latest 恒空 → -all -prerelease -requires VC.Tools)
  + 括号块内路径变量加引号(防 Program Files (x86) 的 ) 提前闭合)
2026-06-15 21:01:26 +08:00