mirror of
https://github.com/tumic0/GPXSee.git
synced 2024-11-24 19:55:53 +01:00
Render MBTiles maps asynchronous if they include vector tiles
This commit is contained in:
parent
69e1198efa
commit
bbc03ae59f
@ -4,8 +4,6 @@
|
|||||||
#include <QSqlError>
|
#include <QSqlError>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QPixmapCache>
|
#include <QPixmapCache>
|
||||||
#include <QImageReader>
|
|
||||||
#include <QBuffer>
|
|
||||||
#include <QtConcurrent>
|
#include <QtConcurrent>
|
||||||
#include "common/util.h"
|
#include "common/util.h"
|
||||||
#include "osm.h"
|
#include "osm.h"
|
||||||
@ -14,37 +12,6 @@
|
|||||||
|
|
||||||
#define META_TYPE(type) static_cast<QMetaType::Type>(type)
|
#define META_TYPE(type) static_cast<QMetaType::Type>(type)
|
||||||
|
|
||||||
class MBTile
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
MBTile(int zoom, int scaledSize, const QPoint &xy, const QByteArray &data,
|
|
||||||
const QString &key) : _zoom(zoom), _scaledSize(scaledSize), _xy(xy),
|
|
||||||
_data(data), _key(key) {}
|
|
||||||
|
|
||||||
const QPoint &xy() const {return _xy;}
|
|
||||||
const QString &key() const {return _key;}
|
|
||||||
const QPixmap &pixmap() const {return _pixmap;}
|
|
||||||
|
|
||||||
void load() {
|
|
||||||
QByteArray z(QString::number(_zoom).toLatin1());
|
|
||||||
|
|
||||||
QBuffer buffer(&_data);
|
|
||||||
QImageReader reader(&buffer, z);
|
|
||||||
if (_scaledSize)
|
|
||||||
reader.setScaledSize(QSize(_scaledSize, _scaledSize));
|
|
||||||
_pixmap = QPixmap::fromImage(reader.read());
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
int _zoom;
|
|
||||||
int _scaledSize;
|
|
||||||
QPoint _xy;
|
|
||||||
QByteArray _data;
|
|
||||||
QString _key;
|
|
||||||
QPixmap _pixmap;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
MBTilesMap::MBTilesMap(const QString &fileName, QObject *parent)
|
MBTilesMap::MBTilesMap(const QString &fileName, QObject *parent)
|
||||||
: Map(fileName, parent), _mapRatio(1.0), _tileRatio(1.0), _scalable(false),
|
: Map(fileName, parent), _mapRatio(1.0), _tileRatio(1.0), _scalable(false),
|
||||||
_scaledSize(0), _valid(false)
|
_scaledSize(0), _valid(false)
|
||||||
@ -183,6 +150,7 @@ void MBTilesMap::load(const Projection &in, const Projection &out,
|
|||||||
|
|
||||||
void MBTilesMap::unload()
|
void MBTilesMap::unload()
|
||||||
{
|
{
|
||||||
|
cancelJobs(true);
|
||||||
_db.close();
|
_db.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,12 +187,16 @@ qreal MBTilesMap::resolution(const QRectF &rect)
|
|||||||
|
|
||||||
int MBTilesMap::zoomIn()
|
int MBTilesMap::zoomIn()
|
||||||
{
|
{
|
||||||
|
cancelJobs(false);
|
||||||
|
|
||||||
_zi = qMin(_zi + 1, _zooms.size() - 1);
|
_zi = qMin(_zi + 1, _zooms.size() - 1);
|
||||||
return _zi;
|
return _zi;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MBTilesMap::zoomOut()
|
int MBTilesMap::zoomOut()
|
||||||
{
|
{
|
||||||
|
cancelJobs(false);
|
||||||
|
|
||||||
_zi = qMax(_zi - 1, 0);
|
_zi = qMax(_zi - 1, 0);
|
||||||
return _zi;
|
return _zi;
|
||||||
}
|
}
|
||||||
@ -260,6 +232,53 @@ QByteArray MBTilesMap::tileData(int zoom, const QPoint &tile) const
|
|||||||
return QByteArray();
|
return QByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MBTilesMap::isRunning(const QString &key) const
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _jobs.size(); i++) {
|
||||||
|
const QList<MBTile> &tiles = _jobs.at(i)->tiles();
|
||||||
|
for (int j = 0; j < tiles.size(); j++)
|
||||||
|
if (tiles.at(j).key() == key)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MBTilesMap::runJob(MBTilesMapJob *job)
|
||||||
|
{
|
||||||
|
_jobs.append(job);
|
||||||
|
|
||||||
|
connect(job, &MBTilesMapJob::finished, this, &MBTilesMap::jobFinished);
|
||||||
|
job->run();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MBTilesMap::removeJob(MBTilesMapJob *job)
|
||||||
|
{
|
||||||
|
_jobs.removeOne(job);
|
||||||
|
job->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MBTilesMap::jobFinished(MBTilesMapJob *job)
|
||||||
|
{
|
||||||
|
const QList<MBTile> &tiles = job->tiles();
|
||||||
|
|
||||||
|
for (int i = 0; i < tiles.size(); i++) {
|
||||||
|
const MBTile &mt = tiles.at(i);
|
||||||
|
if (!mt.pixmap().isNull())
|
||||||
|
QPixmapCache::insert(mt.key(), mt.pixmap());
|
||||||
|
}
|
||||||
|
|
||||||
|
removeJob(job);
|
||||||
|
|
||||||
|
emit tilesLoaded();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MBTilesMap::cancelJobs(bool wait)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _jobs.size(); i++)
|
||||||
|
_jobs.at(i)->cancel(wait);
|
||||||
|
}
|
||||||
|
|
||||||
void MBTilesMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
void MBTilesMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||||
{
|
{
|
||||||
Q_UNUSED(flags);
|
Q_UNUSED(flags);
|
||||||
@ -288,6 +307,9 @@ void MBTilesMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
|||||||
QString key = path() + "-" + QString::number(zoom) + "_"
|
QString key = path() + "-" + QString::number(zoom) + "_"
|
||||||
+ QString::number(t.x()) + "_" + QString::number(t.y());
|
+ QString::number(t.x()) + "_" + QString::number(t.y());
|
||||||
|
|
||||||
|
if (isRunning(key))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (QPixmapCache::find(key, &pm)) {
|
if (QPixmapCache::find(key, &pm)) {
|
||||||
QPointF tp(qMax(tl.x(), b.left()) + (t.x() - tile.x())
|
QPointF tp(qMax(tl.x(), b.left()) + (t.x() - tile.x())
|
||||||
* tileSize(), qMax(tl.y(), b.top()) + (t.y() - tile.y())
|
* tileSize(), qMax(tl.y(), b.top()) + (t.y() - tile.y())
|
||||||
@ -300,21 +322,26 @@ void MBTilesMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QFuture<void> future = QtConcurrent::map(tiles, &MBTile::load);
|
if (!tiles.isEmpty()) {
|
||||||
future.waitForFinished();
|
if (flags & Map::Block || !_scalable) {
|
||||||
|
QFuture<void> future = QtConcurrent::map(tiles, &MBTile::load);
|
||||||
|
future.waitForFinished();
|
||||||
|
|
||||||
for (int i = 0; i < tiles.size(); i++) {
|
for (int i = 0; i < tiles.size(); i++) {
|
||||||
const MBTile &mt = tiles.at(i);
|
const MBTile &mt = tiles.at(i);
|
||||||
QPixmap pm(mt.pixmap());
|
QPixmap pm(mt.pixmap());
|
||||||
if (pm.isNull())
|
if (pm.isNull())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
QPixmapCache::insert(mt.key(), pm);
|
QPixmapCache::insert(mt.key(), pm);
|
||||||
|
|
||||||
QPointF tp(qMax(tl.x(), b.left()) + (mt.xy().x() - tile.x())
|
QPointF tp(qMax(tl.x(), b.left()) + (mt.xy().x() - tile.x())
|
||||||
* tileSize(), qMax(tl.y(), b.top()) + (mt.xy().y() - tile.y())
|
* tileSize(), qMax(tl.y(), b.top()) + (mt.xy().y() - tile.y())
|
||||||
* tileSize());
|
* tileSize());
|
||||||
drawTile(painter, pm, tp);
|
drawTile(painter, pm, tp);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
runJob(new MBTilesMapJob(tiles));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,10 +3,80 @@
|
|||||||
|
|
||||||
#include <QSqlDatabase>
|
#include <QSqlDatabase>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
#include <QImageReader>
|
||||||
|
#include <QBuffer>
|
||||||
|
#include <QPixmap>
|
||||||
|
#include <QtConcurrent>
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
|
|
||||||
|
class MBTile
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MBTile(int zoom, int scaledSize, const QPoint &xy, const QByteArray &data,
|
||||||
|
const QString &key) : _zoom(zoom), _scaledSize(scaledSize), _xy(xy),
|
||||||
|
_data(data), _key(key) {}
|
||||||
|
|
||||||
|
const QPoint &xy() const {return _xy;}
|
||||||
|
const QString &key() const {return _key;}
|
||||||
|
const QPixmap &pixmap() const {return _pixmap;}
|
||||||
|
|
||||||
|
void load() {
|
||||||
|
QByteArray z(QString::number(_zoom).toLatin1());
|
||||||
|
|
||||||
|
QBuffer buffer(&_data);
|
||||||
|
QImageReader reader(&buffer, z);
|
||||||
|
if (_scaledSize)
|
||||||
|
reader.setScaledSize(QSize(_scaledSize, _scaledSize));
|
||||||
|
_pixmap = QPixmap::fromImage(reader.read());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int _zoom;
|
||||||
|
int _scaledSize;
|
||||||
|
QPoint _xy;
|
||||||
|
QByteArray _data;
|
||||||
|
QString _key;
|
||||||
|
QPixmap _pixmap;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MBTilesMapJob : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
MBTilesMapJob(const QList<MBTile> &tiles) : _tiles(tiles) {}
|
||||||
|
|
||||||
|
void run()
|
||||||
|
{
|
||||||
|
connect(&_watcher, &QFutureWatcher<void>::finished, this,
|
||||||
|
&MBTilesMapJob::handleFinished);
|
||||||
|
_future = QtConcurrent::map(_tiles, &MBTile::load);
|
||||||
|
_watcher.setFuture(_future);
|
||||||
|
}
|
||||||
|
void cancel(bool wait)
|
||||||
|
{
|
||||||
|
_future.cancel();
|
||||||
|
if (wait)
|
||||||
|
_future.waitForFinished();
|
||||||
|
}
|
||||||
|
const QList<MBTile> &tiles() const {return _tiles;}
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void finished(MBTilesMapJob *job);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void handleFinished() {emit finished(this);}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QFutureWatcher<void> _watcher;
|
||||||
|
QFuture<void> _future;
|
||||||
|
QList<MBTile> _tiles;
|
||||||
|
};
|
||||||
|
|
||||||
class MBTilesMap : public Map
|
class MBTilesMap : public Map
|
||||||
{
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MBTilesMap(const QString &fileName, QObject *parent = 0);
|
MBTilesMap(const QString &fileName, QObject *parent = 0);
|
||||||
|
|
||||||
@ -36,12 +106,19 @@ public:
|
|||||||
|
|
||||||
static Map *create(const QString &path, const Projection &proj, bool *isDir);
|
static Map *create(const QString &path, const Projection &proj, bool *isDir);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void jobFinished(MBTilesMapJob *job);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
qreal tileSize() const;
|
qreal tileSize() const;
|
||||||
qreal coordinatesRatio() const;
|
qreal coordinatesRatio() const;
|
||||||
qreal imageRatio() const;
|
qreal imageRatio() const;
|
||||||
QByteArray tileData(int zoom, const QPoint &tile) const;
|
QByteArray tileData(int zoom, const QPoint &tile) const;
|
||||||
void drawTile(QPainter *painter, QPixmap &pixmap, QPointF &tp);
|
void drawTile(QPainter *painter, QPixmap &pixmap, QPointF &tp);
|
||||||
|
bool isRunning(const QString &key) const;
|
||||||
|
void runJob(MBTilesMapJob *job);
|
||||||
|
void removeJob(MBTilesMapJob *job);
|
||||||
|
void cancelJobs(bool wait);
|
||||||
|
|
||||||
QSqlDatabase _db;
|
QSqlDatabase _db;
|
||||||
|
|
||||||
@ -54,6 +131,8 @@ private:
|
|||||||
bool _scalable;
|
bool _scalable;
|
||||||
int _scaledSize;
|
int _scaledSize;
|
||||||
|
|
||||||
|
QList<MBTilesMapJob*> _jobs;
|
||||||
|
|
||||||
bool _valid;
|
bool _valid;
|
||||||
QString _errorString;
|
QString _errorString;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user