]> git.street.me.uk Git - andy/viking.git/commitdiff
Add and use capability of defined area by min/max lat/lons for map types.
authorRob Norris <rw_norris@hotmail.com>
Mon, 15 Sep 2014 20:04:05 +0000 (21:04 +0100)
committerRob Norris <rw_norris@hotmail.com>
Mon, 15 Sep 2014 20:04:05 +0000 (21:04 +0100)
Various tile servers have differing coverage extents by area.
Thus don't need to generate download requests that we know are going to fail.
The area levels can be customized for new maps.

NB this only caters for a simple rectangular bounding box, rather then bounding polygon.
All built in maps have world wide coverage.
Only the extension configured map CalTopo is effected limited area to the US.

data/maps.xml
doc/examples/maps.xml
help/C/viking.xml
help/viking.xml
src/vikmapslayer.c
src/vikmapsource.c
src/vikmapsource.h
src/vikslippymapsource.c

index 0a2a5ebc1566377d2f8207246762db2d82830cc3..944a7e0f0dbfbd9846066f869a14e04cdd3d46eb 100644 (file)
     <property name="url">/caltopo/topo/%d/%d/%d.png?v=1</property>
     <property name="zoom-min">0</property>
     <property name="zoom-max">16</property>
+    <property name="lat-min">18.76</property>
+    <property name="lat-max">71.56</property>
+    <property name="lon-min">-178.0</property>
+    <property name="lon-max">-66.95</property>
     <property name="copyright">CalTopo Terms of Use</property>
     <property name="license">CalTopo Terms of Use</property>
     <property name="license-url">http://caltopo.com/</property>
index 3605c4d4a0cfa2b3b9822a69718cd96ceecd23be..0d6f9d763ee403eb580692d35218a13a85801c9b 100644 (file)
     <property name="license">ArcGIS Specific</property>
     <property name="license-url">http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer</property>
   </object>
+
+  <!-- An example with zoom and area limits - UK Only -->
+  <object>
+    <object class="VikSlippyMapSource">
+    <property name="label">OS NPE</property>
+    <property name="hostname">ooc.openstreetmap.org</property>
+    <property name="url">/npe/%d/%d/%d.png</property>
+    <property name="id">245</property>
+    <property name="name">NPE</property>
+    <property name="file-extension">.png</property>
+    <property name="zoom-min">7</property>
+    <property name="zoom-max">18</property>
+    <property name="lat-min">49.8</property>
+    <property name="lat-max">55.8</property>
+    <property name="lon-min">-5.8</property>
+    <property name="lon-max">1.9</property>
+  </object>
 </objects>
