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;
if (isCenterTileChanged(sceneCoordinate)) {
getTiles(sceneCoordinate);
- m_mapScene->removeOutOfViewTiles();
+ m_mapScene->removeOutOfViewTiles(m_viewTilesGrid, m_zoomLevel);
}
}
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)
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);
}
if (m_zoomedIn) {
m_zoomedIn = false;
- m_mapScene->removeOutOfViewTiles();
+ m_mapScene->removeOutOfViewTiles(m_viewTilesGrid, m_zoomLevel);
}
if (m_zoomLevel == MAX_MAP_ZOOM_LEVEL)
*
* @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.
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
* @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
/*******************************************************************************
* SIGNALS
******************************************************************************/
-signals:
+signals:
/**
* @brief Signal for image fetching.
*
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__;
{
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);
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)
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);
}
}
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;
}
return spanRect;
}
-void MapScene::viewRectUpdated(QRect viewRect)
+void MapScene::tilesSceneRectUpdated(QRect tilesSceneRect)
{
qDebug() << __PRETTY_FUNCTION__;
- m_viewRect = viewRect;
+ m_tilesSceneRect = tilesSceneRect;
}
******************************************************************************/
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
* @brief Remove tiles which are out of view bounds.
*
*/
- void removeOutOfViewTiles();
+ void removeOutOfViewTiles(QRect tilesGrid, int zoomLevel);
/**
* @brief Remove tiles which are stacked.
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:
/**
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