summaryrefslogtreecommitdiffstats
path: root/src/location/maps/qgeoprojection.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/location/maps/qgeoprojection.cpp')
-rw-r--r--src/location/maps/qgeoprojection.cpp50
1 files changed, 50 insertions, 0 deletions
diff --git a/src/location/maps/qgeoprojection.cpp b/src/location/maps/qgeoprojection.cpp
index 8cb7a748..cd7e5114 100644
--- a/src/location/maps/qgeoprojection.cpp
+++ b/src/location/maps/qgeoprojection.cpp
@@ -53,6 +53,14 @@ namespace {
QDoubleVector2D(-1.0,1.0) };
}
+static QMatrix4x4 toMatrix4x4(const QDoubleMatrix4x4 &m)
+{
+ return QMatrix4x4(m(0,0), m(0,1), m(0,2), m(0,3),
+ m(1,0), m(1,1), m(1,2), m(1,3),
+ m(2,0), m(2,1), m(2,2), m(2,3),
+ m(3,0), m(3,1), m(3,2), m(3,3));
+}
+
QT_BEGIN_NAMESPACE
QGeoProjection::QGeoProjection()
@@ -244,6 +252,44 @@ QGeoCoordinate QGeoProjectionWebMercator::wrappedMapProjectionToGeo(const QDoubl
return mapProjectionToGeo(unwrapMapProjection(wrappedProjection));
}
+QMatrix4x4 QGeoProjectionWebMercator::quickItemTransformation(const QGeoCoordinate &coordinate, const QPointF &anchorPoint, double zoomLevel) const
+{
+ const QDoubleVector2D coordWrapped = geoToWrappedMapProjection(coordinate);
+ double scale = std::pow(0.5, zoomLevel - m_cameraData.zoomLevel());
+ const QDoubleVector2D anchorScaled = QDoubleVector2D(anchorPoint.x(), anchorPoint.y()) * scale;
+ const QDoubleVector2D anchorMercator = anchorScaled / mapWidth();
+
+ // Check for coord OOB, only coordinate is going to be projected to item position, so
+ // testing also coordAnchored might be superfluous
+ if (!isProjectable(coordWrapped))
+ return QMatrix4x4();
+
+ const QDoubleVector2D coordAnchored = coordWrapped - anchorMercator;
+ const QDoubleVector2D coordAnchoredScaled = coordAnchored * m_sideLength;
+ QDoubleMatrix4x4 matTranslateScale;
+ matTranslateScale.translate(coordAnchoredScaled.x(), coordAnchoredScaled.y(), 0.0);
+
+ scale = std::pow(0.5, (zoomLevel - std::floor(zoomLevel)) +
+ (std::floor(zoomLevel) - std::floor(m_cameraData.zoomLevel())));
+ matTranslateScale.scale(scale);
+
+ const QDoubleVector2D coordOnScreen = wrappedMapProjectionToItemPosition(coordWrapped);
+ QDoubleMatrix4x4 matTransformation;
+ matTransformation.translate(-coordOnScreen.x(), -coordOnScreen.y(), 0);
+ matTransformation *= m_quickItemTransformation;
+
+ /*
+ * The full transformation chain for quickItemTransformation() is:
+ * matScreenShift * m_quickItemTransformation * matTranslate * matScale
+ * where:
+ * matScreenShift = translate(-coordOnScreen.x(), -coordOnScreen.y(), 0)
+ * matTranslate = translate(coordAnchoredScaled.x(), coordAnchoredScaled.y(), 0.0)
+ * matScale = scale(scale)
+ */
+
+ return toMatrix4x4(matTransformation * matTranslateScale);
+}
+
bool QGeoProjectionWebMercator::isProjectable(const QDoubleVector2D &wrappedProjection) const
{
if (m_cameraData.tilt() == 0.0)
@@ -264,6 +310,9 @@ QList<QDoubleVector2D> QGeoProjectionWebMercator::visibleRegion() const
return m_visibleRegion;
}
+/*
+ actual implementation of itemPositionToWrappedMapProjection
+*/
QDoubleVector2D QGeoProjectionWebMercator::viewportToWrappedMapProjection(const QDoubleVector2D &itemPosition) const
{
QDoubleVector2D pos = itemPosition;
@@ -395,6 +444,7 @@ void QGeoProjectionWebMercator::setupCamera()
matScreenTransformation(1,3) = 0.5 * m_viewportHeight;
m_transformation = matScreenTransformation * projectionMatrix * cameraMatrix;
+ m_quickItemTransformation = m_transformation;
m_transformation.scale(m_sideLength, m_sideLength, 1.0);
m_centerNearPlane = m_eye + m_viewNormalized;