#pragma once #include #include #include #include #include #include #include #include #include #include #include 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 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 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& 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 tex); // 拉覆盖该瓦片的 DEM(z>15 取祖先块)后落地 void placeActor(long long key, vtkSmartPointer actor); vtkSmartPointer buildFlat(int z, int x, int y, vtkSmartPointer tex); // 平面瓦片(DEM 兜底) vtkSmartPointer buildWarped(int sz, int sx, int sy, int dz, int dx, int dy, vtkSmartPointer tex, const QImage& dem); // DEM 位移网格 + 卫星贴图 void enqueueGet(const QString& url, std::function onDone); // 限并发取瓦片(回调内负责 deleteLater) void pumpNetQueue(); static void onInteractionEnd(vtkObject*, unsigned long, void* clientData, void*); geopro::render::Scene& scene_; vtkRenderWindow* rw_; std::shared_ptr frame_; QNetworkAccessManager nam_; Kind kind_ = Hidden; int generation_ = 0; // show/hide/换源 自增,丢弃过期回包 std::map> placed_; // 已贴瓦片:key→actor std::set desired_; // 当前视野应显示的瓦片 key std::set inFlight_; // 在途瓦片(续到起伏/平面最终落地) std::map demCache_; // DEM 块缓存(key=DEMz/x/y),跨隐藏/重选复用 std::map> texCache_; // 影像纹理缓存,重选/缩放回看免重拉 double ve_ = 1.0; // 地形垂向夸张(与剖面 verticalExaggeration 一致才对齐) double maxTileDist_ = 2000.0; // 底图最大距离(米),每次刷新按剖面范围动态算 std::function 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 cb; }; std::deque netQueue_; // 限并发请求队列(防瓦片暴发饱和卡死) int netInFlight_ = 0; bool terrainProbed_ = false; // 首次 fetchTerrain 打一行诊断日志 vtkSmartPointer styleObs_; // 持引用保证回调期有效 vtkSmartPointer observer_; bool renderPending_ = false; // 合并渲染:同轮多次请求只渲染一帧 bool refreshing_ = false; }; } // namespace geopro::app