1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-11-30 22:51:16 +01:00

Do not render tiles that will not be shown due to zoom in/out

This commit is contained in:
Martin Tůma 2021-09-16 22:52:46 +02:00
parent d0dc3661e4
commit fd65882907
4 changed files with 71 additions and 50 deletions

View File

@ -344,4 +344,6 @@ void RasterTile::render()
//painter.drawRect(QRect(_rect.topLeft(), _pixmap.size())); //painter.drawRect(QRect(_rect.topLeft(), _pixmap.size()));
qDeleteAll(textItems); qDeleteAll(textItems);
_valid = true;
} }

View File

@ -16,15 +16,16 @@ class RasterTile
{ {
public: public:
RasterTile(const Projection &proj, const Transform &transform, int zoom, RasterTile(const Projection &proj, const Transform &transform, int zoom,
const QRect &rect, qreal ratio, const QString &key, const QRect &rect, qreal ratio, const QList<MapData::Path> &paths,
const QList<MapData::Path> &paths, const QList<MapData::Point> &points) const QList<MapData::Point> &points) : _proj(proj), _transform(transform),
: _proj(proj), _transform(transform), _zoom(zoom), _rect(rect), _zoom(zoom), _rect(rect), _ratio(ratio),
_ratio(ratio), _key(key), _pixmap(rect.width() * ratio, _pixmap(rect.width() * ratio, rect.height() * ratio), _paths(paths),
rect.height() * ratio), _paths(paths), _points(points) {} _points(points), _valid(false) {}
const QString &key() const {return _key;} int zoom() const {return _zoom;}
QPoint xy() const {return _rect.topLeft();} QPoint xy() const {return _rect.topLeft();}
const QPixmap &pixmap() const {return _pixmap;} const QPixmap &pixmap() const {return _pixmap;}
bool isValid() const {return _valid;}
void render(); void render();
@ -84,10 +85,10 @@ private:
int _zoom; int _zoom;
QRect _rect; QRect _rect;
qreal _ratio; qreal _ratio;
QString _key;
QPixmap _pixmap; QPixmap _pixmap;
QList<MapData::Path> _paths; QList<MapData::Path> _paths;
QList<MapData::Point> _points; QList<MapData::Point> _points;
bool _valid;
}; };
inline HASH_T qHash(const RasterTile::Key &key) inline HASH_T qHash(const RasterTile::Key &key)

View File