index 3e04a9d84b7a52a4291da365c96c7d94f3799a5d..9a62f2f950f42b05ddab10847e9a6f29ad733cf8 100644 (file)
@@ -2885,6 +2885,22 @@ Accept: */*
                  <para>See <ulink url="http://wiki.openstreetmap.org/wiki/Zoom_levels">Zoom Levels</ulink></para>
               </listitem>
             </varlistentry>
+            <varlistentry>
+              <term>lat-min (optional)</term>
+              <listitem><para>The minimum latitude value in degrees supported by the tile server. The Default is -90 degrees if not specified.</para></listitem>
+            </varlistentry>
+            <varlistentry>
+              <term>lat-max (optional)</term>
+              <listitem><para>The maximum latitude value in degrees supported by the tile server. The Default is 90 degrees if not specified.</para></listitem>
+            </varlistentry>
+            <varlistentry>
+              <term>lon-min (optional)</term>
+              <listitem><para>The minimum longitude value in degrees supported by the tile server. The Default is -180 degrees if not specified.</para></listitem>
+            </varlistentry>
+            <varlistentry>
+              <term>lon-max (optional)</term>
+              <listitem><para>The maximum longitude value in degrees supported by the tile server. The Default is 180 degrees if not specified.</para></listitem>
+            </varlistentry>
             <varlistentry>
               <term>file-extension (optional)</term>
               <listitem>
index ecd7e81705f85ce3c8f72a2374fae53384e340c9..106280a4c921b0a06c3fb7d66a6761337d83df17 100644 (file)
@@ -222,6 +222,22 @@ and docbook-xsl in your Build-Depends control field.
                  <para>See <ulink url="http://wiki.openstreetmap.org/wiki/Zoom_levels">Zoom Levels</ulink></para>
               </listitem>
             </varlistentry>
+            <varlistentry>
+              <term>lat-min (optional)</term>
+              <listitem><para>The minimum latitude value in degrees supported by the tile server. The Default is -90 degrees if not specified.</para></listitem>
+            </varlistentry>
+            <varlistentry>
+              <term>lat-max (optional)</term>
+              <listitem><para>The maximum latitude value in degrees supported by the tile server. The Default is 90 degrees if not specified.</para></listitem>
+            </varlistentry>
+            <varlistentry>
+              <term>lon-min (optional)</term>
+              <listitem><para>The minimum longitude value in degrees supported by the tile server. The Default is -180 degrees if not specified.</para></listitem>
+            </varlistentry>
+            <varlistentry>
+              <term>lon-max (optional)</term>
+              <listitem><para>The maximum longitude value in degrees supported by the tile server. The Default is 180 degrees if not specified.</para></listitem>
+            </varlistentry>
             <varlistentry>
               <term>file-extension (optional)</term>
               <listitem>
index f566521e48d38012b72125835ae141593e18068b..a352102a93b5d3bea2ba744bb788e55e13ab1971 100644 (file)
@@ -1419,114 +1419,139 @@ static void weak_ref_cb(gpointer ptr, GObject * dead_vml)
   g_mutex_unlock(mdi->mutex);
 }
 
+static gboolean is_in_area (VikMapSource *map, MapCoord mc)
+{
+  VikCoord vc;
+  vik_map_source_mapcoord_to_center_coord ( map, &mc, &vc );
+
+  struct LatLon tl;
+  tl.lat = vik_map_source_get_lat_max(map);
+  tl.lon = vik_map_source_get_lon_min(map);
+  struct LatLon br;
+  br.lat = vik_map_source_get_lat_min(map);
+  br.lon = vik_map_source_get_lon_max(map);
+  VikCoord vctl;
+  vik_coord_load_from_latlon (&vctl, VIK_COORD_LATLON, &tl);
+  VikCoord vcbr;
+  vik_coord_load_from_latlon (&vcbr, VIK_COORD_LATLON, &br);
+
+  return vik_coord_inside ( &vc, &vctl, &vcbr );
+}
+
 static int map_download_thread ( MapDownloadInfo *mdi, gpointer threaddata )
 {
   void *handle = vik_map_source_download_handle_init(MAPS_LAYER_NTH_TYPE(mdi->maptype));
   guint donemaps = 0;
+  MapCoord mcoord = mdi->mapcoord;
   gint x, y;
   for ( x = mdi->x0; x <= mdi->xf; x++ )
   {
+    mcoord.x = x;
     for ( y = mdi->y0; y <= mdi->yf; y++ )
     {
-      gboolean remove_mem_cache = FALSE;
-      gboolean need_download = FALSE;
-
-      get_filename ( mdi->cache_dir, mdi->cache_layout,
-                     vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(mdi->maptype)),
-                     vik_map_source_get_name(MAPS_LAYER_NTH_TYPE(mdi->maptype)),
-                     mdi->mapcoord.scale, mdi->mapcoord.z, x, y, mdi->filename_buf, mdi->maxlen,
-                     vik_map_source_get_file_extension(MAPS_LAYER_NTH_TYPE(mdi->maptype)) );
-
-      donemaps++;
-      int res = a_background_thread_progress ( threaddata, ((gdouble)donemaps) / mdi->mapstoget ); /* this also calls testcancel */
-      if (res != 0) {
-        vik_map_source_download_handle_cleanup(MAPS_LAYER_NTH_TYPE(mdi->maptype), handle);
-        return -1;
-      }
+      mcoord.y = y;
+      // Only attempt to download a tile from supported areas
+      if ( is_in_area ( MAPS_LAYER_NTH_TYPE(mdi->maptype), mcoord ) )
+      {
+        gboolean remove_mem_cache = FALSE;
+        gboolean need_download = FALSE;
 
-      if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE ) {
-        need_download = TRUE;
-        remove_mem_cache = TRUE;
+        get_filename ( mdi->cache_dir, mdi->cache_layout,
+                       vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(mdi->maptype)),
+                       vik_map_source_get_name(MAPS_LAYER_NTH_TYPE(mdi->maptype)),
+                       mdi->mapcoord.scale, mdi->mapcoord.z, x, y, mdi->filename_buf, mdi->maxlen,
+                       vik_map_source_get_file_extension(MAPS_LAYER_NTH_TYPE(mdi->maptype)) );
+
+        donemaps++;
+        int res = a_background_thread_progress ( threaddata, ((gdouble)donemaps) / mdi->mapstoget ); /* this also calls testcancel */
+        if (res != 0) {
+          vik_map_source_download_handle_cleanup(MAPS_LAYER_NTH_TYPE(mdi->maptype), handle);
+          return -1;
+        }
 
-      } else {  /* in case map file already exists */
-        switch (mdi->redownload) {
-          case REDOWNLOAD_NONE:
-            continue;
+        if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE ) {
+          need_download = TRUE;
+          remove_mem_cache = TRUE;
 
-          case REDOWNLOAD_BAD:
-          {
-            /* see if this one is bad or what */
-            GError *gx = NULL;
-            GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file ( mdi->filename_buf, &gx );
-            if (gx || (!pixbuf)) {
-              g_remove ( mdi->filename_buf );
-              need_download = TRUE;
-              remove_mem_cache = TRUE;
-              g_error_free ( gx );
+        } else {  /* in case map file already exists */
+          switch (mdi->redownload) {
+            case REDOWNLOAD_NONE:
+              continue;
+
+            case REDOWNLOAD_BAD:
+            {
+              /* see if this one is bad or what */
+              GError *gx = NULL;
+              GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file ( mdi->filename_buf, &gx );
+              if (gx || (!pixbuf)) {
+                g_remove ( mdi->filename_buf );
+                need_download = TRUE;
+                remove_mem_cache = TRUE;
+                g_error_free ( gx );
 
-            } else {
-              g_object_unref ( pixbuf );
+              } else {
+                g_object_unref ( pixbuf );
+              }
+              break;
             }
-            break;
-          }
 
-          case REDOWNLOAD_NEW:
-            need_download = TRUE;
-            remove_mem_cache = TRUE;
-            break;
+            case REDOWNLOAD_NEW:
+              need_download = TRUE;
+              remove_mem_cache = TRUE;
+              break;
 
-          case REDOWNLOAD_ALL:
-            /* FIXME: need a better way than to erase file in case of server/network problem */
-            g_remove ( mdi->filename_buf );
-            need_download = TRUE;
-            remove_mem_cache = TRUE;
-            break;
+            case REDOWNLOAD_ALL:
+              /* FIXME: need a better way than to erase file in case of server/network problem */
+              g_remove ( mdi->filename_buf );
+              need_download = TRUE;
+              remove_mem_cache = TRUE;
+              break;
 
-          case DOWNLOAD_OR_REFRESH:
-            remove_mem_cache = TRUE;
-            break;
+            case DOWNLOAD_OR_REFRESH:
+              remove_mem_cache = TRUE;
+              break;
 
-          default:
-            g_warning ( "redownload state %d unknown\n", mdi->redownload);
+            default:
+              g_warning ( "redownload state %d unknown\n", mdi->redownload);
+          }
         }
-      }
 
-      mdi->mapcoord.x = x; mdi->mapcoord.y = y;
-
-      if (need_download) {
-        DownloadResult_t dr = vik_map_source_download( MAPS_LAYER_NTH_TYPE(mdi->maptype), &(mdi->mapcoord), mdi->filename_buf, handle);
-        switch ( dr ) {
-          case DOWNLOAD_HTTP_ERROR:
-          case DOWNLOAD_CONTENT_ERROR: {
-            // TODO: ?? count up the number of download errors somehow...
-            gchar* msg = g_strdup_printf ( "%s: %s", vik_maps_layer_get_map_label (mdi->vml), _("Failed to download tile") );
-            vik_window_statusbar_update ( (VikWindow*)VIK_GTK_WINDOW_FROM_LAYER(mdi->vml), msg, VIK_STATUSBAR_INFO );
-            g_free (msg);
-            break;
-          }
-          case DOWNLOAD_FILE_WRITE_ERROR: {
-            gchar* msg = g_strdup_printf ( "%s: %s", vik_maps_layer_get_map_label (mdi->vml), _("Unable to save tile") );
-            vik_window_statusbar_update ( (VikWindow*)VIK_GTK_WINDOW_FROM_LAYER(mdi->vml), msg, VIK_STATUSBAR_INFO );
-            g_free (msg);
-            break;
+        mdi->mapcoord.x = x; mdi->mapcoord.y = y;
+
+        if (need_download) {
+          DownloadResult_t dr = vik_map_source_download( MAPS_LAYER_NTH_TYPE(mdi->maptype), &(mdi->mapcoord), mdi->filename_buf, handle);
+          switch ( dr ) {
+            case DOWNLOAD_HTTP_ERROR:
+            case DOWNLOAD_CONTENT_ERROR: {
+              // TODO: ?? count up the number of download errors somehow...
+              gchar* msg = g_strdup_printf ( "%s: %s", vik_maps_layer_get_map_label (mdi->vml), _("Failed to download tile") );
+              vik_window_statusbar_update ( (VikWindow*)VIK_GTK_WINDOW_FROM_LAYER(mdi->vml), msg, VIK_STATUSBAR_INFO );
+              g_free (msg);
+              break;
+            }
+            case DOWNLOAD_FILE_WRITE_ERROR: {
+              gchar* msg = g_strdup_printf ( "%s: %s", vik_maps_layer_get_map_label (mdi->vml), _("Unable to save tile") );
+              vik_window_statusbar_update ( (VikWindow*)VIK_GTK_WINDOW_FROM_LAYER(mdi->vml), msg, VIK_STATUSBAR_INFO );
+              g_free (msg);
+              break;
+            }
+            case DOWNLOAD_SUCCESS:
+            case DOWNLOAD_NOT_REQUIRED:
+            default:
+              break;
           }
-          case DOWNLOAD_SUCCESS:
-          case DOWNLOAD_NOT_REQUIRED:
-          default:
-            break;
         }
-      }
 
-      g_mutex_lock(mdi->mutex);
-      if (remove_mem_cache)
-          a_mapcache_remove_all_shrinkfactors ( x, y, mdi->mapcoord.z, vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(mdi->maptype)), mdi->mapcoord.scale );
-      if (mdi->refresh_display && mdi->map_layer_alive) {
-        /* TODO: check if it's on visible area */
-        vik_layer_emit_update ( VIK_LAYER(mdi->vml) ); // NB update display from background
+        g_mutex_lock(mdi->mutex);
+        if (remove_mem_cache)
+            a_mapcache_remove_all_shrinkfactors ( x, y, mdi->mapcoord.z, vik_map_source_get_uniq_id(MAPS_LAYER_NTH_TYPE(mdi->maptype)), mdi->mapcoord.scale );
+        if (mdi->refresh_display && mdi->map_layer_alive) {
+          /* TODO: check if it's on visible area */
+          vik_layer_emit_update ( VIK_LAYER(mdi->vml) ); // NB update display from background
+        }
+        g_mutex_unlock(mdi->mutex);
+        mdi->mapcoord.x = mdi->mapcoord.y = 0; /* we're temporarily between downloads */
       }
-      g_mutex_unlock(mdi->mutex);
-      mdi->mapcoord.x = mdi->mapcoord.y = 0; /* we're temporarily between downloads */
-
     }
   }
   vik_map_source_download_handle_cleanup(MAPS_LAYER_NTH_TYPE(mdi->maptype), handle);
