diff options
author | David Laing <david.laing@nokia.com> | 2012-01-17 13:51:40 +1000 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-02-02 04:46:06 +0100 |
commit | d76fceeeddabb1b1a3f00cdc13eb06480c804c7a (patch) | |
tree | 6297f23298feac1a370e71dfdb2fa26ebc4345b5 /src/location/maps/qgeomap.cpp | |
parent | 3d1a04e600e11e8a6c5faab4e9c45e5afe7b3098 (diff) | |
download | qtlocation-d76fceeeddabb1b1a3f00cdc13eb06480c804c7a.tar.gz |
Geometry changes for precision issues.
This also removes / cleans up a few classes that are
made partially redundant by this change.
Change-Id: Ib8118cc3e3df3ecd024a11184ff2523af43d7b03
Task-number: QTBUG-23413
Task-number: QTBUG-23501
Task-number: QTBUG-23166
Reviewed-by: Alex Wilson <alex.wilson@nokia.com>
Diffstat (limited to 'src/location/maps/qgeomap.cpp')
-rw-r--r-- | src/location/maps/qgeomap.cpp | 409 |
1 files changed, 60 insertions, 349 deletions
diff --git a/src/location/maps/qgeomap.cpp b/src/location/maps/qgeomap.cpp index 30d2d79e..44b74cef 100644 --- a/src/location/maps/qgeomap.cpp +++ b/src/location/maps/qgeomap.cpp @@ -42,21 +42,24 @@ #include "qgeomap_p_p.h" #include "qgeotilecache_p.h" -#include "qgeomapsphere_p.h" +#include "qgeotilespec.h" #include "qgeoprojection_p.h" #include "qgeoprojection2d_p.h" -#include "qgeotile_p.h" #include "qgeomapcontroller_p.h" #include "qdoublevector2d_p.h" #include "qdoublevector3d_p.h" #include "qgeocameratiles_p.h" +#include "qgeomapimages_p.h" +#include "qgeomapgeometry_p.h" #include "qgeomappingmanager.h" #include <QMutex> #include <QMap> +#include <qnumeric.h> + #include <qglscenenode.h> #include <qgeometrydata.h> #include <qglbuilder.h> @@ -156,8 +159,6 @@ QGeoCameraData QGeoMap::cameraData() const void QGeoMap::update() { - Q_D(QGeoMap); - d->update(); emit updateRequired(); } @@ -208,14 +209,12 @@ QGeoMapPrivate::QGeoMapPrivate(QGeoMap *parent, QGeoTileCache *cache, int maxZoo cache_(cache), manager_(0), controller_(0), + mapImages_(0), activeMapType_(QGeoMapType()), maxZoom_(maxZoom), tileSize_(tileSize), baseHeight_(100.0) { - sphere_ = new QGeoMapSphere(parent, this, cache); - glCamera_ = new QGLCamera(); - sideLength_ = pow(2.0, 1.0 * maxZoom_) * tileSize; projection_ = QSharedPointer<QGeoProjection>(new QGeoProjection2D(baseHeight_, sideLength_)); @@ -223,17 +222,21 @@ QGeoMapPrivate::QGeoMapPrivate(QGeoMap *parent, QGeoTileCache *cache, int maxZoo cameraTiles_ = new QGeoCameraTiles(projection_); cameraTiles_->setTileSize(tileSize_); cameraTiles_->setMaximumZoomLevel(maxZoom_); + + mapGeometry_ = new QGeoMapGeometry(projection_); + mapGeometry_->setTileSize(tileSize_); } QGeoMapPrivate::~QGeoMapPrivate() { // controller_ is a child of map_, don't need to delete it here + if (mapImages_) + delete mapImages_; + delete mapGeometry_; delete cameraTiles_; manager_->deregisterMap(map_); - delete sphere_; - delete glCamera_; // TODO map items are not deallocated! // However: how to ensure this is done in rendering thread? } @@ -243,25 +246,17 @@ QGeoTileCache* QGeoMapPrivate::tileCache() return cache_; } -QGLSceneNode* QGeoMapPrivate::createTileNode(const QGeoTile &tile) -{ - QGLSceneNode* node = createTileSpecNode(tile.tileSpec()); - - QGLMaterial *mat = new QGLMaterial(node); - mat->setTexture(tile.texture()); - node->setEffect(QGL::LitDecalTexture2D); - node->setMaterial(mat); - - return node; -} - void QGeoMapPrivate::setMappingManager(QGeoMappingManager *manager) { if (manager) { manager->registerMap(map_); pluginString_ = manager->managerName() + QLatin1String("_") + QString::number(manager->managerVersion()); + cameraTiles_->setPluginString(pluginString_); - sphere_->setMappingManager(manager); + + mapImages_ = new QGeoMapImages(map_); + mapImages_->setMappingManager(manager); + } else { manager->deregisterMap(map_); } @@ -277,21 +272,50 @@ QGeoMapController* QGeoMapPrivate::mapController() QGLCamera* QGeoMapPrivate::glCamera() const { - return glCamera_; + return mapGeometry_->camera(); } void QGeoMapPrivate::setCameraData(const QGeoCameraData &cameraData) { + double lat = cameraData_.center().latitude(); + cameraData_ = cameraData; + + if (mapGeometry_->verticalLock()) { + QGeoCoordinate coord = cameraData_.center(); + coord.setLatitude(lat); + cameraData_.setCenter(coord); + } + cameraData_.setAspectRatio(aspectRatio_); cameraData_.setProjection(projection_.toWeakRef()); - updateGlCamera(glCamera_); - updateFrustum(frustum_); cameraTiles_->setCamera(cameraData_); visibleTiles_ = cameraTiles_->tiles(); - sphere_->update(visibleTiles_.toList()); + mapGeometry_->setCameraData(cameraData_); + mapGeometry_->setVisibleTiles(visibleTiles_); + + if (mapImages_) { + mapImages_->setVisibleTiles(visibleTiles_); + + //QSet<QGeoTileSpec> cachedTiles = mapImages_->cachedTiles(); + // TODO make this more efficient + QSet<QGeoTileSpec> cachedTiles = visibleTiles_; + + typedef QSet<QGeoTileSpec>::const_iterator iter; + iter i = cachedTiles.constBegin(); + iter end = cachedTiles.constEnd(); + for (; i != end; ++i) { + QGeoTileSpec tile = *i; + if (cache_->contains(tile)) + mapGeometry_->addTile(tile, cache_->get(tile)); + } + + if (!cachedTiles.isEmpty()) + map_->update(); + + } } QGeoCameraData QGeoMapPrivate::cameraData() const @@ -299,17 +323,13 @@ QGeoCameraData QGeoMapPrivate::cameraData() const return cameraData_; } -void QGeoMapPrivate::update() -{ - sphere_->update(visibleTiles_.toList()); -} - void QGeoMapPrivate::resize(int width, int height) { width_ = width; height_ = height; aspectRatio_ = 1.0 * width_ / height_; cameraTiles_->setScreenSize(QSize(width, height)); + mapGeometry_->setScreenSize(QSize(width, height)); setCameraData(cameraData_); } @@ -334,6 +354,8 @@ void QGeoMapPrivate::setActiveMapType(const QGeoMapType &type) cameraTiles_->setMapType(type); visibleTiles_ = cameraTiles_->tiles(); + setCameraData(cameraData_); + map_->update(); } @@ -344,336 +366,25 @@ const QGeoMapType QGeoMapPrivate::activeMapType() const void QGeoMapPrivate::tileFetched(const QGeoTileSpec &spec) { - sphere_->tileFetched(spec); -} - -QRect QGeoMapPrivate::specToRect(const QGeoTileSpec &tileSpec) const -{ - int geomZoom = tileSpec.zoom(); - int x = tileSpec.x(); - int y = tileSpec.y(); - - int z = 1 << geomZoom; - - bool rightEdge = false; - - double x1 = x * 1.0 / z; - double x2 = ((x + 1) % z) * 1.0 / z; - if (x2 == 0.0) { - x2 = 1.0; - rightEdge = true; - } - double y1 = y * 1.0 / z; - double y2 = (y + 1) * 1.0 / z; - - QDoubleVector3D tl = projection_->mercatorToPoint(QDoubleVector2D(x1, y1)); - QDoubleVector3D tr = projection_->mercatorToPoint(QDoubleVector2D(x2, y1)); - QDoubleVector3D bl = projection_->mercatorToPoint(QDoubleVector2D(x1, y2)); - QDoubleVector3D br = projection_->mercatorToPoint(QDoubleVector2D(x2, y2)); - - if (rightEdge) { - tr.setX(sideLength_); - br.setX(sideLength_); - } - - return QRect(bl.x(), bl.y(), br.x() - tl.x() - 1, tl.y() - br.y() - 1); -} - -QGLSceneNode* QGeoMapPrivate::createTileSpecNode(const QGeoTileSpec &tileSpec) -{ - int geomZoom = tileSpec.zoom(); - int tileZoom = geomZoom; - int x = tileSpec.x(); - int y = tileSpec.y(); - - QGLBuilder builder; - - int z = 1 << geomZoom; - - bool rightEdge = false; - - double x1 = x * 1.0 / z; - double x2 = ((x + 1) % z) * 1.0 / z; - if (x2 == 0.0) { - x2 = 1.0; - rightEdge = true; - } - double y1 = y * 1.0 / z; - double y2 = (y + 1) * 1.0 / z; - - QDoubleVector3D tl = projection_->mercatorToPoint(QDoubleVector2D(x1, y1)); - QDoubleVector3D tr = projection_->mercatorToPoint(QDoubleVector2D(x2, y1)); - QDoubleVector3D bl = projection_->mercatorToPoint(QDoubleVector2D(x1, y2)); - QDoubleVector3D br = projection_->mercatorToPoint(QDoubleVector2D(x2, y2)); - - if (rightEdge) { - tr.setX(sideLength_); - br.setX(sideLength_); - } - - int dz = 1 << (geomZoom - tileZoom); - - int tx1 = x % dz; - int ty1 = y % dz; - - ty1 = dz - ty1; - - int tx2 = (x + 1) % dz; - if (tx2 == 0) - tx2 = dz; - - int ty2 = (y + 1) % dz; - if (ty2 == 0) - ty2 = dz; - - ty2 = dz - ty2; - - QGeometryData g; - - QDoubleVector3D n = QDoubleVector3D(0, 0, 1); - - g.appendVertex(tl); - g.appendNormal(n); - g.appendTexCoord(QDoubleVector2D(tx1 * 1.0 / dz, ty1 * 1.0 / dz)); - - g.appendVertex(bl); - g.appendNormal(n); - g.appendTexCoord(QDoubleVector2D(tx1 * 1.0 / dz, ty2 * 1.0 / dz)); - - g.appendVertex(br); - g.appendNormal(n); - g.appendTexCoord(QDoubleVector2D(tx2 * 1.0 / dz, ty2 * 1.0 / dz)); - - g.appendVertex(tr); - g.appendNormal(n); - g.appendTexCoord(QDoubleVector2D(tx2 * 1.0 / dz, ty1 * 1.0 / dz)); - - builder.addQuads(g); - - return builder.finalizedSceneNode(); + if (cache_->contains(spec)) + mapGeometry_->addTile(spec, cache_->get(spec)); + mapImages_->tileFetched(spec); + map_->update(); } void QGeoMapPrivate::paintGL(QGLPainter *painter) { - double side = pow(2.0, cameraData_.zoomFactor()) * tileSize_; - double mapWidth = width_ * 1.0; - double mapHeight = height_ * 1.0; - double offsetX = 0.0; - double offsetY = 0.0; - - if (side < mapWidth) { - offsetX = (mapWidth - side) / 2.0; - mapWidth = side; - } - - if (side < mapHeight) { - offsetY = (mapHeight - side) / 2.0; - mapHeight = side; - } - - glEnable(GL_SCISSOR_TEST); - - painter->setScissor(QRect(offsetX, offsetY, mapWidth, mapHeight)); - - QGLCamera *camera = glCamera(); - - bool old = camera->blockSignals(true); - - glDisable(GL_DEPTH_TEST); - - QDoubleVector3D c = QDoubleVector3D(camera->center()); - c.setX(c.x() + sideLength_); - camera->setCenter(c); - - QDoubleVector3D e = QDoubleVector3D(camera->eye()); - e.setX(e.x() + sideLength_); - camera->setEye(e); - - painter->setCamera(camera); - painter->projectionMatrix().scale(1, -1, 1); - sphere_->paintGL(painter); - - c.setX(c.x() - 2 * sideLength_); - camera->setCenter(c); - e.setX(e.x() - 2 * sideLength_); - camera->setEye(e); - - painter->setCamera(camera); - painter->projectionMatrix().scale(1, -1, 1); - sphere_->paintGL(painter); - - c.setX(c.x() + sideLength_); - camera->setCenter(c); - e.setX(e.x() + sideLength_); - camera->setEye(e); - - painter->setCamera(camera); - painter->projectionMatrix().scale(1, -1, 1); - sphere_->paintGL(painter); - - glEnable(GL_DEPTH_TEST); - - camera->blockSignals(old); -} - -void QGeoMapPrivate::updateGlCamera(QGLCamera* glCamera) -{ - bool old = glCamera->blockSignals(true); - - QGeoCameraData camera = cameraData(); - - double f = 1.0 * qMin(width(), height()) / tileSize_; - - double altitude = sideLength_ * camera.distance() * f / 2.0; - - QGeoCoordinate coord = camera.center(); - coord.setAltitude(0.0); - QDoubleVector3D center = projection_->coordToPoint(coord); - coord.setAltitude(altitude); - QDoubleVector3D eye = projection_->coordToPoint(coord); - -// if (pow(2.0, cameraData_.zoomFactor()) * tileSize_ < height_) { -// center.setY(sideLength_ / 2.0); -// eye.setY(sideLength_ / 2.0); -// } - - QDoubleVector3D view = eye - center; - QDoubleVector3D side = QDoubleVector3D::normal(view, QDoubleVector3D(0.0, 1.0, 0.0)); - QDoubleVector3D up = QDoubleVector3D::normal(side, view); - -/* - QMatrix4x4 mBearing; - mBearing.rotate(-1.0 * camera.bearing(), view); - up = mBearing * up; - - QDoubleVector3D side2 = QDoubleVector3D::normal(up, view); - QMatrix4x4 mTilt; - mTilt.rotate(camera.tilt(), side2); - eye = (mTilt * view) + center; - - view = eye - center; - side = QDoubleVector3D::normal(view, QDoubleVector3D(0.0, 1.0, 0.0)); - up = QDoubleVector3D::normal(view, side2); - - QMatrix4x4 mRoll; - mRoll.rotate(camera.roll(), view); - up = mRoll * up; -*/ - - double nearPlane = 1.0; - double farPlane = 2.0 * altitude; - - glCamera->setCenter(center); - glCamera->setEye(eye); - glCamera->setUpVector(up); - glCamera->setNearPlane(nearPlane); - glCamera->setFarPlane(farPlane); - - glCamera->blockSignals(old); - - // TODO fold into above code if this works for screen <-> coordinate conversions - viewSize_ = glCamera->viewSize(); - eye_ = eye; - projectionMatrix_ = glCamera->projectionMatrix(aspectRatio()) * glCamera->modelViewMatrix(); + mapGeometry_->paintGL(painter); } QGeoCoordinate QGeoMapPrivate::screenPositionToCoordinate(const QPointF &pos) const { - double side = pow(2.0, cameraData_.zoomFactor()) * tileSize_; - double mapWidth = width_ * 1.0; - double mapHeight = height_ * 1.0; - double offsetX = 0.0; - double offsetY = 0.0; - - if (side < mapWidth) { - offsetX = (mapWidth - side) / 2.0; - mapWidth = side; - } - - if (side < mapHeight) { - offsetY = (mapHeight - side) / 2.0; - mapHeight = side; - } - - double posX = pos.x() - offsetX; - double posY = pos.y() - offsetY; - - if (posX < 0.0) - return QGeoCoordinate(); - if (mapWidth < posX) - return QGeoCoordinate(); - - if (posY < 0.0) - return QGeoCoordinate(); - if (mapHeight < posY) - return QGeoCoordinate(); - - double w = mapWidth / viewSize_.width(); - double h = mapHeight / viewSize_.height(); - double x = (posX - w) / w; - double y = (posY - h) / h; - - x = (x + 1.0) / 2.0; - y = (y + 1.0) / 2.0; - - QDoubleVector3D tl = frustum_.topLeftFar(); - QDoubleVector3D tr = frustum_.topRightFar(); - QDoubleVector3D bl = frustum_.bottomLeftFar(); - - QDoubleVector3D n = (1 - x - y) * tl + x * tr + y * bl; - - if (eye_.z() == n.z()) - return QGeoCoordinate(); - - double alpha = eye_.z() / (eye_.z() - n.z()); - QDoubleVector3D c = (1 - alpha) * eye_ + alpha * n; - - return projection_->pointToCoord(c); + return projection_->mercatorToCoord(mapGeometry_->screenPositionToMercator(pos)); } QPointF QGeoMapPrivate::coordinateToScreenPosition(const QGeoCoordinate &coordinate) const { - QDoubleVector3D c = projection_->coordToPoint(coordinate); - QDoubleVector3D d = QDoubleVector3D(projectionMatrix_.map(c)); - QPointF point = QPointF((d.x() + 1.0) * width() / 2.0, (-d.y() + 1.0) * height() / 2.0); - - double side = pow(2.0, cameraData_.zoomFactor()) * tileSize_; - double mapWidth = width_ * 1.0; - double offsetX = 0.0; - - if (side < mapWidth) { - offsetX = (mapWidth - side) / 2.0; - mapWidth = side; - - if (point.x() < offsetX) - point.setX(point.x() + mapWidth); - - if (offsetX + mapWidth < point.x()) - point.setX(point.x() - mapWidth); - } - - QPointF altPointRight(point.x() + side, point.y()); - QPointF altPointLeft(point.x() - side, point.y()); - - QPointF ret = point; - qreal minDist = qAbs(point.x() - width_ / 2.0); - qreal dist; - - if ((dist = qAbs(altPointRight.x() - width_ / 2.0)) < minDist) { - ret = altPointRight; - minDist = dist; - } - if ((dist = qAbs(altPointLeft.x() - width_ / 2.0)) < minDist) { - ret = altPointLeft; - minDist = dist; - } - - return ret; -} - -void QGeoMapPrivate::updateFrustum(QGeoFrustum &frustum) -{ - frustum.update(glCamera(), cameraData().aspectRatio()); + return mapGeometry_->mercatorToScreenPosition(projection_->coordToMercator(coordinate)); } QT_END_NAMESPACE |