Got map spanning working
authorSami Rämö <sami.ramo@ixonos.com>
Mon, 7 Jun 2010 07:14:12 +0000 (10:14 +0300)
committerSami Rämö <sami.ramo@ixonos.com>
Mon, 7 Jun 2010 07:14:12 +0000 (10:14 +0300)
 - Fixed duplicating received tiles in mapImageReceived()
   when necessary

 - Fixed removeOutOfViewTiles() not to remove duplicated
   tiles when view is near world limits

 - MapScene::addTile() does now take care of remove old
   version of the tile from the scene if it already exists

src/map/mapengine.cpp
src/map/mapengine.h
src/map/mapscene.cpp
src/map/mapscene.h

index 8349a44..edccce2 100644 (file)
@@ -282,45 +282,52 @@ bool MapEngine::isCenterTileChanged(QPoint sceneCoordinate)
 
 void MapEngine::mapImageReceived(int zoomLevel, int x, int y, const QPixmap &image)
 {
-    if (y != 3)
-        return;
+//    if (y != 3)
+//        return;
 
     qWarning() << __PRETTY_FUNCTION__ << "x:" << x << "y:" << y;
 
-    // tile might already be in the scene if expired tile was returned from the cache to be
-    // temporarily displayed while downloading the fresh one
-    QString hashKey = tilePath(zoomLevel, x, y);
-    MapTile *oldTile = m_mapScene->tileInScene(hashKey);
-    if (oldTile)
-        m_mapScene->removeTile(oldTile);
-
     // add normal tile
     QPoint tileNumber(x, y);
     m_mapScene->addTile(zoomLevel, tileNumber, image, m_zoomLevel);
 
-    // expanding is only done if received tile zoom level is same as current zoom level
-    if (zoomLevel == m_zoomLevel) {
-        // expand to east side?
-        if (m_viewTilesGrid.right() > tileMaxValue(zoomLevel)) {
-            int crossing = m_viewTilesGrid.right() - tileMaxValue(zoomLevel);
-            if (tileNumber.x() < crossing) {
-                QPoint adjustedTileNumber(tileNumber.x() + tileMaxValue(zoomLevel) + 1, tileNumber.y());
-                m_mapScene->addTile(zoomLevel, adjustedTileNumber, image, m_zoomLevel);
-                qWarning() << __PRETTY_FUNCTION__ << "duplicate tile to east, x:" << x << "->" << adjustedTileNumber.x() << "y:" << adjustedTileNumber.y();
-            }
-        }
+    // expand to east side?
+    if (tileNumber.x() < 3) {
+        QPoint adjustedTileNumber(tileNumber.x() + tileMaxValue(zoomLevel) + 1, tileNumber.y());
+        m_mapScene->addTile(zoomLevel, adjustedTileNumber, image, m_zoomLevel);
+        qWarning() << __PRETTY_FUNCTION__ << "duplicate tile to east, x:" << x << "->" << adjustedTileNumber.x() << "y:" << adjustedTileNumber.y();
+    }
 
-        // expand to west side?
-        if (m_viewTilesGrid.left() < 0) {
-            int crossing = -m_viewTilesGrid.left();
-            if (tileNumber.x() > (tileMaxValue(zoomLevel) - crossing)) {
-                QPoint adjustedTileNumber(tileNumber.x() - tileMaxValue(zoomLevel) - 1, tileNumber.y());
-                m_mapScene->addTile(zoomLevel, adjustedTileNumber, image, m_zoomLevel);
-                qWarning() << __PRETTY_FUNCTION__ << "duplicate tile to west, x:" << x << "->" << adjustedTileNumber.x() << "y:" << adjustedTileNumber.y();
-            }
-        }
+    // expand to west side?
+    if (tileNumber.x() > (tileMaxValue(zoomLevel) - 3)) {
+        QPoint adjustedTileNumber(tileNumber.x() - tileMaxValue(zoomLevel) - 1, tileNumber.y());
+        m_mapScene->addTile(zoomLevel, adjustedTileNumber, image, m_zoomLevel);
+        qWarning() << __PRETTY_FUNCTION__ << "duplicate tile to west, x:" << x << "->" << adjustedTileNumber.x() << "y:" << adjustedTileNumber.y();
     }
 
+//    // expanding is only done if received tile zoom level is same as current zoom level
+//    if (zoomLevel == m_zoomLevel) {
+//        // expand to east side?
+//        if (m_viewTilesGrid.right() > tileMaxValue(zoomLevel)) {
+//            int crossing = m_viewTilesGrid.right() - tileMaxValue(zoomLevel);
+//            if (tileNumber.x() < crossing) {
+//                QPoint adjustedTileNumber(tileNumber.x() + tileMaxValue(zoomLevel) + 1, tileNumber.y());
+//                m_mapScene->addTile(zoomLevel, adjustedTileNumber, image, m_zoomLevel);
+//                qWarning() << __PRETTY_FUNCTION__ << "duplicate tile to east, x:" << x << "->" << adjustedTileNumber.x() << "y:" << adjustedTileNumber.y();
+//            }
+//        }
+
+//        // expand to west side?
+//        if (m_viewTilesGrid.left() < 0) {
+//            int crossing = -m_viewTilesGrid.left();
+//            if (tileNumber.x() > (tileMaxValue(zoomLevel) - crossing)) {
+//                QPoint adjustedTileNumber(tileNumber.x() - tileMaxValue(zoomLevel) - 1, tileNumber.y());
+//                m_mapScene->addTile(zoomLevel, adjustedTileNumber, image, m_zoomLevel);
+//                qWarning() << __PRETTY_FUNCTION__ << "duplicate tile to west, x:" << x << "->" << adjustedTileNumber.x() << "y:" << adjustedTileNumber.y();
+//            }
+//        }
+//    }
+
 
 //    int crossing =  m_tilesGridSize.width() - tileMaxValue(zoomLevel) - 1;
 ////    qWarning() << __PRETTY_FUNCTION__ << "crossing:" << crossing;
@@ -416,7 +423,7 @@ void MapEngine::setLocation(QPoint sceneCoordinate)
 
     if (isCenterTileChanged(sceneCoordinate)) {
         getTiles(sceneCoordinate);
-        m_mapScene->removeOutOfViewTiles();
+        m_mapScene->removeOutOfViewTiles(m_viewTilesGrid, m_zoomLevel);
     }
 }
 
@@ -496,7 +503,7 @@ void MapEngine::updateViewTilesSceneRect()
                                                             m_viewTilesGrid.bottomRight()
                                                              + ONE_TILE) - ONE_PIXEL;
 
