fix(app): 视图模式三按钮(二维/三维/三维体素)互斥连贯 — 切2D/3D回剖面,体素自身高亮

This commit is contained in:
gaozheng 2026-06-07 22:15:55 +08:00
parent 0413e4359a
commit 39b97ffb70
1 changed files with 52 additions and 35 deletions

View File

@ -220,6 +220,9 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
act2D->setChecked(true); // 默认二维 act2D->setChecked(true); // 默认二维
viewToolBar->addSeparator(); viewToolBar->addSeparator();
auto* actVoxel = viewToolBar->addAction(QStringLiteral("三维体素")); auto* actVoxel = viewToolBar->addAction(QStringLiteral("三维体素"));
// 三按钮做成统一互斥的"3 路视图模式":任意时刻恰一个勾选。
actVoxel->setCheckable(true);
cameraGroup->addAction(actVoxel);
centerLayout->addWidget(viewToolBar); centerLayout->addWidget(viewToolBar);
centerLayout->addWidget(vtkWidget, 1); centerLayout->addWidget(vtkWidget, 1);
@ -231,21 +234,6 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
if (sliceWidget->Get()) (*sliceWidget)->Off(); if (sliceWidget->Get()) (*sliceWidget)->Off();
}; };
QObject::connect(act2D, &QAction::triggered, vtkWidget,
[cameraMode, rendererPtr, renderWindowPtr, hideSlice]() {
*cameraMode = CameraMode::Top2D;
hideSlice(); // 切回剖面视图:关闭体素切片
geopro::render::applyTop2D(rendererPtr);
renderWindowPtr->Render();
});
QObject::connect(act3D, &QAction::triggered, vtkWidget,
[cameraMode, rendererPtr, renderWindowPtr, hideSlice]() {
*cameraMode = CameraMode::Free3D;
hideSlice();
geopro::render::applyFree3D(rendererPtr);
renderWindowPtr->Render();
});
auto* vtkDock = new ads::CDockWidget(QStringLiteral("剖面视图")); auto* vtkDock = new ads::CDockWidget(QStringLiteral("剖面视图"));
vtkDock->setWidget(centerWidget); vtkDock->setWidget(centerWidget);
dockManager->addDockWidget(ads::CenterDockWidgetArea, vtkDock); dockManager->addDockWidget(ads::CenterDockWidgetArea, vtkDock);
@ -267,39 +255,68 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
rightDock->setWidget(propLabel); rightDock->setWidget(propLabel);
dockManager->addDockWidget(ads::RightDockWidgetArea, rightDock); dockManager->addDockWidget(ads::RightDockWidgetArea, rightDock);
// 联动:点击 DS 项 → 加载 grid/colorScale → 渲染 + 更新属性。 // 视图模式状态:当前数据集 id / 名称(供「二维/三维」按钮重渲染剖面用)。
auto currentDsId = std::make_shared<QString>();
auto currentDsName = std::make_shared<QString>();
// 渲染当前数据集的【剖面】:按 *cameraMode 选相机;体素态切回剖面也走这里。
// Scene/renderWindow 按【裸指针值】捕获Scene 挂 window 父链、renderer 被 renderWindow // Scene/renderWindow 按【裸指针值】捕获Scene 挂 window 父链、renderer 被 renderWindow
// 引用计数持有生命周期覆盖事件循环。repo 由调用方保活。 // 引用计数持有生命周期覆盖事件循环。repo 由调用方保活。
auto renderDataset = [&repo, scene, renderWindowPtr, applyCurrentCamera, propLabel]( auto renderSectionCurrent =
[&repo, scene, renderWindowPtr, applyCurrentCamera, hideSlice, propLabel, currentDsId,
currentDsName]() {
if (currentDsId->isEmpty()) return; // 还没有选中任何数据集
const std::string dsId = currentDsId->toStdString();
const auto g = repo.loadGrid(dsId);
const auto cs = repo.loadColorScale(dsId);
hideSlice(); // 回到剖面视图:关闭可能存在的体素切片
scene->clear();
const auto actors = geopro::render::buildGridContour(g, cs);
scene->addActor(actors.bands);
scene->addActor(actors.edges);
applyCurrentCamera(); // 按当前 2D/3D 模式重设相机
renderWindowPtr->Render();
propLabel->setText(QStringLiteral("数据集: %1\n网格: %2 x %3\nvmin / vmax: %4 / %5")
.arg(*currentDsName)
.arg(g.nx())
.arg(g.ny())
.arg(g.vmin)
.arg(g.vmax));
};
// 联动:点击 DS 项 → 记为当前数据集 → 默认回到二维剖面(勾「二维」+ 俯视)。
auto renderDataset = [currentDsId, currentDsName, cameraMode, act2D, renderSectionCurrent](
QTreeWidgetItem* item) { QTreeWidgetItem* item) {
const QString id = item->data(0, Qt::UserRole).toString(); const QString id = item->data(0, Qt::UserRole).toString();
if (id.isEmpty()) return; // GS/TM 节点无 dsId忽略 if (id.isEmpty()) return; // GS/TM 节点无 dsId忽略
const std::string dsId = id.toStdString(); *currentDsId = id;
const auto g = repo.loadGrid(dsId); *currentDsName = item->text(0);
const auto cs = repo.loadColorScale(dsId); *cameraMode = CameraMode::Top2D;
scene->clear(); act2D->setChecked(true); // 点数据集默认回到二维剖面
const auto actors = geopro::render::buildGridContour(g, cs); renderSectionCurrent();
scene->addActor(actors.bands);
scene->addActor(actors.edges);
applyCurrentCamera(); // 按当前 2D/3D 模式重设相机
renderWindowPtr->Render();
propLabel->setText(QStringLiteral("数据集: %1\n网格: %2 x %3\nvmin / vmax: %4 / %5")
.arg(item->text(0))
.arg(g.nx())
.arg(g.ny())
.arg(g.vmin)
.arg(g.vmax));
}; };
QObject::connect(tree, &QTreeWidget::itemClicked, tree, QObject::connect(tree, &QTreeWidget::itemClicked, tree,
[renderDataset](QTreeWidgetItem* it, int) { renderDataset(it); }); [renderDataset](QTreeWidgetItem* it, int) { renderDataset(it); });
// 视图模式:二维 = 剖面 + 俯视;三维 = 剖面 + 斜视。两者都重渲染当前剖面。
QObject::connect(act2D, &QAction::triggered, vtkWidget,
[cameraMode, renderSectionCurrent]() {
*cameraMode = CameraMode::Top2D;
renderSectionCurrent();
});
QObject::connect(act3D, &QAction::triggered, vtkWidget,
[cameraMode, renderSectionCurrent]() {
*cameraMode = CameraMode::Free3D;
renderSectionCurrent();
});
// 当前体素 vtkImageDatadd_slice 切面 widget 需复用,保活到下次重建)。 // 当前体素 vtkImageDatadd_slice 切面 widget 需复用,保活到下次重建)。
auto voxelImage = std::make_shared<vtkSmartPointer<vtkImageData>>(); auto voxelImage = std::make_shared<vtkSmartPointer<vtkImageData>>();
// dd_voxel读两条交叉剖面 → IDW 体素 → GPU 体绘制 + 默认 3D 视角 + 可拖切片。 // dd_voxel读两条交叉剖面 → IDW 体素 → GPU 体绘制 + 默认 3D 视角 + 可拖切片。
QObject::connect(actVoxel, &QAction::triggered, vtkWidget, QObject::connect(actVoxel, &QAction::triggered, vtkWidget,
[&repo, scene, rendererPtr, renderWindowPtr, cameraMode, act3D, propLabel, [&repo, scene, rendererPtr, renderWindowPtr, cameraMode, actVoxel, propLabel,
sliceWidget, voxelImage]() { sliceWidget, voxelImage]() {
QApplication::setOverrideCursor(Qt::WaitCursor); QApplication::setOverrideCursor(Qt::WaitCursor);
const auto scatters = repo.loadVoxelScatters(); const auto scatters = repo.loadVoxelScatters();
@ -318,9 +335,9 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
rendererPtr->AddViewProp(result.volume); rendererPtr->AddViewProp(result.volume);
*voxelImage = result.image; *voxelImage = result.image;
// 体素默认 3D 视角(同步工具条勾选态)。 // 体素 = 体块 + 3D 视角;高亮「三维体素」自身(互斥组会清掉 2D/3D)。
*cameraMode = CameraMode::Free3D; *cameraMode = CameraMode::Free3D;
act3D->setChecked(true); actVoxel->setChecked(true);
geopro::render::applyFree3D(rendererPtr); geopro::render::applyFree3D(rendererPtr);
rendererPtr->ResetCamera(); rendererPtr->ResetCamera();
renderWindowPtr->Render(); // 先渲一帧确保 interactor 就绪 renderWindowPtr->Render(); // 先渲一帧确保 interactor 就绪