- /*
- Situare - A location system for Facebook
- Copyright (C) 2010 Ixonos Plc. Authors:
+/*
+ Situare - A location system for Facebook
+ Copyright (C) 2010 Ixonos Plc. Authors:
- Sami Rämö - sami.ramo@ixonos.com
+ Sami Rämö - sami.ramo@ixonos.com
+ Jussi Laitinen - jussi.laitinen@ixonos.com
- Situare is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
+ Situare is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ version 2 as published by the Free Software Foundation.
- Situare is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Situare; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- USA.
- */
+ Situare is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ You should have received a copy of the GNU General Public License
+ along with Situare; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA.
+*/
#ifndef MAPENGINE_H
#define MAPENGINE_H
-#include <math.h>
+#include <QtCore>
-#include "mapview.h"
+#include "common.h"
+#include "mapfetcher.h"
#include "mapscene.h"
+#include "maptile.h"
-class MapEngine
+/**
+* @brief Map engine
+*
+* Logic for controlling map functionality. Does also include static methods for
+* converting coordinates.
+* @author Sami Rämö - sami.ramo (at) ixonos.com
+*/
+class MapEngine : public QObject
{
+ Q_OBJECT
public:
- MapEngine();
- MapEngine(MapView *mapView);
+ /**
+ * @brief Constructor
+ *
+ * @param parent Parent
+ */
+ MapEngine(QObject *parent = 0);
+
+ /**
+ * @brief MapEngine initializer
+ *
+ * Set initial location and zoom level for the engine. locationChanged and
+ * zoomLevelChanged signals are emitted, so init should be called after
+ * those signals are connected to MapView.
+ */
+ void init();
+
+ /**
+ * @brief Convert tile x & y numbers to MapScene coordinates
+ *
+ * @param zoomLevel Zoom level
+ * @param tileNumber x & y numbers of the tile
+ * @return QPoint MapScene coordinate
+ */
+
static QPoint convertTileNumberToSceneCoordinate(int zoomLevel, QPoint tileNumber)
{
- int x = tileNumber.x() * TILE_SIZE_X * pow(2, MAX_ZOOM_LEVEL - zoomLevel);
- int y = tileNumber.y() * TILE_SIZE_Y * pow(2, MAX_ZOOM_LEVEL - 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;
+
+ return QPoint(x, y);
+ }
+
+ static QPoint convertSceneCoordinateToTileNumber(int zoomLevel, QPointF sceneCoordinate)
+ {
+ 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);
}
+
+ /**
+ * @brief Getter for scene
+ *
+ * @return QGraphicsScene
+ */
+ QGraphicsScene* scene();
+
+ /**
+ * @brief Helper for setting view location based on latitude and longitude
+ * coordinates
+ *
+ * @param latLonCoordinate Latitude & longitude coordinates for location
+ */
void setViewLocation(QPointF latLonCoordinate);
-public:
- static const int TILE_SIZE_X = 256;
- static const int TILE_SIZE_Y = 256;
- static const int MAX_ZOOM_LEVEL = 18;
+ /**
+ * @brief Converts latitude, longitude and zoom to tile x, y values.
+ *
+ * @param latLonCoordinate latitude and longitude values
+ * @return QPoint tile x,y value
+ */
+ static QPointF convertLatLonToSceneCoordinate(QPointF latLonCoordinate)
+ {
+ /// @todo CREATE TEST CASE & CHECK CALCULATION
+ 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);
+ }
+
+public slots:
+ /**
+ * @brief Slot for setting current view location
+ *
+ * Emits locationChanged signal.
+ * @param sceneCoordinate Scene coordinates for new position
+ */
+ void setLocation(QPointF sceneCoordinate);
+
+ void viewResized(const QSize &size);
+
+private:
+ /**
+ * @brief Build URL for donwloading single map tile from OpenStreetMap tile server
+ *
+ * @param zoomLevel Zoom level
+ * @param tileNumbers Tile x & y numbers
+ * @return URL for the required tile
+ */
+ QUrl buildURL(int zoomLevel, QPoint tileNumbers);
+
+ /**
+ * @brief Parses given URL to zoom, x and y values. Parsed values are
+ * placed in variables given as parameters.
+ *
+ * @param url url to parse
+ * @param [out] zoom zoom variable
+ * @param [out] x x variable
+ * @param [out] y y variable
+ */
+ void parseURL(const QUrl &url, int &zoom, int &x, int &y);
+
+ /**
+ * @brief Set zValues for all tiles in the scene
+ *
+ * Drawing order of MapTiles, which has the zoom level higher than the current
+ * zoom level, is reversed and those MapTiles are mapped between lower level MapTiles.
+ * Example: If maximum zoom level is 18 and current view zoomlevel is 15, then
+ * the drawing order from top to bottom is 15, 16, 14, 17, 13, 18, 12, 11, 10, ...
+ */
+ void setZValues();
+
+ int tileMaxValue(int zoomLevel);
+
+ /**
+ * @brief Calculates grid of tile coordinates from current scene coordinate.
+ *
+ * Grid size is calculated from view size and scene's current center coordinate.
+ *
+ * @param sceneCoordinate scene's current center coordinate
+ * @return QRect grid of tile coordinates
+ */
+ QRect calculateGrid(QPointF sceneCoordinate);
+
+ /**
+ * @brief Calculate new tiles to fetch.
+ *
+ * @param sceneCoordinate scene's center coordinate
+ */
+ void calculateNewTiles(QPointF sceneCoordinate);
+
+ /**
+ * @brief Removes tiles which are out of view bounds.
+ */
+ void removeOldTiles();
+
+ /**
+ * @brief Checks if center tile has changed.
+ *
+ * @param sceneCoordinate scene's center coordinate
+ * @return bool true if center tile changed, false otherwise
+ */
+ bool centerTileChanged(QPointF sceneCoordinate);
+
+private slots:
+ /**
+ * @brief Slot for received map tile images
+ *
+ * Does add MapTile objects to MapScene. Zoom level and location is parsed from URL.
+ * @param url URL of the received image
+ * @param pixmap Received pixmap
+ */
+ void mapImageReceived(const QUrl &url, const QPixmap &pixmap);
+
+ /**
+ * @brief Slot for zooming in
+ *
+ */
+ void zoomIn();
+
+ /**
+ * @brief Slot for zooming out
+ *
+ */
+ void zoomOut();
+
+signals:
+ /**
+ * @brief Signal for view location change
+ *
+ * @param sceneCoordinate New scene coordinates
+ */
+ void locationChanged(QPointF sceneCoordinate);
+
+ /**
+ * @brief Signal for zoom level change
+ *
+ * @param newZoomLevel New zoom level
+ */
+ void zoomLevelChanged(int newZoomLevel);
+
+ void fetchImage(const QUrl &url);
+
+ void centerToSceneCoordinates(QPointF sceneCoordinate);
private:
- MapView *m_mapView;
- MapScene *m_mapScene;
+
+ MapScene *m_mapScene; ///< Scene for map tiles
+ MapFetcher *m_mapFetcher; ///< Fetcher for map tiles
+ int m_zoomLevel; ///< Current zoom level
+ QHash<QString, MapTile *> mapTilesInScene; ///< List of map tiles in map scene
+ QSize m_viewSize;
+ QPointF m_sceneCoordinate;
+ QQueue<QString> mapTilesInView;
+ QPoint m_centerTile;
+ QRect viewGrid;
};
#endif // MAPENGINE_H