Modified MapView viewportUpdateMode.
[situare] / src / map / mapengine.h
index 70d7fed..d64a6a4 100644 (file)
- /*
-    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