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