]> Pileus Git - grits/commitdiff
Add GisTile and GisWms and update wms_test accordingly
authorAndy Spencer <andy753421@gmail.com>
Mon, 9 Nov 2009 12:02:23 +0000 (12:02 +0000)
committerAndy Spencer <andy753421@gmail.com>
Mon, 9 Nov 2009 12:02:23 +0000 (12:02 +0000)
GisTile:
 * Represents a lat-lon tile
 * May contain pointers to child tiles of higher resolution

GisWms:
 * Contains Web Map Service support functions

GisWms and GisTile roughly translate to WmsInfo and WmsCacheNode. The main
difference being that the new versions are more independent of each other so
non-wms downloaders can be used in the future.

The other major difference is that GisTile is not transparent as WmsCacheNode
was. That is, there is no gis_tile_fetch function which automatically updates
the tiles.

src/Makefile.am
src/gis-tile.c [new file with mode: 0644]
src/gis-tile.h [new file with mode: 0644]
src/gis-wms.c [new file with mode: 0644]
src/gis-wms.h [new file with mode: 0644]
src/gis-world.h
src/gis.h
src/wms_test.c

index 5c3c3a8c126df7bb79d91934cc5dd024f602a345..5e3da6d153b43e6a36447e40cfb36366495f0c20 100644 (file)
@@ -16,6 +16,8 @@ gis_include_HEADERS = \
        gis-opengl.h  \
        gis-plugin.h  \
        gis-data.h    \
+       gis-tile.h    \
+       gis-wms.h     \
        gpqueue.h     \
        roam.h
 libgis_la_SOURCES = \
@@ -26,6 +28,8 @@ libgis_la_SOURCES = \
        gis-plugin.c  gis-plugin.h  \
        gis-marshal.c gis-marshal.h \
        gis-data.c    gis-data.h    \
+       gis-tile.c    gis-tile.h    \
+       gis-wms.c     gis-wms.h     \
        roam.c        roam.h        \
        gpqueue.c     gpqueue.h
 libgis_la_CPPFLAGS = $(AM_CPPFLAGS) \
@@ -36,14 +40,14 @@ pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = libgis.pc
 
 # Test programs
-bin_PROGRAMS = gis_test wms_test
+bin_PROGRAMS = gis_test wms_test
 
 gis_test_SOURCES  = gis_test.c gis.h
 gis_test_LDFLAGS  = -static
 gis_test_LDADD    = $(AM_LDADD) libgis.la
 
-# wms_test_SOURCES  = wms_test.c gis-world.c gis-world.h
-wms_test_LDADD    = $(AM_LDADD)
+wms_test_SOURCES  = wms_test.c gis-world.c gis-world.h gis-wms.c gis-wms.h gis-tile.c gis-tile.h
+wms_test_LDADD    = $(AM_LDADD)
 
 MAINTAINERCLEANFILES = Makefile.in
 
