summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Angelelli <paolo.angelelli@qt.io>2016-10-11 13:36:06 +0200
committerPaolo Angelelli <paolo.angelelli@qt.io>2017-01-25 13:25:38 +0000
commita66306d3d8eab810b769a536095dbfa2a0eb6ce2 (patch)
tree61843e32114732b10c238d25535c89c95911d0c1
parentbe13464a488ccc2837b0c178ff16086be341e570 (diff)
downloadqtlocation-a66306d3d8eab810b769a536095dbfa2a0eb6ce2.tar.gz
Add rotation and tilt controls to QDeclarativeGeoMap
QDeclarativeGeoMap currently does not provide any mean to set bearing and tilt into qgeocameradata. It has been not a problem since QGeoTiledMap and sons did not support it. External renderers however support it, so this patch adds QML api calls to control these parameters, and adapt the existing logic to take them into consideration in camera-related calls, as well as in the afterViewportChange handlers of the Map Items. This patch also sligthly modifies the QML api to make the handling of all the bounded camera property more homogeneous. Minimum and maximum zoom levels prior plugin initialization aren't -1 anymore, but are some valid lower and upper bounds for this property, that is 0 and 30. in this way all the 2 bounded properties (zoomLevel and tilt) behave the same, in that they can be freely set before plugin initialization, within reasonable predefined bounds, and, after that, they may be clamped depending on the actual plugin capabilities. Autotests for the QML part of the API included. Change-Id: I9d09e32698a7330388e465e8ea7523ee39577d34 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
-rw-r--r--src/imports/location/qdeclarativecirclemapitem.cpp12
-rw-r--r--src/imports/location/qdeclarativegeomap.cpp191
-rw-r--r--src/imports/location/qdeclarativegeomap_p.h25
-rw-r--r--src/imports/location/qdeclarativegeoserviceprovider.cpp3
-rw-r--r--src/imports/location/qdeclarativepolygonmapitem.cpp12
-rw-r--r--src/imports/location/qdeclarativepolylinemapitem.cpp11
-rw-r--r--src/imports/location/qdeclarativerectanglemapitem.cpp12
-rw-r--r--src/imports/location/qquickgeomapgesturearea.cpp1
-rw-r--r--src/imports/location/qquickgeomapgesturearea_p.h2
-rw-r--r--src/location/maps/qgeocameracapabilities.cpp2
-rw-r--r--src/location/maps/qgeocameradata.cpp2
-rw-r--r--src/location/maps/qgeomap.cpp4
-rw-r--r--src/location/maps/qgeomap_p.h4
-rw-r--r--src/location/maps/qgeoprojection.cpp15
-rw-r--r--src/location/maps/qgeoprojection_p.h4
-rw-r--r--src/location/maps/qgeotiledmapscene.cpp3
-rw-r--r--src/positioning/qlocationutils_p.h21
-rw-r--r--tests/auto/declarative_ui/tst_map.qml44
-rw-r--r--tests/auto/qgeotiledmapscene/tst_qgeotiledmapscene.cpp19
19 files changed, 280 insertions, 107 deletions
diff --git a/src/imports/location/qdeclarativecirclemapitem.cpp b/src/imports/location/qdeclarativecirclemapitem.cpp
index e107091c..7961305f 100644
--- a/src/imports/location/qdeclarativecirclemapitem.cpp
+++ b/src/imports/location/qdeclarativecirclemapitem.cpp
@@ -518,17 +518,7 @@ void QDeclarativeCircleMapItem::afterViewportChanged(const QGeoMapViewportChange
return;
// if the scene is tilted, we must regenerate our geometry every frame
- if (map()->cameraCapabilities().supportsTilting()
- && (event.cameraData.tilt() > 0.1
- || event.cameraData.tilt() < -0.1)) {
- geometry_.markSourceDirty();
- borderGeometry_.markSourceDirty();
- }
-
- // if the scene is rolled, we must regen too
- if (map()->cameraCapabilities().supportsRolling()
- && (event.cameraData.roll() > 0.1
- || event.cameraData.roll() < -0.1)) {
+ if ((event.cameraData.tilt() > 0.0 || event.tiltChanged) && map()->cameraCapabilities().supportsTilting()) {
geometry_.markSourceDirty();
borderGeometry_.markSourceDirty();
}
diff --git a/src/imports/location/qdeclarativegeomap.cpp b/src/imports/location/qdeclarativegeomap.cpp
index d19f6929..fb5a2472 100644
--- a/src/imports/location/qdeclarativegeomap.cpp
+++ b/src/imports/location/qdeclarativegeomap.cpp
@@ -308,14 +308,35 @@ void QDeclarativeGeoMap::setError(QGeoServiceProvider::Error error, const QStrin
void QDeclarativeGeoMap::initialize()
{
- // try to keep center change signal in the end
+ // try to keep change signals in the end
bool centerHasChanged = false;
+ bool bearingHasChanged = false;
+ bool tiltHasChanged = false;
+ bool minTiltHasChanged = false;
+ bool maxTiltHasChanged = false;
+
+ QGeoCoordinate center = m_cameraData.center();
setMinimumZoomLevel(m_map->minimumZoom());
- // set latitude bundary check
- m_maximumViewportLatitude = m_map->maximumCenterLatitudeAtZoom(m_cameraData.zoomLevel());
- QGeoCoordinate center = m_cameraData.center();
+ double bearing = m_cameraData.bearing();
+ double tilt = m_cameraData.tilt();
+ if (m_map->cameraCapabilities().minimumTilt() != 0)
+ minTiltHasChanged = true;
+ if (m_map->cameraCapabilities().maximumTilt() != 89)
+ maxTiltHasChanged = true;
+ if (!m_map->cameraCapabilities().supportsBearing() && bearing != 0.0) {
+ m_cameraData.setBearing(0);
+ bearingHasChanged = true;
+ }
+ if (!m_map->cameraCapabilities().supportsTilting() && tilt != 0.0) {
+ m_cameraData.setTilt(0);
+ tiltHasChanged = true;
+ }
+
+ // set latitude boundary check
+ m_maximumViewportLatitude = m_map->maximumCenterLatitudeAtZoom(m_cameraData);
+
center.setLatitude(qBound(-m_maximumViewportLatitude, center.latitude(), m_maximumViewportLatitude));
if (center != m_cameraData.center()) {
@@ -329,6 +350,18 @@ void QDeclarativeGeoMap::initialize()
if (centerHasChanged)
emit centerChanged(m_cameraData.center());
+
+ if (bearingHasChanged)
+ emit bearingChanged(m_cameraData.bearing());
+
+ if (tiltHasChanged)
+ emit tiltChanged(m_cameraData.tilt());
+
+ if (minTiltHasChanged)
+ emit minimumTiltChanged(m_map->cameraCapabilities().minimumTilt());
+
+ if (maxTiltHasChanged)
+ emit maximumTiltChanged(m_map->cameraCapabilities().maximumTilt());
}
/*!
@@ -565,9 +598,8 @@ void QDeclarativeGeoMap::mappingManagerInitialized()
//The zoom level limits are only restricted by the plugins values, if the user has set a more
//strict zoom level limit before initialization nothing is done here.
//minimum zoom level might be changed to limit gray bundaries
-
- if (m_gestureArea->maximumZoomLevel() < 0
- || m_mappingManager->cameraCapabilities().maximumZoomLevelAt256() < m_gestureArea->maximumZoomLevel())
+ //This code assumes that plugins' maximum zoom level will never exceed 30.0
+ if (m_mappingManager->cameraCapabilities().maximumZoomLevelAt256() < m_gestureArea->maximumZoomLevel())
setMaximumZoomLevel(m_mappingManager->cameraCapabilities().maximumZoomLevelAt256());
if (m_mappingManager->cameraCapabilities().minimumZoomLevelAt256() > m_gestureArea->minimumZoomLevel())
@@ -638,7 +670,6 @@ void QDeclarativeGeoMap::setMinimumZoomLevel(qreal minimumZoomLevel)
qreal oldMinimumZoomLevel = this->minimumZoomLevel();
if (m_map) {
-
minimumZoomLevel = qBound(qreal(m_map->cameraCapabilities().minimumZoomLevelAt256()), minimumZoomLevel, maximumZoomLevel());
double minimumViewportZoomLevel = m_map->minimumZoom();
if (minimumZoomLevel < minimumViewportZoomLevel)
@@ -666,17 +697,12 @@ void QDeclarativeGeoMap::setMinimumZoomLevel(qreal minimumZoomLevel)
defined by the plugin used, to prevent the map from being smaller than the
viewport in either dimension.
- If a plugin supporting mapping is not set, -1.0 is returned.
+ If a plugin supporting mapping is not set, 0.0 is returned.
*/
qreal QDeclarativeGeoMap::minimumZoomLevel() const
{
- if (m_gestureArea->minimumZoomLevel() != -1)
- return m_gestureArea->minimumZoomLevel();
- else if (m_map)
- return m_map->cameraCapabilities().minimumZoomLevelAt256();
- else
- return -1.0;
+ return m_gestureArea->minimumZoomLevel();
}
/*!
@@ -708,17 +734,12 @@ void QDeclarativeGeoMap::setMaximumZoomLevel(qreal maximumZoomLevel)
This property holds the maximum valid zoom level for the map.
The maximum zoom level is defined by the \l plugin used.
- If a plugin supporting mapping is not set, -1.0 is returned.
+ If a plugin supporting mapping is not set, 30.0 is returned.
*/
qreal QDeclarativeGeoMap::maximumZoomLevel() const
{
- if (m_gestureArea->maximumZoomLevel() != -1)
- return m_gestureArea->maximumZoomLevel();
- else if (m_map)
- return m_map->cameraCapabilities().minimumZoomLevelAt256();
- else
- return -1.0;
+ return m_gestureArea->maximumZoomLevel();
}
/*!
@@ -734,12 +755,12 @@ void QDeclarativeGeoMap::setZoomLevel(qreal zoomLevel)
if (m_cameraData.zoomLevel() == zoomLevel || zoomLevel < 0)
return;
- //small optiomatization to avoid double setCameraData
+ //small optimization to avoid double setCameraData
bool centerHasChanged = false;
if (m_initialized) {
m_cameraData.setZoomLevel(qBound(minimumZoomLevel(), zoomLevel, maximumZoomLevel()));
- m_maximumViewportLatitude = m_map->maximumCenterLatitudeAtZoom(m_cameraData.zoomLevel());
+ m_maximumViewportLatitude = m_map->maximumCenterLatitudeAtZoom(m_cameraData);
QGeoCoordinate coord = m_cameraData.center();
coord.setLatitude(qBound(-m_maximumViewportLatitude, coord.latitude(), m_maximumViewportLatitude));
if (coord != m_cameraData.center()) {
@@ -764,6 +785,126 @@ qreal QDeclarativeGeoMap::zoomLevel() const
}
/*!
+ \qmlproperty real QtLocation::Map::bearing
+
+ This property holds the bearing for the map.
+ The default value is 0.
+ If the Plugin used for the Map supports bearing, the valid range for this value is between 0 and 360.
+ If the Plugin used for the Map does not support bearing, changing this property will have no effect.
+
+ \since Qt Location 5.9
+*/
+void QDeclarativeGeoMap::setBearing(qreal bearing)
+{
+ bearing = std::fmod(bearing, qreal(360.0));
+ if (m_map && !m_map->cameraCapabilities().supportsBearing())
+ bearing = 0.0;
+ if (m_cameraData.bearing() == bearing || bearing < 0.0)
+ return;
+
+ m_cameraData.setBearing(bearing);
+ if (m_map)
+ m_map->setCameraData(m_cameraData);
+ emit bearingChanged(bearing);
+}
+
+qreal QDeclarativeGeoMap::bearing() const
+{
+ return m_cameraData.bearing();
+}
+
+/*!
+ \qmlproperty real QtLocation::Map::tilt
+
+ This property holds the tilt for the map.
+ The default value is 0.
+ If the Plugin used for the Map supports tilt, the valid range for this value is
+ [ plugin.minimumTilt, plugin.maximumTilt ].
+ If the Plugin used for the Map does not support tilting, changing this property will have no effect.
+
+ \since Qt Location 5.9
+*/
+void QDeclarativeGeoMap::setTilt(qreal tilt)
+{
+ tilt = qBound(minimumTilt(), tilt, maximumTilt());
+ if (m_cameraData.tilt() == tilt)
+ return;
+
+ m_cameraData.setTilt(tilt);
+ if (m_map)
+ m_map->setCameraData(m_cameraData);
+ emit tiltChanged(tilt);
+}
+
+qreal QDeclarativeGeoMap::tilt() const
+{
+ return m_cameraData.tilt();
+}
+
+/*!
+ \qmlproperty bool QtLocation::Map::bearingSupported
+
+ This property indicates if the Map supports bearing.
+ If the plugin property of the map is not set, or the plugin does not support mapping, this property is false.
+
+ \since Qt Location 5.9
+*/
+bool QDeclarativeGeoMap::isBearingSupported() const
+{
+ if (!m_map)
+ return false;
+ return m_map->cameraCapabilities().supportsBearing();
+}
+
+/*!
+ \qmlproperty bool QtLocation::Map::tiltingSupported
+
+ This property indicates if the Map supports tilting.
+ If the plugin property of the map is not set, or the plugin does not support mapping, this property is false.
+
+ \since Qt Location 5.9
+*/
+bool QDeclarativeGeoMap::isTiltingSupported() const
+{
+ if (!m_map)
+ return false;
+ return m_map->cameraCapabilities().supportsTilting();
+}
+
+/*!
+ \qmlproperty bool QtLocation::Map::minimumTilt
+
+ This property holds the minimum tilt that the map supports.
+ If the plugin property of the map is not set, or the plugin does not support mapping, this property is 0.
+
+ \since Qt Location 5.9
+*/
+qreal QDeclarativeGeoMap::minimumTilt() const
+{
+ if (!m_map || !m_map->cameraCapabilities().supportsTilting())
+ return 0.0;
+ return m_map->cameraCapabilities().minimumTilt();
+}
+
+/*!
+ \qmlproperty bool QtLocation::Map::maximumTilt
+
+ This property holds the maximum tilt that the map supports.
+ If the plugin property of the map is not set, this property is 89.
+ If the plugin is set and it does not support mapping, this property is 0.
+
+ \since Qt Location 5.9
+*/
+qreal QDeclarativeGeoMap::maximumTilt() const
+{
+ if (!m_map)
+ return 89.0;
+ else if (!m_map->cameraCapabilities().supportsTilting())
+ return 0.0;
+ return m_map->cameraCapabilities().maximumTilt();
+}
+
+/*!
\qmlproperty coordinate QtLocation::Map::center
This property holds the coordinate which occupies the center of the
@@ -1433,7 +1574,7 @@ void QDeclarativeGeoMap::geometryChanged(const QRectF &newGeometry, const QRectF
setMinimumZoomLevel(m_map->minimumZoom());
// Update the center latitudinal threshold
- double maximumCenterLatitudeAtZoom = m_map->maximumCenterLatitudeAtZoom(m_cameraData.zoomLevel());
+ double maximumCenterLatitudeAtZoom = m_map->maximumCenterLatitudeAtZoom(m_cameraData);
if (maximumCenterLatitudeAtZoom != m_maximumViewportLatitude) {
m_maximumViewportLatitude = maximumCenterLatitudeAtZoom;
QGeoCoordinate coord = m_cameraData.center();
diff --git a/src/imports/location/qdeclarativegeomap_p.h b/src/imports/location/qdeclarativegeomap_p.h
index e0940f97..71538e42 100644
--- a/src/imports/location/qdeclarativegeomap_p.h
+++ b/src/imports/location/qdeclarativegeomap_p.h
@@ -74,6 +74,14 @@ class QDeclarativeGeoMap : public QQuickItem
Q_PROPERTY(qreal minimumZoomLevel READ minimumZoomLevel WRITE setMinimumZoomLevel NOTIFY minimumZoomLevelChanged)
Q_PROPERTY(qreal maximumZoomLevel READ maximumZoomLevel WRITE setMaximumZoomLevel NOTIFY maximumZoomLevelChanged)
Q_PROPERTY(qreal zoomLevel READ zoomLevel WRITE setZoomLevel NOTIFY zoomLevelChanged)
+
+ Q_PROPERTY(bool bearingSupported READ isBearingSupported NOTIFY bearingSupportChanged)
+ Q_PROPERTY(bool tiltingSupported READ isTiltingSupported NOTIFY tiltingSupportChanged)
+ Q_PROPERTY(qreal minimumTilt READ minimumTilt NOTIFY minimumTiltChanged)
+ Q_PROPERTY(qreal maximumTilt READ maximumTilt NOTIFY maximumTiltChanged)
+ Q_PROPERTY(qreal bearing READ bearing WRITE setBearing NOTIFY bearingChanged)
+ Q_PROPERTY(qreal tilt READ tilt WRITE setTilt NOTIFY tiltChanged)
+
Q_PROPERTY(QDeclarativeGeoMapType *activeMapType READ activeMapType WRITE setActiveMapType NOTIFY activeMapTypeChanged)
Q_PROPERTY(QQmlListProperty<QDeclarativeGeoMapType> supportedMapTypes READ supportedMapTypes NOTIFY supportedMapTypesChanged)
Q_PROPERTY(QGeoCoordinate center READ center WRITE setCenter NOTIFY centerChanged)
@@ -106,6 +114,17 @@ public:
void setZoomLevel(qreal zoomLevel);
qreal zoomLevel() const;
+ void setBearing(qreal bearing);
+ qreal bearing() const;
+
+ void setTilt(qreal tilt);
+ qreal tilt() const;
+
+ bool isBearingSupported() const;
+ bool isTiltingSupported() const;
+ qreal minimumTilt() const;
+ qreal maximumTilt() const;
+
void setCenter(const QGeoCoordinate &center);
QGeoCoordinate center() const;
@@ -157,6 +176,12 @@ Q_SIGNALS:
void copyrightLinkActivated(const QString &link);
void copyrightsVisibleChanged(bool visible);
void colorChanged(const QColor &color);
+ void bearingChanged(qreal bearing);
+ void tiltChanged(qreal tilt);
+ void bearingSupportChanged(bool bearingSupport);
+ void tiltingSupportChanged(bool tiltingSupport);
+ void minimumTiltChanged(qreal minimumTilt);
+ void maximumTiltChanged(qreal maximumTilt);
protected:
void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE ;
diff --git a/src/imports/location/qdeclarativegeoserviceprovider.cpp b/src/imports/location/qdeclarativegeoserviceprovider.cpp
index 8ed6a7bf..994b4913 100644
--- a/src/imports/location/qdeclarativegeoserviceprovider.cpp
+++ b/src/imports/location/qdeclarativegeoserviceprovider.cpp
@@ -35,7 +35,6 @@
****************************************************************************/
#include "qdeclarativegeoserviceprovider_p.h"
-
#include <QtQml/QQmlInfo>
QT_BEGIN_NAMESPACE
@@ -421,7 +420,7 @@ void QDeclarativeGeoServiceProvider::setPreferred(const QStringList &val)
/*!
\qmlproperty bool Plugin::isAttached
- This property indicates if the Plugin is attached to another Plugin.
+ This property indicates if the Plugin item is attached to a geoservice provider plugin.
*/
bool QDeclarativeGeoServiceProvider::isAttached() const
{
diff --git a/src/imports/location/qdeclarativepolygonmapitem.cpp b/src/imports/location/qdeclarativepolygonmapitem.cpp
index 0e11db79..2268c885 100644
--- a/src/imports/location/qdeclarativepolygonmapitem.cpp
+++ b/src/imports/location/qdeclarativepolygonmapitem.cpp
@@ -567,17 +567,7 @@ void QDeclarativePolygonMapItem::afterViewportChanged(const QGeoMapViewportChang
return;
// if the scene is tilted, we must regenerate our geometry every frame
- if (map()->cameraCapabilities().supportsTilting()
- && (event.cameraData.tilt() > 0.1
- || event.cameraData.tilt() < -0.1)) {
- geometry_.markSourceDirty();
- borderGeometry_.markSourceDirty();
- }
-
- // if the scene is rolled, we must regen too
- if (map()->cameraCapabilities().supportsRolling()
- && (event.cameraData.roll() > 0.1
- || event.cameraData.roll() < -0.1)) {
+ if ((event.cameraData.tilt() > 0.0 || event.tiltChanged) && map()->cameraCapabilities().supportsTilting()) {
geometry_.markSourceDirty();
borderGeometry_.markSourceDirty();
}
diff --git a/src/imports/location/qdeclarativepolylinemapitem.cpp b/src/imports/location/qdeclarativepolylinemapitem.cpp
index 5fe0535d..a31fcbad 100644
--- a/src/imports/location/qdeclarativepolylinemapitem.cpp
+++ b/src/imports/location/qdeclarativepolylinemapitem.cpp
@@ -873,16 +873,7 @@ void QDeclarativePolylineMapItem::afterViewportChanged(const QGeoMapViewportChan
return;
// if the scene is tilted, we must regenerate our geometry every frame
- if (map()->cameraCapabilities().supportsTilting()
- && (event.cameraData.tilt() > 0.1
- || event.cameraData.tilt() < -0.1)) {
- geometry_.markSourceDirty();
- }
-
- // if the scene is rolled, we must regen too
- if (map()->cameraCapabilities().supportsRolling()
- && (event.cameraData.roll() > 0.1
- || event.cameraData.roll() < -0.1)) {
+ if ((event.cameraData.tilt() > 0.0 || event.tiltChanged) && map()->cameraCapabilities().supportsTilting()) {
geometry_.markSourceDirty();
}
diff --git a/src/imports/location/qdeclarativerectanglemapitem.cpp b/src/imports/location/qdeclarativerectanglemapitem.cpp
index b91c4c08..a3b8db90 100644
--- a/src/imports/location/qdeclarativerectanglemapitem.cpp
+++ b/src/imports/location/qdeclarativerectanglemapitem.cpp
@@ -372,17 +372,7 @@ void QDeclarativeRectangleMapItem::afterViewportChanged(const QGeoMapViewportCha
return;
// if the scene is tilted, we must regenerate our geometry every frame
- if (map()->cameraCapabilities().supportsTilting()
- && (event.cameraData.tilt() > 0.1
- || event.cameraData.tilt() < -0.1)) {
- geometry_.markSourceDirty();
- borderGeometry_.markSourceDirty();
- }
-
- // if the scene is rolled, we must regen too
- if (map()->cameraCapabilities().supportsRolling()
- && (event.cameraData.roll() > 0.1
- || event.cameraData.roll() < -0.1)) {
+ if ((event.cameraData.tilt() > 0.0 || event.tiltChanged) && map()->cameraCapabilities().supportsTilting()) {
geometry_.markSourceDirty();
borderGeometry_.markSourceDirty();
}
diff --git a/src/imports/location/qquickgeomapgesturearea.cpp b/src/imports/location/qquickgeomapgesturearea.cpp
index 50709292..54c3019b 100644
--- a/src/imports/location/qquickgeomapgesturearea.cpp
+++ b/src/imports/location/qquickgeomapgesturearea.cpp
@@ -46,7 +46,6 @@
#include <QtQuick/QQuickWindow>
#include <QPropertyAnimation>
#include <QDebug>
-#include <QtPositioning/private/qwebmercator_p.h>
#include "math.h"
#include "qgeomap_p.h"
#include "qdoublevector2d_p.h"
diff --git a/src/imports/location/qquickgeomapgesturearea_p.h b/src/imports/location/qquickgeomapgesturearea_p.h
index 51c5cc1e..41d7706a 100644
--- a/src/imports/location/qquickgeomapgesturearea_p.h
+++ b/src/imports/location/qquickgeomapgesturearea_p.h
@@ -242,7 +242,7 @@ private:
bool m_enabled;
struct Zoom
{
- Zoom() : m_minimum(-1.0), m_maximum(20.0), m_start(0.0), m_previous(0.0),
+ Zoom() : m_minimum(0.0), m_maximum(30.0), m_start(0.0), m_previous(0.0),
maximumChange(4.0) {}
qreal m_minimum;
qreal m_maximum;
diff --git a/src/location/maps/qgeocameracapabilities.cpp b/src/location/maps/qgeocameracapabilities.cpp
index 97ff5790..fca12a5c 100644
--- a/src/location/maps/qgeocameracapabilities.cpp
+++ b/src/location/maps/qgeocameracapabilities.cpp
@@ -62,6 +62,7 @@ public:
bool supportsTilting_;
// this is mutable so that it can be set from accessor functions that are const
+ // TODO: remove the mutable here
mutable bool valid_;
double minZoom_;
@@ -95,6 +96,7 @@ QGeoCameraCapabilitiesPrivate::QGeoCameraCapabilitiesPrivate(const QGeoCameraCap
maxTilt_(other.maxTilt_),
tileSize_(other.tileSize_) {}
+
QGeoCameraCapabilitiesPrivate::~QGeoCameraCapabilitiesPrivate() {}
QGeoCameraCapabilitiesPrivate &QGeoCameraCapabilitiesPrivate::operator = (const QGeoCameraCapabilitiesPrivate &other)
diff --git a/src/location/maps/qgeocameradata.cpp b/src/location/maps/qgeocameradata.cpp
index 909145fe..0d4c273e 100644
--- a/src/location/maps/qgeocameradata.cpp
+++ b/src/location/maps/qgeocameradata.cpp
@@ -82,7 +82,7 @@ QGeoCameraDataPrivate &QGeoCameraDataPrivate::operator = (const QGeoCameraDataPr
m_center = rhs.m_center;
m_bearing = rhs.m_bearing;
m_tilt = rhs.m_tilt;
- m_roll = rhs.m_roll;
+ m_roll = rhs.m_roll;;
m_zoomLevel = rhs.m_zoomLevel;
return *this;
diff --git a/src/location/maps/qgeomap.cpp b/src/location/maps/qgeomap.cpp
index 325ca83f..6c9c2b7f 100644
--- a/src/location/maps/qgeomap.cpp
+++ b/src/location/maps/qgeomap.cpp
@@ -118,10 +118,10 @@ double QGeoMap::minimumZoom() const
return d->m_geoProjection->minimumZoom();
}
-double QGeoMap::maximumCenterLatitudeAtZoom(double zoomLevel) const
+double QGeoMap::maximumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) const
{
Q_D(const QGeoMap);
- return d->m_geoProjection->maximumCenterLatitudeAtZoom(zoomLevel);
+ return d->m_geoProjection->maximumCenterLatitudeAtZoom(cameraData);
}
double QGeoMap::mapWidth() const
diff --git a/src/location/maps/qgeomap_p.h b/src/location/maps/qgeomap_p.h
index b5e51014..7f9fca8c 100644
--- a/src/location/maps/qgeomap_p.h
+++ b/src/location/maps/qgeomap_p.h
@@ -49,6 +49,7 @@
#include <QtLocation/private/qgeocameradata_p.h>
#include <QtLocation/private/qgeomaptype_p.h>
+#include <QtLocation/private/qgeocameracapabilities_p.h>
#include <QtCore/QObject>
#include <QtPositioning/private/qdoublevector2d_p.h>
#include <QtLocation/private/qgeoprojection_p.h>
@@ -58,7 +59,6 @@ QT_BEGIN_NAMESPACE
class QGeoMappingManagerEngine;
class QGeoMapPrivate;
class QGeoMapController;
-class QGeoCameraCapabilities;
class QGeoCoordinate;
class QSGNode;
class QQuickWindow;
@@ -87,7 +87,7 @@ public:
// returns the minimum zoom at the current viewport size
double minimumZoom() const;
- double maximumCenterLatitudeAtZoom(double zoomLevel) const;
+ double maximumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) const;
// returns the size of the underlying map, at the current zoom level. Unrelated to width()/height()/size().
double mapWidth() const;
diff --git a/src/location/maps/qgeoprojection.cpp b/src/location/maps/qgeoprojection.cpp
index dc7e78f8..b33f180f 100644
--- a/src/location/maps/qgeoprojection.cpp
+++ b/src/location/maps/qgeoprojection.cpp
@@ -98,9 +98,9 @@ double QGeoProjectionWebMercator::minimumZoom() const
// the amount of pixels between the center and the borders changes
// 2) when the zoom level changes, because the amount of pixels between the center
// and the borders stays the same, but the meters per pixel change
-double QGeoProjectionWebMercator::maximumCenterLatitudeAtZoom(double zoomLevel) const
+double QGeoProjectionWebMercator::maximumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) const
{
- double mapEdgeSize = std::pow(2.0, zoomLevel) * defaultTileSize;
+ double mapEdgeSize = std::pow(2.0, cameraData.zoomLevel()) * defaultTileSize;
// At init time weird things happen
int clampedWindowHeight = (m_viewportHeight > mapEdgeSize) ? mapEdgeSize : m_viewportHeight;
@@ -187,7 +187,7 @@ QDoubleVector2D QGeoProjectionWebMercator::wrappedMapProjectionToItemPosition(co
QDoubleVector2D QGeoProjectionWebMercator::itemPositionToWrappedMapProjection(const QDoubleVector2D &itemPosition) const
{
QDoubleVector2D pos = itemPosition;
- pos /= QDoubleVector2D(m_viewportWidth, m_viewportHeight);
+ pos *= QDoubleVector2D(m_1_viewportWidth, m_1_viewportHeight);
pos *= 2.0;
pos -= QDoubleVector2D(1.0,1.0);
pos *= QDoubleVector2D(m_halfWidth, m_halfHeight);
@@ -262,10 +262,9 @@ void QGeoProjectionWebMercator::setupCamera()
double z = std::pow(2.0, m_cameraData.zoomLevel() - intZoomLevel) * defaultTileSize;
double altitude = f / (2.0 * z) ;
+ //aperture(90 / 2) = 1
+ m_aperture = 0.41421356237309503; // For a field of view of 45 degrees, as 90 is loading too many tiles
// calculate eye
- // TODO: support field of view with apertureSize = tan(QLocationUtils::radians(m_cameraData.fieldOfView()) * 0.5);
- double m_aperture = 1.0; //aperture(90 / 2) = 1
-
m_eye = m_center;
m_eye.setZ(altitude * defaultTileSize / m_aperture);
@@ -300,8 +299,8 @@ void QGeoProjectionWebMercator::setupCamera()
double aspectRatio = 1.0 * m_viewportWidth / m_viewportHeight;
- m_halfWidth = 1 * m_aperture;
- m_halfHeight = 1 * m_aperture;
+ m_halfWidth = m_aperture;
+ m_halfHeight = m_aperture;
if (aspectRatio > 1.0) {
m_halfWidth *= aspectRatio;
} else if (aspectRatio > 0.0 && aspectRatio < 1.0) {
diff --git a/src/location/maps/qgeoprojection_p.h b/src/location/maps/qgeoprojection_p.h
index 61059fdd..c31f806b 100644
--- a/src/location/maps/qgeoprojection_p.h
+++ b/src/location/maps/qgeoprojection_p.h
@@ -65,7 +65,7 @@ public:
// returns the minimum zoom at the current viewport size
virtual double minimumZoom() const = 0;
- virtual double maximumCenterLatitudeAtZoom(double zoomLevel) const = 0;
+ virtual double maximumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) const = 0;
// returns the size of the underlying map, at the current zoom level.
virtual double mapWidth() const = 0;
@@ -95,7 +95,7 @@ public:
~QGeoProjectionWebMercator();
double minimumZoom() const Q_DECL_OVERRIDE;
- double maximumCenterLatitudeAtZoom(double zoomLevel) const Q_DECL_OVERRIDE;
+ double maximumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) const Q_DECL_OVERRIDE;
// The size of the underlying map, at the current zoom level.
double mapWidth() const Q_DECL_OVERRIDE;
diff --git a/src/location/maps/qgeotiledmapscene.cpp b/src/location/maps/qgeotiledmapscene.cpp
index 404dcd19..3e75cece 100644
--- a/src/location/maps/qgeotiledmapscene.cpp
+++ b/src/location/maps/qgeotiledmapscene.cpp
@@ -111,6 +111,7 @@ public:
bool buildGeometry(const QGeoTileSpec &spec, QSGImageNode *imageNode);
void setTileBounds(const QSet<QGeoTileSpec> &tiles);
void setupCamera();
+ inline bool isTiltedOrRotated() { return (m_cameraData.tilt() > 0.0) || (m_cameraData.bearing() > 0.0); }
};
QGeoTiledMapScene::QGeoTiledMapScene(QObject *parent)
@@ -140,7 +141,7 @@ void QGeoTiledMapScene::setCameraData(const QGeoCameraData &cameraData)
d->m_cameraData = cameraData;
d->m_intZoomLevel = static_cast<int>(std::floor(d->m_cameraData.zoomLevel()));
float delta = cameraData.zoomLevel() - d->m_intZoomLevel;
- d->m_linearScaling = qAbs(delta) > 0.05;
+ d->m_linearScaling = qAbs(delta) > 0.05 || d->isTiltedOrRotated();
d->m_sideLength = 1 << d->m_intZoomLevel;
}
diff --git a/src/positioning/qlocationutils_p.h b/src/positioning/qlocationutils_p.h
index 552ec33f..704a57f8 100644
--- a/src/positioning/qlocationutils_p.h
+++ b/src/positioning/qlocationutils_p.h
@@ -53,17 +53,11 @@
#include <QtCore/QtGlobal>
#include <math.h>
-#ifndef M_PI
-#define M_PI 3.14159265358979323846264338327950288
-#endif
-
-#ifndef M_1_180
-#define M_1_180 0.0055555555555555555555555555555555555555556
-#endif
-
-#ifndef M_1_PI
-#define M_1_PI 0.31830988618379067154
-#endif
+static const double M_PID = 3.14159265358979323846264338327950288; // to get more precision than float
+static const double M_1_180D = 0.0055555555555555555555555555555555555555556;
+static const double M_1_PID = 1.0 / M_PID;
+static const double M_PI_180D = M_PID / 180.0; //0.0174532925199432954743716805978692718781530857086181640625;
+static const double M_180_PID = 180.0 / M_PID; // 57.29577951308232286464772187173366546630859375
QT_BEGIN_NAMESPACE
class QTime;
@@ -211,14 +205,13 @@ public:
inline static double radians(double degrees)
{
- return degrees * M_PI * M_1_180;
+ return degrees * M_PI_180D;
}
inline static double degrees(double radians)
{
- return radians * 180.0 * M_1_PI;
+ return radians * M_180_PID;
}
-
inline static double earthMeanRadius()
{
return 6371007.2;
diff --git a/tests/auto/declarative_ui/tst_map.qml b/tests/auto/declarative_ui/tst_map.qml
index 998a06d4..1c0f4719 100644
--- a/tests/auto/declarative_ui/tst_map.qml
+++ b/tests/auto/declarative_ui/tst_map.qml
@@ -84,6 +84,12 @@ Item {
Map {id: coordinateMap; plugin: herePlugin; center: coordinate3;
width: 1000; height: 1000; zoomLevel: 15 }
+ Map {id: mapTiltBearing; plugin: testPlugin; center: coordinate1;
+ width: 1000; height: 1000; zoomLevel: 4; bearing: 45.0; tilt: 25.0 }
+
+ Map {id: mapTiltBearingHere; plugin: herePlugin; center: coordinate1;
+ width: 1000; height: 1000; zoomLevel: 4; bearing: 45.0; tilt: 25.0 }
+
MapParameter {
id: testParameter
type: "cameraCenter_test"
@@ -161,11 +167,11 @@ Item {
fuzzyCompare(center.latitude, -33, 0.1)
fuzzyCompare(center.longitude, -47, 0.1)
- testParameter.center = mapPar.center
+ testParameter.center = mapPar.center // map.center has not been affected as it lives in the Declarative Map
mapPar.addMapParameter(testParameter)
compare(mapPar.mapParameters.length, 1)
- var center = mapPar.toCoordinate(Qt.point((mapPar.width - 1) / 2.0, (mapPar.height - 1) / 2.0))
+ center = mapPar.toCoordinate(Qt.point((mapPar.width - 1) / 2.0, (mapPar.height - 1) / 2.0))
fuzzyCompare(center.latitude, 10, 0.1)
fuzzyCompare(center.longitude, 11, 0.1)
@@ -349,6 +355,40 @@ Item {
mapCenterSpy.clear()
}
+ function test_map_tilt_bearing()
+ {
+ compare(map.bearing, 0.0)
+ compare(map.tilt, 0.0)
+ compare(mapTiltBearing.bearing, 45.0)
+ compare(mapTiltBearing.tilt, 25.0)
+ compare(mapTiltBearingHere.bearing, 0.0)
+ compare(mapTiltBearingHere.tilt, 0.0)
+
+ mapTiltBearing.bearing = 0.0
+ mapTiltBearing.tilt = 0.0
+ compare(mapTiltBearing.bearing, 0.0)
+ compare(mapTiltBearing.tilt, 0.0)
+
+ mapTiltBearing.bearing = 480.0
+ mapTiltBearing.tilt = 140.0
+ compare(mapTiltBearing.bearing, 120.0)
+ compare(mapTiltBearing.tilt, 60.0)
+
+ mapTiltBearing.tilt = -140.0
+ compare(mapTiltBearing.tilt, 0.0)
+
+ mapTiltBearingHere.bearing = 45.0
+ mapTiltBearingHere.tilt = 25.0
+ compare(mapTiltBearingHere.bearing, 0.0)
+ compare(mapTiltBearingHere.tilt, 0.0)
+
+ mapTiltBearing.bearing = 45.0
+ mapTiltBearing.tilt = 25.0
+ mapTiltBearing.zoomLevel = 8.0
+ compare(mapTiltBearing.bearing, 45.0)
+ compare(mapTiltBearing.tilt, 25.0)
+ }
+
function test_coordinate_conversion()
{
wait(1000)
diff --git a/tests/auto/qgeotiledmapscene/tst_qgeotiledmapscene.cpp b/tests/auto/qgeotiledmapscene/tst_qgeotiledmapscene.cpp
index 91b3eda8..6b3dc1f6 100644
--- a/tests/auto/qgeotiledmapscene/tst_qgeotiledmapscene.cpp
+++ b/tests/auto/qgeotiledmapscene/tst_qgeotiledmapscene.cpp
@@ -152,7 +152,7 @@ class tst_QGeoTiledMapScene : public QObject
screenY = 0.0;
mercatorX = cameraCenterX - scaledHalfLengthX;
mercatorY = cameraCenterY - scaledHalfLengthY;
- row (name + QString("_topLeftrScreen"), screenX, screenX2, screenY, cameraCenterX, cameraCenterY,
+ row (name + QString("_topLeftScreen"), screenX, screenX2, screenY, cameraCenterX, cameraCenterY,
zoom, tileSize, screenWidth, screenHeight, mercatorX, mercatorY);
// top
@@ -288,6 +288,12 @@ class tst_QGeoTiledMapScene : public QObject
screenCameraPositions(name, zoom, tileSize, screenWidth, screenHeight);
}
+ // Calculates the distance in mercator space of 2 x coordinates, assuming that 1 == 0
+ double wrappedMercatorDistance(double x1, double x2)
+ {
+ return qMin(qMin(qAbs(x1 - 1.0 - x2), qAbs(x1 - x2)), qAbs(x1 + 1.0 - x2));
+ }
+
private slots:
void screenToMercatorPositions(){
QFETCH(double, screenX);
@@ -324,8 +330,15 @@ class tst_QGeoTiledMapScene : public QObject
QDoubleVector2D point(screenX,screenY);
QDoubleVector2D mercartorPos = projection.unwrapMapProjection(projection.itemPositionToWrappedMapProjection(point));
- QCOMPARE(mercartorPos.x(), mercatorX);
- QCOMPARE(mercartorPos.y(), mercatorY);
+ const double tolerance = 0.00000000001; // FuzzyCompare is too strict here
+ QVERIFY2(wrappedMercatorDistance(mercartorPos.x(), mercatorX) < tolerance,
+ qPrintable(QString("Accepted: %1 , Actual: %2")
+ .arg(QString::number(mercatorX))
+ .arg(QString::number(mercartorPos.x()))));
+ QVERIFY2(qAbs(mercartorPos.y() - mercatorY) < tolerance,
+ qPrintable(QString("Accepted: %1 , Actual: %2")
+ .arg(QString::number(mercatorY))
+ .arg(QString::number(mercartorPos.y()))));
}
void screenToMercatorPositions_data()