USA.
*/
-#include <cmath>
-
#include <QDebug>
#include "mapcommon.h"
#include "mapscene.h"
-const int WORLD_PIXELS_Y = MAX_TILES_PER_SIDE * TILE_SIZE_Y;
-
MapScene::MapScene(QObject *parent)
: QGraphicsScene(parent)
, m_isRemoveStackedTilesRunning(false)
qDebug() << __PRETTY_FUNCTION__;
setBackgroundBrush(Qt::lightGray);
- setSceneRect(-WORLD_PIXELS_X * 2, 0, WORLD_PIXELS_X * 5 - 1, WORLD_PIXELS_Y - 1);
+ 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(int tileZoomLevel, QPoint tileNumber, const QPixmap &image, int viewZoomLevel)
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
+ // temporarily shown while downloading the fresh one.
QString hashKey = MapEngine::tilePath(tileZoomLevel, tileNumber.x(), tileNumber.y());
MapTile *oldTile = tileInScene(hashKey);
if (oldTile)
tile->setTileNumber(tileNumber);
tile->setPixmap(image);
- m_mapTilesInScene.insertMulti(hashKey, tile);
+ m_mapTilesInScene.insert(hashKey, tile);
addItem(tile);
+ qDebug() << __PRETTY_FUNCTION__ << "tiles count:" << m_mapTilesInScene.count();
+
enqueueRemoveStackedTiles(tile);
+ removeOtherLevelTiles();
}
void MapScene::enqueueRemoveStackedTiles(MapTile *newTile)
{
qDebug() << __PRETTY_FUNCTION__;
- qWarning() << __PRETTY_FUNCTION__ << "left:" << from.left() << "right:" << from.right() << "distance:" << distance;
-
QList<QGraphicsItem *> spanItems = items(from, Qt::IntersectsItemBoundingRect);
foreach (QGraphicsItem *item, spanItems) {
- if (dynamic_cast<MapTile *>(item))
- continue;
- qWarning() << __PRETTY_FUNCTION__ << "moving item...";
- item->moveBy(distance, 0);
+ if (!dynamic_cast<MapTile *>(item))
+ item->moveBy(distance, 0);
}
}
m_isRemoveStackedTilesRunning = false;
}
-void MapScene::removeOutOfViewTiles(QRect tilesGrid, int zoomLevel)
+void MapScene::removeOtherLevelTiles()
{
qDebug() << __PRETTY_FUNCTION__;
-// qWarning() << __PRETTY_FUNCTION__ << "m_tilesSceneRect:" << m_tilesSceneRect.left() << m_tilesSceneRect.top() << "/" << m_tilesSceneRect.right() << m_tilesSceneRect.bottom();
+ 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;
+ }
+ }
- QList<QGraphicsItem *> viewTiles = items(m_tilesSceneRect, Qt::IntersectsItemBoundingRect);
- QList<QGraphicsItem *> allTiles = items();
+ 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<QGraphicsItem *> viewItems = items(m_tilesSceneRect, Qt::IntersectsItemBoundingRect);
+ QList<QGraphicsItem *> 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;
-// qWarning() << __PRETTY_FUNCTION__ << "half:" << tilesGridWidthHalf;
- if (tilesGrid.right() > (MapEngine::tileMaxValue(zoomLevel) - tilesGridWidthHalf + GRID_PADDING)) { /// @todo must be mirrored also when near the world limit
+ // 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(-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);
+ oppositeRect.translate(-OMS_MAP_PIXELS_X, 0);
+ QList<QGraphicsItem *> oppositeItems = items(oppositeRect, Qt::IntersectsItemBoundingRect);
+ foreach (QGraphicsItem *item, oppositeItems)
+ allItems.removeOne(item);
}
- if (tilesGrid.left() < (tilesGridWidthHalf - GRID_PADDING)) { /// @todo must be mirrored also when near the world limit
+ // 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(WORLD_PIXELS_X, 0);
- QList<QGraphicsItem *> oppositeTiles = items(oppositeRect, Qt::IntersectsItemBoundingRect);
- foreach (QGraphicsItem *tile, oppositeTiles)
- allTiles.removeOne(tile);
+ oppositeRect.translate(OMS_MAP_PIXELS_X, 0);
+ QList<QGraphicsItem *> 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<MapTile *>(tile);
- if (tileToRemove) {
-// qWarning() << __PRETTY_FUNCTION__ << "removing tile, x:" << tileToRemove->tileNumber().x() << "y:" << tileToRemove->tileNumber().y() << "pos:" << tileToRemove->pos().x() << tileToRemove->pos().y();
- removeTile(tileToRemove);
- }
+ foreach (QGraphicsItem *item, allItems) {
+ MapTile *tile = dynamic_cast<MapTile *>(item);
+ if (tile)
+ removeTile(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 << (MAX_MAP_ZOOM_LEVEL - zoomLevel));
+ int overlap = viewHeight / 2 * (1 << (OSM_MAX_ZOOM_LEVEL - zoomLevel));
QRect rect = sceneRect().toRect();
- rect.setTop(-overlap);
- rect.setBottom(WORLD_PIXELS_Y + overlap - 1);
+ rect.setTop(OSM_MAP_MIN_PIXEL_Y - overlap);
+ rect.setBottom(OSM_MAP_MAX_PIXEL_Y + overlap);
setSceneRect(rect);
-
-// qWarning() << __PRETTY_FUNCTION__ << "scene rect:" << rect.left() << rect.top() << rect.right() << rect.bottom();
}
void MapScene::setTilesDrawingLevels(int zoomLevel)
}
}
-void MapScene::spanItems(ScrollDirection direction, int zoomLevel, QPoint sceneCoordinate, QSize viewSize)
+void MapScene::setTilesGrid(QRect grid)
+{
+ qDebug() << __PRETTY_FUNCTION__ ;
+
+ m_viewTilesGrid = grid;
+}
+
+void MapScene::setZoomLevel(int zoomLevel)
{
- qWarning() << __PRETTY_FUNCTION__;
+ 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(0);
- leftRect.setBottom(WORLD_PIXELS_Y);
+ 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 << (MAX_MAP_ZOOM_LEVEL - zoomLevel)) * viewSize.width();
+ int viewSceneWidth = (1 << (OSM_MAX_ZOOM_LEVEL - zoomLevel)) * viewSize.width();
int viewSceneLeft = sceneCoordinate.x() - viewSceneWidth / 2;
int viewSceneRight = sceneCoordinate.x() + viewSceneWidth / 2;
- // limit rect widths to be out of the current view
- leftRect.setRight(viewSceneLeft);
- rightRect.setLeft(viewSceneRight);
+ // 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.width() > 0)
- moveIntersectingItemsHorizontally(leftRect, WORLD_PIXELS_X);
- if (rightRect.width() > 0)
- moveIntersectingItemsHorizontally(rightRect, -WORLD_PIXELS_X);
-
- /// @todo get small rects from boths sides of the view
-
- /// @todo get all intersecting items, check which end of the view is nearer and move there
-
-
-// QRect spanRect; // = m_viewRect;
-// spanRect.setTop(0);
-// spanRect.setBottom(WORLD_PIXELS_Y);
-// int delta;
-
-// int viewSceneWidth = (1 << (MAX_MAP_ZOOM_LEVEL - zoomLevel)) * viewSize.width();
-// int gap = WORLD_PIXELS_X - viewSceneWidth;
-// if (gap < 0)
-// qCritical() << __PRETTY_FUNCTION__ << "viewSceneWidth > WORLD_PIXELS_X";
-
-// int limiterUnNormalized = sceneCoordinate.x() + ((viewSceneWidth + gap) / 2);
-// int limiter = MapEngine::normalize(limiterUnNormalized, 0, WORLD_PIXELS_X -1);
-
-// if (sceneCoordinate.x() > limiter) {
-// spanRect.setRight(limiter);
-// spanRect.setLeft(sceneRect().left());
-// delta = WORLD_PIXELS_X;
-// qWarning() << __PRETTY_FUNCTION__ << "-->";
-// }
-// else {
-// spanRect.setLeft(limiter);
-// spanRect.setRight(sceneRect().right());
-// delta = -WORLD_PIXELS_X;
-// qWarning() << __PRETTY_FUNCTION__ << "<--";
-// }
-
-// QTransform transform;
-// qreal scale = pow(2, zoomLevel - MAX_MAP_ZOOM_LEVEL);
-// transform.scale(scale, scale);
-// QList<QGraphicsItem *> spanItems = items(spanRect, Qt::IntersectsItemBoundingRect,
-// Qt::DescendingOrder, transform);
-
-// foreach (QGraphicsItem *item, spanItems) {
-// if (dynamic_cast<MapTile *>(item))
-// continue;
-// item->moveBy(delta, 0);
-// }
-
-// return spanRect;
+ 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)