diff --git a/src/gis-tile.c b/src/gis-tile.c
new file mode 100644 (file)
index 0000000..ab45616
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * 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/>.
+ */
+
+#include <config.h>
+#include <glib.h>
+
+#include "gis-world.h"
+#include "gis-tile.h"
+
+gchar *gis_tile_path_table[2][2] = {
+       {".00", ".01"},
+       {".10", ".11"},
+};
+
+GisTile *gis_tile_new(GisTile *parent,
+       gdouble n, gdouble s, gdouble e, gdouble w)
+{
+       GisTile *self = g_new0(GisTile, 1);
+       self->parent = parent;
+       self->edge.n = n;
+       self->edge.s = s;
+       self->edge.e = e;
+       self->edge.w = w;
+       return self;
+}
+
+gchar *gis_tile_get_path(GisTile *child)
+{
+       /* This could be easily cached if necessasairy */
+       int x, y;
+       GList *parts = NULL;
+       for (GisTile *parent = child->parent; parent; child = parent, parent = child->parent)
+               gis_tile_foreach_index(child, x, y)
+                       if (parent->children[x][y] == child)
+                               parts = g_list_prepend(parts, gis_tile_path_table[x][y]);
+       GString *path = g_string_new("");
+       for (; parts; parts = parts->next)
+               g_string_append(path, parts->data);
+       g_list_free(parts);
+       return g_string_free(path, FALSE);
+}
+
+
+void gis_tile_free(GisTile *self, GisTileFreeFunc free_func, gpointer user_data)
+{
+       if (!self)
+               return;
+       GisTile *child;
+       gis_tile_foreach(self, child)
+               gis_tile_free(child, free_func, user_data);
+       if (free_func)
+               free_func(self, user_data);
+       g_free(self);
+}
diff --git a/src/gis-tile.h b/src/gis-tile.h
new file mode 100644 (file)
index 0000000..12d397d
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * 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 __GIS_TILE_H__
+#define __GIS_TILE_H__
+
+#include <config.h>
+#include <glib.h>
+
+typedef struct _GisTile        GisTile;
+
+#define gis_tile_foreach(tile, child) \
+       for (int _x = 0; _x < G_N_ELEMENTS(tile->children); _x++) \
+       for (int _y = 0; child = tile->children[_x][_y], \
+               _y < G_N_ELEMENTS(tile->children[_x]); _y++) \
+
+#define gis_tile_foreach_index(tile, x, y) \
+       for (x = 0; x < G_N_ELEMENTS(tile->children); x++) \
+       for (y = 0; y < G_N_ELEMENTS(tile->children[x]); y++)
+
+typedef void (*GisTileLoadFunc)(GisTile *tile, gpointer user_data);
+typedef void (*GisTileFreeFunc)(GisTile *tile, gpointer user_data);
+
+struct _GisTile {
+       /* Pointer to the tile data */
+       gpointer data;
+
+       /* North,South,East,West limits */
+       struct {
+               gdouble n,s,e,w;
+       } edge;
+
+       /* Pointers to parent/child nodes */
+       GisTile *parent;
+       GisTile *children[2][2];
+};
+
+/* Path to string table, keep in sync with tile->children */ 
+extern gchar *gis_tile_path_table[2][2];
+
+/* Allocate a new Tile */
+GisTile *gis_tile_new(GisTile *parent,
+       gdouble n, gdouble s, gdouble e, gdouble w);
+
+/* Return a string representation of the tile's path */
+gchar *gis_tile_get_path(GisTile *child);
+
+/* Free a tile and all it's children */
+void gis_tile_free(GisTile *root,
+               GisTileFreeFunc free_func, gpointer user_data);
+
+#endif
diff --git a/src/gis-wms.c b/src/gis-wms.c
new file mode 100644 (file)
index 0000000..0c15e87
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * 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/>.
+ */
+
+/**
+ * http://www.nasa.network.com/elev?
+ * SERVICE=WMS&
+ * VERSION=1.1.0&
+ * REQUEST=GetMap&
+ * LAYERS=bmng200406&
+ * STYLES=&
+ * SRS=EPSG:4326&
+ * BBOX=-180,-90,180,90&
+ * FORMAT=image/jpeg&
+ * WIDTH=600&
+ * HEIGHT=300
+ *
+ * http://www.nasa.network.com/elev?
+ * SERVICE=WMS&
+ * VERSION=1.1.0&
+ * REQUEST=GetMap&
+ * LAYERS=srtm30&
+ * STYLES=&
+ * SRS=EPSG:4326&
+ * BBOX=-180,-90,180,90&
+ * FORMAT=application/bil32&
+ * WIDTH=600&
+ * HEIGHT=300
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <glib.h>
+
+#include "gis-wms.h"
+
+static gchar *_make_uri(GisWms *wms, GisTile *tile)
+{
+       return g_strdup_printf(
+               "%s?"
+               "SERVICE=WMS&"
+               "VERSION=1.1.0&"
+               "REQUEST=GetMap&"
+               "LAYERS=%s&"
+               "STYLES=&"
+               "SRS=EPSG:4326&"
+               "FORMAT=%s&"
+               "WIDTH=%d&"
+               "HEIGHT=%d&"
+               "BBOX=%f,%f,%f,%f",
+               wms->uri_prefix,
+               wms->uri_layer,
+               wms->uri_format,
+               wms->width,
+               wms->height,
+               tile->edge.w,
+               tile->edge.s,
+               tile->edge.e,
+               tile->edge.n);
+}
+
+void gis_wms_soup_chunk_cb(SoupMessage *message, SoupBuffer *chunk, gpointer _file)
+{
+       FILE *file = _file;
+       if (!SOUP_STATUS_IS_SUCCESSFUL(message->status_code))
+               return;
+       goffset total = soup_message_headers_get_content_length(message->response_headers);
+       if (fwrite(chunk->data, chunk->length, 1, file) != 1)
+               g_warning("GisWms: soup_chunk_cb - eror writing data");
+}
+
+char *gis_wms_make_local(GisWms *self, GisTile *tile)
+{
+       /* Get file path */
+       gchar *tile_path = gis_tile_get_path(tile);
+       gchar *path = g_strdup_printf("%s/wms/%s%s%s",
+               g_get_user_cache_dir(),
+               self->cache_prefix,
+               tile_path,
+               self->cache_ext);
+       g_free(tile_path);
+
+       /* Return if it already exists */
+       if (g_file_test(path, G_FILE_TEST_EXISTS))
+               return path;
+
+       /* Open temp file for writing */
+       gchar *tmp_path = g_strconcat(path, ".part", NULL);
+       gchar *dirname = g_path_get_dirname(tmp_path);
+       g_mkdir_with_parents(dirname, 0755);
+       g_free(dirname);
+       FILE *file = fopen(tmp_path, "a");
+
+       /* Download file */
+       gchar *uri = _make_uri(self, tile);
+       SoupMessage *message = soup_message_new("GET", uri);
+       g_signal_connect(message, "got-chunk", G_CALLBACK(gis_wms_soup_chunk_cb), file);
+       soup_message_headers_set_range(message->request_headers, ftell(file), -1);
+       int status = soup_session_send_message(self->soup, message);
+       g_free(uri);
+
+       /* Clean up */
+       fclose(file);
+       rename(tmp_path, path);
+       g_free(tmp_path);
+       return path;
+}
+
+GisWms *gis_wms_new(
+       gchar *uri_prefix, gchar *uri_layer, gchar *uri_format,
+       gchar *cache_prefix, gchar *cache_ext,
+       gint width, gint height)
+{
+       GisWms *self = g_new0(GisWms, 1);
+       self->uri_prefix   = uri_prefix;
+       self->uri_layer    = uri_layer;
+       self->uri_format   = uri_format;
+       self->cache_prefix = cache_prefix;
+       self->cache_ext    = cache_ext;
+       self->width        = width;
+       self->height       = height;
+       self->soup         = soup_session_sync_new();
+       return self;
+}
+
+void gis_wms_free(GisWms *self)
+{
+       g_object_unref(self->soup);
+       g_free(self);
+}
diff --git a/src/gis-wms.h b/src/gis-wms.h
new file mode 100644 (file)
index 0000000..4151cbf
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * 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 __GIS_WMS_H__
+#define __GIS_WMS_H__
+
+#include <config.h>
+#include <glib.h>
+#include <libsoup/soup.h>
+
+#include "gis-tile.h"
+
+typedef struct _GisWms GisWms;
+
+struct _GisWms {
+       gchar *uri_prefix;
+       gchar *uri_layer;
+       gchar *uri_format;
+       gchar *cache_prefix;
+       gchar *cache_ext;
+       gint   width;
+       gint   height;
+       SoupSession  *soup;
+};
+
+char *gis_wms_make_local(GisWms *wms, GisTile *tile);
+
+GisWms *gis_wms_new(
+       gchar *uri_prefix, gchar *uri_layer, gchar *uri_format,
+       gchar *cache_prefix, gchar *cache_ext,
+       gint width, gint height);
+
+void gis_wms_free(GisWms *self);
+
+#endif
index 93c47e33fd2761a66367749091fa9e5f39ade6f5..3a347808e109c3ba50a9c311f6752382c726c753 100644 (file)
 
 #define EARTH_R (6371000)
 #define EARTH_C (2*M_PI*EARTH_R)
