From: Rob Norris Date: Sat, 6 Sep 2014 12:09:38 +0000 (+0100) Subject: Add OSM Metatiles as a Map Type so one can read metatiles directly from disk. X-Git-Url: https://git.street.me.uk/andy/viking.git/commitdiff_plain/99f0d7dfeb78fda657342719efcc0d8b5963bf1e Add OSM Metatiles as a Map Type so one can read metatiles directly from disk. e.g. as generated by renderd/mod_tile or tirex. --- diff --git a/src/osm.c b/src/osm.c index 637d762b..120cfe48 100644 --- a/src/osm.c +++ b/src/osm.c @@ -3,7 +3,7 @@ * * Copyright (C) 2003-2005, Evan Battaglia * Copyright (C) 2007,2013, Guilhem Bonnefille - * Copyright (c) 2012, Rob Norris + * Copyright (c) 2012-2014, Rob Norris * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -140,6 +140,17 @@ void osm_init () { "is-mbtiles", TRUE, NULL)); + // NB no cache needed for this type!! + VikMapSource *metatiles_type = + VIK_MAP_SOURCE(g_object_new(VIK_TYPE_SLIPPY_MAP_SOURCE, + "id", 24, + "label", _("OSM Metatiles"), + // For using your own generated data assumed you know the license already! + "copyright", "© OpenStreetMap contributors", // probably + "use-direct-file-access", TRUE, + "is-osm-meta-tiles", TRUE, + NULL)); + maps_layer_register_map_source (mapquest_type); maps_layer_register_map_source (mapnik_type); maps_layer_register_map_source (cycle_type); @@ -147,6 +158,7 @@ void osm_init () { maps_layer_register_map_source (hot_type); maps_layer_register_map_source (direct_type); maps_layer_register_map_source (mbtiles_type); + maps_layer_register_map_source (metatiles_type); // Webtools VikWebtoolCenter *webtool = NULL; diff --git a/src/vikmapslayer.c b/src/vikmapslayer.c index ce3a5d70..f566521e 100644 --- a/src/vikmapslayer.c +++ b/src/vikmapslayer.c @@ -53,6 +53,7 @@ #include "preferences.h" #include "vikmapslayer.h" #include "icons/icons.h" +#include "metatile.h" #ifdef HAVE_SQLITE3_H #include "sqlite3.h" @@ -652,8 +653,8 @@ static void maps_layer_change_param ( GtkWidget *widget, ui_change_values values case PARAM_MAPTYPE: { // Get new value VikLayerParamData vlpd = a_uibuilder_widget_get_value ( widget, values[UI_CHG_PARAM] ); - // Is it *not* the OSM On Disk Tile Layout or the MBTiles type - gboolean sensitive = ( 21 != vlpd.u && 23 != vlpd.u); + // Is it *not* the OSM On Disk Tile Layout or the MBTiles type or the OSM Metatiles type + gboolean sensitive = ( 21 != vlpd.u && 23 != vlpd.u && 24 != vlpd.u ); GtkWidget **ww1 = values[UI_CHG_WIDGETS]; GtkWidget **ww2 = values[UI_CHG_LABELS]; GtkWidget *w1 = ww1[PARAM_ONLYMISSING]; @@ -964,6 +965,51 @@ static GdkPixbuf *get_mbtiles_pixbuf ( VikMapsLayer *vml, gint xx, gint yy, gint return pixbuf; } +static GdkPixbuf *get_pixbuf_from_metatile ( VikMapsLayer *vml, gint xx, gint yy, gint zz ) +{ + const int tile_max = METATILE_MAX_SIZE; + char err_msg[PATH_MAX]; + char *buf; + int len; + int compressed; + + buf = malloc(tile_max); + if (!buf) { + return NULL; + } + + err_msg[0] = 0; + len = metatile_read(vml->cache_dir, xx, yy, zz, buf, tile_max, &compressed, err_msg); + + if (len > 0) { + if (compressed) { + // Not handled yet - I don't think this is used often - so implement later if necessary + g_warning ( "Compressed metatiles not implemented:%s\n", __FUNCTION__); + return NULL; + } + + // Convert these buf bytes into a pixbuf via these streaming operations + GdkPixbuf *pixbuf = NULL; + + GInputStream *stream = g_memory_input_stream_new_from_data ( buf, len, NULL ); + GError *error = NULL; + pixbuf = gdk_pixbuf_new_from_stream ( stream, NULL, &error ); + if (error || (!pixbuf)) { + g_warning ( "%s: %s", __FUNCTION__, error->message ); + g_error_free ( error ); + } + g_input_stream_close ( stream, NULL, NULL ); + + free(buf); + return pixbuf; + } + else { + g_warning ( "FAILED:%s %s", __FUNCTION__, err_msg); + return NULL; + } +} + + static GdkPixbuf *pixbuf_apply_settings ( GdkPixbuf *pixbuf, VikMapsLayer *vml, MapCoord *mapcoord, gdouble xshrinkfactor, gdouble yshrinkfactor ) { // Apply alpha setting @@ -1030,6 +1076,11 @@ static GdkPixbuf *get_pixbuf( VikMapsLayer *vml, guint16 id, const gchar* mapnam // return now to avoid file tests that aren't appropriate for this map type return pixbuf; } + else if ( vik_map_source_is_osm_meta_tiles(map) ) { + pixbuf = get_pixbuf_from_metatile ( vml, mapcoord->x, mapcoord->y, (17 - mapcoord->scale) ); + pixbuf = pixbuf_apply_settings ( pixbuf, vml, mapcoord, xshrinkfactor, yshrinkfactor ); + return pixbuf; + } else get_filename ( vml->cache_dir, VIK_MAPS_CACHE_LAYOUT_OSM, id, NULL, mapcoord->scale, mapcoord->z, mapcoord->x, mapcoord->y, filename_buf, buf_len, @@ -1749,6 +1800,12 @@ static void maps_layer_tile_info ( VikMapsLayer *vml ) source = g_strdup ( _("Not available") ); #endif } + else if ( vik_map_source_is_osm_meta_tiles ( map ) ) { + char path[PATH_MAX]; + xyz_to_meta(path, sizeof(path), vml->cache_dir, ulm.x, ulm.y, 17-ulm.scale ); + source = g_strdup ( path ); + filename = g_strdup ( path ); + } else { guint max_path_len = strlen(vml->cache_dir) + 40; filename = g_malloc ( max_path_len * sizeof(char) ); diff --git a/src/vikmapsource.c b/src/vikmapsource.c index ef7d9f7b..23acbb0e 100644 --- a/src/vikmapsource.c +++ b/src/vikmapsource.c @@ -273,6 +273,25 @@ vik_map_source_is_mbtiles (VikMapSource * self) return (*klass->is_mbtiles)(self); } +/** + * vik_map_source_is_osm_meta_tiles: + * @self: the VikMapSource of interest. + * + * Treat the files as a pre generated data set directly by tirex or renderd + * tiledir/Z/[xxxxyyyy]/[xxxxyyyy]/[xxxxyyyy]/[xxxxyyyy]/[xxxxyyyy].meta + */ +gboolean vik_map_source_is_osm_meta_tiles (VikMapSource * self) +{ + VikMapSourceClass *klass; + g_return_val_if_fail (self != NULL, 0); + g_return_val_if_fail (VIK_IS_MAP_SOURCE (self), 0); + klass = VIK_MAP_SOURCE_GET_CLASS(self); + + g_return_val_if_fail (klass->is_osm_meta_tiles != NULL, 0); + + return (*klass->is_osm_meta_tiles)(self); +} + gboolean vik_map_source_supports_download_only_new (VikMapSource * self) { diff --git a/src/vikmapsource.h b/src/vikmapsource.h index c120e2e7..2b11ec16 100644 --- a/src/vikmapsource.h +++ b/src/vikmapsource.h @@ -57,6 +57,7 @@ struct _VikMapSourceClass VikViewportDrawMode (* get_drawmode) (VikMapSource * self); gboolean (* is_direct_file_access) (VikMapSource * self); gboolean (* is_mbtiles) (VikMapSource * self); + gboolean (* is_osm_meta_tiles) (VikMapSource * self); gboolean (* supports_download_only_new) (VikMapSource * self); guint8 (* get_zoom_min) (VikMapSource * self); guint8 (* get_zoom_max) (VikMapSource * self); @@ -88,6 +89,7 @@ guint16 vik_map_source_get_tilesize_y (VikMapSource * self); VikViewportDrawMode vik_map_source_get_drawmode (VikMapSource * self); gboolean vik_map_source_is_direct_file_access (VikMapSource * self); gboolean vik_map_source_is_mbtiles (VikMapSource * self); +gboolean vik_map_source_is_osm_meta_tiles (VikMapSource * self); gboolean vik_map_source_supports_download_only_new (VikMapSource * self); guint8 vik_map_source_get_zoom_min (VikMapSource * self); guint8 vik_map_source_get_zoom_max (VikMapSource * self); diff --git a/src/vikslippymapsource.c b/src/vikslippymapsource.c index a96ab930..53f3c849 100644 --- a/src/vikslippymapsource.c +++ b/src/vikslippymapsource.c @@ -58,6 +58,7 @@ static void _mapcoord_to_center_coord ( VikMapSource *self, MapCoord *src, VikCo static gboolean _is_direct_file_access (VikMapSource *self ); static gboolean _is_mbtiles (VikMapSource *self ); +static gboolean _is_osm_meta_tiles (VikMapSource *self ); static gboolean _supports_download_only_new (VikMapSource *self ); static guint8 _get_zoom_min(VikMapSource *self ); static guint8 _get_zoom_max(VikMapSource *self ); @@ -77,6 +78,7 @@ struct _VikSlippyMapSourcePrivate guint zoom_max; // TMS Zoom level: Often 18 for zoomed in. gboolean is_direct_file_access; gboolean is_mbtiles; + gboolean is_osm_meta_tiles; // http://wiki.openstreetmap.org/wiki/Meta_tiles as used by tirex or renderd // Mainly for ARCGIS Tile Server URL Layout // http://help.arcgis.com/EN/arcgisserver/10.0/apis/rest/tile.html gboolean switch_xy; }; @@ -98,6 +100,7 @@ enum PROP_USE_ETAG, PROP_IS_DIRECT_FILE_ACCESS, PROP_IS_MBTILES, + PROP_IS_OSM_META_TILES, PROP_SWITCH_XY, }; @@ -120,6 +123,7 @@ vik_slippy_map_source_init (VikSlippyMapSource *self) priv->options.use_etag = FALSE; priv->is_direct_file_access = FALSE; priv->is_mbtiles = FALSE; + priv->is_osm_meta_tiles = FALSE; priv->switch_xy = FALSE; g_object_set (G_OBJECT (self), @@ -199,6 +203,10 @@ vik_slippy_map_source_set_property (GObject *object, priv->is_mbtiles = g_value_get_boolean (value); break; + case PROP_IS_OSM_META_TILES: + priv->is_osm_meta_tiles = g_value_get_boolean (value); + break; + case PROP_SWITCH_XY: priv->switch_xy = g_value_get_boolean (value); break; @@ -261,6 +269,10 @@ vik_slippy_map_source_get_property (GObject *object, g_value_set_boolean (value, priv->is_mbtiles); break; + case PROP_IS_OSM_META_TILES: + g_value_set_boolean (value, priv->is_osm_meta_tiles); + break; + case PROP_SWITCH_XY: g_value_set_boolean (value, priv->switch_xy); break; @@ -288,6 +300,7 @@ vik_slippy_map_source_class_init (VikSlippyMapSourceClass *klass) grandparent_class->mapcoord_to_center_coord = _mapcoord_to_center_coord; grandparent_class->is_direct_file_access = _is_direct_file_access; grandparent_class->is_mbtiles = _is_mbtiles; + grandparent_class->is_osm_meta_tiles = _is_osm_meta_tiles; grandparent_class->supports_download_only_new = _supports_download_only_new; grandparent_class->get_zoom_min = _get_zoom_min; grandparent_class->get_zoom_max = _get_zoom_max; @@ -372,6 +385,13 @@ vik_slippy_map_source_class_init (VikSlippyMapSourceClass *klass) G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); g_object_class_install_property (object_class, PROP_IS_MBTILES, pspec); + pspec = g_param_spec_boolean ("is-osm-meta-tiles", + "Is in OSM Meta Tile format", + "Read from OSM Meta Tiles - Should be 'use-direct-file-access' as well", + FALSE /* default value */, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); + g_object_class_install_property (object_class, PROP_IS_OSM_META_TILES, pspec); + pspec = g_param_spec_boolean ("switch-xy", "Switch the order of x,y components in the URL", "Switch the order of x,y components in the URL (such as used by ARCGIS Tile Server", @@ -404,6 +424,17 @@ _is_mbtiles (VikMapSource *self) return priv->is_mbtiles; } +/** + * + */ +static gboolean +_is_osm_meta_tiles (VikMapSource *self) +{ + g_return_val_if_fail (VIK_IS_SLIPPY_MAP_SOURCE(self), FALSE); + VikSlippyMapSourcePrivate *priv = VIK_SLIPPY_MAP_SOURCE_PRIVATE(self); + return priv->is_osm_meta_tiles; +} + static gboolean _supports_download_only_new (VikMapSource *self) {