]> git.street.me.uk Git - andy/viking.git/blame - src/vikslippymapsource.c
Expose VikSlippyMapSource's private fields as properties
[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
4 * Copyright (C) Guilhem Bonnefille 2009 <guilhem.bonnefille@gmail.com>
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 */
19#ifdef HAVE_CONFIG_H
20#include "config.h"
21#endif
22
23#ifdef HAVE_MATH_H
24#include <math.h>
25#endif
26
27#include "globals.h"
8eb12ac6 28#include "vikslippymapsource.h"
e3a90009
GB
29
30static gboolean _coord_to_mapcoord ( VikMapSource *self, const VikCoord *src, gdouble xzoom, gdouble yzoom, MapCoord *dest );
31static void _mapcoord_to_center_coord ( VikMapSource *self, MapCoord *src, VikCoord *dest );
32static int _download ( VikMapSource *self, MapCoord *src, const gchar *dest_fn );
33
8eb12ac6
GB
34static gchar *_get_uri( VikSlippyMapSource *self, MapCoord *src );
35static gchar *_get_hostname( VikSlippyMapSource *self );
36static DownloadOptions *_get_download_options( VikSlippyMapSource *self );
e3a90009 37
8eb12ac6
GB
38/* FIXME Huge gruik */
39static DownloadOptions slippy_options = { NULL, 0, a_check_map_file };
40
41typedef struct _VikSlippyMapSourcePrivate VikSlippyMapSourcePrivate;
42struct _VikSlippyMapSourcePrivate
43{
44 gchar *hostname;
45 gchar *url;
46};
47
48#define VIK_SLIPPY_MAP_SOURCE_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), VIK_TYPE_SLIPPY_MAP_SOURCE, VikSlippyMapSourcePrivate))
49
4e53f3dc
GB
50/* properties */
51enum
52{
53 PROP_0,
54
55 PROP_HOSTNAME,
56 PROP_URL,
57};
58
8eb12ac6 59G_DEFINE_TYPE_EXTENDED (VikSlippyMapSource, vik_slippy_map_source, VIK_TYPE_MAP_SOURCE_DEFAULT, (GTypeFlags)0,);
e3a90009
GB
60
61static void
3a84e537 62vik_slippy_map_source_init (VikSlippyMapSource *self)
e3a90009 63{
8eb12ac6 64 /* initialize the object here */
31f3c5e7
GB
65 g_object_set (G_OBJECT (self),
66 "tilesize-x", 256,
67 "tilesize-y", 256,
68 "drawmode", VIK_VIEWPORT_DRAWMODE_MERCATOR,
69 NULL);
e3a90009
GB
70}
71
72static void
8eb12ac6 73vik_slippy_map_source_finalize (GObject *object)
e3a90009
GB
74{
75 /* TODO: Add deinitalization code here */
76
8eb12ac6 77 G_OBJECT_CLASS (vik_slippy_map_source_parent_class)->finalize (object);
e3a90009
GB
78}
79
4e53f3dc
GB
80static void
81vik_slippy_map_source_set_property (GObject *object,
82 guint property_id,
83 const GValue *value,
84 GParamSpec *pspec)
85{
86 VikSlippyMapSource *self = VIK_SLIPPY_MAP_SOURCE (object);
87 VikSlippyMapSourcePrivate *priv = VIK_SLIPPY_MAP_SOURCE_PRIVATE (self);
88
89 switch (property_id)
90 {
91 case PROP_HOSTNAME:
92 g_free (priv->hostname);
93 priv->hostname = g_value_dup_string (value);
94 break;
95
96 case PROP_URL:
97 g_free (priv->url);
98 priv->url = g_value_dup_string (value);
99 break;
100
101 default:
102 /* We don't have any other property... */
103 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
104 break;
105 }
106}
107
108static void
109vik_slippy_map_source_get_property (GObject *object,
110 guint property_id,
111 GValue *value,
112 GParamSpec *pspec)
113{
114 VikSlippyMapSource *self = VIK_SLIPPY_MAP_SOURCE (object);
115 VikSlippyMapSourcePrivate *priv = VIK_SLIPPY_MAP_SOURCE_PRIVATE (self);
116
117 switch (property_id)
118 {
119 case PROP_HOSTNAME:
120 g_value_set_string (value, priv->hostname);
121 break;
122
123 case PROP_URL:
124 g_value_set_string (value, priv->url);
125 break;
126
127 default:
128 /* We don't have any other property... */
129 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
130 break;
131 }
132}
133
e3a90009 134static void
8eb12ac6 135vik_slippy_map_source_class_init (VikSlippyMapSourceClass *klass)
e3a90009
GB
136{
137 GObjectClass* object_class = G_OBJECT_CLASS (klass);
138 VikMapSourceClass* parent_class = VIK_MAP_SOURCE_CLASS (klass);
4e53f3dc
GB
139 GParamSpec *pspec = NULL;
140
141 object_class->set_property = vik_slippy_map_source_set_property;
142 object_class->get_property = vik_slippy_map_source_get_property;
e3a90009
GB
143
144 /* Overiding methods */
145 parent_class->coord_to_mapcoord = _coord_to_mapcoord;
146 parent_class->mapcoord_to_center_coord = _mapcoord_to_center_coord;
147 parent_class->download = _download;
8eb12ac6
GB
148
149 /* Default implementation of methods */
150 klass->get_uri = _get_uri;
151 klass->get_hostname = _get_hostname;
152 klass->get_download_options = _get_download_options;
4e53f3dc
GB
153
154 pspec = g_param_spec_string ("hostname",
155 "Hostname",
156 "The hostname of the map server",
157 "<no-set>" /* default value */,
158 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
159 g_object_class_install_property (object_class, PROP_HOSTNAME, pspec);
160
161 pspec = g_param_spec_string ("url",
162 "URL",
163 "The template of the tiles' URL",
164 "<no-set>" /* default value */,
165 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
166 g_object_class_install_property (object_class, PROP_URL, pspec);
8eb12ac6
GB
167
168 g_type_class_add_private (klass, sizeof (VikSlippyMapSourcePrivate));
169
170 object_class->finalize = vik_slippy_map_source_finalize;
e3a90009
GB
171}
172
173/* 1 << (x) is like a 2**(x) */
174#define GZ(x) ((1<<x))
175
176static const gdouble scale_mpps[] = { GZ(0), GZ(1), GZ(2), GZ(3), GZ(4), GZ(5), GZ(6), GZ(7), GZ(8), GZ(9),
177 GZ(10), GZ(11), GZ(12), GZ(13), GZ(14), GZ(15), GZ(16), GZ(17) };
178
179static const gint num_scales = (sizeof(scale_mpps) / sizeof(scale_mpps[0]));
180
181#define ERROR_MARGIN 0.01
182static guint8 slippy_zoom ( gdouble mpp ) {
183 gint i;
184 for ( i = 0; i < num_scales; i++ ) {
185 if ( ABS(scale_mpps[i] - mpp) < ERROR_MARGIN )
186 return i;
187 }
188 return 255;
189}
190
191gchar *
8eb12ac6 192vik_slippy_map_source_get_uri( VikSlippyMapSource *self, MapCoord *src )
e3a90009 193{
8eb12ac6 194 VikSlippyMapSourceClass *klass;
e3a90009 195 g_return_val_if_fail (self != NULL, 0);
8eb12ac6
GB
196 g_return_val_if_fail (VIK_IS_SLIPPY_MAP_SOURCE (self), 0);
197 klass = VIK_SLIPPY_MAP_SOURCE_GET_CLASS(self);
e3a90009
GB
198
199 g_return_val_if_fail (klass->get_uri != NULL, 0);
200
201 return (*klass->get_uri)(self, src);
202}
203
204gchar *
8eb12ac6 205vik_slippy_map_source_get_hostname( VikSlippyMapSource *self )
e3a90009 206{
8eb12ac6 207 VikSlippyMapSourceClass *klass;
e3a90009 208 g_return_val_if_fail (self != NULL, 0);
8eb12ac6
GB
209 g_return_val_if_fail (VIK_IS_SLIPPY_MAP_SOURCE (self), 0);
210 klass = VIK_SLIPPY_MAP_SOURCE_GET_CLASS(self);
e3a90009
GB
211
212 g_return_val_if_fail (klass->get_hostname != NULL, 0);
213
214 return (*klass->get_hostname)(self);
215}
216
217DownloadOptions *
8eb12ac6 218vik_slippy_map_source_get_download_options( VikSlippyMapSource *self )
e3a90009 219{
8eb12ac6 220 VikSlippyMapSourceClass *klass;
e3a90009 221 g_return_val_if_fail (self != NULL, 0);
8eb12ac6
GB
222 g_return_val_if_fail (VIK_IS_SLIPPY_MAP_SOURCE (self), 0);
223 klass = VIK_SLIPPY_MAP_SOURCE_GET_CLASS(self);
e3a90009
GB
224
225 g_return_val_if_fail (klass->get_download_options != NULL, 0);
226
227 return (*klass->get_download_options)(self);
228}
229
230static gboolean
231_coord_to_mapcoord ( VikMapSource *self, const VikCoord *src, gdouble xzoom, gdouble yzoom, MapCoord *dest )
232{
233 g_assert ( src->mode == VIK_COORD_LATLON );
234
235 if ( xzoom != yzoom )
236 return FALSE;
237
238 dest->scale = slippy_zoom ( xzoom );
239 if ( dest->scale == 255 )
240 return FALSE;
241
242 dest->x = (src->east_west + 180) / 360 * GZ(17) / xzoom;
243 dest->y = (180 - MERCLAT(src->north_south)) / 360 * GZ(17) / xzoom;
244 dest->z = 0;
245
246 return TRUE;
247}
248
249static void
250_mapcoord_to_center_coord ( VikMapSource *self, MapCoord *src, VikCoord *dest )
251{
252 gdouble socalled_mpp = GZ(src->scale);
253 dest->mode = VIK_COORD_LATLON;
254 dest->east_west = ((src->x+0.5) / GZ(17) * socalled_mpp * 360) - 180;
255 dest->north_south = DEMERCLAT(180 - ((src->y+0.5) / GZ(17) * socalled_mpp * 360));
256}
257
258static int
259_download ( VikMapSource *self, MapCoord *src, const gchar *dest_fn )
260{
261 int res;
8eb12ac6
GB
262 gchar *uri = vik_slippy_map_source_get_uri(VIK_SLIPPY_MAP_SOURCE(self), src);
263 gchar *host = vik_slippy_map_source_get_hostname(VIK_SLIPPY_MAP_SOURCE(self));
264 DownloadOptions *options = vik_slippy_map_source_get_download_options(VIK_SLIPPY_MAP_SOURCE(self));
e3a90009
GB
265 res = a_http_download_get_url ( host, uri, dest_fn, options );
266 g_free ( uri );
267 g_free ( host );
268 return res;
269}
8eb12ac6
GB
270
271static gchar *
272_get_uri( VikSlippyMapSource *self, MapCoord *src )
273{
274 g_return_val_if_fail (VIK_IS_SLIPPY_MAP_SOURCE(self), NULL);
275
276 VikSlippyMapSourcePrivate *priv = VIK_SLIPPY_MAP_SOURCE_PRIVATE(self);
277 gchar *uri = g_strdup_printf (priv->url, 17 - src->scale, src->x, src->y);
278 return uri;
279}
280
281static gchar *
282_get_hostname( VikSlippyMapSource *self )
283{
284 g_return_val_if_fail (VIK_IS_SLIPPY_MAP_SOURCE(self), NULL);
285
286 VikSlippyMapSourcePrivate *priv = VIK_SLIPPY_MAP_SOURCE_PRIVATE(self);
287 return g_strdup( priv->hostname );
288}
289
290static DownloadOptions *
291_get_download_options( VikSlippyMapSource *self )
292{
293 g_return_val_if_fail (VIK_IS_SLIPPY_MAP_SOURCE(self), NULL);
294
295 return &slippy_options;
296}
297
298VikSlippyMapSource *
299vik_slippy_map_source_new_with_id (guint8 id, const gchar *hostname, const gchar *url)
300{
4e53f3dc
GB
301 return g_object_new(VIK_TYPE_SLIPPY_MAP_SOURCE,
302 "id", id, "hostname", hostname, "url", url, NULL);
8eb12ac6 303}