summaryrefslogtreecommitdiff
path: root/src/imports
diff options
context:
space:
mode:
authorPaolo Angelelli <paolo.angelelli@qt.io>2017-01-11 16:50:51 +0100
committerPaolo Angelelli <paolo.angelelli@qt.io>2017-01-26 14:45:55 +0000
commit12b62e04e4c17ddeaeaae46ec09af2eb7244e840 (patch)
tree1034de34bde68db66f449b2810fb8505da432e28 /src/imports
parentc03576000da714a73626f985e84b6084c9deb4fd (diff)
downloadqtlocation-12b62e04e4c17ddeaeaae46ec09af2eb7244e840.tar.gz
Make QDeclarativeGeoMap::setVisibleRegion support all QGeoShapes
This patch uses QGeoShape::boundingGeoRectangle to set the visible region, supporting the new QGeoShapes, simplifying the logic in ::fitViewportToGeoShape, and not requiring updates if new QGeoShapes are added. Change-Id: I4f4c21bc0b62aae9432024d8f20db774d191255b Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
Diffstat (limited to 'src/imports')
-rw-r--r--src/imports/location/qdeclarativegeomap.cpp103
-rw-r--r--src/imports/location/qdeclarativegeomap_p.h3
2 files changed, 18 insertions, 88 deletions
diff --git a/src/imports/location/qdeclarativegeomap.cpp b/src/imports/location/qdeclarativegeomap.cpp
index 7182bb21..15d802e6 100644
--- a/src/imports/location/qdeclarativegeomap.cpp
+++ b/src/imports/location/qdeclarativegeomap.cpp
@@ -174,8 +174,7 @@ QDeclarativeGeoMap::QDeclarativeGeoMap(QQuickItem *parent)
m_pendingFitViewport(false),
m_copyrightsVisible(true),
m_maximumViewportLatitude(0.0),
- m_initialized(false),
- m_validRegion(false)
+ m_initialized(false)
{
setAcceptHoverEvents(false);
setAcceptedMouseButtons(Qt::LeftButton);
@@ -795,8 +794,6 @@ void QDeclarativeGeoMap::setZoomLevel(qreal zoomLevel)
m_cameraData.setZoomLevel(zoomLevel);
}
- m_validRegion = false;
-
if (centerHasChanged)
emit centerChanged(m_cameraData.center());
emit zoomLevelChanged(m_cameraData.zoomLevel());
@@ -1011,7 +1008,6 @@ void QDeclarativeGeoMap::setCenter(const QGeoCoordinate &center)
m_cameraData.setCenter(center);
}
- m_validRegion = false;
emit centerChanged(m_cameraData.center());
}
@@ -1041,12 +1037,15 @@ QGeoCoordinate QDeclarativeGeoMap::center() const
*/
void QDeclarativeGeoMap::setVisibleRegion(const QGeoShape &shape)
{
- if (shape == m_region && m_validRegion)
+ if (shape.boundingGeoRectangle() == visibleRegion())
return;
- m_region = shape;
- if (!shape.isValid()) {
+ m_visibleRegion = shape.boundingGeoRectangle();
+ if (!m_visibleRegion.isValid()
+ || (m_visibleRegion.bottomRight().latitude() >= 85.0) // rect entirely outside web mercator
+ || (m_visibleRegion.topLeft().latitude() <= -85.0)) {
// shape invalidated -> nothing to fit anymore
+ m_visibleRegion = QGeoRectangle();
m_pendingFitViewport = false;
return;
}
@@ -1062,7 +1061,7 @@ void QDeclarativeGeoMap::setVisibleRegion(const QGeoShape &shape)
QGeoShape QDeclarativeGeoMap::visibleRegion() const
{
if (!m_map || !width() || !height())
- return m_region;
+ return m_visibleRegion;
QGeoCoordinate tl = m_map->geoProjection().itemPositionToCoordinate(QDoubleVector2D(0, 0));
QGeoCoordinate br = m_map->geoProjection().itemPositionToCoordinate(QDoubleVector2D(width(), height()));
@@ -1121,87 +1120,18 @@ QColor QDeclarativeGeoMap::color() const
return m_color;
}
+// TODO: offer the possibility to specify the margins.
void QDeclarativeGeoMap::fitViewportToGeoShape()
{
- int margins = 10;
- if (!m_map || width() <= margins || height() <= margins)
+ const int margins = 10;
+ if (!m_map || !m_visibleRegion.isValid() || width() <= margins || height() <= margins)
return;
- QGeoCoordinate topLeft;
- QGeoCoordinate bottomRight;
-
- switch (m_region.type()) {
- case QGeoShape::RectangleType:
- {
- QGeoRectangle rect = m_region;
- topLeft = rect.topLeft();
- bottomRight = rect.bottomRight();
- if (bottomRight.longitude() < topLeft.longitude())
- bottomRight.setLongitude(bottomRight.longitude() + 360.0);
-
- break;
- }
- case QGeoShape::CircleType:
- {
- const double pi = M_PI;
- QGeoCircle circle = m_region;
- QGeoCoordinate centerCoordinate = circle.center();
-
- // calculate geo bounding box of the circle
- // circle tangential points with meridians and the north pole create
- // spherical triangle, we use spherical law of sines
- // sin(lon_delta_in_rad)/sin(r_in_rad) =
- // sin(alpha_in_rad)/sin(pi/2 - lat_in_rad), where:
- // * lon_delta_in_rad - delta of longitudes of circle center
- // and tangential points
- // * r_in_rad - angular radius of the circle
- // * lat_in_rad - latitude of circle center
- // * alpha_in_rad - angle between meridian and radius to the circle =>
- // this is tangential point => sin(alpha) = 1
- // * lat_delta_in_rad - delta of latitudes of circle center and
- // latitude of points where great circle (going through circle
- // center) crosses circle and the pole
-
- double r_in_rad = circle.radius() / EARTH_MEAN_RADIUS; // angular r
- double lat_delta_in_deg = r_in_rad * 180 / pi;
- double lon_delta_in_deg = std::asin(std::sin(r_in_rad) /
- std::cos(centerCoordinate.latitude() * pi / 180)) * 180 / pi;
-
- topLeft.setLatitude(centerCoordinate.latitude() + lat_delta_in_deg);
- topLeft.setLongitude(centerCoordinate.longitude() - lon_delta_in_deg);
- bottomRight.setLatitude(centerCoordinate.latitude()
- - lat_delta_in_deg);
- bottomRight.setLongitude(centerCoordinate.longitude()
- + lon_delta_in_deg);
-
- // adjust if circle reaches poles => cross all meridians and
- // fit into Mercator projection bounds
- if (topLeft.latitude() > 90 || bottomRight.latitude() < -90) {
- topLeft.setLatitude(qMin(topLeft.latitude(), 85.05113));
- topLeft.setLongitude(-180.0);
- bottomRight.setLatitude(qMax(bottomRight.latitude(),
- -85.05113));
- bottomRight.setLongitude(180.0);
- }
- break;
- }
- case QGeoShape::UnknownType:
- //Fallthrough to default
- default:
- return;
- }
-
- QDoubleVector2D topLeftPoint = m_map->geoProjection().geoToMapProjection(topLeft);
- QDoubleVector2D bottomRightPoint = m_map->geoProjection().geoToMapProjection(bottomRight);
+ QDoubleVector2D topLeftPoint = m_map->geoProjection().geoToMapProjection(m_visibleRegion.topLeft());
+ QDoubleVector2D bottomRightPoint = m_map->geoProjection().geoToMapProjection(m_visibleRegion.bottomRight());
if (bottomRightPoint.x() < topLeftPoint.x()) // crossing the dateline
bottomRightPoint.setX(bottomRightPoint.x() + 1.0);
-
- double bboxWidth = bottomRightPoint.x() - topLeftPoint.x();
- double bboxHeight = bottomRightPoint.y() - topLeftPoint.y();
- bboxWidth *= m_map->mapWidth();
- bboxHeight *= m_map->mapHeight();
-
// find center of the bounding box
QDoubleVector2D center = (topLeftPoint + bottomRightPoint) * 0.5;
center.setX(center.x() > 1.0 ? center.x() - 1.0 : center.x());
@@ -1211,16 +1141,17 @@ void QDeclarativeGeoMap::fitViewportToGeoShape()
setCenter(centerCoordinate);
// if the shape is empty we just change center position, not zoom
- if (bboxHeight == 0 && bboxWidth == 0)
+ double bboxWidth = (bottomRightPoint.x() - topLeftPoint.x()) * m_map->mapWidth();
+ double bboxHeight = (bottomRightPoint.y() - topLeftPoint.y()) * m_map->mapHeight();
+
+ if (bboxHeight == 0.0 && bboxWidth == 0.0)
return;
double zoomRatio = qMax(bboxWidth / (width() - margins),
bboxHeight / (height() - margins));
- // fixme: use log2 with c++11
zoomRatio = std::log(zoomRatio) / std::log(2.0);
double newZoom = qMax<double>(minimumZoomLevel(), zoomLevel() - zoomRatio);
setZoomLevel(newZoom);
- m_validRegion = true;
}
diff --git a/src/imports/location/qdeclarativegeomap_p.h b/src/imports/location/qdeclarativegeomap_p.h
index b85daf1a..c77c3338 100644
--- a/src/imports/location/qdeclarativegeomap_p.h
+++ b/src/imports/location/qdeclarativegeomap_p.h
@@ -239,7 +239,7 @@ private:
QList<QPointer<QDeclarativeGeoMapItemBase> > m_mapItems;
QString m_errorString;
QGeoServiceProvider::Error m_error;
- QGeoShape m_region;
+ QGeoRectangle m_visibleRegion;
QColor m_color;
QGeoCameraData m_cameraData;
bool m_componentCompleted;
@@ -247,7 +247,6 @@ private:
bool m_copyrightsVisible;
double m_maximumViewportLatitude;
bool m_initialized;
- bool m_validRegion;
QSet<QDeclarativeGeoMapParameter *> m_mapParameters;
friend class QDeclarativeGeoMapItem;