feat(view): 3D「视图详情」图层浮层 + 体素正经接入(对齐原型, 增量3)
- 中央 QVTK 左上浮层(QFrame, 仅三维显示, 工具条下方, raise 置顶): 图层勾选「帘面 / 体素」。
- rebuildCentral: 帘面层 gate buildCurtain; 体素层 → buildVoxelFromScatters 体绘制(同纵向夸张)。
showCurtain(默认开)/showVoxel(默认关)/crs 共享态; 切视图自动显隐浮层。
- 体素经此正经接入(取代 42a7ed1 移除的困惑工具条开关, 这才是它对齐原型的归宿)。
- main() 自动定位 PROJ_DATA(候选路径; 部署须随包附带 proj 数据); PROJ 不可用→体素勾选禁用+提示。
- app 构建干净; 待人工登录复核(浮层渲染于 QVTK 之上 + 勾体素出十字片)。
This commit is contained in:
parent
50c4de4019
commit
a2efef8ada
|
|
@ -17,7 +17,7 @@
|
||||||
- **左下 数据真实显示栏**(对齐原型):单击测线 → 列其采集批次(数据集,tab 数据/文件);单击采集批次 → 数据详情+异常列表+属性。启动自动选首测线+首数据集。
|
- **左下 数据真实显示栏**(对齐原型):单击测线 → 列其采集批次(数据集,tab 数据/文件);单击采集批次 → 数据详情+异常列表+属性。启动自动选首测线+首数据集。
|
||||||
- **中央 二维地图 / 三维视图**(两个**真内容**,非相机切换):
|
- **中央 二维地图 / 三维视图**(两个**真内容**,非相机切换):
|
||||||
- 二维地图 = `MapLineActor`:测线 `lat/lon` 轨迹**红线**俯视(浅底),像地图。
|
- 二维地图 = `MapLineActor`:测线 `lat/lon` 轨迹**红线**俯视(浅底),像地图。
|
||||||
- 三维视图 = `CurtainActor`:沿测线的**竖直断面墙**(分段色带,z 纵向夸张×3,沿弯曲测线弯)。中央工具条**仅**「二维地图/三维视图」(对齐原型,无体素按钮)。
|
- 三维视图 = `CurtainActor`:沿测线的**竖直断面墙**(分段色带,z 纵向夸张×3,沿弯曲测线弯)。中央工具条**仅**「二维地图/三维视图」。**3D 左上「视图详情」浮层**(对齐原型,仅 3D 显示):图层勾选 **帘面 / 体素**(体素=`buildVoxelFromScatters` 两交叉测线散点经 EPSG:4547 配准 IDW,与帘面同纵向夸张;PROJ 不可用则禁用)。
|
||||||
- **下方 数据详情**:工具条「原数据/网格数据」切换 +「显示异常」开关(对齐原型命名)。单击数据集 → 网格数据=`GridContourActor` 平面剖面(#18,colorBar 真实非均匀分段值上色,纵向夸张×1.5);原数据=`ScatterActor` 彩色方块散点(#17,x=距离/y=深度取负,用散点自带色阶);显示异常=`AnomalyActor` 在上图叠加异常 dashed 折线(同纵向夸张对齐)。
|
- **下方 数据详情**:工具条「原数据/网格数据」切换 +「显示异常」开关(对齐原型命名)。单击数据集 → 网格数据=`GridContourActor` 平面剖面(#18,colorBar 真实非均匀分段值上色,纵向夸张×1.5);原数据=`ScatterActor` 彩色方块散点(#17,x=距离/y=深度取负,用散点自带色阶);显示异常=`AnomalyActor` 在上图叠加异常 dashed 折线(同纵向夸张对齐)。
|
||||||
- **右上 异常列表**(对齐原型):单击数据集→列该数据集异常(颜色块+名称(类型)+派生「位置/深/尺寸」),勾选框显隐,与数据详情异常叠加联动(取消勾选→该异常虚线隐藏)。
|
- **右上 异常列表**(对齐原型):单击数据集→列该数据集异常(颜色块+名称(类型)+派生「位置/深/尺寸」),勾选框显隐,与数据详情异常叠加联动(取消勾选→该异常虚线隐藏)。
|
||||||
- **右下 属性**:名称/网格 nx×ny/vmin·vmax/异常数。
|
- **右下 属性**:名称/网格 nx×ny/vmin·vmax/异常数。
|
||||||
|
|
@ -69,7 +69,7 @@
|
||||||
1. ~~**散点 #17**:`ScatterActor`(剖面原数据 2597 点彩色散点),数据详情"原数据"视图~~ ✅ **已完成**(2026-06-08,离屏 PNG 核对吻合 Python 真值,接入数据详情「反演剖面/原数据」切换;app 待人工登录肉眼复核交互)。
|
1. ~~**散点 #17**:`ScatterActor`(剖面原数据 2597 点彩色散点),数据详情"原数据"视图~~ ✅ **已完成**(2026-06-08,离屏 PNG 核对吻合 Python 真值,接入数据详情「反演剖面/原数据」切换;app 待人工登录肉眼复核交互)。
|
||||||
2. ~~**异常叠加**:`AnomalyActor`(markType 点/线/面)~~ ✅ **已完成**(2026-06-08,叠加在数据详情 #18/#17 上,「显示异常」开关默认开;离屏 `verify_section_anomaly.png` 折线位置吻合 ref_18;样本 3 异常均 markType=2 dashed;app 待人工登录复核)。**注**:dashed 点画在 VTK OpenGL2 下偏弱(几乎实线),几何/颜色/位置正确,纯观感项可后续调。
|
2. ~~**异常叠加**:`AnomalyActor`(markType 点/线/面)~~ ✅ **已完成**(2026-06-08,叠加在数据详情 #18/#17 上,「显示异常」开关默认开;离屏 `verify_section_anomaly.png` 折线位置吻合 ref_18;样本 3 异常均 markType=2 dashed;app 待人工登录复核)。**注**:dashed 点画在 VTK OpenGL2 下偏弱(几乎实线),几何/颜色/位置正确,纯观感项可后续调。
|
||||||
3. **DEM/影像地形**:加 vcpkg `gdal`;GDAL 读 dem.tif/image.tif;**影像 EPSG:3857 必须 PROJ 重投影到世界系**;`vtkWarpScalar` 地形面 + 纹理。
|
3. **DEM/影像地形**:加 vcpkg `gdal`;GDAL 读 dem.tif/image.tif;**影像 EPSG:3857 必须 PROJ 重投影到世界系**;`vtkWarpScalar` 地形面 + 纹理。
|
||||||
4. **dd_voxel 回归**:🔶 **引擎已完成并验证**(2026-06-08,CRS 已定 EPSG:4547)。`render::buildVoxelFromScatters`:散点 projX/Y→4547→4326→GeoLocalFrame 配准 + IDW(maxDist 裁剪)→ `buildVoxel`;离屏 `verify_voxel_top.png` 两臂支撑吻合 ref voxel_hslice、`verify_voxel_3d.png` profile1 片贴合帘面;+1 单测(VoxelRegister,需 PROJ_DATA)。**UI 未接入**:曾加"体素"工具条开关,但与二维/三维平级令人困惑且不在原型,**已移除**;待做 **3D 图层控制(对齐原型「视图详情」浮层)** 再正经接入(届时 main() 需设 PROJ_DATA + 部署随包附带 proj 数据)。**注**:仅 2 交叉线→薄十字片(15.9% 充填,半透明偏淡),可信满体需≥3线(设计 §10/§14)。**dd_slice 交互切片未做**(buildVoxel 已暴露 image 供 reslice widget)。
|
4. **dd_voxel 回归**:✅ **已完成**(2026-06-08,CRS 已定 EPSG:4547)。`render::buildVoxelFromScatters`:散点 projX/Y→4547→4326→GeoLocalFrame 配准 + IDW(maxDist 裁剪)→ `buildVoxel`;离屏 `verify_voxel_top.png` 两臂支撑吻合 ref voxel_hslice、`verify_voxel_3d.png` profile1 片贴合帘面;+1 单测(VoxelRegister,需 PROJ_DATA)。**UI 已接入**(增量3):3D「视图详情」浮层「体素」图层勾选驱动;main() 自动设 PROJ_DATA(部署须随包附带 proj 数据);PROJ 不可用则该层禁用。**注**:仅 2 交叉线→薄十字片(15.9% 充填,半透明偏淡),可信满体需≥3线(设计 §10/§14)。**dd_slice 交互切片未做**(buildVoxel 已暴露 image 供 reslice widget)。
|
||||||
5. **底图瓦片**(二维地图,天地图/Mapbox):M1.5。
|
5. **底图瓦片**(二维地图,天地图/Mapbox):M1.5。
|
||||||
6. **Credential(QtKeychain)**:记住一个月免登录持久化(P3 Task2 未做)。
|
6. **Credential(QtKeychain)**:记住一个月免登录持久化(P3 Task2 未做)。
|
||||||
7. 多测线:当前样本仅 1 条 dd_section(grid1);多条共存机制已就绪,加数据即叠加。
|
7. 多测线:当前样本仅 1 条 dd_section(grid1);多条共存机制已就绪,加数据即叠加。
|
||||||
|
|
@ -78,7 +78,7 @@
|
||||||
10. **布局对齐原型**(权威参考 `http://prototype.geomative.cn/`;截图存 `.playwright-mcp/`)。**计划见 `plans/2026-06-08-m1-prototype-layout.md`(六面板 + view/ 抽取,增量序列)**。进度:
|
10. **布局对齐原型**(权威参考 `http://prototype.geomative.cn/`;截图存 `.playwright-mcp/`)。**计划见 `plans/2026-06-08-m1-prototype-layout.md`(六面板 + view/ 抽取,增量序列)**。进度:
|
||||||
- ✅ **增量1 右上「异常列表」**(2026-06-08,`panels/AnomalyListPanel`,与数据详情显隐联动;待人工复核)。
|
- ✅ **增量1 右上「异常列表」**(2026-06-08,`panels/AnomalyListPanel`,与数据详情显隐联动;待人工复核)。
|
||||||
- ✅ **增量2 左下「数据列表」+ 对象树到 TM 层**(2026-06-08,`panels/DatasetListPanel`;树 GS→TM 复选驱动中央, DS 移出树入数据列表 tab 数据/文件, DS 单击→详情+异常+属性, 启动自动选首测线/首数据集;待人工复核)。
|
- ✅ **增量2 左下「数据列表」+ 对象树到 TM 层**(2026-06-08,`panels/DatasetListPanel`;树 GS→TM 复选驱动中央, DS 移出树入数据列表 tab 数据/文件, DS 单击→详情+异常+属性, 启动自动选首测线/首数据集;待人工复核)。
|
||||||
- ⬜ **增量3 3D「视图详情」图层浮层**(体素的正确归宿;体素引擎已就绪,UI 待此接入)。
|
- ✅ **增量3 3D「视图详情」图层浮层**(2026-06-08,QFrame 浮于 QVTK 左上,仅 3D 显示;帘面/体素图层勾选;体素经此正经接入=之前移除的工具条开关的正确归宿;main() 设 PROJ_DATA;待人工复核浮层渲染+体素显隐)。
|
||||||
- ⬜ **增量4 数据详情富工具条 + 电极标记 + 数值标签**;底图影像=DEM/底图任务。
|
- ⬜ **增量4 数据详情富工具条 + 电极标记 + 数值标签**;底图影像=DEM/底图任务。
|
||||||
- 架构:新面板抽到 `src/app/panels/`(暂随 app 编译,如 login/),控制 main.cpp 体量;后续可升 `src/view/` 库。
|
- 架构:新面板抽到 `src/app/panels/`(暂随 app 编译,如 login/),控制 main.cpp 体量;后续可升 `src/view/` 库。
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,11 @@
|
||||||
- **人工复核**:点 ERT1 → 左下列出采集批次 → 单击 → 数据详情出图。
|
- **人工复核**:点 ERT1 → 左下列出采集批次 → 单击 → 数据详情出图。
|
||||||
- 提交 `feat(view): 左下数据列表 + 对象树到测线层(DS 移出树)`。
|
- 提交 `feat(view): 左下数据列表 + 对象树到测线层(DS 移出树)`。
|
||||||
|
|
||||||
### 增量 3:3D「视图详情」图层浮层(体素的正确归宿)
|
### 增量 3:3D「视图详情」图层浮层 ✅ 已完成(2026-06-08)
|
||||||
|
> main.cpp 内联 QFrame 浮层(child of centerWidget,move 到 QVTK 左上=工具条下方,raise;仅 3D setVisible)。
|
||||||
|
> 含 帘面/体素 QCheckBox。rebuildCentral:帘面层 gate buildCurtain;体素层→buildVoxelFromScatters 加体绘制
|
||||||
|
> (同纵向夸张)。showCurtain/showVoxel/crs 共享态。main() 自动设 PROJ_DATA;crs 失败→体素勾选禁用。
|
||||||
|
> app 构建净;**待人工复核**(浮层是否正确浮于 QVTK 之上、勾体素是否出十字片)。**原计划存档**:
|
||||||
- 中央三维视图左上浮层(QWidget overlay on QVTK,或工具区):勾选显示 测线/帘面/**体素**/(地形)。
|
- 中央三维视图左上浮层(QWidget overlay on QVTK,或工具区):勾选显示 测线/帘面/**体素**/(地形)。
|
||||||
- 勾"体素" → 调 `buildVoxelFromScatters`(已验证)加入 3D 场景;勾选驱动 rebuildCentral 的图层集。
|
- 勾"体素" → 调 `buildVoxelFromScatters`(已验证)加入 3D 场景;勾选驱动 rebuildCentral 的图层集。
|
||||||
- main() 设 PROJ_DATA(体素配准需 proj.db;按候选路径,部署随包附带)。
|
- main() 设 PROJ_DATA(体素配准需 proj.db;按候选路径,部署随包附带)。
|
||||||
|
|
|
||||||
122
src/app/main.cpp
122
src/app/main.cpp
|
|
@ -3,10 +3,9 @@
|
||||||
// - 左下 数据真实显示栏:单击测线 → 列其采集批次(数据集,tab 数据/文件)。单击采集批次 → 数据详情+异常+属性。
|
// - 左下 数据真实显示栏:单击测线 → 列其采集批次(数据集,tab 数据/文件)。单击采集批次 → 数据详情+异常+属性。
|
||||||
// - 中央「二维地图 / 三维视图」:两个互斥视图(内容不同,不是同一物体换相机)。
|
// - 中央「二维地图 / 三维视图」:两个互斥视图(内容不同,不是同一物体换相机)。
|
||||||
// 二维地图 = 对每个勾选数据集 buildSurveyLine(lat/lon 红线俯视,z=0)+ applyTop2D(浅底背景)。
|
// 二维地图 = 对每个勾选数据集 buildSurveyLine(lat/lon 红线俯视,z=0)+ applyTop2D(浅底背景)。
|
||||||
// 三维视图 = 对每个勾选数据集 buildCurtain(竖直断面墙),actor SetScale(1,1,3) 纵向夸张 + applyFree3D(白底)。
|
// 三维视图 = 勾选测线的 buildCurtain(竖直断面墙),actor SetScale(1,1,3) 纵向夸张 + applyFree3D(白底)。
|
||||||
// 切视图 / 勾选变化 → 按当前勾选集重建对应内容。
|
// 三维左上「视图详情」浮层(对齐原型):图层勾选 帘面 / 体素(dd_voxel,散点经 EPSG:4547 配准 IDW)。
|
||||||
// 注:dd_voxel 体素引擎(render::buildVoxelFromScatters)已就绪并验证,但**不**作为工具条开关
|
// 切视图 / 勾选变化 / 图层变化 → 重建对应内容。
|
||||||
// (那样与二维/三维平级会令人困惑、且不在原型);待做 3D 图层控制(对齐原型「视图详情」浮层)再接。
|
|
||||||
// - 下方「数据详情」:独立 QVTK 小视图 + 工具条「原数据 / 网格数据」切换 +「显示异常」开关(对齐原型)。
|
// - 下方「数据详情」:独立 QVTK 小视图 + 工具条「原数据 / 网格数据」切换 +「显示异常」开关(对齐原型)。
|
||||||
// 单击某 DS → 显示该数据集:
|
// 单击某 DS → 显示该数据集:
|
||||||
// 网格数据 = #18 banded 等值面+等值线(两 actor SetScale(1,1.5,1) 纵向夸张)。
|
// 网格数据 = #18 banded 等值面+等值线(两 actor SetScale(1,1.5,1) 纵向夸张)。
|
||||||
|
|
@ -24,11 +23,15 @@
|
||||||
|
|
||||||
#include <QActionGroup>
|
#include <QActionGroup>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
#include <QCheckBox>
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QFrame>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QListWidget>
|
#include <QListWidget>
|
||||||
#include <QListWidgetItem>
|
#include <QListWidgetItem>
|
||||||
#include <QSignalBlocker>
|
#include <QSignalBlocker>
|
||||||
|
#include <QStringList>
|
||||||
#include <QTabWidget>
|
#include <QTabWidget>
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
#include <QSurfaceFormat>
|
#include <QSurfaceFormat>
|
||||||
|
|
@ -53,15 +56,18 @@
|
||||||
|
|
||||||
#include "CameraPreset.hpp"
|
#include "CameraPreset.hpp"
|
||||||
#include "Scene.hpp"
|
#include "Scene.hpp"
|
||||||
|
#include "VoxelFromScatters.hpp"
|
||||||
#include "actors/AnomalyActor.hpp"
|
#include "actors/AnomalyActor.hpp"
|
||||||
#include "actors/CurtainActor.hpp"
|
#include "actors/CurtainActor.hpp"
|
||||||
#include "actors/GridContourActor.hpp"
|
#include "actors/GridContourActor.hpp"
|
||||||
#include "actors/MapLineActor.hpp"
|
#include "actors/MapLineActor.hpp"
|
||||||
#include "actors/ScatterActor.hpp"
|
#include "actors/ScatterActor.hpp"
|
||||||
|
|
||||||
|
#include "geo/CrsTransform.hpp"
|
||||||
#include "geo/GeoLocalFrame.hpp"
|
#include "geo/GeoLocalFrame.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <exception>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
@ -140,6 +146,10 @@ constexpr float kScatterPointSize = 4.0F;
|
||||||
constexpr double kCurtainZScale = 3.0;
|
constexpr double kCurtainZScale = 3.0;
|
||||||
constexpr double kDetailYScale = 1.5;
|
constexpr double kDetailYScale = 1.5;
|
||||||
|
|
||||||
|
// 项目 CRS(实证确定,STATUS §4):散点 projX/Y→经纬→GeoLocalFrame 配准体素到世界系。
|
||||||
|
constexpr const char* kProjectCrs = "EPSG:4547"; // CGCS2000 / 3-degree GK CM 114E
|
||||||
|
constexpr const char* kWgs84 = "EPSG:4326";
|
||||||
|
|
||||||
// 在给定 QMainWindow 上构建 M1 工作台。
|
// 在给定 QMainWindow 上构建 M1 工作台。
|
||||||
// repo 生命周期须覆盖到事件循环结束(由调用方保证)。
|
// repo 生命周期须覆盖到事件循环结束(由调用方保证)。
|
||||||
void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& repo)
|
void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& repo)
|
||||||
|
|
@ -166,6 +176,16 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
|
||||||
// 当前视图模式(全局共享,切视图/勾选时据此重建内容)。默认二维地图。
|
// 当前视图模式(全局共享,切视图/勾选时据此重建内容)。默认二维地图。
|
||||||
auto viewMode = std::make_shared<ViewMode>(ViewMode::Map2D);
|
auto viewMode = std::make_shared<ViewMode>(ViewMode::Map2D);
|
||||||
|
|
||||||
|
// 三维图层显隐(由「视图详情」浮层控制)+ 项目 CRS→WGS84(体素配准)。
|
||||||
|
auto showCurtain = std::make_shared<bool>(true); // 帘面,默认显示
|
||||||
|
auto showVoxel = std::make_shared<bool>(false); // 体素,默认关
|
||||||
|
std::shared_ptr<geopro::core::CrsTransform> crs; // PROJ 失败→空→体素层无效(不崩)
|
||||||
|
try {
|
||||||
|
crs = std::make_shared<geopro::core::CrsTransform>(kProjectCrs, kWgs84);
|
||||||
|
} catch (const std::exception&) {
|
||||||
|
crs.reset();
|
||||||
|
}
|
||||||
|
|
||||||
auto* dockManager = new ads::CDockManager(&window);
|
auto* dockManager = new ads::CDockManager(&window);
|
||||||
window.setCentralWidget(dockManager);
|
window.setCentralWidget(dockManager);
|
||||||
|
|
||||||
|
|
@ -189,6 +209,31 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
|
||||||
centerLayout->addWidget(viewToolBar);
|
centerLayout->addWidget(viewToolBar);
|
||||||
centerLayout->addWidget(vtkWidget, 1);
|
centerLayout->addWidget(vtkWidget, 1);
|
||||||
|
|
||||||
|
// ──「视图详情」图层浮层(对齐原型 3D 视图左上):浮在 QVTK 之上,控制三维图层显隐。
|
||||||
|
// 仅三维视图显示;含 帘面 / 体素 勾选(体素=两交叉测线散点配准 IDW 的派生层,正确归宿)。
|
||||||
|
auto* layerPanel = new QFrame(centerWidget);
|
||||||
|
layerPanel->setFrameShape(QFrame::StyledPanel);
|
||||||
|
layerPanel->setStyleSheet(
|
||||||
|
QStringLiteral("QFrame{background:rgba(255,255,255,0.92);border:1px solid #b0b4bb;"
|
||||||
|
"border-radius:6px;} QCheckBox{padding:1px;}"));
|
||||||
|
auto* layerLayout = new QVBoxLayout(layerPanel);
|
||||||
|
layerLayout->setContentsMargins(10, 8, 12, 8);
|
||||||
|
layerLayout->setSpacing(4);
|
||||||
|
auto* layerTitle = new QLabel(QStringLiteral("视图详情"));
|
||||||
|
layerTitle->setStyleSheet(QStringLiteral("font-weight:bold;border:none;background:transparent;"));
|
||||||
|
auto* chkCurtain = new QCheckBox(QStringLiteral("帘面(断面墙)"));
|
||||||
|
chkCurtain->setChecked(true);
|
||||||
|
auto* chkVoxel = new QCheckBox(QStringLiteral("体素(dd_voxel)"));
|
||||||
|
chkVoxel->setChecked(false);
|
||||||
|
if (!crs) { // PROJ 不可用 → 体素层禁用并提示
|
||||||
|
chkVoxel->setEnabled(false);
|
||||||
|
chkVoxel->setToolTip(QStringLiteral("PROJ 数据(proj.db)缺失,体素配准不可用"));
|
||||||
|
}
|
||||||
|
layerLayout->addWidget(layerTitle);
|
||||||
|
layerLayout->addWidget(chkCurtain);
|
||||||
|
layerLayout->addWidget(chkVoxel);
|
||||||
|
layerPanel->setVisible(false); // 默认二维,不显示图层浮层
|
||||||
|
|
||||||
auto* vtkDock = new ads::CDockWidget(QStringLiteral("二维地图/三维视图"));
|
auto* vtkDock = new ads::CDockWidget(QStringLiteral("二维地图/三维视图"));
|
||||||
vtkDock->setWidget(centerWidget);
|
vtkDock->setWidget(centerWidget);
|
||||||
auto* centerDockArea = dockManager->addDockWidget(ads::CenterDockWidgetArea, vtkDock);
|
auto* centerDockArea = dockManager->addDockWidget(ads::CenterDockWidgetArea, vtkDock);
|
||||||
|
|
@ -277,19 +322,19 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
|
||||||
// 三维视图 = buildCurtain(断面墙)SetScale(1,1,kCurtainZScale) + applyFree3D(白底)。
|
// 三维视图 = buildCurtain(断面墙)SetScale(1,1,kCurtainZScale) + applyFree3D(白底)。
|
||||||
// frame/structure 全局共享;切视图/勾选变化都调用此函数重建当前视图。
|
// frame/structure 全局共享;切视图/勾选变化都调用此函数重建当前视图。
|
||||||
auto rebuildCentral = [scene, rendererPtr, renderWindowPtr, viewMode, &repo, frame, tree,
|
auto rebuildCentral = [scene, rendererPtr, renderWindowPtr, viewMode, &repo, frame, tree,
|
||||||
structure]() {
|
structure, showCurtain, showVoxel, crs]() {
|
||||||
scene->clear();
|
scene->clear();
|
||||||
|
|
||||||
const bool is2D = (*viewMode == ViewMode::Map2D);
|
const bool is2D = (*viewMode == ViewMode::Map2D);
|
||||||
rendererPtr->SetBackground(is2D ? 0.96 : 1.0, is2D ? 0.97 : 1.0, is2D ? 0.99 : 1.0);
|
rendererPtr->SetBackground(is2D ? 0.96 : 1.0, is2D ? 0.97 : 1.0, is2D ? 0.99 : 1.0);
|
||||||
|
|
||||||
// 渲染单个 dd_section 数据集到当前视图。
|
// 渲染单个 dd_section 数据集:二维=测线线;三维=帘面(受「帘面」图层开关控制)。
|
||||||
auto renderSection = [&](const std::string& id) {
|
auto renderSection = [&](const std::string& id) {
|
||||||
const auto g = repo.loadGrid(id);
|
const auto g = repo.loadGrid(id);
|
||||||
if (is2D) {
|
if (is2D) {
|
||||||
auto line = geopro::render::buildSurveyLine(g, *frame);
|
auto line = geopro::render::buildSurveyLine(g, *frame);
|
||||||
if (line) scene->addActor(line);
|
if (line) scene->addActor(line);
|
||||||
} else {
|
} else if (*showCurtain) {
|
||||||
const auto cs = repo.loadColorScale(id);
|
const auto cs = repo.loadColorScale(id);
|
||||||
auto curtain = geopro::render::buildCurtain(g, cs, *frame);
|
auto curtain = geopro::render::buildCurtain(g, cs, *frame);
|
||||||
if (curtain) {
|
if (curtain) {
|
||||||
|
|
@ -315,6 +360,17 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
|
||||||
if (ds.ddType == "dd_section") renderSection(ds.id);
|
if (ds.ddType == "dd_section") renderSection(ds.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 三维「体素」图层:两交叉测线散点经 CRS 配准 IDW 成体素(派生层),与帘面同纵向夸张。
|
||||||
|
if (!is2D && *showVoxel && crs) {
|
||||||
|
const auto profs = repo.loadVoxelScatters();
|
||||||
|
const auto vcs = repo.loadScatterColorScale("grid1");
|
||||||
|
auto vr = geopro::render::buildVoxelFromScatters(profs, vcs, *crs, *frame);
|
||||||
|
if (vr.valid()) {
|
||||||
|
vr.volume->SetScale(1.0, 1.0, kCurtainZScale);
|
||||||
|
rendererPtr->AddVolume(vr.volume);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (is2D)
|
if (is2D)
|
||||||
geopro::render::applyTop2D(rendererPtr);
|
geopro::render::applyTop2D(rendererPtr);
|
||||||
else
|
else
|
||||||
|
|
@ -461,13 +517,41 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
|
||||||
rebuildDetail();
|
rebuildDetail();
|
||||||
});
|
});
|
||||||
|
|
||||||
// ── 工具条「二维地图/三维视图」:切换互斥视图 → 按当前勾选集重建对应内容 ──
|
// 「视图详情」浮层显隐:仅三维显示,置于 QVTK 左上(工具条下方)并置顶。
|
||||||
QObject::connect(act2D, &QAction::triggered, vtkWidget, [viewMode, rebuildCentral]() {
|
auto showLayerPanel = [layerPanel, viewToolBar](bool show3D) {
|
||||||
|
if (show3D) {
|
||||||
|
layerPanel->move(14, viewToolBar->height() + 12);
|
||||||
|
layerPanel->adjustSize();
|
||||||
|
layerPanel->setVisible(true);
|
||||||
|
layerPanel->raise();
|
||||||
|
} else {
|
||||||
|
layerPanel->setVisible(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// ── 工具条「二维地图/三维视图」:切换互斥视图 → 重建内容 + 图层浮层显隐 ──
|
||||||
|
QObject::connect(act2D, &QAction::triggered, vtkWidget,
|
||||||
|
[viewMode, rebuildCentral, showLayerPanel]() {
|
||||||
*viewMode = ViewMode::Map2D;
|
*viewMode = ViewMode::Map2D;
|
||||||
|
showLayerPanel(false);
|
||||||
rebuildCentral();
|
rebuildCentral();
|
||||||
});
|
});
|
||||||
QObject::connect(act3D, &QAction::triggered, vtkWidget, [viewMode, rebuildCentral]() {
|
QObject::connect(act3D, &QAction::triggered, vtkWidget,
|
||||||
|
[viewMode, rebuildCentral, showLayerPanel]() {
|
||||||
*viewMode = ViewMode::View3D;
|
*viewMode = ViewMode::View3D;
|
||||||
|
showLayerPanel(true);
|
||||||
|
rebuildCentral();
|
||||||
|
});
|
||||||
|
|
||||||
|
// ──「视图详情」图层勾选 → 更新图层显隐 → 重建中央 ──
|
||||||
|
QObject::connect(chkCurtain, &QCheckBox::toggled, vtkWidget,
|
||||||
|
[showCurtain, rebuildCentral](bool on) {
|
||||||
|
*showCurtain = on;
|
||||||
|
rebuildCentral();
|
||||||
|
});
|
||||||
|
QObject::connect(chkVoxel, &QCheckBox::toggled, vtkWidget,
|
||||||
|
[showVoxel, rebuildCentral](bool on) {
|
||||||
|
*showVoxel = on;
|
||||||
rebuildCentral();
|
rebuildCentral();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -502,6 +586,24 @@ int main(int argc, char* argv[])
|
||||||
QSurfaceFormat::setDefaultFormat(QVTKOpenGLStereoWidget::defaultFormat());
|
QSurfaceFormat::setDefaultFormat(QVTKOpenGLStereoWidget::defaultFormat());
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
|
|
||||||
|
// PROJ 数据(proj.db)定位:体素配准的 CrsTransform 需要。优先已设环境变量;
|
||||||
|
// 否则按 exe 旁 / 构建目录候选设置。部署时须随包附带 proj 数据并设此变量。
|
||||||
|
if (qEnvironmentVariableIsEmpty("PROJ_DATA")) {
|
||||||
|
const QString appDir = QCoreApplication::applicationDirPath();
|
||||||
|
const QStringList candidates = {
|
||||||
|
appDir + "/proj",
|
||||||
|
appDir + "/../../vcpkg_installed/x64-windows/share/proj",
|
||||||
|
QStringLiteral(
|
||||||
|
"D:/Git/lanbingtech/geopro/build/release/vcpkg_installed/x64-windows/share/proj"),
|
||||||
|
};
|
||||||
|
for (const auto& c : candidates) {
|
||||||
|
if (QFile::exists(c + "/proj.db")) {
|
||||||
|
qputenv("PROJ_DATA", c.toUtf8());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 网络层:共享会话 ApiClient + 登录编排 AuthService(RSA 公钥从 resources 读取)。
|
// 网络层:共享会话 ApiClient + 登录编排 AuthService(RSA 公钥从 resources 读取)。
|
||||||
geopro::net::ApiClient api(QStringLiteral("http://tenant.geomative.cn/pop-api"));
|
geopro::net::ApiClient api(QStringLiteral("http://tenant.geomative.cn/pop-api"));
|
||||||
const std::string pem = readPem("D:/Git/lanbingtech/geopro/resources/rsa_public_key.pem");
|
const std::string pem = readPem("D:/Git/lanbingtech/geopro/resources/rsa_public_key.pem");
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue