]> git.street.me.uk Git - andy/viking.git/commitdiff
Add OSM Metatiles as a Map Type so one can read metatiles directly from disk.
authorRob Norris <rw_norris@hotmail.com>
Sat, 6 Sep 2014 12:09:38 +0000 (13:09 +0100)
committerRob Norris <rw_norris@hotmail.com>
Sat, 13 Sep 2014 08:15:37 +0000 (09:15 +0100)
e.g. as generated by renderd/mod_tile or tirex.

src/osm.c
src/vikmapslayer.c
src/vikmapsource.c
src/vikmapsource.h
src/vikslippymapsource.c

index 637d762b76a0f9ee5b6a18f274d0c6d8d8e70982..120cfe487aab1bb83433c59d748c5f93b1be583c 100644 (file)
--- a/src/osm.c
+++ b/src/osm.c
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2003-2005, Evan Battaglia <gtoevan@gmx.net>
  * Copyright (C) 2007,2013, Guilhem Bonnefille <guilhem.bonnefille@gmail.com>
- * Copyright (c) 2012, Rob Norris <rw_norris@hotmail.com>
+ * Copyright (c) 2012-2014, Rob Norris <rw_norris@hotmail.com>
  *
  * 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;
index ce3a5d708625975952fb443bf9900590e862dcfc..f566521e48d38012b72125835ae141593e18068b 100644 (file)
@@ -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) );
index ef7d9f7be7fbfa8d296754ec7dbf069a771f2199..23acbb0e87268d8ae3e7a61e2b683918173a09fa 100644 (file)
@@ -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)
 {
index c120e2e7cc6f88b358d70b46ac92e11e36edf8d8..2b11ec1643cf4cc68b0a534f47f4c470b179df59 100644 (file)
@@ -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);
index a96ab930a855d02af0db6e59157ace73693f230f..53f3c849122cdf7eea1e6f4ffd43b273c5c1aa40 100644 (file)
@@ -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)
 {