@@ -1593,21 +1618,29 @@ static void start_download_thread ( VikMapsLayer *vml, VikViewport *vvp, const V
 
     mdi->mapstoget = 0;
 
+    MapCoord mcoord = mdi->mapcoord;
+
     if ( mdi->redownload ) {
       mdi->mapstoget = (mdi->xf - mdi->x0 + 1) * (mdi->yf - mdi->y0 + 1);
     } else {
       /* calculate how many we need */
       for ( a = mdi->x0; a <= mdi->xf; a++ )
       {
+        mcoord.x = a;
         for ( b = mdi->y0; b <= mdi->yf; b++ )
         {
-          get_filename ( mdi->cache_dir, mdi->cache_layout,
-                         vik_map_source_get_uniq_id(map),
-                         vik_map_source_get_name(map),
-                         ulm.scale, ulm.z, a, b, mdi->filename_buf, mdi->maxlen,
-                         vik_map_source_get_file_extension(map) );
-          if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE )
-            mdi->mapstoget++;
+          mcoord.y = b;
+          // Only count tiles from supported areas
+          if ( is_in_area (map, mcoord) )
+          {
+            get_filename ( mdi->cache_dir, mdi->cache_layout,
+                           vik_map_source_get_uniq_id(map),
+                           vik_map_source_get_name(map),
+                           ulm.scale, ulm.z, a, b, mdi->filename_buf, mdi->maxlen,
+                           vik_map_source_get_file_extension(map) );
+            if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE )
+              mdi->mapstoget++;
+          }
         }
       }
     }
