1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-11-28 05:34:47 +01:00

Use asynchronous tile rendering in ENC maps

This commit is contained in:
Martin Tůma 2022-11-06 15:26:28 +01:00
parent e1d1842fa6
commit b13bac3af9
4 changed files with 112 additions and 11 deletions

View File

@ -200,4 +200,6 @@ void RasterTile::render()
//painter.setPen(Qt::red); //painter.setPen(Qt::red);
//painter.setBrush(Qt::NoBrush); //painter.setBrush(Qt::NoBrush);
//painter.drawRect(QRect(_rect.topLeft(), _pixmap.size())); //painter.drawRect(QRect(_rect.topLeft(), _pixmap.size()));
_valid = true;
} }

View File

@ -18,11 +18,12 @@ public:
const QList<MapData::Poly*> &polygons, const QList<MapData::Point*> &points) const QList<MapData::Poly*> &polygons, const QList<MapData::Point*> &points)
: _proj(proj), _transform(transform), _zoom(zoom), _rect(rect), : _proj(proj), _transform(transform), _zoom(zoom), _rect(rect),
_ratio(ratio), _pixmap(rect.width() * ratio, rect.height() * ratio), _ratio(ratio), _pixmap(rect.width() * ratio, rect.height() * ratio),
_lines(lines), _polygons(polygons), _points(points) {} _lines(lines), _polygons(polygons), _points(points), _valid(false) {}
int zoom() const {return _zoom;} 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();
@ -48,6 +49,7 @@ private:
QList<MapData::Line*> _lines; QList<MapData::Line*> _lines;
QList<MapData::Poly*> _polygons; QList<MapData::Poly*> _polygons;
QList<MapData::Point*> _points; QList<MapData::Point*> _points;
bool _valid;
}; };
} }

View File

@ -1,9 +1,7 @@
#include <QPainter> #include <QPainter>
#include <QPixmapCache> #include <QPixmapCache>
#include <QtConcurrent>
#include "common/range.h" #include "common/range.h"
#include "common/wgs84.h" #include "common/wgs84.h"
#include "ENC/rastertile.h"
#include "rectd.h" #include "rectd.h"
#include "pcs.h" #include "pcs.h"
#include "encmap.h" #include "encmap.h"
@ -58,6 +56,8 @@ int ENCMap::zoomFit(const QSize &size, const RectC &rect)
int ENCMap::zoomIn() int ENCMap::zoomIn()
{ {
cancelJobs();
_zoom = qMin(_zoom + 1, ZOOMS.max()); _zoom = qMin(_zoom + 1, ZOOMS.max());
updateTransform(); updateTransform();
return _zoom; return _zoom;
@ -65,6 +65,8 @@ int ENCMap::zoomIn()
int ENCMap::zoomOut() int ENCMap::zoomOut()
{ {
cancelJobs();
_zoom = qMax(_zoom - 1, ZOOMS.min()); _zoom = qMax(_zoom - 1, ZOOMS.min());
updateTransform(); updateTransform();
return _zoom; return _zoom;
@ -96,6 +98,55 @@ void ENCMap::updateTransform()
_transform.proj2img(prect.bottomRight())); _transform.proj2img(prect.bottomRight()));
} }
bool ENCMap::isRunning(int zoom, const QPoint &xy) const
{
for (int i = 0; i < _jobs.size(); i++) {
const QList<ENC::RasterTile> &tiles = _jobs.at(i)->tiles();
for (int j = 0; j < tiles.size(); j++) {
const ENC::RasterTile &mt = tiles.at(j);
if (mt.zoom() == zoom && mt.xy() == xy)
return true;
}
}
return false;
}
void ENCMap::runJob(ENCMapJob *job)
{
_jobs.append(job);
connect(job, &ENCMapJob::finished, this, &ENCMap::jobFinished);
job->run();
}
void ENCMap::removeJob(ENCMapJob *job)
{
_jobs.removeOne(job);
job->deleteLater();
}
void ENCMap::jobFinished(ENCMapJob *job)
{
const QList<ENC::RasterTile> &tiles = job->tiles();
for (int i = 0; i < tiles.size(); i++) {
const ENC::RasterTile &mt = tiles.at(i);
if (mt.isValid())
QPixmapCache::insert(key(mt.zoom(), mt.xy()), mt.pixmap());
}
removeJob(job);
emit tilesLoaded();
}
void ENCMap::cancelJobs()
{
for (int i = 0; i < _jobs.size(); i++)
_jobs.at(i)->cancel();
}
QString ENCMap::key(int zoom, const QPoint &xy) const QString ENCMap::key(int zoom, const QPoint &xy) const
{ {
return path() + "-" + QString::number(zoom) + "_" return path() + "-" + QString::number(zoom) + "_"
@ -116,6 +167,8 @@ void ENCMap::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++) {
QPoint ttl(tl.x() + i * TILE_SIZE, tl.y() + j * TILE_SIZE); QPoint ttl(tl.x() + i * TILE_SIZE, tl.y() + j * TILE_SIZE);
if (isRunning(_zoom, ttl))
continue;
QPixmap pm; QPixmap pm;
if (QPixmapCache::find(key(_zoom, ttl), &pm)) if (QPixmapCache::find(key(_zoom, ttl), &pm))
@ -149,14 +202,19 @@ void ENCMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
} }
} }
QFuture<void> future = QtConcurrent::map(tiles, &RasterTile::render); if (!tiles.isEmpty()) {
future.waitForFinished(); if (flags & Map::Block) {
QFuture<void> future = QtConcurrent::map(tiles, &RasterTile::render);
future.waitForFinished();
for (int i = 0; i < tiles.size(); i++) { for (int i = 0; i < tiles.size(); i++) {
const RasterTile &mt = tiles.at(i); const RasterTile &mt = tiles.at(i);
const QPixmap &pm = mt.pixmap(); const QPixmap &pm = mt.pixmap();
painter->drawPixmap(mt.xy(), pm); painter->drawPixmap(mt.xy(), pm);
QPixmapCache::insert(key(mt.zoom(), mt.xy()), pm); QPixmapCache::insert(key(mt.zoom(), mt.xy()), pm);
}
} else
runJob(new ENCMapJob(tiles));
} }
} }

