diff options
author | Paolo Angelelli <paolo.angelelli@qt.io> | 2016-11-14 11:50:56 +0100 |
---|---|---|
committer | Paolo Angelelli <paolo.angelelli@qt.io> | 2016-12-07 09:50:54 +0000 |
commit | 9e71adaf31fe50e9966a6b09619968ae2b1176b6 (patch) | |
tree | 2c13e58f1d2c4f2a421a9852c1f6a08ddae08990 /src/location/maps/qgeotiledmapscene.cpp | |
parent | ad620973ea45b79fd17c6b0d31a613b35ba6566b (diff) |
Refactoring QGeoTiledMapScene::mercatorToItemPosition
This patch reimplements the method mercatorToItemPosition using
values relevant for this type of conversion, instead of re-using
values initially computed for the tile generation.
This allows to greatly optimize the method, reducing branches and
the total number of operations, as well as making it easier to
understand.
This patch also removes the support for letterboxing the map
viewport inside the DeclarativeGeoMap, as there now is the
constraint that the map can never be smaller than the containing
element.
Change-Id: Ida98e97ad0a6b65233c80ae3c4abd3ec7664c555
Reviewed-by: Michal Klocek <michal.klocek@qt.io>
Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
Diffstat (limited to 'src/location/maps/qgeotiledmapscene.cpp')
-rw-r--r-- | src/location/maps/qgeotiledmapscene.cpp | 168 |
1 files changed, 51 insertions, 117 deletions
diff --git a/src/location/maps/qgeotiledmapscene.cpp b/src/location/maps/qgeotiledmapscene.cpp index d859c2af..cff5999e 100644 --- a/src/location/maps/qgeotiledmapscene.cpp +++ b/src/location/maps/qgeotiledmapscene.cpp @@ -84,21 +84,15 @@ public: int m_maxTileY; int m_tileXWrapsBelow; // the wrap point as a tile index - // cameraToGrid transform - double m_mercatorCenterX; // center of camera in grid space (0 to sideLength) - double m_mercatorCenterY; - double m_mercatorWidth; // width of camera in grid space (0 to sideLength) - double m_mercatorHeight; - - // screenToWindow transform - double m_screenOffsetX; // in pixels - double m_screenOffsetY; // in pixels + // mercatorToItemPosition + double m_cameraCenterXMercator; + double m_cameraCenterYMercator; + double m_cameraWidthMercator; + double m_cameraHeightMercator; + // cameraToScreen transform double m_screenWidth; // in pixels double m_screenHeight; // in pixels - - bool m_useVerticalLock; - bool m_verticalLock; bool m_linearScaling; bool m_dropTextures; @@ -124,12 +118,6 @@ QGeoTiledMapScene::~QGeoTiledMapScene() { } -void QGeoTiledMapScene::setUseVerticalLock(bool lock) -{ - Q_D(QGeoTiledMapScene); - d->m_useVerticalLock = lock; -} - void QGeoTiledMapScene::setScreenSize(const QSize &size) { Q_D(QGeoTiledMapScene); @@ -182,12 +170,6 @@ QDoubleVector2D QGeoTiledMapScene::mercatorToItemPosition(const QDoubleVector2D return d->mercatorToItemPosition(mercator); } -bool QGeoTiledMapScene::verticalLock() const -{ - Q_D(const QGeoTiledMapScene); - return d->m_verticalLock; -} - QSet<QGeoTileSpec> QGeoTiledMapScene::texturedTiles() { Q_D(QGeoTiledMapScene); @@ -216,16 +198,12 @@ QGeoTiledMapScenePrivate::QGeoTiledMapScenePrivate() m_maxTileX(-1), m_maxTileY(-1), m_tileXWrapsBelow(0), - m_mercatorCenterX(0.0), - m_mercatorCenterY(0.0), - m_mercatorWidth(0.0), - m_mercatorHeight(0.0), - m_screenOffsetX(0.0), - m_screenOffsetY(0.0), + m_cameraCenterXMercator(0), + m_cameraCenterYMercator(0), + m_cameraWidthMercator(0), + m_cameraHeightMercator(0), m_screenWidth(0.0), m_screenHeight(0.0), - m_useVerticalLock(false), - m_verticalLock(false), m_linearScaling(false), m_dropTextures(false) { @@ -237,63 +215,40 @@ QGeoTiledMapScenePrivate::~QGeoTiledMapScenePrivate() QDoubleVector2D QGeoTiledMapScenePrivate::itemPositionToMercator(const QDoubleVector2D &pos) const { - double x = m_mercatorWidth * (((pos.x() - m_screenOffsetX) / m_screenWidth) - 0.5); - x += m_mercatorCenterX; - - if (x > 1.0 * m_sideLength) - x -= 1.0 * m_sideLength; - if (x < 0.0) - x += 1.0 * m_sideLength; - - x /= 1.0 * m_sideLength; - - double y = m_mercatorHeight * (((pos.y() - m_screenOffsetY) / m_screenHeight) - 0.5); - y += m_mercatorCenterY; - y /= 1.0 * m_sideLength; + double x = pos.x(); + x /= m_screenSize.width(); + x -= 0.5; + x *= m_cameraWidthMercator; + x += m_cameraCenterXMercator; + + double y = pos.y(); + y /= m_screenSize.height(); + y -= 0.5; + y *= m_cameraHeightMercator; + y += m_cameraCenterYMercator; + + if (x > 1.0) + x -= 1.0; + else if (x <= 0.0) + x += 1.0; return QDoubleVector2D(x, y); } QDoubleVector2D QGeoTiledMapScenePrivate::mercatorToItemPosition(const QDoubleVector2D &mercator) const { - double mx = m_sideLength * mercator.x(); - - double lb = m_mercatorCenterX - m_mercatorWidth / 2.0; - if (lb < 0.0) - lb += m_sideLength; - double ub = m_mercatorCenterX + m_mercatorWidth / 2.0; - if (m_sideLength < ub) - ub -= m_sideLength; - - double m = (mx - m_mercatorCenterX) / m_mercatorWidth; - - double mWrapLower = (mx - m_mercatorCenterX - m_sideLength) / m_mercatorWidth; - double mWrapUpper = (mx - m_mercatorCenterX + m_sideLength) / m_mercatorWidth; - - // correct for crossing dateline - if (qFuzzyCompare(ub - lb + 1.0, 1.0) || (ub < lb) ) { - if (m_mercatorCenterX < ub) { - if (lb < mx) { - m = mWrapLower; - } - } else if (lb < m_mercatorCenterX) { - if (mx <= ub) { - m = mWrapUpper; - } - } + double x = mercator.x(); + if (m_cameraCenterXMercator < 0.5) { + if (x - m_cameraCenterXMercator > 0.5 ) + x -= 1.0; + } else if (m_cameraCenterXMercator > 0.5) { + if (x - m_cameraCenterXMercator < -0.5 ) + x += 1.0; } - // apply wrapping if necessary so we don't return unreasonably large pos/neg screen positions - // also allows map items to be drawn properly if some of their coords are out of the screen - if ( qAbs(mWrapLower) < qAbs(m) ) - m = mWrapLower; - if ( qAbs(mWrapUpper) < qAbs(m) ) - m = mWrapUpper; - - double x = m_screenWidth * (0.5 + m); - double y = m_screenHeight * (0.5 + (m_sideLength * mercator.y() - m_mercatorCenterY) / m_mercatorHeight); - - return QDoubleVector2D(x + m_screenOffsetX, y + m_screenOffsetY); + x = ((x - m_cameraCenterXMercator) / m_cameraWidthMercator + 0.5) * m_screenSize.width(); + double y = ((mercator.y() - m_cameraCenterYMercator) / m_cameraHeightMercator + 0.5) * m_screenSize.height(); + return QDoubleVector2D(x, y); } bool QGeoTiledMapScenePrivate::buildGeometry(const QGeoTileSpec &spec, QSGImageNode *imageNode) @@ -453,57 +408,36 @@ void QGeoTiledMapScenePrivate::setupCamera() // fraction of zoom level double z = std::pow(2.0, m_cameraData.zoomLevel() - m_intZoomLevel) * m_tileSize; - // calculate altitdue that allows the visible map tiles - // to fit in the screen correctly (note that a larger f will cause - // the camera be higher, resulting in gray areas displayed around - // the tiles) + // Maps smaller than screen size are NOT supported + + // calculate altitude that allows the visible map tiles + // to fit in the screen correctly (note that a larger f would cause + // the camera be higher, resulting in empty areas displayed around + // the tiles or repeated tiles) double altitude = f / (2.0 * z) ; - // mercatorWidth_ and mercatorHeight_ define the ratio for - // mercator and screen coordinate conversion, - // see mercatorToItemPosition() and itemPositionToMercator() - m_mercatorHeight = m_screenSize.height() / z; - m_mercatorWidth = m_screenSize.width() / z; + m_cameraWidthMercator = m_screenSize.width() / (std::pow(2.0, m_cameraData.zoomLevel()) * m_tileSize); + m_cameraHeightMercator = m_screenSize.height() / (std::pow(2.0, m_cameraData.zoomLevel()) * m_tileSize); // calculate center double edge = m_scaleFactor * m_tileSize; // first calculate the camera center in map space in the range of 0 <-> sideLength (2^z) - QDoubleVector3D center = (m_sideLength * QGeoProjection::coordToMercator(m_cameraData.center())); + QDoubleVector2D camCenterMercator = QGeoProjection::coordToMercator(m_cameraData.center()); + QDoubleVector3D center = m_sideLength * camCenterMercator; + m_cameraCenterXMercator = camCenterMercator.x(); + m_cameraCenterYMercator = camCenterMercator.y(); // wrap the center if necessary (due to dateline crossing) if (center.x() < m_tileXWrapsBelow) center.setX(center.x() + 1.0 * m_sideLength); - m_mercatorCenterX = center.x(); - m_mercatorCenterY = center.y(); - // work out where the camera center is w.r.t minimum tile bounds center.setX(center.x() - 1.0 * m_minTileX); center.setY(1.0 * m_minTileY - center.y()); - // letter box vertically - if (m_useVerticalLock && (m_mercatorHeight > 1.0 * m_sideLength)) { - center.setY(-1.0 * m_sideLength / 2.0); - m_mercatorCenterY = m_sideLength / 2.0; - m_screenOffsetY = m_screenSize.height() * (0.5 - m_sideLength / (2 * m_mercatorHeight)); - m_screenHeight = m_screenSize.height() - 2 * m_screenOffsetY; - m_mercatorHeight = 1.0 * m_sideLength; - m_verticalLock = true; - } else { - m_screenOffsetY = 0.0; - m_screenHeight = m_screenSize.height(); - m_verticalLock = false; - } - - if (m_mercatorWidth > 1.0 * m_sideLength) { - m_screenOffsetX = m_screenSize.width() * (0.5 - (m_sideLength / (2 * m_mercatorWidth))); - m_screenWidth = m_screenSize.width() - 2 * m_screenOffsetX; - m_mercatorWidth = 1.0 * m_sideLength; - } else { - m_screenOffsetX = 0.0; - m_screenWidth = m_screenSize.width(); - } + m_screenHeight = m_screenSize.height(); + m_screenWidth = m_screenSize.width(); // apply necessary scaling to the camera center center *= edge; @@ -714,7 +648,7 @@ QSGNode *QGeoTiledMapScene::updateSceneGraph(QSGNode *oldNode, QQuickWindow *win if (!mapRoot) mapRoot = new QGeoTiledMapRootNode(); - mapRoot->setClipRect(QRect(d->m_screenOffsetX, d->m_screenOffsetY, d->m_screenWidth, d->m_screenHeight)); + mapRoot->setClipRect(QRect(0, 0, d->m_screenWidth, d->m_screenHeight)); QMatrix4x4 itemSpaceMatrix; itemSpaceMatrix.scale(w / 2, h / 2); |