-    m_mapScene->viewRectUpdated(QRect(topLeft, bottomRight));
+    m_mapScene->tilesSceneRectUpdated(QRect(topLeft, bottomRight));
 }
 
 void MapEngine::viewResized(const QSize &size)
@@ -508,7 +515,7 @@ void MapEngine::viewResized(const QSize &size)
 
     emit locationChanged(m_sceneCoordinate);
     getTiles(m_sceneCoordinate);
-    m_mapScene->removeOutOfViewTiles();
+    m_mapScene->removeOutOfViewTiles(m_viewTilesGrid, m_zoomLevel);
     m_mapScene->setSceneVerticalOverlap(m_viewSize.height(), m_zoomLevel);
 }
 
@@ -518,7 +525,7 @@ void MapEngine::viewZoomFinished()
 
     if (m_zoomedIn) {
         m_zoomedIn = false;
-        m_mapScene->removeOutOfViewTiles();
+        m_mapScene->removeOutOfViewTiles(m_viewTilesGrid, m_zoomLevel);
     }
 
     if (m_zoomLevel == MAX_MAP_ZOOM_LEVEL)
index c3e6f87..029e6a7 100644 (file)
@@ -184,7 +184,15 @@ public slots:
     *
     * @param latLonCoordinate Latitude & longitude coordinates for location
     */
-    void setViewLocation(QPointF latLonCoordinate);    
+    void setViewLocation(QPointF latLonCoordinate);
+
+    /**
+    * @brief Calculate maximum value for tile in this zoom level.
+    *
+    * @param zoomLevel zoom level
+    * @return int tile's maximum value
+    */
+    static int tileMaxValue(int zoomLevel);
 
     /**
     * @brief Slot for view resizing.
@@ -246,14 +254,6 @@ private:
     void setTilesGridSize(const QSize &viewSize);
 
     /**
-    * @brief Calculate maximum value for tile in this zoom level.
-    *
-    * @param zoomLevel zoom level
-    * @return int tile's maximum value
-    */
-    int tileMaxValue(int zoomLevel);
-
-    /**
     * @brief Updates the current view rect including margins
     *
     * Calculates tiles rect in scene based on m_viewTilesGrid and
@@ -285,7 +285,7 @@ private slots:
     * @param y Tile y index
     * @param image Received pixmap
     */
