From fd43051d8d3a81cfff0908fc51181222968a0980 Mon Sep 17 00:00:00 2001 From: gaozheng Date: Wed, 17 Jun 2026 15:09:00 +0800 Subject: [PATCH] =?UTF-8?q?perf(vtk):=20=E6=92=A4=E9=94=80=E9=98=B2?= =?UTF-8?q?=E6=8A=96=E5=AE=9A=E6=97=B6=E5=99=A8,=E6=94=B9=E5=90=88?= =?UTF-8?q?=E5=B9=B6=E6=B8=B2=E6=9F=93(requestRender:=E5=90=8C=E4=BA=8B?= =?UTF-8?q?=E4=BB=B6=E5=BE=AA=E7=8E=AF=E5=A4=9A=E6=AC=A1=E8=AF=B7=E6=B1=82?= =?UTF-8?q?=E5=8F=AA=E6=B8=B2=E4=B8=80=E5=B8=A7)=E6=B2=BB=E6=BB=9A?= =?UTF-8?q?=E8=BD=AE=E5=8D=A1=E9=A1=BF-=E6=A0=B9=E5=9B=A0=E6=98=AF?= =?UTF-8?q?=E9=80=90=E7=93=A6=E7=89=87=E9=87=8D=E5=A4=8DRender?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/TileBasemap.cpp | 37 ++++++++++++++++++++++--------------- src/app/TileBasemap.hpp | 4 ++-- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/src/app/TileBasemap.cpp b/src/app/TileBasemap.cpp index cda36fb..2055cf6 100644 --- a/src/app/TileBasemap.cpp +++ b/src/app/TileBasemap.cpp @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include @@ -108,10 +107,19 @@ long long TileBasemap::tileKey(int z, int x, int y) { TileBasemap::TileBasemap(geopro::render::Scene& scene, vtkRenderWindow* rw, std::shared_ptr frame, QObject* parent) - : QObject(parent), scene_(scene), rw_(rw), frame_(std::move(frame)) { - refreshTimer_ = new QTimer(this); - refreshTimer_->setSingleShot(true); - connect(refreshTimer_, &QTimer::timeout, this, [this]() { refresh(); }); + : QObject(parent), scene_(scene), rw_(rw), frame_(std::move(frame)) {} + +void TileBasemap::requestRender() { + // 合并渲染:同一事件循环轮次内的多次请求只渲染一帧(标准做法,避免逐瓦片重复 Render 卡顿)。 + if (renderPending_) return; + renderPending_ = true; + QMetaObject::invokeMethod( + this, + [this]() { + renderPending_ = false; + if (rw_) rw_->Render(); + }, + Qt::QueuedConnection); } TileBasemap::~TileBasemap() { @@ -133,8 +141,7 @@ void TileBasemap::ensureObserver() { } void TileBasemap::onInteractionEnd(vtkObject*, unsigned long, void* clientData, void*) { - // 防抖:交互(滚轮/旋转/平移)停止 ~140ms 后才刷新四叉树,避免每格事件都重算卡顿。 - if (auto* self = static_cast(clientData)) self->refreshTimer_->start(140); + if (auto* self = static_cast(clientData)) self->refresh(); } void TileBasemap::enqueueGet(const QString& url, std::function onDone) { @@ -172,7 +179,7 @@ void TileBasemap::show(Kind kind) { terrainProbed_ = false; kind_ = kind; if (kind == Hidden) { - if (rw_) rw_->Render(); + requestRender(); return; } refresh(); // 四叉树覆盖:近细远粗一次铺满(含远处粗块,无需单独粗底层) @@ -266,7 +273,7 @@ void TileBasemap::refresh() { purgeStale(); ren->ResetCameraClippingRange(); // 交互后扩裁剪面以含新载入的底图瓦片(防被"蒙版"切) - if (rw_) rw_->Render(); + requestRender(); refreshing_ = false; } @@ -284,7 +291,7 @@ void TileBasemap::purgeStale() { ++it; } } - if (removed && rw_) rw_->Render(); + if (removed) requestRender(); } void TileBasemap::fetchTile(int z, int x, int y, long long key) { @@ -299,7 +306,7 @@ void TileBasemap::fetchTile(int z, int x, int y, long long key) { placeActor(key, buildFlat(z, x, y, tex)); inFlight_.erase(key); purgeStale(); - if (rw_) rw_->Render(); + requestRender(); } return; } @@ -331,7 +338,7 @@ void TileBasemap::fetchTile(int z, int x, int y, long long key) { if (!ok) { inFlight_.erase(key); purgeStale(); - if (rw_) rw_->Render(); + requestRender(); return; } auto tex = makeTexture(img); @@ -343,7 +350,7 @@ void TileBasemap::fetchTile(int z, int x, int y, long long key) { placeActor(key, buildFlat(z, x, y, tex)); // 街道图无地形 → 直接平面 inFlight_.erase(key); purgeStale(); - if (rw_) rw_->Render(); + requestRender(); } }); } @@ -410,7 +417,7 @@ void TileBasemap::fetchTerrain(int z, int x, int y, long long key, vtkSmartPoint } inFlight_.erase(key); purgeStale(); - if (rw_) rw_->Render(); + requestRender(); }; // 命中缓存:同一祖先 DEM 块的多个瓦片瞬间起伏,免重复网络。 @@ -439,7 +446,7 @@ void TileBasemap::fetchTerrain(int z, int x, int y, long long key, vtkSmartPoint desired_.find(key) == desired_.end() || placed_.count(key)) { inFlight_.erase(key); // 过期/移出视野 → 不落地 purgeStale(); - if (rw_) rw_->Render(); + requestRender(); return; } QImage dem; diff --git a/src/app/TileBasemap.hpp b/src/app/TileBasemap.hpp index 349b478..42d8797 100644 --- a/src/app/TileBasemap.hpp +++ b/src/app/TileBasemap.hpp @@ -20,7 +20,6 @@ class vtkRenderWindow; class vtkInteractorObserver; class vtkCallbackCommand; class QNetworkReply; -class QTimer; namespace geopro::render { class Scene; } namespace geopro::core { class GeoLocalFrame; } @@ -43,6 +42,7 @@ public: 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); @@ -85,7 +85,7 @@ private: bool terrainProbed_ = false; // 首次 fetchTerrain 打一行诊断日志 vtkSmartPointer styleObs_; // 持引用保证回调期有效 vtkSmartPointer observer_; - QTimer* refreshTimer_ = nullptr; // 交互防抖:滚轮/旋转停止后才刷新四叉树(避免每格卡) + bool renderPending_ = false; // 合并渲染:同轮多次请求只渲染一帧 bool refreshing_ = false; };