diff options
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 ¢er); 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() |