#include #include #include #include #include #include #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) #include #else // QT_VERSION < 5 #include #endif // QT_VERSION < 5 #include "common/rectc.h" #include "common/config.h" #include "osm.h" #include "mbtilesmap.h" struct MBTile { public: MBTile() {} MBTile(const QPoint &xy) : xy(xy) {} QPixmap pixmap; QByteArray data; QString key; int zoom; QPoint xy; }; #define META_TYPE(type) static_cast(type) static void render(MBTile *tile) { tile->pixmap.loadFromData(tile->data, QString::number(tile->zoom) .toLatin1()); } static double index2mercator(int index, int zoom) { return rad2deg(-M_PI + 2 * M_PI * ((double)index / (1< _zooms.max()) return _zooms.max(); return zoom; } int MBTilesMap::zoomFit(const QSize &size, const RectC &rect) { if (!rect.isValid()) _zoom = _zooms.max(); else { QRectF tbr(OSM::ll2m(rect.topLeft()), OSM::ll2m(rect.bottomRight())); QPointF sc(tbr.width() / size.width(), tbr.height() / size.height()); _zoom = limitZoom(OSM::scale2zoom(qMax(sc.x(), -sc.y()) / coordinatesRatio(), _tileSize)); } return _zoom; } qreal MBTilesMap::resolution(const QRectF &rect) { return OSM::resolution(rect.center(), _zoom, _tileSize); } int MBTilesMap::zoomIn() { _zoom = qMin(_zoom + 1, _zooms.max()); return _zoom; } int MBTilesMap::zoomOut() { _zoom = qMax(_zoom - 1, _zooms.min()); return _zoom; } qreal MBTilesMap::coordinatesRatio() const { return _deviceRatio > 1.0 ? _deviceRatio / _tileRatio : 1.0; } qreal MBTilesMap::imageRatio() const { return _deviceRatio > 1.0 ? _deviceRatio : _tileRatio; } qreal MBTilesMap::tileSize() const { return (_tileSize / coordinatesRatio()); } QByteArray MBTilesMap::tileData(int zoom, const QPoint &tile) const { QSqlQuery query(_db); query.prepare("SELECT tile_data FROM tiles " "WHERE zoom_level=:zoom AND tile_column=:x AND tile_row=:y"); query.bindValue(":zoom", zoom); query.bindValue(":x", tile.x()); query.bindValue(":y", (1< jobs; QVector tiles; tiles.reserve(width * height); for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { QPoint t(tile.x() + i, tile.y() + j); QString key = _fileName + "-" + QString::number(_zoom) + "_" + QString::number(t.x()) + "_" + QString::number(t.y()); tiles.append(MBTile(t)); MBTile &mt = tiles.last(); if (!QPixmapCache::find(key, &(mt.pixmap))) { mt.data = tileData(_zoom, t); mt.key = key; mt.zoom = _zoom; jobs.append(&mt); } } } QFuture future = QtConcurrent::map(jobs, render); future.waitForFinished(); for (int i = 0; i < tiles.size(); i++) { MBTile &mt = tiles[i]; if (!mt.pixmap.isNull() && !mt.data.isNull()) QPixmapCache::insert(mt.key, mt.pixmap); QPointF tp(qMax(tl.x(), b.left()) + (mt.xy.x() - tile.x()) * tileSize(), qMax(tl.y(), b.top()) + (mt.xy.y() - tile.y()) * tileSize()); if (!mt.pixmap.isNull()) { #ifdef ENABLE_HIDPI mt.pixmap.setDevicePixelRatio(imageRatio()); #endif // ENABLE_HIDPI painter->drawPixmap(tp, mt.pixmap); } } } QPointF MBTilesMap::ll2xy(const Coordinates &c) { qreal scale = OSM::zoom2scale(_zoom, _tileSize); QPointF m = OSM::ll2m(c); return QPointF(m.x() / scale, m.y() / -scale) / coordinatesRatio(); } Coordinates MBTilesMap::xy2ll(const QPointF &p) { qreal scale = OSM::zoom2scale(_zoom, _tileSize); return OSM::m2ll(QPointF(p.x() * scale, -p.y() * scale) * coordinatesRatio()); }