diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/location/maps/qgeocameratiles.cpp | 85 | ||||
-rw-r--r-- | src/location/maps/qgeocameratiles_p.h | 11 | ||||
-rw-r--r-- | src/location/maps/qgeomapscene.cpp | 6 | ||||
-rw-r--r-- | src/location/maps/qgeomapscene_p.h | 2 | ||||
-rw-r--r-- | src/location/maps/qgeotiledmap.cpp | 112 | ||||
-rw-r--r-- | src/location/maps/qgeotiledmap_p.h | 3 | ||||
-rw-r--r-- | src/location/maps/qgeotiledmap_p_p.h | 5 |
7 files changed, 121 insertions, 103 deletions
diff --git a/src/location/maps/qgeocameratiles.cpp b/src/location/maps/qgeocameratiles.cpp index d2783a5b..5eae7c0b 100644 --- a/src/location/maps/qgeocameratiles.cpp +++ b/src/location/maps/qgeocameratiles.cpp @@ -49,7 +49,6 @@ #include <cmath> QT_BEGIN_NAMESPACE -#define PREFETCH_FRUSTUM_SCALE 2.0 struct Frustum { @@ -77,7 +76,6 @@ public: QGeoCameraData m_camera; QSize m_screenSize; int m_tileSize; - int m_maxZoom; QSet<QGeoTileSpec> m_tiles; int m_intZoomLevel; @@ -86,8 +84,9 @@ public: bool m_dirtyGeometry; bool m_dirtyMetadata; + double m_viewExpansion; void updateMetadata(); - void updateGeometry(double viewExpansion = 1.0); + void updateGeometry(); Frustum createFrustum(double fieldOfViewGradient) const; @@ -127,58 +126,6 @@ QGeoCameraTiles::~QGeoCameraTiles() { } -QSet<QGeoTileSpec> QGeoCameraTiles::prefetchTiles(PrefetchStle style) -{ - int currentIntZoom = static_cast<int>(std::floor(d_ptr->m_camera.zoomLevel())); - double currentFloatZoom = d_ptr->m_camera.zoomLevel(); - - d_ptr->m_tiles.clear(); - d_ptr->m_intZoomLevel = currentIntZoom; - d_ptr->m_sideLength = 1 << d_ptr->m_intZoomLevel ; - d_ptr->updateGeometry(PREFETCH_FRUSTUM_SCALE); - - switch (style) { - - case PrefetchNeighbourLayer: { - - double zoomFraction = d_ptr->m_camera.zoomLevel() - currentIntZoom; - int nearestNeighbourLayer = zoomFraction > 0.5 ? currentIntZoom + 1 : currentIntZoom - 1; - if (nearestNeighbourLayer <= d_ptr->m_maxZoom && nearestNeighbourLayer >= 0) { - d_ptr->m_intZoomLevel = nearestNeighbourLayer; - d_ptr->m_sideLength = 1 << d_ptr->m_intZoomLevel; - d_ptr->m_camera.setZoomLevel(d_ptr->m_intZoomLevel); - // Approx heuristic, keeping total # prefetched tiles roughly independent of the - // fractional zoom level. - double neighbourScale = (1.0 + zoomFraction)/2.0; - d_ptr->updateGeometry(PREFETCH_FRUSTUM_SCALE * neighbourScale); - } - break; - } - - case PrefetchTwoNeighbourLayers: { - // This is a simpler strategy, we just prefetch from layer above and below - // for the layer below we only use half the size as this fills the screen - if (currentIntZoom > 0) { - d_ptr->m_intZoomLevel = currentIntZoom - 1; - d_ptr->m_sideLength = 1 << d_ptr->m_intZoomLevel; - d_ptr->m_camera.setZoomLevel(d_ptr->m_intZoomLevel); - d_ptr->updateGeometry(0.5); - } - if (currentIntZoom < d_ptr->m_maxZoom) { - d_ptr->m_intZoomLevel = currentIntZoom + 1; - d_ptr->m_sideLength = 1 << d_ptr->m_intZoomLevel; - d_ptr->m_camera.setZoomLevel(d_ptr->m_intZoomLevel); - d_ptr->updateGeometry(1.0); - } - } - } - - d_ptr->m_intZoomLevel = currentIntZoom; - d_ptr->m_sideLength = 1 << d_ptr->m_intZoomLevel; - d_ptr->m_camera.setZoomLevel(currentFloatZoom); - return d_ptr->m_tiles; -} - void QGeoCameraTiles::setCameraData(const QGeoCameraData &camera) { if (d_ptr->m_camera == camera) @@ -190,6 +137,11 @@ void QGeoCameraTiles::setCameraData(const QGeoCameraData &camera) d_ptr->m_sideLength = 1 << d_ptr->m_intZoomLevel; } +QGeoCameraData QGeoCameraTiles::cameraData() const +{ + return d_ptr->m_camera; +} + void QGeoCameraTiles::setScreenSize(const QSize &size) { if (d_ptr->m_screenSize == size) @@ -235,21 +187,18 @@ void QGeoCameraTiles::setTileSize(int tileSize) d_ptr->m_tileSize = tileSize; } -int QGeoCameraTiles::tileSize() const +void QGeoCameraTiles::setViewExpansion(double viewExpansion) { - return d_ptr->m_tileSize; + d_ptr->m_viewExpansion = viewExpansion; + d_ptr->m_dirtyGeometry = true; } -void QGeoCameraTiles::setMaximumZoomLevel(int maxZoom) +int QGeoCameraTiles::tileSize() const { - if (d_ptr->m_maxZoom == maxZoom) - return; - - d_ptr->m_dirtyGeometry = true; - d_ptr->m_maxZoom = maxZoom; + return d_ptr->m_tileSize; } -const QSet<QGeoTileSpec>& QGeoCameraTiles::visibleTiles() +const QSet<QGeoTileSpec>& QGeoCameraTiles::createTiles() { if (d_ptr->m_dirtyGeometry) { d_ptr->m_tiles.clear(); @@ -268,11 +217,11 @@ const QSet<QGeoTileSpec>& QGeoCameraTiles::visibleTiles() QGeoCameraTilesPrivate::QGeoCameraTilesPrivate() : m_mapVersion(-1), m_tileSize(0), - m_maxZoom(0), m_intZoomLevel(0), m_sideLength(0), m_dirtyGeometry(false), - m_dirtyMetadata(false) + m_dirtyMetadata(false), + m_viewExpansion(1.0) { } @@ -295,11 +244,11 @@ void QGeoCameraTilesPrivate::updateMetadata() m_tiles = newTiles; } -void QGeoCameraTilesPrivate::updateGeometry(double viewExpansion) +void QGeoCameraTilesPrivate::updateGeometry() { // Find the frustum from the camera / screen / viewport information // The larger frustum when stationary is a form of prefetching - Frustum f = createFrustum(viewExpansion); + Frustum f = createFrustum(m_viewExpansion); // Find the polygon where the frustum intersects the plane of the map PolygonVector footprint = frustumFootprint(f); diff --git a/src/location/maps/qgeocameratiles_p.h b/src/location/maps/qgeocameratiles_p.h index e133f8e6..d10895f8 100644 --- a/src/location/maps/qgeocameratiles_p.h +++ b/src/location/maps/qgeocameratiles_p.h @@ -63,21 +63,16 @@ public: QGeoCameraTiles(); ~QGeoCameraTiles(); - enum PrefetchStle { PrefetchNeighbourLayer, PrefetchTwoNeighbourLayers}; - void setCameraData(const QGeoCameraData &camera); + QGeoCameraData cameraData() const; void setScreenSize(const QSize &size); void setTileSize(int tileSize); - void setMaximumZoomLevel(int maxZoom); - int tileSize() const; - + void setViewExpansion(double viewExpansion); void setPluginString(const QString &pluginString); void setMapType(const QGeoMapType &mapType); void setMapVersion(int mapVersion); - - const QSet<QGeoTileSpec>& visibleTiles(); - QSet<QGeoTileSpec> prefetchTiles(PrefetchStle style); + const QSet<QGeoTileSpec>& createTiles(); protected: QScopedPointer<QGeoCameraTilesPrivate> d_ptr; diff --git a/src/location/maps/qgeomapscene.cpp b/src/location/maps/qgeomapscene.cpp index 4a457005..450be60b 100644 --- a/src/location/maps/qgeomapscene.cpp +++ b/src/location/maps/qgeomapscene.cpp @@ -196,6 +196,12 @@ QSet<QGeoTileSpec> QGeoMapScene::texturedTiles() return textured; } +void QGeoMapScene::clearTexturedTiles() +{ + Q_D(QGeoMapScene); + d->m_textures.clear(); +} + QGeoMapScenePrivate::QGeoMapScenePrivate() : QObjectPrivate(), m_tileSize(0), diff --git a/src/location/maps/qgeomapscene_p.h b/src/location/maps/qgeomapscene_p.h index 34d4a11f..c38612bc 100644 --- a/src/location/maps/qgeomapscene_p.h +++ b/src/location/maps/qgeomapscene_p.h @@ -87,6 +87,8 @@ public: bool verticalLock() const; QSet<QGeoTileSpec> texturedTiles(); + void clearTexturedTiles(); + Q_SIGNALS: void newTilesVisible(const QSet<QGeoTileSpec> &newTiles); diff --git a/src/location/maps/qgeotiledmap.cpp b/src/location/maps/qgeotiledmap.cpp index 97747049..7a56c548 100644 --- a/src/location/maps/qgeotiledmap.cpp +++ b/src/location/maps/qgeotiledmap.cpp @@ -47,7 +47,7 @@ #include <cmath> QT_BEGIN_NAMESPACE - +#define PREFETCH_FRUSTUM_SCALE 2.0 QGeoTiledMap::QGeoTiledMap(QGeoTiledMappingManagerEngine *engine, QObject *parent) : QGeoMap(*new QGeoTiledMapPrivate(engine), parent) @@ -85,6 +85,12 @@ void QGeoTiledMap::updateTile(const QGeoTileSpec &spec) d->updateTile(spec); } +void QGeoTiledMap::setPrefetchStyle(QGeoTiledMap::PrefetchStyle style) +{ + Q_D(QGeoTiledMap); + d->m_prefetchStyle = style; +} + QAbstractGeoTileCache *QGeoTiledMap::tileCache() { Q_D(QGeoTiledMap); @@ -107,6 +113,7 @@ void QGeoTiledMap::clearData() { Q_D(QGeoTiledMap); d->m_cache->clearAll(); + d->m_mapScene->clearTexturedTiles(); } void QGeoTiledMap::handleTileVersionChanged() @@ -157,14 +164,20 @@ QDoubleVector2D QGeoTiledMap::coordinateToItemPosition(const QGeoCoordinate &coo QGeoTiledMapPrivate::QGeoTiledMapPrivate(QGeoTiledMappingManagerEngine *engine) : QGeoMapPrivate(engine), m_cache(engine->tileCache()), - m_cameraTiles(new QGeoCameraTiles()), + m_visibleTiles(new QGeoCameraTiles()), + m_prefetchTiles(new QGeoCameraTiles()), m_mapScene(new QGeoMapScene()), - m_tileRequests(0) + m_tileRequests(0), + m_maxZoomLevel(static_cast<int>(std::ceil(engine->cameraCapabilities().maximumZoomLevel()))), + m_prefetchStyle(QGeoTiledMap::PrefetchTwoNeighbourLayers) { - m_cameraTiles->setMaximumZoomLevel(static_cast<int>(std::ceil(engine->cameraCapabilities().maximumZoomLevel()))); - m_cameraTiles->setTileSize(engine->tileSize().width()); - m_cameraTiles->setPluginString(engine->managerName() + QLatin1Char('_') + QString::number(engine->managerVersion())); - m_mapScene->setTileSize(engine->tileSize().width()); + int tileSize = engine->tileSize().width(); + QString pluginString(engine->managerName() + QLatin1Char('_') + QString::number(engine->managerVersion())); + m_visibleTiles->setTileSize(tileSize); + m_prefetchTiles->setTileSize(tileSize); + m_visibleTiles->setPluginString(pluginString); + m_prefetchTiles->setPluginString(pluginString); + m_mapScene->setTileSize(tileSize); } QGeoTiledMapPrivate::~QGeoTiledMapPrivate() @@ -172,17 +185,65 @@ QGeoTiledMapPrivate::~QGeoTiledMapPrivate() // controller_ is a child of map_, don't need to delete it here delete m_mapScene; - delete m_cameraTiles; + delete m_visibleTiles; + delete m_prefetchTiles; // TODO map items are not deallocated! // However: how to ensure this is done in rendering thread? } + void QGeoTiledMapPrivate::prefetchTiles() { - if (m_tileRequests) - m_tileRequests->requestTiles(m_cameraTiles->prefetchTiles(QGeoCameraTiles::PrefetchTwoNeighbourLayers) - - m_mapScene->texturedTiles()); + if (m_tileRequests) { + + QSet<QGeoTileSpec> tiles; + QGeoCameraData camera = m_visibleTiles->cameraData(); + int currentIntZoom = static_cast<int>(std::floor(camera.zoomLevel())); + + m_prefetchTiles->setCameraData(camera); + m_prefetchTiles->setViewExpansion(PREFETCH_FRUSTUM_SCALE); + tiles = m_prefetchTiles->createTiles(); + + switch (m_prefetchStyle) { + + case QGeoTiledMap::PrefetchNeighbourLayer: { + double zoomFraction = camera.zoomLevel() - currentIntZoom; + int nearestNeighbourLayer = zoomFraction > 0.5 ? currentIntZoom + 1 : currentIntZoom - 1; + if (nearestNeighbourLayer <= m_maxZoomLevel && nearestNeighbourLayer >= 0) { + camera.setZoomLevel(nearestNeighbourLayer); + // Approx heuristic, keeping total # prefetched tiles roughly independent of the + // fractional zoom level. + double neighbourScale = (1.0 + zoomFraction)/2.0; + m_prefetchTiles->setCameraData(camera); + m_prefetchTiles->setViewExpansion(PREFETCH_FRUSTUM_SCALE * neighbourScale); + tiles += m_prefetchTiles->createTiles(); + } + } + break; + + case QGeoTiledMap::PrefetchTwoNeighbourLayers: { + // This is a simpler strategy, we just prefetch from layer above and below + // for the layer below we only use half the size as this fills the screen + if (currentIntZoom > 0) { + camera.setZoomLevel(currentIntZoom - 1); + m_prefetchTiles->setCameraData(camera); + m_prefetchTiles->setViewExpansion(0.5); + tiles += m_prefetchTiles->createTiles(); + } + + if (currentIntZoom < m_maxZoomLevel) { + camera.setZoomLevel(currentIntZoom + 1); + m_prefetchTiles->setCameraData(camera); + m_prefetchTiles->setViewExpansion(1.0); + tiles += m_prefetchTiles->createTiles(); + } + + } + } + + m_tileRequests->requestTiles(tiles - m_mapScene->texturedTiles()); + } } void QGeoTiledMapPrivate::changeCameraData(const QGeoCameraData &oldCameraData) @@ -210,7 +271,7 @@ void QGeoTiledMapPrivate::changeCameraData(const QGeoCameraData &oldCameraData) cam.setZoomLevel(izl); } - m_cameraTiles->setCameraData(cam); + m_visibleTiles->setCameraData(cam); m_mapScene->setCameraData(cam); updateScene(); } @@ -219,7 +280,7 @@ void QGeoTiledMapPrivate::updateScene() { Q_Q(QGeoTiledMap); // detect if new tiles introduced - const QSet<QGeoTileSpec>& tiles = m_cameraTiles->visibleTiles(); + const QSet<QGeoTileSpec>& tiles = m_visibleTiles->createTiles(); bool newTilesIntroduced = !m_mapScene->visibleTiles().contains(tiles); m_mapScene->setVisibleTiles(tiles); @@ -228,7 +289,7 @@ void QGeoTiledMapPrivate::updateScene() // don't request tiles that are already built and textured QList<QSharedPointer<QGeoTileTexture> > cachedTiles = - m_tileRequests->requestTiles(m_cameraTiles->visibleTiles() - m_mapScene->texturedTiles()); + m_tileRequests->requestTiles(m_visibleTiles->createTiles() - m_mapScene->texturedTiles()); foreach (const QSharedPointer<QGeoTileTexture> &tex, cachedTiles) { m_mapScene->addTile(tex->spec, tex); @@ -240,29 +301,30 @@ void QGeoTiledMapPrivate::updateScene() void QGeoTiledMapPrivate::changeActiveMapType(const QGeoMapType mapType) { - m_cameraTiles->setMapType(mapType); + m_visibleTiles->setMapType(mapType); + m_prefetchTiles->setMapType(mapType); } void QGeoTiledMapPrivate::changeTileVersion(int version) { - m_cameraTiles->setMapVersion(version); + m_visibleTiles->setMapVersion(version); + m_prefetchTiles->setMapVersion(version); updateScene(); } void QGeoTiledMapPrivate::mapResized(int width, int height) { Q_Q(QGeoTiledMap); - if (m_cameraTiles) - m_cameraTiles->setScreenSize(QSize(width, height)); - if (m_mapScene) - m_mapScene->setScreenSize(QSize(width, height)); + m_visibleTiles->setScreenSize(QSize(width, height)); + m_prefetchTiles->setScreenSize(QSize(width, height)); + m_mapScene->setScreenSize(QSize(width, height)); if (q) q->setCameraData(q->cameraData()); - if (width > 0 && height > 0 && m_cache && m_cameraTiles) { + if (width > 0 && height > 0 && m_cache) { // absolute minimum size: one tile each side of display, 32-bit colour - int texCacheSize = (width + m_cameraTiles->tileSize() * 2) * - (height + m_cameraTiles->tileSize() * 2) * 4; + int texCacheSize = (width + m_visibleTiles->tileSize() * 2) * + (height + m_visibleTiles->tileSize() * 2) * 4; // multiply by 3 so the 'recent' list in the cache is big enough for // an entire display of tiles @@ -272,14 +334,14 @@ void QGeoTiledMapPrivate::mapResized(int width, int height) int newSize = qMax(m_cache->minTextureUsage(), texCacheSize); m_cache->setMinTextureUsage(newSize); } - q->evaluateCopyrights(m_cameraTiles->visibleTiles()); + q->evaluateCopyrights(m_visibleTiles->createTiles()); } void QGeoTiledMapPrivate::updateTile(const QGeoTileSpec &spec) { Q_Q(QGeoTiledMap); // Only promote the texture up to GPU if it is visible - if (m_cameraTiles->visibleTiles().contains(spec)){ + if (m_visibleTiles->createTiles().contains(spec)){ QSharedPointer<QGeoTileTexture> tex = m_tileRequests->tileTexture(spec); if (!tex.isNull()) { m_mapScene->addTile(spec, tex); diff --git a/src/location/maps/qgeotiledmap_p.h b/src/location/maps/qgeotiledmap_p.h index 87dac5d1..9e1d1596 100644 --- a/src/location/maps/qgeotiledmap_p.h +++ b/src/location/maps/qgeotiledmap_p.h @@ -74,14 +74,15 @@ class Q_LOCATION_EXPORT QGeoTiledMap : public QGeoMap { Q_OBJECT Q_DECLARE_PRIVATE(QGeoTiledMap) - public: + enum PrefetchStyle { PrefetchNeighbourLayer, PrefetchTwoNeighbourLayers }; QGeoTiledMap(QGeoTiledMappingManagerEngine *engine, QObject *parent); virtual ~QGeoTiledMap(); QAbstractGeoTileCache *tileCache(); QGeoTileRequestManager *requestManager(); void updateTile(const QGeoTileSpec &spec); + void setPrefetchStyle(PrefetchStyle style); QGeoCoordinate itemPositionToCoordinate(const QDoubleVector2D &pos, bool clipToViewport = true) const Q_DECL_OVERRIDE; QDoubleVector2D coordinateToItemPosition(const QGeoCoordinate &coordinate, bool clipToViewport = true) const Q_DECL_OVERRIDE; diff --git a/src/location/maps/qgeotiledmap_p_p.h b/src/location/maps/qgeotiledmap_p_p.h index 2e93a006..15442bd1 100644 --- a/src/location/maps/qgeotiledmap_p_p.h +++ b/src/location/maps/qgeotiledmap_p_p.h @@ -93,9 +93,12 @@ private: private: QAbstractGeoTileCache *m_cache; - QGeoCameraTiles *m_cameraTiles; + QGeoCameraTiles *m_visibleTiles; + QGeoCameraTiles *m_prefetchTiles; QGeoMapScene *m_mapScene; QGeoTileRequestManager *m_tileRequests; + int m_maxZoomLevel; + QGeoTiledMap::PrefetchStyle m_prefetchStyle; Q_DISABLE_COPY(QGeoTiledMapPrivate) }; |