2 Situare - A location system for Facebook
3 Copyright (C) 2010 Ixonos Plc. Authors:
5 Sami Rämö - sami.ramo@ixonos.com
6 Jussi Laitinen - jussi.laitinen@ixonos.com
8 Situare is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 version 2 as published by the Free Software Foundation.
12 Situare is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Situare; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
25 #include <QStringList>
28 #include <QHashIterator>
32 #include "mapengine.h"
38 MapEngine::MapEngine(QObject *parent)
41 , m_viewSize(QSize(973, 614))
42 , m_centerTile(QPoint(-1, -1))
44 m_mapScene = new MapScene(this);
46 m_mapFetcher = new MapFetcher(new QNetworkAccessManager(this), this);
47 connect(this, SIGNAL(fetchImage(QUrl)), m_mapFetcher, SLOT(fetchMapImage(QUrl)));
48 connect(m_mapFetcher, SIGNAL(mapImageReceived(QUrl,QPixmap)), this,
49 SLOT(mapImageReceived(QUrl, QPixmap)));
52 void MapEngine::init()
54 emit zoomLevelChanged(m_zoomLevel);
55 setViewLocation(QPointF(25.5000, 65.0000));
57 // // Fetch some map tiles for demo purposes
58 // for (int x=9351; x<=9354; x++) {
59 // for (int y=4261; y<=4264; y++) {
60 // QUrl url = buildURL(m_zoomLevel, QPoint(x, y));
61 // m_mapFetcher->fetchMapImage(url);
66 void MapEngine::setViewLocation(QPointF latLonCoordinate)
68 qDebug() << __PRETTY_FUNCTION__;
69 setLocation(convertLatLonToSceneCoordinate(latLonCoordinate));
72 QUrl MapEngine::buildURL(int zoomLevel, QPoint tileNumbers)
74 QString url = QString("http://tile.openstreetmap.org/mapnik/%1/%2/%3.png")
75 .arg(zoomLevel).arg(tileNumbers.x()).arg(tileNumbers.y());
80 void MapEngine::parseURL(const QUrl &url, int &zoom, int &x, int &y)
82 QString path = url.path();
83 QStringList pathParts = path.split("/", QString::SkipEmptyParts);
85 int size = pathParts.size();
90 zoom = (pathParts.at(size-3)).toInt();
91 x = (pathParts.at(size-2)).toInt();
92 QString yString = pathParts.at(size-1);
97 void MapEngine::mapImageReceived(const QUrl &url, const QPixmap &pixmap)
99 //qDebug() << __PRETTY_FUNCTION__;
101 if (mapTilesInScene.contains(url.toString())) {
106 parseURL(url, zoom, x, y);
108 MapTile *mapTile = new MapTile();
109 mapTile->setZoomLevel(zoom);
110 mapTile->setTileNumber(QPoint(x, y));
111 mapTile->setPixmap(pixmap);
113 mapTilesInScene.insert(url.toString(), mapTile);
114 m_mapScene->addMapTile(mapTile);
116 removeStackedTiles(mapTile);
118 qDebug() << "Tile count: " << m_mapScene->items().count();
122 QGraphicsScene* MapEngine::scene()
124 return dynamic_cast<QGraphicsScene *>(m_mapScene);
127 int MapEngine::tileMaxValue(int zoomLevel)
129 return (1 << zoomLevel) - 1;
132 QRect MapEngine::calculateGrid(QPointF sceneCoordinate)
134 QPoint tileCoordinate = convertSceneCoordinateToTileNumber(m_zoomLevel, sceneCoordinate);
135 int gridWidth = (m_viewSize.width()/TILE_SIZE_X + 1) + (GRID_PADDING*2);
136 int gridHeight = (m_viewSize.height()/TILE_SIZE_Y + 1) + (GRID_PADDING*2);
137 int topLeftX = tileCoordinate.x() - (gridWidth/2);
138 int topLeftY = tileCoordinate.y() - (gridHeight/2);
140 return QRect(topLeftX, topLeftY, gridWidth, gridHeight);
143 void MapEngine::setLocation(QPointF sceneCoordinate)
145 m_sceneCoordinate = sceneCoordinate;
146 emit locationChanged(m_sceneCoordinate);
148 if (centerTileChanged(sceneCoordinate)) {
149 calculateNewTiles(sceneCoordinate);
154 bool MapEngine::centerTileChanged(QPointF sceneCoordinate)
156 QPoint centerTile = convertSceneCoordinateToTileNumber(m_zoomLevel, sceneCoordinate);
157 QPoint temp = m_centerTile;
158 m_centerTile = centerTile;
160 return (centerTile != temp);
163 void MapEngine::calculateNewTiles(QPointF sceneCoordinate)
165 //qDebug() << __PRETTY_FUNCTION__;
167 viewGrid = calculateGrid(sceneCoordinate);
169 int topLeftX = viewGrid.topLeft().x();
170 int topLeftY = viewGrid.topLeft().y();
171 int bottomRightX = viewGrid.bottomRight().x();
172 int bottomRightY = viewGrid.bottomRight().y();
174 int tileMaxVal = tileMaxValue(m_zoomLevel);
176 for (int x = topLeftX; x <= bottomRightX; ++x) {
177 for (int y = topLeftY; y <= bottomRightY; ++y) {
184 else if (tileX > tileMaxVal)
189 else if (tileY > tileMaxVal)
192 QUrl url = buildURL(m_zoomLevel, QPoint(tileX, tileY));
194 if (!mapTilesInScene.contains(url.toString())) {
195 mapTilesInScene.insert(url.toString(), NULL);
196 emit fetchImage(url);
202 void MapEngine::removeOldTiles()
204 //qDebug() << __PRETTY_FUNCTION__;
206 QPointF topLeft = convertTileNumberToSceneCoordinate(m_zoomLevel, viewGrid.topLeft());
207 QPointF bottomRight = convertTileNumberToSceneCoordinate(m_zoomLevel, viewGrid.bottomRight() + QPoint(1, 1));
208 qreal width = bottomRight.x() - topLeft.x();
209 qreal height = bottomRight.y() - topLeft.y();
211 QList<QGraphicsItem *> viewTiles = m_mapScene->items(topLeft.x(), topLeft.y(), width, height, Qt::IntersectsItemShape);
212 QList<QGraphicsItem *> allTiles = m_mapScene->items();
214 foreach (QGraphicsItem *tile, viewTiles)
215 allTiles.removeOne(tile);
217 QHashIterator<QString, MapTile *> i(mapTilesInScene);
219 while (i.hasNext()) {
221 if (allTiles.contains(i.value())) {
222 MapTile *tile = i.value();
224 mapTilesInScene.remove(i.key());
225 m_mapScene->removeItem(tile);
232 void MapEngine::removeStackedTiles(MapTile *tile)
234 QList<QGraphicsItem *> collidingItems = tile->collidingItems(Qt::IntersectsItemBoundingRect);
236 foreach (QGraphicsItem *item, collidingItems) {
238 QRectF itemSceneRect = item->mapRectToScene(item->boundingRect());
239 QList<QGraphicsItem *> stackedItems = m_mapScene->items(itemSceneRect, Qt::IntersectsItemBoundingRect);
241 foreach(QGraphicsItem *stackedItem, stackedItems) {
242 if (item != stackedItem) {
243 MapTile *tmp = dynamic_cast<MapTile *>(item);
244 m_mapScene->removeItem(tmp);
245 mapTilesInScene.remove(buildURL(tmp->zoomLevel(), tmp->tileNumber()).toString());
251 void MapEngine::viewResized(const QSize &size)
254 //setLocation(m_sceneCoordinate);
255 calculateNewTiles(m_sceneCoordinate);
258 void MapEngine::zoomIn()
260 qDebug() << __PRETTY_FUNCTION__;
262 if (m_zoomLevel >= MAX_MAP_ZOOM_LEVEL)
266 emit zoomLevelChanged(m_zoomLevel);
269 calculateNewTiles(m_sceneCoordinate);
273 void MapEngine::zoomOut()
275 qDebug() << __PRETTY_FUNCTION__;
277 if (m_zoomLevel <= MIN_MAP_ZOOM_LEVEL)
281 emit zoomLevelChanged(m_zoomLevel);
284 calculateNewTiles(m_sceneCoordinate);
288 void MapEngine::setZValues()
290 //qDebug() << __PRETTY_FUNCTION__ << "m_zoomLevel:" << m_zoomLevel;
292 QList<QGraphicsItem *> items = m_mapScene->items();
294 for (int i = 0; i < items.size(); ++i) {
295 MapTile *item = dynamic_cast<MapTile *>(items.at(i));
297 item->setSceneLevel(m_zoomLevel);