From fb43237830dedf09de461941db5c2f95364771b8 Mon Sep 17 00:00:00 2001 From: gaozheng Date: Wed, 17 Jun 2026 15:19:16 +0800 Subject: [PATCH] =?UTF-8?q?fix(vtk):=20=E4=BF=AE=E5=9E=82=E7=9B=B4?= =?UTF-8?q?=E5=81=8F=E7=A7=BB=E6=A0=B9=E5=9B=A0-=E5=9B=9B=E5=8F=89?= =?UTF-8?q?=E6=A0=91=E7=B2=97=E5=9D=97=E5=85=88=E5=88=B0=E6=97=B6baseline?= =?UTF-8?q?=E6=9C=AA=E5=AE=9A=E5=B0=B1=E6=8C=89=E5=85=A8=E9=AB=98=E7=A8=8B?= =?UTF-8?q?warp=E6=8A=8A=E5=9C=B0=E5=BD=A2=E6=8A=AC=E9=AB=98;=E6=94=B9show?= =?UTF-8?q?=E6=97=B6=E5=85=88=E6=8B=89=E6=95=B0=E6=8D=AE=E4=B8=AD=E5=BF=83?= =?UTF-8?q?DEM=E5=AE=9A=E5=9F=BA=E5=87=86=E5=86=8D=E9=93=BA=E7=93=A6?= =?UTF-8?q?=E7=89=87(=E5=85=A8=E5=9C=BA=E5=90=8C=E4=B8=80=E5=9F=BA?= =?UTF-8?q?=E5=87=86)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/TileBasemap.cpp | 31 ++++++++++++++++++++++++++++++- src/app/TileBasemap.hpp | 1 + 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/app/TileBasemap.cpp b/src/app/TileBasemap.cpp index 2055cf6..4535bb6 100644 --- a/src/app/TileBasemap.cpp +++ b/src/app/TileBasemap.cpp @@ -182,7 +182,36 @@ void TileBasemap::show(Kind kind) { requestRender(); return; } - refresh(); // 四叉树覆盖:近细远粗一次铺满(含远处粗块,无需单独粗底层) + primeBaselineThenRefresh(); // 先定基准高程再铺瓦片:避免先到的粗块用错基准把地形整体抬高 +} + +void TileBasemap::primeBaselineThenRefresh() { + if (haveBaseline_ || kind_ != Satellite) { refresh(); return; } + // 先拉"含数据中心"的 DEM 块定基准(z15),确保任何瓦片 warp 前基准已就位、全场一致。 + const auto c = frame_->toLatLon(0.0, 0.0); + const int z = kDemMaxZoom; + const geopro::render::TileXY t = geopro::render::lonLatToTile(c.lon, c.lat, z); + const long long demKey = tileKey(z, t.x, t.y); + auto cached = demCache_.find(demKey); + if (cached != demCache_.end()) { + ensureBaseline(z, t.x, t.y, cached->second); + refresh(); + return; + } + const int gen = generation_; + const QString url = + QStringLiteral("https://api.mapbox.com/v4/mapbox.terrain-rgb/%1/%2/%3.pngraw?access_token=%4") + .arg(z).arg(t.x).arg(t.y).arg(QString::fromLatin1(kMapboxToken)); + enqueueGet(url, [this, z, t, demKey, gen](QNetworkReply* r) { + r->deleteLater(); + if (gen != generation_) return; + QImage dem; + if (r->error() == QNetworkReply::NoError && dem.loadFromData(r->readAll())) { + demCache_[demKey] = dem; + ensureBaseline(z, t.x, t.y, dem); + } + refresh(); // 成功→基准就位;失败→baseline=0 兜底,但仍全场一致 + }); } void TileBasemap::refineTile(int z, int x, int y, std::set& out, int& count) { diff --git a/src/app/TileBasemap.hpp b/src/app/TileBasemap.hpp index 42d8797..1a69278 100644 --- a/src/app/TileBasemap.hpp +++ b/src/app/TileBasemap.hpp @@ -43,6 +43,7 @@ private: static long long tileKey(int z, int x, int y); void ensureObserver(); // 首次显示时挂到交互样式的 EndInteractionEvent void requestRender(); // 合并渲染:同一事件循环轮次多次请求只渲染一帧 + void primeBaselineThenRefresh(); // 先定数据中心基准高程,再铺四叉树(保证所有瓦片同一基准) void purgeStale(); // 本轮请求全部落地后再删旧层瓦片,避免缩放空白闪烁 // 四叉树细分:按瓦片投影屏幕尺寸递归(近细远粗),收集叶瓦片到 out。 void refineTile(int z, int x, int y, std::set& out, int& count);