-    void mapImageReceived(int zoomLevel, int x, int y, const QPixmap &image);    
+    void mapImageReceived(int zoomLevel, int x, int y, const QPixmap &image);
 
     /**
     * @brief Slot for actions after view zoom is finished
@@ -307,7 +307,7 @@ private slots:
 /*******************************************************************************
  * SIGNALS
  ******************************************************************************/
-signals:   
+signals:
     /**
     * @brief Signal for image fetching.
     *
index ee74af4..b07b49d 100644 (file)
@@ -34,7 +34,7 @@ const int WORLD_PIXELS_Y = MAX_TILES_PER_SIDE * TILE_SIZE_Y;
 MapScene::MapScene(QObject *parent)
     : QGraphicsScene(parent)
     , m_isRemoveStackedTilesRunning(false)
-    , m_viewRect(QRect(0, 0, 0, 0))
+    , m_tilesSceneRect(QRect(0, 0, 0, 0))
 {
     qDebug() << __PRETTY_FUNCTION__;
 
@@ -46,12 +46,20 @@ void MapScene::addTile(int tileZoomLevel, QPoint tileNumber, const QPixmap &imag
 {
     qDebug() << __PRETTY_FUNCTION__;
 
+    // tile might already be in the scene if expired tile was returned from the cache to be
+    // temporarily displayed while downloading the fresh one. Tile can also be in the scene if the
+    // zoom level is low and world is spanning around, in which case the old tile removal is
+    // unnecessary, but this situation can't be recognised with information currently available
+    QString hashKey = MapEngine::tilePath(tileZoomLevel, tileNumber.x(), tileNumber.y());
+    MapTile *oldTile = tileInScene(hashKey);
+    if (oldTile)
+        removeTile(oldTile);
+
     MapTile *tile = new MapTile();
     tile->setZoomLevel(tileZoomLevel, viewZoomLevel);
     tile->setTileNumber(tileNumber);
     tile->setPixmap(image);
 
-    QString hashKey = MapEngine::tilePath(tileZoomLevel, tileNumber.x(), tileNumber.y());
     m_mapTilesInScene.insertMulti(hashKey, tile);
     addItem(tile);
 
@@ -92,27 +100,34 @@ void MapScene::runNextStackedTilesRemoval()
         m_isRemoveStackedTilesRunning = false;
 }
 
-void MapScene::removeOutOfViewTiles()
+void MapScene::removeOutOfViewTiles(QRect tilesGrid, int zoomLevel)
 {
     qWarning() << __PRETTY_FUNCTION__;
 
-    QList<QGraphicsItem *> viewTiles = items(m_viewRect, Qt::IntersectsItemBoundingRect);
+    qWarning() << __PRETTY_FUNCTION__ << "m_tilesSceneRect:" << m_tilesSceneRect.left() << m_tilesSceneRect.top() << "/" << m_tilesSceneRect.right() << m_tilesSceneRect.bottom();
+
+    QList<QGraphicsItem *> viewTiles = items(m_tilesSceneRect, Qt::IntersectsItemBoundingRect);
     QList<QGraphicsItem *> allTiles = items();
 
     //Remove tiles which are in view from allTiles
     foreach (QGraphicsItem *tile, viewTiles)
         allTiles.removeOne(tile);
 
-    if (m_viewRect.right() > WORLD_PIXELS_X) {
-        QRect oppositeRect = m_viewRect;
+    int lastTile = MapEngine::tileMaxValue(zoomLevel);
+    int half = (tilesGrid.width() + 0.5) / 2;
+    qWarning() << __PRETTY_FUNCTION__ << "half:" << half;
+
+    if (tilesGrid.right() > (lastTile - half)) { /// @todo must be mirrored also when near the world limit
+        QRect oppositeRect = m_tilesSceneRect;
         oppositeRect.translate(-WORLD_PIXELS_X, 0);
+        qWarning() << __PRETTY_FUNCTION__ << "oppositeRect:" << oppositeRect.left() << oppositeRect.top() << "/" << oppositeRect.right() << oppositeRect.bottom();
         QList<QGraphicsItem *> oppositeTiles = items(oppositeRect, Qt::IntersectsItemBoundingRect);
         foreach (QGraphicsItem *tile, oppositeTiles)
             allTiles.removeOne(tile);
     }
 
-    if (m_viewRect.left() < 0) {
-        QRect oppositeRect = m_viewRect;
+    if (tilesGrid.left() < half) { /// @todo must be mirrored also when near the world limit
+        QRect oppositeRect = m_tilesSceneRect;
         oppositeRect.translate(WORLD_PIXELS_X, 0);
         QList<QGraphicsItem *> oppositeTiles = items(oppositeRect, Qt::IntersectsItemBoundingRect);
         foreach (QGraphicsItem *tile, oppositeTiles)
@@ -123,7 +138,7 @@ void MapScene::removeOutOfViewTiles()
     foreach (QGraphicsItem *tile, allTiles) {
         MapTile *tileToRemove = dynamic_cast<MapTile *>(tile);
         if (tileToRemove) {
-            qWarning() << __PRETTY_FUNCTION__ << "removing tile, x:" << tileToRemove->tileNumber().x() << "y:" << tileToRemove->tileNumber().y();
+            qWarning() << __PRETTY_FUNCTION__ << "removing tile, x:" << tileToRemove->tileNumber().x() << "y:" << tileToRemove->tileNumber().y() << "pos:" << tileToRemove->pos().x() << tileToRemove->pos().y();
             removeTile(tileToRemove);
         }
     }
@@ -200,13 +215,13 @@ QRect MapScene::spanItems(ScrollDirection direction, int zoomLevel)
 
     if (direction == SCROLL_WEST) {
         //spanRect.translate(WORLD_PIXELS_X, 0);
-        spanRect.setLeft(m_viewRect.right());
+        spanRect.setLeft(m_tilesSceneRect.right());
         spanRect.setRight(sceneRect().right());
         delta = -WORLD_PIXELS_X;
     }
     else {
         //spanRect.translate(-WORLD_PIXELS_X, 0);
-        spanRect.setRight(m_viewRect.left());
+        spanRect.setRight(m_tilesSceneRect.left());
         spanRect.setLeft(sceneRect().left());
         delta = WORLD_PIXELS_X;
     }
@@ -226,9 +241,9 @@ QRect MapScene::spanItems(ScrollDirection direction, int zoomLevel)
     return spanRect;
 }
 
-void MapScene::viewRectUpdated(QRect viewRect)
+void MapScene::tilesSceneRectUpdated(QRect tilesSceneRect)
 {
     qDebug() << __PRETTY_FUNCTION__;
 
-    m_viewRect = viewRect;
+    m_tilesSceneRect = tilesSceneRect;
 }
index e386309..5722d01 100644 (file)
@@ -50,7 +50,10 @@ public:
  ******************************************************************************/
 public:
     /**
-    * @brief Add MapTile item to scene
+    * @brief Create and add new MapTile to MapScene
+    *
+    * If there is a tile with same parameter already in the scene, it will be removed
+    * before adding the new tile.
     *
     * @param mapTile Map tile item to be added
     * @param hashKey Hash key for the tile
@@ -78,7 +81,7 @@ public:
     * @brief Remove tiles which are out of view bounds.
     *
     */
