geopro/src/app/TileBasemap.hpp

101 lines
5.5 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
#include <QImage>
#include <QNetworkAccessManager>
#include <QObject>
#include <deque>
#include <functional>
#include <map>
#include <memory>
#include <set>
#include <utility>
#include <vector>
#include <vtkSmartPointer.h>
class vtkActor;
class vtkObject;
class vtkTexture;
class vtkRenderWindow;
class vtkInteractorObserver;
class vtkCallbackCommand;
class QNetworkReply;
namespace geopro::render { class Scene; }
namespace geopro::core { class GeoLocalFrame; }
namespace geopro::app {
// 天地图 WMTS 底图层局部平面B 方案)+ LOD按相机视距自动选瓦片层级、覆盖可视范围
// 缩放/平移结束后增量增删瓦片。复用轨迹图同款 token瓦片经同一 GeoLocalFrame 配准。
class TileBasemap : public QObject {
Q_OBJECT
public:
enum Kind { Street = 0, Satellite = 1, Hidden = 2 };
TileBasemap(geopro::render::Scene& scene, vtkRenderWindow* rw,
std::shared_ptr<geopro::core::GeoLocalFrame> frame, QObject* parent = nullptr);
~TileBasemap() override;
void show(Kind kind); // 显示某底图Hidden 等同 hide记住类型供 LOD 刷新复用
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);
void ensureObserver(); // 首次显示时挂到交互样式的 EndInteractionEvent
void requestRender(); // 合并渲染:同一事件循环轮次多次请求只渲染一帧
void purgeStale(); // 本轮请求全部落地后再删旧层瓦片,避免缩放空白闪烁
// 四叉树细分:按瓦片投影屏幕尺寸递归(近细远粗),收集叶瓦片到 out。
void refineTile(int z, int x, int y, std::set<long long>& out, int& count);
void fetchTile(int z, int x, int y, long long key);
void fetchTerrain(int z, int x, int y, long long key,
vtkSmartPointer<vtkTexture> tex); // 拉覆盖该瓦片的 DEM(z>15 取祖先块)后落地
void placeActor(long long key, vtkSmartPointer<vtkActor> actor);
vtkSmartPointer<vtkActor> buildFlat(int z, int x, int y,
vtkSmartPointer<vtkTexture> tex); // 平面瓦片(DEM 兜底)
vtkSmartPointer<vtkActor> buildWarped(int sz, int sx, int sy, int dz, int dx, int dy,
vtkSmartPointer<vtkTexture> tex,
const QImage& dem); // DEM 位移网格 + 卫星贴图
void enqueueGet(const QString& url,
std::function<void(QNetworkReply*)> onDone); // 限并发取瓦片(回调内负责 deleteLater)
void pumpNetQueue();
static void onInteractionEnd(vtkObject*, unsigned long, void* clientData, void*);
geopro::render::Scene& scene_;
vtkRenderWindow* rw_;
std::shared_ptr<geopro::core::GeoLocalFrame> frame_;
QNetworkAccessManager nam_;
Kind kind_ = Hidden;
int generation_ = 0; // show/hide/换源 自增,丢弃过期回包
std::map<long long, vtkSmartPointer<vtkActor>> placed_; // 已贴瓦片key→actor
std::set<long long> desired_; // 当前视野应显示的瓦片 key
std::set<long long> inFlight_; // 在途瓦片(续到起伏/平面最终落地)
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_; // 返回当前勾选剖面合并范围的半径
// 卫星层「学习到的」最大可用层级:天地图卫星影像各区域覆盖深度不同(内地到z18, 台湾等仅到z16),
// 超出则回固定「此级别下无影像」占位图。检测到占位即把上限降到 z-1 并重铺(改用父层真实影像放大),
// 使该区域不再请求无影像层。show()/换源时复位为 kMaxZoom 以便新区域重新探测。
int satMaxZoom_ = 18;
// 四叉树当前帧相机参数(refresh 写, refineTile 读):相机位置 + 投影系数 + 视锥 6 面。
double camX_ = 0, camY_ = 0, camZ_ = 0;
double projK_ = 1.0;
bool projParallel_ = false;
double frustum_[24] = {0}; // 6 个视锥平面(内法向)AABB 全在某面外则剔除
struct PendingGet { QString url; std::function<void(QNetworkReply*)> cb; };
std::deque<PendingGet> netQueue_; // 限并发请求队列(防瓦片暴发饱和卡死)
int netInFlight_ = 0;
bool terrainProbed_ = false; // 首次 fetchTerrain 打一行诊断日志
vtkSmartPointer<vtkInteractorObserver> styleObs_; // 持引用保证回调期有效
vtkSmartPointer<vtkCallbackCommand> observer_;
bool renderPending_ = false; // 合并渲染:同轮多次请求只渲染一帧
bool refreshing_ = false;
};
} // namespace geopro::app