diff options
author | Paolo Angelelli <paolo.angelelli@qt.io> | 2017-08-10 11:37:56 +0200 |
---|---|---|
committer | Paolo Angelelli <paolo.angelelli@qt.io> | 2017-08-10 11:38:31 +0200 |
commit | 93e0c9cbca1a66b2fc6ec1d2b12e25b5e734aef0 (patch) | |
tree | 65479a233204bbdf790794192976a8b347c3406a /src/location/maps | |
parent | 677f7f76d4a0023d278b4d031d620fe63c3be27a (diff) | |
parent | c832af789766fcebd8cfb15e53ce14f36278ca6d (diff) | |
download | qtlocation-93e0c9cbca1a66b2fc6ec1d2b12e25b5e734aef0.tar.gz |
Merge remote-tracking branch 'origin/5.9' into dev
Conflicts:
tests/auto/declarative_ui/tst_map.qml
Change-Id: If408b8242b39f78926b5373393f3b1f65b262499
Diffstat (limited to 'src/location/maps')
-rw-r--r-- | src/location/maps/qgeomappingmanager.cpp | 6 | ||||
-rw-r--r-- | src/location/maps/qgeoprojection.cpp | 114 | ||||
-rw-r--r-- | src/location/maps/qgeoprojection_p.h | 7 | ||||
-rw-r--r-- | src/location/maps/qgeoroute.cpp | 4 |
4 files changed, 107 insertions, 24 deletions
diff --git a/src/location/maps/qgeomappingmanager.cpp b/src/location/maps/qgeomappingmanager.cpp index cf040beb..d73050f7 100644 --- a/src/location/maps/qgeomappingmanager.cpp +++ b/src/location/maps/qgeomappingmanager.cpp @@ -133,10 +133,8 @@ int QGeoMappingManager::managerVersion() const */ QGeoMap *QGeoMappingManager::createMap(QObject *parent) { - QGeoMap * map = d_ptr->engine->createMap(); - if (map) - connect(parent, &QObject::destroyed,map, &QGeoMap::deleteLater); - return map; + Q_UNUSED(parent) + return d_ptr->engine->createMap(); } QList<QGeoMapType> QGeoMappingManager::supportedMapTypes() const diff --git a/src/location/maps/qgeoprojection.cpp b/src/location/maps/qgeoprojection.cpp index 7fefba27..218d806b 100644 --- a/src/location/maps/qgeoprojection.cpp +++ b/src/location/maps/qgeoprojection.cpp @@ -212,14 +212,25 @@ QDoubleVector2D QGeoProjectionWebMercator::wrappedMapProjectionToItemPosition(co QDoubleVector2D QGeoProjectionWebMercator::itemPositionToWrappedMapProjection(const QDoubleVector2D &itemPosition) const { QDoubleVector2D pos = itemPosition; - // when the camera is tilted, picking a point above the horizon returns a coordinate behind the camera - if (pos.y() < m_minimumUnprojectableY) - pos.setY(m_minimumUnprojectableY); pos *= QDoubleVector2D(m_1_viewportWidth, m_1_viewportHeight); pos *= 2.0; pos -= QDoubleVector2D(1.0,1.0); - return viewportToWrappedMapProjection(pos); + double s; + QDoubleVector2D res = viewportToWrappedMapProjection(pos, s); + + // a positive s means a point behind the camera. So do it again, after clamping Y. See QTBUG-61813 + if (s > 0.0) { + pos = itemPosition; + // when the camera is tilted, picking a point above the horizon returns a coordinate behind the camera + pos.setY(m_minimumUnprojectableY); + pos *= QDoubleVector2D(m_1_viewportWidth, m_1_viewportHeight); + pos *= 2.0; + pos -= QDoubleVector2D(1.0,1.0); + res = viewportToWrappedMapProjection(pos, s); + } + + return res; } /* Default implementations */ @@ -317,10 +328,23 @@ QList<QDoubleVector2D> QGeoProjectionWebMercator::visibleRegion() const return m_visibleRegion; } +QList<QDoubleVector2D> QGeoProjectionWebMercator::projectableRegion() const +{ + if (m_visibleRegionDirty) + const_cast<QGeoProjectionWebMercator *>(this)->updateVisibleRegion(); + return m_projectableRegion; +} + +QDoubleVector2D QGeoProjectionWebMercator::viewportToWrappedMapProjection(const QDoubleVector2D &itemPosition) const +{ + double s; + return viewportToWrappedMapProjection(itemPosition, s); +} + /* actual implementation of itemPositionToWrappedMapProjection */ -QDoubleVector2D QGeoProjectionWebMercator::viewportToWrappedMapProjection(const QDoubleVector2D &itemPosition) const +QDoubleVector2D QGeoProjectionWebMercator::viewportToWrappedMapProjection(const QDoubleVector2D &itemPosition, double &s) const { QDoubleVector2D pos = itemPosition; pos *= QDoubleVector2D(m_halfWidth, m_halfHeight); @@ -332,7 +356,7 @@ QDoubleVector2D QGeoProjectionWebMercator::viewportToWrappedMapProjection(const QDoubleVector3D ray = p - m_eye; ray.normalize(); - return (xyPlane.lineIntersection(m_eye, ray) / m_sideLength).toVector2D(); + return (xyPlane.lineIntersection(m_eye, ray, s) / m_sideLength).toVector2D(); } void QGeoProjectionWebMercator::setupCamera() @@ -344,6 +368,8 @@ void QGeoProjectionWebMercator::setupCamera() int intZoomLevel = static_cast<int>(std::floor(m_cameraData.zoomLevel())); m_sideLength = (1 << intZoomLevel) * defaultTileSize; m_center = m_centerMercator * m_sideLength; + //aperture(90 / 2) = 1 + m_aperture = tan(QLocationUtils::radians(m_cameraData.fieldOfView()) * 0.5); double f = m_viewportHeight; double z = std::pow(2.0, m_cameraData.zoomLevel() - intZoomLevel) * defaultTileSize; @@ -352,15 +378,13 @@ void QGeoProjectionWebMercator::setupCamera() double z_mercator = std::pow(2.0, m_cameraData.zoomLevel()) * defaultTileSize; double altitude_mercator = f / (2.0 * z_mercator); - //aperture(90 / 2) = 1 - m_aperture = tan(QLocationUtils::radians(m_cameraData.fieldOfView()) * 0.5); // calculate eye m_eye = m_center; m_eye.setZ(altitude * defaultTileSize / m_aperture); // And in mercator space m_eyeMercator = m_centerMercator; - m_eyeMercator.setZ(altitude_mercator); + m_eyeMercator.setZ(altitude_mercator / m_aperture); m_view = m_eye - m_center; QDoubleVector3D side = QDoubleVector3D::normal(m_view, QDoubleVector3D(0.0, 1.0, 0.0)); @@ -396,7 +420,7 @@ void QGeoProjectionWebMercator::setupCamera() m_eyeMercator = mTiltMercator * m_viewMercator + m_centerMercator; } - m_view = m_eye - m_center; + m_view = m_eye - m_center; // ToDo: this should be inverted (center - eye), and the rest should follow m_viewNormalized = m_view.normalized(); m_up = QDoubleVector3D::normal(m_view, m_side); @@ -449,7 +473,7 @@ void QGeoProjectionWebMercator::setupCamera() m_transformation.scale(m_sideLength, m_sideLength, 1.0); m_centerNearPlane = m_eye + m_viewNormalized; - m_centerNearPlaneMercator = m_eyeMercator + m_viewNormalized * m_nearPlaneMercator; + m_centerNearPlaneMercator = m_eyeMercator - m_viewNormalized * m_nearPlaneMercator; // The method does not support tilting angles >= 90.0 or < 0. @@ -478,11 +502,17 @@ void QGeoProjectionWebMercator::updateVisibleRegion() QDoubleVector2D bl = viewportToWrappedMapProjection(QDoubleVector2D(-1, 1 )); QDoubleVector2D br = viewportToWrappedMapProjection(QDoubleVector2D( 1, 1 )); + // 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()); + double mapRightLongitude = QLocationUtils::mapRightLongitude(m_cameraData.center().longitude()); + double leftX = geoToWrappedMapProjection(QGeoCoordinate(0, mapLeftLongitude)).x(); + double rightX = geoToWrappedMapProjection(QGeoCoordinate(0, mapRightLongitude)).x(); + QList<QDoubleVector2D> mapRect; - mapRect.push_back(QDoubleVector2D(-1.0, 1.0)); - mapRect.push_back(QDoubleVector2D( 2.0, 1.0)); - mapRect.push_back(QDoubleVector2D( 2.0, 0.0)); - mapRect.push_back(QDoubleVector2D(-1.0, 0.0)); + mapRect.push_back(QDoubleVector2D(leftX, 1.0)); + mapRect.push_back(QDoubleVector2D(rightX, 1.0)); + mapRect.push_back(QDoubleVector2D(rightX, 0.0)); + mapRect.push_back(QDoubleVector2D(leftX, 0.0)); QList<QDoubleVector2D> viewportRect; viewportRect.push_back(bl); @@ -499,6 +529,52 @@ void QGeoProjectionWebMercator::updateVisibleRegion() m_visibleRegion.clear(); if (res.size()) m_visibleRegion = QClipperUtils::pathToQList(res[0]); // Intersection between two convex quadrilaterals should always be a single polygon + + m_projectableRegion.clear(); + mapRect.clear(); + // The full map rectangle in extended mercator space + mapRect.push_back(QDoubleVector2D(-1.0, 1.0)); + mapRect.push_back(QDoubleVector2D( 2.0, 1.0)); + mapRect.push_back(QDoubleVector2D( 2.0, 0.0)); + mapRect.push_back(QDoubleVector2D(-1.0, 0.0)); + if (m_cameraData.tilt() == 0) { + m_projectableRegion = mapRect; + } else { + QGeoProjectionWebMercator::Plane nearPlane(m_centerNearPlaneMercator, m_viewNormalized); + Line2D nearPlaneXYIntersection = nearPlane.planeXYIntersection(); + double squareHalfSide = qMax(5.0, nearPlaneXYIntersection.m_point.length()); + QDoubleVector2D viewDirectionProjected = -m_viewNormalized.toVector2D().normalized(); + + + QDoubleVector2D tl = nearPlaneXYIntersection.m_point + - squareHalfSide * nearPlaneXYIntersection.m_direction + + 2 * squareHalfSide * viewDirectionProjected; + QDoubleVector2D tr = nearPlaneXYIntersection.m_point + + squareHalfSide * nearPlaneXYIntersection.m_direction + + 2 * squareHalfSide * viewDirectionProjected; + QDoubleVector2D bl = nearPlaneXYIntersection.m_point + - squareHalfSide * nearPlaneXYIntersection.m_direction; + QDoubleVector2D br = nearPlaneXYIntersection.m_point + + squareHalfSide * nearPlaneXYIntersection.m_direction; + + QList<QDoubleVector2D> projectableRect; + projectableRect.push_back(bl); + projectableRect.push_back(br); + projectableRect.push_back(tr); + projectableRect.push_back(tl); + + + c2t::clip2tri clipperProjectable; + clipperProjectable.clearClipper(); + clipperProjectable.addSubjectPath(QClipperUtils::qListToPath(mapRect), true); + clipperProjectable.addClipPolygon(QClipperUtils::qListToPath(projectableRect)); + + Paths resProjectable = clipperProjectable.execute(c2t::clip2tri::Intersection); + if (resProjectable.size()) + m_projectableRegion = QClipperUtils::pathToQList(resProjectable[0]); // Intersection between two convex quadrilaterals should always be a single polygon + else + m_projectableRegion = viewportRect; + } } QGeoCameraData QGeoProjectionWebMercator::cameraData() const @@ -544,9 +620,15 @@ QGeoProjectionWebMercator::Plane::Plane(const QDoubleVector3D &planePoint, const QDoubleVector3D QGeoProjectionWebMercator::Plane::lineIntersection(const QDoubleVector3D &linePoint, const QDoubleVector3D &lineDirection) const { + double s; + return lineIntersection(linePoint, lineDirection, s); +} + +QDoubleVector3D QGeoProjectionWebMercator::Plane::lineIntersection(const QDoubleVector3D &linePoint, const QDoubleVector3D &lineDirection, double &s) const +{ QDoubleVector3D w = linePoint - m_point; // s = -n.dot(w) / n.dot(u). p = p0 + su; u is lineDirection - double s = QDoubleVector3D::dotProduct(-m_normal, w) / QDoubleVector3D::dotProduct(m_normal, lineDirection); + s = QDoubleVector3D::dotProduct(-m_normal, w) / QDoubleVector3D::dotProduct(m_normal, lineDirection); return linePoint + lineDirection * s; } diff --git a/src/location/maps/qgeoprojection_p.h b/src/location/maps/qgeoprojection_p.h index d3be1177..ca81df3a 100644 --- a/src/location/maps/qgeoprojection_p.h +++ b/src/location/maps/qgeoprojection_p.h @@ -73,6 +73,7 @@ public: 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 @@ -132,9 +133,9 @@ public: 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(); @@ -158,6 +159,7 @@ public: Plane(const QDoubleVector3D &planePoint, const QDoubleVector3D &planeNormal); QDoubleVector3D lineIntersection(const QDoubleVector3D &linePoint, const QDoubleVector3D &lineDirection) const; + inline QDoubleVector3D lineIntersection(const QDoubleVector3D &linePoint, const QDoubleVector3D &lineDirection, double &s) const; Line2D planeXYIntersection() const; bool isValid() const; @@ -208,6 +210,7 @@ private: Line2D m_nearPlaneMapIntersection; QList<QDoubleVector2D> m_visibleRegion; + QList<QDoubleVector2D> m_projectableRegion; bool m_visibleRegionDirty; Q_DISABLE_COPY(QGeoProjectionWebMercator) diff --git a/src/location/maps/qgeoroute.cpp b/src/location/maps/qgeoroute.cpp index 52fa4a5e..facf1949 100644 --- a/src/location/maps/qgeoroute.cpp +++ b/src/location/maps/qgeoroute.cpp @@ -104,7 +104,7 @@ QGeoRoute &QGeoRoute::operator= (const QGeoRoute & other) */ bool QGeoRoute::operator ==(const QGeoRoute &other) const { - return (d_ptr.constData() == other.d_ptr.constData()); + return (*d_ptr.constData() == *other.d_ptr.constData()); } /*! @@ -112,7 +112,7 @@ bool QGeoRoute::operator ==(const QGeoRoute &other) const */ bool QGeoRoute::operator !=(const QGeoRoute &other) const { - return (d_ptr.constData() != other.d_ptr.constData()); + return !(*d_ptr.constData() == *other.d_ptr.constData()); } /*! |