-    void removeOutOfViewTiles();
+    void removeOutOfViewTiles(QRect tilesGrid, int zoomLevel);
 
     /**
     * @brief Remove tiles which are stacked.
@@ -115,16 +118,16 @@ public:
     QRect spanItems(ScrollDirection direction, int zoomLevel);
 
     /**
-    * @brief Save new view rect
+    * @brief Save new tiles scene rect
     *
-    * View rect must be saved to local scope whenever it changes because
+    * Tiles scene rect must be saved to local scope whenever it changes because
     * it is used by removal algorithms and some of the algorithms are run
-    * delayed so the actual view rect may change before the cleanup
+    * delayed so the actual tiles scene rect may change before the cleanup
     * algorithm is run.
     *
-    * @param viewRect New view rect
+    * @param tilesSceneRect New view rect
     */
-    void viewRectUpdated(QRect viewRect);
+    void tilesSceneRectUpdated(QRect tilesSceneRect);
 
 private slots:
     /**
@@ -140,7 +143,7 @@ private:
     bool m_isRemoveStackedTilesRunning; ///< Is singleshot timer already running
     QHash<QString, MapTile *> m_mapTilesInScene;  ///< List of map tiles in map scene
     QList<MapTile *> m_removeStackedTilesList; ///< "Queue" for stacked tiles removal requests
-    QRect m_viewRect; ///< Current viewable area
+    QRect m_tilesSceneRect; ///< Current viewable area
 };
 
 #endif // MAPSCENE_H