Sami Rämö - sami.ramo@ixonos.com
Jussi Laitinen - jussi.laitinen@ixonos.com
+ Pekka Nissinen - pekka.nissinen@ixonos.com
Situare is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
#include <QUrl>
#include <QHash>
#include <QHashIterator>
-#include <QQueue>
#include <QRect>
#include "mapengine.h"
#include "maptile.h"
-#include <QtCore>
-#include <QtGlobal>
-
MapEngine::MapEngine(QObject *parent)
: QObject(parent)
- , m_zoomLevel(14)
- , m_viewSize(QSize(973, 614))
- , m_centerTile(QPoint(-1, -1))
+ , m_centerTile(QPoint(UNDEFINED, UNDEFINED))
+ , m_viewSize(QSize(DEFAULT_SCREEN_WIDTH, DEFAULT_SCREEN_HEIGHT))
+ , m_zoomedIn(false)
+ , m_zoomLevel(DEFAULT_ZOOM_LEVEL)
{
m_mapScene = new MapScene(this);
m_mapFetcher = new MapFetcher(new QNetworkAccessManager(this), this);
- connect(this, SIGNAL(fetchImage(QUrl)), m_mapFetcher, SLOT(fetchMapImage(QUrl)));
+ connect(this, SIGNAL(fetchImage(QUrl)), m_mapFetcher, SLOT(enqueueFetchMapImage(QUrl)));
connect(m_mapFetcher, SIGNAL(mapImageReceived(QUrl,QPixmap)), this,
SLOT(mapImageReceived(QUrl, QPixmap)));
+
+ m_mapZoomPanel = new MapZoomPanel(NULL, MAP_ZOOM_PANEL_POSITION_X, MAP_ZOOM_PANEL_POSITION_Y);
+ m_mapScene->addItem(m_mapZoomPanel);
+ connect(m_mapZoomPanel, SIGNAL(zoomInPressed()), this, SLOT(zoomIn()));
+ connect(m_mapZoomPanel, SIGNAL(zoomOutPressed()), this, SLOT(zoomOut()));
+
+ m_ownLocation = new OwnLocationItem();
+ m_mapScene->addItem(m_ownLocation);
}
void MapEngine::init()
{
emit zoomLevelChanged(m_zoomLevel);
- setViewLocation(QPointF(25.5000, 65.0000));
-
-// // Fetch some map tiles for demo purposes
-// for (int x=9351; x<=9354; x++) {
-// for (int y=4261; y<=4264; y++) {
-// QUrl url = buildURL(m_zoomLevel, QPoint(x, y));
-// m_mapFetcher->fetchMapImage(url);
-// }
-// }
+ setViewLocation(QPointF(DEFAULT_LONGITUDE, DEFAULT_LATITUDE));
}
void MapEngine::setViewLocation(QPointF latLonCoordinate)
int size = pathParts.size();
- if (size < 3)
- return;
-
- zoom = (pathParts.at(size-3)).toInt();
- x = (pathParts.at(size-2)).toInt();
- QString yString = pathParts.at(size-1);
- yString.chop(4);
- y = yString.toInt();
+ if (size >= 3) {
+ zoom = (pathParts.at(size-3)).toInt();
+ x = (pathParts.at(size-2)).toInt();
+ QString yString = pathParts.at(size-1);
+ yString.chop(4);
+ y = yString.toInt();
+ }
}
void MapEngine::mapImageReceived(const QUrl &url, const QPixmap &pixmap)
{
- if (mapTilesInScene.contains(url.toString())) {
- int zoom = -1;
- int x = -1;
- int y = -1;
+ qDebug() << __PRETTY_FUNCTION__;
- parseURL(url, zoom, x, y);
+ int zoom = UNDEFINED;
+ int x = UNDEFINED;
+ int y = UNDEFINED;
+
+ parseURL(url, zoom, x, y);
+ QString hashKey = tilePath(zoom, x, y);
+ if (!m_mapScene->isTileInScene(hashKey)) {
MapTile *mapTile = new MapTile();
- mapTile->setZoomLevel(zoom);
+ mapTile->setZoomLevel(zoom, m_zoomLevel);
mapTile->setTileNumber(QPoint(x, y));
mapTile->setPixmap(pixmap);
- mapTilesInScene.insert(url.toString(), mapTile);
- m_mapScene->addMapTile(mapTile);
- }
+ m_mapScene->addTile(mapTile, hashKey);
+
+ m_mapScene->debugItemsCount();
+
+ m_mapScene->enqueueRemoveStackedTiles(mapTile);
+ }
}
QGraphicsScene* MapEngine::scene()
return (1 << zoomLevel) - 1;
}
-QRect MapEngine::calculateGrid(QPointF sceneCoordinate)
+QRect MapEngine::calculateTileGrid(QPoint sceneCoordinate)
{
QPoint tileCoordinate = convertSceneCoordinateToTileNumber(m_zoomLevel, sceneCoordinate);
-
int gridWidth = (m_viewSize.width()/TILE_SIZE_X + 1) + (GRID_PADDING*2);
int gridHeight = (m_viewSize.height()/TILE_SIZE_Y + 1) + (GRID_PADDING*2);
-
int topLeftX = tileCoordinate.x() - (gridWidth/2);
int topLeftY = tileCoordinate.y() - (gridHeight/2);
+ m_mapFetcher->setDownloadQueueSize(gridWidth * gridHeight);
+
return QRect(topLeftX, topLeftY, gridWidth, gridHeight);
}
-void MapEngine::setLocation(QPointF sceneCoordinate)
+void MapEngine::alignImmovableItems(QPoint viewTopLeft)
+{
+ m_mapZoomPanel->setPos(viewTopLeft);
+
+ qDebug() << __PRETTY_FUNCTION__ << "viewTopLeft:" << viewTopLeft;
+}
+
+void MapEngine::setLocation(QPoint sceneCoordinate)
{
+ qDebug() << __PRETTY_FUNCTION__;
+
m_sceneCoordinate = sceneCoordinate;
emit locationChanged(m_sceneCoordinate);
- if (centerTileChanged(sceneCoordinate)) {
- calculateTileGrid(sceneCoordinate);
- //removeTilesOutOfBounds();
+ if (isCenterTileChanged(sceneCoordinate)) {
+ getTiles(sceneCoordinate);
+ m_mapScene->removeOutOfViewTiles();
}
}
-bool MapEngine::centerTileChanged(QPointF sceneCoordinate)
+bool MapEngine::isCenterTileChanged(QPoint sceneCoordinate)
{
QPoint centerTile = convertSceneCoordinateToTileNumber(m_zoomLevel, sceneCoordinate);
QPoint temp = m_centerTile;
return (centerTile != temp);
}
-void MapEngine::calculateTileGrid(QPointF sceneCoordinate)
+void MapEngine::getTiles(QPoint sceneCoordinate)
{
- //qDebug() << __PRETTY_FUNCTION__;
+ qDebug() << __PRETTY_FUNCTION__;
- viewGrid = calculateGrid(sceneCoordinate);
+ m_viewTilesGrid = calculateTileGrid(sceneCoordinate);
+ updateViewTilesSceneRect();
- int topLeftX = viewGrid.topLeft().x();
- int topLeftY = viewGrid.topLeft().y();
- int bottomRightX = viewGrid.bottomRight().x();
- int bottomRightY = viewGrid.bottomRight().y();
+ int topLeftX = m_viewTilesGrid.topLeft().x();
+ int topLeftY = m_viewTilesGrid.topLeft().y();
+ int bottomRightX = m_viewTilesGrid.bottomRight().x();
+ int bottomRightY = m_viewTilesGrid.bottomRight().y();
int tileMaxVal = tileMaxValue(m_zoomLevel);
QUrl url = buildURL(m_zoomLevel, QPoint(tileX, tileY));
- if (!mapTilesInScene.contains(url.toString())) {
- mapTilesInScene.insert(url.toString(), NULL);
+ if (!m_mapScene->isTileInScene(tilePath(m_zoomLevel, tileX, tileY)))
emit fetchImage(url);
- }
}
}
}
-void MapEngine::removeTilesOutOfBounds()
+void MapEngine::updateViewTilesSceneRect()
{
- //qDebug() << __PRETTY_FUNCTION__;
-
- int zoomFactor = 1 << (MAX_MAP_ZOOM_LEVEL - m_zoomLevel);
-
- QPointF topLeft = convertTileNumberToSceneCoordinate(m_zoomLevel, viewGrid.topLeft());
- QPointF bottomRight = convertTileNumberToSceneCoordinate(m_zoomLevel, viewGrid.bottomRight() + QPoint(1, 1));
- qreal width = bottomRight.x() - topLeft.x();
- qreal height = bottomRight.y() - topLeft.y();
-
- QList<QGraphicsItem *> viewTiles = m_mapScene->items(topLeft.x(), topLeft.y(), width, height, Qt::IntersectsItemShape);
- QList<QGraphicsItem *> allTiles = m_mapScene->items();
-
- foreach (QGraphicsItem *tile, viewTiles)
- allTiles.removeOne(tile);
-
- QHashIterator<QString, MapTile *> i(mapTilesInScene);
-
- while (i.hasNext()) {
- i.next();
- if (allTiles.contains(i.value())) {
- MapTile *tile = i.value();
- if (tile) {
- mapTilesInScene.remove(i.key());
- m_mapScene->removeItem(tile);
- delete tile;
- }
- }
- }
+ QPoint topLeft = convertTileNumberToSceneCoordinate(m_zoomLevel, m_viewTilesGrid.topLeft());
+ QPoint bottomRight = convertTileNumberToSceneCoordinate(m_zoomLevel,
+ m_viewTilesGrid.bottomRight()
+ + QPoint(1, 1)) - QPoint(1, 1);
+ m_mapScene->viewRectUpdated(QRect(topLeft, bottomRight));
}
void MapEngine::viewResized(const QSize &size)
{
m_viewSize = size;
- setLocation(m_sceneCoordinate);
+ getTiles(m_sceneCoordinate);
+ m_mapScene->removeOutOfViewTiles();
+}
+
+void MapEngine::viewZoomFinished()
+{
+ qDebug() << __PRETTY_FUNCTION__;
+
+ if (m_zoomedIn) {
+ m_zoomedIn = false;
+ m_mapScene->removeOutOfViewTiles();
+ }
}
void MapEngine::zoomIn()
{
- if (m_zoomLevel >= MAX_MAP_ZOOM_LEVEL)
- return;
+ qDebug() << __PRETTY_FUNCTION__;
- m_zoomLevel++;
- emit zoomLevelChanged(m_zoomLevel);
+ if (m_zoomLevel < MAX_MAP_ZOOM_LEVEL) {
+ m_zoomLevel++;
+ m_zoomedIn = true;
+ emit zoomLevelChanged(m_zoomLevel);
- setZValues();
+ m_mapScene->setTilesDrawingLevels(m_zoomLevel);
- /// @todo START FETCHING TILES
- calculateTileGrid(m_sceneCoordinate);
+ getTiles(m_sceneCoordinate);
+ }
}
void MapEngine::zoomOut()
{
- if (m_zoomLevel <= MIN_MAP_ZOOM_LEVEL)
- return;
+ qDebug() << __PRETTY_FUNCTION__;
- m_zoomLevel--;
- emit zoomLevelChanged(m_zoomLevel);
+ if (m_zoomLevel > MIN_VIEW_ZOOM_LEVEL) {
+ m_zoomLevel--;
+ emit zoomLevelChanged(m_zoomLevel);
- setZValues();
+ m_mapScene->setTilesDrawingLevels(m_zoomLevel);
- /// @todo START FETCHING TILES
- calculateTileGrid(m_sceneCoordinate);
+ getTiles(m_sceneCoordinate);
+ }
}
-void MapEngine::setZoomLevel(int zoomLevel)
+QString MapEngine::tilePath(int zoomLevel, int x, int y)
{
- m_zoomLevel = zoomLevel;
+ QString tilePathString(QString::number(zoomLevel) + "/");
+ tilePathString.append(QString::number(x) + "/");
+ tilePathString.append(QString::number(y));
+
+ return tilePathString;
}
-int MapEngine::getZoomLevel()
+QPoint MapEngine::convertSceneCoordinateToTileNumber(int zoomLevel, QPoint sceneCoordinate)
{
- return m_zoomLevel;
+ int pow = 1 << (MAX_MAP_ZOOM_LEVEL - zoomLevel);
+ int x = static_cast<int>(sceneCoordinate.x() / (TILE_SIZE_X*pow));
+ int y = static_cast<int>(sceneCoordinate.y() / (TILE_SIZE_Y*pow));
+
+ return QPoint(x, y);
}
-void MapEngine::setZValues()
+QPoint MapEngine::convertTileNumberToSceneCoordinate(int zoomLevel, QPoint tileNumber)
{
- //qDebug() << __PRETTY_FUNCTION__ << "m_zoomLevel:" << m_zoomLevel;
+ int pow = 1 << (MAX_MAP_ZOOM_LEVEL - zoomLevel);
+ int x = tileNumber.x() * TILE_SIZE_X * pow;
+ int y = tileNumber.y() * TILE_SIZE_Y * pow;
- QList<QGraphicsItem *> items = m_mapScene->items();
+ return QPoint(x, y);
+}
- for (int i = 0; i < items.size(); ++i) {
- MapTile *item = dynamic_cast<MapTile *>(items.at(i));
- if (item)
- item->setSceneLevel(m_zoomLevel);
- }
+QPoint MapEngine::convertLatLonToSceneCoordinate(QPointF latLonCoordinate)
+{
+ qDebug() << __PRETTY_FUNCTION__;
+
+ qreal longitude = latLonCoordinate.x();
+ qreal latitude = latLonCoordinate.y();
+
+ if ((longitude > MAX_LONGITUDE) || (longitude < MIN_LONGITUDE))
+ return QPoint(UNDEFINED, UNDEFINED);
+ if ((latitude > MAX_LATITUDE) || (latitude < MIN_LATITUDE))
+ return QPoint(UNDEFINED, UNDEFINED);
+
+ qreal z = static_cast<qreal>(1 << MAX_MAP_ZOOM_LEVEL);
+
+ qreal x = static_cast<qreal>((longitude + 180.0) / 360.0);
+ qreal y = static_cast<qreal>((1.0 - log(tan(latitude * M_PI / 180.0) + 1.0
+ / cos(latitude * M_PI / 180.0)) / M_PI) / 2.0);
+ return QPointF(x*z*TILE_SIZE_X, y*z*TILE_SIZE_Y).toPoint();
}