diff options
Diffstat (limited to 'src/location/maps')
35 files changed, 5113 insertions, 109 deletions
diff --git a/src/location/maps/maps.pri b/src/location/maps/maps.pri index 01603279..1d1e0078 100644 --- a/src/location/maps/maps.pri +++ b/src/location/maps/maps.pri @@ -1,46 +1,70 @@ INCLUDEPATH += maps +QT += network qt3d + PUBLIC_HEADERS += \ - maps/qgeocodingmanager.h \ - maps/qgeocodingmanagerengine.h \ + maps/qgeocameradata.h \ maps/qgeocodereply.h \ + maps/qgeocodingmanagerengine.h \ + maps/qgeocodingmanager.h \ maps/qgeomaneuver.h \ - maps/qgeomappingmanager.h \ + maps/qgeomapcontroller.h \ + maps/qgeomap.h \ maps/qgeomappingmanagerengine.h \ + maps/qgeomappingmanager.h \ + maps/qgeomaptype.h \ maps/qgeoroute.h \ maps/qgeoroutereply.h \ maps/qgeorouterequest.h \ maps/qgeoroutesegment.h \ - maps/qgeoroutingmanager.h \ maps/qgeoroutingmanagerengine.h \ - maps/qgeoserviceprovider.h \ + maps/qgeoroutingmanager.h \ maps/qgeoserviceproviderfactory.h \ - maps/qgeotiledmapreply.h + maps/qgeoserviceprovider.h \ + maps/qgeotilecache.h \ + maps/qgeotiledmapreply.h \ + maps/qgeotile.h \ + maps/qgeotilespec.h PRIVATE_HEADERS += \ - maps/qgeocodingmanager_p.h \ - maps/qgeocodingmanagerengine_p.h \ maps/qgeocodereply_p.h \ + maps/qgeocodingmanagerengine_p.h \ + maps/qgeocodingmanager_p.h \ + maps/qgeofrustum_p.h \ maps/qgeomaneuver_p.h \ - maps/qgeomappingmanager_p.h \ + maps/qgeomap_p.h \ maps/qgeomappingmanagerengine_p.h \ + maps/qgeomappingmanager_p.h \ + maps/qgeomapsphere_p.h \ + maps/qgeomaptype_p.h \ + maps/qgeoprojection2d_p.h \ + maps/qgeoprojection_p.h \ maps/qgeoroute_p.h \ maps/qgeoroutereply_p.h \ maps/qgeorouterequest_p.h \ maps/qgeoroutesegment_p.h \ - maps/qgeoroutingmanager_p.h \ maps/qgeoroutingmanagerengine_p.h \ + maps/qgeoroutingmanager_p.h \ maps/qgeoserviceprovider_p.h \ - maps/qgeotiledmapreply_p.h + maps/qgeotiledmapreply_p.h \ + maps/qgeotilespec_p.h SOURCES += \ + maps/qgeocameradata.cpp \ + maps/qgeocodereply.cpp \ maps/qgeocodingmanager.cpp \ maps/qgeocodingmanagerengine.cpp \ - maps/qgeocodereply.cpp \ + maps/qgeofrustum.cpp \ maps/qgeomaneuver.cpp \ + maps/qgeomapcontroller.cpp \ + maps/qgeomap.cpp \ maps/qgeomappingmanager.cpp \ maps/qgeomappingmanagerengine.cpp \ + maps/qgeomapsphere.cpp \ + maps/qgeomaptype.cpp \ + maps/qgeoprojection2d_p.cpp \ + maps/qgeoprojection.cpp \ maps/qgeoroute.cpp \ maps/qgeoroutereply.cpp \ maps/qgeorouterequest.cpp \ @@ -49,4 +73,7 @@ SOURCES += \ maps/qgeoroutingmanagerengine.cpp \ maps/qgeoserviceprovider.cpp \ maps/qgeoserviceproviderfactory.cpp \ - maps/qgeotiledmapreply.cpp + maps/qgeotilecache.cpp \ + maps/qgeotile.cpp \ + maps/qgeotiledmapreply.cpp \ + maps/qgeotilespec.cpp diff --git a/src/location/maps/qgeocameradata.cpp b/src/location/maps/qgeocameradata.cpp new file mode 100644 index 00000000..e407c5ba --- /dev/null +++ b/src/location/maps/qgeocameradata.cpp @@ -0,0 +1,291 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $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 "qgeocameradata.h" + +#include <QVariant> +#include <QVariantAnimation> + +#include <QMetaType> + +#include <QWeakPointer> + +#include <cmath> + +QT_BEGIN_NAMESPACE + +class QGeoCameraDataPrivate : public QSharedData +{ +public: + QGeoCameraDataPrivate(); + QGeoCameraDataPrivate(const QGeoCameraDataPrivate &rhs); + + QGeoCameraDataPrivate& operator = (const QGeoCameraDataPrivate &rhs); + + bool operator == (const QGeoCameraDataPrivate &rhs) const; + + QGeoCoordinate center_; + double distance_; + double bearing_; + double tilt_; + double roll_; + double aspectRatio_; + int zoomLevel_; + double zoomFactor_; + + QWeakPointer<QGeoProjection> projection_; +}; + +QGeoCameraDataPrivate::QGeoCameraDataPrivate() + : QSharedData(), + center_(-27.5, 153), + distance_(0.02), + bearing_(0.0), + tilt_(0.0), + roll_(0.0), + aspectRatio_(1.0), + zoomLevel_(9) {} + +QGeoCameraDataPrivate::QGeoCameraDataPrivate(const QGeoCameraDataPrivate &rhs) + : QSharedData(rhs), + center_(rhs.center_), + distance_(rhs.distance_), + bearing_(rhs.bearing_), + tilt_(rhs.tilt_), + roll_(rhs.roll_), + aspectRatio_(rhs.aspectRatio_), + zoomLevel_(rhs.zoomLevel_), + zoomFactor_(rhs.zoomFactor_), + projection_(rhs.projection_) {} + +QGeoCameraDataPrivate& QGeoCameraDataPrivate::operator = (const QGeoCameraDataPrivate &rhs) +{ + center_ = rhs.center_; + distance_ = rhs.distance_; + bearing_ = rhs.bearing_; + tilt_ = rhs.tilt_; + roll_ = rhs.roll_; + aspectRatio_ = rhs.aspectRatio_; + zoomLevel_ = rhs.zoomLevel_; + zoomFactor_ = rhs.zoomFactor_; + QSharedPointer<QGeoProjection> p = rhs.projection_.toStrongRef(); + if (p) + projection_ = p.toWeakRef(); + else + projection_.clear(); + + return *this; +} + +bool QGeoCameraDataPrivate::operator == (const QGeoCameraDataPrivate &rhs) const +{ + return ((center_ == rhs.center_) + && (distance_ == rhs.distance_) + && (bearing_ == rhs.bearing_) + && (tilt_ == rhs.tilt_) + && (roll_ == rhs.roll_) + && (aspectRatio_ == rhs.aspectRatio_) + && (zoomLevel_ == rhs.zoomLevel_) + && (zoomFactor_ == rhs.zoomFactor_)); +} + +QVariant cameraInterpolator(const QGeoCameraData &start, + const QGeoCameraData &end, + qreal progress) +{ + QGeoCameraData result = start; + + + QSharedPointer<QGeoProjection> p = start.projection(); + if (!p) + p = end.projection(); + + if (!p) + result.setCenter(start.center()); + else + result.setCenter(p->interpolate(start.center(), end.center(), progress)); + + double sf = 1.0 - progress; + double ef = progress; + + result.setBearing(sf * start.bearing() + ef * end.bearing()); + result.setTilt(sf * start.tilt() + ef * end.tilt()); + result.setRoll(sf * start.roll() + ef * end.roll()); + result.setZoomFactor(sf * start.zoomFactor() + ef * end.zoomFactor()); + + return QVariant::fromValue(result); +} + +QGeoCameraData::QGeoCameraData() + : d(new QGeoCameraDataPrivate()) +{ + qRegisterMetaType<QGeoCameraData>(); + qRegisterAnimationInterpolator<QGeoCameraData>(cameraInterpolator); + setZoomFactor(4.0); +} + +QGeoCameraData::QGeoCameraData(const QGeoCameraData &other) + : d(other.d) {} + +QGeoCameraData::~QGeoCameraData() +{ +} + +QGeoCameraData& QGeoCameraData::operator = (const QGeoCameraData &other) +{ + d = other.d; + return *this; +} + +bool QGeoCameraData::operator == (const QGeoCameraData &rhs) const +{ + return (*(d.constData()) == *(rhs.d.constData())); +} + +bool QGeoCameraData::operator != (const QGeoCameraData &other) const +{ + return !(operator==(other)); +} + +void QGeoCameraData::setCenter(const QGeoCoordinate ¢er) +{ + d->center_ = center; +} + +QGeoCoordinate QGeoCameraData::center() const +{ + return d->center_; +} + +void QGeoCameraData::setBearing(double bearing) +{ + d->bearing_ = bearing; +} + +double QGeoCameraData::bearing() const +{ + return d->bearing_; +} + +void QGeoCameraData::setTilt(double tilt) +{ + d->tilt_ = tilt; +} + +double QGeoCameraData::tilt() const +{ + return d->tilt_; +} + +void QGeoCameraData::setRoll(double roll) +{ + d->roll_ = roll; +} + +double QGeoCameraData::roll() const +{ + return d->roll_; +} + +void QGeoCameraData::setAspectRatio(double aspectRatio) +{ + d->aspectRatio_ = aspectRatio; +} + +double QGeoCameraData::aspectRatio() const +{ + return d->aspectRatio_; +} + +/* + Distance and zoomLevel are only writeable for debugging purposes. + The setters will eventually go away and then zoomFactor will be + the way to set these. +*/ + +void QGeoCameraData::setDistance(double distance) +{ + d->zoomFactor_ = -1.0 * log(distance) / log(2.0); + d->distance_ = distance; +} + +double QGeoCameraData::distance() const +{ + return d->distance_; +} + +void QGeoCameraData::setZoomLevel(int zoomLevel) +{ + d->zoomLevel_ = zoomLevel; +} + +int QGeoCameraData::zoomLevel() const +{ + return d->zoomLevel_; +} + +void QGeoCameraData::setZoomFactor(double zoomFactor) +{ + d->zoomLevel_ = floor(zoomFactor); +// qDebug() << __FUNCTION__ << zoomFactor << d->zoomLevel_; + + // FIXME this will need some tuning + + d->distance_ = 1.0 / pow(2.0, zoomFactor); + + d->zoomFactor_ = zoomFactor; +} + +double QGeoCameraData::zoomFactor() const +{ + return d->zoomFactor_; +} + +void QGeoCameraData::setProjection(QSharedPointer<QGeoProjection> projection) +{ + d->projection_ = projection.toWeakRef(); +} + +QSharedPointer<QGeoProjection> QGeoCameraData::projection() const +{ + return d->projection_.toStrongRef(); +} + +QT_END_NAMESPACE diff --git a/src/location/maps/qgeocameradata.h b/src/location/maps/qgeocameradata.h new file mode 100644 index 00000000..5a9e9233 --- /dev/null +++ b/src/location/maps/qgeocameradata.h @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $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$ +** +****************************************************************************/ +#ifndef QGEOCAMERADATA_H +#define QGEOCAMERADATA_H + +#include "qgeocoordinate.h" +#include "qgeoprojection_p.h" + +#include <QMetaType> + +#include <QSharedPointer> +#include <QSharedDataPointer> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QGeoCameraDataPrivate; + +class Q_LOCATION_EXPORT QGeoCameraData +{ +public: + QGeoCameraData(); + QGeoCameraData(const QGeoCameraData &other); + ~QGeoCameraData(); + + QGeoCameraData& operator = (const QGeoCameraData &other); + + bool operator == (const QGeoCameraData &other) const; + bool operator != (const QGeoCameraData &other) const; + + void setCenter(const QGeoCoordinate &coordinate); + QGeoCoordinate center() const; + + void setBearing(double bearing); + double bearing() const; + + void setTilt(double tilt); + double tilt() const; + + void setRoll(double roll); + double roll() const; + + void setAspectRatio(double aspectRatio); + double aspectRatio() const; + + void setDistance(double distance); + double distance() const; + + void setZoomLevel(int zoomLevel); + int zoomLevel() const; + + void setZoomFactor(double zoomFactor); + double zoomFactor() const; + + void setProjection(QSharedPointer<QGeoProjection> projection); + QSharedPointer<QGeoProjection> projection() const; + +private: + QSharedDataPointer<QGeoCameraDataPrivate> d; +}; + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QGeoCameraData) + +QT_END_HEADER + +#endif // QGEOCAMERADATA_H diff --git a/src/location/maps/qgeofrustum.cpp b/src/location/maps/qgeofrustum.cpp new file mode 100644 index 00000000..8427707f --- /dev/null +++ b/src/location/maps/qgeofrustum.cpp @@ -0,0 +1,138 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $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 "qgeofrustum_p.h" + +#include <Qt3D/qglcamera.h> + +#include <cmath> + +QGeoFrustum::QGeoFrustum() {} + +void QGeoFrustum::update(const QGLCamera *camera, double aspectRatio, bool updatePlanes) +{ + if (aspectRatio > 1.0) { + double fov = atan2(camera->viewSize().height() , (2 * camera->nearPlane())); + + hn_ = 2 * tan(fov) * camera->nearPlane(); + wn_ = hn_ * aspectRatio; + + hf_ = 2 * tan(fov) * camera->farPlane(); + wf_ = hf_ * aspectRatio; + } else { + double fov = atan2(camera->viewSize().width() , (2 * camera->nearPlane())); + + wn_ = 2 * tan(fov) * camera->nearPlane(); + hn_ = wn_ / aspectRatio; + + wf_ = 2 * tan(fov) * camera->farPlane(); + hf_ = wf_ / aspectRatio; + } + + QVector3D p = camera->eye(); + QVector3D d = camera->center() - camera->eye(); + d.normalize(); + + QVector3D up = camera->upVector(); + up.normalize(); + + QVector3D right = QVector3D::normal(d, up); + + cf_ = p + d * camera->farPlane(); + tlf_ = cf_ + (up * hf_ / 2) - (right * wf_ / 2); + trf_ = cf_ + (up * hf_ / 2) + (right * wf_ / 2); + blf_ = cf_ - (up * hf_ / 2) - (right * wf_ / 2); + brf_ = cf_ - (up * hf_ / 2) + (right * wf_ / 2); + + cn_ = p + d * camera->nearPlane(); + tln_ = cn_ + (up * hn_ / 2) - (right * wn_ / 2); + trn_ = cn_ + (up * hn_ / 2) + (right * wn_ / 2); + bln_ = cn_ - (up * hn_ / 2) - (right * wn_ / 2); + brn_ = cn_ - (up * hn_ / 2) + (right * wn_ / 2); + + if (!updatePlanes) + return; + + QPlane3D pn = QPlane3D(bln_, tln_, brn_); + pn.setNormal(pn.normal().normalized()); + planeHash_.insert(QGeoFrustum::Planes(QGeoFrustum::Near), pn); + + QPlane3D pf = QPlane3D(blf_, brf_, tlf_); + pf.setNormal(pf.normal().normalized()); + planeHash_.insert(QGeoFrustum::Planes(QGeoFrustum::Far), pf); + + QPlane3D pl = QPlane3D(blf_, tlf_, bln_); + pl.setNormal(pl.normal().normalized()); + planeHash_.insert(QGeoFrustum::Planes(QGeoFrustum::Left), pl); + + QPlane3D pr = QPlane3D(brf_, brn_, trf_); + pr.setNormal(pr.normal().normalized()); + planeHash_.insert(QGeoFrustum::Planes(QGeoFrustum::Right), pr); + + QPlane3D pt = QPlane3D(tlf_, trf_, tln_); + pt.setNormal(pt.normal().normalized()); + planeHash_.insert(QGeoFrustum::Planes(QGeoFrustum::Top), pt); + + QPlane3D pb = QPlane3D(blf_, bln_, brf_); + pb.setNormal(pb.normal().normalized()); + planeHash_.insert(QGeoFrustum::Planes(QGeoFrustum::Bottom), pb); +} + +bool QGeoFrustum::contains(const QVector3D ¢er, double radius) const +{ + if (planeHash_.isEmpty()) + return false; + + QHash<QGeoFrustum::Planes, QPlane3D>::const_iterator i = planeHash_.constBegin(); + QHash<QGeoFrustum::Planes, QPlane3D>::const_iterator end = planeHash_.constEnd(); + + while (i != end) { + if (i.value().distanceTo(center) < -1.0 * radius) + return false; + ++i; + } + + return true; +} + +QPlane3D QGeoFrustum::plane(Planes planes) const +{ + return planeHash_.value(planes); +} diff --git a/src/location/maps/qgeofrustum_p.h b/src/location/maps/qgeofrustum_p.h new file mode 100644 index 00000000..0d1ca0e7 --- /dev/null +++ b/src/location/maps/qgeofrustum_p.h @@ -0,0 +1,143 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $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$ +** +****************************************************************************/ +#ifndef QGEOFRUSTUM_H +#define QGEOFRUSTUM_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QVector3D> +#include <QHash> + +#include <Qt3D/qplane3d.h> + +QT_BEGIN_NAMESPACE + +class QGLCamera; + +class Q_AUTOTEST_EXPORT QGeoFrustum +{ +public: + enum Plane { + Near = 0x001, + Far = 0x002, + Right = 0x004, + Left = 0x008, + Top = 0x010, + Bottom = 0x020, + TopLeftNear = Top | Left | Near, + TopLeftFar = Top | Left | Far, + TopRightNear = Top | Right | Near, + TopRightFar = Top | Right | Far, + BottomLeftNear = Bottom | Left | Near, + BottomLeftFar = Bottom | Left | Far, + BottomRightNear = Bottom | Right | Near, + BottomRightFar = Bottom | Right | Far + }; + + Q_DECLARE_FLAGS(Planes, Plane) + + QGeoFrustum(); + + void update(const QGLCamera *camera, double aspectRatio, bool updatePlanes = false); + + bool contains(const QVector3D ¢er, double radius) const; + + QVector3D topLeftNear() const { + return tln_; + } + QVector3D topLeftFar() const { + return tlf_; + } + QVector3D bottomLeftNear() const { + return bln_; + } + QVector3D bottomLeftFar() const { + return blf_; + } + QVector3D topRightNear() const { + return trn_; + } + QVector3D topRightFar() const { + return trf_; + } + QVector3D bottomRightNear() const { + return brn_; + } + QVector3D bottomRightFar() const { + return brf_; + } + + QPlane3D plane(Planes planes) const; + +private: + double hf_; + double wf_; + QVector3D cf_; + QVector3D tlf_; + QVector3D trf_; + QVector3D blf_; + QVector3D brf_; + + double hn_; + double wn_; + QVector3D cn_; + QVector3D tln_; + QVector3D trn_; + QVector3D bln_; + QVector3D brn_; + + QHash<Planes, QPlane3D> planeHash_; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QGeoFrustum::Planes) + +QT_END_NAMESPACE + +#endif // QGEOFRUSTUM_H diff --git a/src/location/maps/qgeomap.cpp b/src/location/maps/qgeomap.cpp new file mode 100644 index 00000000..f06fb144 --- /dev/null +++ b/src/location/maps/qgeomap.cpp @@ -0,0 +1,1357 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $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 "qgeomap.h" +#include "qgeomap_p.h" + +#include "qgeotilecache.h" +#include "qgeomapsphere_p.h" +#include "qgeoprojection_p.h" +#include "qgeoprojection2d_p.h" +#include "qgeotile.h" +#include "qgeomapcontroller.h" + +#include "qgeomappingmanager.h" + +#include <QMutex> +#include <QMap> + +#include <qglscenenode.h> +#include <qgeometrydata.h> +#include <qglbuilder.h> +#include <Qt3D/qglpainter.h> +#include <Qt3D/qgeometrydata.h> +#include <Qt3D/qglbuilder.h> +#include <Qt3D/qglcamera.h> +#include <Qt3D/qglsubsurface.h> + +#include <cmath> + +QGeoMap::QGeoMap(QGeoTileCache *cache, QObject *parent) + : QObject(parent) +{ +// d_ptr = new Map3DPrivate(this, cache, 20000.0); + + // edge is 2^max zoom * 4 + d_ptr = new QGeoMapPrivate(this, cache, 20, 256); +} + +QGeoMap::~QGeoMap() +{ + delete d_ptr; +} + +QGeoTileCache* QGeoMap::tileCache() +{ + Q_D(QGeoMap); + return d->tileCache(); +} + +QGeoMapController* QGeoMap::mapController() +{ + Q_D(QGeoMap); + return d->mapController(); +} + +void QGeoMap::setMappingManager(QGeoMappingManager *manager) +{ + Q_D(QGeoMap); + d->setMappingManager(manager); +} + +void QGeoMap::paintGL(QGLPainter *painter) +{ + Q_D(QGeoMap); + d->paintGL(painter); +} + +QGLCamera* QGeoMap::glCamera() const +{ + Q_D(const QGeoMap); + return d->glCamera(); +} + +void QGeoMap::resize(int width, int height) +{ + Q_D(QGeoMap); + d->resize(width, height); + + // always emit this signal to trigger items to redraw + emit cameraDataChanged(d->cameraData()); +} + +int QGeoMap::width() const +{ + Q_D(const QGeoMap); + return d->width(); +} + +int QGeoMap::height() const +{ + Q_D(const QGeoMap); + return d->height(); +} + +void QGeoMap::setCameraData(const QGeoCameraData &cameraData) +{ + Q_D(QGeoMap); + + if (cameraData == d->cameraData()) + return; + + d->setCameraData(cameraData); + update(); + + emit cameraDataChanged(d->cameraData()); +} + +QGeoCameraData QGeoMap::cameraData() const +{ + Q_D(const QGeoMap); + return d->cameraData(); +} + +void QGeoMap::update() +{ + Q_D(QGeoMap); + d->update(); + emit updateRequired(); +} + +QGeoCoordinate QGeoMap::screenPositionToCoordinate(const QPointF &pos, bool clipToViewport) const +{ + Q_D(const QGeoMap); + if (clipToViewport) { + int w = d->width(); + int h = d->height(); + + if ((pos.x() < 0) || (w < pos.x()) || (pos.y() < 0) || (h < pos.y())) + return QGeoCoordinate(); + } + + return d->screenPositionToCoordinate(pos); +} + +QPointF QGeoMap::coordinateToScreenPosition(const QGeoCoordinate &coordinate, bool clipToViewport) const +{ + Q_D(const QGeoMap); + QPointF pos = d->coordinateToScreenPosition(coordinate); + + if (clipToViewport) { + int w = d->width(); + int h = d->height(); + + if ((pos.x() < 0) || (w < pos.x()) || (pos.y() < 0) || (h < pos.y())) + return QPointF(qQNaN(), qQNaN()); + } + + return pos; +} + +void QGeoMap::setActiveMapType(const QGeoMapType type) +{ + Q_D(QGeoMap); + d->setActiveMapType(type); +} + +const QGeoMapType QGeoMap::activeMapType() const +{ + Q_D(const QGeoMap); + return d->activeMapType(); +} + +//------------------------------------------------------------// + +TileMap::TileMap(int minY, int maxY) + : size(0), + minY(minY), + maxY(maxY), + minX(maxY - minY + 1, -1), + maxX(maxY - minY + 1, -1) +{} + +void TileMap::adjust(int tileX, int tileY) +{ + int index = tileY - minY; + int min = minX.at(index); + int max = maxX.at(index); + + if (min == -1) { + min = tileX; + max = tileX; + minX[index] = min; + maxX[index] = max; + size += 1; + } else { + int oldSize = (max - min); + int min2 = qMin(min, tileX); + if (min2 != min) + minX[index] = min2; + int max2 = qMax(max, tileX); + if (max2 != max) + maxX[index] = max2; + int newSize = (max2 - min2); + size += (newSize - oldSize); + } +} + +IntersectGenerator::IntersectGenerator(const QGeoMapPrivate *mp, + double p1, + double p2, + int t1, + int t2, + IntersectGenerator::Axis axis, + int zoomLevel) + : mp_(mp), + axis_(axis), + zoomLevel_(zoomLevel) +{ + if (t1 == t2) { + hasNext_ = false; + return; + } + + bool inc = true; + if (axis_ == IntersectGenerator::XAxis) { + inc = (0 < (p2 - p1)); + } else { + inc = (0 < (p1 - p2)); + } + + step_ = 1; + adjust_ = 0; + if (!inc) { + step_ = -1; + adjust_ = -1; + } + + first_ = p1; + denom_ = p2 - p1; + + current_ = t1; + end_ = t2 + step_; + + hasNext_ = true; + + generateValue(); +} + +bool IntersectGenerator::hasNext() const +{ + return hasNext_; +} + +QPair<double, int> IntersectGenerator::value() const +{ + return value_; +} + +void IntersectGenerator::next() +{ + generateValue(); +} + +void IntersectGenerator::generateValue() +{ + while (current_ != end_) { + double alpha = 0.0; + + if (axis_ == IntersectGenerator::XAxis) { + double x = mp_->tileXIntersectToPoint(zoomLevel_, current_).x(); + alpha = (x - first_) / denom_; + } else { + double y = mp_->tileYIntersectToPoint(zoomLevel_, current_).y(); + alpha = (y - first_) / denom_; + } + + if ((0.0 < alpha) && (alpha < 1.0)) { + value_ = QPair<double,int>(alpha, current_ + adjust_); + current_ += step_; + if (current_ == end_) + hasNext_ = false; + return; + } + current_ += step_; + } + hasNext_ = false; +} + +//------------------------------------------------------------// + +QGeoMapPrivate::QGeoMapPrivate(QGeoMap *parent, QGeoTileCache *cache, int maxZoom, int tileSize) + : map_(parent), + cache_(cache), + manager_(0), + controller_(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_)); + screenPoly_.resize(4); + screenPoly_[0] = QPointF(0.0, 0.0); + screenPoly_[1] = QPointF(0.0, sideLength_); + screenPoly_[2] = QPointF(sideLength_, sideLength_); + screenPoly_[3] = QPointF(sideLength_, 0.0); + + screenPolyLeft_.resize(4); + screenPolyLeft_[0] = QPointF(0.0, 0.0); + screenPolyLeft_[1] = QPointF(0.0, sideLength_); + screenPolyLeft_[2] = QPointF(sideLength_ / 2.0, sideLength_); + screenPolyLeft_[3] = QPointF(sideLength_ / 2.0, 0.0); + + screenPolyRight_.resize(4); + screenPolyRight_[0] = QPointF(sideLength_ / 2.0, 0.0); + screenPolyRight_[1] = QPointF(sideLength_ / 2.0, sideLength_); + screenPolyRight_[2] = QPointF(sideLength_, sideLength_); + screenPolyRight_[3] = QPointF(sideLength_, 0.0); +} + +QGeoMapPrivate::~QGeoMapPrivate() +{ + // controller_ is a child of map_, don't need to delete it here + manager_->deregisterMap(map_); + delete sphere_; + delete glCamera_; + // TODO map items are not deallocated! + // However: how to ensure this is done in rendering thread? +} + +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()); + sphere_->setMappingManager(manager); + } else { + manager->deregisterMap(map_); + } + manager_ = manager; +} + +QGeoMapController* QGeoMapPrivate::mapController() +{ + if (!controller_) + controller_ = new QGeoMapController(map_, projection_); + return controller_; +} + +QGLCamera* QGeoMapPrivate::glCamera() const +{ + return glCamera_; +} + +void QGeoMapPrivate::setCameraData(const QGeoCameraData &cameraData) +{ + cameraData_ = cameraData; + cameraData_.setAspectRatio(aspectRatio_); + cameraData_.setProjection(projection_.toWeakRef()); + updateGlCamera(glCamera_); + updateFrustum(frustum_); + visibleTiles_ = updateVisibleTiles(); + sphere_->update(visibleTiles_); +} + +QGeoCameraData QGeoMapPrivate::cameraData() const +{ + return cameraData_; +} + +void QGeoMapPrivate::update() +{ + sphere_->update(visibleTiles_); +} + +void QGeoMapPrivate::resize(int width, int height) +{ + width_ = width; + height_ = height; + aspectRatio_ = 1.0 * width_ / height_; + setCameraData(cameraData_); +} + +QVector2D QGeoMapPrivate::pointToTile(const QVector3D &point, int zoom, bool roundUp) const +{ + QVector2D p = projection_->pointToMercator(point); + + int z = 1 << zoom; + int x = 0; + int y = 0; + + if (p.y() == 1.0) + y = z - 1; + else + y = static_cast<int>(z * p.y()) % z; + + if ((qAbs(p.x()) < 1e-6) || (qAbs(p.x() - 1) < 1e-6)) + if (roundUp) + x = z - 1; + else + x = 0; + else + x = static_cast<int>(z * p.x()) % z; + + return QVector2D(x, y); +} + +QVector3D QGeoMapPrivate::tileXIntersectToPoint(int zoomLevel, int x) const +{ + int zpow2 = 1 << zoomLevel; + return projection_->mercatorToPoint(QVector2D(x * 1.0 / zpow2, zpow2 / 2.0)); +} + +QVector3D QGeoMapPrivate::tileYIntersectToPoint(int zoomLevel, int y) const +{ + int zpow2 = 1 << zoomLevel; + return projection_->mercatorToPoint(QVector2D(zpow2 / 2.0, y * 1.0 / zpow2)); +} + +int QGeoMapPrivate::width() const +{ + return width_; +} + +int QGeoMapPrivate::height() const +{ + return height_; +} + +double QGeoMapPrivate::aspectRatio() const +{ + return aspectRatio_; +} + +void QGeoMapPrivate::setActiveMapType(const QGeoMapType type) +{ + activeMapType_ = type; + //TODO: check if this shared + //make it more optimal + //rewrite current specs + QList<QGeoTileSpec> temp = visibleTiles_; + visibleTiles_.clear(); + foreach (QGeoTileSpec spec,temp) { + spec.setMapId(type.mapId()); + visibleTiles_ << spec; + } + + map_->update(); +} + +const QGeoMapType QGeoMapPrivate::activeMapType() const +{ + return activeMapType_; +} + +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; + + QVector3D tl = projection_->mercatorToPoint(QVector2D(x1, y1)); + QVector3D tr = projection_->mercatorToPoint(QVector2D(x2, y1)); + QVector3D bl = projection_->mercatorToPoint(QVector2D(x1, y2)); + QVector3D br = projection_->mercatorToPoint(QVector2D(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; + + QVector3D tl = projection_->mercatorToPoint(QVector2D(x1, y1)); + QVector3D tr = projection_->mercatorToPoint(QVector2D(x2, y1)); + QVector3D bl = projection_->mercatorToPoint(QVector2D(x1, y2)); + QVector3D br = projection_->mercatorToPoint(QVector2D(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; + + QVector3D n = QVector3D(0, 0, 1); + + g.appendVertex(tl); + g.appendNormal(n); + g.appendTexCoord(QVector2D(tx1 * 1.0 / dz, ty1 * 1.0 / dz)); + + g.appendVertex(bl); + g.appendNormal(n); + g.appendTexCoord(QVector2D(tx1 * 1.0 / dz, ty2 * 1.0 / dz)); + + g.appendVertex(br); + g.appendNormal(n); + g.appendTexCoord(QVector2D(tx2 * 1.0 / dz, ty2 * 1.0 / dz)); + + g.appendVertex(tr); + g.appendNormal(n); + g.appendTexCoord(QVector2D(tx2 * 1.0 / dz, ty1 * 1.0 / dz)); + + builder.addQuads(g); + + return builder.finalizedSceneNode(); +} + +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); + + QVector3D c = camera->center(); + c.setX(c.x() + sideLength_); + camera->setCenter(c); + + QVector3D e = 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); + QVector3D center = projection_->coordToPoint(coord); + coord.setAltitude(altitude); + QVector3D eye = projection_->coordToPoint(coord); + +// if (pow(2.0, cameraData_.zoomFactor()) * tileSize_ < height_) { +// center.setY(sideLength_ / 2.0); +// eye.setY(sideLength_ / 2.0); +// } + + QVector3D view = eye - center; + QVector3D side = QVector3D::normal(view, QVector3D(0.0, 1.0, 0.0)); + QVector3D up = QVector3D::normal(side, view); + + QMatrix4x4 mBearing; + mBearing.rotate(-1.0 * camera.bearing(), view); + up = mBearing * up; + + QVector3D side2 = QVector3D::normal(up, view); + QMatrix4x4 mTilt; + mTilt.rotate(camera.tilt(), side2); + eye = (mTilt * view) + center; + + view = eye - center; + side = QVector3D::normal(view, QVector3D(0.0, 1.0, 0.0)); + up = QVector3D::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(); +} + +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; + + QVector3D tl = frustum_.topLeftFar(); + QVector3D tr = frustum_.topRightFar(); + QVector3D bl = frustum_.bottomLeftFar(); + + QVector3D n = (1 - x - y) * tl + x * tr + y * bl; + + if (eye_.z() == n.z()) + return QGeoCoordinate(); + + double alpha = eye_.z() / (eye_.z() - n.z()); + QVector3D c = (1 - alpha) * eye_ + alpha * n; + + return projection_->pointToCoord(c); +} + +QPointF QGeoMapPrivate::coordinateToScreenPosition(const QGeoCoordinate &coordinate) const +{ + QVector3D c = projection_->coordToPoint(coordinate); + QVector3D d = 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()); +} + +QList<QGeoTileSpec> QGeoMapPrivate::updateVisibleTiles() +{ + QList<QVector3D> points; + + points.append(pointsOnLineWithZ(frustum_.topLeftNear(), frustum_.topLeftFar(), baseHeight_)); + points.append(pointsOnLineWithZ(frustum_.topRightNear(), frustum_.topRightFar(), baseHeight_)); + points.append(pointsOnLineWithZ(frustum_.bottomLeftNear(), frustum_.bottomLeftFar(), baseHeight_)); + points.append(pointsOnLineWithZ(frustum_.bottomRightNear(), frustum_.bottomRightFar(), baseHeight_)); + + points.append(pointsOnLineWithZ(frustum_.topLeftNear(), frustum_.bottomLeftNear(), baseHeight_)); + points.append(pointsOnLineWithZ(frustum_.bottomLeftNear(), frustum_.bottomRightNear(), baseHeight_)); + points.append(pointsOnLineWithZ(frustum_.bottomRightNear(), frustum_.topRightNear(), baseHeight_)); + points.append(pointsOnLineWithZ(frustum_.topRightNear(), frustum_.topLeftNear(), baseHeight_)); + + points.append(pointsOnLineWithZ(frustum_.topLeftFar(), frustum_.bottomLeftFar(), baseHeight_)); + points.append(pointsOnLineWithZ(frustum_.bottomLeftFar(), frustum_.bottomRightFar(), baseHeight_)); + points.append(pointsOnLineWithZ(frustum_.bottomRightFar(), frustum_.topRightFar(), baseHeight_)); + points.append(pointsOnLineWithZ(frustum_.topRightFar(), frustum_.topLeftFar(), baseHeight_)); + + QList<QGeoTileSpec> tiles; + + if (points.isEmpty()) + return tiles; + + // sort points into a right handed polygon + + LengthSorter sorter; + + // - initial sort to remove duplicates + sorter.base = points.first(); + qSort(points.begin(), points.end(), sorter); + for (int i = points.size() - 1; i > 0; --i) { + if (points.at(i) == points.at(i - 1)) + points.removeAt(i); + } + + // - proper sort + // - start with the first point, put it in the sorted part of the list + // - add the nearest unsorted point to the last sorted point to the end + // of the sorted points + QList<QVector3D>::iterator i; + for (i = points.begin(); i != points.end(); ++i) { + sorter.base = *i; + if (i + 1 != points.end()) + qSort(i + 1, points.end(), sorter); + } + + // - determine if what we have is right handed + if (points.size() >= 3) { + QVector3D normal = QVector3D::normal(points.at(1) - points.at(0), + points.at(2) - points.at(1)); + // - if not, reverse the list + if (normal.z() < 0.0) { + int s = points.size(); + int s2 = s / 2; + for (int i = 0; i < s2; ++i) { + points.swap(i, s - 1 - i); + } + } + } + + // work out if the polygon needs clipping + // - if we go off the far right edge we need to clip into + // two regions - one which rounds down now and one which rounds up + // - otherwise if we cross an edge of the map we just need to clip + // to the map square + + bool round = false; + bool clip = false; + for (int i = 0; i < points.size(); ++i) { + QVector3D p = points.at(i); + if (p.x() >= sideLength_) { + round = true; + break; + } + if ((p.x() < 0) + || (sideLength_ < p.x()) + || (p.y() < 0) + || (sideLength_ < p.y())) { + clip = true; + } + } + + if (!round) { + if (!clip) { + tiles.append(tilesFromPoints(points.toVector(), false)); + } else { + QPair<QList<QVector3D>,QList<QVector3D> > pair = clipPolygonToMap(points); + if (!pair.first.isEmpty()) + tiles.append(tilesFromPoints(pair.first.toVector(), true)); + if (!pair.second.isEmpty()) + tiles.append(tilesFromPoints(pair.second.toVector(), false)); + } + } else { + QPair<QList<QVector3D>,QList<QVector3D> > pair = clipPolygonToMap(points); + if (!pair.first.isEmpty()) { + QPair<QList<QVector3D>, QList<QVector3D> > split = splitPolygonX(pair.first, sideLength_ / 2.0); + if (!split.first.isEmpty()) { + tiles.append(tilesFromPoints(split.first.toVector(), false)); + } + if (!split.second.isEmpty()) { + tiles.append(tilesFromPoints(split.second.toVector(), true)); + } + } + if (!pair.second.isEmpty()) { + QPair<QList<QVector3D>, QList<QVector3D> > split = splitPolygonX(pair.second, sideLength_ / 2.0); + if (!split.first.isEmpty()) { + tiles.append(tilesFromPoints(split.first.toVector(), false)); + } + if (!split.second.isEmpty()) { + tiles.append(tilesFromPoints(split.second.toVector(), true)); + } + } + } + + return tiles; +} + +QList<QGeoTileSpec> QGeoMapPrivate::tilesFromPoints(const QVector<QVector3D> &points, bool roundUp) const +{ + int numPoints = points.size(); + + if (numPoints == 0) + return QList<QGeoTileSpec>(); + + int zoomLevel = cameraData().zoomLevel(); + + int minY = -1; + int maxY = -1; + + QVector<QVector2D> tiles(points.size()); + for (int i = 0; i < numPoints; ++i) { + QVector2D t = pointToTile(points.at(i), zoomLevel, roundUp); + if (minY == -1) { + minY = t.y(); + maxY = t.y(); + } else { + minY = qMin(minY, static_cast<int>(t.y())); + maxY = qMax(maxY, static_cast<int>(t.y())); + } + tiles[i] = t; + } + + TileMap map(minY, maxY); + + for (int i1 = 0; i1 < numPoints; ++i1) { + int i2 = (i1 + 1) % numPoints; + tilesFromLine(points.at(i1), points.at(i2), tiles.at(i1), tiles.at(i2), zoomLevel, map); + } + + QList<QGeoTileSpec> results; + + results.reserve(map.size); + + int size = map.minX.size(); + for (int i = 0; i < size; ++i) { + int y = map.minY + i; + int minX = map.minX[i]; + int maxX = map.maxX[i]; + for (int x = minX; x <= maxX; ++x) + results << QGeoTileSpec(pluginString_, activeMapType().mapId(), zoomLevel, x, y); + } + + return results; +} + +void QGeoMapPrivate::tilesFromLine(const QVector3D &p1, + const QVector3D &p2, + const QVector2D &t1, + const QVector2D &t2, + int zoomLevel, + TileMap &map) const +{ + IntersectGenerator xGen = IntersectGenerator(this, p1.x(), p2.x(), t1.x(), t2.x(), + IntersectGenerator::XAxis, zoomLevel); + IntersectGenerator yGen = IntersectGenerator(this, p1.y(), p2.y(), t1.y(), t2.y(), + IntersectGenerator::YAxis, zoomLevel); + + int tileX = t1.x(); + int tileY = t1.y(); + + map.adjust(tileX, tileY); + + while (xGen.hasNext() && yGen.hasNext()) { + QPair<double, int> x = xGen.value(); + QPair<double, int> y = yGen.value(); + if (x.first < y.first) { + tileX = x.second; + map.adjust(tileX, tileY); + xGen.next(); + } else if (x.first > y.first) { + tileY = y.second; + map.adjust(tileX, tileY); + yGen.next(); + } else { + map.adjust(tileX, y.second); + map.adjust(x.second, tileY); + tileX = x.second; + tileY = y.second; + map.adjust(tileX, tileY); + xGen.next(); + yGen.next(); + } + } + + while (xGen.hasNext()) { + tileX = xGen.value().second; + map.adjust(tileX, tileY); + xGen.next(); + } + + while (yGen.hasNext()) { + tileY = yGen.value().second; + map.adjust(tileX, tileY); + yGen.next(); + } +} + +QPair<QList<QVector3D>,QList<QVector3D> > QGeoMapPrivate::clipPolygonToMap(const QList<QVector3D> &points) const +{ + bool clipX0 = false; + bool clipX1 = false; + bool clipY0 = false; + bool clipY1 = false; + int size = points.size(); + for (int i = 0; i < size; ++i) { + QVector3D p = points.at(i); + if (p.x() < 0.0) + clipX0 = true; + if (sideLength_ < p.x()) + clipX1 = true; + if (p.y() < 0.0) + clipY0 = true; + if (sideLength_ < p.y()) + clipY1 = true; + + } + + QList<QVector3D> results = points; + + if (clipY0) { + results = splitPolygonY(results, 0.0).second; + } + + if (clipY1) { + results = splitPolygonY(results, sideLength_).first; + } + + if (clipX0) { + if (clipX1) { + results = splitPolygonX(results, 0.0).second; + results = splitPolygonX(results, sideLength_).first; + return QPair<QList<QVector3D>,QList<QVector3D> >(results, QList<QVector3D>()); + } else { + QPair<QList<QVector3D>,QList<QVector3D> > pair = splitPolygonX(results, 0.0); + for (int i = 0; i < pair.first.size(); ++i) { + pair.first[i].setX(pair.first.at(i).x() + sideLength_); + } + return pair; + } + } else { + if (clipX1) { + QPair<QList<QVector3D>,QList<QVector3D> > pair = splitPolygonX(results, sideLength_); + for (int i = 0; i < pair.second.size(); ++i) { + pair.second[i].setX(pair.second.at(i).x() - sideLength_); + } + return pair; + } else { + return QPair<QList<QVector3D>,QList<QVector3D> >(results, QList<QVector3D>()); + } + } +} + +QPair<QList<QVector3D>,QList<QVector3D> > QGeoMapPrivate::splitPolygonY(const QList<QVector3D> &points, double y) const +{ + QList<QVector3D> pointsBelow; + QList<QVector3D> pointsAbove; + + int size = points.size(); + + if (size == 0) { + return QPair<QList<QVector3D>,QList<QVector3D> >(pointsBelow, pointsAbove); + } + + bool allAbove = true; + bool allBelow = true; + + for (int i = 0; i < size; ++i) { + double py = points.at(i).y(); + if (py < y) + allAbove = false; + if (y < py) + allBelow = false; + } + + if (allAbove) { + if (allBelow) { + return QPair<QList<QVector3D>,QList<QVector3D> >(pointsBelow, pointsAbove); + } else { + return QPair<QList<QVector3D>,QList<QVector3D> >(pointsBelow, points); + } + } else { + if (allBelow) { + return QPair<QList<QVector3D>,QList<QVector3D> >(points, pointsAbove); + } + } + + + int intersect1 = -1; + int intersect2 = -1; + + // add intersects + + QList<QVector3D> tmpPoints = points; + + for (int i1 = 0; i1 < size; ++i1) { + int i2 = (i1 + 1) % size; + + QVector3D p1 = tmpPoints.at(i1); + QVector3D p2 = tmpPoints.at(i2); + + if (p1.y() == y) { + if (intersect1 == -1) + intersect1 = i1; + else if (intersect2 == -1) + intersect2 = i1; + else + qDebug() << __FUNCTION__ << " more than 2 intersections"; + } + + if (((p1.y() < y) && (y < p2.y())) + || ((p2.y() < y) && (y < p1.y()))) { + QList<QVector3D> newPoints = pointsOnLineWithY(p1, p2, y); + if (newPoints.size() == 1) { + tmpPoints.insert(i1 + 1, newPoints.at(0)); + ++size; + // will get added to intersect1 or intersect 2 in next iteration + } + } + } + + // split at intersects + if ((intersect1 != -1) && (intersect2 != -1)) { + + size = tmpPoints.size(); + + bool firstBelow = true; + + for (int i = intersect1; i <= intersect2; ++i) { + QVector3D p = tmpPoints.at(i); + if (y < p.y()) + firstBelow = false; + pointsBelow.append(p); + } + + for (int i = intersect2; i <= intersect1 + size; ++i) { + pointsAbove.append(tmpPoints.at(i % size)); + } + + if (firstBelow) + return QPair<QList<QVector3D>,QList<QVector3D> >(pointsBelow, pointsAbove); + else + return QPair<QList<QVector3D>,QList<QVector3D> >(pointsAbove, pointsBelow); + + } else { + qDebug() << __FUNCTION__ << " less than 2 intersections"; + } + + return QPair<QList<QVector3D>,QList<QVector3D> >(pointsBelow, pointsAbove); +} + +QPair<QList<QVector3D>,QList<QVector3D> > QGeoMapPrivate::splitPolygonX(const QList<QVector3D> &points, double x) const +{ + QList<QVector3D> pointsBelow; + QList<QVector3D> pointsAbove; + + int size = points.size(); + + if (size == 0) { + return QPair<QList<QVector3D>,QList<QVector3D> >(pointsBelow, pointsAbove); + } + + bool allAbove = true; + bool allBelow = true; + + for (int i = 0; i < size; ++i) { + double px = points.at(i).x(); + if (px < x) + allAbove = false; + if (x < px) + allBelow = false; + } + + if (allAbove) { + if (allBelow) { + return QPair<QList<QVector3D>,QList<QVector3D> >(pointsBelow, pointsAbove); + } else { + return QPair<QList<QVector3D>,QList<QVector3D> >(pointsBelow, points); + } + } else { + if (allBelow) { + return QPair<QList<QVector3D>,QList<QVector3D> >(points, pointsAbove); + } + } + + int intersect1 = -1; + int intersect2 = -1; + + // add intersects + + QList<QVector3D> tmpPoints = points; + + for (int i1 = 0; i1 < size; ++i1) { + int i2 = (i1 + 1) % size; + + QVector3D p1 = tmpPoints.at(i1); + QVector3D p2 = tmpPoints.at(i2); + + if (p1.x() == x) { + if (intersect1 == -1) + intersect1 = i1; + else if (intersect2 == -1) + intersect2 = i1; + else + qDebug() << __FUNCTION__ << " more than 2 intersections"; + } + + if (((p1.x() < x) && (x < p2.x())) + || ((p2.x() < x) && (x < p1.x()))) { + QList<QVector3D> newPoints = pointsOnLineWithX(p1, p2, x); + if (newPoints.size() == 1) { + tmpPoints.insert(i1 + 1, newPoints.at(0)); + ++size; + // will get added to intersect1 or intersect 2 in next iteration + } + } + } + + // split at intersects + if ((intersect1 != -1) && (intersect2 != -1)) { + + size = tmpPoints.size(); + + bool firstBelow = true; + + for (int i = intersect1; i <= intersect2; ++i) { + QVector3D p = tmpPoints.at(i); + if (x < p.x()) + firstBelow = false; + pointsBelow.append(p); + } + + for (int i = intersect2; i <= intersect1 + size; ++i) { + pointsAbove.append(tmpPoints.at(i % size)); + } + + if (firstBelow) + return QPair<QList<QVector3D>,QList<QVector3D> >(pointsBelow, pointsAbove); + else + return QPair<QList<QVector3D>,QList<QVector3D> >(pointsAbove, pointsBelow); + + } else { + qDebug() << __FUNCTION__ << " less than 2 intersections"; + } + + return QPair<QList<QVector3D>,QList<QVector3D> >(pointsBelow, pointsAbove); +} + +QList<QVector3D> QGeoMapPrivate::pointsOnLineWithX(const QVector3D &p1, const QVector3D &p2, double x) const +{ + QList<QVector3D> results; + + if (p1.x() == p2.x()) { + if (p1.x() == x) { + results.append(p1); + results.append(p2); + } + } else { + double f = (p1.x() - x) / (p1.x() - p2.x()); + if ((0 <= f) && (f <= 1.0)) + results.append((1 - f) * p1 + f * p2); + } + + return results; +} + +QList<QVector3D> QGeoMapPrivate::pointsOnLineWithY(const QVector3D &p1, const QVector3D &p2, double y) const +{ + QList<QVector3D> results; + + if (p1.y() == p2.y()) { + if (p1.y() == y) { + results.append(p1); + results.append(p2); + } + } else { + double f = (p1.y() - y) / (p1.y() - p2.y()); + if ((0 <= f) && (f <= 1.0)) + results.append((1 - f) * p1 + f * p2); + } + + return results; +} + +QList<QVector3D> QGeoMapPrivate::pointsOnLineWithZ(const QVector3D &p1, const QVector3D &p2, double z) const +{ + QList<QVector3D> results; + + if (p1.z() == p2.z()) { + if (p1.z() == z) { + results.append(p1); + results.append(p2); + } + } else { + double f = (p1.z() - z) / (p1.z() - p2.z()); + if ((0 <= f) && (f <= 1.0)) + results.append((1 - f) * p1 + f * p2); + } + + return results; +} diff --git a/src/location/maps/qgeomap.h b/src/location/maps/qgeomap.h new file mode 100644 index 00000000..e9fba052 --- /dev/null +++ b/src/location/maps/qgeomap.h @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $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$ +** +****************************************************************************/ +#ifndef QGEOMAP_H +#define QGEOMAP_H + +#include <QObject> + +#include "qgeocameradata.h" +#include "qgeomaptype.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QGeoCoordinate; + +class QGeoMappingManager; + +class QGeoTileCache; +class QGeoMapPrivate; +class MapItem; +class QGeoMapController; + +class QGLCamera; +class QGLPainter; + +class QPointF; + +class Q_LOCATION_EXPORT QGeoMap : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QGeoCameraData camera READ cameraData WRITE setCameraData NOTIFY cameraDataChanged) + Q_PROPERTY(QGeoMapType activeMapType READ activeMapType WRITE setActiveMapType NOTIFY activeMapTypeChanged) + +public: + QGeoMap(QGeoTileCache *cache, QObject *parent = 0); + virtual ~QGeoMap(); + + QGeoTileCache* tileCache(); + + void setMappingManager(QGeoMappingManager *manager); + + QGeoMapController* mapController(); + + QGLCamera* glCamera() const; + void paintGL(QGLPainter *painter); + + void resize(int width, int height); + int width() const; + int height() const; + + void setCameraData(const QGeoCameraData &cameraData); + QGeoCameraData cameraData() const; + + QGeoCoordinate screenPositionToCoordinate(const QPointF &pos, bool clipToViewport = true) const; + QPointF coordinateToScreenPosition(const QGeoCoordinate &coordinate, bool clipToViewport = true) const; + + void setActiveMapType(const QGeoMapType mapType); + const QGeoMapType activeMapType() const; + +public Q_SLOTS: + void update(); + +Q_SIGNALS: + void updateRequired(); + void cameraDataChanged(const QGeoCameraData &cameraData); + void activeMapTypeChanged(); + +private: + QGeoMapPrivate *d_ptr; + Q_DECLARE_PRIVATE(QGeoMap) + + friend class QGeoMappingManager; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QGEOMAP_H diff --git a/src/location/maps/qgeomap_p.h b/src/location/maps/qgeomap_p.h new file mode 100644 index 00000000..d8a4530c --- /dev/null +++ b/src/location/maps/qgeomap_p.h @@ -0,0 +1,254 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $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$ +** +****************************************************************************/ +#ifndef QGEOMAP_P_H +#define QGEOMAP_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QList> +#include <QSet> +#include <QVector> +#include <QPair> +#include <QPolygonF> +#include <QSizeF> +#include <QVector3D> +#include <QMatrix4x4> +#include <QString> + +#include "qgeocameradata.h" +#include "qgeofrustum_p.h" + +#include "qgeomaptype.h" + +#include <QSharedPointer> + +QT_BEGIN_NAMESPACE + +class QGeoMappingManager; + +class QGeoTile; +class QGeoTileCache; +class QGeoTileSpec; +class QGeoMap; +class QGeoMapController; +class QGeoMapSphere; +class QGeoProjection; + +class QGLCamera; +class QGLSceneNode; +class QGLPainter; + +class QGeoMapPrivate; + +struct TileMap +{ + TileMap(int minY, int maxY); + + int size; + int minY; + int maxY; + QVector<int> minX; + QVector<int> maxX; + + void adjust(int tileX, int tileY); +}; + +class IntersectGenerator +{ +public: + enum Axis { + XAxis, + YAxis + }; + IntersectGenerator(const QGeoMapPrivate *mp, + double p1, + double p2, + int t1, + int t2, + Axis axis, + int zoomLevel); + + bool hasNext() const; + QPair<double, int> value() const; + void next(); + +private: + void generateValue(); + +protected: + const QGeoMapPrivate *mp_; + Axis axis_; + int zoomLevel_; + + bool hasNext_; + QPair<double, int> value_; + + int current_; + int step_; + int end_; + + int adjust_; + double first_; + double denom_; +}; + +class QGeoMapPrivate +{ +public: + QGeoMapPrivate(QGeoMap *parent, QGeoTileCache *cache, int maxZoom, int tileSize); + virtual ~QGeoMapPrivate(); + + QGeoTileCache* tileCache(); + + void setMappingManager(QGeoMappingManager *manager); + + QGeoMapController* mapController(); + + QGLCamera* glCamera() const; + void paintGL(QGLPainter *painter); + + void setCameraData(const QGeoCameraData &cameraData); + QGeoCameraData cameraData() const; + + void resize(int width, int height); + int width() const; + int height() const; + double aspectRatio() const; + + QGLSceneNode* createTileSpecNode(const QGeoTileSpec &tileSpec); + QGLSceneNode* createTileNode(const QGeoTile &tile); + + QRect specToRect(const QGeoTileSpec &tileSpec) const; + + void update(); + + const QGeoMapType activeMapType() const; + void setActiveMapType(const QGeoMapType mapType); + + QGeoCoordinate screenPositionToCoordinate(const QPointF &pos) const; + QPointF coordinateToScreenPosition(const QGeoCoordinate &coordinate) const; + + QVector2D pointToTile(const QVector3D &point, int zoom, bool roundUp = false) const; + QVector3D tileXIntersectToPoint(int zoomLevel, int x) const; + QVector3D tileYIntersectToPoint(int zoomLevel, int y) const; + + void tileFetched(const QGeoTileSpec &spec); + +private: + void updateGlCamera(QGLCamera* glCamera); + void updateFrustum(QGeoFrustum &frustum); + QList<QGeoTileSpec> updateVisibleTiles(); + + int width_; + int height_; + double aspectRatio_; + + QGeoMap *map_; + QGeoTileCache* cache_; + QGeoMappingManager *manager_; + QString pluginString_; + QGeoMapController *controller_; + + QSharedPointer<QGeoProjection> projection_; + + QGLCamera *glCamera_; + + QGeoCameraData cameraData_; + QGeoFrustum frustum_; + QList<QGeoTileSpec> visibleTiles_; + + QGeoMapSphere *sphere_; + QGeoMapType activeMapType_; + + // from map2d_p.h + + void tilesFromLine(const QVector3D &p1, + const QVector3D &p2, + const QVector2D &t1, + const QVector2D &t2, + int zoomLevel, + TileMap &map) const; + + QList<QGeoTileSpec> tilesFromPoints(const QVector<QVector3D> &points, bool roundUp) const; + + QPair<QList<QVector3D>,QList<QVector3D> > clipPolygonToMap(const QList<QVector3D> &points) const; + + class LengthSorter { + public: + QVector3D base; + bool operator()(const QVector3D &lhs, const QVector3D &rhs) { + return (lhs - base).lengthSquared() < (rhs - base).lengthSquared(); + } + }; + + QList<QVector3D> pointsOnLineWithX(const QVector3D &p1, const QVector3D &p2, double x) const; + QList<QVector3D> pointsOnLineWithY(const QVector3D &p1, const QVector3D &p2, double y) const; + QList<QVector3D> pointsOnLineWithZ(const QVector3D &p1, const QVector3D &p2, double z) const; + + QPair<QList<QVector3D>,QList<QVector3D> > splitPolygonX(const QList<QVector3D> &points, double x) const; + QPair<QList<QVector3D>,QList<QVector3D> > splitPolygonY(const QList<QVector3D> &points, double y) const; + + int maxZoom_; + int tileSize_; + + double baseHeight_; + double sideLength_; + QPolygonF screenPoly_; + QPolygonF screenPolyLeft_; + QPolygonF screenPolyRight_; + + QSizeF viewSize_; + QVector3D eye_; + QMatrix4x4 projectionMatrix_; +}; + +QT_END_NAMESPACE + +#endif // QGEOMAP_P_H diff --git a/src/location/maps/qgeomapcontroller.cpp b/src/location/maps/qgeomapcontroller.cpp new file mode 100644 index 00000000..43473e64 --- /dev/null +++ b/src/location/maps/qgeomapcontroller.cpp @@ -0,0 +1,234 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $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 "qgeomapcontroller.h" + +#include "qgeomap.h" +#include "qgeoprojection_p.h" + +#include <QPointF> + +#include <QVariant> +#include <QVariantAnimation> + +QVariant coordinateInterpolator(const AnimatableCoordinate &start, + const AnimatableCoordinate &end, + qreal progress) +{ + AnimatableCoordinate result; + + QSharedPointer<QGeoProjection> p = start.projection(); + if (!p) + p = end.projection(); + + if (!p) + result.setCoordinate(start.coordinate()); + else + result.setCoordinate(p->interpolate(start.coordinate(), + end.coordinate(), + progress)); + + result.setProjection(p); + + return QVariant::fromValue(result); +} + +AnimatableCoordinate::AnimatableCoordinate() {} + +AnimatableCoordinate::AnimatableCoordinate(const QGeoCoordinate &coordinate, + QSharedPointer<QGeoProjection> projection) + : coordinate_(coordinate), + projection_(projection) +{ +} + +QGeoCoordinate AnimatableCoordinate::coordinate() const +{ + return coordinate_; +} + +void AnimatableCoordinate::setCoordinate(const QGeoCoordinate &coordinate) +{ + coordinate_ = coordinate; +} + +QSharedPointer<QGeoProjection> AnimatableCoordinate::projection() const +{ + return projection_; +} + +void AnimatableCoordinate::setProjection(QSharedPointer<QGeoProjection> projection) +{ + projection_ = projection; +} + +QGeoMapController::QGeoMapController(QGeoMap *map, QSharedPointer<QGeoProjection> projection) + : QObject(map), + map_(map), + projection_(projection) +{ + qRegisterMetaType<AnimatableCoordinate>(); + qRegisterAnimationInterpolator<AnimatableCoordinate>(coordinateInterpolator); + + oldCameraData_ = map_->cameraData(); + + connect(map, + SIGNAL(cameraDataChanged(QGeoCameraData)), + this, + SLOT(cameraDataChanged(QGeoCameraData))); +} + +QGeoMapController::~QGeoMapController() {} + +void QGeoMapController::cameraDataChanged(const QGeoCameraData &cameraData) +{ + if (oldCameraData_.center() != cameraData.center()) + emit centerChanged(AnimatableCoordinate(cameraData.center(), projection_)); + + if (oldCameraData_.bearing() != cameraData.bearing()) + emit bearingChanged(cameraData.bearing()); + + if (oldCameraData_.tilt() != cameraData.tilt()) + emit tiltChanged(cameraData.tilt()); + + if (oldCameraData_.roll() != cameraData.roll()) + emit rollChanged(cameraData.roll()); + + if (oldCameraData_.zoomFactor() != cameraData.zoomFactor()) + emit zoomChanged(cameraData.zoomFactor()); + + oldCameraData_ = cameraData; +} + +AnimatableCoordinate QGeoMapController::center() const +{ + return AnimatableCoordinate(map_->cameraData().center(), projection_); +} + +void QGeoMapController::setCenter(const AnimatableCoordinate ¢er) +{ + QGeoCameraData cd = map_->cameraData(); + + if (center.coordinate() == cd.center()) + return; + + cd.setCenter(center.coordinate()); + map_->setCameraData(cd); +} + +qreal QGeoMapController::bearing() const +{ + return map_->cameraData().bearing(); +} + +void QGeoMapController::setBearing(qreal bearing) +{ + QGeoCameraData cd = map_->cameraData(); + + if (bearing == cd.bearing()) + return; + + cd.setBearing(bearing); + map_->setCameraData(cd); +} + +qreal QGeoMapController::tilt() const +{ + return map_->cameraData().tilt(); +} + +void QGeoMapController::setTilt(qreal tilt) +{ + QGeoCameraData cd = map_->cameraData(); + + if (tilt == cd.tilt()) + return; + + cd.setTilt(tilt); + map_->setCameraData(cd); +} + +qreal QGeoMapController::roll() const +{ + return map_->cameraData().roll(); +} + +void QGeoMapController::setRoll(qreal roll) +{ + QGeoCameraData cd = map_->cameraData(); + + if (roll == cd.roll()) + return; + + cd.setRoll(roll); + map_->setCameraData(cd); +} + +qreal QGeoMapController::zoom() const +{ + return map_->cameraData().zoomFactor(); +} + +void QGeoMapController::setZoom(qreal zoom) +{ + QGeoCameraData cd = map_->cameraData(); + + if (zoom == cd.zoomFactor()) + return; + + cd.setZoomFactor(zoom); + map_->setCameraData(cd); +} + +void QGeoMapController::pan(qreal dx, qreal dy) +{ + if (dx == 0 && dy == 0) + return; + QGeoCameraData cd = map_->cameraData(); + QGeoCoordinate coord = map_->screenPositionToCoordinate( + QPointF(map_->width() / 2 + dx, + map_->height() / 2 - dy)); + + if (coord.isValid()) { + cd.setCenter(coord); + map_->setCameraData(cd); + } +} diff --git a/src/location/maps/qgeomapcontroller.h b/src/location/maps/qgeomapcontroller.h new file mode 100644 index 00000000..a0605f03 --- /dev/null +++ b/src/location/maps/qgeomapcontroller.h @@ -0,0 +1,122 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $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$ +** +****************************************************************************/ + +#ifndef QGEOMAPCONTROLLER_H +#define QGEOMAPCONTROLLER_H + +#include <QObject> + +#include "qgeocoordinate.h" +#include "qgeocameradata.h" + +QT_BEGIN_NAMESPACE + +class QGeoMap; + +class Q_LOCATION_EXPORT AnimatableCoordinate { +public: + AnimatableCoordinate(); + AnimatableCoordinate(const QGeoCoordinate &coordinate, + QSharedPointer<QGeoProjection> projection); + + QGeoCoordinate coordinate() const; + void setCoordinate(const QGeoCoordinate &coordinate); + + QSharedPointer<QGeoProjection> projection() const; + void setProjection(QSharedPointer<QGeoProjection> projection); + +private: + QGeoCoordinate coordinate_; + QSharedPointer<QGeoProjection> projection_; +}; + +class Q_LOCATION_EXPORT QGeoMapController : public QObject +{ + Q_OBJECT + + Q_PROPERTY(AnimatableCoordinate center READ center WRITE setCenter NOTIFY centerChanged) + Q_PROPERTY(qreal bearing READ bearing WRITE setBearing NOTIFY bearingChanged) + Q_PROPERTY(qreal tilt READ tilt WRITE setTilt NOTIFY tiltChanged) + Q_PROPERTY(qreal roll READ roll WRITE setRoll NOTIFY rollChanged) + Q_PROPERTY(qreal zoom READ zoom WRITE setZoom NOTIFY zoomChanged) + +public: + QGeoMapController(QGeoMap *map, QSharedPointer<QGeoProjection> projection); + ~QGeoMapController(); + + AnimatableCoordinate center() const; + void setCenter(const AnimatableCoordinate ¢er); + + qreal bearing() const; + void setBearing(qreal bearing); + + qreal tilt() const; + void setTilt(qreal tilt); + + qreal roll() const; + void setRoll(qreal roll); + + qreal zoom() const; + void setZoom(qreal zoom); + + void pan(qreal dx, qreal dy); + +private slots: + void cameraDataChanged(const QGeoCameraData &cameraData); + +signals: + void centerChanged(const AnimatableCoordinate ¢er); + void bearingChanged(qreal bearing); + void tiltChanged(qreal tilt); + void rollChanged(qreal roll); + void zoomChanged(qreal zoom); + +private: + QGeoMap *map_; + QSharedPointer<QGeoProjection> projection_; + QGeoCameraData oldCameraData_; +}; + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(AnimatableCoordinate) + +#endif // QGEOMAPCONTROLLER_H diff --git a/src/location/maps/qgeomappingmanager.cpp b/src/location/maps/qgeomappingmanager.cpp index fa4bb749..c40893ec 100644 --- a/src/location/maps/qgeomappingmanager.cpp +++ b/src/location/maps/qgeomappingmanager.cpp @@ -45,10 +45,10 @@ #include "qgeotiledmapreply.h" -#include "map.h" -#include "map_p.h" -#include "tilecache.h" -#include "tilespec.h" +#include "qgeomap.h" +#include "qgeomap_p.h" +#include "qgeotilecache.h" +#include "qgeotilespec.h" #include <QTimer> #include <QNetworkProxy> @@ -103,17 +103,17 @@ QGeoMappingManager::QGeoMappingManager(QGeoMappingManagerEngine *engine, QObject d_ptr->thread= new QThread; - qRegisterMetaType<TileSpec>(); + qRegisterMetaType<QGeoTileSpec>(); connect(d_ptr->engine, - SIGNAL(tileFinished(TileSpec,QByteArray)), + SIGNAL(tileFinished(QGeoTileSpec,QByteArray)), this, - SLOT(engineTileFinished(TileSpec,QByteArray)), + SLOT(engineTileFinished(QGeoTileSpec,QByteArray)), Qt::QueuedConnection); connect(d_ptr->engine, - SIGNAL(tileError(TileSpec,QString)), + SIGNAL(tileError(QGeoTileSpec,QString)), this, - SLOT(engineTileError(TileSpec,QString)), + SLOT(engineTileError(QGeoTileSpec,QString)), Qt::QueuedConnection); connect(d_ptr->engine, @@ -180,15 +180,15 @@ int QGeoMappingManager::managerVersion() const return d_ptr->engine->managerVersion(); } -void QGeoMappingManager::registerMap(Map *map) +void QGeoMappingManager::registerMap(QGeoMap *map) { - TileCache *cache = map->tileCache(); - QSet<Map*> maps = d_ptr->caches.value(cache); + QGeoTileCache *cache = map->tileCache(); + QSet<QGeoMap*> maps = d_ptr->caches.value(cache); maps.insert(map); d_ptr->caches.insert(cache, maps); } -void QGeoMappingManager::deregisterMap(Map *map) +void QGeoMappingManager::deregisterMap(QGeoMap *map) { Q_UNUSED(map); // TileCache *cache = map->tileCache(); @@ -203,15 +203,15 @@ void QGeoMappingManager::deregisterMap(Map *map) // clear any tileHash / mapHash entries } -void QGeoMappingManager::updateTileRequests(Map *map, - const QSet<TileSpec> &tilesAdded, - const QSet<TileSpec> &tilesRemoved) +void QGeoMappingManager::updateTileRequests(QGeoMap *map, + const QSet<QGeoTileSpec> &tilesAdded, + const QSet<QGeoTileSpec> &tilesRemoved) { - typedef QSet<TileSpec>::const_iterator tile_iter; + typedef QSet<QGeoTileSpec>::const_iterator tile_iter; // add and remove tiles from tileset for this map - QSet<TileSpec> oldTiles = d_ptr->mapHash.value(map); + QSet<QGeoTileSpec> oldTiles = d_ptr->mapHash.value(map); tile_iter rem = tilesRemoved.constBegin(); tile_iter remEnd = tilesRemoved.constEnd(); @@ -229,12 +229,12 @@ void QGeoMappingManager::updateTileRequests(Map *map, // add and remove map from mapset for the tiles - QSet<TileSpec> reqTiles; - QSet<TileSpec> cancelTiles; + QSet<QGeoTileSpec> reqTiles; + QSet<QGeoTileSpec> cancelTiles; rem = tilesRemoved.constBegin(); for (; rem != remEnd; ++rem) { - QSet<Map*> mapSet = d_ptr->tileHash.value(*rem); + QSet<QGeoMap*> mapSet = d_ptr->tileHash.value(*rem); mapSet.remove(map); if (mapSet.isEmpty()) { cancelTiles.insert(*rem); @@ -246,7 +246,7 @@ void QGeoMappingManager::updateTileRequests(Map *map, add = tilesAdded.constBegin(); for (; add != addEnd; ++add) { - QSet<Map*> mapSet = d_ptr->tileHash.value(*add); + QSet<QGeoMap*> mapSet = d_ptr->tileHash.value(*add); if (mapSet.isEmpty()) { reqTiles.insert(*add); } @@ -258,24 +258,24 @@ void QGeoMappingManager::updateTileRequests(Map *map, QMetaObject::invokeMethod(d_ptr->engine, "updateTileRequests", Qt::QueuedConnection, - Q_ARG(QSet<TileSpec>, reqTiles), - Q_ARG(QSet<TileSpec>, cancelTiles)); + Q_ARG(QSet<QGeoTileSpec>, reqTiles), + Q_ARG(QSet<QGeoTileSpec>, cancelTiles)); } -void QGeoMappingManager::engineTileFinished(const TileSpec &spec, const QByteArray &bytes) +void QGeoMappingManager::engineTileFinished(const QGeoTileSpec &spec, const QByteArray &bytes) { - QSet<TileCache*> caches; + QSet<QGeoTileCache*> caches; - QSet<Map*> maps = d_ptr->tileHash.value(spec); + QSet<QGeoMap*> maps = d_ptr->tileHash.value(spec); - typedef QSet<Map*>::const_iterator map_iter; + typedef QSet<QGeoMap*>::const_iterator map_iter; map_iter map = maps.constBegin(); map_iter mapEnd = maps.constEnd(); for (; map != mapEnd; ++map) { caches.insert((*map)->tileCache()); - QSet<TileSpec> tileSet = d_ptr->mapHash.value(*map); + QSet<QGeoTileSpec> tileSet = d_ptr->mapHash.value(*map); tileSet.remove(spec); if (tileSet.isEmpty()) d_ptr->mapHash.remove(*map); @@ -285,7 +285,7 @@ void QGeoMappingManager::engineTileFinished(const TileSpec &spec, const QByteArr d_ptr->tileHash.remove(spec); - typedef QSet<TileCache*>::const_iterator cache_iter; + typedef QSet<QGeoTileCache*>::const_iterator cache_iter; cache_iter cache = caches.constBegin(); cache_iter cacheEnd = caches.constEnd(); @@ -299,12 +299,12 @@ void QGeoMappingManager::engineTileFinished(const TileSpec &spec, const QByteArr } } -void QGeoMappingManager::engineTileError(const TileSpec &spec, const QString &errorString) +void QGeoMappingManager::engineTileError(const QGeoTileSpec &spec, const QString &errorString) { emit tileError(spec, errorString); } -QList<MapType> QGeoMappingManager::supportedMapTypes() const +QList<QGeoMapType> QGeoMappingManager::supportedMapTypes() const { return d_ptr->engine->supportedMapTypes(); } @@ -410,7 +410,7 @@ QLocale QGeoMappingManager::locale() const return d_ptr->engine->locale(); } -TileCache::CacheAreas QGeoMappingManager::cacheHint() const +QGeoTileCache::CacheAreas QGeoMappingManager::cacheHint() const { return d_ptr->engine->cacheHint(); } diff --git a/src/location/maps/qgeomappingmanager.h b/src/location/maps/qgeomappingmanager.h index 3c810ddf..84cf62f0 100644 --- a/src/location/maps/qgeomappingmanager.h +++ b/src/location/maps/qgeomappingmanager.h @@ -46,8 +46,8 @@ #include <QSize> #include <QPair> #include <QtLocation/qlocationglobal.h> -#include "maptype.h" -#include "tilecache.h" +#include "qgeomaptype.h" +#include "qgeotilecache.h" QT_BEGIN_HEADER @@ -61,8 +61,8 @@ class QGeoMapRequestOptions; class QGeoMappingManagerEngine; class QGeoTiledMapReply; -class TileSpec; -class Map; +class QGeoTileSpec; +class QGeoMap; class Q_LOCATION_EXPORT QGeoMappingManager : public QObject { @@ -74,14 +74,14 @@ public: QString managerName() const; int managerVersion() const; - void registerMap(Map *map); - void deregisterMap(Map *map); + void registerMap(QGeoMap *map); + void deregisterMap(QGeoMap *map); - void updateTileRequests(Map *map, - const QSet<TileSpec> &tilesAdded, - const QSet<TileSpec> &tilesRemoved); + void updateTileRequests(QGeoMap *map, + const QSet<QGeoTileSpec> &tilesAdded, + const QSet<QGeoTileSpec> &tilesRemoved); - QList<MapType> supportedMapTypes() const; + QList<QGeoMapType> supportedMapTypes() const; // QList<QGraphicsGeoMap::ConnectivityMode> supportedConnectivityModes() const; qreal minimumZoomLevel() const; @@ -94,18 +94,18 @@ public: qreal minimumTilt() const; qreal maximumTilt() const; - TileCache::CacheAreas cacheHint() const; + QGeoTileCache::CacheAreas cacheHint() const; void setLocale(const QLocale &locale); QLocale locale() const; private Q_SLOTS: - void engineTileFinished(const TileSpec &spec, const QByteArray &bytes); - void engineTileError(const TileSpec &spec, const QString &errorString); + void engineTileFinished(const QGeoTileSpec &spec, const QByteArray &bytes); + void engineTileError(const QGeoTileSpec &spec, const QString &errorString); Q_SIGNALS: - void tileFinished(const TileSpec &spec, const QByteArray &bytes); - void tileError(const TileSpec &spec, const QString &errorString); + void tileFinished(const QGeoTileSpec &spec, const QByteArray &bytes); + void tileError(const QGeoTileSpec &spec, const QString &errorString); void initialized(); private: diff --git a/src/location/maps/qgeomappingmanager_p.h b/src/location/maps/qgeomappingmanager_p.h index 124b51d2..68d49dbd 100644 --- a/src/location/maps/qgeomappingmanager_p.h +++ b/src/location/maps/qgeomappingmanager_p.h @@ -59,9 +59,9 @@ #include <QSet> #include <QThread> -class Map; -class TileCache; -class TileSpec; +class QGeoMap; +class QGeoTileCache; +class QGeoTileSpec; QT_BEGIN_NAMESPACE @@ -76,9 +76,9 @@ public: QThread *thread; QGeoMappingManagerEngine *engine; - QHash<TileCache*, QSet<Map*> > caches; - QHash<Map*, QSet<TileSpec> > mapHash; - QHash<TileSpec, QSet<Map*> > tileHash; + QHash<QGeoTileCache*, QSet<QGeoMap*> > caches; + QHash<QGeoMap*, QSet<QGeoTileSpec> > mapHash; + QHash<QGeoTileSpec, QSet<QGeoMap*> > tileHash; private: Q_DISABLE_COPY(QGeoMappingManagerPrivate) diff --git a/src/location/maps/qgeomappingmanagerengine.cpp b/src/location/maps/qgeomappingmanagerengine.cpp index a79db933..a03e7994 100644 --- a/src/location/maps/qgeomappingmanagerengine.cpp +++ b/src/location/maps/qgeomappingmanagerengine.cpp @@ -42,7 +42,7 @@ #include "qgeomappingmanagerengine.h" #include "qgeomappingmanagerengine_p.h" #include "qgeotiledmapreply.h" -#include "tilespec.h" +#include "qgeotilespec.h" #include <QThread> #include <QNetworkProxy> @@ -155,8 +155,8 @@ void QGeoMappingManagerEngine::threadFinished() this->deleteLater(); } -void QGeoMappingManagerEngine::updateTileRequests(const QSet<TileSpec> &tilesAdded, - const QSet<TileSpec> &tilesRemoved) +void QGeoMappingManagerEngine::updateTileRequests(const QSet<QGeoTileSpec> &tilesAdded, + const QSet<QGeoTileSpec> &tilesRemoved) { Q_D(QGeoMappingManagerEngine); @@ -171,11 +171,11 @@ void QGeoMappingManagerEngine::updateTileRequests(const QSet<TileSpec> &tilesAdd d->timer_->start(); } -void QGeoMappingManagerEngine::cancelTileRequests(const QSet<TileSpec> &tiles) +void QGeoMappingManagerEngine::cancelTileRequests(const QSet<QGeoTileSpec> &tiles) { Q_D(QGeoMappingManagerEngine); - typedef QSet<TileSpec>::const_iterator tile_iter; + typedef QSet<QGeoTileSpec>::const_iterator tile_iter; tile_iter tile = tiles.constBegin(); tile_iter end = tiles.constEnd(); for (; tile != end; ++tile) { @@ -204,7 +204,7 @@ void QGeoMappingManagerEngine::requestNextTile() return; } - TileSpec ts = d->queue_.takeFirst(); + QGeoTileSpec ts = d->queue_.takeFirst(); QGeoTiledMapReply *reply = getTileImage(ts); @@ -231,7 +231,7 @@ void QGeoMappingManagerEngine::finished() if (!reply) return; - TileSpec spec = reply->tileSpec(); + QGeoTileSpec spec = reply->tileSpec(); if (!d->invmap_.contains(spec)) { reply->deleteLater(); @@ -243,7 +243,7 @@ void QGeoMappingManagerEngine::finished() handleReply(reply, spec); } -void QGeoMappingManagerEngine::handleReply(QGeoTiledMapReply *reply, const TileSpec &spec) +void QGeoMappingManagerEngine::handleReply(QGeoTiledMapReply *reply, const QGeoTileSpec &spec) { Q_D(QGeoMappingManagerEngine); @@ -308,7 +308,7 @@ int QGeoMappingManagerEngine::managerVersion() const return d_ptr->managerVersion; } -QList<MapType> QGeoMappingManagerEngine::supportedMapTypes() const +QList<QGeoMapType> QGeoMappingManagerEngine::supportedMapTypes() const { Q_D(const QGeoMappingManagerEngine); return d->supportedMapTypes; @@ -320,7 +320,7 @@ QList<MapType> QGeoMappingManagerEngine::supportedMapTypes() const Subclasses of QGeoMappingManagerEngine should use this function to ensure that supportedMapTypes() provides accurate information. */ -void QGeoMappingManagerEngine::setSupportedMapTypes(const QList<MapType> &supportedMapTypes) +void QGeoMappingManagerEngine::setSupportedMapTypes(const QList<QGeoMapType> &supportedMapTypes) { Q_D(QGeoMappingManagerEngine); d->supportedMapTypes = supportedMapTypes; @@ -564,13 +564,13 @@ QLocale QGeoMappingManagerEngine::locale() const return d_ptr->locale; } -TileCache::CacheAreas QGeoMappingManagerEngine::cacheHint() const +QGeoTileCache::CacheAreas QGeoMappingManagerEngine::cacheHint() const { Q_D(const QGeoMappingManagerEngine); return d->cacheHint; } -void QGeoMappingManagerEngine::setCacheHint(TileCache::CacheAreas cacheHint) +void QGeoMappingManagerEngine::setCacheHint(QGeoTileCache::CacheAreas cacheHint) { Q_D(QGeoMappingManagerEngine); d->cacheHint = cacheHint; @@ -587,7 +587,7 @@ QGeoMappingManagerEnginePrivate::QGeoMappingManagerEnginePrivate() supportsTilting(false), minimumTilt(0.0), maximumTilt(0.0), - cacheHint(TileCache::AllCaches), + cacheHint(QGeoTileCache::AllCaches), started_(false), stopped_(false) {} diff --git a/src/location/maps/qgeomappingmanagerengine.h b/src/location/maps/qgeomappingmanagerengine.h index 633654d4..0442cb01 100644 --- a/src/location/maps/qgeomappingmanagerengine.h +++ b/src/location/maps/qgeomappingmanagerengine.h @@ -46,8 +46,8 @@ #include <QSize> #include <QPair> #include <QtLocation/qlocationglobal.h> -#include "maptype.h" -#include "tilecache.h" +#include "qgeomaptype.h" +#include "qgeotilecache.h" QT_BEGIN_HEADER @@ -66,7 +66,7 @@ class QGeoMapRequestOptions; class QGeoMappingManagerEnginePrivate; class QGeoTiledMapReply; -class TileSpec; +class QGeoTileSpec; class Q_LOCATION_EXPORT QGeoMappingManagerEngine : public QObject { @@ -81,7 +81,7 @@ public: QString managerName() const; int managerVersion() const; - QList<MapType> supportedMapTypes() const; + QList<QGeoMapType> supportedMapTypes() const; // QList<QGraphicsGeoMap::ConnectivityMode> supportedConnectivityModes() const; QSize tileSize() const; @@ -95,7 +95,7 @@ public: qreal minimumTilt() const; qreal maximumTilt() const; - TileCache::CacheAreas cacheHint() const; + QGeoTileCache::CacheAreas cacheHint() const; void setLocale(const QLocale &locale); QLocale locale() const; @@ -106,22 +106,22 @@ public: public Q_SLOTS: void threadStarted(); void threadFinished(); - void updateTileRequests(const QSet<TileSpec> &tilesAdded, const QSet<TileSpec> &tilesRemoved); - void cancelTileRequests(const QSet<TileSpec> &tiles); + void updateTileRequests(const QSet<QGeoTileSpec> &tilesAdded, const QSet<QGeoTileSpec> &tilesRemoved); + void cancelTileRequests(const QSet<QGeoTileSpec> &tiles); private Q_SLOTS: void requestNextTile(); void finished(); Q_SIGNALS: - void tileFinished(const TileSpec &spec, const QByteArray &bytes); - void tileError(const TileSpec &spec, const QString &errorString); + void tileFinished(const QGeoTileSpec &spec, const QByteArray &bytes); + void tileError(const QGeoTileSpec &spec, const QString &errorString); void initialized(); protected: QGeoMappingManagerEngine(QGeoMappingManagerEnginePrivate *dd, QObject *parent = 0); - void setSupportedMapTypes(const QList<MapType> &supportedMapTypes); + void setSupportedMapTypes(const QList<QGeoMapType> &supportedMapTypes); // void setSupportedConnectivityModes(const QList<QGraphicsGeoMap::ConnectivityMode> &connectivityModes); void setTileSize(const QSize &tileSize); @@ -135,14 +135,14 @@ protected: void setSupportsBearing(bool supportsBearing); void setSupportsTilting(bool supportsTilting); - void setCacheHint(TileCache::CacheAreas cacheHint); + void setCacheHint(QGeoTileCache::CacheAreas cacheHint); QGeoMappingManagerEnginePrivate* d_ptr; private: - virtual QGeoTiledMapReply* getTileImage(const TileSpec &spec) = 0; + virtual QGeoTiledMapReply* getTileImage(const QGeoTileSpec &spec) = 0; - void handleReply(QGeoTiledMapReply *reply, const TileSpec &spec); + void handleReply(QGeoTiledMapReply *reply, const QGeoTileSpec &spec); void setManagerName(const QString &managerName); void setManagerVersion(int managerVersion); diff --git a/src/location/maps/qgeomappingmanagerengine_p.h b/src/location/maps/qgeomappingmanagerengine_p.h index f4a66958..3c73a4ad 100644 --- a/src/location/maps/qgeomappingmanagerengine_p.h +++ b/src/location/maps/qgeomappingmanagerengine_p.h @@ -60,10 +60,10 @@ #include <QMap> #include <QLocale> #include <QTimer> -#include "maptype.h" -#include "tilecache.h" +#include "qgeomaptype.h" +#include "qgeotilecache.h" -class TileSpec; +class QGeoTileSpec; class QGeoTiledMapReply; QT_BEGIN_NAMESPACE @@ -79,7 +79,7 @@ public: QString managerName; int managerVersion; - QList<MapType> supportedMapTypes; + QList<QGeoMapType> supportedMapTypes; // QList<QGraphicsGeoMap::ConnectivityMode> supportedConnectivityModes; QSize tileSize; qreal minimumZoomLevel; @@ -88,15 +88,15 @@ public: bool supportsTilting; qreal minimumTilt; qreal maximumTilt; - TileCache::CacheAreas cacheHint; + QGeoTileCache::CacheAreas cacheHint; QLocale locale; bool started_; bool initialized; bool stopped_; QTimer *timer_; - QList<TileSpec> queue_; - QHash<TileSpec, QGeoTiledMapReply*> invmap_; + QList<QGeoTileSpec> queue_; + QHash<QGeoTileSpec, QGeoTiledMapReply*> invmap_; private: Q_DISABLE_COPY(QGeoMappingManagerEnginePrivate) diff --git a/src/location/maps/qgeomapsphere.cpp b/src/location/maps/qgeomapsphere.cpp new file mode 100644 index 00000000..e8cb922e --- /dev/null +++ b/src/location/maps/qgeomapsphere.cpp @@ -0,0 +1,227 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $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 "qgeomapsphere_p.h" + +#include "qgeotilecache.h" +#include "qgeotile.h" +#include "qgeomap.h" +#include "qgeomap_p.h" + +#include "qgeomappingmanager.h" + +#include <QOpenGLFramebufferObject> + +#include <Qt3D/qglscenenode.h> +#include <Qt3D/qglframebufferobjectsurface.h> +#include <Qt3D/qglcamera.h> +#include <Qt3D/qglpainter.h> + +#include <QVector> +#include <QTimer> + +QGeoMapSphere::QGeoMapSphere(QGeoMap* map, QGeoMapPrivate *mapPrivate, QGeoTileCache *tileCache) + : QObject(0), + tileCache_(tileCache), + map_(map), + mapPrivate_(mapPrivate), + manager_(0) +{ + + sphereNode_ = new QGLSceneNode(this); + + connect(this, + SIGNAL(tileUpdated()), + map, + SIGNAL(updateRequired())); +} + +QGeoMapSphere::~QGeoMapSphere() +{ + QList<QGLSceneNode*> nodes = built_.values(); + for (int i = 0; i < nodes.size(); ++i) { + QGLSceneNode *node = nodes.at(i); + //node->material()->texture()->release(); + node->geometry().clear(); + sphereNode_->removeNode(node); + delete node; + } +} + +void QGeoMapSphere::setMappingManager(QGeoMappingManager *manager) +{ + manager_ = manager; +} + +QGLSceneNode* QGeoMapSphere::sphereSceneNode() const +{ + return sphereNode_; +} + +// Function to perform housekeeping that require access to GL context +// (access to GL context varies depending on if we are running as +// c++ app or QML app). +// +// Function is guaranteed to be only called when executing in +// rendering thread with valid GL context. Furthermore it is +// safe to update any geometry/structures - mutex is locked. +void QGeoMapSphere::GLContextAvailable() +{ + // need something like this in the cache for + // releasing textures and freeing nodes that + // have been evicted from the GPU + tileCache_->GLContextAvailable(sphereNode_); +// qDeleteAll(obsoleteNodes_); +// obsoleteNodes_.clear(); +} + +void QGeoMapSphere::update(const QList<QGeoTileSpec> &tiles) +{ + QHash<QGeoTileSpec, QGLSceneNode*> stillBuilt; + + QVector<QGeoTileSpec> req(tiles.size()); + QVector<QGeoTileSpec> draw(tiles.size()); + + QSet<QGeoTileSpec> cancelTiles = requested_ - tiles.toSet(); + + int reqSize = 0; + int drawSize = 0; + QList<QGeoTileSpec>::const_iterator i = tiles.constBegin(); + QList<QGeoTileSpec>::const_iterator tilesEnd = tiles.constEnd(); + while (i != tilesEnd) { + /* + If the tile is already built or has been requested then we + shouldn't use it (where "use" means drawing a cached tile or + requested an uncached tile). + */ + if (built_.contains(*i)) { + stillBuilt.insert(*i, built_.value(*i)); + } else if (!requested_.contains(*i)){ + /* + Otherwise we add it to the correct list + */ + if (tileCache_->contains(*i)) { + draw[drawSize] = *i; + ++drawSize; + } else { + req[reqSize] = *i; + ++reqSize; + requested_.insert(*i); + } + } + + ++i; + } + + req.resize(reqSize); + + updateMutex.lock(); + + QHash<QGeoTileSpec, QGLSceneNode*>::const_iterator j = built_.constBegin(); + QHash<QGeoTileSpec, QGLSceneNode*>::const_iterator end = built_.constEnd(); + while (j != end) { + QGeoTileSpec spec = j.key(); + if (!stillBuilt.contains(spec)) { + sphereNode_->removeNode(j.value()); + } + ++j; + } + built_.swap(stillBuilt); + + updateMutex.unlock(); + + for (int i = 0; i < drawSize; ++i) + displayTile(draw.at(i)); + + if (req.isEmpty()) { + emit tileUpdated(); + } else { + if (manager_) { + manager_->updateTileRequests(map_, req.toList().toSet(), cancelTiles); + } + } +} + +void QGeoMapSphere::tileFetched(const QGeoTileSpec &spec) +{ + if (!requested_.contains(spec)) + return; + + displayTile(spec); + + requested_.remove(spec); + + emit tileUpdated(); +} + +void QGeoMapSphere::displayTile(const QGeoTileSpec &spec) +{ + if (built_.contains(spec)) + return; + + updateMutex.lock(); + QGeoTile tile = tileCache_->get(spec); + QGLSceneNode *node = tile.sceneNode(); + if (!node) { + node = mapPrivate_->createTileNode(tile); + tile.setSceneNode(node); + tile.bind(); + tileCache_->update(spec, tile); + } + if (node) { + sphereNode_->addNode(node); + built_.insert(spec, node); + } + updateMutex.unlock(); +} + +void QGeoMapSphere::paintGL(QGLPainter *painter) +{ + if (!updateMutex.tryLock()) { + qWarning() << "----- map will miss a frame, no mutex acquired!------"; + return; + } + + GLContextAvailable(); + + sphereNode_->draw(painter); + + updateMutex.unlock(); +} diff --git a/src/location/maps/qgeomapsphere_p.h b/src/location/maps/qgeomapsphere_p.h new file mode 100644 index 00000000..53f2d081 --- /dev/null +++ b/src/location/maps/qgeomapsphere_p.h @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $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$ +** +****************************************************************************/ +#ifndef QGEOMAPSPHERE_H +#define QGEOMAPSPHERE_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtLocation/qlocationglobal.h> +#include "qgeotilespec.h" + +#include <QObject> +#include <QSet> +#include <QHash> +#include <QList> +#include <QCache> +#include <QSharedPointer> + +#include <QMutex> + +QT_BEGIN_NAMESPACE + +class QGLSceneNode; +class QGLPainter; + +class QOpenGLFramebufferObject; + +class QGeoTileSpec; +class QGeoTileCache; + +class QGeoMap; +class QGeoMapPrivate; + +class QGeoMappingManager; + +class Q_LOCATION_EXPORT QGeoMapSphere : public QObject +{ + Q_OBJECT +public: + QGeoMapSphere(QGeoMap* map, QGeoMapPrivate *mapPrivate, QGeoTileCache *tileCache); + ~QGeoMapSphere(); + + void setMappingManager(QGeoMappingManager *manager); + + QGLSceneNode* sphereSceneNode() const; + + QMutex updateMutex; + // when running as QML app we can't access GL context anywhere + // but QSG rendering thread. + void GLContextAvailable(); + + void paintGL(QGLPainter *painter); + + void tileFetched(const QGeoTileSpec &spec); + +public Q_SLOTS: + void update(const QList<QGeoTileSpec> &tiles); + +Q_SIGNALS: + void tileUpdated(); + +private: + void displayTile(const QGeoTileSpec &spec); + + QList<QGeoTileSpec> visibleTiles_; + + QGeoTileCache *tileCache_; + int minZoom_; + + QSet<QGeoTileSpec> requested_; + QHash<QGeoTileSpec, QGLSceneNode*> built_; + + QGLSceneNode* sphereNode_; + + QGeoMap *map_; + QGeoMapPrivate* mapPrivate_; + QGeoMappingManager *manager_; +}; + +QT_END_NAMESPACE + +#endif // QGEOMAPSPHERE_H diff --git a/src/location/maps/qgeomaptype.cpp b/src/location/maps/qgeomaptype.cpp new file mode 100644 index 00000000..cdb6241c --- /dev/null +++ b/src/location/maps/qgeomaptype.cpp @@ -0,0 +1,132 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $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 "qgeomaptype.h" +#include "qgeomaptype_p.h" + +QT_BEGIN_NAMESPACE + +QGeoMapType::QGeoMapType() + : d_ptr(new QGeoMapTypePrivate()) {} + +QGeoMapType::QGeoMapType(const QGeoMapType &other) + : d_ptr(other.d_ptr) {} + +QGeoMapType::QGeoMapType(QGeoMapType::MapStyle style, const QString &name, const QString &description, bool mobile, int mapId) + : d_ptr(new QGeoMapTypePrivate(style, name, description, mobile, mapId)) {} + +QGeoMapType::~QGeoMapType() {} + +QGeoMapType& QGeoMapType::operator = (const QGeoMapType &other) +{ + d_ptr = other.d_ptr; + return *this; +} + +bool QGeoMapType::operator == (const QGeoMapType &other) const +{ + return (*d_ptr.constData() == *other.d_ptr.constData()); +} + +bool QGeoMapType::operator != (const QGeoMapType &other) const +{ + return !(operator ==(other)); +} + +QGeoMapType::MapStyle QGeoMapType::style() const +{ + return d_ptr->style_; +} + +QString QGeoMapType::name() const +{ + return d_ptr->name_; +} + +QString QGeoMapType::description() const +{ + return d_ptr->description_; +} + +bool QGeoMapType::mobile() const +{ + return d_ptr->mobile_; +} + +int QGeoMapType::mapId() const +{ + return d_ptr->mapId_; +} + +QGeoMapTypePrivate::QGeoMapTypePrivate() + : style_(QGeoMapType::NoMap), + name_(QLatin1String("")), + description_(QLatin1String("")), + mobile_(false), + mapId_(0) {} + +QGeoMapTypePrivate::QGeoMapTypePrivate(const QGeoMapTypePrivate &other) + : QSharedData(other), + style_(other.style_), + name_(other.name_), + description_(other.description_), + mobile_(other.mobile_), + mapId_(other.mapId_) {} + +QGeoMapTypePrivate::QGeoMapTypePrivate(QGeoMapType::MapStyle style, const QString &name, const QString &description, bool mobile, int mapId) + : style_(style), + name_(name), + description_(description), + mobile_(mobile), + mapId_(mapId) {} + +QGeoMapTypePrivate::~QGeoMapTypePrivate() {} + +bool QGeoMapTypePrivate::operator == (const QGeoMapTypePrivate &other) const +{ + return ((style_ == other.style_) + && (name_ == other.name_) + && (description_ == other.description_) + && (mobile_ == other.mobile_) + && (mapId_ == other.mapId_)); +} + +QT_END_NAMESPACE diff --git a/src/location/maps/qgeomaptype.h b/src/location/maps/qgeomaptype.h new file mode 100644 index 00000000..bd927b17 --- /dev/null +++ b/src/location/maps/qgeomaptype.h @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $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$ +** +****************************************************************************/ + +#ifndef QGEOMAPTYPE_H +#define QGEOMAPTYPE_H + +#include <QtLocation/qlocationglobal.h> +#include <QString> +#include <QSharedDataPointer> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QGeoMapTypePrivate; + +class Q_LOCATION_EXPORT QGeoMapType +{ + +public: + enum MapStyle { + NoMap = 0, + StreetMap, + SatelliteMapDay, + SatelliteMapNight, + TerrainMap, + HybridMap, + TransitMap, + GrayStreetMap, + CustomMap = 100 + }; + + QGeoMapType(); + QGeoMapType(const QGeoMapType &other); + QGeoMapType(MapStyle style, const QString &name, const QString &description, bool mobile, int mapId); + ~QGeoMapType(); + + QGeoMapType& operator = (const QGeoMapType &other); + + bool operator == (const QGeoMapType &other) const; + bool operator != (const QGeoMapType &other) const; + + MapStyle style() const; + QString name() const; + QString description() const; + bool mobile() const; + int mapId() const; + +private: + QSharedDataPointer<QGeoMapTypePrivate> d_ptr; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QGEOMAPTYPE_H diff --git a/src/location/maps/qgeomaptype_p.h b/src/location/maps/qgeomaptype_p.h new file mode 100644 index 00000000..e6fa71aa --- /dev/null +++ b/src/location/maps/qgeomaptype_p.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $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$ +** +****************************************************************************/ + +#ifndef QGEOMAPTYPE_P_H +#define QGEOMAPTYPE_P_H + +#include <QMetaType> +#include <QString> +#include <QSharedData> + +#include "qgeomaptype.h" + +QT_BEGIN_NAMESPACE + +class QGeoMapTypePrivate : public QSharedData +{ + +public: + QGeoMapTypePrivate(); + QGeoMapTypePrivate(QGeoMapType::MapStyle style, const QString &name, const QString &description, bool mobile, int mapId); + QGeoMapTypePrivate(const QGeoMapTypePrivate &other); + ~QGeoMapTypePrivate(); + + QGeoMapTypePrivate& operator = (const QGeoMapTypePrivate &other); + + bool operator == (const QGeoMapTypePrivate &other) const; + + QGeoMapType::MapStyle style_; + QString name_; + QString description_; + bool mobile_; + int mapId_; +}; + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QGeoMapTypePrivate) + +#endif // QGEOMAPTYPE_P_H diff --git a/src/location/maps/qgeoprojection.cpp b/src/location/maps/qgeoprojection.cpp new file mode 100644 index 00000000..4561af7d --- /dev/null +++ b/src/location/maps/qgeoprojection.cpp @@ -0,0 +1,117 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $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 "qgeoprojection_p.h" + +#include "qgeocoordinate.h" + +#include <qvector2d.h> +#include <qvector3d.h> +#include <QMatrix4x4> +#include <qnumeric.h> + +#include <cmath> + +QGeoProjection::QGeoProjection() {} + +QGeoProjection::~QGeoProjection() {} + +QVector3D QGeoProjection::mercatorToPoint(const QVector2D &mercator) const +{ + return this->coordToPoint(mercatorToCoord(mercator)); +} + +QVector2D QGeoProjection::pointToMercator(const QVector3D &point) const +{ + return coordToMercator(this->pointToCoord(point)); +} + +QVector2D QGeoProjection::coordToMercator(const QGeoCoordinate &coord) const +{ + const double pi = M_PI; + + double lon = coord.longitude() / 360.0 + 0.5; + + double lat = coord.latitude(); + 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); + + return QVector2D(lon, lat); +} + +double QGeoProjection::realmod(const double a, const double b) +{ + quint64 div = static_cast<quint64>(a / b); + return a - static_cast<double>(div) * b; +} + +QGeoCoordinate QGeoProjection::mercatorToCoord(const QVector2D &mercator) const +{ + const double pi = M_PI; + + double fx = mercator.x(); + double fy = mercator.y(); + + if (fy < 0.0) + fy = 0.0; + else if (fy > 1.0) + fy = 1.0; + + double lat; + + if (fy == 0.0) + lat = 90.0; + else if (fy == 1.0) + lat = -90.0; + else + lat = (180.0 / pi) * (2.0 * atan(exp(pi * (1.0 - 2.0 * fy))) - (pi / 2.0)); + + double lng; + if (fx >= 0) { + lng = realmod(fx, 1.0); + } else { + lng = realmod(1.0 - realmod(-1.0 * fx, 1.0), 1.0); + } + + lng = lng * 360.0 - 180.0; + + return QGeoCoordinate(lat, lng, 0.0); +} diff --git a/src/location/maps/qgeoprojection2d_p.cpp b/src/location/maps/qgeoprojection2d_p.cpp new file mode 100644 index 00000000..21488b84 --- /dev/null +++ b/src/location/maps/qgeoprojection2d_p.cpp @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $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 "qgeoprojection2d_p.h" + +#include "qgeocoordinate.h" + +#include <QVector2D> +#include <QVector3D> + +#include <qnumeric.h> + +QGeoProjection2D::QGeoProjection2D(double baseHeight, double sideLength) + : baseHeight_(baseHeight), sideLength_(sideLength) {} + +QGeoProjection2D::~QGeoProjection2D() {} + +QVector3D QGeoProjection2D::coordToPoint(const QGeoCoordinate &coord) const +{ + QVector2D m = coordToMercator(coord); + double z = baseHeight_; + if (!qIsNaN(coord.altitude())) + z += coord.altitude(); + return QVector3D(m.x() * sideLength_, (1.0 - m.y()) * sideLength_, z); +} + +QGeoCoordinate QGeoProjection2D::pointToCoord(const QVector3D &point) const +{ + QVector2D m = QVector2D(point.x() / sideLength_, 1.0 - point.y() / sideLength_); + QGeoCoordinate coord = mercatorToCoord(m); + coord.setAltitude(point.z() - baseHeight_); + return coord; +} + +QVector3D QGeoProjection2D::mercatorToPoint(const QVector2D &mercator) const +{ + return QVector3D(mercator.x() * sideLength_, (1.0 - mercator.y()) * sideLength_, baseHeight_); +} + +QVector2D QGeoProjection2D::pointToMercator(const QVector3D &point) const +{ + return QVector2D(point.x() / sideLength_, 1.0 - (point.y() / sideLength_)); +} + +QGeoCoordinate QGeoProjection2D::interpolate(const QGeoCoordinate &start, const QGeoCoordinate &end, qreal progress) +{ + if (start == end) { + if (progress < 0.5) { + return start; + } else { + return end; + } + } + + QGeoCoordinate s2 = start; + s2.setAltitude(0.0); + QGeoCoordinate e2 = end; + e2.setAltitude(0.0); + QVector3D s = coordToPoint(s2); + QVector3D e = coordToPoint(e2); + + double x = s.x(); + + if (sideLength_ / 2.0 < qAbs(e.x() - s.x())) { + // handle dateline crossing + } else { + x = (1.0 - progress) * s.x() + progress * e.x(); + } + + double y = (1.0 - progress) * s.y() + progress * e.y(); + + QGeoCoordinate result = pointToCoord(QVector3D(x, y, 0.0)); + result.setAltitude((1.0 - progress) * start.altitude() + progress * end.altitude()); + return result; +} diff --git a/src/location/maps/qgeoprojection2d_p.h b/src/location/maps/qgeoprojection2d_p.h new file mode 100644 index 00000000..a43fcac9 --- /dev/null +++ b/src/location/maps/qgeoprojection2d_p.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $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$ +** +****************************************************************************/ +#ifndef QGEOPROJECTION2D_P_H +#define QGEOPROJECTION2D_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qgeoprojection_p.h" + +QT_BEGIN_NAMESPACE + +class Q_AUTOTEST_EXPORT QGeoProjection2D : public QGeoProjection +{ +public: + QGeoProjection2D(double baseHeight, double sideLength); + virtual ~QGeoProjection2D(); + + virtual QVector3D coordToPoint(const QGeoCoordinate &coord) const; + virtual QGeoCoordinate pointToCoord(const QVector3D &point) const; + + virtual QVector3D mercatorToPoint(const QVector2D &mercator) const; + virtual QVector2D pointToMercator(const QVector3D &point) const; + + virtual QGeoCoordinate interpolate(const QGeoCoordinate &start, const QGeoCoordinate &end, qreal progress); + +private: + double baseHeight_; + double sideLength_; +}; + +QT_END_NAMESPACE + +#endif // QGEOPROJECTION2D_P_H diff --git a/src/location/maps/qgeoprojection_p.h b/src/location/maps/qgeoprojection_p.h new file mode 100644 index 00000000..8eece8f2 --- /dev/null +++ b/src/location/maps/qgeoprojection_p.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $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$ +** +****************************************************************************/ +#ifndef QGEOPROJECTION_H +#define QGEOPROJECTION_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qglobal.h" + +QT_BEGIN_NAMESPACE + +class QGeoCoordinate; +class QVector2D; +class QVector3D; + +class Q_AUTOTEST_EXPORT QGeoProjection +{ +public: + QGeoProjection(); + virtual ~QGeoProjection(); + + virtual QVector3D coordToPoint(const QGeoCoordinate &coord) const = 0; + virtual QGeoCoordinate pointToCoord(const QVector3D &point) const = 0; + + QVector2D coordToMercator(const QGeoCoordinate &coord) const; + QGeoCoordinate mercatorToCoord(const QVector2D &mercator) const; + + virtual QVector3D mercatorToPoint(const QVector2D &mercator) const; + virtual QVector2D pointToMercator(const QVector3D &point) const; + + virtual QGeoCoordinate interpolate(const QGeoCoordinate &start, const QGeoCoordinate &end, qreal progress) = 0; +private: + static double realmod(const double a, const double b); +}; + +QT_END_NAMESPACE + +#endif // QGEOPROJECTION_H diff --git a/src/location/maps/qgeotile.cpp b/src/location/maps/qgeotile.cpp new file mode 100644 index 00000000..42a92d1e --- /dev/null +++ b/src/location/maps/qgeotile.cpp @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $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 "qgeotile.h" + +#include <Qt3D/qgltexture2d.h> +#include <Qt3D/qglscenenode.h> + +QT_BEGIN_NAMESPACE + +QGeoTile::QGeoTile() {} + +QGeoTile::QGeoTile(const QGeoTileSpec &spec) + : spec_(spec), + texture_(0), + sceneNode_(0), + bound_(false) {} + +bool QGeoTile::operator == (const QGeoTile &rhs) const +{ + return (spec_ == rhs.spec_); +} + +void QGeoTile::setTileSpec(const QGeoTileSpec &spec) +{ + spec_ = spec; +} + +QGeoTileSpec QGeoTile::tileSpec() const +{ + return spec_; +} + +void QGeoTile::setTexture(QGLTexture2D *texture) +{ + texture_ = texture; +} + +QGLTexture2D* QGeoTile::texture() const +{ + return texture_; +} + +void QGeoTile::setSceneNode(QGLSceneNode *sceneNode) +{ + sceneNode_ = sceneNode; +} + +QGLSceneNode* QGeoTile::sceneNode() const +{ + return sceneNode_; +} + +void QGeoTile::bind() +{ + if (bound_) + return; + + texture_->bind(); +// texture_->clearImage(); + + bound_ = true; +} + +void QGeoTile::setBound(bool bound) +{ + bound_ = bound; +} + +bool QGeoTile::isBound() const +{ + return bound_; +} + +QT_END_NAMESPACE diff --git a/src/location/maps/qgeotile.h b/src/location/maps/qgeotile.h new file mode 100644 index 00000000..44584e29 --- /dev/null +++ b/src/location/maps/qgeotile.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $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$ +** +****************************************************************************/ +#ifndef QGEOTILE_H +#define QGEOTILE_H + +#include "qglobal.h" + +#include "qgeotilespec.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QGLTexture2D; +class QGLSceneNode; + +class Q_LOCATION_EXPORT QGeoTile +{ +public: + QGeoTile(); + QGeoTile(const QGeoTileSpec &spec); + + bool operator == (const QGeoTile &rhs) const; + + void setTileSpec(const QGeoTileSpec &spec); + QGeoTileSpec tileSpec() const; + + void setTexture(QGLTexture2D *texture); + QGLTexture2D* texture() const; + + void setSceneNode(QGLSceneNode *sceneNode); + QGLSceneNode *sceneNode() const; + + void bind(); + void setBound(bool bound); + bool isBound() const; + +private: + QGeoTileSpec spec_; + QGLTexture2D *texture_; + QGLSceneNode *sceneNode_; + bool bound_; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QGEOTILE_H diff --git a/src/location/maps/qgeotilecache.cpp b/src/location/maps/qgeotilecache.cpp new file mode 100644 index 00000000..cd0cf5e8 --- /dev/null +++ b/src/location/maps/qgeotilecache.cpp @@ -0,0 +1,441 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $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 "qgeotilecache.h" + +#include "qgeotile.h" +#include "qgeotilespec.h" + +#include "qgeomappingmanager.h" + +#include <QDir> +#include <QMetaType> +#include <QDebug> + +#include <Qt3D/qgltexture2d.h> +#include <Qt3D/qglscenenode.h> + +Q_DECLARE_METATYPE(QList<QGeoTileSpec>) +Q_DECLARE_METATYPE(QSet<QGeoTileSpec>) + +QT_BEGIN_NAMESPACE + +class TileDisk +{ +public: + ~TileDisk() + { +// qWarning() << "evicting (disk) " << spec; +// cache->evictFromDiskCache(this); + } + + QGeoTileSpec spec; + QString filename; + QGeoTileCache *cache; +}; + +class TileMemory +{ +public: + ~TileMemory() + { +// qWarning() << "evicting (memory) " << spec; + cache->evictFromMemoryCache(this); + } + + QGeoTileSpec spec; + QPixmap pixmap; + QGeoTileCache *cache; +}; + +class TileTexture { +public: + ~TileTexture() + { +// qWarning() << "evicting (texture) " << spec; + cache->evictFromTextureCache(this); + } + + QGeoTileSpec spec; + bool bound; + QGLTexture2D *texture; + QGLSceneNode *node; + QGeoTileCache *cache; +}; + +QGeoTileCache::QGeoTileCache(const QString &directory, QObject *parent) +: QObject(parent), directory_(directory) +{ + qRegisterMetaType<QGeoTileSpec>(); + qRegisterMetaType<QList<QGeoTileSpec> >(); + qRegisterMetaType<QSet<QGeoTileSpec> >(); + + + if (directory_.isEmpty()) { + QString dirname = QLatin1String(".tilecache"); + QDir home = QDir::home(); + if (!home.exists(dirname)) + home.mkdir(dirname); + directory_ = home.filePath(dirname); + } + qDebug() << __FUNCTION__ << directory_; + + diskCache_.setMaxCost(100 * 1024 * 1024); + memoryCache_.setMaxCost(50 * 1024 * 1024); + textureCache_.setMaxCost(100 * 1024 * 1024); + + loadTiles(); +} + +QGeoTileCache::~QGeoTileCache() {} + +void QGeoTileCache::setMaxDiskUsage(int diskUsage) +{ + diskCache_.setMaxCost(diskUsage); +} + +int QGeoTileCache::maxDiskUsage() const +{ + return diskCache_.maxCost(); +} + +int QGeoTileCache::diskUsage() const +{ + return diskCache_.totalCost(); +} + +void QGeoTileCache::setMaxMemoryUsage(int memoryUsage) +{ + memoryCache_.setMaxCost(memoryUsage); +} + +int QGeoTileCache::maxMemoryUsage() const +{ + return memoryCache_.maxCost(); +} + +int QGeoTileCache::memoryUsage() const +{ + return memoryCache_.totalCost(); +} + +void QGeoTileCache::setMaxTextureUsage(int textureUsage) +{ + textureCache_.setMaxCost(textureUsage); +} + +int QGeoTileCache::maxTextureUsage() const +{ + return textureCache_.maxCost(); +} + +int QGeoTileCache::textureUsage() const +{ + return textureCache_.totalCost(); +} + +void QGeoTileCache::GLContextAvailable(QGLSceneNode *parentNode) +{ + int size = cleanupList_.size(); + for (int i = 0; i < size; ++i) { + QGeoTile t = cleanupList_.at(i); + QGLSceneNode *node = t.sceneNode(); + if (node) { + parentNode->removeNode(node); + delete node; + } + QGLTexture2D *texture = t.texture(); + if (texture) { + texture->release(); + delete texture; + } + } + cleanupList_.clear(); +} + +bool QGeoTileCache::contains(const QGeoTileSpec &spec) const +{ + return keys_.contains(spec); +} + +QGeoTile QGeoTileCache::get(const QGeoTileSpec &spec) +{ + if (textureCache_.contains(spec)) { + TileTexture *tt = textureCache_.object(spec); + + QGeoTile t = QGeoTile(tt->spec); + t.setTexture(tt->texture); + t.setSceneNode(tt->node); + t.setBound(tt->bound); + return t; + } +// if (memoryCache_.contains(spec)) { +// TileMemory *tm = memoryCache_.object(spec); +// TileTexture *tt = addToTextureCache(tm->spec, tm->pixmap); + +// QGeoTile t = Tile(tt->spec); +// t.setTexture(tt->texture); +// t.setSceneNode(tt->node); +// t.setBound(tt->bound); +// return t; +// } + if (diskCache_.contains(spec)) { + TileDisk *td = diskCache_.object(spec); +// TileMemory *tm = addToMemoryCache(td->spec, QPixmap(td->filename)); +// TileTexture *tt = addToTextureCache(tm->spec, tm->pixmap); + TileTexture *tt = addToTextureCache(td->spec, QPixmap(td->filename)); + + QGeoTile t = QGeoTile(tt->spec); + t.setTexture(tt->texture); + t.setSceneNode(tt->node); + t.setBound(tt->bound); + return t; + } + + return QGeoTile(); +} + +// TODO rename so this is less strange +// OR do node creation in here somehow +void QGeoTileCache::update(const QGeoTileSpec &spec, const QGeoTile &tile) +{ + TileTexture *tt = textureCache_.object(spec); + if (tt) { + tt->node = tile.sceneNode(); + tt->texture = tile.texture(); + tt->bound = tile.isBound(); + } +} + +void QGeoTileCache::insert(const QGeoTileSpec &spec, const QByteArray &bytes, QGeoTileCache::CacheAreas areas) +{ + keys_.insert(spec); + + QPixmap pixmap; + if (!pixmap.loadFromData(bytes)) { + handleError(spec, QLatin1String("Problem with tile image")); + return; + } + + if (areas & QGeoTileCache::DiskCache) { + QString filename = tileSpecToFilename(spec, directory_); + + QFile file(filename); + file.open(QIODevice::WriteOnly); + file.write(bytes); + file.close(); + + addToDiskCache(spec, filename); + } + + if (areas & QGeoTileCache::MemoryCache) { +// addToMemoryCache(spec, pixmap); + } + + if (areas & QGeoTileCache::TextureCache) { + addToTextureCache(spec, pixmap); + } +} + +void QGeoTileCache::evictFromDiskCache(TileDisk *td) +{ + keys_.remove(td->spec); + QFile::remove(td->filename); +} + +void QGeoTileCache::evictFromMemoryCache(TileMemory * /* tm */) +{ +} + +void QGeoTileCache::evictFromTextureCache(TileTexture *tt) +{ + QGeoTile t(tt->spec); + t.setTexture(tt->texture); + t.setSceneNode(tt->node); + cleanupList_ << t; +} + +TileDisk* QGeoTileCache::addToDiskCache(const QGeoTileSpec &spec, const QString &filename) +{ + keys_.insert(spec); + +// qWarning() << "adding (disk) " << spec; + + TileDisk *td = new TileDisk; + td->spec = spec; + td->filename = filename; + td->cache = this; + + QFileInfo fi(filename); + int diskCost = fi.size(); + + diskCache_.insert(spec, + td, + diskCost); + + return td; +} + +TileMemory* QGeoTileCache::addToMemoryCache(const QGeoTileSpec &spec, const QPixmap &pixmap) +{ + keys_.insert(spec); + +// qWarning() << "adding (memory) " << spec; + + TileMemory *tm = new TileMemory; + tm->spec = spec; + tm->pixmap = pixmap; + tm->cache = this; + + int memoryCost = pixmap.width() * pixmap.height() * pixmap.depth() / 8; + + memoryCache_.insert(spec, + tm, + memoryCost); + + return tm; +} + +TileTexture* QGeoTileCache::addToTextureCache(const QGeoTileSpec &spec, const QPixmap &pixmap) +{ + keys_.insert(spec); + +// qWarning() << "adding (texture) " << spec; + + TileTexture *tt = new TileTexture; + tt->spec = spec; + tt->texture = new QGLTexture2D(); + tt->texture->setPixmap(pixmap); + tt->texture->setHorizontalWrap(QGL::ClampToEdge); + tt->texture->setVerticalWrap(QGL::ClampToEdge); + +// tt->texture->bind(); +// tt->texture->clearImage(); + + tt->node = 0; + tt->cache = this; + + int textureCost = pixmap.width() * pixmap.height() * pixmap.depth() / 8;; + + textureCache_.insert(spec, + tt, + textureCost); + + return tt; +} + +void QGeoTileCache::handleError(const QGeoTileSpec &, const QString &error) +{ + qWarning() << "tile request error " << error; +} + +void QGeoTileCache::loadTiles() +{ + QStringList formats; + formats << QLatin1String("*.png"); + + QDir dir(directory_); + //QStringList files = dir.entryList(formats, QDir::Files, QDir::Time | QDir::Reversed); + QStringList files = dir.entryList(formats, QDir::Files); + int tiles = 0; + for (int i = 0; i < files.size(); ++i) { + QGeoTileSpec spec = filenameToTileSpec(files.at(i)); + if (spec.zoom() == -1) + continue; + QString filename = dir.filePath(files.at(i)); + addToDiskCache(spec, filename); + tiles++; + } + qDebug() << __FUNCTION__ << " loaded this many map tiles to cache: " << tiles; + +} + +QString QGeoTileCache::tileSpecToFilename(const QGeoTileSpec &spec, const QString &directory) +{ + QString filename = spec.plugin(); + filename += QLatin1String("-"); + filename += QString::number(spec.mapId()); + filename += QLatin1String("-"); + filename += QString::number(spec.zoom()); + filename += QLatin1String("-"); + filename += QString::number(spec.x()); + filename += QLatin1String("-"); + filename += QString::number(spec.y()); + filename += QLatin1String(".png"); + + QDir dir = QDir(directory); + + return dir.filePath(filename); +} + +QGeoTileSpec QGeoTileCache::filenameToTileSpec(const QString &filename) +{ + QGeoTileSpec emptySpec; + QString extension = QLatin1String(".png"); + + if (!filename.endsWith(extension)) + return emptySpec; + + QString name = filename; + name.chop(extension.length()); + QStringList fields = name.split('-'); + + if (fields.length() != 5) + return emptySpec; + + QList<int> numbers; + + bool ok = false; + for (int i = 1; i < 5; ++i) { + ok = false; + int value = fields.at(i).toInt(&ok); + if (!ok) + return emptySpec; + numbers.append(value); + } + + return QGeoTileSpec(fields.at(0), + numbers.at(0), + numbers.at(1), + numbers.at(2), + numbers.at(3)); +} + +QT_END_NAMESPACE diff --git a/src/location/maps/qgeotilecache.h b/src/location/maps/qgeotilecache.h new file mode 100644 index 00000000..42bf7879 --- /dev/null +++ b/src/location/maps/qgeotilecache.h @@ -0,0 +1,135 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $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$ +** +****************************************************************************/ +#ifndef QGEOTILECACHE_H +#define QGEOTILECACHE_H + +#include <QtLocation/qlocationglobal.h> + +#include <QObject> +#include <QCache> +#include <QSet> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QGeoMappingManager; + +class QGeoTileSpec; +class QGeoTile; + +class TileDisk; +class TileMemory; +class TileTexture; + +class QGLSceneNode; + +class QPixmap; +class QThread; + +class Q_LOCATION_EXPORT QGeoTileCache : public QObject +{ + Q_OBJECT +public: + enum CacheArea { + DiskCache = 0x01, + MemoryCache = 0x02, + TextureCache = 0x04, + AllCaches = 0xFF + }; + Q_DECLARE_FLAGS(CacheAreas, CacheArea) + + QGeoTileCache(const QString &directory = QString(), QObject *parent = 0); + ~QGeoTileCache(); + + void setMaxDiskUsage(int diskUsage); + int maxDiskUsage() const; + int diskUsage() const; + + void setMaxMemoryUsage(int memoryUsage); + int maxMemoryUsage() const; + int memoryUsage() const; + + void setMaxTextureUsage(int textureUsage); + int maxTextureUsage() const; + int textureUsage() const; + + void GLContextAvailable(QGLSceneNode *parentNode); + + bool contains(const QGeoTileSpec &spec) const; + QGeoTile get(const QGeoTileSpec &spec); + + void update(const QGeoTileSpec &spec, const QGeoTile &tile); + + void evictFromDiskCache(TileDisk *td); + void evictFromMemoryCache(TileMemory *tm); + void evictFromTextureCache(TileTexture *tt); + + void insert(const QGeoTileSpec &spec, const QByteArray &bytes, CacheAreas areas = AllCaches); + void handleError(const QGeoTileSpec &spec, const QString &errorString); + +private: + void loadTiles(); + + TileDisk* addToDiskCache(const QGeoTileSpec &spec, const QString &filename); + TileMemory* addToMemoryCache(const QGeoTileSpec &spec, const QPixmap &pixmap); + TileTexture* addToTextureCache(const QGeoTileSpec &spec, const QPixmap &pixmap); + + static QString tileSpecToFilename(const QGeoTileSpec &spec, const QString &directory); + static QGeoTileSpec filenameToTileSpec(const QString &filename); + + QString directory_; + + QSet<QGeoTileSpec> keys_; + QCache<QGeoTileSpec, TileDisk > diskCache_; + QCache<QGeoTileSpec, TileMemory > memoryCache_; + QCache<QGeoTileSpec, TileTexture > textureCache_; + + QList<QGeoTile> cleanupList_; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QGeoTileCache::CacheAreas) + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QGEOTILECACHE_H diff --git a/src/location/maps/qgeotiledmapreply.cpp b/src/location/maps/qgeotiledmapreply.cpp index 400a0713..c8d40c04 100644 --- a/src/location/maps/qgeotiledmapreply.cpp +++ b/src/location/maps/qgeotiledmapreply.cpp @@ -93,7 +93,7 @@ QT_BEGIN_NAMESPACE /*! Constructs a tiled map reply object based on \a request, with parent \a parent. */ -QGeoTiledMapReply::QGeoTiledMapReply(const TileSpec &spec, QObject *parent) +QGeoTiledMapReply::QGeoTiledMapReply(const QGeoTileSpec &spec, QObject *parent) : QObject(parent), d_ptr(new QGeoTiledMapReplyPrivate(spec)) { @@ -201,7 +201,7 @@ void QGeoTiledMapReply::setCached(bool cached) /*! Returns the request which corresponds to this reply. */ -TileSpec QGeoTiledMapReply::tileSpec() const +QGeoTileSpec QGeoTiledMapReply::tileSpec() const { return d_ptr->spec; } @@ -304,7 +304,7 @@ void QGeoTiledMapReply::abort() /******************************************************************************* *******************************************************************************/ -QGeoTiledMapReplyPrivate::QGeoTiledMapReplyPrivate(const TileSpec &spec) +QGeoTiledMapReplyPrivate::QGeoTiledMapReplyPrivate(const QGeoTileSpec &spec) : error(QGeoTiledMapReply::NoError), errorString(QLatin1String("")), isFinished(false), diff --git a/src/location/maps/qgeotiledmapreply.h b/src/location/maps/qgeotiledmapreply.h index e7cfb628..d354e6ad 100644 --- a/src/location/maps/qgeotiledmapreply.h +++ b/src/location/maps/qgeotiledmapreply.h @@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE -class TileSpec; +class QGeoTileSpec; class QGeoTiledMapReplyPrivate; class Q_LOCATION_EXPORT QGeoTiledMapReply : public QObject @@ -67,7 +67,7 @@ public: UnknownError }; - QGeoTiledMapReply(const TileSpec &spec, QObject *parent = 0); + QGeoTiledMapReply(const QGeoTileSpec &spec, QObject *parent = 0); QGeoTiledMapReply(Error error, const QString &errorString, QObject *parent = 0); virtual ~QGeoTiledMapReply(); @@ -77,7 +77,7 @@ public: bool isCached() const; - TileSpec tileSpec() const; + QGeoTileSpec tileSpec() const; QByteArray mapImageData() const; QString mapImageFormat() const; diff --git a/src/location/maps/qgeotiledmapreply_p.h b/src/location/maps/qgeotiledmapreply_p.h index cf0043cb..5ac1fccc 100644 --- a/src/location/maps/qgeotiledmapreply_p.h +++ b/src/location/maps/qgeotiledmapreply_p.h @@ -54,14 +54,14 @@ // #include "qgeotiledmapreply.h" -#include "tilespec.h" +#include "qgeotilespec.h" QT_BEGIN_NAMESPACE class QGeoTiledMapReplyPrivate { public: - QGeoTiledMapReplyPrivate(const TileSpec &spec); + QGeoTiledMapReplyPrivate(const QGeoTileSpec &spec); QGeoTiledMapReplyPrivate(QGeoTiledMapReply::Error error, const QString& errorString); ~QGeoTiledMapReplyPrivate(); @@ -70,7 +70,7 @@ public: bool isFinished; bool isCached; - TileSpec spec; + QGeoTileSpec spec; QByteArray mapImageData; QString mapImageFormat; }; diff --git a/src/location/maps/qgeotilespec.cpp b/src/location/maps/qgeotilespec.cpp new file mode 100644 index 00000000..13a0b394 --- /dev/null +++ b/src/location/maps/qgeotilespec.cpp @@ -0,0 +1,218 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $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 "qgeotilespec.h" +#include "qgeotilespec_p.h" +#include <QDebug> + +QT_BEGIN_NAMESPACE + +QGeoTileSpec::QGeoTileSpec() + : d_ptr(new QGeoTileSpecPrivate()) {} + +QGeoTileSpec::QGeoTileSpec(const QString &plugin, int mapId, int zoom, int x, int y) + : d_ptr(new QGeoTileSpecPrivate(plugin, mapId, zoom, x, y)) {} + +QGeoTileSpec::QGeoTileSpec(const QGeoTileSpec &other) + : d_ptr(new QGeoTileSpecPrivate(*(other.d_ptr))) {} + +QGeoTileSpec::~QGeoTileSpec() { + delete d_ptr; +} + +QGeoTileSpec& QGeoTileSpec::operator = (const QGeoTileSpec &other) +{ + d_ptr->operator=(*(other.d_ptr)); + return *this; +} + +QString QGeoTileSpec::plugin() const +{ + Q_D(const QGeoTileSpec); + return d->plugin_; +} + +void QGeoTileSpec::setZoom(int zoom) +{ + Q_D(QGeoTileSpec); + d->zoom_ = zoom; +} + +int QGeoTileSpec::zoom() const +{ + Q_D(const QGeoTileSpec); + return d->zoom_; +} + +void QGeoTileSpec::setX(int x) +{ + Q_D(QGeoTileSpec); + d->x_ = x; +} + +int QGeoTileSpec::x() const +{ + Q_D(const QGeoTileSpec); + return d->x_; +} + +void QGeoTileSpec::setY(int y) +{ + Q_D(QGeoTileSpec); + d->y_ = y; +} + +int QGeoTileSpec::y() const +{ + Q_D(const QGeoTileSpec); + return d->y_; +} + +void QGeoTileSpec::setMapId(int mapId) +{ + Q_D(QGeoTileSpec); + d->mapId_ = mapId; +} + +int QGeoTileSpec::mapId() const +{ + Q_D(const QGeoTileSpec); + return d->mapId_; +} + +bool QGeoTileSpec::operator == (const QGeoTileSpec &rhs) const +{ + return (d_ptr->operator == (*(rhs.d_ptr))); +} + +bool QGeoTileSpec::operator < (const QGeoTileSpec &rhs) const +{ + return (d_ptr->operator < (*(rhs.d_ptr))); +} + +unsigned int qHash(const QGeoTileSpec &spec) +{ + unsigned int result = (qHash(spec.plugin()) * 13) % 31; + result += ((spec.mapId() * 17) % 31) << 5; + result += ((spec.zoom() * 19) % 31) << 10; + result += ((spec.x() * 23) % 31) << 15; + result += ((spec.y() * 29) % 31) << 20; + return result; +} + +QDebug operator<< (QDebug dbg, const QGeoTileSpec &spec) +{ + dbg << spec.plugin() << spec.mapId() << spec.zoom() << spec.x() << spec.y(); + return dbg; +} + +QGeoTileSpecPrivate::QGeoTileSpecPrivate() + : mapId_(0), + zoom_(-1), + x_(-1), + y_(-1) {} + +QGeoTileSpecPrivate::QGeoTileSpecPrivate(const QGeoTileSpecPrivate &other) + : plugin_(other.plugin_), + mapId_(other.mapId_), + zoom_(other.zoom_), + x_(other.x_), + y_(other.y_) {} + +QGeoTileSpecPrivate::QGeoTileSpecPrivate(const QString &plugin, int mapId, int zoom, int x, int y) + : plugin_(plugin), + mapId_(mapId), + zoom_(zoom), + x_(x), + y_(y) {} + +QGeoTileSpecPrivate::~QGeoTileSpecPrivate() {} + +QGeoTileSpecPrivate& QGeoTileSpecPrivate::operator = (const QGeoTileSpecPrivate &other) +{ + plugin_ = other.plugin_; + mapId_ = other.mapId_; + zoom_ = other.zoom_; + x_ = other.x_; + y_ = other.y_; + return *this; +} + +bool QGeoTileSpecPrivate::operator == (const QGeoTileSpecPrivate &rhs) const +{ + if (plugin_ != rhs.plugin_) + return false; + + if (mapId_ != rhs.mapId_) + return false; + + if (zoom_ != rhs.zoom_) + return false; + + if (x_ != rhs.x_) + return false; + + if (y_ != rhs.y_) + return false; + + return true; +} + +bool QGeoTileSpecPrivate::operator < (const QGeoTileSpecPrivate &rhs) const +{ + if (plugin_ < rhs.plugin_) + return true; + if (plugin_ > rhs.plugin_) + return false; + + if (zoom_ < rhs.zoom_) + return true; + if (zoom_ > rhs.zoom_) + return false; + + if (x_ < rhs.x_) + return true; + if (x_ > rhs.x_) + return false; + + return (y_ < rhs.y_); +} + +QT_END_NAMESPACE diff --git a/src/location/maps/qgeotilespec.h b/src/location/maps/qgeotilespec.h new file mode 100644 index 00000000..6726b936 --- /dev/null +++ b/src/location/maps/qgeotilespec.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $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$ +** +****************************************************************************/ +#ifndef QGEOTILESPEC_H +#define QGEOTILESPEC_H + +#include <QtLocation/qlocationglobal.h> +#include <QtCore/QMetaType> +#include <QString> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QGeoTileSpecPrivate; + +class Q_LOCATION_EXPORT QGeoTileSpec +{ +public: + QGeoTileSpec(); + QGeoTileSpec(const QGeoTileSpec &other); + QGeoTileSpec(const QString &plugin, int mapId, int zoom, int x, int y); + ~QGeoTileSpec(); + + QGeoTileSpec& operator = (const QGeoTileSpec &other); + + QString plugin() const; + + void setZoom(int zoom); + int zoom() const; + + void setX(int x); + int x() const; + + void setY(int y); + int y() const; + + void setMapId(int mapId); + int mapId() const; + + bool operator == (const QGeoTileSpec &rhs) const; + bool operator < (const QGeoTileSpec &rhs) const; + +private: + QGeoTileSpecPrivate *d_ptr; + Q_DECLARE_PRIVATE(QGeoTileSpec) +}; + +unsigned int qHash(const QGeoTileSpec &spec); + +QDebug operator<<(QDebug, const QGeoTileSpec &); + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QGeoTileSpec) + +QT_END_HEADER + +#endif // QGEOTILESPEC_H diff --git a/src/location/maps/qgeotilespec_p.h b/src/location/maps/qgeotilespec_p.h new file mode 100644 index 00000000..8c364c85 --- /dev/null +++ b/src/location/maps/qgeotilespec_p.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $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$ +** +****************************************************************************/ +#ifndef QGEOTILESPEC_P_H +#define QGEOTILESPEC_P_H + +#include <QString> + +QT_BEGIN_NAMESPACE + +class QGeoTileSpecPrivate +{ +public: + QGeoTileSpecPrivate(); + QGeoTileSpecPrivate(const QGeoTileSpecPrivate &other); + QGeoTileSpecPrivate(const QString &plugin, int mapId, int zoom, int x, int y); + ~QGeoTileSpecPrivate(); + + QGeoTileSpecPrivate& operator = (const QGeoTileSpecPrivate &other); + + bool operator == (const QGeoTileSpecPrivate &rhs) const; + bool operator < (const QGeoTileSpecPrivate &rhs) const; + + QString plugin_; + int mapId_; + int zoom_; + int x_; + int y_; +}; + +QT_END_NAMESPACE + +#endif // QGEOTILESPEC_P_H |