mirror of
https://github.com/tumic0/GPXSee.git
synced 2024-11-27 21:24:47 +01:00
Use asynchronous tiles rendering in IMG maps
On Android devices, the rendering is very slow so use the same approach as already used in Mapsforge maps.
This commit is contained in:
parent
25869200db
commit
7ba19b8c0a
@ -174,6 +174,8 @@ void RasterTile::render()
|
|||||||
|
|
||||||
qDeleteAll(textItems);
|
qDeleteAll(textItems);
|
||||||
|
|
||||||
|
_valid = true;
|
||||||
|
|
||||||
//painter.setPen(Qt::red);
|
//painter.setPen(Qt::red);
|
||||||
//painter.setRenderHint(QPainter::Antialiasing, false);
|
//painter.setRenderHint(QPainter::Antialiasing, false);
|
||||||
//painter.drawRect(QRect(_xy, _pixmap.size()));
|
//painter.drawRect(QRect(_xy, _pixmap.size()));
|
||||||
@ -185,7 +187,7 @@ void RasterTile::ll2xy(QList<MapData::Poly> &polys)
|
|||||||
MapData::Poly &poly = polys[i];
|
MapData::Poly &poly = polys[i];
|
||||||
for (int j = 0; j < poly.points.size(); j++) {
|
for (int j = 0; j < poly.points.size(); j++) {
|
||||||
QPointF &p = poly.points[j];
|
QPointF &p = poly.points[j];
|
||||||
p = _map->ll2xy(Coordinates(p.x(), p.y()));
|
p = ll2xy(Coordinates(p.x(), p.y()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -193,7 +195,7 @@ void RasterTile::ll2xy(QList<MapData::Poly> &polys)
|
|||||||
void RasterTile::ll2xy(QList<MapData::Point> &points)
|
void RasterTile::ll2xy(QList<MapData::Point> &points)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < points.size(); i++) {
|
for (int i = 0; i < points.size(); i++) {
|
||||||
QPointF p(_map->ll2xy(points.at(i).coordinates));
|
QPointF p(ll2xy(points.at(i).coordinates));
|
||||||
points[i].coordinates = Coordinates(p.x(), p.y());
|
points[i].coordinates = Coordinates(p.x(), p.y());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -210,8 +212,8 @@ void RasterTile::drawPolygons(QPainter *painter)
|
|||||||
|
|
||||||
if (poly.raster.isValid()) {
|
if (poly.raster.isValid()) {
|
||||||
RectC r(poly.raster.rect());
|
RectC r(poly.raster.rect());
|
||||||
QPointF tl(_map->ll2xy(r.topLeft()));
|
QPointF tl(ll2xy(r.topLeft()));
|
||||||
QPointF br(_map->ll2xy(r.bottomRight()));
|
QPointF br(ll2xy(r.bottomRight()));
|
||||||
QSizeF size(QRectF(tl, br).size());
|
QSizeF size(QRectF(tl, br).size());
|
||||||
|
|
||||||
bool insert = false;
|
bool insert = false;
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#include <QPixmap>
|
#include <QPixmap>
|
||||||
#include "mapdata.h"
|
#include "mapdata.h"
|
||||||
|
#include "map/projection.h"
|
||||||
|
#include "map/transform.h"
|
||||||
|
|
||||||
class QPainter;
|
class QPainter;
|
||||||
class IMGMap;
|
class IMGMap;
|
||||||
@ -15,20 +17,25 @@ class Style;
|
|||||||
class RasterTile
|
class RasterTile
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RasterTile(IMGMap *map, const Style *style, int zoom, const QRect &rect,
|
RasterTile(const Projection &proj, const Transform &transform,
|
||||||
qreal ratio, const QString &key, const QList<MapData::Poly> &polygons,
|
const Style *style, int zoom, const QRect &rect, qreal ratio,
|
||||||
|
const QString &key, const QList<MapData::Poly> &polygons,
|
||||||
const QList<MapData::Poly> &lines, QList<MapData::Point> &points)
|
const QList<MapData::Poly> &lines, QList<MapData::Point> &points)
|
||||||
: _map(map), _style(style), _zoom(zoom), _rect(rect), _ratio(ratio),
|
: _proj(proj), _transform(transform), _style(style), _zoom(zoom),
|
||||||
_key(key), _pixmap(rect.width() * ratio, rect.height() * ratio),
|
_rect(rect), _ratio(ratio), _key(key),
|
||||||
_polygons(polygons), _lines(lines), _points(points) {}
|
_pixmap(rect.width() * ratio, rect.height() * ratio), _polygons(polygons),
|
||||||
|
_lines(lines), _points(points), _valid(false) {}
|
||||||
|
|
||||||
const QString &key() const {return _key;}
|
const QString &key() const {return _key;}
|
||||||
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();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
QPointF ll2xy(const Coordinates &c) const
|
||||||
|
{return _transform.proj2img(_proj.ll2xy(c));}
|
||||||
void ll2xy(QList<MapData::Poly> &polys);
|
void ll2xy(QList<MapData::Poly> &polys);
|
||||||
void ll2xy(QList<MapData::Point> &points);
|
void ll2xy(QList<MapData::Point> &points);
|
||||||
|
|
||||||
@ -42,7 +49,8 @@ private:
|
|||||||
void processShields(QList<TextItem*> &textItems);
|
void processShields(QList<TextItem*> &textItems);
|
||||||
void processStreetNames(QList<TextItem*> &textItems);
|
void processStreetNames(QList<TextItem*> &textItems);
|
||||||
|
|
||||||
IMGMap *_map;
|
Projection _proj;
|
||||||
|
Transform _transform;
|
||||||
const Style *_style;
|
const Style *_style;
|
||||||
int _zoom;
|
int _zoom;
|
||||||
QRect _rect;
|
QRect _rect;
|
||||||
@ -52,6 +60,7 @@ private:
|
|||||||
QList<MapData::Poly> _polygons;
|
QList<MapData::Poly> _polygons;
|
||||||
QList<MapData::Poly> _lines;
|
QList<MapData::Poly> _lines;
|
||||||
QList<MapData::Point> _points;
|
QList<MapData::Point> _points;
|
||||||
|
bool _valid;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -100,6 +100,8 @@ int IMGMap::zoomFit(const QSize &size, const RectC &rect)
|
|||||||
|
|
||||||
int IMGMap::zoomIn()
|
int IMGMap::zoomIn()
|
||||||
{
|
{
|
||||||
|
cancelJobs();
|
||||||
|
|
||||||
_zoom = qMin(_zoom + 1, _data.first()->zooms().max());
|
_zoom = qMin(_zoom + 1, _data.first()->zooms().max());
|
||||||
updateTransform();
|
updateTransform();
|
||||||
return _zoom;
|
return _zoom;
|
||||||
@ -107,6 +109,8 @@ int IMGMap::zoomIn()
|
|||||||
|
|
||||||
int IMGMap::zoomOut()
|
int IMGMap::zoomOut()
|
||||||
{
|
{
|
||||||
|
cancelJobs();
|
||||||
|
|
||||||
_zoom = qMax(_zoom - 1, _data.first()->zooms().min());
|
_zoom = qMax(_zoom - 1, _data.first()->zooms().min());
|
||||||
updateTransform();
|
updateTransform();
|
||||||
return _zoom;
|
return _zoom;
|
||||||
@ -139,6 +143,53 @@ void IMGMap::updateTransform()
|
|||||||
_bounds.adjust(0.5, 0, -0.5, 0);
|
_bounds.adjust(0.5, 0, -0.5, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IMGMap::isRunning(const QString &key) const
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _jobs.size(); i++) {
|
||||||
|
const QList<IMG::RasterTile> &tiles = _jobs.at(i)->tiles();
|
||||||
|
for (int j = 0; j < tiles.size(); j++)
|
||||||
|
if (tiles.at(j).key() == key)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IMGMap::runJob(IMGMapJob *job)
|
||||||
|
{
|
||||||
|
_jobs.append(job);
|
||||||
|
|
||||||
|
connect(job, &IMGMapJob::finished, this, &IMGMap::jobFinished);
|
||||||
|
job->run();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IMGMap::removeJob(IMGMapJob *job)
|
||||||
|
{
|
||||||
|
_jobs.removeOne(job);
|
||||||
|
job->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IMGMap::jobFinished(IMGMapJob *job)
|
||||||
|
{
|
||||||
|
const QList<IMG::RasterTile> &tiles = job->tiles();
|
||||||
|
|
||||||
|
for (int i = 0; i < tiles.size(); i++) {
|
||||||
|
const IMG::RasterTile &mt = tiles.at(i);
|
||||||
|
if (mt.isValid())
|
||||||
|
QPixmapCache::insert(mt.key(), mt.pixmap());
|
||||||
|
}
|
||||||
|
|
||||||
|
removeJob(job);
|
||||||
|
|
||||||
|
emit tilesLoaded();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IMGMap::cancelJobs()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _jobs.size(); i++)
|
||||||
|
_jobs.at(i)->cancel();
|
||||||
|
}
|
||||||
|
|
||||||
void IMGMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
void IMGMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||||
{
|
{
|
||||||
Q_UNUSED(flags);
|
Q_UNUSED(flags);
|
||||||
@ -159,6 +210,9 @@ void IMGMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
|||||||
QString key(_data.at(n)->fileName() + "-" + QString::number(_zoom)
|
QString key(_data.at(n)->fileName() + "-" + 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 {
|
||||||
@ -182,7 +236,8 @@ void IMGMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
|||||||
_data.at(n)->points(pointRectD.toRectC(_projection, 20),
|
_data.at(n)->points(pointRectD.toRectC(_projection, 20),
|
||||||
_zoom, &points);
|
_zoom, &points);
|
||||||
|
|
||||||
tiles.append(RasterTile(this, _data.at(n)->style(), _zoom,
|
tiles.append(RasterTile(_projection, _transform,
|
||||||
|
_data.at(n)->style(), _zoom,
|
||||||
QRect(ttl, QSize(TILE_SIZE, TILE_SIZE)), _tileRatio, key,
|
QRect(ttl, QSize(TILE_SIZE, TILE_SIZE)), _tileRatio, key,
|
||||||
polygons, lines, points));
|
polygons, lines, points));
|
||||||
}
|
}
|
||||||
@ -190,6 +245,8 @@ void IMGMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!tiles.isEmpty()) {
|
||||||
|
if (flags & Map::Block) {
|
||||||
QFuture<void> future = QtConcurrent::map(tiles, &RasterTile::render);
|
QFuture<void> future = QtConcurrent::map(tiles, &RasterTile::render);
|
||||||
future.waitForFinished();
|
future.waitForFinished();
|
||||||
|
|
||||||
@ -199,6 +256,9 @@ void IMGMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
|||||||
painter->drawPixmap(mt.xy(), pm);
|
painter->drawPixmap(mt.xy(), pm);
|
||||||
QPixmapCache::insert(mt.key(), pm);
|
QPixmapCache::insert(mt.key(), pm);
|
||||||
}
|
}
|
||||||
|
} else
|
||||||
|
runJob(new IMGMapJob(tiles));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IMGMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
|
void IMGMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
|
||||||
|
@ -1,12 +1,44 @@
|
|||||||
#ifndef IMGMAP_H
|
#ifndef IMGMAP_H
|
||||||
#define IMGMAP_H
|
#define IMGMAP_H
|
||||||
|
|
||||||
|
#include <QtConcurrent>
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
#include "projection.h"
|
#include "projection.h"
|
||||||
#include "transform.h"
|
#include "transform.h"
|
||||||
#include "IMG/mapdata.h"
|
#include "IMG/mapdata.h"
|
||||||
|
#include "IMG/rastertile.h"
|
||||||
|
|
||||||
|
|
||||||
|
class IMGMapJob : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
IMGMapJob(const QList<IMG::RasterTile> &tiles)
|
||||||
|
: _tiles(tiles) {}
|
||||||
|
|
||||||
|
void run()
|
||||||
|
{
|
||||||
|
connect(&_watcher, &QFutureWatcher<void>::finished, this,
|
||||||
|
&IMGMapJob::handleFinished);
|
||||||
|
_future = QtConcurrent::map(_tiles, &IMG::RasterTile::render);
|
||||||
|
_watcher.setFuture(_future);
|
||||||
|
}
|
||||||
|
void cancel() {_future.cancel();}
|
||||||
|
const QList<IMG::RasterTile> &tiles() const {return _tiles;}
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void finished(IMGMapJob *job);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void handleFinished() {emit finished(this);}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QFutureWatcher<void> _watcher;
|
||||||
|
QFuture<void> _future;
|
||||||
|
QList<IMG::RasterTile> _tiles;
|
||||||
|
};
|
||||||
|
|
||||||
class IMGMap : public Map
|
class IMGMap : public Map
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -44,9 +76,16 @@ public:
|
|||||||
|
|
||||||
static Map* create(const QString &path, const Projection &, bool *isDir);
|
static Map* create(const QString &path, const Projection &, bool *isDir);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void jobFinished(IMGMapJob *job);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Transform transform(int zoom) const;
|
Transform transform(int zoom) const;
|
||||||
void updateTransform();
|
void updateTransform();
|
||||||
|
bool isRunning(const QString &key) const;
|
||||||
|
void runJob(IMGMapJob *job);
|
||||||
|
void removeJob(IMGMapJob *job);
|
||||||
|
void cancelJobs();
|
||||||
|
|
||||||
QList<IMG::MapData *> _data;
|
QList<IMG::MapData *> _data;
|
||||||
int _zoom;
|
int _zoom;
|
||||||
@ -56,6 +95,8 @@ private:
|
|||||||
RectC _dataBounds;
|
RectC _dataBounds;
|
||||||
qreal _tileRatio;
|
qreal _tileRatio;
|
||||||
|
|
||||||
|
QList<IMGMapJob*> _jobs;
|
||||||
|
|
||||||
bool _valid;
|
bool _valid;
|
||||||
QString _errorString;
|
QString _errorString;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user