]> Pileus Git - grits/commitdiff
Add Tile Map Service downloading
authorAndy Spencer <andy753421@gmail.com>
Mon, 16 Jan 2012 03:13:00 +0000 (03:13 +0000)
committerAndy Spencer <andy753421@gmail.com>
Mon, 30 Jan 2012 07:16:48 +0000 (07:16 +0000)
This uses map tiles directly from openstreetmap.org. The problem with
this is that those tiles are rendered using a Mercator projections which
is non-linear with respect to latitude. Two things must be done to
properly correct for this:

1. Split tiles at the correct location. With the Mercator projection,
   the midpoint of a tile is the midpoint of the longitude but not the
   midpoint of the latitude.

   Correcting this very important because it prevent tiles from being
   drawn in entirely the wrong place.

2. Morph each tile to lat-lon projection when it is drawn. This could
   possibly be done with a OpenGL fragment shader.

   This noticeable when zoomed out so it's not too bad to just ignore
   the issue.. The web based map servers have similar issues with land
   area at high-up zoom levels.

Eventually we'll want to fetch the XML and render the maps locally..

src/data/Makefile.am
src/data/grits-tms.c [new file with mode: 0644]
src/data/grits-tms.h [new file with mode: 0644]
src/grits-viewer.h
src/grits.h
src/plugins/map.c
src/plugins/map.h
src/tile-test.c

index 5a8c80611325eba22257aa9b7c09517aaa9ea363..c193fc01c210347e1325051cf997df4cc659ad26 100644 (file)
@@ -9,12 +9,14 @@ grits_data_includedir = $(includedir)/grits/data
 grits_data_include_HEADERS = \
        grits-data.h \
        grits-http.h \
+       grits-tms.h  \
        grits-wms.h
 
 noinst_LTLIBRARIES = libgrits-data.la
 libgrits_data_la_SOURCES = \
        grits-data.c grits-data.h \
        grits-http.c grits-http.h \
+       grits-tms.c  grits-tms.h \
        grits-wms.c  grits-wms.h
 libgrits_data_la_LDFLAGS = -static
 
