From a9506a1c73ada80262157ae4736a16cbc0fcb435 Mon Sep 17 00:00:00 2001 From: David Laing Date: Mon, 9 Jan 2012 08:57:54 +1000 Subject: Refactoring ahead of precision issue fixes. We need to rework the GL geometry and camera positioning code to avoid problems with arising from the single precision floats that GL uses. This change is the first step down this path, which adds double precision versions of the QVector2/3D classes and changes the maps code to use them. It also adds a new class which determines which tiles will be visible based on the relevant bits of information from the map (now using double precision). This was done to force the decoupling of the code which determines the visible tiles from the details of the GL geometry / camera / etc... Change-Id: I7127e39097a92028dfea01d816c14c9b9666569e Reviewed-by: Alex Wilson --- src/location/maps/maps.pri | 6 + src/location/maps/qdoublevector2d.cpp | 132 ++++++ src/location/maps/qdoublevector2d_p.h | 240 ++++++++++ src/location/maps/qdoublevector3d.cpp | 187 ++++++++ src/location/maps/qdoublevector3d_p.h | 294 ++++++++++++ src/location/maps/qgeocameratiles.cpp | 746 +++++++++++++++++++++++++++++++ src/location/maps/qgeocameratiles_p.h | 92 ++++ src/location/maps/qgeofrustum.cpp | 11 +- src/location/maps/qgeofrustum_p.h | 41 +- src/location/maps/qgeomap.cpp | 790 +++------------------------------ src/location/maps/qgeomap_p_p.h | 103 +---- src/location/maps/qgeoprojection.cpp | 15 +- src/location/maps/qgeoprojection2d.cpp | 28 +- src/location/maps/qgeoprojection2d_p.h | 8 +- src/location/maps/qgeoprojection_p.h | 16 +- 15 files changed, 1821 insertions(+), 888 deletions(-) create mode 100644 src/location/maps/qdoublevector2d.cpp create mode 100644 src/location/maps/qdoublevector2d_p.h create mode 100644 src/location/maps/qdoublevector3d.cpp create mode 100644 src/location/maps/qdoublevector3d_p.h create mode 100644 src/location/maps/qgeocameratiles.cpp create mode 100644 src/location/maps/qgeocameratiles_p.h (limited to 'src/location/maps') diff --git a/src/location/maps/maps.pri b/src/location/maps/maps.pri index 548b177b..520fb004 100644 --- a/src/location/maps/maps.pri +++ b/src/location/maps/maps.pri @@ -23,7 +23,10 @@ PUBLIC_HEADERS += \ maps/qgeotilespec.h PRIVATE_HEADERS += \ + maps/qdoublevector2d_p.h \ + maps/qdoublevector3d_p.h \ maps/qgeocameradata_p.h \ + maps/qgeocameratiles_p.h \ maps/qgeocodereply_p.h \ maps/qgeocodingmanagerengine_p.h \ maps/qgeocodingmanager_p.h \ @@ -51,7 +54,10 @@ PRIVATE_HEADERS += \ maps/qgeotilespec_p.h SOURCES += \ + maps/qdoublevector2d.cpp \ + maps/qdoublevector3d.cpp \ maps/qgeocameradata.cpp \ + maps/qgeocameratiles.cpp \ maps/qgeocodereply.cpp \ maps/qgeocodingmanager.cpp \ maps/qgeocodingmanagerengine.cpp \ diff --git a/src/location/maps/qdoublevector2d.cpp b/src/location/maps/qdoublevector2d.cpp new file mode 100644 index 00000000..b5a87553 --- /dev/null +++ b/src/location/maps/qdoublevector2d.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 QtGui 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 "qdoublevector2d_p.h" +#include "qdoublevector3d_p.h" +#include +#include + +QT_BEGIN_NAMESPACE + +QDoubleVector2D::QDoubleVector2D(const QDoubleVector3D& vector) +{ + xp = vector.xp; + yp = vector.yp; +} + +double QDoubleVector2D::length() const +{ + return qSqrt(xp * xp + yp * yp); +} + +double QDoubleVector2D::lengthSquared() const +{ + return xp * xp + yp * yp; +} + +QDoubleVector2D QDoubleVector2D::normalized() const +{ + // Need some extra precision if the length is very small. + double len = double(xp) * double(xp) + + double(yp) * double(yp); + if (qFuzzyIsNull(len - 1.0)) + return *this; + else if (!qFuzzyIsNull(len)) + return *this / qSqrt(len); + else + return QDoubleVector2D(); +} + +void QDoubleVector2D::normalize() +{ + // Need some extra precision if the length is very small. + double len = double(xp) * double(xp) + + double(yp) * double(yp); + if (qFuzzyIsNull(len - 1.0) || qFuzzyIsNull(len)) + return; + + len = qSqrt(len); + + xp /= len; + yp /= len; +} + +double QDoubleVector2D::dotProduct(const QDoubleVector2D& v1, const QDoubleVector2D& v2) +{ + return v1.xp * v2.xp + v1.yp * v2.yp; +} + +QDoubleVector3D QDoubleVector2D::toVector3D() const +{ + return QDoubleVector3D(xp, yp, 0.0); +} + +#ifndef QT_NO_DEBUG_STREAM + +QDebug operator<<(QDebug dbg, const QDoubleVector2D &vector) +{ + dbg.nospace() << "QDoubleVector2D(" << vector.x() << ", " << vector.y() << ')'; + return dbg.space(); +} + +#endif + +#ifndef QT_NO_DATASTREAM + +QDataStream &operator<<(QDataStream &stream, const QDoubleVector2D &vector) +{ + stream << double(vector.x()) << double(vector.y()); + return stream; +} + +QDataStream &operator>>(QDataStream &stream, QDoubleVector2D &vector) +{ + double x, y; + stream >> x; + stream >> y; + vector.setX(double(x)); + vector.setY(double(y)); + return stream; +} + +#endif // QT_NO_DATASTREAM + +QT_END_NAMESPACE diff --git a/src/location/maps/qdoublevector2d_p.h b/src/location/maps/qdoublevector2d_p.h new file mode 100644 index 00000000..a8d05667 --- /dev/null +++ b/src/location/maps/qdoublevector2d_p.h @@ -0,0 +1,240 @@ +/**************************************************************************** +** +** 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 QtGui 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 QDOUBLEVECTOR2D_P_H +#define QDOUBLEVECTOR2D_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 + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QDoubleVector3D; + +class QDoubleVector2D +{ +public: + QDoubleVector2D(); + explicit QDoubleVector2D(const QVector2D &vector); + QDoubleVector2D(double xpos, double ypos); + explicit QDoubleVector2D(const QDoubleVector3D& vector); + + operator QVector2D() const; + + bool isNull() const; + + double x() const; + double y() const; + + void setX(double x); + void setY(double y); + + double length() const; + double lengthSquared() const; + + QDoubleVector2D normalized() const; + void normalize(); + + QDoubleVector2D &operator+=(const QDoubleVector2D &vector); + QDoubleVector2D &operator-=(const QDoubleVector2D &vector); + QDoubleVector2D &operator*=(double factor); + QDoubleVector2D &operator*=(const QDoubleVector2D &vector); + QDoubleVector2D &operator/=(double divisor); + + static double dotProduct(const QDoubleVector2D& v1, const QDoubleVector2D& v2); + + friend inline bool operator==(const QDoubleVector2D &v1, const QDoubleVector2D &v2); + friend inline bool operator!=(const QDoubleVector2D &v1, const QDoubleVector2D &v2); + friend inline const QDoubleVector2D operator+(const QDoubleVector2D &v1, const QDoubleVector2D &v2); + friend inline const QDoubleVector2D operator-(const QDoubleVector2D &v1, const QDoubleVector2D &v2); + friend inline const QDoubleVector2D operator*(double factor, const QDoubleVector2D &vector); + friend inline const QDoubleVector2D operator*(const QDoubleVector2D &vector, double factor); + friend inline const QDoubleVector2D operator*(const QDoubleVector2D &v1, const QDoubleVector2D &v2); + friend inline const QDoubleVector2D operator-(const QDoubleVector2D &vector); + friend inline const QDoubleVector2D operator/(const QDoubleVector2D &vector, double divisor); + + friend inline bool qFuzzyCompare(const QDoubleVector2D& v1, const QDoubleVector2D& v2); + + QDoubleVector3D toVector3D() const; + +private: + double xp, yp; + + friend class QDoubleVector3D; +}; + +Q_DECLARE_TYPEINFO(QDoubleVector2D, Q_MOVABLE_TYPE); + +inline QDoubleVector2D::QDoubleVector2D() : xp(0.0), yp(0.0) {} + +inline QDoubleVector2D::QDoubleVector2D(const QVector2D &vector) : xp(vector.x()), yp(vector.y()) {} + +inline QDoubleVector2D::QDoubleVector2D(double xpos, double ypos) : xp(xpos), yp(ypos) {} + +inline QDoubleVector2D::operator QVector2D() const +{ + return QVector2D(xp, yp); +} + +inline bool QDoubleVector2D::isNull() const +{ + return qIsNull(xp) && qIsNull(yp); +} + +inline double QDoubleVector2D::x() const { return double(xp); } +inline double QDoubleVector2D::y() const { return double(yp); } + +inline void QDoubleVector2D::setX(double aX) { xp = aX; } +inline void QDoubleVector2D::setY(double aY) { yp = aY; } + +inline QDoubleVector2D &QDoubleVector2D::operator+=(const QDoubleVector2D &vector) +{ + xp += vector.xp; + yp += vector.yp; + return *this; +} + +inline QDoubleVector2D &QDoubleVector2D::operator-=(const QDoubleVector2D &vector) +{ + xp -= vector.xp; + yp -= vector.yp; + return *this; +} + +inline QDoubleVector2D &QDoubleVector2D::operator*=(double factor) +{ + xp *= factor; + yp *= factor; + return *this; +} + +inline QDoubleVector2D &QDoubleVector2D::operator*=(const QDoubleVector2D &vector) +{ + xp *= vector.xp; + yp *= vector.yp; + return *this; +} + +inline QDoubleVector2D &QDoubleVector2D::operator/=(double divisor) +{ + xp /= divisor; + yp /= divisor; + return *this; +} + +inline bool operator==(const QDoubleVector2D &v1, const QDoubleVector2D &v2) +{ + return v1.xp == v2.xp && v1.yp == v2.yp; +} + +inline bool operator!=(const QDoubleVector2D &v1, const QDoubleVector2D &v2) +{ + return v1.xp != v2.xp || v1.yp != v2.yp; +} + +inline const QDoubleVector2D operator+(const QDoubleVector2D &v1, const QDoubleVector2D &v2) +{ + return QDoubleVector2D(v1.xp + v2.xp, v1.yp + v2.yp); +} + +inline const QDoubleVector2D operator-(const QDoubleVector2D &v1, const QDoubleVector2D &v2) +{ + return QDoubleVector2D(v1.xp - v2.xp, v1.yp - v2.yp); +} + +inline const QDoubleVector2D operator*(double factor, const QDoubleVector2D &vector) +{ + return QDoubleVector2D(vector.xp * factor, vector.yp * factor); +} + +inline const QDoubleVector2D operator*(const QDoubleVector2D &vector, double factor) +{ + return QDoubleVector2D(vector.xp * factor, vector.yp * factor); +} + +inline const QDoubleVector2D operator*(const QDoubleVector2D &v1, const QDoubleVector2D &v2) +{ + return QDoubleVector2D(v1.xp * v2.xp, v1.yp * v2.yp); +} + +inline const QDoubleVector2D operator-(const QDoubleVector2D &vector) +{ + return QDoubleVector2D(-vector.xp, -vector.yp); +} + +inline const QDoubleVector2D operator/(const QDoubleVector2D &vector, double divisor) +{ + return QDoubleVector2D(vector.xp / divisor, vector.yp / divisor); +} + +inline bool qFuzzyCompare(const QDoubleVector2D& v1, const QDoubleVector2D& v2) +{ + return qFuzzyCompare(v1.xp, v2.xp) && qFuzzyCompare(v1.yp, v2.yp); +} + +#ifndef QT_NO_DEBUG_STREAM +Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QDoubleVector2D &vector); +#endif + +#ifndef QT_NO_DATASTREAM +Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QDoubleVector2D &); +Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QDoubleVector2D &); +#endif + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/location/maps/qdoublevector3d.cpp b/src/location/maps/qdoublevector3d.cpp new file mode 100644 index 00000000..6f0e708e --- /dev/null +++ b/src/location/maps/qdoublevector3d.cpp @@ -0,0 +1,187 @@ +/**************************************************************************** +** +** 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 QtGui 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 "qdoublevector3d_p.h" +#include "qdoublevector2d_p.h" +#include +#include + +QT_BEGIN_NAMESPACE + +QDoubleVector3D::QDoubleVector3D(const QDoubleVector2D& vector) +{ + xp = vector.xp; + yp = vector.yp; + zp = 0.0; +} + +QDoubleVector3D::QDoubleVector3D(const QDoubleVector2D& vector, double zpos) +{ + xp = vector.xp; + yp = vector.yp; + zp = zpos; +} + +QDoubleVector3D QDoubleVector3D::normalized() const +{ + // Need some extra precision if the length is very small. + double len = double(xp) * double(xp) + + double(yp) * double(yp) + + double(zp) * double(zp); + if (qFuzzyIsNull(len - 1.0)) + return *this; + else if (!qFuzzyIsNull(len)) + return *this / qSqrt(len); + else + return QDoubleVector3D(); +} + +void QDoubleVector3D::normalize() +{ + // Need some extra precision if the length is very small. + double len = double(xp) * double(xp) + + double(yp) * double(yp) + + double(zp) * double(zp); + if (qFuzzyIsNull(len - 1.0) || qFuzzyIsNull(len)) + return; + + len = qSqrt(len); + + xp /= len; + yp /= len; + zp /= len; +} + +double QDoubleVector3D::dotProduct(const QDoubleVector3D& v1, const QDoubleVector3D& v2) +{ + return v1.xp * v2.xp + v1.yp * v2.yp + v1.zp * v2.zp; +} + +QDoubleVector3D QDoubleVector3D::crossProduct(const QDoubleVector3D& v1, const QDoubleVector3D& v2) +{ + return QDoubleVector3D(v1.yp * v2.zp - v1.zp * v2.yp, + v1.zp * v2.xp - v1.xp * v2.zp, + v1.xp * v2.yp - v1.yp * v2.xp); +} + +QDoubleVector3D QDoubleVector3D::normal(const QDoubleVector3D& v1, const QDoubleVector3D& v2) +{ + return crossProduct(v1, v2).normalized(); +} + +QDoubleVector3D QDoubleVector3D::normal + (const QDoubleVector3D& v1, const QDoubleVector3D& v2, const QDoubleVector3D& v3) +{ + return crossProduct((v2 - v1), (v3 - v1)).normalized(); +} + +double QDoubleVector3D::distanceToPlane + (const QDoubleVector3D& plane, const QDoubleVector3D& normal) const +{ + return dotProduct(*this - plane, normal); +} + +double QDoubleVector3D::distanceToPlane + (const QDoubleVector3D& plane1, const QDoubleVector3D& plane2, const QDoubleVector3D& plane3) const +{ + QDoubleVector3D n = normal(plane2 - plane1, plane3 - plane1); + return dotProduct(*this - plane1, n); +} + +double QDoubleVector3D::distanceToLine + (const QDoubleVector3D& point, const QDoubleVector3D& direction) const +{ + if (direction.isNull()) + return (*this - point).length(); + QDoubleVector3D p = point + dotProduct(*this - point, direction) * direction; + return (*this - p).length(); +} + +QDoubleVector2D QDoubleVector3D::toVector2D() const +{ + return QDoubleVector2D(xp, yp); +} + +double QDoubleVector3D::length() const +{ + return qSqrt(xp * xp + yp * yp + zp * zp); +} + +double QDoubleVector3D::lengthSquared() const +{ + return xp * xp + yp * yp + zp * zp; +} + +#ifndef QT_NO_DEBUG_STREAM + +QDebug operator<<(QDebug dbg, const QDoubleVector3D &vector) +{ + dbg.nospace() << "QDoubleVector3D(" + << vector.x() << ", " << vector.y() << ", " << vector.z() << ')'; + return dbg.space(); +} + +#endif + +#ifndef QT_NO_DATASTREAM + +QDataStream &operator<<(QDataStream &stream, const QDoubleVector3D &vector) +{ + stream << double(vector.x()) << double(vector.y()) + << double(vector.z()); + return stream; +} + +QDataStream &operator>>(QDataStream &stream, QDoubleVector3D &vector) +{ + double x, y, z; + stream >> x; + stream >> y; + stream >> z; + vector.setX(double(x)); + vector.setY(double(y)); + vector.setZ(double(z)); + return stream; +} + +#endif // QT_NO_DATASTREAM + +QT_END_NAMESPACE diff --git a/src/location/maps/qdoublevector3d_p.h b/src/location/maps/qdoublevector3d_p.h new file mode 100644 index 00000000..26c426bf --- /dev/null +++ b/src/location/maps/qdoublevector3d_p.h @@ -0,0 +1,294 @@ +/**************************************************************************** +** +** 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 QtGui 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 QDOUBLEVECTOR3D_P_H +#define QDOUBLEVECTOR3D_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 + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QDoubleVector2D; + +class QDoubleVector3D +{ +public: + QDoubleVector3D(); + QDoubleVector3D(double xpos, double ypos, double zpos); + explicit QDoubleVector3D(const QVector3D &vector); + QDoubleVector3D(const QDoubleVector2D& vector); + QDoubleVector3D(const QDoubleVector2D& vector, double zpos); + + operator QVector3D() const; + + bool isNull() const; + + double x() const; + double y() const; + double z() const; + + void setX(double x); + void setY(double y); + void setZ(double z); + + double get(int i) const; + void set(int i, double value); + + double length() const; + double lengthSquared() const; + + QDoubleVector3D normalized() const; + void normalize(); + + QDoubleVector3D &operator+=(const QDoubleVector3D &vector); + QDoubleVector3D &operator-=(const QDoubleVector3D &vector); + QDoubleVector3D &operator*=(double factor); + QDoubleVector3D &operator*=(const QDoubleVector3D& vector); + QDoubleVector3D &operator/=(double divisor); + + static double dotProduct(const QDoubleVector3D& v1, const QDoubleVector3D& v2); + static QDoubleVector3D crossProduct(const QDoubleVector3D& v1, const QDoubleVector3D& v2); + static QDoubleVector3D normal(const QDoubleVector3D& v1, const QDoubleVector3D& v2); + static QDoubleVector3D normal + (const QDoubleVector3D& v1, const QDoubleVector3D& v2, const QDoubleVector3D& v3); + + double distanceToPlane(const QDoubleVector3D& plane, const QDoubleVector3D& normal) const; + double distanceToPlane(const QDoubleVector3D& plane1, const QDoubleVector3D& plane2, const QDoubleVector3D& plane3) const; + double distanceToLine(const QDoubleVector3D& point, const QDoubleVector3D& direction) const; + + friend inline bool operator==(const QDoubleVector3D &v1, const QDoubleVector3D &v2); + friend inline bool operator!=(const QDoubleVector3D &v1, const QDoubleVector3D &v2); + friend inline const QDoubleVector3D operator+(const QDoubleVector3D &v1, const QDoubleVector3D &v2); + friend inline const QDoubleVector3D operator-(const QDoubleVector3D &v1, const QDoubleVector3D &v2); + friend inline const QDoubleVector3D operator*(double factor, const QDoubleVector3D &vector); + friend inline const QDoubleVector3D operator*(const QDoubleVector3D &vector, double factor); + friend const QDoubleVector3D operator*(const QDoubleVector3D &v1, const QDoubleVector3D& v2); + friend inline const QDoubleVector3D operator-(const QDoubleVector3D &vector); + friend inline const QDoubleVector3D operator/(const QDoubleVector3D &vector, double divisor); + + friend inline bool qFuzzyCompare(const QDoubleVector3D& v1, const QDoubleVector3D& v2); + + QDoubleVector2D toVector2D() const; + +private: + double xp, yp, zp; + + friend class QDoubleVector2D; +}; + +Q_DECLARE_TYPEINFO(QDoubleVector3D, Q_MOVABLE_TYPE); + +inline QDoubleVector3D::QDoubleVector3D() : xp(0.0), yp(0.0), zp(0.0) {} + +inline QDoubleVector3D::QDoubleVector3D(const QVector3D &vector) : xp(vector.x()), yp(vector.y()), zp(vector.z()) {} + +inline QDoubleVector3D::QDoubleVector3D(double xpos, double ypos, double zpos) : xp(xpos), yp(ypos), zp(zpos) {} + +inline QDoubleVector3D::operator QVector3D() const +{ + return QVector3D(xp, yp, zp); +} + +inline bool QDoubleVector3D::isNull() const +{ + return qIsNull(xp) && qIsNull(yp) && qIsNull(zp); +} + +inline double QDoubleVector3D::x() const { return xp; } +inline double QDoubleVector3D::y() const { return yp; } +inline double QDoubleVector3D::z() const { return zp; } + +inline void QDoubleVector3D::setX(double aX) { xp = aX; } +inline void QDoubleVector3D::setY(double aY) { yp = aY; } +inline void QDoubleVector3D::setZ(double aZ) { zp = aZ; } + +inline double QDoubleVector3D::get(int i) const +{ + switch (i) { + case 0: + return xp; + case 1: + return yp; + case 2: + return zp; + default: + return 0.0; + } +} + +inline void QDoubleVector3D::set(int i, double value) +{ + switch (i) { + case 0: + xp = value; + break; + case 1: + yp = value; + break; + case 2: + zp = value; + break; + default: + break; + } +} + +inline QDoubleVector3D &QDoubleVector3D::operator+=(const QDoubleVector3D &vector) +{ + xp += vector.xp; + yp += vector.yp; + zp += vector.zp; + return *this; +} + +inline QDoubleVector3D &QDoubleVector3D::operator-=(const QDoubleVector3D &vector) +{ + xp -= vector.xp; + yp -= vector.yp; + zp -= vector.zp; + return *this; +} + +inline QDoubleVector3D &QDoubleVector3D::operator*=(double factor) +{ + xp *= factor; + yp *= factor; + zp *= factor; + return *this; +} + +inline QDoubleVector3D &QDoubleVector3D::operator*=(const QDoubleVector3D& vector) +{ + xp *= vector.xp; + yp *= vector.yp; + zp *= vector.zp; + return *this; +} + +inline QDoubleVector3D &QDoubleVector3D::operator/=(double divisor) +{ + xp /= divisor; + yp /= divisor; + zp /= divisor; + return *this; +} + +inline bool operator==(const QDoubleVector3D &v1, const QDoubleVector3D &v2) +{ + return v1.xp == v2.xp && v1.yp == v2.yp && v1.zp == v2.zp; +} + +inline bool operator!=(const QDoubleVector3D &v1, const QDoubleVector3D &v2) +{ + return v1.xp != v2.xp || v1.yp != v2.yp || v1.zp != v2.zp; +} + +inline const QDoubleVector3D operator+(const QDoubleVector3D &v1, const QDoubleVector3D &v2) +{ + return QDoubleVector3D(v1.xp + v2.xp, v1.yp + v2.yp, v1.zp + v2.zp); +} + +inline const QDoubleVector3D operator-(const QDoubleVector3D &v1, const QDoubleVector3D &v2) +{ + return QDoubleVector3D(v1.xp - v2.xp, v1.yp - v2.yp, v1.zp - v2.zp); +} + +inline const QDoubleVector3D operator*(double factor, const QDoubleVector3D &vector) +{ + return QDoubleVector3D(vector.xp * factor, vector.yp * factor, vector.zp * factor); +} + +inline const QDoubleVector3D operator*(const QDoubleVector3D &vector, double factor) +{ + return QDoubleVector3D(vector.xp * factor, vector.yp * factor, vector.zp * factor); +} + +inline const QDoubleVector3D operator*(const QDoubleVector3D &v1, const QDoubleVector3D& v2) +{ + return QDoubleVector3D(v1.xp * v2.xp, v1.yp * v2.yp, v1.zp * v2.zp); +} + +inline const QDoubleVector3D operator-(const QDoubleVector3D &vector) +{ + return QDoubleVector3D(-vector.xp, -vector.yp, -vector.zp); +} + +inline const QDoubleVector3D operator/(const QDoubleVector3D &vector, double divisor) +{ + return QDoubleVector3D(vector.xp / divisor, vector.yp / divisor, vector.zp / divisor); +} + +inline bool qFuzzyCompare(const QDoubleVector3D& v1, const QDoubleVector3D& v2) +{ + return qFuzzyCompare(v1.xp, v2.xp) && + qFuzzyCompare(v1.yp, v2.yp) && + qFuzzyCompare(v1.zp, v2.zp); +} + +#ifndef QT_NO_DEBUG_STREAM +Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QDoubleVector3D &vector); +#endif + +#ifndef QT_NO_DATASTREAM +Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QDoubleVector3D &); +Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QDoubleVector3D &); +#endif + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/location/maps/qgeocameratiles.cpp b/src/location/maps/qgeocameratiles.cpp new file mode 100644 index 00000000..7f5c2c33 --- /dev/null +++ b/src/location/maps/qgeocameratiles.cpp @@ -0,0 +1,746 @@ +/**************************************************************************** +** +** Copyright (C) 2012 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 "qgeocameratiles_p.h" + +#include "qgeocameradata_p.h" +#include "qgeoprojection_p.h" +#include "qgeotilespec.h" + +#include "qdoublevector2d_p.h" +#include "qdoublevector3d_p.h" + +#include "qgeomaptype.h" + +#include + +#include + +#include + +QT_BEGIN_NAMESPACE + +struct Frustum { + QDoubleVector3D topLeftNear; + QDoubleVector3D topLeftFar; + QDoubleVector3D topRightNear; + QDoubleVector3D topRightFar; + QDoubleVector3D bottomLeftNear; + QDoubleVector3D bottomLeftFar; + QDoubleVector3D bottomRightNear; + QDoubleVector3D bottomRightFar; +}; + +typedef QVector Polygon; + +class QGeoCameraTilesPrivate { +public: + QGeoCameraTilesPrivate(QSharedPointer projection); + ~QGeoCameraTilesPrivate(); + + QSharedPointer projection_; + QString pluginString_; + QGeoMapType mapType_; + QGeoCameraData camera_; + QSize screenSize_; + int tileSize_; + int maxZoom_; + QSet tiles_; + + void updateMetadata(); + void updateGeometry(); + + double sideLength() const; + + Frustum frustum() const; + + class LengthSorter { + public: + QDoubleVector3D base; + bool operator()(const QDoubleVector3D &lhs, const QDoubleVector3D &rhs) { + return (lhs - base).lengthSquared() < (rhs - base).lengthSquared(); + } + }; + + void appendZIntersects(const QDoubleVector3D &start, const QDoubleVector3D &end, double z, QVector &results) const; + Polygon frustumFootprint(const Frustum &frustum) const; + + QPair splitPolygonAtAxisValue(const Polygon &polygon, int axis, double value) const; + QPair clipFootprintToMap(const Polygon &footprint) const; + + QList > tileIntersections(double p1, int t1, double p2, int t2) const; + QSet tilesFromPolygon(const Polygon &polygon) const; + + struct TileMap + { + TileMap(int minY, int maxY); + + int size; + int minY; + int maxY; + QVector minX; + QVector maxX; + + void add(int tileX, int tileY); + }; +}; + +QGeoCameraTiles::QGeoCameraTiles(QSharedPointer projection) + : d_ptr(new QGeoCameraTilesPrivate(projection)) {} + +QGeoCameraTiles::~QGeoCameraTiles() +{ + delete d_ptr; +} + +void QGeoCameraTiles::setCamera(const QGeoCameraData &camera) +{ + Q_D(QGeoCameraTiles); + + if (d->camera_ == camera) + return; + + d->camera_ = camera; + d->updateGeometry(); +} + +void QGeoCameraTiles::setScreenSize(const QSize &size) +{ + Q_D(QGeoCameraTiles); + + if (d->screenSize_ == size) + return; + + d->screenSize_ = size; + d->updateGeometry(); +} + +void QGeoCameraTiles::setPluginString(const QString &pluginString) +{ + Q_D(QGeoCameraTiles); + + if (d->pluginString_ == pluginString) + return; + + d->pluginString_ = pluginString; + d->updateMetadata(); +} + +void QGeoCameraTiles::setMapType(const QGeoMapType &mapType) +{ + Q_D(QGeoCameraTiles); + + if (d->mapType_ == mapType) + return; + + d->mapType_ = mapType; + d->updateMetadata(); +} + +void QGeoCameraTiles::setTileSize(int tileSize) +{ + Q_D(QGeoCameraTiles); + + if (d->tileSize_ == tileSize) + return; + + d->tileSize_ = tileSize; + d->updateGeometry(); +} + +void QGeoCameraTiles::setMaximumZoomLevel(int maxZoom) +{ + Q_D(QGeoCameraTiles); + + if (d->maxZoom_ == maxZoom) + return; + + d->maxZoom_ = maxZoom; + d->updateGeometry(); +} + +QSet QGeoCameraTiles::tiles() const +{ + Q_D(const QGeoCameraTiles); + + return d->tiles_; +} + +QGeoCameraTilesPrivate::QGeoCameraTilesPrivate(QSharedPointer projection) + : projection_(projection) {} + +QGeoCameraTilesPrivate::~QGeoCameraTilesPrivate() {} + +void QGeoCameraTilesPrivate::updateMetadata() +{ + typedef QSet::const_iterator iter; + + QSet newTiles; + + iter i = tiles_.constBegin(); + iter end = tiles_.constEnd(); + + for (; i != end; ++i) { + QGeoTileSpec tile = *i; + newTiles.insert(QGeoTileSpec(pluginString_, mapType_.mapId(), tile.zoom(), tile.x(), tile.y())); + } + + tiles_ = newTiles; +} + +void QGeoCameraTilesPrivate::updateGeometry() +{ + tiles_.clear(); + + // Find the frustum from the camera / screen / viewport information + Frustum f = frustum(); + + // Find the polygon where the frustum intersects the plane of the map + Polygon footprint = frustumFootprint(f); + + // Clip the polygon to the map, split it up if it cross the dateline + QPair polygons = clipFootprintToMap(footprint); + + if (!polygons.first.isEmpty()) { + tiles_.unite(tilesFromPolygon(polygons.first)); + } + + if (!polygons.second.isEmpty()) { + tiles_.unite(tilesFromPolygon(polygons.second)); + } +} + +double QGeoCameraTilesPrivate::sideLength() const +{ + return double(1 << camera_.zoomLevel()); +} + +Frustum QGeoCameraTilesPrivate::frustum() const +{ + int zpow2 = 1 << camera_.zoomLevel(); + + QDoubleVector3D center = zpow2 * projection_->coordToMercator(camera_.center()); + center.setZ(0.0); + + double f = qMin(screenSize_.width(), screenSize_.height()) / (1.0 * tileSize_); + + double z = pow(2.0, camera_.zoomFactor() - camera_.zoomLevel()); + + double altitude = f / (2.0 * z); + QDoubleVector3D eye = center; + eye.setZ(altitude); + + QDoubleVector3D view = eye - center; + QDoubleVector3D side = QDoubleVector3D::normal(view, QDoubleVector3D(0.0, 1.0, 0.0)); + QDoubleVector3D up = QDoubleVector3D::normal(side, view); + + double nearPlane = zpow2 / (1.0 * tileSize_ * (1 << maxZoom_)); + double farPlane = 3.0; + + double aspectRatio = 1.0 * screenSize_.width() / screenSize_.height(); + + double hn = 0.0; + double wn = 0.0; + double hf = 0.0; + double wf = 0.0; + + // fixes field of view at 45 degrees + // this assumes that viewSize = 2*nearPlane x 2*nearPlane + + if (aspectRatio > 1.0) { + hn = 2 * nearPlane; + wn = hn * aspectRatio; + + hf = 2 * farPlane; + wf = hf * aspectRatio; + } else { + wn = 2 * nearPlane; + hn = wn / aspectRatio; + + wf = 2 * farPlane; + hf = wf / aspectRatio; + } + + QDoubleVector3D d = center - eye; + d.normalize(); + up.normalize(); + QDoubleVector3D right = QDoubleVector3D::normal(d, up); + + QDoubleVector3D cf = eye + d * farPlane; + QDoubleVector3D cn = eye + d * nearPlane; + + Frustum frustum; + + frustum.topLeftFar = cf + (up * hf / 2) - (right * wf / 2); + frustum.topRightFar = cf + (up * hf / 2) + (right * wf / 2); + frustum.bottomLeftFar = cf - (up * hf / 2) - (right * wf / 2); + frustum.bottomRightFar = cf - (up * hf / 2) + (right * wf / 2); + + frustum.topLeftNear = cn + (up * hn / 2) - (right * wn / 2); + frustum.topRightNear = cn + (up * hn / 2) + (right * wn / 2); + frustum.bottomLeftNear = cn - (up * hn / 2) - (right * wn / 2); + frustum.bottomRightNear = cn - (up * hn / 2) + (right * wn / 2); + + return frustum; +} + +void QGeoCameraTilesPrivate::appendZIntersects(const QDoubleVector3D &start, + const QDoubleVector3D &end, + double z, + QVector &results) const +{ + if (start.z() == end.z()) { + if (start.z() == z) { + results.append(start); + results.append(end); + } + } else { + double f = (start.z() - z) / (start.z() - end.z()); + if ((0 <= f) && (f <= 1.0)) { + results.append((1 - f) * start + f * end); + } + } +} + +// Returns the intersection of the plane of the map and the camera frustum as a right handed polygon +Polygon QGeoCameraTilesPrivate::frustumFootprint(const Frustum &frustum) const +{ + Polygon points; + points.reserve(24); + + appendZIntersects(frustum.topLeftNear, frustum.topLeftFar, 0.0, points); + appendZIntersects(frustum.topRightNear, frustum.topRightFar, 0.0, points); + appendZIntersects(frustum.bottomLeftNear, frustum.bottomLeftFar, 0.0, points); + appendZIntersects(frustum.bottomRightNear, frustum.bottomRightFar, 0.0, points); + + appendZIntersects(frustum.topLeftNear, frustum.bottomLeftNear, 0.0, points); + appendZIntersects(frustum.bottomLeftNear, frustum.bottomRightNear, 0.0, points); + appendZIntersects(frustum.bottomRightNear, frustum.topRightNear, 0.0, points); + appendZIntersects(frustum.topRightNear, frustum.topLeftNear, 0.0, points); + + appendZIntersects(frustum.topLeftFar, frustum.bottomLeftFar, 0.0, points); + appendZIntersects(frustum.bottomLeftFar, frustum.bottomRightFar, 0.0, points); + appendZIntersects(frustum.bottomRightFar, frustum.topRightFar, 0.0, points); + appendZIntersects(frustum.topRightFar, frustum.topLeftFar, 0.0, points); + + if (points.isEmpty()) + return points; + + // 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.remove(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 + Polygon::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 + int size = points.size(); + if (size >= 3) { + QDoubleVector3D normal = QDoubleVector3D::normal(points.at(1) - points.at(0), + points.at(2) - points.at(1)); + // - if not, reverse the list + if (normal.z() < 0.0) { + int halfSize = size / 2; + for (int i = 0; i < halfSize; ++i) { + QDoubleVector3D spare = points.at(i); + points[i] = points[size - 1 - i]; + points[size - 1 - i] = spare; + } + } + } + + return points; +} + +QPair QGeoCameraTilesPrivate::splitPolygonAtAxisValue(const Polygon &polygon, int axis, double value) const +{ + Polygon polygonBelow; + Polygon polygonAbove; + + int size = polygon.size(); + + if (size == 0) { + return QPair(polygonBelow, polygonAbove); + } + + QVector comparisons = QVector(polygon.size()); + + for (int i = 0; i < size; ++i) { + double v = polygon.at(i).get(axis); + if (qFuzzyCompare(v - value + 1.0, 1.0)) { + comparisons[i] = 0; + } else { + if (v < value) { + comparisons[i] = -1; + } else if (value < v) { + comparisons[i] = 1; + } + } + } + + for (int index = 0; index < size; ++index) { + int prevIndex = index - 1; + if (prevIndex < 0) + prevIndex += size; + int nextIndex = (index + 1) % size; + + int prevComp = comparisons[prevIndex]; + int comp = comparisons[index]; + int nextComp = comparisons[nextIndex]; + + if (comp == 0) { + if (prevComp == -1) { + polygonBelow.append(polygon.at(index)); + if (nextComp == 1) { + polygonAbove.append(polygon.at(index)); + } + } else if (prevComp == 1) { + polygonAbove.append(polygon.at(index)); + if (nextComp == -1) { + polygonBelow.append(polygon.at(index)); + } + } else if (prevComp == 0) { + if (nextComp == -1) { + polygonBelow.append(polygon.at(index)); + } else if (nextComp == 1) { + polygonAbove.append(polygon.at(index)); + } else if (nextComp == 0) { + // do nothing + } + } + } else { + if (comp == -1) { + polygonBelow.append(polygon.at(index)); + } else if (comp == 1) { + polygonAbove.append(polygon.at(index)); + } + + // there is a point between this and the next point + // on the polygon that lies on the splitting line + // and should be added to both the below and above + // polygons + if ((nextComp != 0) && (nextComp != comp)) { + QDoubleVector3D p1 = polygon.at(index); + QDoubleVector3D p2 = polygon.at(nextIndex); + + double p1v = p1.get(axis); + double p2v = p2.get(axis); + + double f = (p1v - value) / (p1v - p2v); + + if (((0 <= f) && (f <= 1.0)) + || qFuzzyCompare(f + 1.0, 1.0) + || qFuzzyCompare(f + 1.0, 2.0) ) { + QDoubleVector3D midPoint = (1.0 - f) * p1 + f * p2; + polygonBelow.append(midPoint); + polygonAbove.append(midPoint); + } + } + } + } + + return QPair(polygonBelow, polygonAbove); +} + + +QPair QGeoCameraTilesPrivate::clipFootprintToMap(const Polygon &footprint) const +{ + bool clipX0 = false; + bool clipX1 = false; + bool clipY0 = false; + bool clipY1 = false; + + double side = sideLength(); + + typedef Polygon::iterator iter; + typedef Polygon::const_iterator const_iter; + + const_iter i = footprint.constBegin(); + const_iter end = footprint.constEnd(); + for (; i != end; ++i) { + QDoubleVector3D p = *i; + if (p.x() < 0.0) + clipX0 = true; + if (side < p.x()) + clipX1 = true; + if (p.y() < 0.0) + clipY0 = true; + if (side < p.y()) + clipY1 = true; + } + + Polygon results = footprint; + + if (clipY0) { + results = splitPolygonAtAxisValue(results, 1, 0.0).second; + } + + if (clipY1) { + results = splitPolygonAtAxisValue(results, 1, side).first; + } + + if (clipX0) { + if (clipX1) { + results = splitPolygonAtAxisValue(results, 0, 0.0).second; + results = splitPolygonAtAxisValue(results, 0, side).first; + return QPair(results, Polygon()); + } else { + QPair pair = splitPolygonAtAxisValue(results, 0, 0.0); + for (int i = 0; i < pair.first.size(); ++i) { + pair.first[i].setX(pair.first.at(i).x() + side); + } + return pair; + } + } else { + if (clipX1) { + QPair pair = splitPolygonAtAxisValue(results, 0, side); + for (int i = 0; i < pair.second.size(); ++i) { + pair.second[i].setX(pair.second.at(i).x() - side); + } + return pair; + } else { + return QPair(results, Polygon()); + } + } + +} + +QList > QGeoCameraTilesPrivate::tileIntersections(double p1, int t1, double p2, int t2) const +{ + if (t1 == t2) { + QList > results = QList >(); + results.append(QPair(0.0, t1)); + return results; + } + + int step = 1; + if (t1 > t2) { + step = -1; + } + + int size = 1 + ((t2 - t1) / step); + + QList > results = QList >(); + + results.append(QPair(0.0, t1)); + + if (step == 1) { + for (int i = 1; i < size; ++i) { + double f = (t1 + i - p1) / (p2 - p1); + results.append(QPair(f, t1 + i)); + } + } else { + for (int i = 1; i < size; ++i) { + double f = (t1 - i + 1 - p1) / (p2 - p1); + results.append(QPair(f, t1 - i)); + } + } + + return results; +} + +QSet QGeoCameraTilesPrivate::tilesFromPolygon(const Polygon &polygon) const +{ + int numPoints = polygon.size(); + + if (numPoints == 0) + return QSet(); + + int zoomLevel = camera_.zoomLevel(); + + int minY = -1; + int maxY = -1; + + int zpow2 = 1 << zoomLevel; + + QVector tilesX(polygon.size()); + QVector tilesY(polygon.size()); + + double side = sideLength(); + + for (int i = 0; i < numPoints; ++i) { + + QDoubleVector2D p = polygon.at(i).toVector2D(); + + int x = 0; + int y = 0; + + if (qFuzzyCompare(p.x(), side)) + x = zpow2 - 1; + else + x = static_cast(p.x()) % zpow2; + + if (qFuzzyCompare(p.y(), side)) + y = zpow2 - 1; + else + y = static_cast(p.y()) % zpow2; + + if (minY == -1) { + minY = y; + maxY = y; + } else { + minY = qMin(minY, y); + maxY = qMax(maxY, y); + } + + tilesX[i] = x; + tilesY[i] = y; + } + + QGeoCameraTilesPrivate::TileMap map(minY, maxY); + + for (int i1 = 0; i1 < numPoints; ++i1) { + int i2 = (i1 + 1) % numPoints; + + QList > xIntersects + = tileIntersections(polygon.at(i1).get(0), + tilesX.at(i1), + polygon.at(i2).get(0), + tilesX.at(i2)); + + QList > yIntersects + = tileIntersections(polygon.at(i1).get(1), + tilesY.at(i1), + polygon.at(i2).get(1), + tilesY.at(i2)); + + int x = xIntersects.takeFirst().second; + int y = yIntersects.takeFirst().second; + + map.add(x, y); + + while (!xIntersects.isEmpty() && !yIntersects.isEmpty()) { + QPair nextX = xIntersects.first(); + QPair nextY = yIntersects.first(); + if (nextX.first < nextY.first) { + x = nextX.second; + map.add(x, y); + xIntersects.removeFirst(); + } else if (nextX.first > nextY.first) { + y = nextY.second; + map.add(x, y); + yIntersects.removeFirst(); + } else { + map.add(x, nextY.second); + map.add(nextX.second, y); + x = nextX.second; + y = nextY.second; + map.add(x, y); + xIntersects.removeFirst(); + yIntersects.removeFirst(); + } + } + + while (!xIntersects.isEmpty()) { + x = xIntersects.takeFirst().second; + map.add(x, y); + } + + while (!yIntersects.isEmpty()) { + y = yIntersects.takeFirst().second; + map.add(x, y); + } + } + + QSet results; + + 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.insert(QGeoTileSpec(pluginString_, mapType_.mapId(), zoomLevel, x, y)); + } + } + + return results; +} + +QGeoCameraTilesPrivate::TileMap::TileMap(int minY, int maxY) + : size(0), + minY(minY), + maxY(maxY), + minX(maxY - minY + 1, -1), + maxX(maxY - minY + 1, -1) +{} + +void QGeoCameraTilesPrivate::TileMap::add(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); + } +} + +QT_END_NAMESPACE diff --git a/src/location/maps/qgeocameratiles_p.h b/src/location/maps/qgeocameratiles_p.h new file mode 100644 index 00000000..4f83317e --- /dev/null +++ b/src/location/maps/qgeocameratiles_p.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2012 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 QGEOCAMERATILES_P_H +#define QGEOCAMERATILES_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 +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoProjection; +class QGeoCameraData; +class QGeoTileSpec; +class QGeoMapType; + +class QGeoCameraTilesPrivate; + +class Q_LOCATION_EXPORT QGeoCameraTiles { +public: + QGeoCameraTiles(QSharedPointer projection); + ~QGeoCameraTiles(); + + void setCamera(const QGeoCameraData &camera); + void setScreenSize(const QSize &size); + void setPluginString(const QString &pluginString); + void setMapType(const QGeoMapType &mapType); + + void setTileSize(int tileSize); + void setMaximumZoomLevel(int maxZoom); + + QSet tiles() const; + +private: + QGeoCameraTilesPrivate *d_ptr; + Q_DECLARE_PRIVATE(QGeoCameraTiles) +}; + +QT_END_NAMESPACE + +#endif // QGEOCAMERATILES_P_H diff --git a/src/location/maps/qgeofrustum.cpp b/src/location/maps/qgeofrustum.cpp index 8d4bb290..35adc33e 100644 --- a/src/location/maps/qgeofrustum.cpp +++ b/src/location/maps/qgeofrustum.cpp @@ -68,14 +68,15 @@ void QGeoFrustum::update(const QGLCamera *camera, double aspectRatio, bool updat hf_ = wf_ / aspectRatio; } - QVector3D p = camera->eye(); - QVector3D d = camera->center() - camera->eye(); + QDoubleVector3D p = QDoubleVector3D(camera->eye()); + QDoubleVector3D d = QDoubleVector3D(camera->center()) - p; d.normalize(); - QVector3D up = camera->upVector(); + QDoubleVector3D up = QDoubleVector3D(camera->upVector()); + up.normalize(); - QVector3D right = QVector3D::normal(d, up); + QDoubleVector3D right = QDoubleVector3D::normal(d, up); cf_ = p + d * camera->farPlane(); tlf_ = cf_ + (up * hf_ / 2) - (right * wf_ / 2); @@ -117,7 +118,7 @@ void QGeoFrustum::update(const QGLCamera *camera, double aspectRatio, bool updat planeHash_.insert(QGeoFrustum::Planes(QGeoFrustum::Bottom), pb); } -bool QGeoFrustum::contains(const QVector3D ¢er, double radius) const +bool QGeoFrustum::contains(const QDoubleVector3D ¢er, double radius) const { if (planeHash_.isEmpty()) return false; diff --git a/src/location/maps/qgeofrustum_p.h b/src/location/maps/qgeofrustum_p.h index 1e0a3fa1..7d3553b7 100644 --- a/src/location/maps/qgeofrustum_p.h +++ b/src/location/maps/qgeofrustum_p.h @@ -52,11 +52,12 @@ // We mean it. // -#include #include #include +#include "qdoublevector3d_p.h" + QT_BEGIN_NAMESPACE class QGLCamera; @@ -87,30 +88,30 @@ public: void update(const QGLCamera *camera, double aspectRatio, bool updatePlanes = false); - bool contains(const QVector3D ¢er, double radius) const; + bool contains(const QDoubleVector3D ¢er, double radius) const; - QVector3D topLeftNear() const { + QDoubleVector3D topLeftNear() const { return tln_; } - QVector3D topLeftFar() const { + QDoubleVector3D topLeftFar() const { return tlf_; } - QVector3D bottomLeftNear() const { + QDoubleVector3D bottomLeftNear() const { return bln_; } - QVector3D bottomLeftFar() const { + QDoubleVector3D bottomLeftFar() const { return blf_; } - QVector3D topRightNear() const { + QDoubleVector3D topRightNear() const { return trn_; } - QVector3D topRightFar() const { + QDoubleVector3D topRightFar() const { return trf_; } - QVector3D bottomRightNear() const { + QDoubleVector3D bottomRightNear() const { return brn_; } - QVector3D bottomRightFar() const { + QDoubleVector3D bottomRightFar() const { return brf_; } @@ -119,19 +120,19 @@ public: private: double hf_; double wf_; - QVector3D cf_; - QVector3D tlf_; - QVector3D trf_; - QVector3D blf_; - QVector3D brf_; + QDoubleVector3D cf_; + QDoubleVector3D tlf_; + QDoubleVector3D trf_; + QDoubleVector3D blf_; + QDoubleVector3D brf_; double hn_; double wn_; - QVector3D cn_; - QVector3D tln_; - QVector3D trn_; - QVector3D bln_; - QVector3D brn_; + QDoubleVector3D cn_; + QDoubleVector3D tln_; + QDoubleVector3D trn_; + QDoubleVector3D bln_; + QDoubleVector3D brn_; QHash planeHash_; }; diff --git a/src/location/maps/qgeomap.cpp b/src/location/maps/qgeomap.cpp index 7f98902c..81f249c6 100644 --- a/src/location/maps/qgeomap.cpp +++ b/src/location/maps/qgeomap.cpp @@ -47,6 +47,10 @@ #include "qgeoprojection2d_p.h" #include "qgeotile_p.h" #include "qgeomapcontroller_p.h" +#include "qdoublevector2d_p.h" +#include "qdoublevector3d_p.h" + +#include "qgeocameratiles_p.h" #include "qgeomappingmanager.h" @@ -199,124 +203,6 @@ const QGeoMapType QGeoMap::activeMapType() const 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 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(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), @@ -333,28 +219,18 @@ QGeoMapPrivate::QGeoMapPrivate(QGeoMap *parent, QGeoTileCache *cache, int maxZoo sideLength_ = pow(2.0, 1.0 * maxZoom_) * tileSize; projection_ = QSharedPointer(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); + + cameraTiles_ = new QGeoCameraTiles(projection_); + cameraTiles_->setTileSize(tileSize_); + cameraTiles_->setMaximumZoomLevel(maxZoom_); } QGeoMapPrivate::~QGeoMapPrivate() { // controller_ is a child of map_, don't need to delete it here + + delete cameraTiles_; + manager_->deregisterMap(map_); delete sphere_; delete glCamera_; @@ -384,6 +260,7 @@ void QGeoMapPrivate::setMappingManager(QGeoMappingManager *manager) if (manager) { manager->registerMap(map_); pluginString_ = manager->managerName() + QLatin1String("_") + QString::number(manager->managerVersion()); + cameraTiles_->setPluginString(pluginString_); sphere_->setMappingManager(manager); } else { manager->deregisterMap(map_); @@ -410,8 +287,11 @@ void QGeoMapPrivate::setCameraData(const QGeoCameraData &cameraData) cameraData_.setProjection(projection_.toWeakRef()); updateGlCamera(glCamera_); updateFrustum(frustum_); - visibleTiles_ = updateVisibleTiles(); - sphere_->update(visibleTiles_); + + cameraTiles_->setCamera(cameraData_); + visibleTiles_ = cameraTiles_->tiles(); + + sphere_->update(visibleTiles_.toList()); } QGeoCameraData QGeoMapPrivate::cameraData() const @@ -421,7 +301,7 @@ QGeoCameraData QGeoMapPrivate::cameraData() const void QGeoMapPrivate::update() { - sphere_->update(visibleTiles_); + sphere_->update(visibleTiles_.toList()); } void QGeoMapPrivate::resize(int width, int height) @@ -429,45 +309,10 @@ void QGeoMapPrivate::resize(int width, int height) width_ = width; height_ = height; aspectRatio_ = 1.0 * width_ / height_; + cameraTiles_->setScreenSize(QSize(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(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(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_; @@ -483,18 +328,11 @@ double QGeoMapPrivate::aspectRatio() const return aspectRatio_; } -void QGeoMapPrivate::setActiveMapType(const QGeoMapType type) +void QGeoMapPrivate::setActiveMapType(const QGeoMapType &type) { activeMapType_ = type; - //TODO: check if this shared - //make it more optimal - //rewrite current specs - QList temp = visibleTiles_; - visibleTiles_.clear(); - foreach (QGeoTileSpec spec,temp) { - spec.setMapId(type.mapId()); - visibleTiles_ << spec; - } + cameraTiles_->setMapType(type); + visibleTiles_ = cameraTiles_->tiles(); map_->update(); } @@ -528,10 +366,10 @@ QRect QGeoMapPrivate::specToRect(const QGeoTileSpec &tileSpec) const 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)); + QDoubleVector3D tl = projection_->mercatorToPoint(QDoubleVector2D(x1, y1)); + QDoubleVector3D tr = projection_->mercatorToPoint(QDoubleVector2D(x2, y1)); + QDoubleVector3D bl = projection_->mercatorToPoint(QDoubleVector2D(x1, y2)); + QDoubleVector3D br = projection_->mercatorToPoint(QDoubleVector2D(x2, y2)); if (rightEdge) { tr.setX(sideLength_); @@ -563,10 +401,10 @@ QGLSceneNode* QGeoMapPrivate::createTileSpecNode(const QGeoTileSpec &tileSpec) 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)); + QDoubleVector3D tl = projection_->mercatorToPoint(QDoubleVector2D(x1, y1)); + QDoubleVector3D tr = projection_->mercatorToPoint(QDoubleVector2D(x2, y1)); + QDoubleVector3D bl = projection_->mercatorToPoint(QDoubleVector2D(x1, y2)); + QDoubleVector3D br = projection_->mercatorToPoint(QDoubleVector2D(x2, y2)); if (rightEdge) { tr.setX(sideLength_); @@ -592,23 +430,23 @@ QGLSceneNode* QGeoMapPrivate::createTileSpecNode(const QGeoTileSpec &tileSpec) QGeometryData g; - QVector3D n = QVector3D(0, 0, 1); + QDoubleVector3D n = QDoubleVector3D(0, 0, 1); g.appendVertex(tl); g.appendNormal(n); - g.appendTexCoord(QVector2D(tx1 * 1.0 / dz, ty1 * 1.0 / dz)); + g.appendTexCoord(QDoubleVector2D(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.appendTexCoord(QDoubleVector2D(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.appendTexCoord(QDoubleVector2D(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)); + g.appendTexCoord(QDoubleVector2D(tx2 * 1.0 / dz, ty1 * 1.0 / dz)); builder.addQuads(g); @@ -643,11 +481,11 @@ void QGeoMapPrivate::paintGL(QGLPainter *painter) glDisable(GL_DEPTH_TEST); - QVector3D c = camera->center(); + QDoubleVector3D c = QDoubleVector3D(camera->center()); c.setX(c.x() + sideLength_); camera->setCenter(c); - QVector3D e = camera->eye(); + QDoubleVector3D e = QDoubleVector3D(camera->eye()); e.setX(e.x() + sideLength_); camera->setEye(e); @@ -690,35 +528,37 @@ void QGeoMapPrivate::updateGlCamera(QGLCamera* glCamera) QGeoCoordinate coord = camera.center(); coord.setAltitude(0.0); - QVector3D center = projection_->coordToPoint(coord); + QDoubleVector3D center = projection_->coordToPoint(coord); coord.setAltitude(altitude); - QVector3D eye = projection_->coordToPoint(coord); + QDoubleVector3D 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); + QDoubleVector3D view = eye - center; + QDoubleVector3D side = QDoubleVector3D::normal(view, QDoubleVector3D(0.0, 1.0, 0.0)); + QDoubleVector3D up = QDoubleVector3D::normal(side, view); +/* QMatrix4x4 mBearing; mBearing.rotate(-1.0 * camera.bearing(), view); up = mBearing * up; - QVector3D side2 = QVector3D::normal(up, view); + QDoubleVector3D side2 = QDoubleVector3D::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); + side = QDoubleVector3D::normal(view, QDoubleVector3D(0.0, 1.0, 0.0)); + up = QDoubleVector3D::normal(view, side2); QMatrix4x4 mRoll; mRoll.rotate(camera.roll(), view); up = mRoll * up; +*/ double nearPlane = 1.0; double farPlane = 2.0 * altitude; @@ -776,25 +616,25 @@ QGeoCoordinate QGeoMapPrivate::screenPositionToCoordinate(const QPointF &pos) co x = (x + 1.0) / 2.0; y = (y + 1.0) / 2.0; - QVector3D tl = frustum_.topLeftFar(); - QVector3D tr = frustum_.topRightFar(); - QVector3D bl = frustum_.bottomLeftFar(); + QDoubleVector3D tl = frustum_.topLeftFar(); + QDoubleVector3D tr = frustum_.topRightFar(); + QDoubleVector3D bl = frustum_.bottomLeftFar(); - QVector3D n = (1 - x - y) * tl + x * tr + y * bl; + QDoubleVector3D n = (1 - x - y) * tl + x * tr + y * bl; if (eye_.z() == n.z()) return QGeoCoordinate(); double alpha = eye_.z() / (eye_.z() - n.z()); - QVector3D c = (1 - alpha) * eye_ + alpha * n; + QDoubleVector3D 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); + QDoubleVector3D c = projection_->coordToPoint(coordinate); + QDoubleVector3D d = QDoubleVector3D(projectionMatrix_.map(c)); QPointF point = QPointF((d.x() + 1.0) * width() / 2.0, (-d.y() + 1.0) * height() / 2.0); double side = pow(2.0, cameraData_.zoomFactor()) * tileSize_; @@ -836,526 +676,4 @@ void QGeoMapPrivate::updateFrustum(QGeoFrustum &frustum) frustum.update(glCamera(), cameraData().aspectRatio()); } -QList QGeoMapPrivate::updateVisibleTiles() -{ - QList 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 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::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 > 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 > pair = clipPolygonToMap(points); - if (!pair.first.isEmpty()) { - QPair, QList > 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 > 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 QGeoMapPrivate::tilesFromPoints(const QVector &points, bool roundUp) const -{ - int numPoints = points.size(); - - if (numPoints == 0) - return QList(); - - int zoomLevel = cameraData().zoomLevel(); - - int minY = -1; - int maxY = -1; - - QVector 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(t.y())); - maxY = qMax(maxY, static_cast(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 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 x = xGen.value(); - QPair 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 > QGeoMapPrivate::clipPolygonToMap(const QList &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 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 >(results, QList()); - } else { - QPair,QList > 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 > 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 >(results, QList()); - } - } -} - -QPair,QList > QGeoMapPrivate::splitPolygonY(const QList &points, double y) const -{ - QList pointsBelow; - QList pointsAbove; - - int size = points.size(); - - if (size == 0) { - return QPair,QList >(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 >(pointsBelow, pointsAbove); - } else { - return QPair,QList >(pointsBelow, points); - } - } else { - if (allBelow) { - return QPair,QList >(points, pointsAbove); - } - } - - - int intersect1 = -1; - int intersect2 = -1; - - // add intersects - - QList 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 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 >(pointsBelow, pointsAbove); - else - return QPair,QList >(pointsAbove, pointsBelow); - - } else { - qDebug() << __FUNCTION__ << " less than 2 intersections"; - } - - return QPair,QList >(pointsBelow, pointsAbove); -} - -QPair,QList > QGeoMapPrivate::splitPolygonX(const QList &points, double x) const -{ - QList pointsBelow; - QList pointsAbove; - - int size = points.size(); - - if (size == 0) { - return QPair,QList >(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 >(pointsBelow, pointsAbove); - } else { - return QPair,QList >(pointsBelow, points); - } - } else { - if (allBelow) { - return QPair,QList >(points, pointsAbove); - } - } - - int intersect1 = -1; - int intersect2 = -1; - - // add intersects - - QList 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 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 >(pointsBelow, pointsAbove); - else - return QPair,QList >(pointsAbove, pointsBelow); - - } else { - qDebug() << __FUNCTION__ << " less than 2 intersections"; - } - - return QPair,QList >(pointsBelow, pointsAbove); -} - -QList QGeoMapPrivate::pointsOnLineWithX(const QVector3D &p1, const QVector3D &p2, double x) const -{ - QList 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 QGeoMapPrivate::pointsOnLineWithY(const QVector3D &p1, const QVector3D &p2, double y) const -{ - QList 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 QGeoMapPrivate::pointsOnLineWithZ(const QVector3D &p1, const QVector3D &p2, double z) const -{ - QList 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; -} - QT_END_NAMESPACE diff --git a/src/location/maps/qgeomap_p_p.h b/src/location/maps/qgeomap_p_p.h index c686fb7e..300e7766 100644 --- a/src/location/maps/qgeomap_p_p.h +++ b/src/location/maps/qgeomap_p_p.h @@ -58,16 +58,15 @@ #include #include #include -#include #include #include +#include #include "qgeocameradata_p.h" #include "qgeofrustum_p.h" - #include "qgeomaptype.h" -#include +#include "qdoublevector3d_p.h" QT_BEGIN_NAMESPACE @@ -81,64 +80,12 @@ class QGeoMapController; class QGeoMapSphere; class QGeoProjection; +class QGeoCameraTiles; + class QGLCamera; class QGLSceneNode; class QGLPainter; -class QGeoMapPrivate; - -struct TileMap -{ - TileMap(int minY, int maxY); - - int size; - int minY; - int maxY; - QVector minX; - QVector 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 value() const; - void next(); - -private: - void generateValue(); - -protected: - const QGeoMapPrivate *mp_; - Axis axis_; - int zoomLevel_; - - bool hasNext_; - QPair value_; - - int current_; - int step_; - int end_; - - int adjust_; - double first_; - double denom_; -}; - class QGeoMapPrivate { public: @@ -170,21 +117,16 @@ public: void update(); const QGeoMapType activeMapType() const; - void setActiveMapType(const QGeoMapType mapType); + 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 updateVisibleTiles(); int width_; int height_; @@ -202,50 +144,23 @@ private: QGeoCameraData cameraData_; QGeoFrustum frustum_; - QList visibleTiles_; + QSet visibleTiles_; + + QGeoCameraTiles *cameraTiles_; 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 tilesFromPoints(const QVector &points, bool roundUp) const; - - QPair,QList > clipPolygonToMap(const QList &points) const; - - class LengthSorter { - public: - QVector3D base; - bool operator()(const QVector3D &lhs, const QVector3D &rhs) { - return (lhs - base).lengthSquared() < (rhs - base).lengthSquared(); - } - }; - - QList pointsOnLineWithX(const QVector3D &p1, const QVector3D &p2, double x) const; - QList pointsOnLineWithY(const QVector3D &p1, const QVector3D &p2, double y) const; - QList pointsOnLineWithZ(const QVector3D &p1, const QVector3D &p2, double z) const; - - QPair,QList > splitPolygonX(const QList &points, double x) const; - QPair,QList > splitPolygonY(const QList &points, double y) const; - int maxZoom_; int tileSize_; double baseHeight_; double sideLength_; - QPolygonF screenPoly_; - QPolygonF screenPolyLeft_; - QPolygonF screenPolyRight_; QSizeF viewSize_; - QVector3D eye_; + QDoubleVector3D eye_; QMatrix4x4 projectionMatrix_; }; diff --git a/src/location/maps/qgeoprojection.cpp b/src/location/maps/qgeoprojection.cpp index b751bcd4..ead0f61e 100644 --- a/src/location/maps/qgeoprojection.cpp +++ b/src/location/maps/qgeoprojection.cpp @@ -42,30 +42,31 @@ #include "qgeocoordinate.h" -#include -#include #include #include #include +#include "qdoublevector2d_p.h" +#include "qdoublevector3d_p.h" + QT_BEGIN_NAMESPACE QGeoProjection::QGeoProjection() {} QGeoProjection::~QGeoProjection() {} -QVector3D QGeoProjection::mercatorToPoint(const QVector2D &mercator) const +QDoubleVector3D QGeoProjection::mercatorToPoint(const QDoubleVector2D &mercator) const { return this->coordToPoint(mercatorToCoord(mercator)); } -QVector2D QGeoProjection::pointToMercator(const QVector3D &point) const +QDoubleVector2D QGeoProjection::pointToMercator(const QDoubleVector3D &point) const { return coordToMercator(this->pointToCoord(point)); } -QVector2D QGeoProjection::coordToMercator(const QGeoCoordinate &coord) const +QDoubleVector2D QGeoProjection::coordToMercator(const QGeoCoordinate &coord) const { const double pi = M_PI; @@ -76,7 +77,7 @@ QVector2D QGeoProjection::coordToMercator(const QGeoCoordinate &coord) const lat = qMax(0.0, lat); lat = qMin(1.0, lat); - return QVector2D(lon, lat); + return QDoubleVector2D(lon, lat); } double QGeoProjection::realmod(const double a, const double b) @@ -85,7 +86,7 @@ double QGeoProjection::realmod(const double a, const double b) return a - static_cast(div) * b; } -QGeoCoordinate QGeoProjection::mercatorToCoord(const QVector2D &mercator) const +QGeoCoordinate QGeoProjection::mercatorToCoord(const QDoubleVector2D &mercator) const { const double pi = M_PI; diff --git a/src/location/maps/qgeoprojection2d.cpp b/src/location/maps/qgeoprojection2d.cpp index b14c6a3f..a34c896a 100644 --- a/src/location/maps/qgeoprojection2d.cpp +++ b/src/location/maps/qgeoprojection2d.cpp @@ -42,8 +42,8 @@ #include "qgeocoordinate.h" -#include -#include +#include "qdoublevector2d_p.h" +#include "qdoublevector3d_p.h" #include @@ -54,31 +54,31 @@ QGeoProjection2D::QGeoProjection2D(double baseHeight, double sideLength) QGeoProjection2D::~QGeoProjection2D() {} -QVector3D QGeoProjection2D::coordToPoint(const QGeoCoordinate &coord) const +QDoubleVector3D QGeoProjection2D::coordToPoint(const QGeoCoordinate &coord) const { - QVector2D m = coordToMercator(coord); + QDoubleVector2D m = coordToMercator(coord); double z = baseHeight_; if (!qIsNaN(coord.altitude())) z += coord.altitude(); - return QVector3D(m.x() * sideLength_, (1.0 - m.y()) * sideLength_, z); + return QDoubleVector3D(m.x() * sideLength_, (1.0 - m.y()) * sideLength_, z); } -QGeoCoordinate QGeoProjection2D::pointToCoord(const QVector3D &point) const +QGeoCoordinate QGeoProjection2D::pointToCoord(const QDoubleVector3D &point) const { - QVector2D m = QVector2D(point.x() / sideLength_, 1.0 - point.y() / sideLength_); + QDoubleVector2D m = QDoubleVector2D(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 +QDoubleVector3D QGeoProjection2D::mercatorToPoint(const QDoubleVector2D &mercator) const { - return QVector3D(mercator.x() * sideLength_, (1.0 - mercator.y()) * sideLength_, baseHeight_); + return QDoubleVector3D(mercator.x() * sideLength_, (1.0 - mercator.y()) * sideLength_, baseHeight_); } -QVector2D QGeoProjection2D::pointToMercator(const QVector3D &point) const +QDoubleVector2D QGeoProjection2D::pointToMercator(const QDoubleVector3D &point) const { - return QVector2D(point.x() / sideLength_, 1.0 - (point.y() / sideLength_)); + return QDoubleVector2D(point.x() / sideLength_, 1.0 - (point.y() / sideLength_)); } QGeoCoordinate QGeoProjection2D::interpolate(const QGeoCoordinate &start, const QGeoCoordinate &end, qreal progress) @@ -95,8 +95,8 @@ QGeoCoordinate QGeoProjection2D::interpolate(const QGeoCoordinate &start, const s2.setAltitude(0.0); QGeoCoordinate e2 = end; e2.setAltitude(0.0); - QVector3D s = coordToPoint(s2); - QVector3D e = coordToPoint(e2); + QDoubleVector3D s = coordToPoint(s2); + QDoubleVector3D e = coordToPoint(e2); double x = s.x(); @@ -108,7 +108,7 @@ QGeoCoordinate QGeoProjection2D::interpolate(const QGeoCoordinate &start, const double y = (1.0 - progress) * s.y() + progress * e.y(); - QGeoCoordinate result = pointToCoord(QVector3D(x, y, 0.0)); + QGeoCoordinate result = pointToCoord(QDoubleVector3D(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 index d749d05b..2ceab778 100644 --- a/src/location/maps/qgeoprojection2d_p.h +++ b/src/location/maps/qgeoprojection2d_p.h @@ -62,11 +62,11 @@ public: QGeoProjection2D(double baseHeight, double sideLength); virtual ~QGeoProjection2D(); - virtual QVector3D coordToPoint(const QGeoCoordinate &coord) const; - virtual QGeoCoordinate pointToCoord(const QVector3D &point) const; + virtual QDoubleVector3D coordToPoint(const QGeoCoordinate &coord) const; + virtual QGeoCoordinate pointToCoord(const QDoubleVector3D &point) const; - virtual QVector3D mercatorToPoint(const QVector2D &mercator) const; - virtual QVector2D pointToMercator(const QVector3D &point) const; + virtual QDoubleVector3D mercatorToPoint(const QDoubleVector2D &mercator) const; + virtual QDoubleVector2D pointToMercator(const QDoubleVector3D &point) const; virtual QGeoCoordinate interpolate(const QGeoCoordinate &start, const QGeoCoordinate &end, qreal progress); diff --git a/src/location/maps/qgeoprojection_p.h b/src/location/maps/qgeoprojection_p.h index fb83a896..ec27d9ff 100644 --- a/src/location/maps/qgeoprojection_p.h +++ b/src/location/maps/qgeoprojection_p.h @@ -57,8 +57,8 @@ QT_BEGIN_NAMESPACE class QGeoCoordinate; -class QVector2D; -class QVector3D; +class QDoubleVector2D; +class QDoubleVector3D; class Q_AUTOTEST_EXPORT QGeoProjection { @@ -66,14 +66,14 @@ public: QGeoProjection(); virtual ~QGeoProjection(); - virtual QVector3D coordToPoint(const QGeoCoordinate &coord) const = 0; - virtual QGeoCoordinate pointToCoord(const QVector3D &point) const = 0; + virtual QDoubleVector3D coordToPoint(const QGeoCoordinate &coord) const = 0; + virtual QGeoCoordinate pointToCoord(const QDoubleVector3D &point) const = 0; - QVector2D coordToMercator(const QGeoCoordinate &coord) const; - QGeoCoordinate mercatorToCoord(const QVector2D &mercator) const; + QDoubleVector2D coordToMercator(const QGeoCoordinate &coord) const; + QGeoCoordinate mercatorToCoord(const QDoubleVector2D &mercator) const; - virtual QVector3D mercatorToPoint(const QVector2D &mercator) const; - virtual QVector2D pointToMercator(const QVector3D &point) const; + virtual QDoubleVector3D mercatorToPoint(const QDoubleVector2D &mercator) const; + virtual QDoubleVector2D pointToMercator(const QDoubleVector3D &point) const; virtual QGeoCoordinate interpolate(const QGeoCoordinate &start, const QGeoCoordinate &end, qreal progress) = 0; private: -- cgit v1.2.1