+#define NORTH  90
+#define SOUTH -90
+#define EAST  180
+#define WEST -180
 
 /**
  * Terms
index 365c8438e6ea4afc53fbee19a2ff8acae188363b..6ff9789231eb7e8bfc291617e5749a03266f34dd 100644 (file)
--- a/src/gis.h
+++ b/src/gis.h
@@ -26,6 +26,8 @@
 
 /* GIS helprs */
 #include "gis-data.h"
+#include "gis-tile.h"
+#include "gis-wms.h"
 
 /* Plugins */
 #include "gis-plugin.h"
index 59868e5f111e57085153e2c7a6fe3b15f946cc0f..c45665996c6ccb3cff7c42599787e43b281cb483 100644 (file)
@@ -1,7 +1,9 @@
 #include <gtk/gtk.h>
 #include <gdk/gdkkeysyms.h>
 
-#include "wms.h"
+#include "gis-world.h"
+#include "gis-tile.h"
+#include "gis-wms.h"
 
 struct CacheState {
        GtkWidget *image;
@@ -9,12 +11,6 @@ struct CacheState {
        GtkWidget *progress;
 };
 
-void done_callback(WmsCacheNode *node, gpointer _state)
-{
-       struct CacheState *state = _state;
-       g_message("done_callback: %p->%p", node, node->data);
-       gtk_image_set_from_pixbuf(GTK_IMAGE(state->image), node->data);
-}
 
 void chunk_callback(gsize cur, gsize total, gpointer _state)
 {
@@ -33,6 +29,32 @@ void chunk_callback(gsize cur, gsize total, gpointer _state)
                gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(state->progress), (gdouble)cur/total);
 }
 