diff --git a/src/data/grits-tms.c b/src/data/grits-tms.c
new file mode 100644 (file)
index 0000000..cfe84f5
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2009, 2012 Andy Spencer <spenceal@rose-hulman.edu>
+ *
+ * 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include <config.h>
+#include <stdio.h>
+#include <math.h>
+#include <glib.h>
+
+#include "grits-tms.h"
+
+static gchar *_make_uri(GritsTms *tms, GritsTile *tile)
+{
+
+#if 0
+       /* This doesn't make any sense.. */
+       gdouble lon_rad = deg2rad(tile->edge.n + tile->edge.s)/2;
+       gdouble lat_rad = deg2rad(tile->edge.e + tile->edge.w)/2;
+       g_message("%lf,%lf", lat_rad, lon_rad);
+
+       /* Reproject the coordinates to the Mercator projection: */
+       gdouble x = lon_rad;
+       gdouble y = log(tan(lat_rad) + 1.0/cos(lat_rad));
+
+       /* Transform range of x and y to 0 - 1 and shift origin to top left */
+       x = (1.0 + (x / G_PI)) / 2.0;
+       y = (1.0 - (y / G_PI)) / 2.0;
+
+       /* Calculate the number of tiles across the map, n, using 2^zoom */
+       gint zoom = 0;
+       for (GritsTile *tmp = tile->parent; tmp; tmp = tmp->parent)
+               zoom++;
+       gint n = pow(2, zoom);
+
+       /* Multiply x and y by n. Round results down to give tilex and tiley. */
+       gint xtile = x * n;
+       gint ytile = y * n;
+
+       g_message("xy=%f,%f  zoom=%d  n=%d  xy_tiles=%d,%d",
+                       x, y, zoom, n, xtile, ytile);
+#endif
+
+#if 1
+       /* This is broken */
+       gint zoom = 0;
+       for (GritsTile *tmp = tile->parent; tmp; tmp = tmp->parent)
+               zoom++;
+       gint breath = pow(2,zoom);
+
+       gdouble lon_pos =  (tile->edge.e+tile->edge.w)/2 + 180;
+       gdouble lat_pos = -(tile->edge.n+tile->edge.s)/2 +  90 - 4.9489;
+
+       gdouble lon_total = 360;
+       gdouble lat_total = 85.0511*2;
+
+       gdouble lon_pct = lon_pos / lon_total;
+       gdouble lat_pct = lat_pos / lat_total;
+
+       gint xtile = lon_pct * breath;
+       gint ytile = lat_pct * breath;
+
+       //g_message("bbok=%f,%f,%f,%f",
+       //              tile->edge.n, tile->edge.s,
+       //              tile->edge.e, tile->edge.w);
+       //g_message("pos=%f,%f total=%f,%f pct=%f,%f tile=%d,%d",
+       //              lon_pos,   lat_pos,
+       //              lon_total, lat_total,
+       //              lon_pct,   lat_pct,
+       //              xtile,     ytile);
+#endif
+
+       // http://tile.openstreetmap.org/<zoom>/<xtile>/<ytile>.png
+       return g_strdup_printf("%s/%d/%d/%d.%s",
+                       tms->uri_prefix, zoom, xtile, ytile, tms->extension);
+}
+
+gchar *grits_tms_fetch(GritsTms *tms, GritsTile *tile, GritsCacheType mode,
+               GritsChunkCallback callback, gpointer user_data)
+{
+       /* Get file path */
+       gchar *uri   = _make_uri(tms, tile);
+       gchar *tilep = grits_tile_get_path(tile);
+       gchar *local = g_strdup_printf("%s%s", tilep, tms->extension);
+       gchar *path  = grits_http_fetch(tms->http, uri, local,
+                       mode, callback, user_data);
+       g_free(uri);
+       g_free(tilep);
+       g_free(local);
+       return path;
+}
+
+GritsTms *grits_tms_new(const gchar *uri_prefix,
+               const gchar *prefix, const gchar *extension)
+{
+       GritsTms *tms = g_new0(GritsTms, 1);
+       tms->http         = grits_http_new(prefix);
+       tms->uri_prefix   = g_strdup(uri_prefix);
+       tms->extension    = g_strdup(extension);
+       return tms;
+}
+
+void grits_tms_free(GritsTms *tms)
+{
+       grits_http_free(tms->http);
+       g_free(tms->uri_prefix);
+       g_free(tms->extension);
+       g_free(tms);
+}
diff --git a/src/data/grits-tms.h b/src/data/grits-tms.h
new file mode 100644 (file)
index 0000000..49fb0c4
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2009 Andy Spencer <spenceal@rose-hulman.edu>
+ *
+ * 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GRITS_TMS_H__
+#define __GRITS_TMS_H__
+
+#include <glib.h>
+
+#include "data/grits-http.h"
+#include "objects/grits-tile.h"
+
+typedef struct _GritsTms GritsTms;
+
+struct _GritsTms {
+       GritsHttp *http;
+       gchar *uri_prefix;
+       gchar *cache_prefix;
+       gchar *extension;
+};
+
+gchar *grits_tms_fetch(GritsTms *tms, GritsTile *tile, GritsCacheType mode,
+               GritsChunkCallback callback, gpointer user_data);
+
+GritsTms *grits_tms_new(const gchar *uri_prefix, const gchar *cache_prefix, const gchar *extention);
+
+void grits_tms_free(GritsTms *self);
+
+#endif
index 0fe73657625d195d1f4652b4be6a9a8d62cd33a2..b7ff2166029a18d1bc02dd67624a8a873dde9716 100644 (file)
 #include <gtk/gtk.h>
 #include <glib-object.h>
 
+/* Projections */
+enum {
+       GRITS_PROJ_MERCATOR,
+       GRITS_PROJ_EQUIRECTANGULAR,
+} GritsProjection;
+
 /* Rendering levels */
 /**
  * GRITS_LEVEL_BACKGROUND: 
index 540120c24d8cd1377c122ce0f746d492fbdbbf71..fa8f00133ea17f1edb6fc72cd1c3a70859d8683c 100644 (file)
@@ -27,6 +27,7 @@
 /* Grits data */
 #include <data/grits-data.h>
 #include <data/grits-http.h>
+#include <data/grits-tms.h>
 #include <data/grits-wms.h>
 
 /* Grits objects */
index 96f2c994565c437fcb2cf84dc0c6aa6f04a35bdd..aa4d0f27d51d3454e1ae9acdb97de45af94babab 100644 (file)
@@ -86,6 +86,7 @@ static void _load_tile(GritsTile *tile, gpointer _map)
        }
 
        /* Download tile */
+       //gchar *path = grits_tms_fetch(map->tms, tile, GRITS_ONCE, NULL, NULL);
        gchar *path = grits_wms_fetch(map->wms, tile, GRITS_ONCE, NULL, NULL);
        if (!path) return; // Canceled/error
 
@@ -217,6 +218,9 @@ static void grits_plugin_map_init(GritsPluginMap *map)
        g_debug("GritsPluginMap: init");
        /* Set defaults */
        map->threads = g_thread_pool_new(_update_tiles, map, 1, FALSE, NULL);
