summaryrefslogtreecommitdiff
path: root/src/location/maps
diff options
context:
space:
mode:
authorDavid Laing <david.laing@nokia.com>2012-01-09 08:57:54 +1000
committerQt by Nokia <qt-info@nokia.com>2012-01-17 04:51:11 +0100
commita9506a1c73ada80262157ae4736a16cbc0fcb435 (patch)
treefffd04f6a3dc565794a1e42673b8d80c3c3eeeaf /src/location/maps
parentb37ebe9cc169b26dc547b8cb709784750a43dc66 (diff)
downloadqtlocation-a9506a1c73ada80262157ae4736a16cbc0fcb435.tar.gz
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 <alex.wilson@nokia.com>
Diffstat (limited to 'src/location/maps')
-rw-r--r--src/location/maps/maps.pri6
-rw-r--r--src/location/maps/qdoublevector2d.cpp132
-rw-r--r--src/location/maps/qdoublevector2d_p.h240
-rw-r--r--src/location/maps/qdoublevector3d.cpp187
-rw-r--r--src/location/maps/qdoublevector3d_p.h294
-rw-r--r--src/location/maps/qgeocameratiles.cpp746
-rw-r--r--src/location/maps/qgeocameratiles_p.h92
-rw-r--r--src/location/maps/qgeofrustum.cpp11
-rw-r--r--src/location/maps/qgeofrustum_p.h41
-rw-r--r--src/location/maps/qgeomap.cpp790
-rw-r--r--src/location/maps/qgeomap_p_p.h103
-rw-r--r--src/location/maps/qgeoprojection.cpp15
-rw-r--r--src/location/maps/qgeoprojection2d.cpp28
-rw-r--r--src/location/maps/qgeoprojection2d_p.h8
-rw-r--r--src/location/maps/qgeoprojection_p.h16
15 files changed, 1821 insertions, 888 deletions
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 <QtCore/qdebug.h>
+#include <QtCore/qmath.h>
+
+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 <QVector2D>
+
+#include <QtCore/qmetatype.h>
+
+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 <QtCore/qmath.h>
+#include <QtCore/qdebug.h>
+
+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 <QVector3D>
+
+#include <QtCore/qmetatype.h>
+
+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 <QVector>
+
+#include <QDebug>
+
+#include <cmath>
+
+QT_BEGIN_NAMESPACE
+
+struct Frustum {
+ QDoubleVector3D topLeftNear;
+ QDoubleVector3D topLeftFar;
+ QDoubleVector3D topRightNear;
+ QDoubleVector3D topRightFar;
+ QDoubleVector3D bottomLeftNear;
+ QDoubleVector3D bottomLeftFar;
+ QDoubleVector3D bottomRightNear;
+ QDoubleVector3D bottomRightFar;
+};
+
+typedef QVector<QDoubleVector3D> Polygon;
+
+class QGeoCameraTilesPrivate {
+public:
+ QGeoCameraTilesPrivate(QSharedPointer<QGeoProjection> projection);
+ ~QGeoCameraTilesPrivate();
+
+ QSharedPointer<QGeoProjection> projection_;
+ QString pluginString_;
+ QGeoMapType mapType_;
+ QGeoCameraData camera_;
+ QSize screenSize_;
+ int tileSize_;
+ int maxZoom_;
+ QSet<QGeoTileSpec> 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<QDoubleVector3D> &results) const;
+ Polygon frustumFootprint(const Frustum &frustum) const;
+
+ QPair<Polygon, Polygon> splitPolygonAtAxisValue(const Polygon &polygon, int axis, double value) const;
+ QPair<Polygon, Polygon> clipFootprintToMap(const Polygon &footprint) const;
+
+ QList<QPair<double, int> > tileIntersections(double p1, int t1, double p2, int t2) const;
+ QSet<QGeoTileSpec> tilesFromPolygon(const Polygon &polygon) const;
+
+ struct TileMap
+ {
+ TileMap(int minY, int maxY);
+
+ int size;
+ int minY;
+ int maxY;
+ QVector<int> minX;
+ QVector<int> maxX;
+
+ void add(int tileX, int tileY);
+ };
+};
+
+QGeoCameraTiles::QGeoCameraTiles(QSharedPointer<QGeoProjection> 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<QGeoTileSpec> QGeoCameraTiles::tiles() const
+{
+ Q_D(const QGeoCameraTiles);
+
+ return d->tiles_;
+}
+
+QGeoCameraTilesPrivate::QGeoCameraTilesPrivate(QSharedPointer<QGeoProjection> projection)
+ : projection_(projection) {}
+
+QGeoCameraTilesPrivate::~QGeoCameraTilesPrivate() {}
+
+void QGeoCameraTilesPrivate::updateMetadata()
+{
+ typedef QSet<QGeoTileSpec>::const_iterator iter;
+
+ QSet<QGeoTileSpec> 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<Polygon, Polygon> 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<QDoubleVector3D> &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<Polygon, Polygon> QGeoCameraTilesPrivate::splitPolygonAtAxisValue(const Polygon &polygon, int axis, double value) const
+{
+ Polygon polygonBelow;
+ Polygon polygonAbove;
+
+ int size = polygon.size();
+
+ if (size == 0) {
+ return QPair<Polygon, Polygon>(polygonBelow, polygonAbove);
+ }
+
+ QVector<int> comparisons = QVector<int>(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<Polygon, Polygon>(polygonBelow, polygonAbove);
+}
+
+
+QPair<Polygon, Polygon> 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<Polygon, Polygon>(results, Polygon());
+ } else {
+ QPair<Polygon, Polygon> 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<Polygon, Polygon> 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<Polygon, Polygon>(results, Polygon());
+ }
+ }
+
+}
+
+QList<QPair<double, int> > QGeoCameraTilesPrivate::tileIntersections(double p1, int t1, double p2, int t2) const
+{
+ if (t1 == t2) {
+ QList<QPair<double, int> > results = QList<QPair<double, int> >();
+ results.append(QPair<double, int>(0.0, t1));
+ return results;
+ }
+
+ int step = 1;
+ if (t1 > t2) {
+ step = -1;
+ }
+
+ int size = 1 + ((t2 - t1) / step);
+
+ QList<QPair<double, int> > results = QList<QPair<double, int> >();
+
+ results.append(QPair<double, int>(0.0, t1));
+
+ if (step == 1) {
+ for (int i = 1; i < size; ++i) {
+ double f = (t1 + i - p1) / (p2 - p1);
+ results.append(QPair<double, int>(f, t1 + i));
+ }
+ } else {
+ for (int i = 1; i < size; ++i) {
+ double f = (t1 - i + 1 - p1) / (p2 - p1);
+ results.append(QPair<double, int>(f, t1 - i));
+ }
+ }
+
+ return results;
+}
+
+QSet<QGeoTileSpec> QGeoCameraTilesPrivate::tilesFromPolygon(const Polygon &polygon) const
+{
+ int numPoints = polygon.size();
+
+ if (numPoints == 0)
+ return QSet<QGeoTileSpec>();
+
+ int zoomLevel = camera_.zoomLevel();
+
+ int minY = -1;
+ int maxY = -1;
+
+ int zpow2 = 1 << zoomLevel;
+
+ QVector<int> tilesX(polygon.size());
+ QVector<int> 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<int>(p.x()) % zpow2;
+
+ if (qFuzzyCompare(p.y(), side))
+ y = zpow2 - 1;
+ else
+ y = static_cast<int>(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<QPair<double, int> > xIntersects
+ = tileIntersections(polygon.at(i1).get(0),
+ tilesX.at(i1),
+ polygon.at(i2).get(0),
+ tilesX.at(i2));
+
+ QList<QPair<double, int> > 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<double, int> nextX = xIntersects.first();
+ QPair<double, int> 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<QGeoTileSpec> 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 <QtLocation/qlocationglobal.h>
+#include <QSharedPointer>
+#include <QSet>
+#include <QSize>
+#include <QSizeF>
+
+QT_BEGIN_NAMESPACE
+
+class QGeoProjection;
+class QGeoCameraData;
+class QGeoTileSpec;
+class QGeoMapType;
+
+class QGeoCameraTilesPrivate;
+
+class Q_LOCATION_EXPORT QGeoCameraTiles {
+public:
+ QGeoCameraTiles(QSharedPointer<QGeoProjection> 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<QGeoTileSpec> 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 &center, double radius) const
+bool QGeoFrustum::contains(const QDoubleVector3D &center, 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 <QVector3D>
#include <QHash>
#include <Qt3D/qplane3d.h>
+#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 &center, double radius) const;
+ bool contains(const QDoubleVector3D &center, 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<Planes, QPlane3D> 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<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),
@@ -333,28 +219,18 @@ QGeoMapPrivate::QGeoMapPrivate(QGeoMap *parent, QGeoTileCache *cache, int maxZoo
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);
+
+ 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<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_;
@@ -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<QGeoTileSpec> 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<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;
-}
-
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 <QPair>
#include <QPolygonF>
#include <QSizeF>
-#include <QVector3D>
#include <QMatrix4x4>
#include <QString>
+#include <QSharedPointer>
#include "qgeocameradata_p.h"
#include "qgeofrustum_p.h"
-
#include "qgeomaptype.h"
-#include <QSharedPointer>
+#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<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:
@@ -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<QGeoTileSpec> updateVisibleTiles();
int width_;
int height_;
@@ -202,50 +144,23 @@ private:
QGeoCameraData cameraData_;
QGeoFrustum frustum_;
- QList<QGeoTileSpec> visibleTiles_;
+ QSet<QGeoTileSpec> 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<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_;
+ 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 <qvector2d.h>
-#include <qvector3d.h>
#include <QMatrix4x4>
#include <qnumeric.h>
#include <cmath>
+#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<double>(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 <QVector2D>
-#include <QVector3D>
+#include "qdoublevector2d_p.h"
+#include "qdoublevector3d_p.h"
#include <qnumeric.h>
@@ -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: