// so collisions are detected even if the items are spanned around
while (rect.left() < 0)
- rect.translate(WORLD_PIXELS_X, 0);
+ rect.translate(MAP_PIXELS_X, 0);
- while (rect.left() > WORLD_PIXELS_X - 1)
- rect.translate(-WORLD_PIXELS_X, 0);
+ while (rect.left() > MAP_PIXELS_X - 1)
+ rect.translate(-MAP_PIXELS_X, 0);
return rect;
}
#include <QLinkedList>
#include <QObject>
-#include "mapcommon.h"
class FriendGroupItem;
class FriendLocationItem;
class MapScene;
/*******************************************************************************
* MEMBER FUNCTIONS AND SLOTS
******************************************************************************/
-public slots:
- /**
- * @brief Re-factors all FriendLocationItem and FriendGroupItem items.
- *
- * Calls mergeCollidingGroups(), dropOutOfGroupFriends(), checkAllGroupsForCollidingFriends()
- * and checkAllFriendsForCollidingFriends().
- *
- * @param zoomLevel Current view zoom level
- */
- void refactorFriendItems(int zoomLevel);
-
private:
/**
* @brief Add new FriendLocationItem
*/
void friendListUpdated(QList<User *> &friendsList);
+ /**
+ * @brief Re-factors all FriendLocationItem and FriendGroupItem items.
+ *
+ * Calls mergeCollidingGroups(), dropOutOfGroupFriends(), checkAllGroupsForCollidingFriends()
+ * and checkAllFriendsForCollidingFriends().
+ *
+ * @param zoomLevel Current view zoom level
+ */
+ void refactorFriendItems(int zoomLevel);
+
/*******************************************************************************
* SIGNALS
******************************************************************************/
const int MIN_MAP_SCENE_NORMAL_LEVEL = MAX_MAP_ZOOM_LEVEL + 1;
const int MAX_TILES_PER_SIDE = (1 << MAX_MAP_ZOOM_LEVEL);
-const int WORLD_PIXELS_X = MAX_TILES_PER_SIDE * TILE_SIZE_X;
-const int MAP_SCENE_MIN_PIXEL_X = -WORLD_PIXELS_X / 2;
-const int MAP_SCENE_MAX_PIXEL_X = WORLD_PIXELS_X * 2;
+const int MAP_PIXELS_X = MAX_TILES_PER_SIDE * TILE_SIZE_X;
+
+const int MAP_MIN_PIXEL_X = 0;
+const int MAP_MAX_PIXEL_X = MAP_PIXELS_X - 1;
+
+const int MAP_SCENE_MIN_PIXEL_X = -MAP_PIXELS_X / 2;
+const int MAP_SCENE_MAX_PIXEL_X = MAP_PIXELS_X * 2;
/**
* @var DEFAULT_START_ZOOM_LEVEL
for (int x = topLeftX; x <= bottomRightX; ++x) {
for (int y = topLeftY; y <= bottomRightY; ++y) {
- int tileX = x;
- int tileY = y;
-
- // span in horizontal direction if world limits has been reached
-// if (tileX < 0)
-// tileX += tileMaxVal + 1;
-// else if (tileX > tileMaxVal)
-// tileX -= tileMaxVal + 1;
-
// map doesn't span in vertical direction
- if (tileY < 0 || tileY > tileMaxVal)
+ if (y < 0 || y > tileMaxVal)
continue;
- if (!m_mapScene->tileInScene(tilePath(m_zoomLevel, tileX, tileY)))
- emit fetchImage(m_zoomLevel, normalize(tileX, 0, tileMaxVal), tileY);
+ if (!m_mapScene->tileInScene(tilePath(m_zoomLevel, x, y)))
+ emit fetchImage(m_zoomLevel, normalize(x, 0, tileMaxVal), y);
}
}
-
-// QRect spanRect = m_mapScene->spanItems(m_scrollDirection, m_zoomLevel, m_sceneCoordinate, m_viewSize);
-// m_friendItemsHandler->spanHiddenFriendLocationItems(m_scrollDirection, spanRect, m_sceneCoordinate);
-// m_friendItemsHandler->refactorFriendItems(m_zoomLevel);
-
-
}
void MapEngine::gpsPositionUpdate(QPointF position, qreal accuracy)
void MapEngine::mapImageReceived(int zoomLevel, int x, int y, const QPixmap &image)
{
-// if (y != 3)
-// return;
-
- qDebug() << __PRETTY_FUNCTION__; // << "x:" << x << "y:" << y;
+ qDebug() << __PRETTY_FUNCTION__;
- // add normal tile
+ // add normal tile inside the world
QPoint tileNumber(x, y);
m_mapScene->addTile(zoomLevel, tileNumber, image, m_zoomLevel);
- // add 1 so odd width is rounded up and even is rounded down
+ // note: add 1 so odd width is rounded up and even is rounded down
int tilesGridWidthHalf = (m_viewTilesGrid.width() + 1) / 2;
- // expand to east side? (don't need to expand over padding)
+ // duplicate to east side? (don't need to duplicate over padding)
if (tileNumber.x() < (tilesGridWidthHalf - GRID_PADDING)) {
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? (don't need to expand over padding)
+ // duplicate to west side? (don't need to duplicate over padding)
if (tileNumber.x() > (tileMaxValue(zoomLevel) - tilesGridWidthHalf + GRID_PADDING - 1)) {
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 (crossing > 0) {
-// qWarning() << __PRETTY_FUNCTION__ << "grid was bigger than amount of tiles at this tile level";
-
-// if (x < crossing) {
-// // expand to east side
-// 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();
-// }
-
-// if (x > (tileMaxValue(zoomLevel) - crossing)) {
-// // expand to west side
-// 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();
-// }
-// }
-
-// m_mapScene->spanItems(m_scrollDirection, m_zoomLevel);
}
int MapEngine::normalize(int value, int min, int max)
{
- qDebug() << __PRETTY_FUNCTION__; // << "value:" << value << "min:" << min << "max:" << max;
+ qDebug() << __PRETTY_FUNCTION__;
Q_ASSERT_X(max >= min, "parameters", "max can't be smaller than min");
while (value < min)
qDebug() << __PRETTY_FUNCTION__;
// jump to opposite side of the world if world limit is exceeded
- if (sceneCoordinate.x() < 0)
- sceneCoordinate.setX(sceneCoordinate.x() + WORLD_PIXELS_X);
- else if (sceneCoordinate.x() > WORLD_PIXELS_X - 1)
- sceneCoordinate.setX(sceneCoordinate.x() - WORLD_PIXELS_X);
+ if (sceneCoordinate.x() < MAP_MIN_PIXEL_X)
+ sceneCoordinate.setX(sceneCoordinate.x() + MAP_PIXELS_X);
+ else if (sceneCoordinate.x() > MAP_MAX_PIXEL_X)
+ sceneCoordinate.setX(sceneCoordinate.x() - MAP_PIXELS_X);
if (disableAutoCentering(sceneCoordinate))
emit mapScrolledManually();
m_tilesGridSize.setHeight(gridHeight);
m_tilesGridSize.setWidth(gridWidth);
- qWarning() << __PRETTY_FUNCTION__ << "tiles grid:" << m_tilesGridSize.width()
+ qWarning() << __PRETTY_FUNCTION__ << "tiles:" << m_tilesGridSize.width()
<< "*" << m_tilesGridSize.height()
- << "=" << m_tilesGridSize.width() * m_tilesGridSize.height() << "tiles";
+ << "=" << m_tilesGridSize.width() * m_tilesGridSize.height();
}
void MapEngine::setViewLocation(QPointF latLonCoordinate)
{
qDebug() << __PRETTY_FUNCTION__;
- const int MAX_UPPER_LEVELS = 4;
-
bool imageFound = false;
QAbstractNetworkCache *cache = m_manager->cache();
// try to fetch requested and upper level images until found or MAX_UPPER_LEVELS
// limit is reached
+ const int MAX_UPPER_LEVELS = 4;
do {
QIODevice *cacheImage = cache->data(buildURL(zoomLevel, QPoint(x, y)));
if (cacheImage) {
USA.
*/
-#include <cmath>
-
#include <QDebug>
#include "mapcommon.h"
{
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
+ // tile might already be in the scene if:
+ // - expired tile was returned from the cache to be temporarily displayed while downloading
+ // the fresh one.
+ // - upper level tile is not cleaned after zooming in and back to out (not scrolled enough)
+ // - upper level tile was earlier returned from cache while downloading the requested tile
+ // and user has zoomed up to that level
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);
enqueueRemoveStackedTiles(tile);
{
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);
}
}
{
qDebug() << __PRETTY_FUNCTION__;
-// 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();
foreach (QGraphicsItem *tile, viewTiles)
allTiles.removeOne(tile);
+ // 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 (tilesGrid.right() > (MapEngine::tileMaxValue(zoomLevel) - tilesGridWidthHalf + GRID_PADDING)) {
QRect oppositeRect = m_tilesSceneRect;
- oppositeRect.translate(-WORLD_PIXELS_X, 0);
-// qWarning() << __PRETTY_FUNCTION__ << "oppositeRect:" << oppositeRect.left() << oppositeRect.top() << "/" << oppositeRect.right() << oppositeRect.bottom();
+ oppositeRect.translate(-MAP_PIXELS_X, 0);
QList<QGraphicsItem *> oppositeTiles = items(oppositeRect, Qt::IntersectsItemBoundingRect);
foreach (QGraphicsItem *tile, oppositeTiles)
allTiles.removeOne(tile);
}
- if (tilesGrid.left() < (tilesGridWidthHalf - GRID_PADDING)) { /// @todo must be mirrored also when near the world limit
+ if (tilesGrid.left() < (tilesGridWidthHalf - GRID_PADDING)) {
QRect oppositeRect = m_tilesSceneRect;
- oppositeRect.translate(WORLD_PIXELS_X, 0);
+ oppositeRect.translate(MAP_PIXELS_X, 0);
QList<QGraphicsItem *> oppositeTiles = items(oppositeRect, Qt::IntersectsItemBoundingRect);
foreach (QGraphicsItem *tile, oppositeTiles)
allTiles.removeOne(tile);
//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();
+ if (tileToRemove)
removeTile(tileToRemove);
- }
}
- qWarning() << __PRETTY_FUNCTION__ << "tiles in scene:" << items().count();
+ qWarning() << __PRETTY_FUNCTION__ << "items in scene:" << items().count();
}
void MapScene::removeStackedTiles(MapTile *newTile)
}
}
}
-// qWarning() << __PRETTY_FUNCTION__ << "tiles in scene:" << items().count();
+ qWarning() << __PRETTY_FUNCTION__ << "items in scene:" << items().count();
}
void MapScene::removeTile(MapTile *tile)
rect.setTop(MAP_MIN_PIXEL_Y - overlap);
rect.setBottom(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(int zoomLevel, QPoint sceneCoordinate, QSize viewSize)
{
-// qWarning() << __PRETTY_FUNCTION__;
+ qDebug() << __PRETTY_FUNCTION__;
// create rects for left and right side
QRect leftRect = sceneRect().toRect(); // this way we get the horizontal limits of the scene
int viewSceneLeft = sceneCoordinate.x() - viewSceneWidth / 2;
int viewSceneRight = sceneCoordinate.x() + viewSceneWidth / 2;
-// qWarning() << __PRETTY_FUNCTION__ << "width:" << viewSceneWidth << "left:" << viewSceneLeft << "right:" << viewSceneRight;
-
// limit rects to include only area which really must be moved
- leftRect.setRight(-1 - (WORLD_PIXELS_X - 1 - viewSceneRight));
- rightRect.setLeft(WORLD_PIXELS_X + viewSceneLeft);
+ leftRect.setRight(-1 - (MAP_PIXELS_X - 1 - viewSceneRight));
+ rightRect.setLeft(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, WORLD_PIXELS_X);
+ moveIntersectingItemsHorizontally(leftRect, MAP_PIXELS_X);
if (rightRect.left() < rightRect.right())
- 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;
+ moveIntersectingItemsHorizontally(rightRect, -MAP_PIXELS_X);
}
void MapScene::tilesSceneRectUpdated(QRect tilesSceneRect)
#include <QGraphicsScene>
-#include "mapcommon.h"
-
-class MapTile;
+#include "maptile.h"
/**
* @brief Map scene for storing MapTile items
/**
* @brief Create and add new MapTile to MapScene
*
- * If there is a tile with same parameter already in the scene, it will be removed
+ * If there is a tile with same parameters already in the scene, it will be removed
* before adding the new tile.
*
* @param zoomLevel Zoom level of the new tile