@@ -1688,15 +1721,22 @@ static void maps_layer_download_section ( VikMapsLayer *vml, VikViewport *vvp, V
 
   mdi->mapstoget = 0;
 
+  MapCoord mcoord = mdi->mapcoord;
+
   for (i = mdi->x0; i <= mdi->xf; i++) {
+    mcoord.x = i;
     for (j = mdi->y0; j <= mdi->yf; j++) {
-      get_filename ( mdi->cache_dir, mdi->cache_layout,
-                     vik_map_source_get_uniq_id(map),
-                     vik_map_source_get_name(map),
-                     ulm.scale, ulm.z, i, j, mdi->filename_buf, mdi->maxlen,
-                     vik_map_source_get_file_extension(map) );
-      if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE )
-            mdi->mapstoget++;
+      mcoord.y = j;
+      // Only count tiles from supported areas
+      if ( is_in_area (map, mcoord) ) {
+        get_filename ( mdi->cache_dir, mdi->cache_layout,
+                       vik_map_source_get_uniq_id(map),
+                       vik_map_source_get_name(map),
+                       ulm.scale, ulm.z, i, j, mdi->filename_buf, mdi->maxlen,
+                       vik_map_source_get_file_extension(map) );
+        if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE )
+              mdi->mapstoget++;
+      }
     }
   }
 
