summaryrefslogtreecommitdiff
path: root/src/location/maps/tiled/qgeotiledmapdata.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/location/maps/tiled/qgeotiledmapdata.cpp')
-rw-r--r--src/location/maps/tiled/qgeotiledmapdata.cpp1431
1 files changed, 0 insertions, 1431 deletions
diff --git a/src/location/maps/tiled/qgeotiledmapdata.cpp b/src/location/maps/tiled/qgeotiledmapdata.cpp
deleted file mode 100644
index 207242f1..00000000
--- a/src/location/maps/tiled/qgeotiledmapdata.cpp
+++ /dev/null
@@ -1,1431 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Qt Mobility Components.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qgeotiledmapdata.h"
-#include "qgeotiledmapdata_p.h"
-
-#include "qgeotiledmappingmanagerengine.h"
-#include "qgeotiledmappingmanagerengine_p.h"
-#include "qgeotiledmaprequest.h"
-#include "qgeocoordinate.h"
-#include "qgeoboundingbox.h"
-#include "qgeomapoverlay.h"
-#include <private/projwrapper_p.h>
-#include "qgeomapobjectengine_p.h"
-
-#include "qgeotiledmapobjectinfo_p.h"
-#include "qgeotiledmapcircleobjectinfo_p.h"
-#include "qgeotiledmapgroupobjectinfo_p.h"
-#include "qgeotiledmappixmapobjectinfo_p.h"
-#include "qgeotiledmappolygonobjectinfo_p.h"
-#include "qgeotiledmappolylineobjectinfo_p.h"
-#include "qgeotiledmaprectangleobjectinfo_p.h"
-#include "qgeotiledmaprouteobjectinfo_p.h"
-#include "qgeotiledmaptextobjectinfo_p.h"
-#include "qgeotiledmapcustomobjectinfo_p.h"
-
-#include "qgeomaptextobject.h"
-
-#include <QTimer>
-#include <QImage>
-#include <QGraphicsScene>
-
-#include <QDebug>
-
-//#define DEFAULT_ZOOMLEVEL 8
-#define PI 3.14159265
-//#define HIT_DETECTION_COLOR qRgba(0, 0, 255, 127) //semi-transparent blue
-
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
-
-#include <math.h>
-
-QT_BEGIN_NAMESPACE
-
-uint qHash(const QRectF& key)
-{
- uint result = qHash(qRound(key.x()));
- result += qHash(qRound(key.y()));
- result += qHash(qRound(key.width()));
- result += qHash(qRound(key.height()));
- return result;
-}
-
-
-/*!
- \class QGeoTiledMapData
- \brief The QGeoTiledMapData class is a subclass of QGeoMapData provided
- to make working with tile based mapping services more convenient.
-
- \inmodule QtLocation
-
- \ingroup maps-impl-tiled
-
- \since 1.2
-
- This class assumes that at a zoom level of z the world is represented as a
- 2^z by 2^z grid of tiles, and that the Mercator projection is used to map
- back and forth between coordinate and positions on the map.
-
- Different projections can be provided by reimplementing
- coordinateToWorldReferencePosition() and worldReferencePositionToCoordinate().
-
- Many of the internal calculations deal with positions as though they are
- pixel positions on the map at the maximum zoom level. Several functions are
- provided which expose information about the map and the viewport onto the
- map in these terms for use with custom QGeoMapObjectInfo subclasses.
-
- These functions include worldReferenceViewportCenter(), worldReferenceSize() and
- worldReferenceViewportRect().
-
- NOTE: QGeoTiledMapData blocks property change signals from QGeoMapData by calling
- QGeoMapData::setBlockPropertyChangeSignals() with true. Changing this in
- QGeoTiledMapData subclasses will cause the signals being emitted at wrong time.
-*/
-
-/*!
- Constructs a new tiled map data object, which makes use of the functionality provided by \a engine.
-*/
-QGeoTiledMapData::QGeoTiledMapData(QGeoMappingManagerEngine *engine)
- : QGeoMapData(new QGeoTiledMapDataPrivate(this, engine))
-{
- Q_D(QGeoTiledMapData);
-
- QGeoTiledMappingManagerEngine *tileEngine = static_cast<QGeoTiledMappingManagerEngine *>(d->engine);
-
- setBlockPropertyChangeSignals(true);
-
- setZoomLevel(8.0);
-
- d->worldReferenceSize = (1 << qRound(tileEngine->maximumZoomLevel())) * tileEngine->tileSize();
-
- // TODO get this from the engine, which should give different values depending on if this is running on a device or not
-#if defined(Q_OS_SYMBIAN) || defined(Q_OS_WINCE_WM) || defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6)
- d->cache.setMaxCost(5 * 1024 * 1024);
- d->zoomCache.setMaxCost(5 * 1024 * 1024);
-#else
- d->cache.setMaxCost(10 * 1024 * 1024);
- d->zoomCache.setMaxCost(10 * 1024 * 1024);
-#endif
-}
-
-/*!
- Destroys this tiled map data object.
-*/
-QGeoTiledMapData::~QGeoTiledMapData()
-{
-}
-
-
-QPointF QGeoTiledMapDataPrivate::coordinateToScreenPosition(double lon, double lat) const
-{
- QPointF offset = windowOffset();
-
- QPoint pos(coordinateToWorldReferencePosition(lon, lat));
-
- const int x = pos.x() - worldReferenceViewportRect.left();
-// if (x < 0)
-// x += worldReferenceSize.width();
-
- const int y = pos.y() - worldReferenceViewportRect.top();
-
- QPointF posF(offset.x() + qreal(x) / zoomFactor, offset.y() + qreal(y) / zoomFactor);
-
- return posF;
-}
-
-/*!
- \reimp
-*/
-QPointF QGeoTiledMapData::coordinateToScreenPosition(const QGeoCoordinate &coordwgs) const
-{
- Q_D(const QGeoTiledMapData);
- return d->coordinateToScreenPosition(coordwgs.longitude(), coordwgs.latitude());
-}
-
-/*!
- \reimp
-*/
-QGeoCoordinate QGeoTiledMapData::screenPositionToCoordinate(const QPointF &screenPosition) const
-{
- Q_D(const QGeoTiledMapData);
-
- QPoint worldRef = d->screenPositionToWorldReferencePosition(screenPosition);
-
- if (worldRef.isNull())
- return QGeoCoordinate();
-
- const QGeoCoordinate insph = worldReferencePositionToCoordinate(worldRef);
-
- //ProjCoordinate c(insph.longitude(), insph.latitude(), 0.0, d->spherical);
- //c.convert(d->wgs84);
- return insph;
-}
-
-// this belongs to QGeoTiledMapDataPrivate in order to avoid
-// breaking B.C.
-QPoint QGeoTiledMapDataPrivate::screenPositionToWorldReferencePosition(const QPointF &screenPosition) const
-{
- QPointF offset = windowOffset();
-
- QPointF pos(screenPosition.x() - offset.x(), screenPosition.y() - offset.y());
-
- const int worldX = int(worldReferenceViewportRect.left() + pos.x() * zoomFactor + 0.5) % worldReferenceSize.width();
- const int worldY = int(worldReferenceViewportRect.top() + pos.y() * zoomFactor + 0.5) % worldReferenceSize.height();
-
- return QPoint(worldX, worldY);
-}
-
-QPoint QGeoTiledMapDataPrivate::coordinateToWorldReferencePosition(double lng, double lat) const
-{
- lng = lng / 360.0 + 0.5;
-
- lat = 0.5 - (log(tan((PI / 4.0) + (PI / 2.0) * lat / 180.0)) / PI) / 2.0;
- lat = qMax(0.0, lat);
- lat = qMin(1.0, lat);
-
- const double x = lng * worldReferenceSize.width();
- const double y = lat * worldReferenceSize.height();
-
- const QPoint r(int(x > 0 ? x + 0.5 : x - 0.5),
- int(y > 0 ? y + 0.5 : y - 0.5));
- return r;
-}
-
-/*!
- Converts the coordinate \a coordinate to a pixel position on the entire
- map at the maximum zoom level.
-
- The default implementation is based on the Mercator projection.
-*/
-QPoint QGeoTiledMapData::coordinateToWorldReferencePosition(const QGeoCoordinate &coordinate) const
-{
- Q_D(const QGeoTiledMapData);
- return d->coordinateToWorldReferencePosition(coordinate.longitude(),
- coordinate.latitude());
-}
-
-qreal rmod(const qreal a, const qreal b)
-{
- quint64 div = static_cast<quint64>(a / b);
- return a - static_cast<qreal>(div) * b;
-}
-
-/*!
- Converts the pixel position \a pixel on the map to a coordinate.
-
- The pixel position is relative the entire map at the maximum zoom level.
-
- The default implementation is based on the Mercator projection.
-*/
-QGeoCoordinate QGeoTiledMapData::worldReferencePositionToCoordinate(const QPoint &pixel) const
-{
- Q_D(const QGeoTiledMapData);
-
- qreal fx = qreal(pixel.x()) / d->worldReferenceSize.width();
- qreal fy = qreal(pixel.y()) / d->worldReferenceSize.height();
-
- if (fy < 0.0f)
- fy = 0.0f;
- else if (fy > 1.0f)
- fy = 1.0f;
-
- qreal lat;
-
- if (fy == 0.0f)
- lat = 90.0f;
- else if (fy == 1.0f)
- lat = -90.0f;
- else
- lat = (180.0f / PI) * (2.0f * atan(exp(PI * (1.0f - 2.0f * fy))) - (PI / 2.0f));
-
- qreal lng;
- if (fx >= 0) {
- lng = rmod(fx, 1.0f);
- } else {
- lng = rmod(1.0f - rmod(-1.0f * fx, 1.0f), 1.0f);
- }
-
- lng = lng * 360.0f - 180.0f;
-
- return QGeoCoordinate(lat, lng, 0.0);
-}
-
-/*!
- \reimp
-*/
-void QGeoTiledMapData::setCenter(const QGeoCoordinate &center)
-{
- Q_D(QGeoTiledMapData);
-
- bool changed = (d->center != center);
-
- if (!changed)
- return;
-
- d->worldReferenceViewportCenter = coordinateToWorldReferencePosition(center);
- d->updateScreenRect();
- emit updateMapDisplay();
-
- emit centerChanged(center);
-
- d->updateMapImage();
-
- QGeoMapData::setCenter(center);
- d->oe->invalidatePixelsForViewport();
- d->oe->trimPixelTransforms();
-}
-
-/*!
- \reimp
-*/
-void QGeoTiledMapData::setMapType(QGraphicsGeoMap::MapType mapType)
-{
- Q_D(QGeoTiledMapData);
-
- bool changed = (d->mapType != mapType);
-
- if (!changed)
- return;
-
- QGeoMapData::setMapType(mapType);
-
- d->clearRequests();
- d->cache.clear();
- d->zoomCache.clear();
- emit updateMapDisplay();
-
- emit mapTypeChanged(d->mapType);
-
- d->updateMapImage();
-}
-
-/*!
- \reimp
-*/
-void QGeoTiledMapData::setConnectivityMode(QGraphicsGeoMap::ConnectivityMode connectivityMode)
-{
- QGraphicsGeoMap::ConnectivityMode oldMode = QGeoMapData::connectivityMode();
-
- if (oldMode == connectivityMode)
- return;
-
- QGeoMapData::setConnectivityMode(connectivityMode);
-
- if (oldMode == QGeoMapData::connectivityMode())
- return;
-
- emit connectivityModeChanged(connectivityMode);
-}
-
-/*!
- \reimp
-*/
-QGeoCoordinate QGeoTiledMapData::center() const
-{
- Q_D(const QGeoTiledMapData);
- return worldReferencePositionToCoordinate(d->worldReferenceViewportCenter);
-}
-
-/*!
- \reimp
-*/
-void QGeoTiledMapData::setZoomLevel(qreal zoomLevelf)
-{
- Q_D(QGeoTiledMapData);
-
- QPixmap oldImage(windowSize().toSize());
- if (!oldImage.isNull()) {
- // grab the old image
- QPainter painter1(&oldImage);
- d->paintMap(&painter1, 0);
- painter1.end();
- }
-
- qreal oldZoomLevel = d->zoomLevel;
- int zoomLevel = qRound(zoomLevelf);
-
- QGeoMapData::setZoomLevel(zoomLevel);
-
- d->oe->invalidateZoomDependents();
- d->oe->invalidatePixelsForViewport();
- d->oe->trimPixelTransforms();
-
- // QGeoMapData::setZoomLevel clips the zoom level to be
- // in between the minimum and maximum zoom levels
- zoomLevel = QGeoMapData::zoomLevel();
-
- int zoomDiff = qRound(zoomLevel - oldZoomLevel);
-
- if (zoomDiff == 0)
- return;
-
- d->zoomFactor = 1 << qRound(d->engine->maximumZoomLevel() - d->zoomLevel);
-
- QGeoTiledMappingManagerEngine *tileEngine = static_cast<QGeoTiledMappingManagerEngine *>(d->engine);
- QSize tileSize = tileEngine->tileSize();
-
- d->updateScreenRect();
-
- if (oldImage.isNull()) {
- d->updateMapImage();
- emit zoomLevelChanged(d->zoomLevel);
- return;
- }
-
- //scale old image
- QRectF target = oldImage.rect();
- qreal width = target.width() / (1 << qAbs(zoomDiff));
- qreal height = target.height() / (1 << qAbs(zoomDiff));
- qreal x = target.x() + ((target.width() - width) / 2.0);
- qreal y = target.y() + ((target.height() - height) / 2.0);
- QRectF source = QRectF(x, y, width, height);
-
- QPixmap newImage(oldImage.size());
- newImage.fill(Qt::lightGray);
- QPainter painter2(&newImage);
-#if !(defined(Q_OS_SYMBIAN) || defined(Q_OS_WINCE_WM) || defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6))
- painter2.setRenderHint(QPainter::SmoothPixmapTransform, true);
-#endif
- if (zoomDiff < 0) {
- painter2.drawPixmap(source, oldImage, target);
- } else {
- painter2.drawPixmap(target, oldImage, source);
- }
- painter2.end();
-
- d->zoomCache.clear();
-
- QGeoTileIterator it(d);
-
- QPointF offset = d->windowOffset();
-
- while (it.hasNext()) {
- QGeoTiledMapRequest req = it.next();
- QRect tileRect = req.tileRect();
-
- if (d->cache.contains(req))
- continue;
-
- if (!d->intersectsScreen(tileRect))
- continue;
-
- QList<QPair<QRect, QRect> > overlaps = d->intersectedScreen(tileRect);
- for (int i = 0; i < overlaps.size(); ++i) {
- QRect s = overlaps.at(i).first;
- QRect t = overlaps.at(i).second;
-
- QRectF source = QRectF(offset.x() + int(t.left()) / d->zoomFactor,
- offset.y() + int(t.top()) / d->zoomFactor,
- int(t.width()) / d->zoomFactor,
- int(t.height()) / d->zoomFactor);
-
- QPixmap *tile = new QPixmap(tileSize);
- tile->fill(Qt::lightGray); // TODO: this looks useless
-
- QRectF target = QRectF(int(s.left()) / d->zoomFactor,
- int(s.top()) / d->zoomFactor,
- int(s.width()) / d->zoomFactor,
- int(s.height()) / d->zoomFactor);
-
- QPainter painter3(tile);
- painter3.drawPixmap(target, newImage, source);
- painter3.end();
-
- d->zoomCache.insert(req, tile, (tile->depth() * tile->width() * tile->height()) / 8);
- }
- }
-
- emit updateMapDisplay();
-
- d->clearRequests();
- d->updateMapImage();
-
- emit zoomLevelChanged(d->zoomLevel);
-
- // call again
- QGeoMapData::setZoomLevel(zoomLevel);
-}
-
-/*!
- \reimp
-*/
-void QGeoTiledMapData::setWindowSize(const QSizeF &size)
-{
- Q_D(QGeoTiledMapData);
-
- bool changed = (d->windowSize != size);
-
- if (!changed)
- return;
-
- QGeoMapData::setWindowSize(size);
-
- d->oe->invalidatePixelsForViewport();
- d->oe->trimPixelTransforms();
-
- d->updateScreenRect();
-
- emit windowSizeChanged(d->windowSize);
-
- d->updateMapImage();
-}
-
-/*!
- \reimp
-*/
-void QGeoTiledMapData::pan(int dx, int dy)
-{
- Q_D(QGeoTiledMapData);
-
- int x = d->worldReferenceViewportCenter.x();
- int y = d->worldReferenceViewportCenter.y();
-
- x = (x + dx * d->zoomFactor) % d->worldReferenceSize.width();
- if (x < 0)
- x += d->worldReferenceSize.width();
-
- y = (y + dy * d->zoomFactor);
- int height = int(d->worldReferenceViewportRect.height() / 2.0);
- if (y < height)
- y = height;
- if (y > d->worldReferenceSize.height() - height)
- y = d->worldReferenceSize.height() - height;
-
- d->worldReferenceViewportCenter.setX(x);
- d->worldReferenceViewportCenter.setY(y);
-
- QGeoCoordinate centerCoord = center();
-
- QGeoMapData::setCenter(centerCoord);
- d->oe->invalidatePixelsForViewport();
- d->oe->trimPixelTransforms();
-
- d->updateScreenRect();
-
- emit centerChanged(centerCoord);
-
- d->updateMapImage();
-}
-
-/*!
- \reimp
-*/
-QGeoBoundingBox QGeoTiledMapData::viewport() const
-{
- Q_D(const QGeoTiledMapData);
- if (d->worldReferenceViewportRectRight.isValid()) {
- return QGeoBoundingBox(worldReferencePositionToCoordinate(d->worldReferenceViewportRectLeft.topLeft()),
- worldReferencePositionToCoordinate(d->worldReferenceViewportRectRight.bottomRight()));
- } else {
- return QGeoBoundingBox(worldReferencePositionToCoordinate(d->worldReferenceViewportRect.topLeft()),
- worldReferencePositionToCoordinate(d->worldReferenceViewportRect.bottomRight()));
- }
-}
-
-/*!
- \reimp
-*/
-void QGeoTiledMapData::fitInViewport(const QGeoBoundingBox &bounds, bool preserveViewportCenter)
-{
- Q_D(QGeoTiledMapData);
-
- if (!preserveViewportCenter)
- setCenter(bounds.center());
-
- int minZoomLevel = engine()->minimumZoomLevel();
- int maxZoomLevel = engine()->maximumZoomLevel();
-
- int zoomFactor = 1 << maxZoomLevel;
-
- for (int i = minZoomLevel; i <= maxZoomLevel; ++i) {
- QRect rect = d->screenRectForZoomFactor(zoomFactor);
- QGeoBoundingBox viewport = QGeoBoundingBox(worldReferencePositionToCoordinate(rect.topLeft()),
- worldReferencePositionToCoordinate(rect.bottomRight()));
-
-// qWarning() << i << zoomFactor
-// << viewport.topLeft()
-// << viewport.bottomRight();
-
- if (!viewport.contains(bounds)) {
- setZoomLevel(qMax(minZoomLevel, i - 1));
- return;
- }
-
- zoomFactor /= 2;
- }
-
- setZoomLevel(maxZoomLevel);
-}
-
-/*!
- \reimp
-*/
-void QGeoTiledMapData::paintMap(QPainter *painter, const QStyleOptionGraphicsItem *option)
-{
- Q_D(QGeoTiledMapData);
- d->paintMap(painter, option);
-}
-
-/*!
- \reimp
-*/
-void QGeoTiledMapData::paintObjects(QPainter *painter, const QStyleOptionGraphicsItem *option)
-{
- Q_D(QGeoTiledMapData);
- d->paintObjects(painter, option);
-}
-
-/*!
- \reimp
-*/
-QGeoMapObjectInfo *QGeoTiledMapData::createMapObjectInfo(QGeoMapObject *mapObject)
-{
- switch (mapObject->type()) {
- case QGeoMapObject::GroupType:
- return new QGeoTiledMapGroupObjectInfo(this, mapObject);
- case QGeoMapObject::RectangleType:
- return new QGeoTiledMapRectangleObjectInfo(this, mapObject);
- case QGeoMapObject::CircleType:
- return new QGeoTiledMapCircleObjectInfo(this, mapObject);
- case QGeoMapObject::PolylineType:
- return new QGeoTiledMapPolylineObjectInfo(this, mapObject);
- case QGeoMapObject::PolygonType:
- return new QGeoTiledMapPolygonObjectInfo(this, mapObject);
- case QGeoMapObject::PixmapType:
- return new QGeoTiledMapPixmapObjectInfo(this, mapObject);
- case QGeoMapObject::TextType:
- return new QGeoTiledMapTextObjectInfo(this, mapObject);
- case QGeoMapObject::RouteType:
- return new QGeoTiledMapRouteObjectInfo(this, mapObject);
- case QGeoMapObject::CustomType:
- return new QGeoTiledMapCustomObjectInfo(this, mapObject);
- default:
- return 0;
- }
-}
-
-void QGeoTiledMapData::processRequests()
-{
- Q_D(QGeoTiledMapData);
-
- QMutableSetIterator<QGeoTiledMapReply*> replyIter(d->replies);
- // Abort off-screen replies
- while (replyIter.hasNext()) {
- QGeoTiledMapReply *reply = replyIter.next();
- if (!d->intersectsScreen(reply->request().tileRect())
- || (zoomLevel() != reply->request().zoomLevel())
- || (mapType() != reply->request().mapType())
- || (connectivityMode() != reply->request().connectivityMode())) {
- d->replyRects.remove(reply->request().tileRect());
- d->zoomCache.remove(reply->request());
- replyIter.remove();
- reply->abort();
- }
- }
-
- QGeoTiledMappingManagerEngine *tiledEngine
- = static_cast<QGeoTiledMappingManagerEngine*>(engine());
-
- QMutableListIterator<QGeoTiledMapRequest> requestIter(d->requests);
- while (requestIter.hasNext()) {
- QGeoTiledMapRequest req = requestIter.next();
-
- d->requestRects.remove(req.tileRect());
- requestIter.remove();
-
- // Do not use the requests which have pending replies or are off screen
- if (d->replyRects.contains(req.tileRect()) || !d->intersectsScreen(req.tileRect())) {
- continue;
- }
-
- QGeoTiledMapReply *reply = tiledEngine->getTileImage(req);
-
- if (!reply) {
- continue;
- }
-
- if (reply->error() != QGeoTiledMapReply::NoError) {
- tileError(reply->error(), reply->errorString());
- reply->deleteLater();
- d->zoomCache.remove(reply->request());
- continue;
- }
-
- connect(reply,
- SIGNAL(finished()),
- this,
- SLOT(tileFinished()));
-
- connect(reply,
- SIGNAL(error(QGeoTiledMapReply::Error, QString)),
- this,
- SLOT(tileError(QGeoTiledMapReply::Error, QString)));
-
- d->replies.insert(reply);
- d->replyRects.insert(reply->request().tileRect());
-
- if (reply->isFinished())
- replyFinished(reply);
- }
-}
-
-void QGeoTiledMapData::tileFinished()
-{
- Q_D(QGeoTiledMapData);
-
- QGeoTiledMapReply *reply = qobject_cast<QGeoTiledMapReply*>(sender());
-
- if (!reply) {
- if (d->requests.size() > 0)
- QTimer::singleShot(0, this, SLOT(processRequests()));
- return;
- } else {
- replyFinished(reply);
- }
-}
-
-void QGeoTiledMapData::replyFinished(QGeoTiledMapReply *reply)
-{
- Q_D(QGeoTiledMapData);
-
- d->replyRects.remove(reply->request().tileRect());
- d->replies.remove(reply);
- d->zoomCache.remove(reply->request());
-
- if (reply->error() != QGeoTiledMapReply::NoError) {
- if (d->requests.size() > 0)
- QTimer::singleShot(0, this, SLOT(processRequests()));
- reply->deleteLater();
- return;
- }
-
- if ((zoomLevel() != reply->request().zoomLevel())
- || (mapType() != reply->request().mapType())
- || (connectivityMode() != reply->request().connectivityMode())) {
- if (d->requests.size() > 0)
- QTimer::singleShot(0, this, SLOT(processRequests()));
- reply->deleteLater();
- return;
- }
-
- //QPixmap *tile = new QPixmap();
- QImage *tile = new QImage();
-
- if (!tile->loadFromData(reply->mapImageData(), reply->mapImageFormat().toAscii())) {
- delete tile;
- if (d->requests.size() > 0)
- QTimer::singleShot(0, this, SLOT(processRequests()));
- reply->deleteLater();
- return;
- //setError(QGeoTiledMapReply::ParseError, "The response from the service was not in a recognisable format.");
- }
-
- if (tile->isNull() || tile->size().isEmpty()) {
- delete tile;
- if (d->requests.size() > 0)
- QTimer::singleShot(0, this, SLOT(processRequests()));
- reply->deleteLater();
- return;
- //setError(QGeoTiledMapReply::ParseError, "The map image is empty.");
- }
-
- d->cache.insert(reply->request(), tile, (tile->depth() * tile->width() * tile->height()) / 8);
-
- d->cleanupCaches();
-
- QRect tileRect = reply->request().tileRect();
-
- QPointF offset = d->windowOffset();
-
- QList<QPair<QRect, QRect> > overlaps = d->intersectedScreen(tileRect);
- for (int i = 0; i < overlaps.size(); ++i) {
- QRect t = overlaps.at(i).second;
- QRectF target = QRectF(offset.x() + int(t.left()) / d->zoomFactor,
- offset.y() + int(t.top()) / d->zoomFactor,
- int(t.width()) / d->zoomFactor,
- int(t.height()) / d->zoomFactor);
-
- emit updateMapDisplay(target);
- }
-
- if (d->requests.size() > 0)
- QTimer::singleShot(0, this, SLOT(processRequests()));
-
- reply->deleteLater();
-}
-
-void QGeoTiledMapData::tileError(QGeoTiledMapReply::Error error, QString errorString)
-{
- Q_UNUSED(error)
- qWarning() << errorString;
-}
-
-/*!
- \reimp
-*/
-QList<QGeoMapObject*> QGeoTiledMapData::mapObjectsAtScreenPosition(const QPointF &screenPosition) const
-{
- return mapObjectsInScreenRect(QRectF(screenPosition - QPointF(1,1),
- screenPosition + QPointF(1,1)));
-// if (screenPosition.isNull())
-// return QList<QGeoMapObject*>();
-
-// Q_D(const QGeoTiledMapData);
-
-// QList<QGeoMapObject*> results;
-// QSet<QGeoMapObject*> considered;
-
-// d->oe->updateTransforms();
-
-// QList<QGraphicsItem*> pixelItems;
-// pixelItems = d->oe->pixelScene->items(QRectF(screenPosition - QPointF(1,1),
-// screenPosition + QPointF(1,1)),
-// Qt::IntersectsItemShape,
-// Qt::AscendingOrder);
-
-// foreach (QGraphicsItem *item, pixelItems) {
-// QGeoMapObject *object = d->oe->pixelItems.value(item);
-// Q_ASSERT(object);
-
-// if (object->isVisible() && !considered.contains(object)) {
-// bool contains = false;
-
-// if (d->oe->pixelExact.contains(object)) {
-// foreach (QGraphicsItem *item, d->oe->pixelExact.values(object)) {
-// if (item->shape().contains(screenPosition)) {
-// contains = true;
-// break;
-// }
-// }
-// } else {
-// QGraphicsItem *item
-// = d->oe->graphicsItemFromMapObject(object);
-
-// if (item) {
-// QList<QTransform> trans = d->oe->pixelTrans.values(object);
-
-// foreach (QTransform t, trans) {
-// bool ok;
-// QTransform inv = t.inverted(&ok);
-// if (ok) {
-// QPointF testPt = screenPosition * inv;
-
-// // we have to special case text objects here
-// // in order to maintain their old (1.1) behaviour
-// QGeoMapTextObject *tobj = qobject_cast<QGeoMapTextObject*>(object);
-// if (tobj) {
-// if (item->boundingRect().contains(testPt)) {
-// contains = true;
-// break;
-// }
-// } else {
-// if (item->shape().contains(testPt)) {
-// contains = true;
-// break;
-// }
-// }
-// }
-// }
-// }
-// }
-
-// if (contains)
-// results << object;
-
-// considered.insert(object);
-// }
-// }
-
-// return results;
-}
-
-/*!
- \reimp
-*/
-QList<QGeoMapObject*> QGeoTiledMapData::mapObjectsInScreenRect(const QRectF &screenRect) const
-{
- QList<QGeoMapObject*> results;
- QSet<QGeoMapObject*> considered;
-
- Q_D(const QGeoTiledMapData);
-
- d->oe->updateTransforms();
-
- QList<QGraphicsItem*> pixelItems = d->oe->pixelScene->items(screenRect,
- Qt::IntersectsItemShape,
- Qt::AscendingOrder);
-
- foreach (QGraphicsItem *item, pixelItems) {
- QGeoMapObject *object = d->oe->pixelItems.value(item);
- Q_ASSERT(object);
-
- if (object->isVisible() && !considered.contains(object)) {
- bool contains = false;
-
- if (d->oe->pixelExact.contains(object)) {
- foreach (QGraphicsItem *item, d->oe->pixelExact.values(object))
- if (item->shape().intersects(screenRect))
- contains = true;
- } else {
- QGraphicsItem *item
- = d->oe->graphicsItemFromMapObject(object);
-
- if (item) {
- QList<QTransform> trans = d->oe->pixelTrans.values(object);
-
- foreach (QTransform t, trans) {
- bool ok;
- QTransform inv = t.inverted(&ok);
- if (ok) {
- QPolygonF testPoly = screenRect * inv;
-
- QPainterPath testPath;
- testPath.moveTo(testPoly[0]);
- testPath.lineTo(testPoly[1]);
- testPath.lineTo(testPoly[2]);
- testPath.lineTo(testPoly[3]);
- testPath.closeSubpath();
-
- if (item->shape().intersects(testPath))
- contains = true;
- }
- }
- }
- }
-
- if (contains)
- results << object;
-
- considered.insert(object);
- }
- }
-
- return results;
-}
-
-/*!
- Returns the center of the viewport, in pixels on the entire
- map as a pixmap at the maximum zoom level.
-*/
-QPoint QGeoTiledMapData::worldReferenceViewportCenter() const
-{
- Q_D(const QGeoTiledMapData);
- return d->worldReferenceViewportCenter;
-}
-
-/*!
- Returns the size, in pixels, of the entire map as a pixmap at the maximum
- zoom level.
-*/
-QSize QGeoTiledMapData::worldReferenceSize() const
-{
- Q_D(const QGeoTiledMapData);
- return d->worldReferenceSize;
-}
-
-/*!
- Returns the visible screen rectangle, in pixels on the entire map
- as a pixmap at the maximum zoom level.
-*/
-QRect QGeoTiledMapData::worldReferenceViewportRect() const
-{
- Q_D(const QGeoTiledMapData);
- return d->worldReferenceViewportRect;
-}
-
-/*!
- Returns the ratio between a single pixel on the screen and a pixel on
- the entire map as a pixmap at the maximum zoom level.
-*/
-int QGeoTiledMapData::zoomFactor() const
-{
- Q_D(const QGeoTiledMapData);
- return d->zoomFactor;
-}
-
-/*!
- Forces the map display to update in the region specified by \a target.
-
- If \a target is empty the entire map display will be updated.
-*/
-void QGeoTiledMapData::triggerUpdateMapDisplay(const QRectF &target)
-{
- emit updateMapDisplay(target);
-}
-
-/*******************************************************************************
-*******************************************************************************/
-
-QGeoTiledMapDataPrivate::QGeoTiledMapDataPrivate(QGeoTiledMapData *parent, QGeoMappingManagerEngine *engine)
- : QGeoMapDataPrivate(parent, engine),
- oe(new QGeoMapObjectEngine(parent, this)),
- zoomFactor(0),
- spherical(QLatin1String("+proj=latlon +ellps=sphere")),
- wgs84(QLatin1String("+proj=latlon +ellps=WGS84")) {}
-
-QGeoTiledMapDataPrivate::~QGeoTiledMapDataPrivate()
-{
- foreach(QGeoTiledMapReply * reply, replies) {
- reply->abort();
- reply->deleteLater();
- }
-
- if (oe)
- delete oe;
-}
-
-QPointF QGeoTiledMapDataPrivate::windowOffset() const
-{
- qreal offsetX = ((windowSize.width() * zoomFactor) - worldReferenceViewportRect.width()) / 2.0;
- if (offsetX < 0.0)
- offsetX = 0.0;
- offsetX /= zoomFactor;
-
- qreal offsetY = ((windowSize.height() * zoomFactor) - worldReferenceViewportRect.height()) / 2.0;
- if (offsetY < 0.0)
- offsetY = 0.0;
- offsetY /= zoomFactor;
-
- return QPointF(offsetX, offsetY);
-}
-
-void QGeoTiledMapDataPrivate::updateMapImage()
-{
- Q_Q(QGeoTiledMapData);
-
- if ((zoomLevel == -1.0) || !windowSize.isValid())
- return;
-
- bool wasEmpty = (requests.size() == 0);
- QGeoTileIterator it(this);
-
- while (it.hasNext()) {
- QGeoTiledMapRequest req = it.next();
- QRect tileRect = req.tileRect();
-
- if (!cache.contains(req)) {
- if (!requestRects.contains(tileRect) && !replyRects.contains(tileRect)) {
- requests.append(req);
- requestRects.insert(tileRect);
- }
- }
- }
-
-// qWarning()
-// << d->requests.size()
-// << d->cache.size()
-// << d->cache.totalCost()
-// << d->zoomCache.size()
-// << d->zoomCache.totalCost();
-
- if (wasEmpty && requests.size() > 0) {
- QTimer::singleShot(0, q, SLOT(processRequests()));
- }
-}
-
-void QGeoTiledMapDataPrivate::clearRequests()
-{
- requests.clear();
- requestRects.clear();
-}
-
-void QGeoTiledMapDataPrivate::paintMap(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/)
-{
- QPointF offset = windowOffset();
-
- QGeoTileIterator it(this);
-
- while (it.hasNext()) {
- QGeoTiledMapRequest req = it.next();
- QRect tileRect = req.tileRect();
-
- QList<QPair<QRect, QRect> > overlaps = intersectedScreen(tileRect);
- for (int i = 0; i < overlaps.size(); ++i) {
- QRect s = overlaps.at(i).first;
- QRect t = overlaps.at(i).second;
-
- QRectF source = QRectF(int(s.left()) / zoomFactor,
- int(s.top()) / zoomFactor,
- int(s.width()) / zoomFactor,
- int(s.height()) / zoomFactor);
- QRectF target = QRectF(offset.x() + int(t.left()) / zoomFactor,
- offset.y() + int(t.top()) / zoomFactor,
- int(t.width()) / zoomFactor,
- int(t.height()) / zoomFactor);
-
- if (cache.contains(req)) {
- //painter->drawPixmap(target, *cache.object(req), source);
- painter->drawImage(target, *cache.object(req), source);
- } else {
- if (zoomCache.contains(req)) {
- painter->drawPixmap(target, *zoomCache.object(req), source);
- } else {
- painter->fillRect(target, Qt::lightGray);
- }
- }
- }
- }
-}
-
-void QGeoTiledMapDataPrivate::paintObjects(QPainter *painter, const QStyleOptionGraphicsItem * option)
-{
- painter->save();
- painter->setRenderHint(QPainter::Antialiasing);
-
- QRectF target = option ? option->rect : QRectF(QPointF(0,0), windowSize);
-
- QPointF offset = windowOffset();
-
- target.adjust(offset.x(), offset.y(), -1.0 * offset.x(), -1.0 * offset.y());
-
- painter->setClipRect(target);
-
- oe->updateTransforms();
-
- QList<QGraphicsItem*> items = oe->pixelScene->items(target,
- Qt::IntersectsItemShape,
- Qt::AscendingOrder);
- QSet<QGeoMapObject*> objsDone;
-
- QTransform baseTrans = painter->transform();
-
- QStyleOptionGraphicsItem *style = new QStyleOptionGraphicsItem;
-
- foreach (QGraphicsItem *item, items) {
- QGeoMapObject *object = oe->pixelItems.value(item);
- Q_ASSERT(object);
- if (object->isVisible() && !objsDone.contains(object)) {
- if (oe->pixelExact.contains(object)) {
- foreach (QGraphicsItem *it, oe->pixelExact.values(object)) {
- painter->setTransform(baseTrans);
-
-// QStyleOptionGraphicsItem *style = new QStyleOptionGraphicsItem;
- it->paint(painter, style);
-// delete style;
- }
- } else {
- QGraphicsItem *item = oe->graphicsItemFromMapObject(object);
- if (item) {
- foreach (QTransform trans, oe->pixelTrans.values(object)) {
- painter->setTransform(trans * baseTrans);
-
-// QStyleOptionGraphicsItem *style = new QStyleOptionGraphicsItem;
- item->paint(painter, style);
- foreach (QGraphicsItem *child, item->children()) {
- painter->setTransform(child->transform() * trans * baseTrans);
- painter->translate(child->pos());
- child->paint(painter, style);
- }
-
-// delete style;
- }
- }
- }
- objsDone.insert(object);
- }
- }
-
- painter->restore();
-
- delete style;
-}
-
-void QGeoTiledMapDataPrivate::cleanupCaches()
-{
- int boundaryTiles = 3;
-
- QGeoTiledMappingManagerEngine *tiledEngine = static_cast<QGeoTiledMappingManagerEngine*>(engine);
-
- QSize tileSize = tiledEngine->tileSize();
-
- QRectF cacheRect1;
- QRectF cacheRect2;
-
- cacheRect1 = worldReferenceViewportRect.adjusted(-boundaryTiles * tileSize.width(),
- -boundaryTiles * tileSize.height(),
- boundaryTiles * tileSize.width(),
- boundaryTiles * tileSize.height());
-
- if (cacheRect1.width() > worldReferenceSize.width()) {
- cacheRect1.setX(0);
- cacheRect1.setWidth(worldReferenceSize.width());
- } else {
- if (cacheRect1.x() + cacheRect1.width() > worldReferenceSize.width()) {
- int oldWidth = cacheRect1.width();
- cacheRect1.setWidth(worldReferenceSize.width() - cacheRect1.x());
- cacheRect2 = QRectF(0,
- cacheRect1.y(),
- oldWidth - cacheRect1.width(),
- cacheRect1.height());
- }
- }
-
- QList<QGeoTiledMapRequest> keys = cache.keys();
- for (int i = 0; i < keys.size(); ++i) {
- QRectF tileRect = keys.at(i).tileRect();
- if (!cacheRect1.intersects(tileRect)) {
- if (cacheRect2.isNull() || !cacheRect2.intersects(tileRect)) {
- cache.remove(keys.at(i));
- }
- }
- }
-}
-
-QRect QGeoTiledMapDataPrivate::screenRectForZoomFactor(int factor)
-{
- qreal viewportWidth = q_ptr->windowSize().width();
- qreal viewportHeight = q_ptr->windowSize().height();
-
- int width = int(viewportWidth * factor);
- int height = int(viewportHeight * factor);
-
- if (width > worldReferenceSize.width())
- width = worldReferenceSize.width();
-
- if (height > worldReferenceSize.height())
- height = worldReferenceSize.height();
-
- int x = (worldReferenceViewportCenter.x() - (width / 2)) % worldReferenceSize.width();
- if (x < 0)
- x += worldReferenceSize.width();
-
- int y = worldReferenceViewportCenter.y() - (height / 2);
-
- if (y < 0)
- y = 0;
-
- if ((y + height) >= worldReferenceSize.height())
- y = worldReferenceSize.height() - height;
-
- return QRect(x, y, width, height);
-}
-
-void QGeoTiledMapDataPrivate::updateScreenRect()
-{
- worldReferenceViewportRect = screenRectForZoomFactor(zoomFactor);
-
- int x = worldReferenceViewportRect.x();
- int y = worldReferenceViewportRect.y();
- int width = worldReferenceViewportRect.width();
- int height = worldReferenceViewportRect.height();
-
- if (x + width < worldReferenceSize.width()) {
- worldReferenceViewportRectLeft = worldReferenceViewportRect;
- worldReferenceViewportRectRight = QRect();
- } else {
- int widthLeft = worldReferenceSize.width() - x;
- int widthRight = width - widthLeft;
- worldReferenceViewportRectLeft = QRect(x, y, widthLeft, height);
- worldReferenceViewportRectRight = QRect(0, y, widthRight, height);
- }
-}
-
-bool QGeoTiledMapDataPrivate::containedInScreen(const QPoint &point) const
-{
- return (worldReferenceViewportRectLeft.contains(point)
- || (worldReferenceViewportRectRight.isValid()
- && worldReferenceViewportRectRight.contains(point)));
-}
-
-bool QGeoTiledMapDataPrivate::intersectsScreen(const QRect &rect) const
-{
- return (worldReferenceViewportRectLeft.intersects(rect)
- || (worldReferenceViewportRectRight.isValid()
- && worldReferenceViewportRectRight.intersects(rect)));
-}
-
-QList<QPair<QRect, QRect> > QGeoTiledMapDataPrivate::intersectedScreen(const QRect &rect, bool translateToScreen) const
-{
- QList<QPair<QRect, QRect> > result;
-
- QRect rectL = rect.intersected(worldReferenceViewportRectLeft);
- if (!rectL.isEmpty()) {
- QRect source = QRect(rectL.topLeft() - rect.topLeft(), rectL.size());
- QRect target = QRect(rectL.topLeft() - worldReferenceViewportRectLeft.topLeft(), rectL.size());
- result << QPair<QRect, QRect>(source, target);
- }
-
- if (worldReferenceViewportRectRight.isValid()) {
- QRect rectR = rect.intersected(worldReferenceViewportRectRight);
- if (!rectR.isEmpty()) {
- QRect source = QRect(rectR.topLeft() - rect.topLeft(), rectR.size());
- QRect target = QRect(rectR.topLeft() - worldReferenceViewportRectRight.topLeft(), rectR.size());
- if (translateToScreen)
- target.translate(worldReferenceViewportRectLeft.width(), 0);
- result << QPair<QRect, QRect>(source, target);
- }
- }
-
- return result;
-}
-
-// Old version, for reference
-
-//void QGeoMapDataPrivate::addObject(QGeoMapObject *object)
-//{
-// containerObject->addChildObject(object);
-// oe->addObject(object);
-// emit q_ptr->updateMapDisplay();
-//}
-
-//void QGeoMapDataPrivate::removeObject(QGeoMapObject *object)
-//{
-// containerObject->removeChildObject(object);
-// oe->removeObject(object);
-//}
-
-void QGeoTiledMapDataPrivate::addObject(QGeoMapObject *object)
-{
-// containerObject->addChildObject(object);
-// oe->addObject(object);
-// emit q_ptr->updateMapDisplay();
-
- QGeoMapDataPrivate::addObject(object);
- oe->addObject(object);
-}
-
-void QGeoTiledMapDataPrivate::removeObject(QGeoMapObject *object)
-{
- QGeoMapDataPrivate::removeObject(object);
- oe->removeObject(object);
-}
-
-void QGeoTiledMapDataPrivate::update(QObject *object)
-{
- QGeoMapObject *obj = qobject_cast<QGeoMapObject*>(object);
- if (obj) {
- QGeoMapGroupObject *group = qobject_cast<QGeoMapGroupObject*>(obj);
- if (group) {
- oe->objectsForLatLonUpdate << group;
- oe->objectsForPixelUpdate << group;
- static_cast<QGeoTiledMapData*>(q_ptr)->triggerUpdateMapDisplay();
- } else {
- oe->invalidateObject(obj);
- }
- } else {
- static_cast<QGeoTiledMapData*>(q_ptr)->triggerUpdateMapDisplay();
- }
-}
-
-/*******************************************************************************
-*******************************************************************************/
-
-QGeoTileIterator::QGeoTileIterator(const QGeoTiledMapDataPrivate *mapDataPrivate)
- : atEnd(false),
- row(-1),
- col(-1),
- screenRect(mapDataPrivate->worldReferenceViewportRect),
- mapType(mapDataPrivate->mapType),
- connectivityMode(mapDataPrivate->connectivityMode),
- zoomLevel(mapDataPrivate->zoomLevel)
-{
- QGeoTiledMappingManagerEngine *tiledEngine
- = static_cast<QGeoTiledMappingManagerEngine*>(mapDataPrivate->engine);
- tileSize = tiledEngine->tileSize() * mapDataPrivate->zoomFactor;
- tileRect = QRect(QPoint(0, 0), tileSize);
-
- qulonglong x = static_cast<qulonglong>(screenRect.topLeft().x() / tileSize.width());
- qulonglong y = static_cast<qulonglong>(screenRect.topLeft().y() / tileSize.height());
-
- width = tileSize.width() * (1 << zoomLevel);
-
- currTopLeft.setX(x * tileSize.width());
- currTopLeft.setY(y * tileSize.height());
-}
-
-QGeoTileIterator::QGeoTileIterator(QGraphicsGeoMap::ConnectivityMode connectivityMode,
- QGraphicsGeoMap::MapType mapType,
- const QRect &screenRect,
- const QSize &tileSize,
- int zoomLevel)
- : atEnd(false),
- row(-1),
- col(-1),
- screenRect(screenRect),
- tileSize(tileSize),
- mapType(mapType),
- connectivityMode(connectivityMode),
- zoomLevel(zoomLevel),
- tileRect(QPoint(0, 0), tileSize)
-{
- qulonglong x = static_cast<qulonglong>(screenRect.topLeft().x() / tileSize.width());
- qulonglong y = static_cast<qulonglong>(screenRect.topLeft().y() / tileSize.height());
-
- width = tileSize.width() * (1 << zoomLevel);
-
- currTopLeft.setX(x * tileSize.width());
- currTopLeft.setY(y * tileSize.height());
-}
-
-bool QGeoTileIterator::hasNext()
-{
- return !atEnd;
-}
-
-QGeoTiledMapRequest QGeoTileIterator::next()
-{
- int numCols = 1 << zoomLevel;
- col = static_cast<int>(currTopLeft.x() / tileSize.width()) % numCols;
- row = static_cast<int>(currTopLeft.y() / tileSize.height()) % numCols;
- tileRect.moveTopLeft(currTopLeft);
- if (tileRect.left() >= width)
- tileRect.translate(-width, 0);
-
- currTopLeft.rx() += tileSize.width();
-
- if (currTopLeft.x() > screenRect.right()) { //next row
- qulonglong x = static_cast<qulonglong>(screenRect.topLeft().x() / tileSize.width());
- currTopLeft.setX(x * tileSize.width());
- currTopLeft.ry() += tileSize.height();
- }
-
- if (currTopLeft.y() > screenRect.bottom()) //done
- atEnd = true;
-
- return QGeoTiledMapRequest(connectivityMode, mapType, zoomLevel, row, col, tileRect);
-}
-
-#include "moc_qgeotiledmapdata.cpp"
-
-QT_END_NAMESPACE