View File

@ -1,12 +1,42 @@
#ifndef ENCMAP_H #ifndef ENCMAP_H
#define ENCMAP_H #define ENCMAP_H
#include <QtConcurrent>
#include "map.h" #include "map.h"
#include "projection.h" #include "projection.h"
#include "transform.h" #include "transform.h"
#include "ENC/mapdata.h" #include "ENC/mapdata.h"
#include "ENC/rastertile.h"
class QFile; class ENCMapJob : public QObject
{
Q_OBJECT
public:
ENCMapJob(const QList<ENC::RasterTile> &tiles)
: _tiles(tiles) {}
void run()
{
connect(&_watcher, &QFutureWatcher<void>::finished, this,
&ENCMapJob::handleFinished);
_future = QtConcurrent::map(_tiles, &ENC::RasterTile::render);
_watcher.setFuture(_future);
}
void cancel() {_future.cancel();}
const QList<ENC::RasterTile> &tiles() const {return _tiles;}
signals:
void finished(ENCMapJob *job);
private slots:
void handleFinished() {emit finished(this);}
private:
QFutureWatcher<void> _watcher;
QFuture<void> _future;
QList<ENC::RasterTile> _tiles;
};
class ENCMap : public Map class ENCMap : public Map
{ {
@ -43,9 +73,16 @@ public:
static Map *create(const QString &path, const Projection &, bool *isMap); static Map *create(const QString &path, const Projection &, bool *isMap);
private slots:
void jobFinished(ENCMapJob *job);
private: private:
Transform transform(int zoom) const; Transform transform(int zoom) const;
void updateTransform(); void updateTransform();
bool isRunning(int zoom, const QPoint &xy) const;
void runJob(ENCMapJob *job);
void removeJob(ENCMapJob *job);
void cancelJobs();
QString key(int zoom, const QPoint &xy) const; QString key(int zoom, const QPoint &xy) const;
ENC::MapData _data; ENC::MapData _data;
@ -56,6 +93,8 @@ private:
QRectF _bounds; QRectF _bounds;
int _zoom; int _zoom;
QList<ENCMapJob*> _jobs;
bool _valid; bool _valid;
QString _errorString; QString _errorString;
}; };