@@ -2046,33 +2086,39 @@ static gint maps_layer_how_many_maps ( VikMapsLayer *vml, VikViewport *vvp, VikC
   }
   else {
     /* calculate how many we need */
+    MapCoord mcoord = mdi->mapcoord;
     for (i = mdi->x0; i <= mdi->xf; i++) {
+      mcoord.x = i;
       for (j = mdi->y0; j <= mdi->yf; j++) {
-        get_filename ( mdi->cache_dir, mdi->cache_layout,
-                       vik_map_source_get_uniq_id(map),
-                       vik_map_source_get_name(map),
-                       ulm.scale, ulm.z, i, j, mdi->filename_buf, mdi->maxlen,
-                       vik_map_source_get_file_extension(map) );
-        if ( mdi->redownload == REDOWNLOAD_NEW ) {
-          // Assume the worst - always a new file
-          // Absolute value would requires server lookup - but that is too slow
-          mdi->mapstoget++;
-        }
-        else {
-          if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE ) {
-            // Missing
+        mcoord.y = j;
+        // Only count tiles from supported areas
+        if ( is_in_area ( map, mcoord ) ) {
+          get_filename ( mdi->cache_dir, mdi->cache_layout,
+                         vik_map_source_get_uniq_id(map),
+                         vik_map_source_get_name(map),
+                         ulm.scale, ulm.z, i, j, mdi->filename_buf, mdi->maxlen,
+                         vik_map_source_get_file_extension(map) );
+          if ( mdi->redownload == REDOWNLOAD_NEW ) {
+            // Assume the worst - always a new file
+            // Absolute value would require a server lookup - but that is too slow
             mdi->mapstoget++;
           }
           else {
-            if ( mdi->redownload == REDOWNLOAD_BAD ) {
-              /* see if this one is bad or what */
-              GError *gx = NULL;
-              GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file ( mdi->filename_buf, &gx );
-              if (gx || (!pixbuf)) {
-                mdi->mapstoget++;
+            if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE ) {
+              // Missing
+              mdi->mapstoget++;
+            }
+            else {
+              if ( mdi->redownload == REDOWNLOAD_BAD ) {
+                /* see if this one is bad or what */
+                GError *gx = NULL;
+                GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file ( mdi->filename_buf, &gx );
+                if (gx || (!pixbuf)) {
+                  mdi->mapstoget++;
+                }
+                break;
+                // Other download cases already considered or just ignored
               }
-              break;
-              // Other download cases already considered or just ignored
             }
           }
         }
index 23acbb0e87268d8ae3e7a61e2b683918173a09fa..d59b41635d31d798e75f14a6d0e77bb936618131 100644 (file)
@@ -76,6 +76,10 @@ vik_map_source_class_init (VikMapSourceClass *klass)
        klass->supports_download_only_new = _supports_download_only_new;
        klass->get_zoom_min = NULL;
        klass->get_zoom_max = NULL;
+       klass->get_lat_min = NULL;
+       klass->get_lat_max = NULL;
+       klass->get_lon_min = NULL;
+       klass->get_lon_max = NULL;
        klass->coord_to_mapcoord = NULL;
        klass->mapcoord_to_center_coord = NULL;
        klass->download = NULL;
@@ -333,6 +337,61 @@ vik_map_source_get_zoom_max (VikMapSource * self)
        return (*klass->get_zoom_max)(self);
 }
 
+/**
+ *
+ */
+gdouble
+vik_map_source_get_lat_max (VikMapSource * self)
+{
+       VikMapSourceClass *klass;
+       g_return_val_if_fail (self != NULL, 90.0);
+       g_return_val_if_fail (VIK_IS_MAP_SOURCE (self), 90.0);
+       klass = VIK_MAP_SOURCE_GET_CLASS(self);
+       g_return_val_if_fail (klass->get_lat_max != NULL, 90.0);
+       return (*klass->get_lat_max)(self);
+}
+
+/**
+ *
+ */
+gdouble
+vik_map_source_get_lat_min (VikMapSource * self)
+{
+       VikMapSourceClass *klass;
+       g_return_val_if_fail (self != NULL, -90.0);
+       g_return_val_if_fail (VIK_IS_MAP_SOURCE (self), -90.0);
+       klass = VIK_MAP_SOURCE_GET_CLASS(self);
+       g_return_val_if_fail (klass->get_lat_min != NULL, -90.0);
+       return (*klass->get_lat_min)(self);
+}
+
+/**
+ *
+ */
+gdouble
+vik_map_source_get_lon_max (VikMapSource * self)
+{
+       VikMapSourceClass *klass;
+       g_return_val_if_fail (self != NULL, 180.0);
+       g_return_val_if_fail (VIK_IS_MAP_SOURCE (self), 180.0);
+       klass = VIK_MAP_SOURCE_GET_CLASS(self);
+       g_return_val_if_fail (klass->get_lon_max != NULL, 180.0);
+       return (*klass->get_lon_max)(self);
+}
+
+/**
+ *
+ */
+gdouble
+vik_map_source_get_lon_min (VikMapSource * self)
+{
+       VikMapSourceClass *klass;
+       g_return_val_if_fail (self != NULL, -180.0);
+       g_return_val_if_fail (VIK_IS_MAP_SOURCE (self), -180.0);
+       klass = VIK_MAP_SOURCE_GET_CLASS(self);
+       g_return_val_if_fail (klass->get_lon_min != NULL, -180.0);
+       return (*klass->get_lon_min)(self);
+}
 
 /**
  * vik_map_source_get_file_extension:
index 2b11ec1643cf4cc68b0a534f47f4c470b179df59..44a811e6e5abb1526b82f5abbcf88d72137f89f7 100644 (file)
@@ -61,6 +61,10 @@ struct _VikMapSourceClass
        gboolean (* supports_download_only_new) (VikMapSource * self);
        guint8 (* get_zoom_min) (VikMapSource * self);
        guint8 (* get_zoom_max) (VikMapSource * self);
+       gdouble (* get_lat_min) (VikMapSource * self);
+       gdouble (* get_lat_max) (VikMapSource * self);
+       gdouble (* get_lon_min) (VikMapSource * self);
+       gdouble (* get_lon_max) (VikMapSource * self);
        const gchar * (* get_file_extension) (VikMapSource * self);
        gboolean (* coord_to_mapcoord) (VikMapSource * self, const VikCoord * src, gdouble xzoom, gdouble yzoom, MapCoord * dest);
        void (* mapcoord_to_center_coord) (VikMapSource * self, MapCoord * src, VikCoord * dest);
@@ -93,6 +97,10 @@ 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);
+gdouble vik_map_source_get_lat_min (VikMapSource * self);
+gdouble vik_map_source_get_lat_max (VikMapSource * self);
+gdouble vik_map_source_get_lon_min (VikMapSource * self);
+gdouble vik_map_source_get_lon_max (VikMapSource * self);
 const gchar * vik_map_source_get_file_extension (VikMapSource * self);
 gboolean vik_map_source_coord_to_mapcoord (VikMapSource * self, const VikCoord *src, gdouble xzoom, gdouble yzoom, MapCoord *dest );
 void vik_map_source_mapcoord_to_center_coord (VikMapSource * self, MapCoord *src, VikCoord *dest);
index 53f3c849122cdf7eea1e6f4ffd43b273c5c1aa40..54cffc8d36f2f81444fde076e4f12ebc319e2535 100644 (file)
@@ -62,6 +62,10 @@ 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 );
+static gdouble _get_lat_min(VikMapSource *self );
+static gdouble _get_lat_max(VikMapSource *self );
+static gdouble _get_lon_min(VikMapSource *self );
+static gdouble _get_lon_max(VikMapSource *self );
 
 static gchar *_get_uri( VikMapSourceDefault *self, MapCoord *src );
 static gchar *_get_hostname( VikMapSourceDefault *self );
@@ -76,6 +80,10 @@ struct _VikSlippyMapSourcePrivate
   // NB Probably best to keep the above fields in same order to be common across Slippy, TMS & WMS map definitions
   guint zoom_min; // TMS Zoom level: 0 = Whole World // http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
   guint zoom_max; // TMS Zoom level: Often 18 for zoomed in.
+  gdouble lat_min; // Degrees
+  gdouble lat_max; // Degrees
+  gdouble lon_min; // Degrees
+  gdouble lon_max; // Degrees
   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
@@ -94,6 +102,10 @@ enum
   PROP_URL,
   PROP_ZOOM_MIN,
   PROP_ZOOM_MAX,
+  PROP_LAT_MIN,
+  PROP_LAT_MAX,
+  PROP_LON_MIN,
+  PROP_LON_MAX,
   PROP_REFERER,
   PROP_FOLLOW_LOCATION,
   PROP_CHECK_FILE_SERVER_TIME,
@@ -116,6 +128,10 @@ vik_slippy_map_source_init (VikSlippyMapSource *self)
   priv->url = NULL;
   priv->zoom_min = 0;
   priv->zoom_max = 18;
+  priv->lat_min = -90.0;
+  priv->lat_max = 90.0;
+  priv->lon_min = -180.0;
+  priv->lon_max = 180.0;
   priv->options.referer = NULL;
   priv->options.follow_location = 0;
   priv->options.check_file = a_check_map_file;
@@ -178,6 +194,22 @@ vik_slippy_map_source_set_property (GObject      *object,
       priv->zoom_max = g_value_get_uint (value);
       break;
 
+    case PROP_LAT_MIN:
+      priv->lat_min = g_value_get_double (value);
+      break;
+
+    case PROP_LAT_MAX:
+      priv->lat_max = g_value_get_double (value);
+      break;
+
+    case PROP_LON_MIN:
+      priv->lon_min = g_value_get_double (value);
+      break;
+
+    case PROP_LON_MAX:
+      priv->lon_max = g_value_get_double (value);
+      break;
+
     case PROP_REFERER:
       g_free (priv->options.referer);
       priv->options.referer = g_value_dup_string (value);
@@ -245,6 +277,22 @@ vik_slippy_map_source_get_property (GObject    *object,
       g_value_set_uint (value, priv->zoom_max);
       break;
 
+    case PROP_LON_MIN:
+      g_value_set_double (value, priv->lon_min);
+      break;
+
+    case PROP_LON_MAX:
+      g_value_set_double (value, priv->lon_max);
+      break;
+
+    case PROP_LAT_MIN:
+      g_value_set_double (value, priv->lat_min);
+      break;
+
+    case PROP_LAT_MAX:
+      g_value_set_double (value, priv->lat_max);
+      break;
+
     case PROP_REFERER:
       g_value_set_string (value, priv->options.referer);
       break;
@@ -304,6 +352,10 @@ vik_slippy_map_source_class_init (VikSlippyMapSourceClass *klass)
        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;
+       grandparent_class->get_lat_min = _get_lat_min;
+       grandparent_class->get_lat_max = _get_lat_max;
+       grandparent_class->get_lon_min = _get_lon_min;
+       grandparent_class->get_lon_max = _get_lon_max;
 
        parent_class->get_uri = _get_uri;
        parent_class->get_hostname = _get_hostname;
@@ -341,6 +393,42 @@ vik_slippy_map_source_class_init (VikSlippyMapSourceClass *klass)
                                   G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
        g_object_class_install_property (object_class, PROP_ZOOM_MAX, pspec);
 
+       pspec = g_param_spec_double ("lat-min",
+                                    "Minimum latitude",
+                                    "Minimum latitude in degrees supported by the map provider",
+                                    -90.0,  // minimum value
+                                    90.0, // maximum value
+                                    -90.0, // default value
+                                    G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
+       g_object_class_install_property (object_class, PROP_LAT_MIN, pspec);
+
+       pspec = g_param_spec_double ("lat-max",
+                                    "Maximum latitude",
+                                    "Maximum latitude in degrees supported by the map provider",
+                                    -90.0,  // minimum value
+                                    90.0, // maximum value
+                                    90.0, // default value
+                                    G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
+       g_object_class_install_property (object_class, PROP_LAT_MAX, pspec);
+
+       pspec = g_param_spec_double ("lon-min",
+                                    "Minimum longitude",
+                                    "Minimum longitude in degrees supported by the map provider",
+                                    -180.0,  // minimum value
+                                    180.0, // maximum value
+                                    -180.0, // default value
+                                    G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
+       g_object_class_install_property (object_class, PROP_LON_MIN, pspec);
+
+       pspec = g_param_spec_double ("lon-max",
+                                    "Maximum longitude",
+                                    "Maximum longitude in degrees supported by the map provider",
+                                    -180.0,  // minimum value
+                                    180.0, // maximum value
+                                    180.0, // default value
+                                    G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
+       g_object_class_install_property (object_class, PROP_LON_MAX, pspec);
+
        pspec = g_param_spec_string ("referer",
                                     "Referer",
                                     "The REFERER string to use in HTTP request",
@@ -467,6 +555,50 @@ _get_zoom_max (VikMapSource *self)
   return priv->zoom_max;
 }
 
+/**
+ *
+ */
+static gdouble
+_get_lat_min (VikMapSource *self)
+{
+  g_return_val_if_fail (VIK_IS_SLIPPY_MAP_SOURCE(self), FALSE);
+  VikSlippyMapSourcePrivate *priv = VIK_SLIPPY_MAP_SOURCE_PRIVATE(self);
+  return priv->lat_min;
+}
+
+/**
+ *
+ */
+static gdouble
+_get_lat_max (VikMapSource *self)
+{
+  g_return_val_if_fail (VIK_IS_SLIPPY_MAP_SOURCE(self), FALSE);
+  VikSlippyMapSourcePrivate *priv = VIK_SLIPPY_MAP_SOURCE_PRIVATE(self);
+  return priv->lat_max;
+}
+
+/**
+ *
+ */
+static gdouble
+_get_lon_min (VikMapSource *self)
+{
+  g_return_val_if_fail (VIK_IS_SLIPPY_MAP_SOURCE(self), FALSE);
+  VikSlippyMapSourcePrivate *priv = VIK_SLIPPY_MAP_SOURCE_PRIVATE(self);
+  return priv->lon_min;
+}
+
+/**
+ *
+ */
+static gdouble
+_get_lon_max (VikMapSource *self)
+{
+  g_return_val_if_fail (VIK_IS_SLIPPY_MAP_SOURCE(self), FALSE);
+  VikSlippyMapSourcePrivate *priv = VIK_SLIPPY_MAP_SOURCE_PRIVATE(self);
+  return priv->lon_max;
+}
+
 static gboolean
 _coord_to_mapcoord ( VikMapSource *self, const VikCoord *src, gdouble xzoom, gdouble yzoom, MapCoord *dest )
 {