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,
27 #include <QStringList>
30 #include <QHashIterator>
33 #include "mapengine.h"
36 MapEngine::MapEngine(QObject *parent)
38 , m_zoomLevel(DEFAULT_ZOOM_LEVEL)
39 , m_viewSize(QSize(DEFAULT_SCREEN_WIDTH, DEFAULT_SCREEN_HEIGHT))
40 , m_centerTile(QPoint(UNDEFINED, UNDEFINED))
42 m_mapScene = new MapScene(this);
44 m_mapFetcher = new MapFetcher(new QNetworkAccessManager(this), this);
45 connect(this, SIGNAL(fetchImage(QUrl)), m_mapFetcher, SLOT(fetchMapImage(QUrl)));
46 connect(m_mapFetcher, SIGNAL(mapImageReceived(QUrl,QPixmap)), this,
47 SLOT(mapImageReceived(QUrl, QPixmap)));
50 void MapEngine::init()
52 emit zoomLevelChanged(m_zoomLevel);
53 setViewLocation(QPointF(DEFAULT_LONGITUDE, DEFAULT_LATITUDE));
54 emit locationChanged(m_sceneCoordinate);
57 void MapEngine::setViewLocation(QPointF latLonCoordinate)
59 qDebug() << __PRETTY_FUNCTION__;
60 setLocation(convertLatLonToSceneCoordinate(latLonCoordinate));
61 emit locationChanged(m_sceneCoordinate);
64 QUrl MapEngine::buildURL(int zoomLevel, QPoint tileNumbers)
66 QString url = QString("http://tile.openstreetmap.org/mapnik/%1/%2/%3.png")
67 .arg(zoomLevel).arg(tileNumbers.x()).arg(tileNumbers.y());
72 void MapEngine::parseURL(const QUrl &url, int &zoom, int &x, int &y)
74 QString path = url.path();
75 QStringList pathParts = path.split("/", QString::SkipEmptyParts);
77 int size = pathParts.size();
82 zoom = (pathParts.at(size-3)).toInt();
83 x = (pathParts.at(size-2)).toInt();
84 QString yString = pathParts.at(size-1);
89 void MapEngine::mapImageReceived(const QUrl &url, const QPixmap &pixmap)
91 //qDebug() << __PRETTY_FUNCTION__;
93 if (!mapTilesInScene.contains(url.toString())) {
98 parseURL(url, zoom, x, y);
100 MapTile *mapTile = new MapTile();
101 mapTile->setZoomLevel(zoom);
102 mapTile->setTileNumber(QPoint(x, y));
103 mapTile->setPixmap(pixmap);
105 mapTilesInScene.insert(tilePath(zoom, x, y), mapTile);
106 m_mapScene->addMapTile(mapTile);
108 removeStackedTiles(mapTile);
112 QGraphicsScene* MapEngine::scene()
114 return dynamic_cast<QGraphicsScene *>(m_mapScene);
117 int MapEngine::tileMaxValue(int zoomLevel)
119 return (1 << zoomLevel) - 1;
122 QRect MapEngine::calculateGrid(QPoint sceneCoordinate)
124 QPoint tileCoordinate = convertSceneCoordinateToTileNumber(m_zoomLevel, sceneCoordinate);
125 int gridWidth = (m_viewSize.width()/TILE_SIZE_X + 1) + (GRID_PADDING*2);
126 int gridHeight = (m_viewSize.height()/TILE_SIZE_Y + 1) + (GRID_PADDING*2);
127 int topLeftX = tileCoordinate.x() - (gridWidth/2);
128 int topLeftY = tileCoordinate.y() - (gridHeight/2);
130 return QRect(topLeftX, topLeftY, gridWidth, gridHeight);
133 void MapEngine::setLocation(QPoint sceneCoordinate)
135 //qDebug() << __PRETTY_FUNCTION__;
137 m_sceneCoordinate = sceneCoordinate;
139 if (centerTileChanged(sceneCoordinate)) {
140 calculateNewTiles(sceneCoordinate);
145 bool MapEngine::centerTileChanged(QPoint sceneCoordinate)
147 QPoint centerTile = convertSceneCoordinateToTileNumber(m_zoomLevel, sceneCoordinate);
148 QPoint temp = m_centerTile;
149 m_centerTile = centerTile;
151 return (centerTile != temp);
154 void MapEngine::calculateNewTiles(QPoint sceneCoordinate)
156 //qDebug() << __PRETTY_FUNCTION__;
158 viewGrid = calculateGrid(sceneCoordinate);
160 int topLeftX = viewGrid.topLeft().x();
161 int topLeftY = viewGrid.topLeft().y();
162 int bottomRightX = viewGrid.bottomRight().x();
163 int bottomRightY = viewGrid.bottomRight().y();
165 int tileMaxVal = tileMaxValue(m_zoomLevel);
167 for (int x = topLeftX; x <= bottomRightX; ++x) {
168 for (int y = topLeftY; y <= bottomRightY; ++y) {
175 else if (tileX > tileMaxVal)
180 else if (tileY > tileMaxVal)
183 QUrl url = buildURL(m_zoomLevel, QPoint(tileX, tileY));
185 if (!mapTilesInScene.contains(tilePath(m_zoomLevel, tileX, tileY)))
186 emit fetchImage(url);
191 void MapEngine::removeOldTiles()
193 //qDebug() << __PRETTY_FUNCTION__;
195 QPointF topLeft = convertTileNumberToSceneCoordinate(m_zoomLevel, viewGrid.topLeft());
196 QPointF bottomRight = convertTileNumberToSceneCoordinate(m_zoomLevel, viewGrid.bottomRight() + QPoint(1, 1));
197 qreal width = bottomRight.x() - topLeft.x();
198 qreal height = bottomRight.y() - topLeft.y();
200 QList<QGraphicsItem *> viewTiles = m_mapScene->items(topLeft.x(), topLeft.y(), width, height, Qt::IntersectsItemShape);
201 QList<QGraphicsItem *> allTiles = m_mapScene->items();
203 foreach (QGraphicsItem *tile, viewTiles)
204 allTiles.removeOne(tile);
206 QHashIterator<QString, MapTile *> i(mapTilesInScene);
208 while (i.hasNext()) {
210 if (allTiles.contains(i.value()) && mapTilesInScene.contains(i.key())) {
211 MapTile *tile = i.value();
213 mapTilesInScene.remove(i.key());
214 m_mapScene->removeItem(tile);
221 void MapEngine::removeStackedTiles(MapTile *tile)
223 QList<QGraphicsItem *> collidingItems = tile->collidingItems(Qt::IntersectsItemBoundingRect);
225 foreach (QGraphicsItem *item, collidingItems) {
227 QRectF itemSceneRect = item->mapRectToScene(item->boundingRect());
228 QList<QGraphicsItem *> stackedItems = m_mapScene->items(itemSceneRect, Qt::IntersectsItemBoundingRect);
230 foreach(QGraphicsItem *stackedItem, stackedItems) {
231 if (item != stackedItem) {
232 MapTile *tmp = dynamic_cast<MapTile *>(item);
234 m_mapScene->removeItem(tmp);
235 mapTilesInScene.remove(tilePath(tmp->zoomLevel(), tmp->x(), tmp->y()));
243 void MapEngine::viewResized(const QSize &size)
246 calculateNewTiles(m_sceneCoordinate);
250 void MapEngine::zoomIn()
252 qDebug() << __PRETTY_FUNCTION__;
254 if (m_zoomLevel >= MAX_MAP_ZOOM_LEVEL)
258 emit zoomLevelChanged(m_zoomLevel);
263 void MapEngine::zoomOut()
265 qDebug() << __PRETTY_FUNCTION__;
267 if (m_zoomLevel <= MIN_MAP_ZOOM_LEVEL)
271 emit zoomLevelChanged(m_zoomLevel);
276 void MapEngine::setZValues()
278 //qDebug() << __PRETTY_FUNCTION__ << "m_zoomLevel:" << m_zoomLevel;
280 QList<QGraphicsItem *> items = m_mapScene->items();
282 for (int i = 0; i < items.size(); ++i) {
283 MapTile *item = dynamic_cast<MapTile *>(items.at(i));
285 item->setSceneLevel(m_zoomLevel);
290 QString MapEngine::tilePath(int zoomLevel, int x, int y)
292 QString tilePathString(QString::number(zoomLevel) + "/");
293 tilePathString.append(QString::number(x) + "/");
294 tilePathString.append(QString::number(y));
296 return tilePathString;