@ -60,6 +60,8 @@ int MapsforgeMap::zoomFit(const QSize &size, const RectC &rect)
int MapsforgeMap::zoomIn() int MapsforgeMap::zoomIn()
{ {
cancelJobs();
_zoom = qMin(_zoom + 1, _data.zooms().max()); _zoom = qMin(_zoom + 1, _data.zooms().max());
updateTransform(); updateTransform();
return _zoom; return _zoom;
@ -67,6 +69,8 @@ int MapsforgeMap::zoomIn()
int MapsforgeMap::zoomOut() int MapsforgeMap::zoomOut()
{ {
cancelJobs();
_zoom = qMax(_zoom - 1, _data.zooms().min()); _zoom = qMax(_zoom - 1, _data.zooms().min());
updateTransform(); updateTransform();
return _zoom; return _zoom;
@ -101,29 +105,59 @@ void MapsforgeMap::updateTransform()
_bounds.adjust(0.5, 0, -0.5, 0); _bounds.adjust(0.5, 0, -0.5, 0);
} }
bool MapsforgeMap::isRunning(const QString &key) const bool MapsforgeMap::isRunning(int zoom, const QPoint &xy) const
{ {
return _running.contains(key); for (int i = 0; i < _jobs.size(); i++) {
const QList<Mapsforge::RasterTile> &tiles = _jobs.at(i)->tiles();
for (int j = 0; j < tiles.size(); j++) {
const Mapsforge::RasterTile &mt = tiles.at(j);
if (mt.zoom() == zoom && mt.xy() == xy)
return true;
}
}
return false;
} }
void MapsforgeMap::addRunning(const QList<RasterTile> &tiles) void MapsforgeMap::runJob(MapsforgeMapJob *job)
{ {
for (int i = 0; i < tiles.size(); i++) _jobs.append(job);
_running.insert(tiles.at(i).key());
connect(job, &MapsforgeMapJob::finished, this, &MapsforgeMap::jobFinished);
job->run();
} }
void MapsforgeMap::removeRunning(const QList<RasterTile> &tiles) void MapsforgeMap::removeJob(MapsforgeMapJob *job)
{ {
for (int i = 0; i < tiles.size(); i++) _jobs.removeOne(job);
_running.remove(tiles.at(i).key()); job->deleteLater();
} }
void MapsforgeMap::jobFinished(const QList<RasterTile> &tiles) void MapsforgeMap::jobFinished(MapsforgeMapJob *job)
{ {
removeRunning(tiles); const QList<Mapsforge::RasterTile> &tiles = job->tiles();
for (int i = 0; i < tiles.size(); i++) {
const Mapsforge::RasterTile &mt = tiles.at(i);
if (!mt.isValid())
continue;
QString key = path() + "-" + QString::number(mt.zoom()) + "_"
+ QString::number(mt.xy().x()) + "_" + QString::number(mt.xy().y());
QPixmapCache::insert(key, mt.pixmap());
}
removeJob(job);
emit tilesLoaded(); emit tilesLoaded();
} }
void MapsforgeMap::cancelJobs()
{
for (int i = 0; i < _jobs.size(); i++)
_jobs.at(i)->cancel();
}
void MapsforgeMap::draw(QPainter *painter, const QRectF &rect, Flags flags) void MapsforgeMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
{ {
Q_UNUSED(flags); Q_UNUSED(flags);
@ -138,15 +172,15 @@ void MapsforgeMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
for (int i = 0; i < width; i++) { for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) { for (int j = 0; j < height; j++) {
QPixmap pm;
QPoint ttl(tl.x() + i * _data.tileSize(), tl.y() + j QPoint ttl(tl.x() + i * _data.tileSize(), tl.y() + j
* _data.tileSize()); * _data.tileSize());
if (isRunning(_zoom, ttl))
continue;
QPixmap pm;
QString key = path() + "-" + QString::number(_zoom) + "_" QString key = path() + "-" + QString::number(_zoom) + "_"
+ QString::number(ttl.x()) + "_" + QString::number(ttl.y()); + QString::number(ttl.x()) + "_" + QString::number(ttl.y());
if (isRunning(key))
continue;
if (QPixmapCache::find(key, &pm)) if (QPixmapCache::find(key, &pm))
painter->drawPixmap(ttl, pm); painter->drawPixmap(ttl, pm);
else { else {
@ -175,18 +209,13 @@ void MapsforgeMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
tiles.append(RasterTile(_projection, _transform, _zoom, tiles.append(RasterTile(_projection, _transform, _zoom,
QRect(ttl, QSize(_data.tileSize(), _data.tileSize())), QRect(ttl, QSize(_data.tileSize(), _data.tileSize())),
_tileRatio, key, paths, points)); _tileRatio, paths, points));
} }
} }
} }
if (!tiles.isEmpty()) { if (!tiles.isEmpty())
MapsforgeMapJob *job = new MapsforgeMapJob(tiles); runJob(new MapsforgeMapJob(tiles));
connect(job, &MapsforgeMapJob::finished, this,
&MapsforgeMap::jobFinished);
addRunning(tiles);
job->run();
}
} }
void MapsforgeMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio) void MapsforgeMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)

View File

@ -26,26 +26,14 @@ public:
_future = QtConcurrent::map(_tiles, &Mapsforge::RasterTile::render); _future = QtConcurrent::map(_tiles, &Mapsforge::RasterTile::render);
_watcher.setFuture(_future); _watcher.setFuture(_future);
} }
void cancel() {_future.cancel();}
const QList<Mapsforge::RasterTile> &tiles() const {return _tiles;}
signals: signals:
void finished(const QList<Mapsforge::RasterTile> &); void finished(MapsforgeMapJob *job);
private slots: private slots:
void handleFinished() void handleFinished() {emit finished(this);}
{
for (int i = 0; i < _tiles.size(); i++) {
Mapsforge::RasterTile &mt = _tiles[i];
const QPixmap &pm = mt.pixmap();
if (pm.isNull())
continue;
QPixmapCache::insert(mt.key(), pm);
}
emit finished(_tiles);
deleteLater();
}
private: private:
QFutureWatcher<void> _watcher; QFutureWatcher<void> _watcher;
@ -85,14 +73,15 @@ public:
QString errorString() const {return _data.errorString();} QString errorString() const {return _data.errorString();}
private slots: private slots:
void jobFinished(const QList<Mapsforge::RasterTile> &tiles); void jobFinished(MapsforgeMapJob *job);
private: private:
Transform transform(int zoom) const; Transform transform(int zoom) const;
void updateTransform(); void updateTransform();
bool isRunning(const QString &key) const; bool isRunning(int zoom, const QPoint &xy) const;
void addRunning(const QList<Mapsforge::RasterTile> &tiles); void runJob(MapsforgeMapJob *job);
void removeRunning(const QList<Mapsforge::RasterTile> &tiles); void removeJob(MapsforgeMapJob *job);
void cancelJobs();
Mapsforge::MapData _data; Mapsforge::MapData _data;
int _zoom; int _zoom;
@ -102,7 +91,7 @@ private:
QRectF _bounds; QRectF _bounds;
qreal _tileRatio; qreal _tileRatio;
QSet<QString> _running; QList<MapsforgeMapJob*> _jobs;
}; };
#endif // MAPSFORGEMAP_H #endif // MAPSFORGEMAP_H