+       //map->tiles = grits_tile_new(NULL, 85.0511, -85.0511, EAST, WEST);
+       //map->wms   = grits_tms_new("http://tile.openstreetmap.org",
+       //      "osm/", "png");
        map->tiles = grits_tile_new(NULL, NORTH, SOUTH, EAST, WEST);
        map->wms   = grits_wms_new(
                "http://vmap0.tiles.osgeo.org/wms/vmap0",
@@ -247,6 +251,7 @@ static void grits_plugin_map_finalize(GObject *gobject)
        g_debug("GritsPluginMap: finalize");
        GritsPluginMap *map = GRITS_PLUGIN_MAP(gobject);
        /* Free data */
+       //grits_wms_free(map->tms);
        grits_wms_free(map->wms);
        grits_tile_free(map->tiles, _free_tile, map);
        G_OBJECT_CLASS(grits_plugin_map_parent_class)->finalize(gobject);
index 91e96ab611ffc681711fb0a414dcc637de881adb..5161837609ee62daeca13323fdcef67c583e9b73 100644 (file)
@@ -36,6 +36,7 @@ struct _GritsPluginMap {
        /* instance members */
        GritsViewer *viewer;
        GritsTile   *tiles;
+       GritsTms    *tms;
        GritsWms    *wms;
        GThreadPool *threads;
        gulong       sigid;
index 9a4fd81629e4eae679c951889eff4aa74dd6a6ff..8be6fe94d2992b0b8209e4df90c325d3351312aa 100644 (file)
@@ -20,6 +20,7 @@
 
 #include "grits-util.h"
 #include "data/grits-wms.h"
+#include "data/grits-tms.h"
 #include "objects/grits-tile.h"
 
 struct CacheState {
@@ -98,6 +99,32 @@ gpointer do_osm_cache(gpointer _image)
        return NULL;
 }
 
+gpointer do_osm2_cache(gpointer _image)
+{
+       GtkImage *image = _image;
+       g_message("Creating osm2 tile");
+       GritsTile *tile = grits_tile_new(NULL, 85.0511, -85.0511, EAST, WEST);
+       tile->children[0][1] = grits_tile_new(tile, 85.0511, 0, 0, WEST);
+       tile = tile->children[0][1];
+
+       g_message("Fetching osm2 image");
+       GritsTms *osm2_tms = grits_tms_new("http://tile.openstreetmap.org",
+                       "tms_test/", "png");
+       const char *path = grits_tms_fetch(osm2_tms, tile, GRITS_ONCE, NULL, NULL);
+
+       g_message("Loading osm2 image: [%s]", path);
+       GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(path, NULL);
+       gdk_threads_enter();
+       gtk_image_set_from_pixbuf(GTK_IMAGE(image), pixbuf);
+       gdk_threads_leave();
+
+       g_message("Cleaning osm2 up");
+       grits_tms_free(osm2_tms);
+       grits_tile_free(tile, NULL, NULL);
+       return NULL;
+}
+
+
 gboolean key_press_cb(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
 {
        if (event->keyval == GDK_q)
@@ -119,12 +146,14 @@ int main(int argc, char **argv)
        GtkWidget *bmng_image = gtk_image_new();
        GtkWidget *srtm_image = gtk_image_new();
        GtkWidget *osm_image  = gtk_image_new();
+       GtkWidget *osm2_image = gtk_image_new();
        gtk_container_add(GTK_CONTAINER(win), vbox1);
        gtk_box_pack_start(GTK_BOX(vbox1), scroll, TRUE, TRUE, 0);
        gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll), vbox2);
        gtk_box_pack_start(GTK_BOX(vbox2), bmng_image, TRUE, TRUE, 0);
        gtk_box_pack_start(GTK_BOX(vbox2), srtm_image, TRUE, TRUE, 0);
        gtk_box_pack_start(GTK_BOX(vbox2), osm_image,  TRUE, TRUE, 0);
+       gtk_box_pack_start(GTK_BOX(vbox2), osm2_image, TRUE, TRUE, 0);
        gtk_box_pack_start(GTK_BOX(vbox1), status, FALSE, FALSE, 0);
        g_signal_connect(win, "key-press-event", G_CALLBACK(key_press_cb), NULL);
        g_signal_connect(win, "destroy", gtk_main_quit, NULL);
@@ -133,6 +162,7 @@ int main(int argc, char **argv)
 
        g_thread_create(do_bmng_cache, bmng_image, FALSE, NULL);
        g_thread_create(do_osm_cache,  osm_image,  FALSE, NULL);
+       g_thread_create(do_osm2_cache, osm2_image, FALSE, NULL);
 
        gtk_widget_show_all(win);
        gtk_main();