+gpointer do_cache(gpointer _image)
+{
+       GtkImage *image = _image;
+       g_message("Creating tile");
+       GisTile *tile = gis_tile_new(NULL, NORTH, SOUTH, EAST, WEST);
+       tile->children[0][1] = gis_tile_new(tile, NORTH, 0, 0, WEST);
+       tile = tile->children[0][1];
+
+       g_message("Fetching image");
+       GisWms *bmng_wms = gis_wms_new(
+               "http://www.nasa.network.com/wms", "bmng200406", "image/jpeg",
+               "bmng", ".jpg", 512, 256);
+       const char *path = gis_wms_make_local(bmng_wms, tile);
+
+       g_message("Loading 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 up");
+       gis_wms_free(bmng_wms);
+       gis_tile_free(tile, NULL, NULL);
+       return NULL;
+}
+
 gboolean key_press_cb(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
 {
        if (event->keyval == GDK_q)
@@ -64,22 +86,10 @@ int main(int argc, char **argv)
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll),
                        GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
 
-       struct CacheState bmng_state = {bmng_image, status, NULL};
-       struct CacheState srtm_state = {srtm_image, status, NULL};
-
-       gdouble res = 200, lon = -101.76, lat = 46.85;
-
-       WmsInfo *bmng_info = wms_info_new_for_bmng(bmng_pixbuf_loader, bmng_pixbuf_freeer);
-       wms_info_fetch_cache(bmng_info, NULL, res, lat, lon, chunk_callback, done_callback, &bmng_state);
-
-       WmsInfo *srtm_info = wms_info_new_for_srtm(srtm_pixbuf_loader, srtm_pixbuf_freeer);
-       wms_info_fetch_cache(srtm_info, NULL, res, lat, lon, chunk_callback, done_callback, &srtm_state);
+       g_thread_create(do_cache, bmng_image, FALSE, NULL);
 
        gtk_widget_show_all(win);
        gtk_main();
 
-       wms_info_free(bmng_info);
-       wms_info_free(srtm_info);
-
        return 0;
 }