summaryrefslogtreecommitdiff
path: root/src/location/maps
diff options
context:
space:
mode:
authorPaolo Angelelli <paolo.angelelli@qt.io>2017-08-10 11:37:56 +0200
committerPaolo Angelelli <paolo.angelelli@qt.io>2017-08-10 11:38:31 +0200
commit93e0c9cbca1a66b2fc6ec1d2b12e25b5e734aef0 (patch)
tree65479a233204bbdf790794192976a8b347c3406a /src/location/maps
parent677f7f76d4a0023d278b4d031d620fe63c3be27a (diff)
parentc832af789766fcebd8cfb15e53ce14f36278ca6d (diff)
downloadqtlocation-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.cpp6
-rw-r--r--src/location/maps/qgeoprojection.cpp114
-rw-r--r--src/location/maps/qgeoprojection_p.h7
-rw-r--r--src/location/maps/qgeoroute.cpp4
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());
}
/*!