feat(vtk): 底图范围按剖面合并范围动态定(半径x10,夹2-30km),随勾选增删自动伸缩;取代固定10km/234km
This commit is contained in:
parent
c5577ce071
commit
484992a434
|
|
@ -43,7 +43,10 @@ const char* kTk = "aca91d8c9f59a4f779f39061b8a07737";
|
|||
constexpr int kRootZoom = 9; // 四叉树根层级(单块~78km,±1 覆盖~234km 到天边)
|
||||
constexpr double kTargetPx = 384.0; // 瓦片屏幕像素阈值:超过则细分(越小越清晰但块更多)
|
||||
constexpr int kMaxLeaves = 200; // 一次覆盖的叶瓦片上限(安全兜底,防细分爆炸)
|
||||
constexpr double kMaxTileDist = 10000.0; // 底图离数据中心最大距离(米):远裁剪面有界,且免无限拉远
|
||||
// 底图最大距离按剖面范围动态定:半径×倍数,夹在[下限,上限]。随勾选增删自动伸缩;无数据时用下限。
|
||||
constexpr double kRangeFactor = 10.0;
|
||||
constexpr double kRangeFloor = 2000.0; // 至少 2km(小剖面也有足够地理背景)
|
||||
constexpr double kRangeCeil = 30000.0; // 最多 30km(防远裁剪面失控)
|
||||
constexpr int kMaxConcurrent = 8; // 瓦片请求最大并发(防暴发饱和单域名连接)
|
||||
constexpr int kMinZoom = 3;
|
||||
constexpr int kMaxZoom = 18;
|
||||
|
|
@ -217,9 +220,9 @@ void TileBasemap::refineTile(int z, int x, int y, std::set<long long>& out, int&
|
|||
const double cx = (sw.x + ne.x) * 0.5, cy = (sw.y + ne.y) * 0.5; // 瓦片中心(局部米)
|
||||
const double g = std::max(std::abs(ne.x - sw.x), std::abs(ne.y - sw.y)); // 瓦片地面尺寸(米)
|
||||
|
||||
// 距离上限:数据中心在局部原点(0,0);瓦片离它太远则不加载——远裁剪面有界(剖面不被近裁剪面切),
|
||||
// 也避免拉远时无限铺。叶块本身可大于此距离(其近端仍在范围内即保留)。
|
||||
if (std::sqrt(cx * cx + cy * cy) - g * 0.5 > kMaxTileDist) return;
|
||||
// 距离上限(按剖面范围动态):数据中心在局部原点(0,0);瓦片离它太远则不加载——远裁剪面有界
|
||||
// (剖面不被近裁剪面切),也避免拉远无限铺。叶块本身可大于此距离(其近端仍在范围内即保留)。
|
||||
if (std::sqrt(cx * cx + cy * cy) - g * 0.5 > maxTileDist_) return;
|
||||
|
||||
// 该瓦片投影到屏幕的近似像素尺寸 > 阈值且未到最大层级 → 细分为 4 子块(近处更细)。
|
||||
double screenPx;
|
||||
|
|
@ -268,6 +271,13 @@ void TileBasemap::refresh() {
|
|||
for (int k = 0; k < 4; ++k) pl[k] = -pl[k];
|
||||
}
|
||||
|
||||
// 底图最大距离按当前剖面合并范围动态定(随勾选增删自动伸缩);无数据用下限。
|
||||
maxTileDist_ = kRangeFloor;
|
||||
if (dataRadiusProvider_) {
|
||||
const double r = dataRadiusProvider_();
|
||||
if (r > 0.0) maxTileDist_ = std::clamp(r * kRangeFactor, kRangeFloor, kRangeCeil);
|
||||
}
|
||||
|
||||
// 四叉树:从数据中心一圈粗根块出发,按屏幕误差细分 → 近细远粗、铺满视野,无单层级盲区。
|
||||
desired_.clear();
|
||||
int count = 0;
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <vtkSmartPointer.h>
|
||||
|
|
@ -39,6 +40,8 @@ public:
|
|||
void hide(); // 移除全部瓦片
|
||||
void refresh(); // 按当前相机重算层级+覆盖,增量更新瓦片(交互结束回调)
|
||||
void setVerticalExaggeration(double ve); // 地形垂向夸张(须与剖面 VE 一致才对齐)
|
||||
// 数据半径提供者:刷新时查询当前所有勾选剖面的合并范围(半径,米),据此动态定底图最大范围。
|
||||
void setDataRadiusProvider(std::function<double()> fn) { dataRadiusProvider_ = std::move(fn); }
|
||||
|
||||
private:
|
||||
static long long tileKey(int z, int x, int y);
|
||||
|
|
@ -73,6 +76,8 @@ private:
|
|||
std::map<long long, QImage> demCache_; // DEM 块缓存(key=DEMz/x/y),跨隐藏/重选复用
|
||||
std::map<long long, vtkSmartPointer<vtkTexture>> texCache_; // 影像纹理缓存,重选/缩放回看免重拉
|
||||
double ve_ = 1.0; // 地形垂向夸张(与剖面 verticalExaggeration 一致才对齐)
|
||||
double maxTileDist_ = 2000.0; // 底图最大距离(米),每次刷新按剖面范围动态算
|
||||
std::function<double()> dataRadiusProvider_; // 返回当前勾选剖面合并范围的半径
|
||||
// 四叉树当前帧相机参数(refresh 写, refineTile 读):相机位置 + 投影系数 + 视锥 6 面。
|
||||
double camX_ = 0, camY_ = 0, camZ_ = 0;
|
||||
double projK_ = 1.0;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include "VtkSceneView.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
|
|
@ -88,6 +89,13 @@ bool VtkSceneView::computeDataBounds(double out[6]) const {
|
|||
return true;
|
||||
}
|
||||
|
||||
double VtkSceneView::dataHorizontalRadius() const {
|
||||
double b[6];
|
||||
if (!computeDataBounds(b)) return 0.0;
|
||||
const double dx = b[1] - b[0], dy = b[3] - b[2];
|
||||
return 0.5 * std::sqrt(dx * dx + dy * dy); // 水平对角线半径
|
||||
}
|
||||
|
||||
void VtkSceneView::clear() {
|
||||
// 只移除数据 prop(按 ds 跟踪)+ 杂项(地形/测线)+ 坐标轴;不动底图(TileBasemap 自管)→ 重建不丢图。
|
||||
for (auto& kv : dsProps_) removeProps(kv.second);
|
||||
|
|
|
|||
|
|
@ -72,6 +72,12 @@ private:
|
|||
// 仅数据图元(剖面/体素/地形/测线)的包围盒,不含底图 → 坐标轴/取景不被~公里级底图撑大。
|
||||
bool computeDataBounds(double out[6]) const;
|
||||
|
||||
public:
|
||||
// 当前所有数据图元(剖面等)合并范围的水平半径(米);无数据返回 0。供底图动态定最大范围。
|
||||
double dataHorizontalRadius() const;
|
||||
|
||||
private:
|
||||
|
||||
geopro::render::Scene& scene_;
|
||||
vtkRenderWindow* renderWindow_;
|
||||
std::shared_ptr<geopro::core::GeoLocalFrame> frame_;
|
||||
|
|
|
|||
|
|
@ -414,6 +414,8 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
|
|||
};
|
||||
// 相机程序化变化(取景/预设/缩放)后,底图按新视锥重算覆盖(治首帧部分瓦片需手动微动才出)。
|
||||
sceneView->onCameraChanged = [basemap]() { basemap->refresh(); };
|
||||
// 底图最大范围按当前勾选剖面合并范围动态定(随增删自动伸缩);刷新时实时查询。
|
||||
basemap->setDataRadiusProvider([sceneView]() { return sceneView->dataHorizontalRadius(); });
|
||||
// 垂直夸张:地形须与剖面用同一 VE 才对齐(都按真实高程×VE)。
|
||||
QObject::connect(drawer->col3D(), &geopro::app::Column3DDataset::verticalExaggerationChanged,
|
||||
basemap, [basemap](double ve) { basemap->setVerticalExaggeration(ve); });
|
||||
|
|
|
|||
Loading…
Reference in New Issue