diff --git a/src/app/VtkSceneView.cpp b/src/app/VtkSceneView.cpp index 9afc54f..a10db8a 100644 --- a/src/app/VtkSceneView.cpp +++ b/src/app/VtkSceneView.cpp @@ -1,5 +1,7 @@ #include "VtkSceneView.hpp" +#include +#include #include #include @@ -64,6 +66,7 @@ void VtkSceneView::clear() { currentAxes_ = nullptr; // 旧坐标轴已随 clear 移除,置空避免悬留引用 // 体素 image 失效:置空并通知上层关闭切片(防切片附着到已移除的 image)。 currentVolumeImage_ = nullptr; + frameAnchoredToData_ = false; // 新一轮选择重新按其首个真实剖面重锚原点 if (onVolumeChanged) onVolumeChanged(); } @@ -75,6 +78,19 @@ void VtkSceneView::addSurveyLine(const geopro::core::Grid& grid) { } void VtkSceneView::addCurtain(const geopro::core::Grid& grid, const geopro::core::ColorScale& cs) { + // 首个带经纬度的剖面到达 → 把 GeoLocalFrame 原点重锚到该剖面 lat/lon 中心:使局部坐标从 0 附近起 + // (轴刻度有意义),同一选择内多条剖面共用此原点 → 相互地理配准。无经纬剖面是平面、不受原点影响。 + const int nx = grid.nx(); + if (!frameAnchoredToData_ && nx > 0 && static_cast(grid.lat.size()) >= nx && + static_cast(grid.lon.size()) >= nx) { + double la0 = grid.lat[0], la1 = grid.lat[0], lo0 = grid.lon[0], lo1 = grid.lon[0]; + for (int i = 1; i < nx; ++i) { + la0 = std::min(la0, grid.lat[i]); la1 = std::max(la1, grid.lat[i]); + lo0 = std::min(lo0, grid.lon[i]); lo1 = std::max(lo1, grid.lon[i]); + } + frame_ = std::make_shared((la0 + la1) / 2.0, (lo0 + lo1) / 2.0); + frameAnchoredToData_ = true; + } auto curtain = geopro::render::buildCurtain(grid, cs, *frame_); if (curtain) { curtain->SetScale(1.0, 1.0, verticalExaggeration_); // 纵向夸张成墙 diff --git a/src/app/VtkSceneView.hpp b/src/app/VtkSceneView.hpp index 360f11e..6f6430b 100644 --- a/src/app/VtkSceneView.hpp +++ b/src/app/VtkSceneView.hpp @@ -60,6 +60,9 @@ private: std::shared_ptr frame_; double zRefElev_; double verticalExaggeration_ = 2.0; + // 是否已按真实剖面 lat/lon 重锚 frame 原点(每次 clear 重置):默认原点取自样本、可能离真实数据 + // 很远→局部坐标巨大、轴刻度无意义;首个带经纬剖面到达时重锚到其中心,同选择内多剖面共用配准。 + bool frameAnchoredToData_ = false; // 坐标轴设置(P2):默认标准 + 米。 geopro::controller::AxesMode axesMode_ = geopro::controller::AxesMode::Standard;