diff options
Diffstat (limited to 'src')
18 files changed, 515 insertions, 235 deletions
diff --git a/src/location/declarativemaps/qdeclarativecirclemapitem.cpp b/src/location/declarativemaps/qdeclarativecirclemapitem.cpp index 91328dc7..a1e34a30 100644 --- a/src/location/declarativemaps/qdeclarativecirclemapitem.cpp +++ b/src/location/declarativemaps/qdeclarativecirclemapitem.cpp @@ -144,6 +144,7 @@ QGeoMapCircleGeometry::QGeoMapCircleGeometry() */ void QGeoMapCircleGeometry::updateScreenPointsInvert(const QList<QDoubleVector2D> &circlePath, const QGeoMap &map) { + const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(map.geoProjection()); // Not checking for !screenDirty anymore, as everything is now recalculated. clear(); if (map.viewportWidth() == 0 || map.viewportHeight() == 0 || circlePath.size() < 3) // a circle requires at least 3 points; @@ -160,23 +161,23 @@ void QGeoMapCircleGeometry::updateScreenPointsInvert(const QList<QDoubleVector2D */ // 1) - double topLati = QLocationUtils::mercatorMaxLatitude(); - double bottomLati = -(QLocationUtils::mercatorMaxLatitude()); - double leftLongi = QLocationUtils::mapLeftLongitude(map.cameraData().center().longitude()); - double rightLongi = QLocationUtils::mapRightLongitude(map.cameraData().center().longitude()); + const double topLati = QLocationUtils::mercatorMaxLatitude(); + const double bottomLati = -(QLocationUtils::mercatorMaxLatitude()); + const double leftLongi = QLocationUtils::mapLeftLongitude(map.cameraData().center().longitude()); + const double rightLongi = QLocationUtils::mapRightLongitude(map.cameraData().center().longitude()); srcOrigin_ = QGeoCoordinate(topLati,leftLongi); - QDoubleVector2D tl = map.geoProjection().geoToWrappedMapProjection(QGeoCoordinate(topLati,leftLongi)); - QDoubleVector2D tr = map.geoProjection().geoToWrappedMapProjection(QGeoCoordinate(topLati,rightLongi)); - QDoubleVector2D br = map.geoProjection().geoToWrappedMapProjection(QGeoCoordinate(bottomLati,rightLongi)); - QDoubleVector2D bl = map.geoProjection().geoToWrappedMapProjection(QGeoCoordinate(bottomLati,leftLongi)); + const QDoubleVector2D tl = p.geoToWrappedMapProjection(QGeoCoordinate(topLati,leftLongi)); + const QDoubleVector2D tr = p.geoToWrappedMapProjection(QGeoCoordinate(topLati,rightLongi)); + const QDoubleVector2D br = p.geoToWrappedMapProjection(QGeoCoordinate(bottomLati,rightLongi)); + const QDoubleVector2D bl = p.geoToWrappedMapProjection(QGeoCoordinate(bottomLati,leftLongi)); QList<QDoubleVector2D> fill; fill << tl << tr << br << bl; QList<QDoubleVector2D> hole; for (const QDoubleVector2D &c: circlePath) - hole << map.geoProjection().wrapMapProjection(c); + hole << p.wrapMapProjection(c); c2t::clip2tri clipper; clipper.addSubjectPath(QClipperUtils::qListToPath(fill), true); @@ -184,9 +185,9 @@ void QGeoMapCircleGeometry::updateScreenPointsInvert(const QList<QDoubleVector2D Paths difference = clipper.execute(c2t::clip2tri::Difference, QtClipperLib::pftEvenOdd, QtClipperLib::pftEvenOdd); // 2) - QDoubleVector2D lb = map.geoProjection().geoToWrappedMapProjection(srcOrigin_); + QDoubleVector2D lb = p.geoToWrappedMapProjection(srcOrigin_); QList<QList<QDoubleVector2D> > clippedPaths; - const QList<QDoubleVector2D> &visibleRegion = map.geoProjection().visibleRegion(); + const QList<QDoubleVector2D> &visibleRegion = p.visibleGeometry(); if (visibleRegion.size()) { clipper.clearClipper(); for (const Path &p: difference) @@ -210,19 +211,19 @@ void QGeoMapCircleGeometry::updateScreenPointsInvert(const QList<QDoubleVector2D // Prevent the conversion to and from clipper from introducing negative offsets which // in turn will make the geometry wrap around. lb.setX(qMax(tl.x(), lb.x())); - srcOrigin_ = map.geoProjection().mapProjectionToGeo(map.geoProjection().unwrapMapProjection(lb)); + srcOrigin_ = p.mapProjectionToGeo(p.unwrapMapProjection(lb)); } else { clippedPaths = QClipperUtils::pathsToQList(difference); } //3) - QDoubleVector2D origin = map.geoProjection().wrappedMapProjectionToItemPosition(lb); + QDoubleVector2D origin = p.wrappedMapProjectionToItemPosition(lb); QPainterPath ppi; for (const QList<QDoubleVector2D> &path: clippedPaths) { QDoubleVector2D lastAddedPoint; for (int i = 0; i < path.size(); ++i) { - QDoubleVector2D point = map.geoProjection().wrappedMapProjectionToItemPosition(path.at(i)); + QDoubleVector2D point = p.wrappedMapProjectionToItemPosition(path.at(i)); //point = point - origin; // Do this using ppi.translate() if (i == 0) { @@ -483,9 +484,11 @@ QSGNode *QDeclarativeCircleMapItem::updateMapItemPaintNode(QSGNode *oldNode, Upd */ void QDeclarativeCircleMapItem::updatePolish() { - if (!map() || !circle_.isValid()) + if (!map() || !circle_.isValid() + || map()->geoProjection().projectionType() != QGeoProjection::ProjectionWebMercator) return; + const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(map()->geoProjection()); QScopedValueRollback<bool> rollback(updatingGeometry_); updatingGeometry_ = true; @@ -533,7 +536,7 @@ void QDeclarativeCircleMapItem::updatePolish() QDoubleVector2D borderLeftBoundWrapped; QList<QList<QDoubleVector2D > > clippedPaths = borderGeometry_.clipPath(*map(), closedPath, borderLeftBoundWrapped); if (clippedPaths.size()) { - borderLeftBoundWrapped = map()->geoProjection().geoToWrappedMapProjection(geometryOrigin); + borderLeftBoundWrapped = p.geoToWrappedMapProjection(geometryOrigin); borderGeometry_.pathToScreen(*map(), clippedPaths, borderLeftBoundWrapped); borderGeometry_.updateScreenPoints(*map(), border_.width()); geoms << &borderGeometry_; @@ -565,13 +568,15 @@ void QDeclarativeCircleMapItem::afterViewportChanged(const QGeoMapViewportChange */ void QDeclarativeCircleMapItem::updateCirclePath() { - if (!map()) + if (!map() || map()->geoProjection().projectionType() != QGeoProjection::ProjectionWebMercator) return; + + const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(map()->geoProjection()); QList<QGeoCoordinate> path; calculatePeripheralPoints(path, circle_.center(), circle_.radius(), CircleSamples, leftBound_); circlePath_.clear(); for (const QGeoCoordinate &c : path) - circlePath_ << map()->geoProjection().geoToMapProjection(c); + circlePath_ << p.geoToMapProjection(c); } /*! @@ -644,6 +649,7 @@ void QDeclarativeCircleMapItem::updateCirclePathForRendering(QList<QDoubleVector const QGeoCoordinate ¢er, qreal distance) { + const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(map()->geoProjection()); const qreal poleLat = 90; const qreal distanceToNorthPole = center.distanceTo(QGeoCoordinate(poleLat, 0)); const qreal distanceToSouthPole = center.distanceTo(QGeoCoordinate(-poleLat, 0)); @@ -651,11 +657,11 @@ void QDeclarativeCircleMapItem::updateCirclePathForRendering(QList<QDoubleVector bool crossSouthPole = distanceToSouthPole < distance; QList<int> wrapPathIndex; - QDoubleVector2D prev = map()->geoProjection().wrapMapProjection(path.at(0)); + QDoubleVector2D prev = p.wrapMapProjection(path.at(0)); for (int i = 1; i <= path.count(); ++i) { int index = i % path.count(); - QDoubleVector2D point = map()->geoProjection().wrapMapProjection(path.at(index)); + QDoubleVector2D point = p.wrapMapProjection(path.at(index)); double diff = qAbs(point.x() - prev.x()); if (diff > 0.5) { continue; @@ -665,7 +671,7 @@ void QDeclarativeCircleMapItem::updateCirclePathForRendering(QList<QDoubleVector // find the points in path where wrapping occurs for (int i = 1; i <= path.count(); ++i) { int index = i % path.count(); - QDoubleVector2D point = map()->geoProjection().wrapMapProjection(path.at(index)); + QDoubleVector2D point = p.wrapMapProjection(path.at(index)); if ( (qAbs(point.x() - prev.x())) >= 0.5 ) { wrapPathIndex << index; if (wrapPathIndex.size() == 2 || !(crossNorthPole && crossSouthPole)) diff --git a/src/location/declarativemaps/qdeclarativegeomap.cpp b/src/location/declarativemaps/qdeclarativegeomap.cpp index 42ed633d..c5d01ebd 100644 --- a/src/location/declarativemaps/qdeclarativegeomap.cpp +++ b/src/location/declarativemaps/qdeclarativegeomap.cpp @@ -61,6 +61,15 @@ QT_BEGIN_NAMESPACE +static qreal sanitizeBearing(qreal bearing) +{ + bearing = std::fmod(bearing, qreal(360.0)); + if (bearing < 0.0) + bearing += 360.0; + + return bearing; +} + /*! \qmltype Map \instantiates QDeclarativeGeoMap @@ -389,7 +398,7 @@ void QDeclarativeGeoMap::initialize() QGeoCoordinate center = m_cameraData.center(); - if (qIsNaN(m_userMinimumZoomLevel)) + if (!qIsFinite(m_userMinimumZoomLevel)) setMinimumZoomLevel(m_map->minimumZoom(), false); else setMinimumZoomLevel(qMax<qreal>(m_map->minimumZoom(), m_userMinimumZoomLevel), false); @@ -681,7 +690,7 @@ void QDeclarativeGeoMap::onCameraCapabilitiesChanged(const QGeoCameraCapabilitie if (m_cameraCapabilities.maximumZoomLevelAt256() < m_gestureArea->maximumZoomLevel()) { setMaximumZoomLevel(m_cameraCapabilities.maximumZoomLevelAt256(), false); } else if (m_cameraCapabilities.maximumZoomLevelAt256() > m_gestureArea->maximumZoomLevel()) { - if (qIsNaN(m_userMaximumZoomLevel)) { + if (!qIsFinite(m_userMaximumZoomLevel)) { // If the user didn't set anything setMaximumZoomLevel(m_cameraCapabilities.maximumZoomLevelAt256(), false); } else { // Try to set what the user requested @@ -694,7 +703,7 @@ void QDeclarativeGeoMap::onCameraCapabilitiesChanged(const QGeoCameraCapabilitie if (m_cameraCapabilities.minimumZoomLevelAt256() > m_gestureArea->minimumZoomLevel()) { setMinimumZoomLevel(m_cameraCapabilities.minimumZoomLevelAt256(), false); } else if (m_cameraCapabilities.minimumZoomLevelAt256() < m_gestureArea->minimumZoomLevel()) { - if (qIsNaN(m_userMinimumZoomLevel)) { + if (!qIsFinite(m_userMinimumZoomLevel)) { // If the user didn't set anything, trying to set the new caps. setMinimumZoomLevel(m_cameraCapabilities.minimumZoomLevelAt256(), false); } else { // Try to set what the user requested @@ -710,7 +719,7 @@ void QDeclarativeGeoMap::onCameraCapabilitiesChanged(const QGeoCameraCapabilitie if (m_cameraCapabilities.maximumTilt() < m_maximumTilt) { setMaximumTilt(m_cameraCapabilities.maximumTilt(), false); } else if (m_cameraCapabilities.maximumTilt() > m_maximumTilt) { - if (qIsNaN(m_userMaximumTilt)) + if (!qIsFinite(m_userMaximumTilt)) setMaximumTilt(m_cameraCapabilities.maximumTilt(), false); else // Try to set what the user requested setMaximumTilt(qMin<qreal>(m_cameraCapabilities.maximumTilt(), m_userMaximumTilt), false); @@ -719,7 +728,7 @@ void QDeclarativeGeoMap::onCameraCapabilitiesChanged(const QGeoCameraCapabilitie if (m_cameraCapabilities.minimumTilt() > m_minimumTilt) { setMinimumTilt(m_cameraCapabilities.minimumTilt(), false); } else if (m_cameraCapabilities.minimumTilt() < m_minimumTilt) { - if (qIsNaN(m_userMinimumTilt)) + if (!qIsFinite(m_userMinimumTilt)) setMinimumTilt(m_cameraCapabilities.minimumTilt(), false); else // Try to set what the user requested setMinimumTilt(qMax<qreal>(m_cameraCapabilities.minimumTilt(), m_userMinimumTilt), false); @@ -729,7 +738,7 @@ void QDeclarativeGeoMap::onCameraCapabilitiesChanged(const QGeoCameraCapabilitie if (m_cameraCapabilities.maximumFieldOfView() < m_maximumFieldOfView) { setMaximumFieldOfView(m_cameraCapabilities.maximumFieldOfView(), false); } else if (m_cameraCapabilities.maximumFieldOfView() > m_maximumFieldOfView) { - if (qIsNaN(m_userMaximumFieldOfView)) + if (!qIsFinite(m_userMaximumFieldOfView)) setMaximumFieldOfView(m_cameraCapabilities.maximumFieldOfView(), false); else // Try to set what the user requested setMaximumFieldOfView(qMin<qreal>(m_cameraCapabilities.maximumFieldOfView(), m_userMaximumFieldOfView), false); @@ -738,7 +747,7 @@ void QDeclarativeGeoMap::onCameraCapabilitiesChanged(const QGeoCameraCapabilitie if (m_cameraCapabilities.minimumFieldOfView() > m_minimumFieldOfView) { setMinimumFieldOfView(m_cameraCapabilities.minimumFieldOfView(), false); } else if (m_cameraCapabilities.minimumFieldOfView() < m_minimumFieldOfView) { - if (qIsNaN(m_userMinimumFieldOfView)) + if (!qIsFinite(m_userMinimumFieldOfView)) setMinimumFieldOfView(m_cameraCapabilities.minimumFieldOfView(), false); else // Try to set what the user requested setMinimumFieldOfView(qMax<qreal>(m_cameraCapabilities.minimumFieldOfView(), m_userMinimumFieldOfView), false); @@ -1042,12 +1051,8 @@ qreal QDeclarativeGeoMap::zoomLevel() const */ void QDeclarativeGeoMap::setBearing(qreal bearing) { - bearing = std::fmod(bearing, qreal(360.0)); - if (bearing < 0.0) - bearing += 360.0; - if (m_map && !m_cameraCapabilities.supportsBearing()) - bearing = 0.0; - if (m_cameraData.bearing() == bearing || bearing < 0.0) + bearing = sanitizeBearing(bearing); + if (m_cameraData.bearing() == bearing) return; m_cameraData.setBearing(bearing); @@ -1056,6 +1061,45 @@ void QDeclarativeGeoMap::setBearing(qreal bearing) emit bearingChanged(bearing); } +/*! + \qmlmethod void QtLocation::Map::setBearing(real bearing, coordinate coordinate) + + Sets the bearing for the map to \a bearing, rotating it around \a coordinate. + If the Plugin used for the Map supports bearing, the valid range for \a bearing is between 0 and 360. + If the Plugin used for the Map does not support bearing, or if the map is tilted and \a coordinate happens + to be behind the camera, or if the map is not ready (see \l mapReady), calling this method will have no effect. + + The release of this API with Qt 5.10 is a Technology Preview. + + \since 5.10 +*/ +void QDeclarativeGeoMap::setBearing(qreal bearing, const QGeoCoordinate &coordinate) +{ + if (!m_map) + return; + + const QGeoCoordinate currentCenter = center(); + const qreal currentBearing = QDeclarativeGeoMap::bearing(); + bearing = sanitizeBearing(bearing); + + if (!coordinate.isValid() + || !qIsFinite(bearing) + || (coordinate == currentCenter && bearing == currentBearing)) + return; + + if (m_map->capabilities() & QGeoMap::SupportsSetBearing) { + if (!m_map->setBearing(bearing, coordinate)) + return; + + m_cameraData = m_map->cameraData(); + + if (m_cameraData.center() != currentCenter) + emit centerChanged(m_cameraData.center()); + if (m_cameraData.bearing() != currentBearing) + emit bearingChanged(bearing); + } +} + qreal QDeclarativeGeoMap::bearing() const { return m_cameraData.bearing(); @@ -1351,23 +1395,23 @@ QGeoShape QDeclarativeGeoMap::visibleRegion() const if (!m_map || !width() || !height()) return m_visibleRegion; - const QList<QDoubleVector2D> &visibleRegion = m_map->geoProjection().visibleRegion(); - QGeoPolygon poly; - for (int i = 0; i < visibleRegion.size(); ++i) { - const QDoubleVector2D &c = visibleRegion.at(i); - // If a segment spans more than half of the map longitudinally, split in 2. - if (i && qAbs(visibleRegion.at(i-1).x() - c.x()) >= 0.5) { // This assumes a segment is never >= 1.0 (whole map span) - QDoubleVector2D extraPoint = (visibleRegion.at(i-1) + c) * 0.5; - poly.addCoordinate(m_map->geoProjection().wrappedMapProjectionToGeo(extraPoint)); - } - poly.addCoordinate(m_map->geoProjection().wrappedMapProjectionToGeo(c)); - } - if (visibleRegion.size() >= 2 && qAbs(visibleRegion.last().x() - visibleRegion.first().x()) >= 0.5) { - QDoubleVector2D extraPoint = (visibleRegion.last() + visibleRegion.first()) * 0.5; - poly.addCoordinate(m_map->geoProjection().wrappedMapProjectionToGeo(extraPoint)); + if (m_map->capabilities() & QGeoMap::SupportsVisibleRegion) { + return m_map->visibleRegion(); + } else { + // ToDo: handle projections not supporting visible region in a better way. + // This approach will fail when horizon is in the view or the map is greatly zoomed out. + QList<QGeoCoordinate> visiblePoly; + visiblePoly << m_map->geoProjection().itemPositionToCoordinate(QDoubleVector2D(0,0), false); + visiblePoly << m_map->geoProjection().itemPositionToCoordinate(QDoubleVector2D(m_map->viewportWidth() - 1, + 0), false); + visiblePoly << m_map->geoProjection().itemPositionToCoordinate(QDoubleVector2D(m_map->viewportWidth() - 1, + m_map->viewportHeight() - 1), false); + visiblePoly << m_map->geoProjection().itemPositionToCoordinate(QDoubleVector2D(0, + m_map->viewportHeight() - 1), false); + QGeoPath path; + path.setPath(visiblePoly); + return path.boundingGeoRectangle(); } - - return poly; } /*! @@ -1439,35 +1483,53 @@ bool QDeclarativeGeoMap::mapReady() const // TODO: offer the possibility to specify the margins. void QDeclarativeGeoMap::fitViewportToGeoShape() { - const int margins = 10; - if (!m_map || !m_visibleRegion.isValid() || width() <= margins || height() <= margins) - return; - - 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); - - // 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 = m_map->geoProjection().mapProjectionToGeo(center); - - // 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(); - - if (bboxHeight == 0.0 && bboxWidth == 0.0) - 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); - setProperty("zoomLevel", QVariant::fromValue(newZoom)); // not using setZoomLevel(newZoom) to honor a possible animation set on the zoomLevel property + if (m_map->geoProjection().projectionType() == QGeoProjection::ProjectionWebMercator) { + // 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; + + 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); + + // 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); + + // 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(); + + if (bboxHeight == 0.0 && bboxWidth == 0.0) + 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); + 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 + const QGeoCoordinate currentCenter = center(); + const qreal currentZoom = zoomLevel(); + + if (!m_map->fitViewportToGeoRectangle(m_visibleRegion)) + return; + + m_cameraData = m_map->cameraData(); + if (m_cameraData.center() != currentCenter) + emit centerChanged(m_cameraData.center()); + if (m_cameraData.zoomLevel() != currentZoom) + emit zoomLevelChanged(m_cameraData.zoomLevel()); + } } @@ -1484,35 +1546,6 @@ QQmlListProperty<QDeclarativeGeoMapType> QDeclarativeGeoMap::supportedMapTypes() } /*! - \qmlmethod void QtLocation::Map::setBearing(real bearing, coordinate coordinate) - - Sets the bearing for the map to \a bearing, rotating it around \a coordinate. - If the Plugin used for the Map supports bearing, the valid range for \a bearing is between 0 and 360. - If the Plugin used for the Map does not support bearing, or if the map is tilted and \a coordinate happens - to be behind the camera, or if the map is not ready (see \l mapReady), calling this method will have no effect. - - The release of this API with Qt 5.10 is a Technology Preview. - - \since 5.10 -*/ -void QDeclarativeGeoMap::setBearing(qreal bearing, const QGeoCoordinate &coordinate) -{ - if (!m_map) - return; - - const QDoubleVector2D coordWrapped = m_map->geoProjection().geoToWrappedMapProjection(coordinate); - if (!m_map->geoProjection().isProjectable(coordWrapped)) - return; - - const QPointF rotationPoint = m_map->geoProjection().wrappedMapProjectionToItemPosition(coordWrapped).toPointF(); - - // First set bearing - setBearing(bearing); - // then reanchor - setCenter(m_map->geoProjection().anchorCoordinateToPoint(coordinate, rotationPoint)); -} - -/*! \qmlmethod void QtLocation::Map::alignCoordinateToPoint(coordinate coordinate, QPointF point) Aligns \a coordinate to \a point. @@ -1532,10 +1565,23 @@ void QDeclarativeGeoMap::setBearing(qreal bearing, const QGeoCoordinate &coordin */ void QDeclarativeGeoMap::alignCoordinateToPoint(const QGeoCoordinate &coordinate, const QPointF &point) { - if (!m_map) + if (!m_map || !(m_map->capabilities() & QGeoMap::SupportsAnchoringCoordinate)) + return; + + const QGeoCoordinate currentCenter = center(); + + if (!coordinate.isValid() + || !qIsFinite(point.x()) + || !qIsFinite(point.y())) return; - setCenter(m_map->geoProjection().anchorCoordinateToPoint(coordinate, point)); + if (!m_map->anchorCoordinateToPoint(coordinate, point)) + return; + + m_cameraData = m_map->cameraData(); + + if (m_cameraData.center() != currentCenter) + emit centerChanged(m_cameraData.center()); } /*! diff --git a/src/location/declarativemaps/qdeclarativegeomapitembase.cpp b/src/location/declarativemaps/qdeclarativegeomapitembase.cpp index 729825fd..fed0a74b 100644 --- a/src/location/declarativemaps/qdeclarativegeomapitembase.cpp +++ b/src/location/declarativemaps/qdeclarativegeomapitembase.cpp @@ -185,11 +185,19 @@ void QDeclarativeGeoMapItemBase::setPositionOnMap(const QGeoCoordinate &coordina if (!map_ || !quickMap_) return; - QDoubleVector2D wrappedProjection = map_->geoProjection().geoToWrappedMapProjection(coordinate); - if (!map_->geoProjection().isProjectable(wrappedProjection)) - return; + QDoubleVector2D pos; + if (map()->geoProjection().projectionType() == QGeoProjection::ProjectionWebMercator) { + const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(map()->geoProjection()); + QDoubleVector2D wrappedProjection = p.geoToWrappedMapProjection(coordinate); + if (!p.isProjectable(wrappedProjection)) + return; + pos = p.wrappedMapProjectionToItemPosition(wrappedProjection); + } else { + pos = map()->geoProjection().coordinateToItemPosition(coordinate, false); + if (qIsNaN(pos.x())) + return; + } - QDoubleVector2D pos = map_->geoProjection().wrappedMapProjectionToItemPosition(wrappedProjection); QPointF topLeft = pos.toPointF() - offset; setPosition(topLeft); diff --git a/src/location/declarativemaps/qdeclarativegeomapquickitem.cpp b/src/location/declarativemaps/qdeclarativegeomapquickitem.cpp index 7c0764aa..43efc940 100644 --- a/src/location/declarativemaps/qdeclarativegeomapquickitem.cpp +++ b/src/location/declarativemaps/qdeclarativegeomapquickitem.cpp @@ -210,9 +210,12 @@ void QDeclarativeGeoMapQuickItem::geometryChanged(const QRectF &newGeometry, con QGeoCoordinate newCoordinate; // with zoomLevel set the anchorPoint has to be factored into the transformation to properly transform around it. - if (zoomLevel_ != 0.0) { + if (zoomLevel_ != 0.0 + && map()->geoProjection().projectionType() == QGeoProjection::ProjectionWebMercator) { + const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(map()->geoProjection()); + // When dragStartCoordinate_ can't be projected to screen, dragging must be disabled. - if (!map()->geoProjection().isProjectable(map()->geoProjection().geoToWrappedMapProjection(dragStartCoordinate_))) + if (!p.isProjectable(p.geoToWrappedMapProjection(dragStartCoordinate_))) return; QDoubleVector2D pos = map()->geoProjection().coordinateToItemPosition(dragStartCoordinate_, false); @@ -392,27 +395,42 @@ void QDeclarativeGeoMapQuickItem::updatePolish() setWidth(sourceItem_.data()->width()); setHeight(sourceItem_.data()->height()); - if (zoomLevel_ != 0.0) { // zoom level initialized to 0.0. If it's different, it has been set explicitly. + if (zoomLevel_ != 0.0 // zoom level initialized to 0.0. If it's different, it has been set explicitly. + && map()->geoProjection().projectionType() == QGeoProjection::ProjectionWebMercator) { // Currently unsupported on any other projection + const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(map()->geoProjection()); + if (!matrix_) { matrix_ = new QMapQuickItemMatrix4x4(this); matrix_->appendToItem(opacityContainer_); } - matrix_->setMatrix(map()->geoProjection().quickItemTransformation(coordinate(), anchorPoint_, zoomLevel_)); + matrix_->setMatrix(p.quickItemTransformation(coordinate(), anchorPoint_, zoomLevel_)); setPosition(QPointF(0,0)); } else { - // if the coordinate is behind the camera, we use the transformation to get the item out of the way - if (map()->cameraData().tilt() > 0.0 - && !map()->geoProjection().isProjectable(map()->geoProjection().geoToWrappedMapProjection(coordinate()))) { - if (!matrix_) { - matrix_ = new QMapQuickItemMatrix4x4(this); - matrix_->appendToItem(opacityContainer_); + if (map()->geoProjection().projectionType() == QGeoProjection::ProjectionWebMercator) { + const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(map()->geoProjection()); + if (map()->cameraData().tilt() > 0.0 + && !p.isProjectable(p.geoToWrappedMapProjection(coordinate()))) { + // if the coordinate is behind the camera, we use the transformation to get the item out of the way + if (!matrix_) { + matrix_ = new QMapQuickItemMatrix4x4(this); + matrix_->appendToItem(opacityContainer_); + } + matrix_->setMatrix(p.quickItemTransformation(coordinate(), anchorPoint_, map()->cameraData().zoomLevel())); + setPosition(QPointF(0,0)); + } else { // All good, rendering screen-aligned + if (matrix_) + matrix_->setMatrix(QMatrix4x4()); + setPositionOnMap(coordinate(), anchorPoint_); + } + } else { // On other projections we can only currently test if coordinateToItemPosition returns a valid position + if (map()->cameraData().tilt() > 0.0 + && qIsNaN(map()->geoProjection().coordinateToItemPosition(coordinate(), false).x())) { + opacityContainer_->setVisible(false); + } else { + if (matrix_) + matrix_->setMatrix(QMatrix4x4()); + setPositionOnMap(coordinate(), anchorPoint_); } - matrix_->setMatrix(map()->geoProjection().quickItemTransformation(coordinate(), anchorPoint_, map()->cameraData().zoomLevel())); - setPosition(QPointF(0,0)); - } else { - if (matrix_) - matrix_->setMatrix(QMatrix4x4()); - setPositionOnMap(coordinate(), anchorPoint_); } } } diff --git a/src/location/declarativemaps/qdeclarativepolygonmapitem.cpp b/src/location/declarativemaps/qdeclarativepolygonmapitem.cpp index 8c7afc17..aa3a3bd9 100644 --- a/src/location/declarativemaps/qdeclarativepolygonmapitem.cpp +++ b/src/location/declarativemaps/qdeclarativepolygonmapitem.cpp @@ -147,14 +147,14 @@ void QGeoMapPolygonGeometry::updateSourcePoints(const QGeoMap &map, { if (!sourceDirty_) return; - + const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(map.geoProjection()); srcPath_ = QPainterPath(); // build the actual path // The approach is the same as described in QGeoMapPolylineGeometry::updateSourcePoints srcOrigin_ = geoLeftBound_; double unwrapBelowX = 0; - QDoubleVector2D leftBoundWrapped = map.geoProjection().wrapMapProjection(map.geoProjection().geoToMapProjection(geoLeftBound_)); + QDoubleVector2D leftBoundWrapped = p.wrapMapProjection(p.geoToMapProjection(geoLeftBound_)); if (preserveGeometry_) unwrapBelowX = leftBoundWrapped.x(); @@ -164,7 +164,7 @@ void QGeoMapPolygonGeometry::updateSourcePoints(const QGeoMap &map, // 1) for (int i = 0; i < path.size(); ++i) { const QDoubleVector2D &coord = path.at(i); - QDoubleVector2D wrappedProjection = map.geoProjection().wrapMapProjection(coord); + QDoubleVector2D wrappedProjection = p.wrapMapProjection(coord); // We can get NaN if the map isn't set up correctly, or the projection // is faulty -- probably best thing to do is abort @@ -187,7 +187,7 @@ void QGeoMapPolygonGeometry::updateSourcePoints(const QGeoMap &map, // 2) QList<QList<QDoubleVector2D> > clippedPaths; - const QList<QDoubleVector2D> &visibleRegion = map.geoProjection().projectableRegion(); + const QList<QDoubleVector2D> &visibleRegion = p.projectableGeometry(); if (visibleRegion.size()) { c2t::clip2tri clipper; clipper.addSubjectPath(QClipperUtils::qListToPath(wrappedPath), true); @@ -210,17 +210,17 @@ void QGeoMapPolygonGeometry::updateSourcePoints(const QGeoMap &map, // in turn will make the geometry wrap around. lb.setX(qMax(wrappedLeftBound.x(), lb.x())); leftBoundWrapped = lb; - srcOrigin_ = map.geoProjection().mapProjectionToGeo(map.geoProjection().unwrapMapProjection(lb)); + srcOrigin_ = p.mapProjectionToGeo(p.unwrapMapProjection(lb)); } else { clippedPaths.append(wrappedPath); } // 3) - QDoubleVector2D origin = map.geoProjection().wrappedMapProjectionToItemPosition(leftBoundWrapped); + QDoubleVector2D origin = p.wrappedMapProjectionToItemPosition(leftBoundWrapped); for (const QList<QDoubleVector2D> &path: clippedPaths) { QDoubleVector2D lastAddedPoint; for (int i = 0; i < path.size(); ++i) { - QDoubleVector2D point = map.geoProjection().wrappedMapProjectionToItemPosition(path.at(i)); + QDoubleVector2D point = p.wrappedMapProjectionToItemPosition(path.at(i)); point = point - origin; // (0,0) if point == geoLeftBound_ if (i == 0) { @@ -500,9 +500,11 @@ QSGNode *QDeclarativePolygonMapItem::updateMapItemPaintNode(QSGNode *oldNode, Up */ void QDeclarativePolygonMapItem::updatePolish() { - if (!map() || geopath_.path().length() == 0) + if (!map() || geopath_.path().length() == 0 + || map()->geoProjection().projectionType() != QGeoProjection::ProjectionWebMercator) return; + const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(map()->geoProjection()); QScopedValueRollback<bool> rollback(updatingGeometry_); updatingGeometry_ = true; @@ -527,7 +529,7 @@ void QDeclarativePolygonMapItem::updatePolish() QDoubleVector2D borderLeftBoundWrapped; QList<QList<QDoubleVector2D > > clippedPaths = borderGeometry_.clipPath(*map(), closedPath, borderLeftBoundWrapped); if (clippedPaths.size()) { - borderLeftBoundWrapped = map()->geoProjection().geoToWrappedMapProjection(geometryOrigin); + borderLeftBoundWrapped = p.geoToWrappedMapProjection(geometryOrigin); borderGeometry_.pathToScreen(*map(), clippedPaths, borderLeftBoundWrapped); borderGeometry_.updateScreenPoints(*map(), border_.width()); @@ -571,12 +573,13 @@ void QDeclarativePolygonMapItem::afterViewportChanged(const QGeoMapViewportChang */ void QDeclarativePolygonMapItem::regenerateCache() { - if (!map()) + if (!map() || map()->geoProjection().projectionType() != QGeoProjection::ProjectionWebMercator) return; + const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(map()->geoProjection()); geopathProjected_.clear(); geopathProjected_.reserve(geopath_.path().size()); for (const QGeoCoordinate &c : geopath_.path()) - geopathProjected_ << map()->geoProjection().geoToMapProjection(c); + geopathProjected_ << p.geoToMapProjection(c); } /*! @@ -584,9 +587,10 @@ void QDeclarativePolygonMapItem::regenerateCache() */ void QDeclarativePolygonMapItem::updateCache() { - if (!map()) + if (!map() || map()->geoProjection().projectionType() != QGeoProjection::ProjectionWebMercator) return; - geopathProjected_ << map()->geoProjection().geoToMapProjection(geopath_.path().last()); + const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(map()->geoProjection()); + geopathProjected_ << p.geoToMapProjection(geopath_.path().last()); } /*! diff --git a/src/location/declarativemaps/qdeclarativepolylinemapitem.cpp b/src/location/declarativemaps/qdeclarativepolylinemapitem.cpp index 7c1b922f..90ed95e4 100644 --- a/src/location/declarativemaps/qdeclarativepolylinemapitem.cpp +++ b/src/location/declarativemaps/qdeclarativepolylinemapitem.cpp @@ -189,11 +189,11 @@ QList<QList<QDoubleVector2D> > QGeoMapPolylineGeometry::clipPath(const QGeoMap & * 2.1) recalculate the origin and geoLeftBound to prevent these parameters from ending in unprojectable areas * 2.2) ensure the left bound does not wrap around due to QGeoCoordinate <-> clipper conversions */ - + const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(map.geoProjection()); srcOrigin_ = geoLeftBound_; double unwrapBelowX = 0; - leftBoundWrapped = map.geoProjection().wrapMapProjection(map.geoProjection().geoToMapProjection(geoLeftBound_)); + leftBoundWrapped = p.wrapMapProjection(p.geoToMapProjection(geoLeftBound_)); if (preserveGeometry_) unwrapBelowX = leftBoundWrapped.x(); @@ -203,7 +203,7 @@ QList<QList<QDoubleVector2D> > QGeoMapPolylineGeometry::clipPath(const QGeoMap & // 1) for (int i = 0; i < path.size(); ++i) { const QDoubleVector2D &coord = path.at(i); - QDoubleVector2D wrappedProjection = map.geoProjection().wrapMapProjection(coord); + QDoubleVector2D wrappedProjection = p.wrapMapProjection(coord); // We can get NaN if the map isn't set up correctly, or the projection // is faulty -- probably best thing to do is abort @@ -226,7 +226,7 @@ QList<QList<QDoubleVector2D> > QGeoMapPolylineGeometry::clipPath(const QGeoMap & // 2) QList<QList<QDoubleVector2D> > clippedPaths; - const QList<QDoubleVector2D> &visibleRegion = map.geoProjection().projectableRegion(); + const QList<QDoubleVector2D> &visibleRegion = p.projectableGeometry(); if (visibleRegion.size()) { c2t::clip2tri clipper; clipper.addSubjectPath(QClipperUtils::qListToPath(wrappedPath), false); @@ -265,18 +265,19 @@ void QGeoMapPolylineGeometry::pathToScreen(const QGeoMap &map, const QList<QList<QDoubleVector2D> > &clippedPaths, const QDoubleVector2D &leftBoundWrapped) { + const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(map.geoProjection()); // 3) project the resulting geometry to screen position and calculate screen bounds double minX = qInf(); double minY = qInf(); double maxX = -qInf(); double maxY = -qInf(); - srcOrigin_ = map.geoProjection().mapProjectionToGeo(map.geoProjection().unwrapMapProjection(leftBoundWrapped)); - QDoubleVector2D origin = map.geoProjection().wrappedMapProjectionToItemPosition(leftBoundWrapped); + srcOrigin_ = p.mapProjectionToGeo(p.unwrapMapProjection(leftBoundWrapped)); + QDoubleVector2D origin = p.wrappedMapProjectionToItemPosition(leftBoundWrapped); for (const QList<QDoubleVector2D> &path: clippedPaths) { QDoubleVector2D lastAddedPoint; for (int i = 0; i < path.size(); ++i) { - QDoubleVector2D point = map.geoProjection().wrappedMapProjectionToItemPosition(path.at(i)); + QDoubleVector2D point = p.wrappedMapProjectionToItemPosition(path.at(i)); point = point - origin; // (0,0) if point == geoLeftBound_ @@ -722,12 +723,13 @@ void QDeclarativePolylineMapItem::afterViewportChanged(const QGeoMapViewportChan */ void QDeclarativePolylineMapItem::regenerateCache() { - if (!map()) + if (!map() || map()->geoProjection().projectionType() != QGeoProjection::ProjectionWebMercator) return; + const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(map()->geoProjection()); geopathProjected_.clear(); geopathProjected_.reserve(geopath_.path().size()); for (const QGeoCoordinate &c : geopath_.path()) - geopathProjected_ << map()->geoProjection().geoToMapProjection(c); + geopathProjected_ << p.geoToMapProjection(c); } /*! @@ -735,9 +737,10 @@ void QDeclarativePolylineMapItem::regenerateCache() */ void QDeclarativePolylineMapItem::updateCache() { - if (!map()) + if (!map() || map()->geoProjection().projectionType() != QGeoProjection::ProjectionWebMercator) return; - geopathProjected_ << map()->geoProjection().geoToMapProjection(geopath_.path().last()); + const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(map()->geoProjection()); + geopathProjected_ << p.geoToMapProjection(geopath_.path().last()); } /*! @@ -745,7 +748,8 @@ void QDeclarativePolylineMapItem::updateCache() */ void QDeclarativePolylineMapItem::updatePolish() { - if (!map() || geopath_.path().length() == 0) + if (!map() || geopath_.path().length() == 0 + || map()->geoProjection().projectionType() != QGeoProjection::ProjectionWebMercator) return; QScopedValueRollback<bool> rollback(updatingGeometry_); diff --git a/src/location/declarativemaps/qdeclarativerectanglemapitem.cpp b/src/location/declarativemaps/qdeclarativerectanglemapitem.cpp index 79750416..0206ac96 100644 --- a/src/location/declarativemaps/qdeclarativerectanglemapitem.cpp +++ b/src/location/declarativemaps/qdeclarativerectanglemapitem.cpp @@ -41,6 +41,7 @@ #include <qnumeric.h> #include <QRectF> #include <QPointF> +#include <QtPositioning/private/qwebmercator_p.h> #include <QtLocation/private/qgeomap_p.h> #include <QtPositioning/private/qdoublevector2d_p.h> #include <QtCore/QScopedValueRollback> @@ -272,9 +273,12 @@ QSGNode *QDeclarativeRectangleMapItem::updateMapItemPaintNode(QSGNode *oldNode, */ void QDeclarativeRectangleMapItem::updatePolish() { - if (!map() || !topLeft().isValid() || !bottomRight().isValid()) + if (!map() || !topLeft().isValid() || !bottomRight().isValid() + || map()->geoProjection().projectionType() != QGeoProjection::ProjectionWebMercator) return; + const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(map()->geoProjection()); + QScopedValueRollback<bool> rollback(updatingGeometry_); updatingGeometry_ = true; @@ -299,7 +303,7 @@ void QDeclarativeRectangleMapItem::updatePolish() QDoubleVector2D borderLeftBoundWrapped; QList<QList<QDoubleVector2D > > clippedPaths = borderGeometry_.clipPath(*map(), closedPath, borderLeftBoundWrapped); if (clippedPaths.size()) { - borderLeftBoundWrapped = map()->geoProjection().geoToWrappedMapProjection(geometryOrigin); + borderLeftBoundWrapped = p.geoToWrappedMapProjection(geometryOrigin); borderGeometry_.pathToScreen(*map(), clippedPaths, borderLeftBoundWrapped); borderGeometry_.updateScreenPoints(*map(), border_.width()); @@ -355,11 +359,11 @@ void QDeclarativeRectangleMapItem::updatePath() if (!map()) return; pathMercator_.clear(); - pathMercator_ << map()->geoProjection().geoToMapProjection(rectangle_.topLeft()); - pathMercator_ << map()->geoProjection().geoToMapProjection( + pathMercator_ << QWebMercator::coordToMercator(rectangle_.topLeft()); + pathMercator_ << QWebMercator::coordToMercator( QGeoCoordinate(rectangle_.topLeft().latitude(), rectangle_.bottomRight().longitude())); - pathMercator_ << map()->geoProjection().geoToMapProjection(rectangle_.bottomRight()); - pathMercator_ << map()->geoProjection().geoToMapProjection( + pathMercator_ << QWebMercator::coordToMercator(rectangle_.bottomRight()); + pathMercator_ << QWebMercator::coordToMercator( QGeoCoordinate(rectangle_.bottomRight().latitude(), rectangle_.topLeft().longitude())); } diff --git a/src/location/declarativemaps/qquickgeomapgesturearea.cpp b/src/location/declarativemaps/qquickgeomapgesturearea.cpp index 2f095ee0..1703bcfa 100644 --- a/src/location/declarativemaps/qquickgeomapgesturearea.cpp +++ b/src/location/declarativemaps/qquickgeomapgesturearea.cpp @@ -969,7 +969,7 @@ void QQuickGeoMapGestureArea::handleWheelEvent(QWheelEvent *event) return; } - const QGeoCoordinate &wheelGeoPos = m_map->geoProjection().itemPositionToCoordinate(QDoubleVector2D(event->posF()), false); + const QGeoCoordinate &wheelGeoPos = m_declarativeMap->toCoordinate(event->posF(), false); const QPointF &preZoomPoint = event->posF(); // Not using AltModifier as, for some reason, it causes angleDelta to be 0 @@ -977,9 +977,7 @@ void QQuickGeoMapGestureArea::handleWheelEvent(QWheelEvent *event) emit rotationStarted(&m_pinch.m_event); // First set bearing const double bearingDelta = event->angleDelta().y() * qreal(0.05); - m_declarativeMap->setBearing(m_declarativeMap->bearing() + bearingDelta); - // then reanchor - m_declarativeMap->setCenter(m_map->geoProjection().anchorCoordinateToPoint(wheelGeoPos, preZoomPoint)); + m_declarativeMap->setBearing(m_declarativeMap->bearing() + bearingDelta, wheelGeoPos); emit rotationUpdated(&m_pinch.m_event); emit rotationFinished(&m_pinch.m_event); } else if (event->modifiers() & Qt::ControlModifier && tiltEnabled()) { @@ -993,10 +991,10 @@ void QQuickGeoMapGestureArea::handleWheelEvent(QWheelEvent *event) // Gesture area should always honor maxZL, but Map might not. m_declarativeMap->setZoomLevel(qMin<qreal>(m_declarativeMap->zoomLevel() + zoomLevelDelta, maximumZoomLevel()), false); - const QPointF &postZoomPoint = m_map->geoProjection().coordinateToItemPosition(wheelGeoPos, false).toPointF(); + const QPointF &postZoomPoint = m_declarativeMap->fromCoordinate(wheelGeoPos, false); if (preZoomPoint != postZoomPoint) // need to re-anchor the wheel geoPos to the event position - m_declarativeMap->setCenter(m_map->geoProjection().anchorCoordinateToPoint(wheelGeoPos, preZoomPoint)); + m_declarativeMap->alignCoordinateToPoint(wheelGeoPos, preZoomPoint); } event->accept(); } @@ -1134,7 +1132,7 @@ void QQuickGeoMapGestureArea::touchPointStateMachine() if (m_allPoints.count() == 0) { setTouchPointState(touchPoints0); } else if (m_allPoints.count() == 2) { - m_touchCenterCoord = m_map->geoProjection().itemPositionToCoordinate(QDoubleVector2D(m_touchPointsCentroid), false); + m_touchCenterCoord = m_declarativeMap->toCoordinate(m_touchPointsCentroid, false); startTwoTouchPoints(); setTouchPointState(touchPoints2); } @@ -1143,7 +1141,7 @@ void QQuickGeoMapGestureArea::touchPointStateMachine() if (m_allPoints.count() == 0) { setTouchPointState(touchPoints0); } else if (m_allPoints.count() == 1) { - m_touchCenterCoord = m_map->geoProjection().itemPositionToCoordinate(QDoubleVector2D(m_touchPointsCentroid), false); + m_touchCenterCoord = m_declarativeMap->toCoordinate(m_touchPointsCentroid, false); startOneTouchPoint(); setTouchPointState(touchPoints1); } @@ -1171,7 +1169,7 @@ void QQuickGeoMapGestureArea::startOneTouchPoint() m_sceneStartPoint1 = mapFromScene(m_allPoints.at(0).scenePos()); m_lastPos = m_sceneStartPoint1; m_lastPosTime.start(); - QGeoCoordinate startCoord = m_map->geoProjection().itemPositionToCoordinate(QDoubleVector2D(m_sceneStartPoint1), false); + QGeoCoordinate startCoord = m_declarativeMap->toCoordinate(m_sceneStartPoint1, false); // ensures a smooth transition for panning m_startCoord.setLongitude(m_startCoord.longitude() + startCoord.longitude() - m_touchCenterCoord.longitude()); @@ -1198,7 +1196,7 @@ void QQuickGeoMapGestureArea::startTwoTouchPoints() QPointF startPos = (m_sceneStartPoint1 + m_sceneStartPoint2) * 0.5; m_lastPos = startPos; m_lastPosTime.start(); - QGeoCoordinate startCoord = m_map->geoProjection().itemPositionToCoordinate(QDoubleVector2D(startPos), false); + QGeoCoordinate startCoord = m_declarativeMap->toCoordinate(startPos, false); m_startCoord.setLongitude(m_startCoord.longitude() + startCoord.longitude() - m_touchCenterCoord.longitude()); m_startCoord.setLatitude(m_startCoord.latitude() + startCoord.latitude() - @@ -1668,7 +1666,7 @@ void QQuickGeoMapGestureArea::panStateMachine() case flickInactive: if (!isTiltActive() && canStartPan()) { // Update startCoord_ to ensure smooth start for panning when going over startDragDistance - QGeoCoordinate newStartCoord = m_map->geoProjection().itemPositionToCoordinate(QDoubleVector2D(m_touchPointsCentroid), false); + QGeoCoordinate newStartCoord = m_declarativeMap->toCoordinate(m_touchPointsCentroid, false); m_startCoord.setLongitude(newStartCoord.longitude()); m_startCoord.setLatitude(newStartCoord.latitude()); m_declarativeMap->setKeepMouseGrab(true); @@ -1743,8 +1741,7 @@ bool QQuickGeoMapGestureArea::canStartPan() */ void QQuickGeoMapGestureArea::updatePan() { - QGeoCoordinate animationStartCoordinate = m_map->geoProjection().anchorCoordinateToPoint(m_startCoord, m_touchPointsCentroid); - m_declarativeMap->setCenter(animationStartCoordinate); + m_declarativeMap->alignCoordinateToPoint(m_startCoord, m_touchPointsCentroid); } /*! diff --git a/src/location/maps/qgeomap.cpp b/src/location/maps/qgeomap.cpp index 529ebf82..4ac36fed 100644 --- a/src/location/maps/qgeomap.cpp +++ b/src/location/maps/qgeomap.cpp @@ -91,7 +91,7 @@ void QGeoMap::setCameraData(const QGeoCameraData &cameraData) if (cameraData == d->m_cameraData) return; d->m_cameraData = cameraData; - d->m_geoProjection->setCameraData(cameraData); + d->m_geoProjection->setCameraData(cameraData, false); d->changeCameraData(cameraData); emit cameraDataChanged(d->m_cameraData); } @@ -108,6 +108,40 @@ bool QGeoMap::handleEvent(QEvent *event) return false; } +bool QGeoMap::setBearing(qreal bearing, const QGeoCoordinate &coordinate) +{ + Q_D(QGeoMap); + bool res = d->m_geoProjection->setBearing(bearing, coordinate); + if (!res) + return false; + + setCameraData(geoProjection().cameraData()); + return true; +} + +bool QGeoMap::anchorCoordinateToPoint(const QGeoCoordinate &coordinate, const QPointF &anchorPoint) +{ + QGeoCoordinate newCenter = geoProjection().anchorCoordinateToPoint(coordinate, anchorPoint); + QGeoCameraData data = cameraData(); + if (data.center() != newCenter) { + data.setCenter(newCenter); + setCameraData(data); + return true; + } + return false; +} + +bool QGeoMap::fitViewportToGeoRectangle(const QGeoRectangle &rectangle) +{ + Q_UNUSED(rectangle) + return false; +} + +QGeoShape QGeoMap::visibleRegion() const +{ + return geoProjection().visibleRegion(); +} + QGeoCameraData QGeoMap::cameraData() const { Q_D(const QGeoMap); @@ -146,13 +180,13 @@ double QGeoMap::maximumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) co double QGeoMap::mapWidth() const { Q_D(const QGeoMap); - return d->m_geoProjection->mapWidth(); + return d->mapWidth(); } double QGeoMap::mapHeight() const { Q_D(const QGeoMap); - return d->m_geoProjection->mapHeight(); + return d->mapHeight(); } const QGeoProjection &QGeoMap::geoProjection() const @@ -167,6 +201,11 @@ QGeoCameraCapabilities QGeoMap::cameraCapabilities() const return d->m_cameraCapabilities; } +QGeoMap::Capabilities QGeoMap::capabilities() const +{ + return Capabilities(QGeoMap::SupportsNothing); +} + void QGeoMap::prefetchData() { @@ -337,4 +376,18 @@ QList<QGeoMapObject *> QGeoMapPrivate::mapObjects() const return QList<QGeoMapObject *>(); } +double QGeoMapPrivate::mapWidth() const +{ + if (m_geoProjection->projectionType() == QGeoProjection::ProjectionWebMercator) + return static_cast<const QGeoProjectionWebMercator *>(m_geoProjection)->mapWidth(); + return 0; // override this for maps supporting other projections +} + +double QGeoMapPrivate::mapHeight() const +{ + if (m_geoProjection->projectionType() == QGeoProjection::ProjectionWebMercator) + return static_cast<const QGeoProjectionWebMercator *>(m_geoProjection)->mapHeight(); + return 0; // override this for maps supporting other projections +} + QT_END_NAMESPACE diff --git a/src/location/maps/qgeomap_p.h b/src/location/maps/qgeomap_p.h index 7c7825f2..b2382099 100644 --- a/src/location/maps/qgeomap_p.h +++ b/src/location/maps/qgeomap_p.h @@ -73,6 +73,8 @@ class Q_LOCATION_PRIVATE_EXPORT QGeoMap : public QObject Q_OBJECT Q_DECLARE_PRIVATE(QGeoMap) + Q_ENUMS(Capability) + Q_FLAGS(Capabilities) public: enum ItemType { NoItem = 0x0000, @@ -86,6 +88,16 @@ public: Q_DECLARE_FLAGS(ItemTypes, ItemType) + enum Capability { + SupportsNothing = 0x0000, + SupportsVisibleRegion = 0x0001, + SupportsSetBearing = 0x0002, + SupportsAnchoringCoordinate = 0x0004, + SupportsFittingViewportToGeoRectangle = 0x0008 + }; + + Q_DECLARE_FLAGS(Capabilities, Capability) + virtual ~QGeoMap(); // Sets the display size @@ -97,6 +109,7 @@ public: QGeoCameraData cameraData() const; QGeoCameraCapabilities cameraCapabilities() const; + virtual Capabilities capabilities() const; void setActiveMapType(const QGeoMapType mapType); const QGeoMapType activeMapType() const; @@ -132,6 +145,11 @@ public: virtual void setAcceptedGestures(bool pan, bool flick, bool pinch, bool rotate, bool tilt); virtual bool handleEvent(QEvent *event); + virtual bool setBearing(qreal bearing, const QGeoCoordinate &coordinate); + virtual QGeoShape visibleRegion() const; + virtual bool anchorCoordinateToPoint(const QGeoCoordinate &coordinate, const QPointF &anchorPoint); + virtual bool fitViewportToGeoRectangle(const QGeoRectangle &rectangle); + protected: QGeoMap(QGeoMapPrivate &dd, QObject *parent = 0); void setCameraData(const QGeoCameraData &cameraData); diff --git a/src/location/maps/qgeomap_p_p.h b/src/location/maps/qgeomap_p_p.h index 80fc70d2..d6ab40b6 100644 --- a/src/location/maps/qgeomap_p_p.h +++ b/src/location/maps/qgeomap_p_p.h @@ -96,6 +96,9 @@ protected: virtual void changeCameraData(const QGeoCameraData &oldCameraData) = 0; // called by QGeoMap::setCameraData() virtual void changeActiveMapType(const QGeoMapType mapType) = 0; // called by QGeoMap::setActiveMapType() + virtual double mapWidth() const; + virtual double mapHeight() const; + protected: QSize m_viewportSize; QGeoProjection *m_geoProjection; diff --git a/src/location/maps/qgeoprojection.cpp b/src/location/maps/qgeoprojection.cpp index 1df174fb..1ab9970b 100644 --- a/src/location/maps/qgeoprojection.cpp +++ b/src/location/maps/qgeoprojection.cpp @@ -38,6 +38,7 @@ #include <QtPositioning/private/qwebmercator_p.h> #include <QtPositioning/private/qlocationutils_p.h> #include <QtPositioning/private/qclipperutils_p.h> +#include <QtPositioning/QGeoPolygon> #include <QSize> #include <QtGui/QMatrix4x4> #include <cmath> @@ -75,6 +76,30 @@ QGeoProjection::~QGeoProjection() QGeoCoordinate QGeoProjection::anchorCoordinateToPoint(const QGeoCoordinate &coordinate, const QPointF &anchorPoint) const { + Q_UNUSED(coordinate) + Q_UNUSED(anchorPoint) + return QGeoCoordinate(); +} + +QGeoShape QGeoProjection::visibleRegion() const +{ + return QGeoShape(); +} + +bool QGeoProjection::setBearing(qreal bearing, const QGeoCoordinate &coordinate) +{ + Q_UNUSED(bearing) + Q_UNUSED(coordinate) + return false; +} + + +/* + * QGeoProjectionWebMercator implementation +*/ + +QGeoCoordinate QGeoProjectionWebMercator::anchorCoordinateToPoint(const QGeoCoordinate &coordinate, const QPointF &anchorPoint) const +{ // Approach: find the displacement in (wrapped) mercator space, and apply that to the center QDoubleVector2D centerProj = geoToWrappedMapProjection(cameraData().center()); QDoubleVector2D coordProj = geoToWrappedMapProjection(coordinate); @@ -84,9 +109,25 @@ QGeoCoordinate QGeoProjection::anchorCoordinateToPoint(const QGeoCoordinate &coo return wrappedMapProjectionToGeo(centerProj + coordProj - anchorProj); } -/* - * QGeoProjectionWebMercator implementation -*/ +bool QGeoProjectionWebMercator::setBearing(qreal bearing, const QGeoCoordinate &coordinate) +{ + const QDoubleVector2D coordWrapped = geoToWrappedMapProjection(coordinate); + if (!isProjectable(coordWrapped)) + return false; + const QPointF rotationPoint = wrappedMapProjectionToItemPosition(coordWrapped).toPointF(); + + QGeoCameraData camera = cameraData(); + // first set bearing + camera.setBearing(bearing); + setCameraData(camera); + camera = cameraData(); + + // then reanchor + const QGeoCoordinate center = anchorCoordinateToPoint(coordinate, rotationPoint); + camera.setCenter(center); + setCameraData(camera); + return true; +} QGeoProjectionWebMercator::QGeoProjectionWebMercator() : QGeoProjection(), @@ -154,6 +195,9 @@ double QGeoProjectionWebMercator::mapHeight() const void QGeoProjectionWebMercator::setViewportSize(const QSize &size) { + if (int(m_viewportWidth) == size.width() && int(m_viewportHeight) == size.height()) + return; + m_viewportWidth = size.width(); m_viewportHeight = size.height(); m_1_viewportWidth = 1.0 / m_viewportWidth; @@ -162,8 +206,11 @@ void QGeoProjectionWebMercator::setViewportSize(const QSize &size) setupCamera(); } -void QGeoProjectionWebMercator::setCameraData(const QGeoCameraData &cameraData) +void QGeoProjectionWebMercator::setCameraData(const QGeoCameraData &cameraData, bool force) { + if (m_cameraData == cameraData && !force) + return; + m_cameraData = cameraData; m_mapEdgeSize = std::pow(2.0, cameraData.zoomLevel()) * defaultTileSize; setupCamera(); @@ -331,20 +378,41 @@ bool QGeoProjectionWebMercator::isProjectable(const QDoubleVector2D &wrappedProj return true; } -QList<QDoubleVector2D> QGeoProjectionWebMercator::visibleRegion() const +QList<QDoubleVector2D> QGeoProjectionWebMercator::visibleGeometry() const { if (m_visibleRegionDirty) const_cast<QGeoProjectionWebMercator *>(this)->updateVisibleRegion(); return m_visibleRegion; } -QList<QDoubleVector2D> QGeoProjectionWebMercator::projectableRegion() const +QList<QDoubleVector2D> QGeoProjectionWebMercator::projectableGeometry() const { if (m_visibleRegionDirty) const_cast<QGeoProjectionWebMercator *>(this)->updateVisibleRegion(); return m_projectableRegion; } +QGeoShape QGeoProjectionWebMercator::visibleRegion() const +{ + const QList<QDoubleVector2D> &visibleRegion = visibleGeometry(); + QGeoPolygon poly; + for (int i = 0; i < visibleRegion.size(); ++i) { + const QDoubleVector2D &c = visibleRegion.at(i); + // If a segment spans more than half of the map longitudinally, split in 2. + if (i && qAbs(visibleRegion.at(i-1).x() - c.x()) >= 0.5) { // This assumes a segment is never >= 1.0 (whole map span) + QDoubleVector2D extraPoint = (visibleRegion.at(i-1) + c) * 0.5; + poly.addCoordinate(wrappedMapProjectionToGeo(extraPoint)); + } + poly.addCoordinate(wrappedMapProjectionToGeo(c)); + } + if (visibleRegion.size() >= 2 && qAbs(visibleRegion.last().x() - visibleRegion.first().x()) >= 0.5) { + QDoubleVector2D extraPoint = (visibleRegion.last() + visibleRegion.first()) * 0.5; + poly.addCoordinate(wrappedMapProjectionToGeo(extraPoint)); + } + + return poly; +} + QDoubleVector2D QGeoProjectionWebMercator::viewportToWrappedMapProjection(const QDoubleVector2D &itemPosition) const { double s; @@ -369,6 +437,21 @@ QDoubleVector2D QGeoProjectionWebMercator::viewportToWrappedMapProjection(const return (xyPlane.lineIntersection(m_eye, ray, s) / m_sideLength).toVector2D(); } +QGeoProjection::ProjectionGroup QGeoProjectionWebMercator::projectionGroup() const +{ + return QGeoProjection::ProjectionCylindrical; +} + +QGeoProjection::Datum QGeoProjectionWebMercator::datum() const +{ + return QGeoProjection::DatumWGS84; +} + +QGeoProjection::ProjectionType QGeoProjectionWebMercator::projectionType() const +{ + return QGeoProjection::ProjectionWebMercator; +} + void QGeoProjectionWebMercator::setupCamera() { m_centerMercator = geoToMapProjection(m_cameraData.center()); diff --git a/src/location/maps/qgeoprojection_p.h b/src/location/maps/qgeoprojection_p.h index ca81df3a..dc05d4d1 100644 --- a/src/location/maps/qgeoprojection_p.h +++ b/src/location/maps/qgeoprojection_p.h @@ -51,53 +51,60 @@ #include <QtLocation/private/qlocationglobal_p.h> #include <QtLocation/private/qgeocameradata_p.h> #include <QtPositioning/private/qdoublematrix4x4_p.h> +#include <QtPositioning/QGeoShape> QT_BEGIN_NAMESPACE class Q_LOCATION_PRIVATE_EXPORT QGeoProjection { public: + enum ProjectionGroup { + ProjectionOther, + ProjectionCylindrical, + ProjectionPseudocylindrical, + ProjectionAzimuthal, + ProjectionPseudoazimuthal, + ProjectionConic, + ProjectionPseudoconic + //Polyhedral + //Retroazimuthal + }; + + enum Datum { + DatumUnknown, + DatumWGS84, + DatumSphere + }; + + enum ProjectionType { + ProjectionUnknown, + ProjectionGeneralPerspective, + ProjectionWebMercator + }; + QGeoProjection(); virtual ~QGeoProjection(); virtual void setViewportSize(const QSize &size) = 0; - virtual void setCameraData(const QGeoCameraData &cameraData) = 0; + virtual void setCameraData(const QGeoCameraData &cameraData, bool force = true) = 0; + virtual QGeoCameraData cameraData() const = 0; // returns the minimum zoom at the current viewport size virtual double minimumZoom() 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; - virtual double mapHeight() const = 0; - - virtual bool isProjectable(const QDoubleVector2D &wrappedProjection) const = 0; - virtual QList<QDoubleVector2D> visibleRegion() const = 0; - virtual QList<QDoubleVector2D> projectableRegion() const = 0; - - // Conversion methods for QGeoCoordinate <-> screen. - // This currently assumes that the "MapProjection" space is [0, 1][0, 1] for every type of possibly supported map projection - virtual QDoubleVector2D geoToMapProjection(const QGeoCoordinate &coordinate) const = 0; - virtual QGeoCoordinate mapProjectionToGeo(const QDoubleVector2D &projection) const = 0; - - virtual QDoubleVector2D wrapMapProjection(const QDoubleVector2D &projection) const = 0; - virtual QDoubleVector2D unwrapMapProjection(const QDoubleVector2D &wrappedProjection) const = 0; - - virtual QDoubleVector2D wrappedMapProjectionToItemPosition(const QDoubleVector2D &wrappedProjection) const = 0; - virtual QDoubleVector2D itemPositionToWrappedMapProjection(const QDoubleVector2D &itemPosition) const = 0; - - // Convenience methods to avoid the chain itemPositionToWrappedProjection(wrapProjection(geoToProjection())) virtual QGeoCoordinate itemPositionToCoordinate(const QDoubleVector2D &pos, bool clipToViewport = true) const = 0; virtual QDoubleVector2D coordinateToItemPosition(const QGeoCoordinate &coordinate, bool clipToViewport = true) const = 0; - virtual QDoubleVector2D geoToWrappedMapProjection(const QGeoCoordinate &coordinate) const = 0; - virtual QGeoCoordinate wrappedMapProjectionToGeo(const QDoubleVector2D &wrappedProjection) const = 0; - virtual QMatrix4x4 quickItemTransformation(const QGeoCoordinate &coordinate, const QPointF &anchorPoint, qreal zoomLevel) const = 0; + + virtual ProjectionGroup projectionGroup() const = 0; + virtual Datum datum() const = 0; + virtual ProjectionType projectionType() const = 0; // Returns the new map center after anchoring coordinate to anchorPoint on the screen - QGeoCoordinate anchorCoordinateToPoint(const QGeoCoordinate &coordinate, const QPointF &anchorPoint) const; + virtual QGeoCoordinate anchorCoordinateToPoint(const QGeoCoordinate &coordinate, const QPointF &anchorPoint) const; -private: - virtual QGeoCameraData cameraData() const = 0; + virtual QGeoShape visibleRegion() const; + virtual bool setBearing(qreal bearing, const QGeoCoordinate &coordinate); }; class Q_LOCATION_PRIVATE_EXPORT QGeoProjectionWebMercator : public QGeoProjection @@ -106,40 +113,53 @@ public: QGeoProjectionWebMercator(); ~QGeoProjectionWebMercator(); - double minimumZoom() const Q_DECL_OVERRIDE; - double maximumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) const Q_DECL_OVERRIDE; + // From QGeoProjection + double minimumZoom() const override; + double maximumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) const override; + + void setViewportSize(const QSize &size) override; + void setCameraData(const QGeoCameraData &cameraData, bool force = true) override; + QGeoCameraData cameraData() const override; - // The size of the underlying map, at the current zoom level. - double mapWidth() const Q_DECL_OVERRIDE; - double mapHeight() const Q_DECL_OVERRIDE; + QGeoCoordinate itemPositionToCoordinate(const QDoubleVector2D &pos, bool clipToViewport = true) const override; + QDoubleVector2D coordinateToItemPosition(const QGeoCoordinate &coordinate, bool clipToViewport = true) const override; - void setViewportSize(const QSize &size) Q_DECL_OVERRIDE; - void setCameraData(const QGeoCameraData &cameraData) Q_DECL_OVERRIDE; + QGeoProjection::ProjectionGroup projectionGroup() const override; + QGeoProjection::Datum datum() const override; + QGeoProjection::ProjectionType projectionType() const override; - QDoubleVector2D geoToMapProjection(const QGeoCoordinate &coordinate) const Q_DECL_OVERRIDE; - QGeoCoordinate mapProjectionToGeo(const QDoubleVector2D &projection) const Q_DECL_OVERRIDE; + QGeoCoordinate anchorCoordinateToPoint(const QGeoCoordinate &coordinate, const QPointF &anchorPoint) const override; + bool setBearing(qreal bearing, const QGeoCoordinate &coordinate) override; - QDoubleVector2D wrapMapProjection(const QDoubleVector2D &projection) const Q_DECL_OVERRIDE; - QDoubleVector2D unwrapMapProjection(const QDoubleVector2D &wrappedProjection) const Q_DECL_OVERRIDE; + QGeoShape visibleRegion() const override; - QDoubleVector2D wrappedMapProjectionToItemPosition(const QDoubleVector2D &wrappedProjection) const Q_DECL_OVERRIDE; - QDoubleVector2D itemPositionToWrappedMapProjection(const QDoubleVector2D &itemPosition) const Q_DECL_OVERRIDE; + // Specific to QGeoProjectionWebMercator + double mapWidth() const; // The size of the underlying map, at the current zoom level. + double mapHeight() const; - QGeoCoordinate itemPositionToCoordinate(const QDoubleVector2D &pos, bool clipToViewport = true) const Q_DECL_OVERRIDE; - QDoubleVector2D coordinateToItemPosition(const QGeoCoordinate &coordinate, bool clipToViewport = true) const Q_DECL_OVERRIDE; - QDoubleVector2D geoToWrappedMapProjection(const QGeoCoordinate &coordinate) const Q_DECL_OVERRIDE; - QGeoCoordinate wrappedMapProjectionToGeo(const QDoubleVector2D &wrappedProjection) const Q_DECL_OVERRIDE; - QMatrix4x4 quickItemTransformation(const QGeoCoordinate &coordinate, const QPointF &anchorPoint, qreal zoomLevel) const Q_DECL_OVERRIDE; + QDoubleVector2D geoToMapProjection(const QGeoCoordinate &coordinate) const; + QGeoCoordinate mapProjectionToGeo(const QDoubleVector2D &projection) const; + + QDoubleVector2D wrapMapProjection(const QDoubleVector2D &projection) const; + QDoubleVector2D unwrapMapProjection(const QDoubleVector2D &wrappedProjection) const; + + QDoubleVector2D wrappedMapProjectionToItemPosition(const QDoubleVector2D &wrappedProjection) const; + QDoubleVector2D itemPositionToWrappedMapProjection(const QDoubleVector2D &itemPosition) const; + + QDoubleVector2D geoToWrappedMapProjection(const QGeoCoordinate &coordinate) const; + QGeoCoordinate wrappedMapProjectionToGeo(const QDoubleVector2D &wrappedProjection) const; + QMatrix4x4 quickItemTransformation(const QGeoCoordinate &coordinate, const QPointF &anchorPoint, qreal zoomLevel) const; + + bool isProjectable(const QDoubleVector2D &wrappedProjection) const; + QList<QDoubleVector2D> visibleGeometry() const; + QList<QDoubleVector2D> projectableGeometry() const; - bool isProjectable(const QDoubleVector2D &wrappedProjection) const Q_DECL_OVERRIDE; - QList<QDoubleVector2D> visibleRegion() const Q_DECL_OVERRIDE; - QList<QDoubleVector2D> projectableRegion() const Q_DECL_OVERRIDE; inline QDoubleVector2D viewportToWrappedMapProjection(const QDoubleVector2D &itemPosition) const; inline QDoubleVector2D viewportToWrappedMapProjection(const QDoubleVector2D &itemPosition, double &s) const; + private: void setupCamera(); void updateVisibleRegion(); - QGeoCameraData cameraData() const Q_DECL_OVERRIDE; public: struct Line2D diff --git a/src/location/maps/qgeotiledmap.cpp b/src/location/maps/qgeotiledmap.cpp index 0eeb189d..81eb3b14 100644 --- a/src/location/maps/qgeotiledmap.cpp +++ b/src/location/maps/qgeotiledmap.cpp @@ -143,6 +143,13 @@ void QGeoTiledMap::clearData() d->m_mapScene->clearTexturedTiles(); } +QGeoMap::Capabilities QGeoTiledMap::capabilities() const +{ + return Capabilities(SupportsVisibleRegion + | SupportsSetBearing + | SupportsAnchoringCoordinate); +} + void QGeoTiledMap::clearScene(int mapId) { Q_D(QGeoTiledMap); diff --git a/src/location/maps/qgeotiledmap_p.h b/src/location/maps/qgeotiledmap_p.h index b709cb57..6152d60d 100644 --- a/src/location/maps/qgeotiledmap_p.h +++ b/src/location/maps/qgeotiledmap_p.h @@ -86,6 +86,7 @@ public: void prefetchData() Q_DECL_OVERRIDE; void clearData() Q_DECL_OVERRIDE; + Capabilities capabilities() const override; public Q_SLOTS: virtual void clearScene(int mapId); diff --git a/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.cpp b/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.cpp index dd5c9a86..c04aa5e3 100644 --- a/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.cpp +++ b/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.cpp @@ -372,6 +372,13 @@ void QGeoMapMapboxGL::setMapItemsBefore(const QString &before) d->m_mapItemsBefore = before; } +QGeoMap::Capabilities QGeoMapMapboxGL::capabilities() const +{ + return Capabilities(SupportsVisibleRegion + | SupportsSetBearing + | SupportsAnchoringCoordinate); +} + QSGNode *QGeoMapMapboxGL::updateSceneGraph(QSGNode *oldNode, QQuickWindow *window) { Q_D(QGeoMapMapboxGL); diff --git a/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.h b/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.h index 73cfd75a..df76fcab 100644 --- a/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.h +++ b/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.h @@ -57,6 +57,7 @@ public: void setMapboxGLSettings(const QMapboxGLSettings &); void setUseFBO(bool); void setMapItemsBefore(const QString &); + Capabilities capabilities() const override; private Q_SLOTS: // QMapboxGL diff --git a/src/plugins/geoservices/mapboxgl/qmapboxglstylechange.cpp b/src/plugins/geoservices/mapboxgl/qmapboxglstylechange.cpp index f39bfae3..4835c201 100644 --- a/src/plugins/geoservices/mapboxgl/qmapboxglstylechange.cpp +++ b/src/plugins/geoservices/mapboxgl/qmapboxglstylechange.cpp @@ -89,18 +89,18 @@ QMapbox::Feature featureFromMapRectangle(QDeclarativeRectangleMapItem *mapItem) QMapbox::Feature featureFromMapCircle(QDeclarativeCircleMapItem *mapItem) { static const int circleSamples = 128; - + const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(mapItem->map()->geoProjection()); QList<QGeoCoordinate> path; QGeoCoordinate leftBound; QDeclarativeCircleMapItem::calculatePeripheralPoints(path, mapItem->center(), mapItem->radius(), circleSamples, leftBound); QList<QDoubleVector2D> pathProjected; for (const QGeoCoordinate &c : qAsConst(path)) - pathProjected << mapItem->map()->geoProjection().geoToMapProjection(c); + pathProjected << p.geoToMapProjection(c); if (QDeclarativeCircleMapItem::crossEarthPole(mapItem->center(), mapItem->radius())) mapItem->preserveCircleGeometry(pathProjected, mapItem->center(), mapItem->radius()); path.clear(); for (const QDoubleVector2D &c : qAsConst(pathProjected)) - path << mapItem->map()->geoProjection().mapProjectionToGeo(c); + path << p.mapProjectionToGeo(c); QMapbox::Coordinates coordinates; |