]> git.street.me.uk Git - andy/viking.git/blame - src/vikslippymapsource.c
Refactor: TrackWaypoint sublayer menu callback functions.
[andy/viking.git] / src / vikslippymapsource.c
CommitLineData
e3a90009
GB
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2/*
3 * viking
a482007a 4 * Copyright (C) 2009, Guilhem Bonnefille <guilhem.bonnefille@gmail.com>
e3a90009
GB
5 *
6 * viking is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * viking is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
dfc4db8b
GB
19
20 /**
21 * SECTION:vikslippymapsource
22 * @short_description: the class for SlippyMap oriented map sources
23 *
24 * The #VikSlippyMapSource class handles slippy map oriented map sources.
25 * The related service is tile oriented, à la Google.
26 *
27 * The tiles are in 'google spherical mercator', which is
28 * basically a mercator projection that assumes a spherical earth.
29 * http://docs.openlayers.org/library/spherical_mercator.html
30 *
31 * Such service is also a type of TMS (Tile Map Service) as defined in
32 * OSGeo's wiki.
33 * http://wiki.osgeo.org/wiki/Tile_Map_Service_Specification
34 * But take care that the Y axis is inverted, ie the origin is at top-left
35 * corner.
36 * Following this specification, the protocol handled by this class
37 * follows the global-mercator profile.
38 *
39 * You can also find many interesting information on the OSM's wiki.
40 * http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
41 * http://wiki.openstreetmap.org/wiki/Setting_up_TMS
42 */
43
e3a90009
GB
44#ifdef HAVE_CONFIG_H
45#include "config.h"
46#endif
47
48#ifdef HAVE_MATH_H
49#include <math.h>
50#endif
51
52#include "globals.h"
8eb12ac6 53#include "vikslippymapsource.h"
e1dde2a6 54#include "maputils.h"
e3a90009
GB
55
56static gboolean _coord_to_mapcoord ( VikMapSource *self, const VikCoord *src, gdouble xzoom, gdouble yzoom, MapCoord *dest );
57static void _mapcoord_to_center_coord ( VikMapSource *self, MapCoord *src, VikCoord *dest );
f66ea3ec 58
2673b29d 59static gboolean _is_direct_file_access (VikMapSource *self );
0fb11294 60static gboolean _is_mbtiles (VikMapSource *self );
c81ded98 61static gboolean _supports_download_only_new (VikMapSource *self );
e3a90009 62
f66ea3ec
GB
63static gchar *_get_uri( VikMapSourceDefault *self, MapCoord *src );
64static gchar *_get_hostname( VikMapSourceDefault *self );
65static DownloadMapOptions *_get_download_options( VikMapSourceDefault *self );
e3a90009 66
8eb12ac6
GB
67typedef struct _VikSlippyMapSourcePrivate VikSlippyMapSourcePrivate;
68struct _VikSlippyMapSourcePrivate
69{
70 gchar *hostname;
71 gchar *url;
b529dc9c 72 DownloadMapOptions options;
2673b29d 73 gboolean is_direct_file_access;
0fb11294 74 gboolean is_mbtiles;
8eb12ac6
GB
75};
76
77#define VIK_SLIPPY_MAP_SOURCE_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), VIK_TYPE_SLIPPY_MAP_SOURCE, VikSlippyMapSourcePrivate))
78
4e53f3dc
GB
79/* properties */
80enum
81{
82 PROP_0,
83
84 PROP_HOSTNAME,
85 PROP_URL,
c395c6a5
GB
86 PROP_REFERER,
87 PROP_FOLLOW_LOCATION,
0f08bd0d 88 PROP_CHECK_FILE_SERVER_TIME,
05dbd9ba 89 PROP_USE_ETAG,
2673b29d 90 PROP_IS_DIRECT_FILE_ACCESS,
0fb11294 91 PROP_IS_MBTILES,
4e53f3dc
GB
92};
93
f6411015 94G_DEFINE_TYPE (VikSlippyMapSource, vik_slippy_map_source, VIK_TYPE_MAP_SOURCE_DEFAULT);
e3a90009
GB
95
96static void
3a84e537 97vik_slippy_map_source_init (VikSlippyMapSource *self)
e3a90009 98{
9cca9d93
GB
99 /* initialize the object here */
100 VikSlippyMapSourcePrivate *priv = VIK_SLIPPY_MAP_SOURCE_PRIVATE (self);
101
102 priv->hostname = NULL;
103 priv->url = NULL;
c395c6a5
GB
104 priv->options.referer = NULL;
105 priv->options.follow_location = 0;
106 priv->options.check_file = a_check_map_file;
6693f5f9 107 priv->options.check_file_server_time = FALSE;
2673b29d
RN
108 priv->options.use_etag = FALSE;
109 priv->is_direct_file_access = FALSE;
0fb11294 110 priv->is_mbtiles = FALSE;
9cca9d93
GB
111
112 g_object_set (G_OBJECT (self),
113 "tilesize-x", 256,
114 "tilesize-y", 256,
115 "drawmode", VIK_VIEWPORT_DRAWMODE_MERCATOR,
116 NULL);
e3a90009
GB
117}
118
119static void
8eb12ac6 120vik_slippy_map_source_finalize (GObject *object)
e3a90009 121{
9cca9d93
GB
122 VikSlippyMapSource *self = VIK_SLIPPY_MAP_SOURCE (object);
123 VikSlippyMapSourcePrivate *priv = VIK_SLIPPY_MAP_SOURCE_PRIVATE (self);
124
125 g_free (priv->hostname);
126 priv->hostname = NULL;
127 g_free (priv->url);
128 priv->url = NULL;
c395c6a5
GB
129 g_free (priv->options.referer);
130 priv->options.referer = NULL;
e3a90009 131
9cca9d93 132 G_OBJECT_CLASS (vik_slippy_map_source_parent_class)->finalize (object);
e3a90009
GB
133}
134
4e53f3dc
GB
135static void
136vik_slippy_map_source_set_property (GObject *object,
137 guint property_id,
138 const GValue *value,
139 GParamSpec *pspec)
140{
141 VikSlippyMapSource *self = VIK_SLIPPY_MAP_SOURCE (object);
142 VikSlippyMapSourcePrivate *priv = VIK_SLIPPY_MAP_SOURCE_PRIVATE (self);
143
144 switch (property_id)
145 {
146 case PROP_HOSTNAME:
147 g_free (priv->hostname);
148 priv->hostname = g_value_dup_string (value);
149 break;
150
151 case PROP_URL:
152 g_free (priv->url);
153 priv->url = g_value_dup_string (value);
154 break;
155
c395c6a5
GB
156 case PROP_REFERER:
157 g_free (priv->options.referer);
158 priv->options.referer = g_value_dup_string (value);
159 break;
160
161 case PROP_FOLLOW_LOCATION:
162 priv->options.follow_location = g_value_get_long (value);
163 break;
164
0f08bd0d 165 case PROP_CHECK_FILE_SERVER_TIME:
6693f5f9 166 priv->options.check_file_server_time = g_value_get_boolean (value);
0f08bd0d
GB
167 break;
168
05dbd9ba
JJ
169 case PROP_USE_ETAG:
170 priv->options.use_etag = g_value_get_boolean (value);
171 break;
172
2673b29d
RN
173 case PROP_IS_DIRECT_FILE_ACCESS:
174 priv->is_direct_file_access = g_value_get_boolean (value);
175 break;
176
0fb11294
RN
177 case PROP_IS_MBTILES:
178 priv->is_mbtiles = g_value_get_boolean (value);
179 break;
180
4e53f3dc
GB
181 default:
182 /* We don't have any other property... */
183 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
184 break;
185 }
186}
187
188static void
189vik_slippy_map_source_get_property (GObject *object,
190 guint property_id,
191 GValue *value,
192 GParamSpec *pspec)
193{
194 VikSlippyMapSource *self = VIK_SLIPPY_MAP_SOURCE (object);
195 VikSlippyMapSourcePrivate *priv = VIK_SLIPPY_MAP_SOURCE_PRIVATE (self);
196
197 switch (property_id)
198 {
199 case PROP_HOSTNAME:
200 g_value_set_string (value, priv->hostname);
201 break;
202
203 case PROP_URL:
204 g_value_set_string (value, priv->url);
205 break;
206
c395c6a5
GB
207 case PROP_REFERER:
208 g_value_set_string (value, priv->options.referer);
209 break;
210
211 case PROP_FOLLOW_LOCATION:
212 g_value_set_long (value, priv->options.follow_location);
213 break;
214
0f08bd0d 215 case PROP_CHECK_FILE_SERVER_TIME:
6693f5f9 216 g_value_set_boolean (value, priv->options.check_file_server_time);
0f08bd0d
GB
217 break;
218
05dbd9ba
JJ
219 case PROP_USE_ETAG:
220 g_value_set_boolean (value, priv->options.use_etag);
221 break;
222
2673b29d
RN
223 case PROP_IS_DIRECT_FILE_ACCESS:
224 g_value_set_boolean (value, priv->is_direct_file_access);
225 break;
226
0fb11294
RN
227 case PROP_IS_MBTILES:
228 g_value_set_boolean (value, priv->is_mbtiles);
229 break;
230
4e53f3dc
GB
231 default:
232 /* We don't have any other property... */
233 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
234 break;
235 }
236}
237
e3a90009 238static void
8eb12ac6 239vik_slippy_map_source_class_init (VikSlippyMapSourceClass *klass)
e3a90009
GB
240{
241 GObjectClass* object_class = G_OBJECT_CLASS (klass);
de674329 242 VikMapSourceClass* grandparent_class = VIK_MAP_SOURCE_CLASS (klass);
f66ea3ec 243 VikMapSourceDefaultClass* parent_class = VIK_MAP_SOURCE_DEFAULT_CLASS (klass);
4e53f3dc
GB
244 GParamSpec *pspec = NULL;
245
246 object_class->set_property = vik_slippy_map_source_set_property;
247 object_class->get_property = vik_slippy_map_source_get_property;
e3a90009
GB
248
249 /* Overiding methods */
de674329
RN
250 grandparent_class->coord_to_mapcoord = _coord_to_mapcoord;
251 grandparent_class->mapcoord_to_center_coord = _mapcoord_to_center_coord;
2673b29d 252 grandparent_class->is_direct_file_access = _is_direct_file_access;
0fb11294 253 grandparent_class->is_mbtiles = _is_mbtiles;
de674329 254 grandparent_class->supports_download_only_new = _supports_download_only_new;
f66ea3ec
GB
255
256 parent_class->get_uri = _get_uri;
257 parent_class->get_hostname = _get_hostname;
258 parent_class->get_download_options = _get_download_options;
4e53f3dc
GB
259
260 pspec = g_param_spec_string ("hostname",
261 "Hostname",
262 "The hostname of the map server",
263 "<no-set>" /* default value */,
9f58c4b4 264 G_PARAM_READWRITE);
4e53f3dc
GB
265 g_object_class_install_property (object_class, PROP_HOSTNAME, pspec);
266
267 pspec = g_param_spec_string ("url",
268 "URL",
269 "The template of the tiles' URL",
270 "<no-set>" /* default value */,
9f58c4b4 271 G_PARAM_READWRITE);
4e53f3dc 272 g_object_class_install_property (object_class, PROP_URL, pspec);
c395c6a5
GB
273
274 pspec = g_param_spec_string ("referer",
275 "Referer",
276 "The REFERER string to use in HTTP request",
277 NULL /* default value */,
278 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
279 g_object_class_install_property (object_class, PROP_REFERER, pspec);
8eb12ac6 280
c395c6a5
GB
281 pspec = g_param_spec_long ("follow-location",
282 "Follow location",
283 "Specifies the number of retries to follow a redirect while downloading a page",
284 0 /* minimum value */,
285 G_MAXLONG /* maximum value */,
286 0 /* default value */,
287 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
288 g_object_class_install_property (object_class, PROP_FOLLOW_LOCATION, pspec);
0f08bd0d 289
6693f5f9
GB
290 pspec = g_param_spec_boolean ("check-file-server-time",
291 "Check file server time",
292 "Age of current cache before redownloading tile",
293 FALSE /* default value */,
294 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
0f08bd0d 295 g_object_class_install_property (object_class, PROP_CHECK_FILE_SERVER_TIME, pspec);
c395c6a5 296
05dbd9ba
JJ
297 pspec = g_param_spec_boolean ("use-etag",
298 "Use etag values with server",
299 "Store etag in a file, and send it to server to check if we have the latest file",
300 FALSE /* default value */,
301 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
302 g_object_class_install_property (object_class, PROP_USE_ETAG, pspec);
303
2673b29d
RN
304 pspec = g_param_spec_boolean ("use-direct-file-access",
305 "Use direct file access",
306 "Use direct file access to OSM like tile images - no need for a webservice",
307 FALSE /* default value */,
308 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
309 g_object_class_install_property (object_class, PROP_IS_DIRECT_FILE_ACCESS, pspec);
310
0fb11294
RN
311 pspec = g_param_spec_boolean ("is-mbtiles",
312 "Is an SQL MBTiles File",
313 "Use an SQL MBTiles File for the tileset - no need for a webservice",
314 FALSE /* default value */,
315 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
316 g_object_class_install_property (object_class, PROP_IS_MBTILES, pspec);
8eb12ac6
GB
317 g_type_class_add_private (klass, sizeof (VikSlippyMapSourcePrivate));
318
319 object_class->finalize = vik_slippy_map_source_finalize;
e3a90009
GB
320}
321
cf65dac0 322static gboolean
2673b29d
RN
323_is_direct_file_access (VikMapSource *self)
324{
325 g_return_val_if_fail (VIK_IS_SLIPPY_MAP_SOURCE(self), FALSE);
326
327 VikSlippyMapSourcePrivate *priv = VIK_SLIPPY_MAP_SOURCE_PRIVATE(self);
328
329 return priv->is_direct_file_access;
330}
331
0fb11294
RN
332static gboolean
333_is_mbtiles (VikMapSource *self)
334{
335 g_return_val_if_fail (VIK_IS_SLIPPY_MAP_SOURCE(self), FALSE);
336
337 VikSlippyMapSourcePrivate *priv = VIK_SLIPPY_MAP_SOURCE_PRIVATE(self);
338
339 return priv->is_mbtiles;
340}
341
cf65dac0 342static gboolean
c81ded98 343_supports_download_only_new (VikMapSource *self)
0f08bd0d 344{
c81ded98 345 g_return_val_if_fail (VIK_IS_SLIPPY_MAP_SOURCE(self), FALSE);
0f08bd0d 346
c81ded98 347 VikSlippyMapSourcePrivate *priv = VIK_SLIPPY_MAP_SOURCE_PRIVATE(self);
0f08bd0d 348
c81ded98 349 return priv->options.check_file_server_time || priv->options.use_etag;
0f08bd0d 350}
f66ea3ec 351
e3a90009
GB
352static gboolean
353_coord_to_mapcoord ( VikMapSource *self, const VikCoord *src, gdouble xzoom, gdouble yzoom, MapCoord *dest )
354{
355 g_assert ( src->mode == VIK_COORD_LATLON );
356
357 if ( xzoom != yzoom )
358 return FALSE;
359
e1dde2a6 360 dest->scale = map_utils_mpp_to_scale ( xzoom );
e3a90009
GB
361 if ( dest->scale == 255 )
362 return FALSE;
363
e1dde2a6
RN
364 dest->x = (src->east_west + 180) / 360 * VIK_GZ(17) / xzoom;
365 dest->y = (180 - MERCLAT(src->north_south)) / 360 * VIK_GZ(17) / xzoom;
e3a90009
GB
366 dest->z = 0;
367
368 return TRUE;
369}
370
371static void
372_mapcoord_to_center_coord ( VikMapSource *self, MapCoord *src, VikCoord *dest )
373{
d1302dec
JJ
374 gdouble socalled_mpp;
375 if (src->scale >= 0)
e1dde2a6 376 socalled_mpp = VIK_GZ(src->scale);
d1302dec 377 else
e1dde2a6 378 socalled_mpp = 1.0/VIK_GZ(-src->scale);
e3a90009 379 dest->mode = VIK_COORD_LATLON;
e1dde2a6
RN
380 dest->east_west = ((src->x+0.5) / VIK_GZ(17) * socalled_mpp * 360) - 180;
381 dest->north_south = DEMERCLAT(180 - ((src->y+0.5) / VIK_GZ(17) * socalled_mpp * 360));
e3a90009
GB
382}
383
8eb12ac6 384static gchar *
f66ea3ec 385_get_uri( VikMapSourceDefault *self, MapCoord *src )
8eb12ac6
GB
386{
387 g_return_val_if_fail (VIK_IS_SLIPPY_MAP_SOURCE(self), NULL);
388
389 VikSlippyMapSourcePrivate *priv = VIK_SLIPPY_MAP_SOURCE_PRIVATE(self);
390 gchar *uri = g_strdup_printf (priv->url, 17 - src->scale, src->x, src->y);
391 return uri;
392}
393
394static gchar *
f66ea3ec 395_get_hostname( VikMapSourceDefault *self )
8eb12ac6
GB
396{
397 g_return_val_if_fail (VIK_IS_SLIPPY_MAP_SOURCE(self), NULL);
398
399 VikSlippyMapSourcePrivate *priv = VIK_SLIPPY_MAP_SOURCE_PRIVATE(self);
400 return g_strdup( priv->hostname );
401}
402
b529dc9c 403static DownloadMapOptions *
f66ea3ec 404_get_download_options( VikMapSourceDefault *self )
8eb12ac6
GB
405{
406 g_return_val_if_fail (VIK_IS_SLIPPY_MAP_SOURCE(self), NULL);
407
c395c6a5
GB
408 VikSlippyMapSourcePrivate *priv = VIK_SLIPPY_MAP_SOURCE_PRIVATE(self);
409 return &(priv->options);
8eb12ac6
GB
410}
411
412VikSlippyMapSource *
d7e495b2 413vik_slippy_map_source_new_with_id (guint16 id, const gchar *label, const gchar *hostname, const gchar *url)
8eb12ac6 414{
4e53f3dc 415 return g_object_new(VIK_TYPE_SLIPPY_MAP_SOURCE,
db03733a 416 "id", id, "label", label, "hostname", hostname, "url", url, NULL);
c395c6a5 417}