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