summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Angelelli <paolo.angelelli@qt.io>2018-06-19 16:33:44 +0200
committerPaolo Angelelli <paolo.angelelli@qt.io>2018-07-26 13:38:02 +0000
commiteca7cc8a260538fcccde97fe59d9580250600bf1 (patch)
tree6a87cc4391b1e0dbf65ee011d0314cfae4c8b19f
parentd6fc6ba0f84c4cda0ccc2e1250da4a68441dd6ba (diff)
downloadqtlocation-eca7cc8a260538fcccde97fe59d9580250600bf1.tar.gz
Introduce Map.visibleArea
This will allow moving the visible map area to a subregion of the viewport, allowing to maintain the desired visible region visible when overlaying controls on top of the map. Task-number: QTBUG-68966 Change-Id: Idf4b30f7c1e4062e5e1c0ddc01a31bc856c0bc0c Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
-rw-r--r--src/imports/location/location.cpp1
-rw-r--r--src/location/declarativemaps/qdeclarativegeomap.cpp107
-rw-r--r--src/location/declarativemaps/qdeclarativegeomap_p.h8
-rw-r--r--src/location/declarativemaps/qdeclarativegeomapitembase.cpp9
-rw-r--r--src/location/declarativemaps/qdeclarativegeomapitembase_p.h1
-rw-r--r--src/location/declarativemaps/qdeclarativegeomapquickitem.cpp4
-rw-r--r--src/location/maps/qgeocameratiles.cpp45
-rw-r--r--src/location/maps/qgeocameratiles_p.h2
-rw-r--r--src/location/maps/qgeomap.cpp51
-rw-r--r--src/location/maps/qgeomap_p.h8
-rw-r--r--src/location/maps/qgeomap_p_p.h7
-rw-r--r--src/location/maps/qgeoprojection.cpp113
-rw-r--r--src/location/maps/qgeoprojection_p.h8
-rw-r--r--src/location/maps/qgeotiledmap.cpp28
-rw-r--r--src/location/maps/qgeotiledmap_p_p.h4
-rw-r--r--src/location/maps/qgeotiledmapscene.cpp36
-rw-r--r--src/location/maps/qgeotiledmapscene_p.h1
-rw-r--r--src/plugins/geoservices/itemsoverlay/qgeomapitemsoverlay.cpp24
-rw-r--r--src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.cpp36
-rw-r--r--src/plugins/geoservices/mapboxgl/qgeomapmapboxgl_p.h13
-rw-r--r--src/plugins/geoservices/mapboxgl/qmapboxglstylechange.cpp41
-rw-r--r--src/plugins/geoservices/mapboxgl/qmapboxglstylechange_p.h13
-rw-r--r--tests/auto/declarative_ui/tst_map.qml41
-rw-r--r--tests/auto/geotestplugin/qgeotiledmap_test.cpp29
-rw-r--r--tests/auto/geotestplugin/qgeotiledmap_test.h8
-rw-r--r--tests/auto/geotestplugin/qgeotiledmappingmanagerengine_test.h10
26 files changed, 531 insertions, 117 deletions
diff --git a/src/imports/location/location.cpp b/src/imports/location/location.cpp
index b632836f..62debb1d 100644
--- a/src/imports/location/location.cpp
+++ b/src/imports/location/location.cpp
@@ -190,6 +190,7 @@ public:
minor = 12;
qmlRegisterType<QDeclarativeGeoMapItemView, 12>(uri, major, minor, "MapItemView");
qmlRegisterType<QDeclarativeSearchResultModel, 12>(uri, major, minor, "PlaceSearchModel");
+ qmlRegisterType<QDeclarativeGeoMap, 12>(uri, major, minor, "Map");
// Register the latest Qt version as QML type version
qmlRegisterModule(uri, QT_VERSION_MAJOR, QT_VERSION_MINOR);
diff --git a/src/location/declarativemaps/qdeclarativegeomap.cpp b/src/location/declarativemaps/qdeclarativegeomap.cpp
index faa25916..d201b6ab 100644
--- a/src/location/declarativemaps/qdeclarativegeomap.cpp
+++ b/src/location/declarativemaps/qdeclarativegeomap.cpp
@@ -333,6 +333,7 @@ void QDeclarativeGeoMap::initialize()
bool bearingHasChanged = false;
bool tiltHasChanged = false;
bool fovHasChanged = false;
+ bool visibleAreaHasChanged = false;
QGeoCoordinate center = m_cameraData.center();
@@ -354,6 +355,10 @@ void QDeclarativeGeoMap::initialize()
tiltHasChanged = true;
}
+ m_map->setVisibleArea(m_visibleArea);
+ if (m_map->visibleArea() != m_visibleArea)
+ visibleAreaHasChanged = true;
+
m_cameraData.setFieldOfView(qBound(m_cameraCapabilities.minimumFieldOfView(),
fov,
m_cameraCapabilities.maximumFieldOfView()));
@@ -362,8 +367,9 @@ void QDeclarativeGeoMap::initialize()
// set latitude boundary check
m_maximumViewportLatitude = m_map->maximumCenterLatitudeAtZoom(m_cameraData);
+ m_minimumViewportLatitude = m_map->minimumCenterLatitudeAtZoom(m_cameraData);
- center.setLatitude(qBound(-m_maximumViewportLatitude, center.latitude(), m_maximumViewportLatitude));
+ center.setLatitude(qBound(m_minimumViewportLatitude, center.latitude(), m_maximumViewportLatitude));
if (center != m_cameraData.center()) {
centerHasChanged = true;
@@ -389,6 +395,10 @@ void QDeclarativeGeoMap::initialize()
if (fovHasChanged)
emit fieldOfViewChanged(m_cameraData.fieldOfView());
+ if (visibleAreaHasChanged)
+ emit visibleAreaChanged();
+ connect(m_map, &QGeoMap::visibleAreaChanged, this, &QDeclarativeGeoMap::visibleAreaChanged);
+
emit mapReadyChanged(true);
if (m_copyrights) // To not update during initialize()
@@ -915,8 +925,9 @@ void QDeclarativeGeoMap::setZoomLevel(qreal zoomLevel, bool overzoom)
zoomLevel,
overzoom ? 30 : maximumZoomLevel()));
m_maximumViewportLatitude = m_map->maximumCenterLatitudeAtZoom(m_cameraData);
+ m_minimumViewportLatitude = m_map->minimumCenterLatitudeAtZoom(m_cameraData);
QGeoCoordinate coord = m_cameraData.center();
- coord.setLatitude(qBound(-m_maximumViewportLatitude, coord.latitude(), m_maximumViewportLatitude));
+ coord.setLatitude(qBound(m_minimumViewportLatitude, coord.latitude(), m_maximumViewportLatitude));
if (coord != m_cameraData.center()) {
centerHasChanged = true;
m_cameraData.setCenter(coord);
@@ -1231,7 +1242,7 @@ void QDeclarativeGeoMap::setCenter(const QGeoCoordinate &center)
if (m_initialized) {
QGeoCoordinate coord(center);
- coord.setLatitude(qBound(-m_maximumViewportLatitude, center.latitude(), m_maximumViewportLatitude));
+ coord.setLatitude(qBound(m_minimumViewportLatitude, center.latitude(), m_maximumViewportLatitude));
m_cameraData.setCenter(coord);
m_map->setCameraData(m_cameraData);
} else {
@@ -1364,6 +1375,42 @@ QColor QDeclarativeGeoMap::color() const
}
/*!
+ \qmlproperty rect QtLocation::Map::visibleArea
+
+ This property holds the visible area inside the Map QML element.
+ It is a rect whose coordinates are relative to the Map element.
+ Its size will be clamped to the size of the Map element.
+ A null visibleArea means that the whole Map is visible.
+
+ \since 5.12
+*/
+QRectF QDeclarativeGeoMap::visibleArea() const
+{
+ if (m_initialized)
+ return m_map->visibleArea();
+ return m_visibleArea;
+}
+
+void QDeclarativeGeoMap::setVisibleArea(const QRectF &visibleArea)
+{
+ const QRectF oldVisibleArea = QDeclarativeGeoMap::visibleArea();
+ if (visibleArea == oldVisibleArea)
+ return;
+
+ if (!visibleArea.isValid() && !visibleArea.isEmpty()) // values < 0
+ return;
+
+ if (m_initialized) {
+ m_map->setVisibleArea(visibleArea);
+ } else {
+ m_visibleArea = visibleArea;
+ const QRectF newVisibleArea = QDeclarativeGeoMap::visibleArea();
+ if (newVisibleArea != oldVisibleArea)
+ emit visibleAreaChanged();
+ }
+}
+
+/*!
\qmlproperty bool QtLocation::Map::mapReady
This property holds whether the map has been successfully initialized and is ready to be used.
@@ -1378,6 +1425,17 @@ bool QDeclarativeGeoMap::mapReady() const
return m_initialized;
}
+QMargins QDeclarativeGeoMap::mapMargins() const
+{
+ const QRectF va = m_map->visibleArea();
+ if (va.isEmpty())
+ return QMargins();
+ return QMargins( va.x()
+ , va.y()
+ , width() - va.width() - va.x()
+ , height() - va.height() - va.y());
+}
+
// TODO: offer the possibility to specify the margins.
void QDeclarativeGeoMap::fitViewportToGeoShape()
{
@@ -1385,34 +1443,24 @@ void QDeclarativeGeoMap::fitViewportToGeoShape()
// This case remains handled here, and not inside QGeoMap*::fitViewportToGeoRectangle,
// in order to honor animations on center and zoomLevel
const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(m_map->geoProjection());
- const int margins = 10;
- if (!m_map || !m_visibleRegion.isValid() || width() <= margins || height() <= margins)
- return;
+ const int borderSize = 10;
+ const QMargins borders(borderSize, borderSize, borderSize, borderSize);
- QDoubleVector2D topLeftPoint = p.geoToMapProjection(m_visibleRegion.topLeft());
- QDoubleVector2D bottomRightPoint = p.geoToMapProjection(m_visibleRegion.bottomRight());
- if (bottomRightPoint.x() < topLeftPoint.x()) // crossing the dateline
- bottomRightPoint.setX(bottomRightPoint.x() + 1.0);
+ if (!m_map || !m_visibleRegion.isValid())
+ return;
- // find center of the bounding box
- QDoubleVector2D center = (topLeftPoint + bottomRightPoint) * 0.5;
- center.setX(center.x() > 1.0 ? center.x() - 1.0 : center.x());
- QGeoCoordinate centerCoordinate = p.mapProjectionToGeo(center);
+ const QMargins margins = borders + mapMargins();
+ const QPair<QGeoCoordinate, qreal> fitData = p.fitViewportToGeoRectangle(m_visibleRegion,
+ margins);
+ if (!fitData.first.isValid())
+ return;
// position camera to the center of bounding box
- setProperty("center", QVariant::fromValue(centerCoordinate)); // not using setCenter(centerCoordinate) to honor a possible animation set on the center property
-
- // if the shape is empty we just change center position, not zoom
- double bboxWidth = (bottomRightPoint.x() - topLeftPoint.x()) * m_map->mapWidth();
- double bboxHeight = (bottomRightPoint.y() - topLeftPoint.y()) * m_map->mapHeight();
+ setProperty("center", QVariant::fromValue(fitData.first)); // not using setCenter(centerCoordinate) to honor a possible animation set on the center property
- if (bboxHeight == 0.0 && bboxWidth == 0.0)
+ if (!qIsFinite(fitData.second))
return;
-
- double zoomRatio = qMax(bboxWidth / (width() - margins),
- bboxHeight / (height() - margins));
- zoomRatio = std::log(zoomRatio) / std::log(2.0);
- double newZoom = qMax<double>(minimumZoomLevel(), zoomLevel() - zoomRatio);
+ double newZoom = qMax<double>(minimumZoomLevel(), fitData.second);
setProperty("zoomLevel", QVariant::fromValue(newZoom)); // not using setZoomLevel(newZoom) to honor a possible animation set on the zoomLevel property
} else if (m_map->capabilities() & QGeoMap::SupportsFittingViewportToGeoRectangle) {
// Animations cannot be honored in this case, as m_map act as a black box
@@ -2067,11 +2115,14 @@ void QDeclarativeGeoMap::geometryChanged(const QRectF &newGeometry, const QRectF
setMinimumZoomLevel(m_map->minimumZoom(), false);
// Update the center latitudinal threshold
- double maximumCenterLatitudeAtZoom = m_map->maximumCenterLatitudeAtZoom(m_cameraData);
- if (maximumCenterLatitudeAtZoom != m_maximumViewportLatitude) {
+ const double maximumCenterLatitudeAtZoom = m_map->maximumCenterLatitudeAtZoom(m_cameraData);
+ const double minimumCenterLatitudeAtZoom = m_map->minimumCenterLatitudeAtZoom(m_cameraData);
+ if (maximumCenterLatitudeAtZoom != m_maximumViewportLatitude
+ || minimumCenterLatitudeAtZoom != m_minimumViewportLatitude) {
m_maximumViewportLatitude = maximumCenterLatitudeAtZoom;
+ m_minimumViewportLatitude = minimumCenterLatitudeAtZoom;
QGeoCoordinate coord = m_cameraData.center();
- coord.setLatitude(qBound(-m_maximumViewportLatitude, coord.latitude(), m_maximumViewportLatitude));
+ coord.setLatitude(qBound(m_minimumViewportLatitude, coord.latitude(), m_maximumViewportLatitude));
if (coord != m_cameraData.center()) {
m_cameraData.setCenter(coord);
diff --git a/src/location/declarativemaps/qdeclarativegeomap_p.h b/src/location/declarativemaps/qdeclarativegeomap_p.h
index 7f1bf7ab..6948b15b 100644
--- a/src/location/declarativemaps/qdeclarativegeomap_p.h
+++ b/src/location/declarativemaps/qdeclarativegeomap_p.h
@@ -101,6 +101,7 @@ class Q_LOCATION_PRIVATE_EXPORT QDeclarativeGeoMap : public QQuickItem
Q_PROPERTY(bool copyrightsVisible READ copyrightsVisible WRITE setCopyrightsVisible NOTIFY copyrightsVisibleChanged)
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
Q_PROPERTY(bool mapReady READ mapReady NOTIFY mapReadyChanged)
+ Q_PROPERTY(QRectF visibleArea READ visibleArea WRITE setVisibleArea NOTIFY visibleAreaChanged REVISION 12)
Q_INTERFACES(QQmlParserStatus)
public:
@@ -154,6 +155,9 @@ public:
void setColor(const QColor &color);
QColor color() const;
+ QRectF visibleArea() const;
+ void setVisibleArea(const QRectF &visibleArea);
+
bool mapReady() const;
QQmlListProperty<QDeclarativeGeoMapType> supportedMapTypes();
@@ -226,6 +230,7 @@ Q_SIGNALS:
void copyrightsChanged(const QString &copyrightsHtml);
void mapReadyChanged(bool ready);
Q_REVISION(11) void mapObjectsChanged();
+ void visibleAreaChanged();
protected:
void mousePressEvent(QMouseEvent *event) override ;
@@ -266,6 +271,7 @@ private:
bool isInteractive();
void attachCopyrightNotice(bool initialVisibility);
void detachCopyrightNotice(bool currentVisibility);
+ QMargins mapMargins() const;
private:
QDeclarativeGeoServiceProvider *m_plugin;
@@ -287,6 +293,7 @@ private:
bool m_pendingFitViewport;
bool m_copyrightsVisible;
double m_maximumViewportLatitude;
+ double m_minimumViewportLatitude = 0.0;
bool m_initialized;
QList<QDeclarativeGeoMapParameter *> m_mapParameters;
QList<QGeoMapObject*> m_pendingMapObjects; // Used only in the initialization phase
@@ -306,6 +313,7 @@ private:
int m_copyNoticesVisible = 0;
qreal m_maxChildZ = 0;
+ QRectF m_visibleArea;
friend class QDeclarativeGeoMapItem;
diff --git a/src/location/declarativemaps/qdeclarativegeomapitembase.cpp b/src/location/declarativemaps/qdeclarativegeomapitembase.cpp
index faa06fef..366992ed 100644
--- a/src/location/declarativemaps/qdeclarativegeomapitembase.cpp
+++ b/src/location/declarativemaps/qdeclarativegeomapitembase.cpp
@@ -141,6 +141,8 @@ void QDeclarativeGeoMapItemBase::setMap(QDeclarativeGeoMap *quickMap, QGeoMap *m
if (map_ && quickMap_) {
connect(map_, SIGNAL(cameraDataChanged(QGeoCameraData)),
this, SLOT(baseCameraDataChanged(QGeoCameraData)));
+ connect(map_, SIGNAL(visibleAreaChanged()),
+ this, SLOT(visibleAreaChanged()));
connect(quickMap, SIGNAL(heightChanged()), this, SLOT(polishAndUpdate()));
connect(quickMap, SIGNAL(widthChanged()), this, SLOT(polishAndUpdate()));
lastSize_ = QSizeF(quickMap_->width(), quickMap_->height());
@@ -177,6 +179,13 @@ void QDeclarativeGeoMapItemBase::baseCameraDataChanged(const QGeoCameraData &cam
afterViewportChanged(evt);
}
+void QDeclarativeGeoMapItemBase::visibleAreaChanged()
+{
+ QGeoMapViewportChangeEvent evt;
+ evt.mapSize = QSizeF(quickMap_->width(), quickMap_->height());
+ afterViewportChanged(evt);
+}
+
/*!
\internal
*/
diff --git a/src/location/declarativemaps/qdeclarativegeomapitembase_p.h b/src/location/declarativemaps/qdeclarativegeomapitembase_p.h
index 7a284e8a..4a2f9282 100644
--- a/src/location/declarativemaps/qdeclarativegeomapitembase_p.h
+++ b/src/location/declarativemaps/qdeclarativegeomapitembase_p.h
@@ -147,6 +147,7 @@ protected:
private Q_SLOTS:
void baseCameraDataChanged(const QGeoCameraData &camera);
+ void visibleAreaChanged();
private:
QPointer<QGeoMap> map_;
diff --git a/src/location/declarativemaps/qdeclarativegeomapquickitem.cpp b/src/location/declarativemaps/qdeclarativegeomapquickitem.cpp
index 62613126..9a86fc8e 100644
--- a/src/location/declarativemaps/qdeclarativegeomapquickitem.cpp
+++ b/src/location/declarativemaps/qdeclarativegeomapquickitem.cpp
@@ -441,6 +441,10 @@ void QDeclarativeGeoMapQuickItem::updatePolish()
void QDeclarativeGeoMapQuickItem::afterViewportChanged(const QGeoMapViewportChangeEvent &event)
{
Q_UNUSED(event);
+ if (event.mapSize.width() <= 0 || event.mapSize.height() <= 0)
+ return;
+
+ polishAndUpdate();
}
/*!
diff --git a/src/location/maps/qgeocameratiles.cpp b/src/location/maps/qgeocameratiles.cpp
index 327d54b3..b7eac306 100644
--- a/src/location/maps/qgeocameratiles.cpp
+++ b/src/location/maps/qgeocameratiles.cpp
@@ -89,6 +89,7 @@ public:
int m_mapVersion;
QGeoCameraData m_camera;
QSize m_screenSize;
+ QRectF m_visibleArea;
int m_tileSize;
QSet<QGeoTileSpec> m_tiles;
@@ -155,6 +156,15 @@ QGeoCameraData QGeoCameraTiles::cameraData() const
return d_ptr->m_camera;
}
+void QGeoCameraTiles::setVisibleArea(const QRectF &visibleArea)
+{
+ if (d_ptr->m_visibleArea == visibleArea)
+ return;
+
+ d_ptr->m_visibleArea = visibleArea;
+ d_ptr->m_dirtyGeometry = true;
+}
+
void QGeoCameraTiles::setScreenSize(const QSize &size)
{
if (d_ptr->m_screenSize == size)
@@ -358,15 +368,32 @@ Frustum QGeoCameraTilesPrivate::createFrustum(double viewExpansion) const
frustum.apex = eye;
- frustum.topLeftFar = cf - (up * hhf) - (right * hwf);
- frustum.topRightFar = cf - (up * hhf) + (right * hwf);
- frustum.bottomLeftFar = cf + (up * hhf) - (right * hwf);
- frustum.bottomRightFar = cf + (up * hhf) + (right * hwf);
-
- frustum.topLeftNear = cn - (up * hhn) - (right * hwn);
- frustum.topRightNear = cn - (up * hhn) + (right * hwn);
- frustum.bottomLeftNear = cn + (up * hhn) - (right * hwn);
- frustum.bottomRightNear = cn + (up * hhn) + (right * hwn);
+ QRectF va = m_visibleArea;
+ if (va.isNull())
+ va = QRectF(0, 0, m_screenSize.width(), m_screenSize.height());
+ QRectF screen = QRectF(QPointF(0,0),m_screenSize);
+ QPointF vaCenter = va.center();
+ QPointF screenCenter = screen.center();
+ QPointF diff = screenCenter - vaCenter;
+ double xdiffpct = diff.x() / m_screenSize.width();
+ double ydiffpct = -(diff.y() / m_screenSize.height());
+
+ double wn = (2 * hwn) * xdiffpct;
+ double hn = (2 * hhn) * ydiffpct;
+ double wf = (2 * hwf) * xdiffpct;
+ double hf = (2 * hhf) * ydiffpct;
+
+ // TODO: fix eye
+
+ frustum.topLeftFar = cf - (up * (hhf + hf)) - (right * (hwf + wf));
+ frustum.topRightFar = cf - (up * (hhf + hf)) + (right * (hwf + wf));
+ frustum.bottomLeftFar = cf + (up * (hhf + hf)) - (right * (hwf + wf));
+ frustum.bottomRightFar = cf + (up * (hhf + hf)) + (right * (hwf + wf));
+
+ frustum.topLeftNear = cn - (up * (hhn + hn)) - (right * (hwn + wn));
+ frustum.topRightNear = cn - (up * (hhn + hn)) + (right * (hwn + wn));
+ frustum.bottomLeftNear = cn + (up * (hhn + hn)) - (right * (hwn + wn));
+ frustum.bottomRightNear = cn + (up * (hhn + hn)) + (right * (hwn + wn));
return frustum;
}
diff --git a/src/location/maps/qgeocameratiles_p.h b/src/location/maps/qgeocameratiles_p.h
index 3ff00688..f95db44d 100644
--- a/src/location/maps/qgeocameratiles_p.h
+++ b/src/location/maps/qgeocameratiles_p.h
@@ -49,6 +49,7 @@
#include <QtLocation/private/qlocationglobal_p.h>
#include <QtCore/QScopedPointer>
+#include <QRectF>
QT_BEGIN_NAMESPACE
@@ -65,6 +66,7 @@ public:
void setCameraData(const QGeoCameraData &camera);
QGeoCameraData cameraData() const;
+ void setVisibleArea(const QRectF &visibleArea);
void setScreenSize(const QSize &size);
void setTileSize(int tileSize);
int tileSize() const;
diff --git a/src/location/maps/qgeomap.cpp b/src/location/maps/qgeomap.cpp
index 5f125169..db0df702 100644
--- a/src/location/maps/qgeomap.cpp
+++ b/src/location/maps/qgeomap.cpp
@@ -42,6 +42,7 @@
#include "qgeomapobject_p.h"
#include "qgeomapobject_p_p.h"
#include <QDebug>
+#include <QRectF>
QT_BEGIN_NAMESPACE
@@ -109,7 +110,7 @@ bool QGeoMap::handleEvent(QEvent *event)
return false;
}
-bool QGeoMap::setBearing(qreal bearing, const QGeoCoordinate &coordinate)
+bool QGeoMap::setBearing(qreal bearing, const QGeoCoordinate &coordinate) //FIXME visibleArea
{
Q_D(QGeoMap);
bool res = d->m_geoProjection->setBearing(bearing, coordinate);
@@ -124,7 +125,7 @@ bool QGeoMap::anchorCoordinateToPoint(const QGeoCoordinate &coordinate, const QP
{
Q_D(QGeoMap);
QGeoCoordinate newCenter = geoProjection().anchorCoordinateToPoint(coordinate, anchorPoint);
- newCenter.setLatitude(qBound(-d->m_maximumViewportLatitude, newCenter.latitude(), d->m_maximumViewportLatitude));
+ newCenter.setLatitude(qBound(d->m_minimumViewportLatitude, newCenter.latitude(), d->m_maximumViewportLatitude));
QGeoCameraData data = cameraData();
if (data.center() != newCenter) {
data.setCenter(newCenter);
@@ -180,6 +181,12 @@ double QGeoMap::maximumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) co
return d->maximumCenterLatitudeAtZoom(cameraData);
}
+double QGeoMap::minimumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) const
+{
+ Q_D(const QGeoMap);
+ return d->minimumCenterLatitudeAtZoom(cameraData);
+}
+
double QGeoMap::mapWidth() const
{
Q_D(const QGeoMap);
@@ -297,6 +304,21 @@ void QGeoMap::removeMapObject(QGeoMapObject * /*obj*/)
{
}
+void QGeoMap::setVisibleArea(const QRectF &visibleArea)
+{
+ Q_D(QGeoMap);
+ const QRectF &va = d->visibleArea();
+ d->setVisibleArea(visibleArea);
+ if (va != d->visibleArea())
+ emit visibleAreaChanged();
+}
+
+QRectF QGeoMap::visibleArea() const
+{
+ Q_D(const QGeoMap);
+ return d->visibleArea();
+}
+
QList<QGeoMapObject *> QGeoMap::mapObjects() const
{
Q_D(const QGeoMap);
@@ -429,4 +451,29 @@ double QGeoMapPrivate::maximumCenterLatitudeAtZoom(const QGeoCameraData &cameraD
return m_maximumViewportLatitude;
}
+double QGeoMapPrivate::minimumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) const
+{
+ m_minimumViewportLatitude = m_geoProjection->minimumCenterLatitudeAtZoom(cameraData);
+ return m_minimumViewportLatitude;
+}
+
+void QGeoMapPrivate::setVisibleArea(const QRectF &/*visibleArea*/)
+{
+
+}
+
+QRectF QGeoMapPrivate::visibleArea() const
+{
+ return QRectF();
+}
+
+QRectF QGeoMapPrivate::clampVisibleArea(const QRectF &visibleArea) const
+{
+ qreal xp = qMin<qreal>(visibleArea.x(), qMax(m_viewportSize.width() - 1, 0));
+ qreal yp = qMin<qreal>(visibleArea.y(), qMax(m_viewportSize.height() - 1, 0));
+ qreal w = qMin<qreal>(visibleArea.width(), qMax<qreal>(m_viewportSize.width() - xp, 0));
+ qreal h = qMin<qreal>(visibleArea.height(), qMax<qreal>(m_viewportSize.height() - yp, 0));
+ return QRectF(xp, yp, w, h);
+}
+
QT_END_NAMESPACE
diff --git a/src/location/maps/qgeomap_p.h b/src/location/maps/qgeomap_p.h
index f6be5cae..0c396e16 100644
--- a/src/location/maps/qgeomap_p.h
+++ b/src/location/maps/qgeomap_p.h
@@ -93,7 +93,8 @@ public:
SupportsVisibleRegion = 0x0001,
SupportsSetBearing = 0x0002,
SupportsAnchoringCoordinate = 0x0004,
- SupportsFittingViewportToGeoRectangle = 0x0008
+ SupportsFittingViewportToGeoRectangle = 0x0008,
+ SupportsVisibleArea = 0x0010,
};
Q_DECLARE_FLAGS(Capabilities, Capability)
@@ -117,6 +118,7 @@ public:
// returns the minimum zoom at the current viewport size
double minimumZoom() const;
double maximumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) const;
+ double minimumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) const;
// returns the size of the underlying map, at the current zoom level. Unrelated to width()/height()/size().
double mapWidth() const;
@@ -153,6 +155,9 @@ public:
virtual void setCopyrightVisible(bool visible);
virtual void removeMapObject(QGeoMapObject *obj);
+ void setVisibleArea(const QRectF &visibleArea);
+ QRectF visibleArea() const;
+
protected:
QGeoMap(QGeoMapPrivate &dd, QObject *parent = 0);
void setCameraData(const QGeoCameraData &cameraData);
@@ -167,6 +172,7 @@ Q_SIGNALS:
void copyrightsChanged(const QImage &copyrightsImage);
void copyrightsChanged(const QString &copyrightsHtml);
void copyrightsStyleSheetChanged(const QString &styleSheet);
+ void visibleAreaChanged();
private:
Q_DISABLE_COPY(QGeoMap)
diff --git a/src/location/maps/qgeomap_p_p.h b/src/location/maps/qgeomap_p_p.h
index 47780c47..7bda316d 100644
--- a/src/location/maps/qgeomap_p_p.h
+++ b/src/location/maps/qgeomap_p_p.h
@@ -103,6 +103,12 @@ protected:
virtual void setCopyrightVisible(bool visible);
virtual bool copyrightVisible() const;
virtual double maximumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) const;
+ virtual double minimumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) const;
+
+ virtual void setVisibleArea(const QRectF &visibleArea);
+ virtual QRectF visibleArea() const;
+
+ QRectF clampVisibleArea(const QRectF &visibleArea) const;
protected:
QSize m_viewportSize;
@@ -115,6 +121,7 @@ protected:
QGeoCameraCapabilities m_cameraCapabilities;
bool m_copyrightVisible = true;
mutable double m_maximumViewportLatitude = 0;
+ mutable double m_minimumViewportLatitude = 0;
};
QT_END_NAMESPACE
diff --git a/src/location/maps/qgeoprojection.cpp b/src/location/maps/qgeoprojection.cpp
index 74736cef..a456f80e 100644
--- a/src/location/maps/qgeoprojection.cpp
+++ b/src/location/maps/qgeoprojection.cpp
@@ -39,6 +39,7 @@
#include <QtPositioning/private/qlocationutils_p.h>
#include <QtPositioning/private/qclipperutils_p.h>
#include <QtPositioning/QGeoPolygon>
+#include <QtPositioning/QGeoRectangle>
#include <QSize>
#include <QtGui/QMatrix4x4>
#include <cmath>
@@ -62,6 +63,30 @@ static QMatrix4x4 toMatrix4x4(const QDoubleMatrix4x4 &m)
m(3,0), m(3,1), m(3,2), m(3,3));
}
+static QPointF centerOffset(const QSizeF &screenSize, const QRectF &visibleArea)
+{
+ QRectF va = visibleArea;
+ if (va.isNull())
+ va = QRectF(0, 0, screenSize.width(), screenSize.height());
+
+ QRectF screen = QRectF(QPointF(0,0),screenSize);
+ QPointF vaCenter = va.center();
+
+ QPointF screenCenter = screen.center();
+ QPointF diff = screenCenter - vaCenter;
+
+ return diff;
+}
+
+static QPointF marginsOffset(const QSizeF &screenSize, const QRectF &visibleArea)
+{
+ QPointF diff = centerOffset(screenSize, visibleArea);
+ qreal xdiffpct = diff.x() / qMax<double>(screenSize.width() - 1, 1);
+ qreal ydiffpct = diff.y() / qMax<double>(screenSize.height() - 1, 1);
+
+ return QPointF(-xdiffpct, -ydiffpct);
+}
+
QT_BEGIN_NAMESPACE
QGeoProjection::QGeoProjection()
@@ -175,14 +200,36 @@ double QGeoProjectionWebMercator::maximumCenterLatitudeAtZoom(const QGeoCameraDa
// At init time weird things happen
int clampedWindowHeight = (m_viewportHeight > mapEdgeSize) ? mapEdgeSize : m_viewportHeight;
+ QPointF offsetPct = centerOffset(QSizeF(m_viewportWidth, m_viewportHeight), m_visibleArea);
+ double hpct = offsetPct.y() / qMax<double>(m_viewportHeight - 1, 1);
// Use the window height divided by 2 as the topmost allowed center, with respect to the map size in pixels
- double mercatorTopmost = (clampedWindowHeight * 0.5) / mapEdgeSize ;
+ double mercatorTopmost = (clampedWindowHeight * (0.5 - hpct)) / mapEdgeSize ;
QGeoCoordinate topMost = QWebMercator::mercatorToCoord(QDoubleVector2D(0.0, mercatorTopmost));
-
return topMost.latitude();
}
+double QGeoProjectionWebMercator::minimumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) const
+{
+ double mapEdgeSize = std::pow(2.0, cameraData.zoomLevel()) * defaultTileSize;
+
+ // At init time weird things happen
+ int clampedWindowHeight = (m_viewportHeight > mapEdgeSize) ? mapEdgeSize : m_viewportHeight;
+ QPointF offsetPct = centerOffset(QSizeF(m_viewportWidth, m_viewportHeight), m_visibleArea);
+ double hpct = offsetPct.y() / qMax<double>(m_viewportHeight - 1, 1);
+
+ // Use the window height divided by 2 as the topmost allowed center, with respect to the map size in pixels
+ double mercatorTopmost = (clampedWindowHeight * (0.5 + hpct)) / mapEdgeSize ;
+ QGeoCoordinate topMost = QWebMercator::mercatorToCoord(QDoubleVector2D(0.0, mercatorTopmost));
+ return -topMost.latitude();
+}
+
+void QGeoProjectionWebMercator::setVisibleArea(const QRectF &visibleArea)
+{
+ m_visibleArea = visibleArea;
+ setupCamera();
+}
+
double QGeoProjectionWebMercator::mapWidth() const
{
return m_mapEdgeSize;
@@ -258,7 +305,8 @@ QDoubleVector2D QGeoProjectionWebMercator::wrappedMapProjectionToItemPosition(co
QDoubleVector2D QGeoProjectionWebMercator::itemPositionToWrappedMapProjection(const QDoubleVector2D &itemPosition) const
{
- QDoubleVector2D pos = itemPosition;
+ const QPointF centerOff = centerOffset(QSizeF(m_viewportWidth, m_viewportHeight), m_visibleArea);
+ QDoubleVector2D pos = itemPosition + QDoubleVector2D(centerOff);
pos *= QDoubleVector2D(m_1_viewportWidth, m_1_viewportHeight);
pos *= 2.0;
pos -= QDoubleVector2D(1.0,1.0);
@@ -434,16 +482,54 @@ QDoubleVector2D QGeoProjectionWebMercator::viewportToWrappedMapProjection(const
QDoubleVector2D pos = itemPosition;
pos *= QDoubleVector2D(m_halfWidth, m_halfHeight);
+ // determine itemPosition on the near plane
QDoubleVector3D p = m_centerNearPlane;
p += m_up * pos.y();
p += m_side * pos.x();
+ // compute the ray using the eye position
QDoubleVector3D ray = m_eye - p;
ray.normalize();
return (xyPlane.lineIntersection(m_eye, ray, s) / m_sideLength).toVector2D();
}
+/*
+ Returns a pair of <newCenter, newZoom>
+*/
+QPair<QGeoCoordinate, qreal> QGeoProjectionWebMercator::fitViewportToGeoRectangle(const QGeoRectangle &rectangle,
+ const QMargins &m) const
+{
+ QPair<QGeoCoordinate, qreal> res;
+ res.second = qQNaN();
+ if (m_viewportWidth <= m.left() + m.right() || m_viewportHeight <= m.top() + m.bottom())
+ return res;
+
+ QDoubleVector2D topLeftPoint = geoToMapProjection(rectangle.topLeft());
+ QDoubleVector2D bottomRightPoint = geoToMapProjection(rectangle.bottomRight());
+ if (bottomRightPoint.x() < topLeftPoint.x()) // crossing the dateline
+ bottomRightPoint.setX(bottomRightPoint.x() + 1.0);
+
+ // find center of the bounding box
+ QDoubleVector2D center = (topLeftPoint + bottomRightPoint) * 0.5;
+ center.setX(center.x() > 1.0 ? center.x() - 1.0 : center.x());
+ res.first = mapProjectionToGeo(center);
+
+ // if the shape is empty we just change center position, not zoom
+ double bboxWidth = (bottomRightPoint.x() - topLeftPoint.x()) * mapWidth();
+ double bboxHeight = (bottomRightPoint.y() - topLeftPoint.y()) * mapHeight();
+
+ if (bboxHeight == 0.0 && bboxWidth == 0.0)
+ return res;
+
+ double zoomRatio = qMax(bboxWidth / (m_viewportWidth - m.left() - m.right()),
+ bboxHeight / (m_viewportHeight - m.top() - m.bottom()));
+ zoomRatio = std::log(zoomRatio) / std::log(2.0);
+ res.second = m_cameraData.zoomLevel() - zoomRatio;
+
+ return res;
+}
+
QGeoProjection::ProjectionGroup QGeoProjectionWebMercator::projectionGroup() const
{
return QGeoProjection::ProjectionCylindrical;
@@ -563,10 +649,11 @@ void QGeoProjectionWebMercator::setupCamera()
* matScreen = scale(m_viewportWidth, m_viewportHeight, 1.0)
*/
+ QPointF offsetPct = marginsOffset(QSizeF(m_viewportWidth, m_viewportHeight), m_visibleArea);
QDoubleMatrix4x4 matScreenTransformation;
matScreenTransformation.scale(0.5 * m_viewportWidth, 0.5 * m_viewportHeight, 1.0);
- matScreenTransformation(0,3) = 0.5 * m_viewportWidth;
- matScreenTransformation(1,3) = 0.5 * m_viewportHeight;
+ matScreenTransformation(0,3) = (0.5 + offsetPct.x()) * m_viewportWidth;
+ matScreenTransformation(1,3) = (0.5 + offsetPct.y()) * m_viewportHeight;
m_transformation = matScreenTransformation * projectionMatrix * cameraMatrix;
m_quickItemTransformation = m_transformation;
@@ -597,10 +684,18 @@ void QGeoProjectionWebMercator::updateVisibleRegion()
{
m_visibleRegionDirty = false;
- QDoubleVector2D tl = viewportToWrappedMapProjection(QDoubleVector2D(-1, -1 + m_verticalEstateToSkip ));
- QDoubleVector2D tr = viewportToWrappedMapProjection(QDoubleVector2D( 1, -1 + m_verticalEstateToSkip ));
- QDoubleVector2D bl = viewportToWrappedMapProjection(QDoubleVector2D(-1, 1 ));
- QDoubleVector2D br = viewportToWrappedMapProjection(QDoubleVector2D( 1, 1 ));
+ double viewportHalfWidth = (!m_visibleArea.isEmpty()) ? m_visibleArea.width() / m_viewportWidth : 1.0;
+ double viewportHalfHeight = (!m_visibleArea.isEmpty()) ? m_visibleArea.height() / m_viewportHeight : 1.0;
+
+ double top = qMax<double>(-viewportHalfHeight, -1 + m_verticalEstateToSkip);
+ double bottom = viewportHalfHeight;
+ double left = -viewportHalfWidth;
+ double right = viewportHalfWidth;
+
+ QDoubleVector2D tl = viewportToWrappedMapProjection(QDoubleVector2D(left, top ));
+ QDoubleVector2D tr = viewportToWrappedMapProjection(QDoubleVector2D(right, top ));
+ QDoubleVector2D bl = viewportToWrappedMapProjection(QDoubleVector2D(left, bottom ));
+ QDoubleVector2D br = viewportToWrappedMapProjection(QDoubleVector2D(right, bottom ));
// To make sure that what is returned can be safely converted back to lat/lon without risking overlaps
double mapLeftLongitude = QLocationUtils::mapLeftLongitude(m_cameraData.center().longitude());
diff --git a/src/location/maps/qgeoprojection_p.h b/src/location/maps/qgeoprojection_p.h
index b0fffa28..e33ae880 100644
--- a/src/location/maps/qgeoprojection_p.h
+++ b/src/location/maps/qgeoprojection_p.h
@@ -85,6 +85,7 @@ public:
QGeoProjection();
virtual ~QGeoProjection();
+ virtual void setVisibleArea(const QRectF &visibleArea) = 0;
virtual void setViewportSize(const QSize &size) = 0;
virtual void setCameraData(const QGeoCameraData &cameraData, bool force = true) = 0;
virtual QGeoCameraData cameraData() const = 0;
@@ -92,6 +93,7 @@ public:
// returns the minimum zoom at the current viewport size
virtual double minimumZoom() const = 0;
virtual double maximumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) const = 0;
+ virtual double minimumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) const = 0;
virtual QGeoCoordinate itemPositionToCoordinate(const QDoubleVector2D &pos, bool clipToViewport = true) const = 0;
virtual QDoubleVector2D coordinateToItemPosition(const QGeoCoordinate &coordinate, bool clipToViewport = true) const = 0;
@@ -116,7 +118,9 @@ public:
// From QGeoProjection
double minimumZoom() const override;
double maximumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) const override;
+ double minimumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) const override;
+ void setVisibleArea(const QRectF &visibleArea) override;
void setViewportSize(const QSize &size) override;
void setCameraData(const QGeoCameraData &cameraData, bool force = true) override;
QGeoCameraData cameraData() const override;
@@ -158,6 +162,9 @@ public:
inline QDoubleVector2D viewportToWrappedMapProjection(const QDoubleVector2D &itemPosition) const;
inline QDoubleVector2D viewportToWrappedMapProjection(const QDoubleVector2D &itemPosition, double &s) const;
+ QPair<QGeoCoordinate, qreal> fitViewportToGeoRectangle(const QGeoRectangle &rectangle,
+ const QMargins &margins) const;
+
private:
void setupCamera();
void updateVisibleRegion();
@@ -234,6 +241,7 @@ private:
QList<QDoubleVector2D> m_visibleRegionExpanded;
QList<QDoubleVector2D> m_projectableRegion;
bool m_visibleRegionDirty;
+ QRectF m_visibleArea;
Q_DISABLE_COPY(QGeoProjectionWebMercator)
};
diff --git a/src/location/maps/qgeotiledmap.cpp b/src/location/maps/qgeotiledmap.cpp
index a1231cf4..74346fdb 100644
--- a/src/location/maps/qgeotiledmap.cpp
+++ b/src/location/maps/qgeotiledmap.cpp
@@ -149,7 +149,8 @@ QGeoMap::Capabilities QGeoTiledMap::capabilities() const
{
return Capabilities(SupportsVisibleRegion
| SupportsSetBearing
- | SupportsAnchoringCoordinate);
+ | SupportsAnchoringCoordinate
+ | SupportsVisibleArea);
}
void QGeoTiledMap::setCopyrightVisible(bool visible)
@@ -353,6 +354,31 @@ void QGeoTiledMapPrivate::updateScene()
emit q->sgNodeChanged();
}
+void QGeoTiledMapPrivate::setVisibleArea(const QRectF &visibleArea)
+{
+ Q_Q(QGeoTiledMap);
+ const QRectF va = clampVisibleArea(visibleArea);
+ if (va == m_visibleArea)
+ return;
+
+ m_visibleArea = va;
+ m_geoProjection->setVisibleArea(va);
+
+ m_visibleTiles->setVisibleArea(va);
+ m_prefetchTiles->setVisibleArea(va);
+ m_mapScene->setVisibleArea(va);
+
+ if (m_copyrightVisible)
+ q->evaluateCopyrights(m_mapScene->visibleTiles());
+ updateScene();
+ q->sgNodeChanged();
+}
+
+QRectF QGeoTiledMapPrivate::visibleArea() const
+{
+ return m_visibleArea;
+}
+
void QGeoTiledMapPrivate::changeActiveMapType(const QGeoMapType mapType)
{
m_visibleTiles->setTileSize(m_cameraCapabilities.tileSize());
diff --git a/src/location/maps/qgeotiledmap_p_p.h b/src/location/maps/qgeotiledmap_p_p.h
index d3791d49..0ba349ca 100644
--- a/src/location/maps/qgeotiledmap_p_p.h
+++ b/src/location/maps/qgeotiledmap_p_p.h
@@ -91,12 +91,16 @@ protected:
void updateScene();
+ void setVisibleArea(const QRectF &visibleArea) override;
+ QRectF visibleArea() const override;
+
protected:
QAbstractGeoTileCache *m_cache;
QGeoCameraTiles *m_visibleTiles;
QGeoCameraTiles *m_prefetchTiles;
QGeoTiledMapScene *m_mapScene;
QGeoTileRequestManager *m_tileRequests;
+ QRectF m_visibleArea;
int m_maxZoomLevel;
int m_minZoomLevel;
QGeoTiledMap::PrefetchStyle m_prefetchStyle;
diff --git a/src/location/maps/qgeotiledmapscene.cpp b/src/location/maps/qgeotiledmapscene.cpp
index ab15e37b..4709a48f 100644
--- a/src/location/maps/qgeotiledmapscene.cpp
+++ b/src/location/maps/qgeotiledmapscene.cpp
@@ -67,6 +67,7 @@ public:
QSize m_screenSize; // in pixels
int m_tileSize; // the pixel resolution for each tile
QGeoCameraData m_cameraData;
+ QRectF m_visibleArea;
QSet<QGeoTileSpec> m_visibleTiles;
QDoubleVector3D m_cameraUp;
@@ -153,6 +154,15 @@ void QGeoTiledMapScene::setCameraData(const QGeoCameraData &cameraData)
updateSceneParameters();
}
+void QGeoTiledMapScene::setVisibleArea(const QRectF &visibleArea)
+{
+ Q_D(QGeoTiledMapScene);
+ if (d->m_visibleArea == visibleArea)
+ return;
+ d->m_visibleArea = visibleArea;
+ updateSceneParameters();
+}
+
void QGeoTiledMapScene::setVisibleTiles(const QSet<QGeoTileSpec> &tiles)
{
Q_D(QGeoTiledMapScene);
@@ -465,8 +475,32 @@ void QGeoTiledMapScenePrivate::setupCamera()
float halfHeight = 1 * apertureSize;
halfWidth *= aspectRatio;
+// m_projectionMatrix.setToIdentity();
+// m_projectionMatrix.frustum(-halfWidth, halfWidth, -halfHeight, halfHeight, nearPlane, farPlane);
+
+ QRectF va = m_visibleArea;
+ if (va.isNull())
+ va = QRectF(0, 0, m_screenSize.width(), m_screenSize.height());
+
+ QRectF screen = QRectF(QPointF(0,0),m_screenSize);
+ QPointF vaCenter = va.center();
+
+ QPointF screenCenter = screen.center();
+ QPointF diff = screenCenter - vaCenter;
+ float xdiffpct = diff.x() / m_screenSize.width();
+ float ydiffpct = -(diff.y() / m_screenSize.height());
+
m_projectionMatrix.setToIdentity();
- m_projectionMatrix.frustum(-halfWidth, halfWidth, -halfHeight, halfHeight, nearPlane, farPlane);
+ float l = -halfWidth + (2 * halfWidth) * xdiffpct;
+ float r = halfWidth + (2 * halfWidth) * xdiffpct;
+ float t = halfHeight + (2 * halfHeight) * ydiffpct;
+ float b = -halfHeight + (2 * halfHeight) * ydiffpct;
+
+ m_projectionMatrix.frustum(l,
+ r,
+ b,
+ t,
+ nearPlane, farPlane);
}
class QGeoTiledMapTileContainerNode : public QSGTransformNode
diff --git a/src/location/maps/qgeotiledmapscene_p.h b/src/location/maps/qgeotiledmapscene_p.h
index f6a8f714..ac607f41 100644
--- a/src/location/maps/qgeotiledmapscene_p.h
+++ b/src/location/maps/qgeotiledmapscene_p.h
@@ -72,6 +72,7 @@ public:
void setScreenSize(const QSize &size);
void setTileSize(int tileSize);
void setCameraData(const QGeoCameraData &cameraData);
+ void setVisibleArea(const QRectF &visibleArea);
void setVisibleTiles(const QSet<QGeoTileSpec> &tiles);
const QSet<QGeoTileSpec> &visibleTiles() const;
diff --git a/src/plugins/geoservices/itemsoverlay/qgeomapitemsoverlay.cpp b/src/plugins/geoservices/itemsoverlay/qgeomapitemsoverlay.cpp
index af0e263b..dede9dbc 100644
--- a/src/plugins/geoservices/itemsoverlay/qgeomapitemsoverlay.cpp
+++ b/src/plugins/geoservices/itemsoverlay/qgeomapitemsoverlay.cpp
@@ -70,10 +70,16 @@ public:
#endif
void updateObjectsGeometry();
+
+ void setVisibleArea(const QRectF &visibleArea) override;
+ QRectF visibleArea() const override;
+
protected:
void changeViewportSize(const QSize &size) override;
void changeCameraData(const QGeoCameraData &oldCameraData) override;
void changeActiveMapType(const QGeoMapType mapType) override;
+
+ QRectF m_visibleArea;
};
QGeoMapItemsOverlay::QGeoMapItemsOverlay(QGeoMappingManagerEngineItemsOverlay *engine, QObject *parent)
@@ -131,6 +137,24 @@ void QGeoMapItemsOverlay::removeMapObject(QGeoMapObject *obj)
#endif
}
+void QGeoMapItemsOverlayPrivate::setVisibleArea(const QRectF &visibleArea)
+{
+ Q_Q(QGeoMapItemsOverlay);
+ const QRectF va = clampVisibleArea(visibleArea);
+ if (va == m_visibleArea)
+ return;
+
+ m_visibleArea = va;
+ m_geoProjection->setVisibleArea(va);
+
+ q->sgNodeChanged();
+}
+
+QRectF QGeoMapItemsOverlayPrivate::visibleArea() const
+{
+ return m_visibleArea;
+}
+
QGeoMapItemsOverlayPrivate::QGeoMapItemsOverlayPrivate(QGeoMappingManagerEngineItemsOverlay *engine, QGeoMapItemsOverlay *map)
: QGeoMapPrivate(engine, new QGeoProjectionWebMercator)
{
diff --git a/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.cpp b/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.cpp
index dfebc20d..575bf3b4 100644
--- a/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.cpp
+++ b/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.cpp
@@ -106,12 +106,12 @@ QSGNode *QGeoMapMapboxGLPrivate::updateSceneGraph(QSGNode *node, QQuickWindow *w
if (m_useFBO) {
QSGMapboxGLTextureNode *mbglNode = new QSGMapboxGLTextureNode(m_settings, m_viewportSize, window->devicePixelRatio(), q);
QObject::connect(mbglNode->map(), &QMapboxGL::mapChanged, q, &QGeoMapMapboxGL::onMapChanged);
- m_syncState = MapTypeSync | CameraDataSync | ViewportSync;
+ m_syncState = MapTypeSync | CameraDataSync | ViewportSync | VisibleAreaSync;
node = mbglNode;
} else {
QSGMapboxGLRenderNode *mbglNode = new QSGMapboxGLRenderNode(m_settings, m_viewportSize, window->devicePixelRatio(), q);
QObject::connect(mbglNode->map(), &QMapboxGL::mapChanged, q, &QGeoMapMapboxGL::onMapChanged);
- m_syncState = MapTypeSync | CameraDataSync | ViewportSync;
+ m_syncState = MapTypeSync | CameraDataSync | ViewportSync | VisibleAreaSync;
node = mbglNode;
}
}
@@ -125,7 +125,15 @@ QSGNode *QGeoMapMapboxGLPrivate::updateSceneGraph(QSGNode *node, QQuickWindow *w
map->setStyleUrl(m_activeMapType.name());
}
- if (m_syncState & CameraDataSync) {
+ if (m_syncState & VisibleAreaSync) {
+ QMargins margins(m_visibleArea.x(), // left
+ m_visibleArea.y(), // top
+ m_viewportSize.width() - m_visibleArea.width() - m_visibleArea.x(), // right
+ m_viewportSize.height() - m_visibleArea.height() - m_visibleArea.y()); // bottom
+ map->setMargins(margins);
+ }
+
+ if (m_syncState & CameraDataSync || m_syncState & VisibleAreaSync) {
map->setZoom(zoomLevelFrom256(m_cameraData.zoomLevel() , MBGL_TILE_SIZE));
map->setBearing(m_cameraData.bearing());
map->setPitch(m_cameraData.tilt());
@@ -291,6 +299,25 @@ void QGeoMapMapboxGLPrivate::changeActiveMapType(const QGeoMapType)
emit q->sgNodeChanged();
}
+void QGeoMapMapboxGLPrivate::setVisibleArea(const QRectF &visibleArea)
+{
+ Q_Q(QGeoMapMapboxGL);
+ const QRectF va = clampVisibleArea(visibleArea);
+ if (va == m_visibleArea)
+ return;
+
+ m_visibleArea = va;
+ m_geoProjection->setVisibleArea(va);
+
+ m_syncState = m_syncState | VisibleAreaSync;
+ emit q->sgNodeChanged();
+}
+
+QRectF QGeoMapMapboxGLPrivate::visibleArea() const
+{
+ return m_visibleArea;
+}
+
void QGeoMapMapboxGLPrivate::syncStyleChanges(QMapboxGL *map)
{
for (const auto& change : m_styleChanges) {
@@ -376,7 +403,8 @@ QGeoMap::Capabilities QGeoMapMapboxGL::capabilities() const
{
return Capabilities(SupportsVisibleRegion
| SupportsSetBearing
- | SupportsAnchoringCoordinate);
+ | SupportsAnchoringCoordinate
+ | SupportsVisibleArea );
}
QSGNode *QGeoMapMapboxGL::updateSceneGraph(QSGNode *oldNode, QQuickWindow *window)
diff --git a/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl_p.h b/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl_p.h
index ffb06208..f07b4c98 100644
--- a/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl_p.h
+++ b/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl_p.h
@@ -43,6 +43,7 @@
#include <QtCore/QSharedPointer>
#include <QtCore/QTimer>
#include <QtCore/QVariant>
+#include <QtCore/QRectF>
#include <QtLocation/private/qgeomap_p_p.h>
#include <QtLocation/private/qgeomapparameter_p.h>
@@ -70,9 +71,10 @@ public:
/* Data members */
enum SyncState : int {
NoSync = 0,
- ViewportSync = 1 << 0,
- CameraDataSync = 1 << 1,
- MapTypeSync = 1 << 2
+ ViewportSync = 1 << 0,
+ CameraDataSync = 1 << 1,
+ MapTypeSync = 1 << 2,
+ VisibleAreaSync = 1 << 3
};
Q_DECLARE_FLAGS(SyncStates, SyncState);
@@ -96,11 +98,16 @@ protected:
void changeCameraData(const QGeoCameraData &oldCameraData) override;
void changeActiveMapType(const QGeoMapType mapType) override;
+ void setVisibleArea(const QRectF &visibleArea) override;
+ QRectF visibleArea() const override;
+
private:
Q_DISABLE_COPY(QGeoMapMapboxGLPrivate);
void syncStyleChanges(QMapboxGL *map);
void threadedRenderingHack(QQuickWindow *window, QMapboxGL *map);
+
+ QRectF m_visibleArea;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QGeoMapMapboxGLPrivate::SyncStates)
diff --git a/src/plugins/geoservices/mapboxgl/qmapboxglstylechange.cpp b/src/plugins/geoservices/mapboxgl/qmapboxglstylechange.cpp
index 6c47d3ee..d9de5ba9 100644
--- a/src/plugins/geoservices/mapboxgl/qmapboxglstylechange.cpp
+++ b/src/plugins/geoservices/mapboxgl/qmapboxglstylechange.cpp
@@ -186,8 +186,7 @@ QList<QSharedPointer<QMapboxGLStyleChange>> QMapboxGLStyleChange::addMapParamete
{
static const QStringList acceptedParameterTypes = QStringList()
<< QStringLiteral("paint") << QStringLiteral("layout") << QStringLiteral("filter")
- << QStringLiteral("layer") << QStringLiteral("source") << QStringLiteral("image")
- << QStringLiteral("margins");
+ << QStringLiteral("layer") << QStringLiteral("source") << QStringLiteral("image");
QList<QSharedPointer<QMapboxGLStyleChange>> changes;
@@ -213,9 +212,6 @@ QList<QSharedPointer<QMapboxGLStyleChange>> QMapboxGLStyleChange::addMapParamete
case 5: // image
changes << QMapboxGLStyleAddImage::fromMapParameter(param);
break;
- case 6: // margins
- changes << QMapboxGLMapMargins::fromMapParameter(param);
- break;
}
return changes;
@@ -641,38 +637,3 @@ QSharedPointer<QMapboxGLStyleChange> QMapboxGLStyleAddImage::fromMapParameter(QG
return QSharedPointer<QMapboxGLStyleChange>(image);
}
-
-// QMapboxGLMapMargins
-
-void QMapboxGLMapMargins::apply(QMapboxGL *map)
-{
- // FIXME: Qt projection handlers are not yet aware of these margins,
- // thus map items placement, {to,from}Coordinate, mouse area, etc.
- // will require manual fixups.
- map->setMargins(m_margins);
-}
-
-QSharedPointer<QMapboxGLStyleChange> QMapboxGLMapMargins::fromMapParameter(QGeoMapParameter *param)
-{
- Q_ASSERT(param->type() == "margins");
-
- auto mapMargins = new QMapboxGLMapMargins();
-
- QVariant leftMargin = param->property("left");
- if (leftMargin.isValid())
- mapMargins->m_margins.setLeft(leftMargin.toInt());
-
- QVariant topMargin = param->property("top");
- if (topMargin.isValid())
- mapMargins->m_margins.setTop(topMargin.toInt());
-
- QVariant rightMargin = param->property("right");
- if (rightMargin.isValid())
- mapMargins->m_margins.setRight(rightMargin.toInt());
-
- QVariant bottomMargin = param->property("bottom");
- if (bottomMargin.isValid())
- mapMargins->m_margins.setBottom(bottomMargin.toInt());
-
- return QSharedPointer<QMapboxGLStyleChange>(mapMargins);
-}
diff --git a/src/plugins/geoservices/mapboxgl/qmapboxglstylechange_p.h b/src/plugins/geoservices/mapboxgl/qmapboxglstylechange_p.h
index 38aa87f8..fd5b9af4 100644
--- a/src/plugins/geoservices/mapboxgl/qmapboxglstylechange_p.h
+++ b/src/plugins/geoservices/mapboxgl/qmapboxglstylechange_p.h
@@ -190,17 +190,4 @@ private:
QImage m_sprite;
};
-class QMapboxGLMapMargins : public QMapboxGLStyleChange
-{
-public:
- static QSharedPointer<QMapboxGLStyleChange> fromMapParameter(QGeoMapParameter *);
-
- void apply(QMapboxGL *map) override;
-
-private:
- QMapboxGLMapMargins() = default;
-
- QMargins m_margins;
-};
-
#endif // QQMAPBOXGLSTYLECHANGE_P_H
diff --git a/tests/auto/declarative_ui/tst_map.qml b/tests/auto/declarative_ui/tst_map.qml
index f05b2c72..2d35fce0 100644
--- a/tests/auto/declarative_ui/tst_map.qml
+++ b/tests/auto/declarative_ui/tst_map.qml
@@ -52,6 +52,13 @@ Item {
extraTypeName = "SomeString"
}
}
+ Plugin {
+ id: testPluginNoVisibleArea;
+ name: "qmlgeo.test.plugin";
+ allowExperimental: true
+ PluginParameter { name: "supportVisibleArea"; value: false}
+ }
+ Plugin { id: itemsOverlay; name: "itemsoverlay"; }
property variant coordinate1: QtPositioning.coordinate(10, 11)
property variant coordinate2: QtPositioning.coordinate(12, 13)
@@ -127,6 +134,16 @@ Item {
property var center: QtPositioning.coordinate(-33.0, -47.0)
}
+ Map {
+ id: mapVisibleArea
+ width: 256; height: 256;
+ }
+ Map {
+ id: mapVisibleAreaUnsupported
+ width: 256; height: 256;
+ }
+ SignalSpy { id: visibleAreaSpy; target: mapVisibleArea; signalName: 'visibleAreaChanged'}
+ SignalSpy { id: visibleAreaUnsupportedSpy; target: mapVisibleAreaUnsupported; signalName: 'visibleAreaChanged'}
TestCase {
when: windowShown && allMapsReady
@@ -684,5 +701,29 @@ Item {
verify(isNaN(pos.latitude))
verify(isNaN(pos.longitde))
}
+
+ function test_visible_area()
+ {
+ wait(1000)
+ visibleAreaSpy.clear();
+ visibleAreaUnsupportedSpy.clear();
+ var defaultRect = Qt.rect(0,0,0,0)
+
+ verify(mapVisibleAreaUnsupported.visibleArea, defaultRect)
+ mapVisibleAreaUnsupported.visibleArea = Qt.rect(0,0,256,256)
+ compare(visibleAreaUnsupportedSpy.count, 1)
+ verify(mapVisibleAreaUnsupported.visibleArea, Qt.rect(0,0,256,256))
+ mapVisibleAreaUnsupported.plugin = testPluginNoVisibleArea
+ tryCompare(visibleAreaUnsupportedSpy, "count", 2)
+ verify(mapVisibleAreaUnsupported.visibleArea, defaultRect)
+
+ verify(mapVisibleArea.visibleArea, defaultRect)
+ mapVisibleArea.visibleArea = Qt.rect(0,0,256,256)
+ compare(visibleAreaSpy.count, 1)
+ verify(mapVisibleArea.visibleArea, Qt.rect(0,0,256,256))
+ mapVisibleArea.plugin = testPlugin
+ tryCompare(visibleAreaSpy, "count", 1)
+ verify(mapVisibleAreaUnsupported.visibleArea, Qt.rect(0,0,256,256))
+ }
}
}
diff --git a/tests/auto/geotestplugin/qgeotiledmap_test.cpp b/tests/auto/geotestplugin/qgeotiledmap_test.cpp
index ef2af7db..62abb313 100644
--- a/tests/auto/geotestplugin/qgeotiledmap_test.cpp
+++ b/tests/auto/geotestplugin/qgeotiledmap_test.cpp
@@ -36,8 +36,9 @@ class QGeoTiledMapTestPrivate: public QGeoTiledMapPrivate
{
Q_DECLARE_PUBLIC(QGeoTiledMapTest)
public:
- QGeoTiledMapTestPrivate(QGeoTiledMappingManagerEngine *engine)
- : QGeoTiledMapPrivate(engine)
+ QGeoTiledMapTestPrivate(QGeoTiledMappingManagerEngine *engine,
+ const QGeoTiledMapTestOptions &options)
+ : QGeoTiledMapPrivate(engine), m_options(options)
{
}
@@ -68,10 +69,30 @@ public:
Q_Q(QGeoTiledMapTest);
param->disconnect(q);
}
+
+ virtual void setVisibleArea(const QRectF &visibleArea) override
+ {
+ if (m_options.supportVisibleArea)
+ return QGeoTiledMapPrivate::setVisibleArea(visibleArea);
+ else
+ return QGeoMapPrivate::setVisibleArea(visibleArea);
+ }
+
+ virtual QRectF visibleArea() const override
+ {
+ if (m_options.supportVisibleArea)
+ return QGeoTiledMapPrivate::visibleArea();
+ else
+ return QGeoMapPrivate::visibleArea();
+ }
+
+ QGeoTiledMapTestOptions m_options;
};
-QGeoTiledMapTest::QGeoTiledMapTest(QGeoTiledMappingManagerEngine *engine, QObject *parent)
-: QGeoTiledMap(*new QGeoTiledMapTestPrivate(engine), engine, parent), m_engine(engine)
+QGeoTiledMapTest::QGeoTiledMapTest(QGeoTiledMappingManagerEngine *engine,
+ const QGeoTiledMapTestOptions &options,
+ QObject *parent)
+: QGeoTiledMap(*new QGeoTiledMapTestPrivate(engine, options), engine, parent), m_engine(engine)
{
}
diff --git a/tests/auto/geotestplugin/qgeotiledmap_test.h b/tests/auto/geotestplugin/qgeotiledmap_test.h
index 19c7620e..a6299efe 100644
--- a/tests/auto/geotestplugin/qgeotiledmap_test.h
+++ b/tests/auto/geotestplugin/qgeotiledmap_test.h
@@ -37,12 +37,18 @@ QT_USE_NAMESPACE
class QGeoTiledMappingManagerEngineTest;
class QGeoTiledMapTestPrivate;
+struct QGeoTiledMapTestOptions {
+ bool supportVisibleArea = true;
+};
+
class QGeoTiledMapTest: public QGeoTiledMap
{
Q_OBJECT
Q_DECLARE_PRIVATE(QGeoTiledMapTest)
public:
- QGeoTiledMapTest(QGeoTiledMappingManagerEngine *engine, QObject *parent = 0);
+ QGeoTiledMapTest(QGeoTiledMappingManagerEngine *engine,
+ const QGeoTiledMapTestOptions &options,
+ QObject *parent = 0);
protected slots:
void onCameraCenter_testChanged(QGeoMapParameter *param, const char *propertyName);
diff --git a/tests/auto/geotestplugin/qgeotiledmappingmanagerengine_test.h b/tests/auto/geotestplugin/qgeotiledmappingmanagerengine_test.h
index 297be0d5..0db78336 100644
--- a/tests/auto/geotestplugin/qgeotiledmappingmanagerengine_test.h
+++ b/tests/auto/geotestplugin/qgeotiledmappingmanagerengine_test.h
@@ -100,6 +100,10 @@ public:
double maxZoomLevel = parameters.value(QStringLiteral("maxZoomLevel")).toDouble();
capabilities.setMaximumZoomLevel(maxZoomLevel);
}
+ if (parameters.contains(QStringLiteral("supportVisibleArea"))) {
+ bool supportVisibleArea = parameters.value(QStringLiteral("supportVisibleArea")).toBool();
+ m_supportVisibleArea = supportVisibleArea;
+ }
setCameraCapabilities(capabilities);
fetcher->setTileSize(tileSize());
@@ -108,8 +112,12 @@ public:
QGeoMap *createMap() override
{
- return new QGeoTiledMapTest(this);
+ QGeoTiledMapTestOptions opts;
+ opts.supportVisibleArea = m_supportVisibleArea;
+ return new QGeoTiledMapTest(this, opts);
}
+
+ bool m_supportVisibleArea = true;
};
#endif