fix(vtk): 视口内点选切片/异常也显示子树贴合轴(与树选一致)

视口点选经 onSliceSelectionChanged→selectItem(QSignalBlocker下)压制 datasetSelected,
故 T2 贴合轴只在树选中出、视口点选缺失(仅取消方向已恢复全景轴)。抽 T2 树路解析序列为
共用 lambda applyFittedAxes(subtreeDsIds→datasetBounds→showFittedAxes),树路精简复用,
视口非空分支直接调用补齐(不解 blocker,保留防选择环);无盒则保持现状不强推全景轴。
This commit is contained in:
gaozheng 2026-07-01 10:26:32 +08:00
parent dd0205919d
commit f67913982d
1 changed files with 24 additions and 16 deletions

View File

@ -1263,10 +1263,26 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
sceneView->setAnomalyVisible(id.toStdString(), vis); sceneView->setAnomalyVisible(id.toStdString(), vis);
renderWindowPtr->Render(); renderWindowPtr->Render();
}); });
// 贴合坐标轴T2据非空选中 ds 解析其子树盒并显示贴合轴。返回 true=已应用贴合轴(有效盒)。
// 树选中与 VTK 视口点选共用同一解析(子树 dsId → datasetBounds → showFittedAxes保证两路对称。
// 调用方据返回值决定退回策略(树路:非空但无盒 → 全景轴;视口路:无盒 → 保持现状不强推全景)。
auto applyFittedAxes = [sceneView, analysisTab](const QString& dsId) -> bool {
if (dsId.isEmpty()) return false;
const QStringList sub = analysisTab->subtreeDsIds(dsId);
std::vector<std::string> ids;
ids.reserve(static_cast<size_t>(sub.size()));
for (const QString& s : sub) ids.push_back(s.toStdString());
double box[6];
if (!ids.empty() && sceneView->datasetBounds(ids, box)) {
sceneView->showFittedAxes(box);
return true;
}
return false;
};
// 树选中切片/异常 → VTK 高亮联动(正向 list→VTK反向 VTK→list 需拾取回调,见 OPT-002 // 树选中切片/异常 → VTK 高亮联动(正向 list→VTK反向 VTK→list 需拾取回调,见 OPT-002
QObject::connect(analysisTab, &geopro::app::CategoryAnalysisTab::datasetSelected, vtkWidget, QObject::connect(analysisTab, &geopro::app::CategoryAnalysisTab::datasetSelected, vtkWidget,
[sceneView, interactionMgr, renderWindowPtr, analysisTab](const QString& dsId, [sceneView, interactionMgr, renderWindowPtr, applyFittedAxes](
const QString& ddCode) { const QString& dsId, const QString& ddCode) {
const std::string id = dsId.toStdString(); const std::string id = dsId.toStdString();
// 选中项决定高亮:异常↔切片互斥,选其它对象两者都清(否则切到别的对象后切片/异常仍高亮)。 // 选中项决定高亮:异常↔切片互斥,选其它对象两者都清(否则切到别的对象后切片/异常仍高亮)。
if (ddCode == QStringLiteral("dd_anomaly")) { if (ddCode == QStringLiteral("dd_anomaly")) {
@ -1281,19 +1297,7 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
} }
// 贴合坐标轴T2选中 → 该 ds 子树盒贴合轴+隐全景;空选中(取消) → 恢复全景轴。 // 贴合坐标轴T2选中 → 该 ds 子树盒贴合轴+隐全景;空选中(取消) → 恢复全景轴。
// 子树未渲染/无盒 → 退回全景轴,避免留下无据的贴合框。 // 子树未渲染/无盒 → 退回全景轴,避免留下无据的贴合框。
if (dsId.isEmpty()) { if (!applyFittedAxes(dsId)) sceneView->showSceneAxes();
sceneView->showSceneAxes();
} else {
const QStringList sub = analysisTab->subtreeDsIds(dsId);
std::vector<std::string> ids;
ids.reserve(static_cast<size_t>(sub.size()));
for (const QString& s : sub) ids.push_back(s.toStdString());
double box[6];
if (!ids.empty() && sceneView->datasetBounds(ids, box))
sceneView->showFittedAxes(box);
else
sceneView->showSceneAxes();
}
renderWindowPtr->Render(); renderWindowPtr->Render();
}); });
// 2D 段「z 值」滑块 → 整体升降该 2D 类型平面Plane2DRenderStrategy 重摆其全部足迹)。 // 2D 段「z 值」滑块 → 整体升降该 2D 类型平面Plane2DRenderStrategy 重摆其全部足迹)。
@ -1306,7 +1310,7 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
&geopro::controller::VtkSceneController::setBasemapOpacity); &geopro::controller::VtkSceneController::setBasemapOpacity);
// 反向 VTK→list在 VTK 里点中/选中一张切片 → 在三维体段树里同步选中该切片行(②反向)。 // 反向 VTK→list在 VTK 里点中/选中一张切片 → 在三维体段树里同步选中该切片行(②反向)。
// 点空白/清选(dsId 空) → 一并清 VTK 异常高亮(否则取消选中后异常图形仍高亮,用户反馈)。 // 点空白/清选(dsId 空) → 一并清 VTK 异常高亮(否则取消选中后异常图形仍高亮,用户反馈)。
interactionMgr->onSliceSelectionChanged = [drawer, sceneView, renderWindowPtr]( interactionMgr->onSliceSelectionChanged = [drawer, sceneView, renderWindowPtr, applyFittedAxes](
const std::string& dsId) { const std::string& dsId) {
if (auto* sec = drawer->analysisTab()->section("voxel")) if (auto* sec = drawer->analysisTab()->section("voxel"))
sec->selectItem(QString::fromStdString(dsId)); sec->selectItem(QString::fromStdString(dsId));
@ -1314,6 +1318,10 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
sceneView->setSelectedAnomaly(std::string{}); sceneView->setSelectedAnomaly(std::string{});
sceneView->showSceneAxes(); // VTK 里点空白清选 → 一并恢复全景轴selectItem 空被 blocker 拦,不走 datasetSelected sceneView->showSceneAxes(); // VTK 里点空白清选 → 一并恢复全景轴selectItem 空被 blocker 拦,不走 datasetSelected
renderWindowPtr->Render(); renderWindowPtr->Render();
} else {
// 视口内点选切片/异常/体 → 与树选一致显示子树贴合轴。selectItem 在 QSignalBlocker 下不发
// datasetSelected防选择环故这里直接走共用解析补上贴合轴。无盒则保持现状不强推全景
if (applyFittedAxes(QString::fromStdString(dsId))) renderWindowPtr->Render();
} }
}; };
// 已保存切片经 VTK 右键「关闭」→ 取消数据列表对应切片项的勾选(否则列表仍勾选,用户反馈)。 // 已保存切片经 VTK 右键「关闭」→ 取消数据列表对应切片项的勾选(否则列表仍勾选,用户反馈)。