Merge branch 'map' of https://vcs.maemo.org/git/situare into map
[situare] / src / map / mapengine.h
1 /*
2    Situare - A location system for Facebook
3    Copyright (C) 2010  Ixonos Plc. Authors:
4
5        Sami Rämö - sami.ramo@ixonos.com
6        Jussi Laitinen - jussi.laitinen@ixonos.com
7
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.
11
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.
16
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,
20    USA.
21 */
22
23 #ifndef MAPENGINE_H
24 #define MAPENGINE_H
25
26 #include <QtCore>
27
28 #include "common.h"
29 #include "mapfetcher.h"
30 #include "mapscene.h"
31 #include "maptile.h"
32
33 /**
34 * @brief Map engine
35 *
36 * Logic for controlling map functionality. Does also include static methods for
37 * converting coordinates.
38 * @author Sami Rämö - sami.ramo (at) ixonos.com
39 */
40 class MapEngine : public QObject
41 {
42     Q_OBJECT
43 public:
44     /**
45     * @brief Constructor
46     *
47     * @param parent Parent
48     */
49     MapEngine(QObject *parent = 0);
50
51     /**
52     * @brief MapEngine initializer
53     *
54     * Set initial location and zoom level for the engine. locationChanged and
55     * zoomLevelChanged signals are emitted, so init should be called after
56     * those signals are connected to MapView.
57     */
58     void init();
59     
60     /**
61     * @brief Convert tile x & y numbers to MapScene coordinates
62     *
63     * @param zoomLevel Zoom level
64     * @param tileNumber x & y numbers of the tile
65     * @return QPoint MapScene coordinate
66     */
67
68     static QPoint convertTileNumberToSceneCoordinate(int zoomLevel, QPoint tileNumber)
69     {
70         int pow = 1 << (MAX_ZOOM_LEVEL - zoomLevel);
71         int x = tileNumber.x() * TILE_SIZE_X * pow;
72         int y = tileNumber.y() * TILE_SIZE_Y * pow;
73
74         return QPoint(x, y);
75     }
76
77     static QPoint convertSceneCoordinateToTileNumber(int zoomLevel, QPointF sceneCoordinate)
78     {
79         int pow = 1 << (MAX_ZOOM_LEVEL - zoomLevel);
80         int x = static_cast<int>(sceneCoordinate.x()) / (TILE_SIZE_X*pow);
81         int y = static_cast<int>(sceneCoordinate.y()) / (TILE_SIZE_Y*pow);
82
83         return QPoint(x, y);
84     }
85
86     /**
87     * @brief Getter for scene
88     *
89     * @return QGraphicsScene
90     */
91     QGraphicsScene* scene();
92
93     /**
94     * @brief Helper for setting view location based on latitude and longitude
95     * coordinates
96     *
97     * @param latLonCoordinate Latitude & longitude coordinates for location
98     */
99     void setViewLocation(QPointF latLonCoordinate);
100
101     /**
102     * @brief Converts latitude, longitude and zoom to tile x, y values.
103     *
104     * @param latLonCoordinate latitude and longitude values
105     * @return QPoint tile x,y value
106     */
107     static QPointF convertLatLonToSceneCoordinate(QPointF latLonCoordinate)
108     {
109         /// @todo CREATE TEST CASE & CHECK CALCULATION
110         qDebug() << __PRETTY_FUNCTION__;
111
112         qreal longitude = latLonCoordinate.x();
113         qreal latitude = latLonCoordinate.y();
114
115         if ((longitude > MAX_LONGITUDE) || (longitude < MIN_LONGITUDE))
116             return QPoint(UNDEFINED, UNDEFINED);
117         if ((latitude > MAX_LATITUDE) || (latitude < MIN_LATITUDE))
118             return QPoint(UNDEFINED, UNDEFINED);
119
120         qreal z = static_cast<qreal>(1 << MAX_ZOOM_LEVEL);
121
122         qreal x = static_cast<qreal>((longitude + 180.0) / 360.0);
123         qreal y = static_cast<qreal>((1.0 - log(tan(latitude * M_PI / 180.0) + 1.0
124                                     / cos(latitude * M_PI / 180.0)) / M_PI) / 2.0);
125
126         return QPointF(x*z*TILE_SIZE_X, y*z*TILE_SIZE_Y);
127     }
128
129     QRect calculateGrid(QPointF sceneCoordinate);
130
131 private:
132     /**
133     * @brief Build URL for donwloading single map tile from OpenStreetMap tile server
134     *
135     * @param zoomLevel Zoom level
136     * @param tileNumbers Tile x & y numbers
137     * @return URL for the required tile
138     */
139     QUrl buildURL(int zoomLevel, QPoint tileNumbers);
140
141     /**
142     * @brief Parses given URL to zoom, x and y values. Parsed values are
143     * placed in variables given as parameters.
144     *
145     * @param url url to parse
146     * @param [out] zoom zoom variable
147     * @param [out] x x variable
148     * @param [out] y y variable
149     */
150     void parseURL(const QUrl &url, int &zoom, int &x, int &y);
151
152     int tileMaxValue(int zoomLevel);
153
154
155 private slots:
156     /**
157     * @brief Slot for received map tile images
158     *
159     * Does add MapTile objects to MapScene. Zoom level and location is parsed from URL.
160     * @param url URL of the received image
161     * @param pixmap Received pixmap
162     */
163     void mapImageReceived(const QUrl &url, const QPixmap &pixmap);
164
165     /**
166     * @brief Slot for setting current view location
167     *
168     * Emits locationChanged signal.
169     * @param sceneCoordinate Scene coordinates for new position
170     */
171     void setLocation(QPointF sceneCoordinate);
172
173 signals:
174     /**
175     * @brief Signal for view location change
176     *
177     * @param sceneCoordinate New scene coordinates
178     */
179     void locationChanged(QPointF sceneCoordinate);
180
181     /**
182     * @brief Signal for zoom level change
183     *
184     * @param newZoomLevel New zoom level
185     */
186     void zoomLevelChanged(int newZoomLevel);
187
188     void fetchImage(const QUrl &url);
189
190     void centerToSceneCoordinates(QPointF sceneCoordinate);
191
192 private:
193     MapScene *m_mapScene; ///< Scene for map tiles
194     MapFetcher *m_mapFetcher; ///< Fetcher for map tiles
195     int m_zoomLevel; ///< Current zoom level
196     QHash<QString, MapTile *> mapTilesInScene;  ///< List of map tiles in map scene
197 };
198
199 #endif // MAPENGINE_H