diff options
-rw-r--r-- | src/location/maps/qgeotiledmap.cpp | 7 | ||||
-rw-r--r-- | src/location/maps/qgeotiledmapscene.cpp | 42 | ||||
-rw-r--r-- | src/location/maps/qgeotilerequestmanager.cpp | 25 | ||||
-rw-r--r-- | src/location/maps/qgeotilerequestmanager_p.h | 2 |
4 files changed, 62 insertions, 14 deletions
diff --git a/src/location/maps/qgeotiledmap.cpp b/src/location/maps/qgeotiledmap.cpp index 68f150db..450cdd44 100644 --- a/src/location/maps/qgeotiledmap.cpp +++ b/src/location/maps/qgeotiledmap.cpp @@ -320,12 +320,11 @@ void QGeoTiledMapPrivate::updateScene() q->evaluateCopyrights(tiles); // don't request tiles that are already built and textured - QList<QSharedPointer<QGeoTileTexture> > cachedTiles = + QMap<QGeoTileSpec, QSharedPointer<QGeoTileTexture> > cachedTiles = m_tileRequests->requestTiles(m_visibleTiles->createTiles() - m_mapScene->texturedTiles()); - foreach (const QSharedPointer<QGeoTileTexture> &tex, cachedTiles) { - m_mapScene->addTile(tex->spec, tex); - } + for (auto it = cachedTiles.cbegin(); it != cachedTiles.cend(); ++it) + m_mapScene->addTile(it.key(), it.value()); if (!cachedTiles.isEmpty()) emit q->sgNodeChanged(); diff --git a/src/location/maps/qgeotiledmapscene.cpp b/src/location/maps/qgeotiledmapscene.cpp index d38eec39..977b4764 100644 --- a/src/location/maps/qgeotiledmapscene.cpp +++ b/src/location/maps/qgeotiledmapscene.cpp @@ -88,6 +88,7 @@ public: double m_mapEdgeSize; QHash<QGeoTileSpec, QSharedPointer<QGeoTileTexture> > m_textures; + QVector<QGeoTileSpec> m_updatedTextures; // tilesToGrid transform int m_minTileX; // the minimum tile index, i.e. 0 to sideLength which is 1<< zoomLevel @@ -164,9 +165,9 @@ QSet<QGeoTileSpec> QGeoTiledMapScene::texturedTiles() { Q_D(QGeoTiledMapScene); QSet<QGeoTileSpec> textured; - foreach (const QGeoTileSpec &tile, d->m_textures.keys()) { - textured += tile; - } + for (auto it = d->m_textures.cbegin(); it != d->m_textures.cend(); ++it) + textured += it.value()->spec; + return textured; } @@ -227,7 +228,19 @@ bool QGeoTiledMapScenePrivate::buildGeometry(const QGeoTileSpec &spec, QSGImageN imageNode->setRect(QRectF(QPointF(x1, y2), QPointF(x2, y1))); imageNode->setTextureCoordinatesTransform(QSGImageNode::MirrorVertically); - imageNode->setSourceRect(QRectF(QPointF(0,0), imageNode->texture()->textureSize())); + + // Calculate the texture mapping, in case we are magnifying some lower ZL tile + const QGeoTileSpec textureSpec = m_textures.value(spec)->spec; + if (textureSpec.zoom() < spec.zoom()) { + // Currently only using lower ZL tiles for the overzoom. + const int tilesPerTexture = 1 << (spec.zoom() - textureSpec.zoom()); + const int mappedSize = imageNode->texture()->textureSize().width() / tilesPerTexture; + const int x = (spec.x() % tilesPerTexture) * mappedSize; + const int y = (spec.y() % tilesPerTexture) * mappedSize; + imageNode->setSourceRect(QRectF(x, y, mappedSize, mappedSize)); + } else { + imageNode->setSourceRect(QRectF(QPointF(0,0), imageNode->texture()->textureSize())); + } return true; } @@ -237,6 +250,8 @@ void QGeoTiledMapScenePrivate::addTile(const QGeoTileSpec &spec, QSharedPointer< if (!m_visibleTiles.contains(spec)) // Don't add the geometry if it isn't visible return; + if (m_textures.contains(spec)) + m_updatedTextures.append(spec); m_textures.insert(spec, texture); } @@ -644,6 +659,25 @@ QSGNode *QGeoTiledMapScene::updateSceneGraph(QSGNode *oldNode, QQuickWindow *win d->m_dropTextures = false; } + // Evicting loZL tiles temporarily used in place of hiZL ones + if (d->m_updatedTextures.size()) { + const QVector<QGeoTileSpec> &toRemove = d->m_updatedTextures; + for (const QGeoTileSpec &s : toRemove) { + if (mapRoot->tiles->tiles.contains(s)) + delete mapRoot->tiles->tiles.take(s); + + if (mapRoot->wrapLeft->tiles.contains(s)) + delete mapRoot->wrapLeft->tiles.take(s); + + if (mapRoot->wrapRight->tiles.contains(s)) + delete mapRoot->wrapRight->tiles.take(s); + + if (mapRoot->textures.contains(s)) + mapRoot->textures.take(s)->deleteLater(); + } + d->m_updatedTextures.clear(); + } + QSet<QGeoTileSpec> textures = QSet<QGeoTileSpec>::fromList(mapRoot->textures.keys()); QSet<QGeoTileSpec> toRemove = textures - d->m_visibleTiles; QSet<QGeoTileSpec> toAdd = d->m_visibleTiles - textures; diff --git a/src/location/maps/qgeotilerequestmanager.cpp b/src/location/maps/qgeotilerequestmanager.cpp index 1409856a..7672a98f 100644 --- a/src/location/maps/qgeotilerequestmanager.cpp +++ b/src/location/maps/qgeotilerequestmanager.cpp @@ -53,7 +53,7 @@ public: QGeoTiledMap *m_map; QPointer<QGeoTiledMappingManagerEngine> m_engine; - QList<QSharedPointer<QGeoTileTexture> > requestTiles(const QSet<QGeoTileSpec> &tiles); + QMap<QGeoTileSpec, QSharedPointer<QGeoTileTexture> > requestTiles(const QSet<QGeoTileSpec> &tiles); void tileError(const QGeoTileSpec &tile, const QString &errorString); QHash<QGeoTileSpec, int> m_retries; @@ -74,7 +74,7 @@ QGeoTileRequestManager::~QGeoTileRequestManager() } -QList<QSharedPointer<QGeoTileTexture> > QGeoTileRequestManager::requestTiles(const QSet<QGeoTileSpec> &tiles) +QMap<QGeoTileSpec, QSharedPointer<QGeoTileTexture> > QGeoTileRequestManager::requestTiles(const QSet<QGeoTileSpec> &tiles) { return d_ptr->requestTiles(tiles); } @@ -107,7 +107,7 @@ QGeoTileRequestManagerPrivate::~QGeoTileRequestManagerPrivate() { } -QList<QSharedPointer<QGeoTileTexture> > QGeoTileRequestManagerPrivate::requestTiles(const QSet<QGeoTileSpec> &tiles) +QMap<QGeoTileSpec, QSharedPointer<QGeoTileTexture> > QGeoTileRequestManagerPrivate::requestTiles(const QSet<QGeoTileSpec> &tiles) { QSet<QGeoTileSpec> cancelTiles = m_requested - tiles; QSet<QGeoTileSpec> requestTiles = tiles - m_requested; @@ -117,7 +117,7 @@ QList<QSharedPointer<QGeoTileTexture> > QGeoTileRequestManagerPrivate::requestTi typedef QSet<QGeoTileSpec>::const_iterator iter; - QList<QSharedPointer<QGeoTileTexture> > cachedTex; + QMap<QGeoTileSpec, QSharedPointer<QGeoTileTexture> > cachedTex; // remove tiles in cache from request tiles if (!m_engine.isNull()) { @@ -127,8 +127,23 @@ QList<QSharedPointer<QGeoTileTexture> > QGeoTileRequestManagerPrivate::requestTi QGeoTileSpec tile = *i; QSharedPointer<QGeoTileTexture> tex = m_engine->getTileTexture(tile); if (tex) { - cachedTex << tex; + cachedTex.insert(tile, tex); cached.insert(tile); + } else { + // Try to use textures from lower zoom levels, but still request the proper tile + QGeoTileSpec spec = tile; + const int endRange = qMax(0, tile.zoom() - 4); // Using up to 4 zoom levels up. 4 is arbitrary. + for (int z = tile.zoom() - 1; z >= endRange; z--) { + int denominator = 1 << (tile.zoom() - z); + spec.setZoom(z); + spec.setX(tile.x() / denominator); + spec.setY(tile.y() / denominator); + QSharedPointer<QGeoTileTexture> t = m_engine->getTileTexture(spec); + if (t) { + cachedTex.insert(tile, t); + break; + } + } } } } diff --git a/src/location/maps/qgeotilerequestmanager_p.h b/src/location/maps/qgeotilerequestmanager_p.h index 66d2251e..f8ea4814 100644 --- a/src/location/maps/qgeotilerequestmanager_p.h +++ b/src/location/maps/qgeotilerequestmanager_p.h @@ -64,7 +64,7 @@ public: explicit QGeoTileRequestManager(QGeoTiledMap *map, QGeoTiledMappingManagerEngine *engine); ~QGeoTileRequestManager(); - QList<QSharedPointer<QGeoTileTexture> > requestTiles(const QSet<QGeoTileSpec> &tiles); + QMap<QGeoTileSpec, QSharedPointer<QGeoTileTexture> > requestTiles(const QSet<QGeoTileSpec> &tiles); void tileError(const QGeoTileSpec &tile, const QString &errorString); void tileFetched(const QGeoTileSpec &spec); |