X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;ds=sidebyside;f=src%2Fmap%2Fmapscene.cpp;h=556ac85d82be7496e383b8610ff2c8d32f048c13;hb=905d4e77412084ed24523c364362b45b1feba2be;hp=a3792860686620628498a72485f35977a9952c55;hpb=b3c66486ac57c548b64c7c7d2692054a2d0a5963;p=situare diff --git a/src/map/mapscene.cpp b/src/map/mapscene.cpp index a379286..556ac85 100644 --- a/src/map/mapscene.cpp +++ b/src/map/mapscene.cpp @@ -21,28 +21,47 @@ #include -#include "mapscene.h" +#include "mapcommon.h" #include "mapengine.h" +#include "maptile.h" + +#include "mapscene.h" 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__; - const int maxTilesPerSide = (1 << MAX_MAP_ZOOM_LEVEL); - const int maxPixelsX = maxTilesPerSide * TILE_SIZE_X; - const int maxPixelsY = maxTilesPerSide * TILE_SIZE_Y; - setSceneRect(0, 0, maxPixelsX, maxPixelsY); + setBackgroundBrush(Qt::lightGray); + setSceneRect(QRect(QPoint(MAP_SCENE_MIN_PIXEL_X, OSM_MAP_MIN_PIXEL_Y), + QPoint(MAP_SCENE_MAX_PIXEL_X, OSM_MAP_MAX_PIXEL_Y))); } -void MapScene::addTile(MapTile *mapTile, QString hashKey) +void MapScene::addTile(int tileZoomLevel, QPoint tileNumber, const QPixmap &image, int viewZoomLevel) { qDebug() << __PRETTY_FUNCTION__; - m_mapTilesInScene.insert(hashKey, mapTile); - addItem(mapTile); + // tile might already be in the scene if expired tile was returned from the cache to be + // temporarily shown while downloading the fresh one. + 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); + + m_mapTilesInScene.insert(hashKey, tile); + addItem(tile); + + qDebug() << __PRETTY_FUNCTION__ << "tiles count:" << m_mapTilesInScene.count(); + + enqueueRemoveStackedTiles(tile); + removeOtherLevelTiles(); } void MapScene::enqueueRemoveStackedTiles(MapTile *newTile) @@ -56,11 +75,22 @@ void MapScene::enqueueRemoveStackedTiles(MapTile *newTile) } } -bool MapScene::isTileInScene(QString hashKey) +void MapScene::moveIntersectingItemsHorizontally(QRect from, int distance) { qDebug() << __PRETTY_FUNCTION__; - return m_mapTilesInScene.contains(hashKey); + QList spanItems = items(from, Qt::IntersectsItemBoundingRect); + foreach (QGraphicsItem *item, spanItems) { + if (!dynamic_cast(item)) + item->moveBy(distance, 0); + } +} + +MapTile* MapScene::tileInScene(QString hashKey) +{ + qDebug() << __PRETTY_FUNCTION__; + + return m_mapTilesInScene.value(hashKey, 0); } void MapScene::runNextStackedTilesRemoval() @@ -79,22 +109,64 @@ void MapScene::runNextStackedTilesRemoval() m_isRemoveStackedTilesRunning = false; } -void MapScene::removeOutOfViewTiles() +void MapScene::removeOtherLevelTiles() { qDebug() << __PRETTY_FUNCTION__; - QList viewTiles = items(m_viewRect, Qt::IntersectsItemBoundingRect); - QList allTiles = items(); + for (int x = m_viewTilesGrid.left(); x <= m_viewTilesGrid.right(); x++) { + for (int y = m_viewTilesGrid.top(); y <= m_viewTilesGrid.bottom(); y++) { + if (!m_mapTilesInScene.contains(MapEngine::tilePath(m_zoomLevel, x, y))) + return; + } + } + + foreach(MapTile *tile, m_mapTilesInScene) { + if (tile->zoomLevel() != m_zoomLevel) { + removeTile(tile); + qDebug() << __PRETTY_FUNCTION__ << "removed other level tile"; + } + } +} + +void MapScene::removeOutOfViewTiles(QRect tilesGrid, int zoomLevel) +{ + qDebug() << __PRETTY_FUNCTION__; + + QList viewItems = items(m_tilesSceneRect, Qt::IntersectsItemBoundingRect); + QList allItems = items(); //Remove tiles which are in view from allTiles - foreach (QGraphicsItem *tile, viewTiles) - allTiles.removeOne(tile); + foreach (QGraphicsItem *item, viewItems) + allItems.removeOne(item); + + // note: add 1 so odd values are rounded up + int tilesGridWidthHalf = (tilesGrid.width() + 1) / 2; + + // if view is near east limit of the map, then there is duplicate tiles also on the opposite + // side of the world which are removed from allTiles + if (tilesGrid.right() > (MapEngine::tileMaxIndex(zoomLevel) - tilesGridWidthHalf + MAP_GRID_PADDING)) { + QRect oppositeRect = m_tilesSceneRect; + oppositeRect.translate(-OMS_MAP_PIXELS_X, 0); + QList oppositeItems = items(oppositeRect, Qt::IntersectsItemBoundingRect); + foreach (QGraphicsItem *item, oppositeItems) + allItems.removeOne(item); + } + + // if view is near west limit of the map, then there is duplicate tiles also on the opposite + // side of the world which are removed from allTiles + if (tilesGrid.left() < (tilesGridWidthHalf - MAP_GRID_PADDING)) { + QRect oppositeRect = m_tilesSceneRect; + oppositeRect.translate(OMS_MAP_PIXELS_X, 0); + QList oppositeItems = items(oppositeRect, Qt::IntersectsItemBoundingRect); + foreach (QGraphicsItem *item, oppositeItems) + allItems.removeOne(item); + } //Remove tiles out of view - foreach (QGraphicsItem *tile, allTiles) { - MapTile *tileToRemove = dynamic_cast(tile); - if (tileToRemove) - removeTile(tileToRemove); + foreach (QGraphicsItem *item, allItems) { + MapTile *tile = dynamic_cast(item); + if (tile) + removeTile(tile); } } @@ -129,6 +201,20 @@ void MapScene::removeTile(MapTile *tile) removeItem(tile); m_removeStackedTilesList.removeAll(tile); delete tile; + + qDebug() << __PRETTY_FUNCTION__ << "tiles count:" << m_mapTilesInScene.count(); +} + +void MapScene::setSceneVerticalOverlap(int viewHeight, int zoomLevel) +{ + qDebug() << __PRETTY_FUNCTION__; + + int overlap = viewHeight / 2 * (1 << (OSM_MAX_ZOOM_LEVEL - zoomLevel)); + + QRect rect = sceneRect().toRect(); + rect.setTop(OSM_MAP_MIN_PIXEL_Y - overlap); + rect.setBottom(OSM_MAP_MAX_PIXEL_Y + overlap); + setSceneRect(rect); } void MapScene::setTilesDrawingLevels(int zoomLevel) @@ -144,9 +230,52 @@ void MapScene::setTilesDrawingLevels(int zoomLevel) } } -void MapScene::viewRectUpdated(QRect viewRect) +void MapScene::setTilesGrid(QRect grid) +{ + qDebug() << __PRETTY_FUNCTION__ ; + + m_viewTilesGrid = grid; +} + +void MapScene::setZoomLevel(int zoomLevel) +{ + qDebug() << __PRETTY_FUNCTION__ ; + + m_zoomLevel = zoomLevel; +} + +void MapScene::spanItems(int zoomLevel, QPoint sceneCoordinate, QSize viewSize) +{ + qDebug() << __PRETTY_FUNCTION__; + + // create rects for left and right side + QRect leftRect = sceneRect().toRect(); // this way we get the horizontal limits of the scene + leftRect.setTop(OSM_MAP_MIN_PIXEL_Y); + leftRect.setBottom(OSM_MAP_MAX_PIXEL_Y); + QRect rightRect = leftRect; + + // calculate current horizontal area shown on the view + int viewSceneWidth = (1 << (OSM_MAX_ZOOM_LEVEL - zoomLevel)) * viewSize.width(); + int viewSceneLeft = sceneCoordinate.x() - viewSceneWidth / 2; + int viewSceneRight = sceneCoordinate.x() + viewSceneWidth / 2; + + // limit rects to include only area which really must be moved + leftRect.setRight(-1 - (OMS_MAP_PIXELS_X - 1 - viewSceneRight)); + rightRect.setLeft(OMS_MAP_PIXELS_X + viewSceneLeft); + + Q_ASSERT_X(leftRect.right() < viewSceneLeft, "spanning rect right value", "move rect is in the view area"); + Q_ASSERT_X(rightRect.left() > viewSceneRight, "spanning rect left value", "move rect is in the view area"); + + // move all items which intersects the rects + if (leftRect.left() < leftRect.right()) + moveIntersectingItemsHorizontally(leftRect, OMS_MAP_PIXELS_X); + if (rightRect.left() < rightRect.right()) + moveIntersectingItemsHorizontally(rightRect, -OMS_MAP_PIXELS_X); +} + +void MapScene::tilesSceneRectUpdated(QRect tilesSceneRect) { qDebug() << __PRETTY_FUNCTION__; - m_viewRect = viewRect; + m_tilesSceneRect = tilesSceneRect; }