summaryrefslogtreecommitdiff
path: root/src/location/maps/qgeocameratiles.cpp
diff options
context:
space:
mode:
authorThomas Lowe <thomas.lowe@nokia.com>2012-05-08 15:40:12 +1000
committerQt by Nokia <qt-info@nokia.com>2012-05-16 09:23:55 +0200
commitf9377591312f3c426e8d4bfa45f7554ad7e3e966 (patch)
tree3817480012dd575861dbf1c57d518af75af739e0 /src/location/maps/qgeocameratiles.cpp
parent321e37cb2b04cf075b85399fd97ea77b25f371c1 (diff)
downloadqtlocation-f9377591312f3c426e8d4bfa45f7554ad7e3e966.tar.gz
Simple prefetch scheme
Prefetches larger set of tiles when camera is stopped QTBUG-25136 Prefetch implementation including zoom-level prefetching Two prefetching options- pan buffer, or pan buffer for two nearest zoom levels Code simplified by removing all three visibleTiles lists, so they can't go out of sync Textures not promoted up the cache if they aren't visible when retrieved from server Also: Prefetch on map initialize + optimisation This ensures that the prefetch is called at the end of initialisation Useful if the location is not already in disk cache. And makes no difference if it is already in disk cache. QTBUG-25786 Change-Id: Ife7c1d103f83695659f4534880268fa5afd8f7c7 Reviewed-by: Alex Wilson <alex.wilson@nokia.com>
Diffstat (limited to 'src/location/maps/qgeocameratiles.cpp')
-rw-r--r--src/location/maps/qgeocameratiles.cpp91
1 files changed, 79 insertions, 12 deletions
diff --git a/src/location/maps/qgeocameratiles.cpp b/src/location/maps/qgeocameratiles.cpp
index 9258661b..a63420ed 100644
--- a/src/location/maps/qgeocameratiles.cpp
+++ b/src/location/maps/qgeocameratiles.cpp
@@ -58,6 +58,11 @@
#include <cmath>
QT_BEGIN_NAMESPACE
+#define ENABLE_PREFETCHING
+// larger values fetch a bigger set when the camera stops
+#define PREFETCH_FRUSTUM_SCALE 2.0
+// #define PREFETCH_NEIGHBOUR_LAYER
+#define PREFETCH_TWO_NEIGHBOUR_LAYERS
struct Frustum
{
@@ -91,9 +96,9 @@ public:
int sideLength_;
void updateMetadata();
- void updateGeometry();
+ void updateGeometry(double viewExpansion = 1.0);
- Frustum frustum() const;
+ Frustum frustum(double fieldOfViewGradient) const;
class LengthSorter
{
@@ -132,18 +137,78 @@ QGeoCameraTiles::~QGeoCameraTiles()
delete d_ptr;
}
+void QGeoCameraTiles::findPrefetchTiles()
+{
+#if defined(ENABLE_PREFETCHING)
+ Q_D(QGeoCameraTiles);
+
+ d->tiles_.clear();
+
+ // qDebug() << "prefetch called";
+ int zoom = static_cast<int>(floor(d->camera_.zoomLevel()));
+ d->intZoomLevel_ = zoom;
+ d->sideLength_ = 1 << d->intZoomLevel_;
+ d->updateGeometry(PREFETCH_FRUSTUM_SCALE);
+
+#if defined(PREFETCH_NEIGHBOUR_LAYER)
+ double zoomFraction = d->camera_.zoomLevel() - zoom;
+ int nearestNeighbourLayer = zoomFraction > 0.5 ? zoom + 1 : zoom - 1;
+ if (nearestNeighbourLayer <= d->maxZoom_ && nearestNeighbourLayer >= 0)
+ {
+ double oldZoom = d->camera_.zoomLevel();
+ d->intZoomLevel_ = nearestNeighbourLayer;
+ d->sideLength_ = 1 << d->intZoomLevel_;
+ d->camera_.setZoomLevel(d->intZoomLevel_);
+
+ // Approx heuristic, keeping total # prefetched tiles roughly independent of the
+ // fractional zoom level.
+ double neighbourScale = (1.0 + zoomFraction)/2.0;
+
+ d->updateGeometry(PREFETCH_FRUSTUM_SCALE * neighbourScale);
+ d->camera_.setZoomLevel(oldZoom);
+ }
+#elif defined(PREFETCH_TWO_NEIGHBOUR_LAYERS)
+ // int size1 = d->tiles_.size();
+
+ // 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
+ double oldZoom = d->camera_.zoomLevel();
+ if (zoom > 0)
+ {
+ d->intZoomLevel_ = zoom-1;
+ d->sideLength_ = 1 << d->intZoomLevel_;
+ d->camera_.setZoomLevel(d->intZoomLevel_);
+ d->updateGeometry(0.5);
+ }
+ // int size2 = d->tiles_.size();
+ if (zoom < d->maxZoom_)
+ {
+ d->intZoomLevel_ = zoom+1;
+ d->sideLength_ = 1 << d->intZoomLevel_;
+ d->camera_.setZoomLevel(d->intZoomLevel_);
+ d->updateGeometry(1.0);
+ }
+ // qDebug() << "prefetched main tiles: " << size1 << " higher detail layer: " << d->tiles_.size() - size2 << " low detail layer: " << size2 - size1;
+ d->intZoomLevel_ = zoom;
+ d->sideLength_ = 1 << d->intZoomLevel_;
+ d->camera_.setZoomLevel(oldZoom);
+#endif
+#endif
+}
+
+
void QGeoCameraTiles::setCamera(const QGeoCameraData &camera)
{
Q_D(QGeoCameraTiles);
if (d->camera_ == camera)
return;
-
d->camera_ = camera;
d->intZoomLevel_ = static_cast<int>(floor(d->camera_.zoomLevel()));
d->sideLength_ = 1 << d->intZoomLevel_;
+ d->tiles_.clear();
d->updateGeometry();
}
@@ -155,6 +220,7 @@ void QGeoCameraTiles::setScreenSize(const QSize &size)
return;
d->screenSize_ = size;
+ d->tiles_.clear();
d->updateGeometry();
}
@@ -188,6 +254,7 @@ void QGeoCameraTiles::setTileSize(int tileSize)
return;
d->tileSize_ = tileSize;
+ d->tiles_.clear();
d->updateGeometry();
}
@@ -205,6 +272,7 @@ void QGeoCameraTiles::setMaximumZoomLevel(int maxZoom)
return;
d->maxZoom_ = maxZoom;
+ d->tiles_.clear();
d->updateGeometry();
}
@@ -239,12 +307,11 @@ void QGeoCameraTilesPrivate::updateMetadata()
tiles_ = newTiles;
}
-void QGeoCameraTilesPrivate::updateGeometry()
+void QGeoCameraTilesPrivate::updateGeometry(double viewExpansion)
{
- tiles_.clear();
-
// Find the frustum from the camera / screen / viewport information
- Frustum f = frustum();
+ // The larger frustum when stationary is a form of prefetching
+ Frustum f = frustum(viewExpansion);
// Find the polygon where the frustum intersects the plane of the map
Polygon footprint = frustumFootprint(f);
@@ -263,7 +330,7 @@ void QGeoCameraTilesPrivate::updateGeometry()
}
}
-Frustum QGeoCameraTilesPrivate::frustum() const
+Frustum QGeoCameraTilesPrivate::frustum(double fieldOfViewGradient) const
{
QDoubleVector3D center = sideLength_ * QGeoProjection::coordToMercator(camera_.center());
center.setZ(0.0);
@@ -294,16 +361,16 @@ Frustum QGeoCameraTilesPrivate::frustum() const
// this assumes that viewSize = 2*nearPlane x 2*nearPlane
if (aspectRatio > 1.0) {
- hn = 2 * nearPlane;
+ hn = 2 * fieldOfViewGradient * nearPlane;
wn = hn * aspectRatio;
- hf = 2 * farPlane;
+ hf = 2 * fieldOfViewGradient * farPlane;
wf = hf * aspectRatio;
} else {
- wn = 2 * nearPlane;
+ wn = 2 * fieldOfViewGradient * nearPlane;
hn = wn / aspectRatio;
- wf = 2 * farPlane;
+ wf = 2 * fieldOfViewGradient * farPlane;
hf = wf / aspectRatio;
}