* GTK docs
0.x - GIS
- * Use Vertex Arrays/
- VertexBufferObjects/
- DisplayLists/
- glInterleavedArrays
- * States/cities/roads overlays
* NEXRAD LLE listings, click to center
0.x - Volume scans
GTK_DOC_CHECK(1.9)
# Check for required packages
-PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.14 gobject-2.0 gthread-2.0 gmodule-export-2.0)
-PKG_CHECK_MODULES(GTK, gtk+-2.0 >= 2.16 gtkglext-1.0)
-PKG_CHECK_MODULES(SOUP, libsoup-2.4 >= 2.26)
+PKG_CHECK_MODULES(GIS, libgis)
# Define odd RSL install location
AC_CHECK_LIB(rsl, RSL_wsr88d_to_radar, RSL_LIBS="-lrsl")
AC_CONFIG_FILES([
Makefile
src/Makefile
- src/gis/Makefile
- src/gis/libgis.pc
src/plugins/Makefile
data/Makefile
docs/Makefile
- docs/api/Makefile
])
AC_OUTPUT
-SUBDIRS = api
+# TODO: write man pages
maintainer-clean-local:
rm -f Makefile.in
+++ /dev/null
-AM_CPPFLAGS=$(SOUP_CFLAGS) $(GLIB_CFLAGS) $(GTK_CFLAGS)
-GTKDOC_LIBS=$(SOUP_LIBS) $(GLIB_LIBS) $(GTK_LIBS) \
- $(top_srcdir)/src/aweather-aweather-*.o \
- $(top_srcdir)/src/gis/libgis*.o
-IGNORE_HFILES=
-if HAVE_RSL
-GTKDOC_LIBS += $(RSL_LIBS) $(top_srcdir)/src/plugins/*.o
-else
-IGNORE_HFILES += radar.h
-endif
-DOC_MODULE=aweather
-DOC_SOURCE_DIR=$(top_srcdir)/src/
-DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml
-MKDB_OPTIONS=--sgml-mode --output-format=xml
-include $(top_srcdir)/gtk-doc.make
-CLEANFILES += aweather-sections.txt
-MAINTAINERCLEANFILES=\
- tmpl/* Makefile.in aweather-docs.sgml aweather-overrides.txt aweather.types aweather-scan.*
+++ /dev/null
-CFLAGS=`{pkg-config --cflags libgis}
-LDFLAGS=`{pkg-config --libs libgis}
-LIB=teapot.so
-default:V: $LIB
-%.so: %.o
- gcc $CFLAGS -fPIC -shared -o $target $prereq $LDFLAGS
-%.o: %.c
- gcc $CFLAGS -fPIC -c -o $target $prereq
-clean:V:
- rm -f *.o *.so
-install:V:
- cp $LIB /usr/lib/gis/
-uninstall:V:
- rm /usr/lib/gis/$LIB
+++ /dev/null
-/*
- * 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 <gtk/gtkgl.h>
-#include <GL/gl.h>
-
-#include <gis.h>
-
-#include "teapot.h"
-
-/***********
- * Helpers *
- ***********/
-static gboolean rotate(gpointer _self)
-{
- GisPluginTeapot *self = _self;
- if (gtk_toggle_button_get_active(self->button)) {
- self->rotation += 1.0;
- gis_opengl_redraw(self->opengl);
- }
- return TRUE;
-}
-
-
-/***********
- * Methods *
- ***********/
-GisPluginTeapot *gis_plugin_teapot_new(GisWorld *world, GisView *view, GisOpenGL *opengl)
-{
- g_debug("GisPluginTeapot: new");
- GisPluginTeapot *self = g_object_new(GIS_TYPE_PLUGIN_TEAPOT, NULL);
- self->opengl = opengl;
-
- return self;
-}
-
-static GtkWidget *gis_plugin_teapot_get_config(GisPlugin *_self)
-{
- GisPluginTeapot *self = GIS_PLUGIN_TEAPOT(_self);
- return GTK_WIDGET(self->button);
-}
-
-static void gis_plugin_teapot_expose(GisPlugin *_self)
-{
- GisPluginTeapot *self = GIS_PLUGIN_TEAPOT(_self);
- g_debug("GisPluginTeapot: expose");
-
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(1,-1, -1,1, -10,10);
-
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
-
- float light_ambient[] = {0.1f, 0.1f, 0.0f, 1.0f};
- float light_diffuse[] = {0.9f, 0.9f, 0.9f, 1.0f};
- float light_position[] = {-30.0f, 50.0f, 40.0f, 1.0f};
- glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
- glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
- glLightfv(GL_LIGHT0, GL_POSITION, light_position);
- glEnable(GL_COLOR_MATERIAL);
-
- glTranslatef(-0.5, -0.5, -2);
- glRotatef(self->rotation, 1, 1, 0);
- glColor4f(0.9, 0.9, 0.7, 1.0);
- glDisable(GL_CULL_FACE);
- gdk_gl_draw_teapot(TRUE, 0.25);
-}
-
-
-/****************
- * GObject code *
- ****************/
-/* Plugin init */
-static void gis_plugin_teapot_plugin_init(GisPluginInterface *iface);
-G_DEFINE_TYPE_WITH_CODE(GisPluginTeapot, gis_plugin_teapot, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE(GIS_TYPE_PLUGIN,
- gis_plugin_teapot_plugin_init));
-static void gis_plugin_teapot_plugin_init(GisPluginInterface *iface)
-{
- g_debug("GisPluginTeapot: plugin_init");
- /* Add methods to the interface */
- iface->expose = gis_plugin_teapot_expose;
- iface->get_config = gis_plugin_teapot_get_config;
-}
-/* Class/Object init */
-static void gis_plugin_teapot_init(GisPluginTeapot *self)
-{
- g_debug("GisPluginTeapot: init");
- /* Set defaults */
- self->button = GTK_TOGGLE_BUTTON(gtk_toggle_button_new_with_label("Rotate"));
- self->rotate_id = g_timeout_add(1000/60, rotate, self);
- self->rotation = 30.0;
- self->opengl = NULL;
-}
-static void gis_plugin_teapot_dispose(GObject *gobject)
-{
- g_debug("GisPluginTeapot: dispose");
- GisPluginTeapot *self = GIS_PLUGIN_TEAPOT(gobject);
- g_source_remove(self->rotate_id);
- /* Drop references */
- G_OBJECT_CLASS(gis_plugin_teapot_parent_class)->dispose(gobject);
-}
-static void gis_plugin_teapot_finalize(GObject *gobject)
-{
- g_debug("GisPluginTeapot: finalize");
- GisPluginTeapot *self = GIS_PLUGIN_TEAPOT(gobject);
- /* Free data */
- G_OBJECT_CLASS(gis_plugin_teapot_parent_class)->finalize(gobject);
-
-}
-static void gis_plugin_teapot_class_init(GisPluginTeapotClass *klass)
-{
- g_debug("GisPluginTeapot: class_init");
- GObjectClass *gobject_class = (GObjectClass*)klass;
- gobject_class->dispose = gis_plugin_teapot_dispose;
- gobject_class->finalize = gis_plugin_teapot_finalize;
-}
+++ /dev/null
-/*
- * 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 __TEAPOT_H__
-#define __TEAPOT_H__
-
-#include <glib-object.h>
-
-#define GIS_TYPE_PLUGIN_TEAPOT (gis_plugin_teapot_get_type ())
-#define GIS_PLUGIN_TEAPOT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GIS_TYPE_PLUGIN_TEAPOT, GisPluginTeapot))
-#define GIS_IS_PLUGIN_TEAPOT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GIS_TYPE_PLUGIN_TEAPOT))
-#define GIS_PLUGIN_TEAPOT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIS_TYPE_PLUGIN_TEAPOT, GisPluginTeapotClass))
-#define GIS_IS_PLUGIN_TEAPOT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIS_TYPE_PLUGIN_TEAPOT))
-#define GIS_PLUGIN_TEAPOT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIS_TYPE_PLUGIN_TEAPOT, GisPluginTeapotClass))
-
-typedef struct _GisPluginTeapot GisPluginTeapot;
-typedef struct _GisPluginTeapotClass GisPluginTeapotClass;
-
-struct _GisPluginTeapot {
- GObject parent_instance;
-
- /* instance members */
- GtkToggleButton *button;
- guint rotate_id;
- float rotation;
- GisOpenGL *opengl;
-};
-
-struct _GisPluginTeapotClass {
- GObjectClass parent_class;
-};
-
-GType gis_plugin_teapot_get_type();
-
-/* Methods */
-GisPluginTeapot *gis_plugin_teapot_new(GisWorld *world, GisView *view, GisOpenGL *opengl);
-
-#endif
+++ /dev/null
-MKSHELL=/usr/lib/plan9/bin/rc
-PROGS=tex
-tex_libs=`{pkg-config --libs gtkglext-1.0}
-tex_cflags=`{pkg-config --cflags gtkglext-1.0}
-default:V: tex-run
-<$HOME/lib/mkcommon
+++ /dev/null
-#include <gtk/gtk.h>
-#include <gtk/gtkgl.h>
-#include <gdk/gdkkeysyms.h>
-#include <GL/gl.h>
-#include <GL/glu.h>
-
-guint tex, texl, texr;
-
-gboolean on_key_press(GtkWidget *widget, GdkEventKey *event, gpointer _)
-{
- if (event->keyval == GDK_q)
- gtk_main_quit();
- return FALSE;
-}
-
-gboolean on_expose(GtkWidget *drawing, GdkEventExpose *event, gpointer _)
-{
- glClearColor(0.5, 0.5, 1.0, 1.0);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(-1,1, -1,1, 10,-10);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- glTranslatef(0, 0, -5);
-
- glEnable(GL_COLOR_MATERIAL);
- glDisable(GL_TEXTURE_2D);
- glColor3f(1.0, 1.0, 1.0);
- glBegin(GL_QUADS);
- glVertex3f(-0.25, -0.75, 0.0);
- glVertex3f(-0.25, 0.75, 0.0);
- glVertex3f( 0.25, 0.75, 0.0);
- glVertex3f( 0.25, -0.75, 0.0);
- glEnd();
-
- /* Textures */
- glDisable(GL_COLOR_MATERIAL);
- glEnable(GL_TEXTURE_2D);
- glEnable(GL_BLEND);
-
- gdouble y = 0.875;
-
- /* Left */
- glBlendFunc(GL_ONE, GL_ZERO);
- glBindTexture(GL_TEXTURE_2D, texl);
- glBegin(GL_QUADS);
- glTexCoord2f(0.0, y); glVertex3f(-0.75, 0.0, 0.0);
- glTexCoord2f(0.0, 1.0); glVertex3f(-0.75, 0.5, 0.0);
- glTexCoord2f(2.0, 1.0); glVertex3f( 0.75, 0.5, 0.0);
- glTexCoord2f(2.0, y); glVertex3f( 0.75, 0.0, 0.0);
- glEnd();
-
- /* Right */
- glBlendFunc(GL_ONE, GL_ONE);
- glBindTexture(GL_TEXTURE_2D, texr);
- glBegin(GL_QUADS);
- glTexCoord2f(-1.0, y); glVertex3f(-0.75, 0.0, 0.0);
- glTexCoord2f(-1.0, 1.0); glVertex3f(-0.75, 0.5, 0.0);
- glTexCoord2f( 1.0, 1.0); glVertex3f( 0.75, 0.5, 0.0);
- glTexCoord2f( 1.0, y); glVertex3f( 0.75, 0.0, 0.0);
- glEnd();
-
- /* Bottom */
- glBlendFunc(GL_ONE, GL_ZERO);
- glBindTexture(GL_TEXTURE_2D, tex);
- glBegin(GL_QUADS);
- glTexCoord2f(0.0, 0.0); glVertex3f(-0.75, -0.5, 0.0);
- glTexCoord2f(0.0, 1.0-y); glVertex3f(-0.75, -0.0, 0.0);
- glTexCoord2f(1.0, 1.0-y); glVertex3f( 0.75, -0.0, 0.0);
- glTexCoord2f(1.0, 0.0); glVertex3f( 0.75, -0.5, 0.0);
- glEnd();
-
-
- /* Flush */
- GdkGLDrawable *gldrawable = gdk_gl_drawable_get_current();
- if (gdk_gl_drawable_is_double_buffered(gldrawable))
- gdk_gl_drawable_swap_buffers(gldrawable);
- else
- glFlush();
- return FALSE;
-}
-gboolean on_configure(GtkWidget *drawing, GdkEventConfigure *event, gpointer _)
-{
- glViewport(0, 0,
- drawing->allocation.width,
- drawing->allocation.height);
- return FALSE;
-}
-
-guint load_tex(gchar *filename)
-{
- GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
- guchar *pixels = gdk_pixbuf_get_pixels(pixbuf);
- int width = gdk_pixbuf_get_width(pixbuf);
- int height = gdk_pixbuf_get_height(pixbuf);
- int alpha = gdk_pixbuf_get_has_alpha(pixbuf);
- guint tex;
- glGenTextures(1, &tex);
- glBindTexture(GL_TEXTURE_2D, tex);
- glTexImage2D(GL_TEXTURE_2D, 0, 4, width, height, 0,
- (alpha ? GL_RGBA : GL_RGB), GL_UNSIGNED_BYTE, pixels);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
- g_object_unref(pixbuf);
- return tex;
-}
-
-int main(int argc, char **argv)
-{
- gtk_init(&argc, &argv);
-
- GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- GtkWidget *drawing = gtk_drawing_area_new();
- GdkGLConfig *glconfig = gdk_gl_config_new_by_mode((GdkGLConfigMode)(
- GDK_GL_MODE_RGBA | GDK_GL_MODE_DEPTH |
- GDK_GL_MODE_DOUBLE | GDK_GL_MODE_ALPHA));
- g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
- g_signal_connect(window, "key-press-event", G_CALLBACK(on_key_press), NULL);
- g_signal_connect(drawing, "expose-event", G_CALLBACK(on_expose), NULL);
- g_signal_connect(drawing, "configure-event", G_CALLBACK(on_configure), NULL);
- gtk_widget_set_gl_capability(drawing, glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE);
- gtk_container_add(GTK_CONTAINER(window), drawing);
- gtk_widget_show_all(window);
-
- /* OpenGL setup */
- GdkGLContext *glcontext = gtk_widget_get_gl_context(GTK_WIDGET(drawing));
- GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(GTK_WIDGET(drawing));
- gdk_gl_drawable_gl_begin(gldrawable, glcontext);
-
- /* Load texture */
- texl = load_tex("texls.png");
- texr = load_tex("texrs.png");
- tex = load_tex("tex.png");
-
- gtk_main();
-
- gdk_gl_drawable_gl_end(gldrawable);
-}
#!/bin/bash
dir=$(dirname $(readlink -f $0))
+# "--libdir=$dir/src/plugins"
+# "--datadir=$dir/data"
./autogen.sh \
- "--libdir=$dir/src/plugins" \
- "--datadir=$dir/data" \
--enable-gtk-doc \
CFLAGS="-g -Werror -Wno-unused $CFLAGS" \
LDFLAGS="-Wl,-z,defs"
-SUBDIRS = gis plugins
+SUBDIRS = plugins
AM_CFLAGS = -Wall --std=gnu99
-AM_CPPFLAGS = $(GLIB_CFLAGS) $(GTK_CFLAGS) $(SOUP_CFLAGS)
-AM_LDADD = $(GLIB_LIBS) $(GTK_LIBS) $(SOUP_LIBS)
+AM_CPPFLAGS = $(GIS_CFLAGS)
+LIBS = $(GIS_LIBS)
bin_PROGRAMS = aweather wsr88ddec
aweather_SOURCES = main.c \
aweather-gui.c aweather-gui.h \
aweather-location.c aweather-location.h
aweather_CPPFLAGS = $(AM_CPPFLAGS) -DDATADIR="\"$(datadir)\""
-aweather_LDADD = $(AM_LDADD) gis/libgis.la
wsr88ddec = wsr88ddec.c
wsr88ddec_LDADD = -lbz2
MAINTAINERCLEANFILES = Makefile.in
test: all
- LD_LIBRARY_PATH=gis/.libs .libs/aweather -o -d 7 -s KVNX
+ aweather -o -d 7 -s KVNX
gdb: all
- LD_LIBRARY_PATH=gis/.libs gdb .libs/aweather
+ gdb aweather
ddd: all
- LD_LIBRARY_PATH=gis/.libs ddd .libs/aweather
+ ddd aweather
+++ /dev/null
-*.pc
-gis-marshal.*
-gis_test
-wms_test
+++ /dev/null
-set makeprg=make\ test
-set tw=100
+++ /dev/null
-AM_CFLAGS = -Wall --std=gnu99
-AM_CPPFLAGS = $(GLIB_CFLAGS) $(GTK_CFLAGS) $(SOUP_CFLAGS)
-AM_LDADD = $(GLIB_LIBS) $(GTK_LIBS) $(SOUP_LIBS)
-
-# Library
-BUILT_SOURCES = gis-marshal.c gis-marshal.h
-lib_LTLIBRARIES = libgis.la
-gis_includedir = $(includedir)/gis
-gis_include_HEADERS = \
- gis.h \
- gis-world.h \
- gis-view.h \
- gis-prefs.h \
- gis-opengl.h \
- gis-plugin.h \
- gis-data.h \
- gpqueue.h \
- roam.h \
- wms.h
-libgis_la_SOURCES = \
- gis-world.c gis-world.h \
- gis-view.c gis-view.h \
- gis-prefs.c gis-prefs.h \
- gis-opengl.c gis-opengl.h \
- gis-plugin.c gis-plugin.h \
- gis-marshal.c gis-marshal.h \
- gis-data.c gis-data.h \
- roam.c roam.h \
- wms.c wms.h \
- gpqueue.c gpqueue.h
-libgis_la_CPPFLAGS = $(AM_CPPFLAGS) \
- -DDATADIR="\"$(datadir)\"" -DPLUGINDIR="\"$(libdir)/gis\""
-libgis_la_LIBADD = $(AM_LDADD)
-
-pkgconfigdir = $(libdir)/pkgconfig
-pkgconfig_DATA = libgis.pc
-
-# Test programs
-bin_PROGRAMS = gis_test wms_test
-
-gis_test_SOURCES = gis_test.c gis.h
-gis_test_LDADD = $(AM_LDADD) .libs/libgis.a
-
-wms_test_SOURCES = wms_test.c gis-world.c gis-world.h wms.c wms.h
-wms_test_LDADD = $(AM_LDADD)
-
-MAINTAINERCLEANFILES = Makefile.in
-
-.list.c:
- glib-genmarshal --prefix=gis_cclosure_marshal --body $< > $@
-.list.h:
- glib-genmarshal --prefix=gis_cclosure_marshal --header $< > $@
-
-test: all
- make -C ../plugins all
- ./gis_test
-
-gdb: all
- LD_LIBRARY_PATH=.libs gdb .libs/gis_test
-
-ddd: all
- LD_LIBRARY_PATH=.libs ddd .libs/gis_test
-
-memcheck: all
- LD_LIBRARY_PATH=.libs \
- G_SLICE=always-malloc \
- G_DEBUG=gc-friendly,resident-modules \
- valgrind --track-origins=yes \
- --leak-check=full \
- --leak-resolution=high \
- --num-callers=100 \
- --suppressions=../gtk.suppression \
- .libs/gis_test \
- 2> valgrind.out
+++ /dev/null
-/*
- * 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 <stdio.h>
-#include <glib.h>
-#include <libsoup/soup.h>
-
-#include "gis-data.h"
-
-typedef struct {
- gchar *uri;
- gchar *local;
- FILE *fp;
- GisDataCacheDoneCallback user_done_cb;
- GisDataCacheChunkCallback user_chunk_cb;
- gpointer user_data;
-} cache_file_end_t;
-
-/*
- * Open a file, creating parent directories if needed
- */
-static FILE *fopen_p(const gchar *path, const gchar *mode)
-{
- gchar *parent = g_path_get_dirname(path);
- if (!g_file_test(parent, G_FILE_TEST_EXISTS))
- g_mkdir_with_parents(parent, 0755);
- g_free(parent);
- return fopen(path, mode);
-}
-
-static void done_cb(SoupSession *session, SoupMessage *message, gpointer _info)
-{
- cache_file_end_t *info = _info;
- g_debug("data: done_cb");
-
- if (message->status_code == 416)
- /* Range unsatisfiable, file already complete */
- info->user_done_cb(info->local, FALSE, info->user_data);
- else if (SOUP_STATUS_IS_SUCCESSFUL(message->status_code))
- info->user_done_cb(info->local, TRUE, info->user_data);
- else
- g_warning("data: done_cb - error copying file, status=%d\n"
- "\tsrc=%s\n"
- "\tdst=%s",
- message->status_code, info->uri, info->local);
- g_free(info->uri);
- g_free(info->local);
- fclose(info->fp);
- g_free(info);
- //g_object_unref(session); This is probably leaking
-}
-
-void chunk_cb(SoupMessage *message, SoupBuffer *chunk, gpointer _info)
-{
- cache_file_end_t *info = _info;
- if (!SOUP_STATUS_IS_SUCCESSFUL(message->status_code))
- return;
-
- if (!fwrite(chunk->data, chunk->length, 1, info->fp))
- g_error("data: chunk_cb - Unable to write data");
- goffset cur = ftell(info->fp);
- //goffset total = soup_message_headers_get_range(message->response_headers);
- goffset start=0, end=0, total=0;
- soup_message_headers_get_content_range(message->response_headers,
- &start, &end, &total);
-
- if (info->user_chunk_cb)
- info->user_chunk_cb(info->local, cur, total, info->user_data);
-}
-
-static SoupSession *do_cache(cache_file_end_t *info, gboolean truncate, gchar *reason)
-{
- char *name = g_path_get_basename(info->uri);
- g_debug("data: do_cache - Caching file %s: %s", name, reason);
- g_free(name);
-
- /* TODO: move this to callback so we don't end up with 0 byte files
- * Then change back to check for valid file after download */
- if (truncate) info->fp = fopen_p(info->local, "w");
- else info->fp = fopen_p(info->local, "a");
- long bytes = ftell(info->fp);
-
- SoupSession *session = soup_session_async_new();
- g_object_set(session, "user-agent", PACKAGE_STRING, NULL);
- SoupMessage *message = soup_message_new("GET", info->uri);
- if (message == NULL)
- g_error("message is null, cannot parse uri");
- g_signal_connect(message, "got-chunk", G_CALLBACK(chunk_cb), info);
- soup_message_headers_set_range(message->request_headers, bytes, -1);
- soup_session_queue_message(session, message, done_cb, info);
- return session;
-}
-
-/*
- * Cache a image from Ridge to the local disk
- * \param path Path to the Ridge file, starting after /ridge/
- * \return The local path to the cached image
- */
-SoupSession *cache_file(char *base, char *path, GisDataCacheType update,
- GisDataCacheChunkCallback user_chunk_cb,
- GisDataCacheDoneCallback user_done_cb,
- gpointer user_data)
-{
- g_debug("GisData: cache_file - base=%s, path=%s", base, path);
- if (base == NULL) {
- g_warning("GisData: cache_file - base is null");
- return NULL;
- }
- if (path == NULL) {
- g_warning("GisData: cache_file - base is null");
- return NULL;
- }
- cache_file_end_t *info = g_malloc0(sizeof(cache_file_end_t));
- info->uri = g_strconcat(base, path, NULL);
- info->local = g_build_filename(g_get_user_cache_dir(), PACKAGE, path, NULL);
- info->fp = NULL;
- info->user_chunk_cb = user_chunk_cb;
- info->user_done_cb = user_done_cb;
- info->user_data = user_data;
-
- if (update == GIS_REFRESH)
- return do_cache(info, TRUE, "cache forced");
-
- if (update == GIS_UPDATE)
- return do_cache(info, FALSE, "attempting updating");
-
- if (update == GIS_ONCE && !g_file_test(info->local, G_FILE_TEST_EXISTS))
- return do_cache(info, TRUE, "local does not exist");
-
- /* No nead to cache, run the callback now and clean up */
- user_done_cb(info->local, FALSE, user_data);
- g_free(info->uri);
- g_free(info->local);
- g_free(info);
- return NULL;
-}
+++ /dev/null
-/*
- * 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 __DATA_H__
-#define __DATA_H__
-
-#include <libsoup/soup.h>
-
-typedef enum {
- GIS_ONCE, // Cache the file if it does not exist
- GIS_UPDATE, // Append additional data to cached copy (resume)
- GIS_REFRESH, // Delete existing file and cache a new copy
-} GisDataCacheType;
-
-typedef void (*GisDataCacheDoneCallback)(gchar *file, gboolean updated,
- gpointer user_data);
-
-typedef void (*GisDataCacheChunkCallback)(gchar *file, goffset cur,
- goffset total, gpointer user_data);
-
-SoupSession *cache_file(char *base, char *path, GisDataCacheType update,
- GisDataCacheChunkCallback user_chunk_cb,
- GisDataCacheDoneCallback user_done_cb,
- gpointer user_data);
-
-#endif
+++ /dev/null
-VOID:DOUBLE,DOUBLE,DOUBLE
-VOID:STRING,UINT,POINTER
+++ /dev/null
-/*
- * 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/>.
- */
-
-/* Tessellation, "finding intersecting triangles" */
-/* http://research.microsoft.com/pubs/70307/tr-2006-81.pdf */
-/* http://www.opengl.org/wiki/Alpha_Blending */
-
-#include <config.h>
-#include <math.h>
-#include <gdk/gdkkeysyms.h>
-#include <gtk/gtk.h>
-#include <gtk/gtkgl.h>
-#include <GL/gl.h>
-#include <GL/glu.h>
-
-#include "gis-opengl.h"
-#include "roam.h"
-#include "wms.h"
-
-#define FOV_DIST 2000.0
-#define MPPX(dist) (4*dist/FOV_DIST)
-
-// #define ROAM_DEBUG
-
-/*************
- * ROAM Code *
- *************/
-void roam_queue_draw(WmsCacheNode *node, gpointer _self)
-{
- gtk_widget_queue_draw(GTK_WIDGET(_self));
-}
-
-void roam_height_func(RoamPoint *point, gpointer _self)
-{
- GisOpenGL *self = _self;
-
- gdouble lat, lon, elev;
- xyz2lle(point->x, point->y, point->z, &lat, &lon, &elev);
-
-#ifdef ROAM_DEBUG
- lle2xyz(lat, lon, 0, &point->x, &point->y, &point->z);
- return;
-#endif
-
- gdouble cam_lle[3], cam_xyz[3];
- gis_view_get_location(self->view, &cam_lle[0], &cam_lle[1], &cam_lle[2]);
- lle2xyz(cam_lle[0], cam_lle[1], cam_lle[2], &cam_xyz[0], &cam_xyz[1], &cam_xyz[2]);
-
- gdouble res = MPPX(distd(cam_xyz, (double*)point));
- //g_message("lat=%f, lon=%f, res=%f", lat, lon, res);
-
- point->node = wms_info_fetch_cache(self->srtm, point->node,
- res, lat, lon, NULL, roam_queue_draw, self);
-
- if (point->node) {
- WmsBil *bil = point->node->data;
-
- gint w = bil->width;
- gint h = bil->height;
-
- gdouble xmin = point->node->latlon[0];
- gdouble ymin = point->node->latlon[1];
- gdouble xmax = point->node->latlon[2];
- gdouble ymax = point->node->latlon[3];
-
- gdouble xdist = xmax - xmin;
- gdouble ydist = ymax - ymin;
-
- gdouble x = (lon-xmin)/xdist * w;
- gdouble y = (1-(lat-ymin)/ydist) * h;
-
- gdouble x_rem = x - (int)x;
- gdouble y_rem = y - (int)y;
- guint x_flr = (int)x;
- guint y_flr = (int)y;
-
- /* TODO: Fix interpolation at edges:
- * - Pad these at the edges instead of wrapping/truncating
- * - Figure out which pixels to index (is 0,0 edge, center, etc) */
- gint16 px00 = bil->data[MIN((y_flr ),h-1)*w + MIN((x_flr ),w-1)];
- gint16 px10 = bil->data[MIN((y_flr ),h-1)*w + MIN((x_flr+1),w-1)];
- gint16 px01 = bil->data[MIN((y_flr+1),h-1)*w + MIN((x_flr ),w-1)];
- gint16 px11 = bil->data[MIN((y_flr+1),h-1)*w + MIN((x_flr+1),w-1)];
-
- elev = px00 * (1-x_rem) * (1-y_rem) +
- px10 * ( x_rem) * (1-y_rem) +
- px01 * (1-x_rem) * ( y_rem) +
- px11 * ( x_rem) * ( y_rem);
- //g_message("elev=%f -- %hd %hd %hd %hd",
- // elev, px00, px10, px01, px11);
- } else {
- elev = 0;
- }
-
- lle2xyz(lat, lon, elev, &point->x, &point->y, &point->z);
-}
-
-void roam_tri_func(RoamTriangle *tri, gpointer _self)
-{
-#ifdef ROAM_DEBUG
- glBegin(GL_TRIANGLES);
- glNormal3dv(tri->p.r->norm); glVertex3dv((double*)tri->p.r);
- glNormal3dv(tri->p.m->norm); glVertex3dv((double*)tri->p.m);
- glNormal3dv(tri->p.l->norm); glVertex3dv((double*)tri->p.l);
- glEnd();
- return;
-#endif
-
- GisOpenGL *self = _self;
- if (tri->error < 0) return;
-
- /* Get lat-lon min and maxes for the triangle */
- gdouble lat[3], lon[3], elev[3];
- xyz2lle(tri->p.r->x, tri->p.r->y, tri->p.r->z, &lat[0], &lon[0], &elev[0]);
- xyz2lle(tri->p.m->x, tri->p.m->y, tri->p.m->z, &lat[1], &lon[1], &elev[1]);
- xyz2lle(tri->p.l->x, tri->p.l->y, tri->p.l->z, &lat[2], &lon[2], &elev[2]);
- gdouble lat_max = MAX(MAX(lat[0], lat[1]), lat[2]);
- gdouble lat_min = MIN(MIN(lat[0], lat[1]), lat[2]);
- gdouble lat_avg = (lat_min+lat_max)/2;
- gdouble lon_max = MAX(MAX(lon[0], lon[1]), lon[2]);
- gdouble lon_min = MIN(MIN(lon[0], lon[1]), lon[2]);
- gdouble lon_avg = (lon_min+lon_max)/2;
-
- /* Get target resolution */
- gdouble cam_lle[3], cam_xyz[3];
- gis_view_get_location(self->view, &cam_lle[0], &cam_lle[1], &cam_lle[2]);
- lle2xyz(cam_lle[0], cam_lle[1], cam_lle[2], &cam_xyz[0], &cam_xyz[1], &cam_xyz[2]);
- gdouble distr = distd(cam_xyz, (double*)tri->p.r);
- gdouble distm = distd(cam_xyz, (double*)tri->p.m);
- gdouble distl = distd(cam_xyz, (double*)tri->p.l);
- double res = MPPX(MIN(MIN(distr, distm), distl));
-
- /* TODO:
- * - Fetch needed textures, not all corners
- * - Also fetch center textures that aren't touched by a corner
- * - Idea: send {lat,lon}{min,max} to fetch_cache and handle it in the recursion */
- /* Fetch textures */
- tri->nodes[0] = wms_info_fetch_cache(self->bmng, tri->nodes[0], res, lat_min, lon_min, NULL, roam_queue_draw, self);
- tri->nodes[1] = wms_info_fetch_cache(self->bmng, tri->nodes[1], res, lat_max, lon_min, NULL, roam_queue_draw, self);
- tri->nodes[2] = wms_info_fetch_cache(self->bmng, tri->nodes[2], res, lat_min, lon_max, NULL, roam_queue_draw, self);
- tri->nodes[3] = wms_info_fetch_cache(self->bmng, tri->nodes[3], res, lat_max, lon_max, NULL, roam_queue_draw, self);
- tri->nodes[4] = wms_info_fetch_cache(self->bmng, tri->nodes[4], res, lat_avg, lon_avg, NULL, roam_queue_draw, self);
- /* Hopefully get all textures at the same resolution to prevent overlaps */
- //gdouble maxres = 0;
- //for (int i = 0; i < 5; i++)
- // if (tri->nodes[i] && tri->nodes[i]->res > maxres)
- // maxres = tri->nodes[i]->res;
- //if (maxres != 0) {
- // tri->nodes[0] = wms_info_fetch_cache(self->bmng, tri->nodes[0], maxres, lat_min, lon_min, NULL, roam_queue_draw, self);
- // tri->nodes[1] = wms_info_fetch_cache(self->bmng, tri->nodes[1], maxres, lat_max, lon_min, NULL, roam_queue_draw, self);
- // tri->nodes[2] = wms_info_fetch_cache(self->bmng, tri->nodes[2], maxres, lat_min, lon_max, NULL, roam_queue_draw, self);
- // tri->nodes[3] = wms_info_fetch_cache(self->bmng, tri->nodes[3], maxres, lat_max, lon_max, NULL, roam_queue_draw, self);
- // tri->nodes[4] = wms_info_fetch_cache(self->bmng, tri->nodes[4], maxres, lat_avg, lon_avg, NULL, roam_queue_draw, self);
- //}
-
- /* Vertex color for hieght map viewing, 8848m == Everest */
- gfloat colors[] = {
- (elev[0]-EARTH_R)/8848,
- (elev[1]-EARTH_R)/8848,
- (elev[2]-EARTH_R)/8848,
- };
-
- /* Draw each texture */
- /* TODO: Prevent double exposure when of hi-res textures on top of
- * low-res textures when some high-res textures are not yet loaded. */
- glBlendFunc(GL_ONE, GL_ZERO);
- for (int i = 0; i < 5; i++) {
- /* Skip missing textures */
- if (tri->nodes[i] == NULL)
- continue;
- /* Skip already drawn textures */
- switch (i) {
- case 4: if (tri->nodes[i] == tri->nodes[3]) continue;
- case 3: if (tri->nodes[i] == tri->nodes[2]) continue;
- case 2: if (tri->nodes[i] == tri->nodes[1]) continue;
- case 1: if (tri->nodes[i] == tri->nodes[0]) continue;
- }
-
- WmsCacheNode *node = tri->nodes[i];
-
- if (node->latlon[0] == -180) {
- if (lon[0] < -90 || lon[1] < -90 || lon[2] < -90) {
- if (lon[0] > 90) lon[0] -= 360;
- if (lon[1] > 90) lon[1] -= 360;
- if (lon[2] > 90) lon[2] -= 360;
- }
- } else if (node->latlon[2] == 180.0) {
- if (lon[0] < -90) lon[0] += 360;
- if (lon[1] < -90) lon[1] += 360;
- if (lon[2] < -90) lon[2] += 360;
- }
-
- gdouble xmin = node->latlon[0];
- gdouble ymin = node->latlon[1];
- gdouble xmax = node->latlon[2];
- gdouble ymax = node->latlon[3];
-
- gdouble xdist = xmax - xmin;
- gdouble ydist = ymax - ymin;
-
- gdouble xy[][3] = {
- {(lon[0]-xmin)/xdist, 1-(lat[0]-ymin)/ydist},
- {(lon[1]-xmin)/xdist, 1-(lat[1]-ymin)/ydist},
- {(lon[2]-xmin)/xdist, 1-(lat[2]-ymin)/ydist},
- };
-
- glBindTexture(GL_TEXTURE_2D, *(guint*)node->data);
-
- glBegin(GL_TRIANGLES);
- glColor3fv(colors); glNormal3dv(tri->p.r->norm); glTexCoord2dv(xy[0]); glVertex3dv((double*)tri->p.r);
- glColor3fv(colors); glNormal3dv(tri->p.m->norm); glTexCoord2dv(xy[1]); glVertex3dv((double*)tri->p.m);
- glColor3fv(colors); glNormal3dv(tri->p.l->norm); glTexCoord2dv(xy[2]); glVertex3dv((double*)tri->p.l);
- glEnd();
- glBlendFunc(GL_ONE, GL_ONE);
- }
-}
-
-static void set_camera(GisOpenGL *self)
-{
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- double lat, lon, elev, rx, ry, rz;
- gis_view_get_location(self->view, &lat, &lon, &elev);
- gis_view_get_rotation(self->view, &rx, &ry, &rz);
- glRotatef(rx, 1, 0, 0);
- glRotatef(rz, 0, 0, 1);
- glTranslatef(0, 0, -elev2rad(elev));
- glRotatef(lat, 1, 0, 0);
- glRotatef(-lon, 0, 1, 0);
-}
-
-static void set_visuals(GisOpenGL *self)
-{
- /* Lighting */
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
-#ifdef ROAM_DEBUG
- float light_ambient[] = {0.7f, 0.7f, 0.7f, 1.0f};
- float light_diffuse[] = {2.0f, 2.0f, 2.0f, 1.0f};
-#else
- float light_ambient[] = {0.2f, 0.2f, 0.2f, 1.0f};
- float light_diffuse[] = {5.0f, 5.0f, 5.0f, 1.0f};
-#endif
- float light_position[] = {-13*EARTH_R, 1*EARTH_R, 3*EARTH_R, 1.0f};
- glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
- glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
- glLightfv(GL_LIGHT0, GL_POSITION, light_position);
- glEnable(GL_LIGHT0);
- glEnable(GL_LIGHTING);
-
- float material_ambient[] = {0.2, 0.2, 0.2, 1.0};
- float material_diffuse[] = {0.8, 0.8, 0.8, 1.0};
- float material_specular[] = {0.0, 0.0, 0.0, 1.0};
- float material_emission[] = {0.0, 0.0, 0.0, 1.0};
- glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, material_ambient);
- glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material_diffuse);
- glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, material_specular);
- glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, material_emission);
- glDisable(GL_TEXTURE_2D);
- glDisable(GL_COLOR_MATERIAL);
-
- /* Camera */
- set_camera(self);
-
- /* Misc */
- gdouble lat, lon, elev;
- gis_view_get_location(self->view, &lat, &lon, &elev);
- gdouble rg = MAX(0, 1-(elev/20000));
- gdouble blue = MAX(0, 1-(elev/50000));
- glClearColor(MIN(0.65,rg), MIN(0.65,rg), MIN(1,blue), 1.0f);
-
- glDisable(GL_ALPHA_TEST);
-
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_BLEND);
-
-#ifndef ROAM_DEBUG
- glCullFace(GL_BACK);
- glEnable(GL_CULL_FACE);
-#endif
-
- glClearDepth(1.0);
- glDepthFunc(GL_LEQUAL);
- glEnable(GL_DEPTH_TEST);
-
- glEnable(GL_LINE_SMOOTH);
-
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- //glShadeModel(GL_FLAT);
-}
-
-
-/*************
- * Callbacks *
- *************/
-static void on_realize(GisOpenGL *self, gpointer _)
-{
- set_visuals(self);
-}
-static gboolean on_configure(GisOpenGL *self, GdkEventConfigure *event, gpointer _)
-{
- g_debug("GisOpenGL: on_confiure");
- gis_opengl_begin(self);
-
- double width = GTK_WIDGET(self)->allocation.width;
- double height = GTK_WIDGET(self)->allocation.height;
- glViewport(0, 0, width, height);
-
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- double ang = atan(height/FOV_DIST);
- gluPerspective(rad2deg(ang)*2, width/height, 1, 20*EARTH_R);
-
-#ifndef ROAM_DEBUG
- roam_sphere_update(self->sphere);
-#endif
-
- gis_opengl_end(self);
- return FALSE;
-}
-
-static void on_expose_plugin(GisPlugin *plugin, gchar *name, GisOpenGL *self)
-{
- set_visuals(self);
- glMatrixMode(GL_PROJECTION); glPushMatrix();
- glMatrixMode(GL_MODELVIEW); glPushMatrix();
- gis_plugin_expose(plugin);
- glMatrixMode(GL_PROJECTION); glPopMatrix();
- glMatrixMode(GL_MODELVIEW); glPopMatrix();
-}
-static gboolean on_expose(GisOpenGL *self, GdkEventExpose *event, gpointer _)
-{
- g_debug("GisOpenGL: on_expose - begin");
- gis_opengl_begin(self);
-
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
-#ifndef ROAM_DEBUG
- set_visuals(self);
- glEnable(GL_TEXTURE_2D);
- roam_sphere_draw(self->sphere);
-#endif
-
-#ifdef ROAM_DEBUG
- set_visuals(self);
- glColor4f(0.0, 0.0, 9.0, 0.6);
- glDisable(GL_TEXTURE_2D);
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- roam_sphere_draw(self->sphere);
-#endif
-
- //glDisable(GL_TEXTURE_2D);
- //glEnable(GL_COLOR_MATERIAL);
- //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- //roam_sphere_draw(self->sphere);
-
- gis_plugins_foreach(self->plugins, G_CALLBACK(on_expose_plugin), self);
-
- set_visuals(self);
- gis_opengl_end(self);
- gis_opengl_flush(self);
- g_debug("GisOpenGL: on_expose - end\n");
- return FALSE;
-}
-
-static gboolean on_button_press(GisOpenGL *self, GdkEventButton *event, gpointer _)
-{
- g_debug("GisOpenGL: on_button_press - Grabbing focus");
- gtk_widget_grab_focus(GTK_WIDGET(self));
- return TRUE;
-}
-
-static gboolean on_key_press(GisOpenGL *self, GdkEventKey *event, gpointer _)
-{
- g_debug("GisOpenGL: on_key_press - key=%x, state=%x, plus=%x",
- event->keyval, event->state, GDK_plus);
-
- double lat, lon, elev, pan;
- gis_view_get_location(self->view, &lat, &lon, &elev);
- pan = MIN(elev/(EARTH_R/2), 30);
- guint kv = event->keyval;
- if (kv == GDK_Left || kv == GDK_h) gis_view_pan(self->view, 0, -pan, 0);
- else if (kv == GDK_Down || kv == GDK_j) gis_view_pan(self->view, -pan, 0, 0);
- else if (kv == GDK_Up || kv == GDK_k) gis_view_pan(self->view, pan, 0, 0);
- else if (kv == GDK_Right || kv == GDK_l) gis_view_pan(self->view, 0, pan, 0);
- else if (kv == GDK_minus || kv == GDK_o) gis_view_zoom(self->view, 10./9);
- else if (kv == GDK_plus || kv == GDK_i) gis_view_zoom(self->view, 9./10);
- else if (kv == GDK_H) gis_view_rotate(self->view, 0, 0, -10);
- else if (kv == GDK_J) gis_view_rotate(self->view, 10, 0, 0);
- else if (kv == GDK_K) gis_view_rotate(self->view, -10, 0, 0);
- else if (kv == GDK_L) gis_view_rotate(self->view, 0, 0, 10);
-
- /* Testing */
-#ifdef ROAM_DEBUG
- else if (kv == GDK_n) roam_sphere_split_one(self->sphere);
- else if (kv == GDK_p) roam_sphere_merge_one(self->sphere);
- else if (kv == GDK_r) roam_sphere_split_merge(self->sphere);
- else if (kv == GDK_u) roam_sphere_update(self->sphere);
- gtk_widget_queue_draw(GTK_WIDGET(self));
-#endif
-
- return TRUE;
-}
-
-static void on_view_changed(GisView *view,
- gdouble _1, gdouble _2, gdouble _3, GisOpenGL *self)
-{
- gis_opengl_begin(self);
- set_visuals(self);
-#ifndef ROAM_DEBUG
- roam_sphere_update(self->sphere);
-#endif
- gis_opengl_redraw(self);
- gis_opengl_end(self);
-}
-
-static gboolean on_idle(GisOpenGL *self)
-{
- gis_opengl_begin(self);
- if (roam_sphere_split_merge(self->sphere))
- gis_opengl_redraw(self);
- gis_opengl_end(self);
- return TRUE;
-}
-
-
-/***********
- * Methods *
- ***********/
-GisOpenGL *gis_opengl_new(GisWorld *world, GisView *view, GisPlugins *plugins)
-{
- g_debug("GisOpenGL: new");
- GisOpenGL *self = g_object_new(GIS_TYPE_OPENGL, NULL);
- self->world = world;
- self->view = view;
- self->plugins = plugins;
- g_object_ref(world);
- g_object_ref(view);
-
- g_signal_connect(self->view, "location-changed", G_CALLBACK(on_view_changed), self);
- g_signal_connect(self->view, "rotation-changed", G_CALLBACK(on_view_changed), self);
-
- /* TODO: update point eights sometime later so we have heigh-res heights for them */
- self->sphere = roam_sphere_new(roam_tri_func, roam_height_func, self);
-
- return g_object_ref(self);
-}
-
-void gis_opengl_center_position(GisOpenGL *self, gdouble lat, gdouble lon, gdouble elev)
-{
- set_camera(self);
- glRotatef(lon, 0, 1, 0);
- glRotatef(-lat, 1, 0, 0);
- glTranslatef(0, 0, elev2rad(elev));
-}
-
-void gis_opengl_redraw(GisOpenGL *self)
-{
- g_debug("GisOpenGL: gl_redraw");
- gtk_widget_queue_draw(GTK_WIDGET(self));
-}
-void gis_opengl_begin(GisOpenGL *self)
-{
- g_assert(GIS_IS_OPENGL(self));
-
- GdkGLContext *glcontext = gtk_widget_get_gl_context(GTK_WIDGET(self));
- GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(GTK_WIDGET(self));
-
- if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext))
- g_assert_not_reached();
-}
-void gis_opengl_end(GisOpenGL *self)
-{
- g_assert(GIS_IS_OPENGL(self));
- GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(GTK_WIDGET(self));
- gdk_gl_drawable_gl_end(gldrawable);
-}
-void gis_opengl_flush(GisOpenGL *self)
-{
- g_assert(GIS_IS_OPENGL(self));
- GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(GTK_WIDGET(self));
- if (gdk_gl_drawable_is_double_buffered(gldrawable))
- gdk_gl_drawable_swap_buffers(gldrawable);
- else
- glFlush();
- gdk_gl_drawable_gl_end(gldrawable);
-}
-
-
-/****************
- * GObject code *
- ****************/
-G_DEFINE_TYPE(GisOpenGL, gis_opengl, GTK_TYPE_DRAWING_AREA);
-static void gis_opengl_init(GisOpenGL *self)
-{
- g_debug("GisOpenGL: init");
- self->bmng = wms_info_new_for_bmng(NULL, NULL);
- self->srtm = wms_info_new_for_srtm(NULL, NULL);
-
- /* OpenGL setup */
- GdkGLConfig *glconfig = gdk_gl_config_new_by_mode(
- GDK_GL_MODE_RGBA | GDK_GL_MODE_DEPTH |
- GDK_GL_MODE_DOUBLE | GDK_GL_MODE_ALPHA);
- if (!glconfig)
- g_error("Failed to create glconfig");
- if (!gtk_widget_set_gl_capability(GTK_WIDGET(self),
- glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE))
- g_error("GL lacks required capabilities");
- g_object_unref(glconfig);
-
- gtk_widget_set_size_request(GTK_WIDGET(self), 600, 550);
- gtk_widget_set_events(GTK_WIDGET(self),
- GDK_BUTTON_PRESS_MASK |
- GDK_ENTER_NOTIFY_MASK |
- GDK_KEY_PRESS_MASK);
- g_object_set(self, "can-focus", TRUE, NULL);
-
-#ifndef ROAM_DEBUG
- self->sm_source = g_timeout_add(10, (GSourceFunc)on_idle, self);
-#endif
-
- g_signal_connect(self, "realize", G_CALLBACK(on_realize), NULL);
- g_signal_connect(self, "configure-event", G_CALLBACK(on_configure), NULL);
- g_signal_connect(self, "expose-event", G_CALLBACK(on_expose), NULL);
-
- g_signal_connect(self, "button-press-event", G_CALLBACK(on_button_press), NULL);
- g_signal_connect(self, "enter-notify-event", G_CALLBACK(on_button_press), NULL);
- g_signal_connect(self, "key-press-event", G_CALLBACK(on_key_press), NULL);
-}
-static GObject *gis_opengl_constructor(GType gtype, guint n_properties,
- GObjectConstructParam *properties)
-{
- g_debug("GisOpengl: constructor");
- GObjectClass *parent_class = G_OBJECT_CLASS(gis_opengl_parent_class);
- return parent_class->constructor(gtype, n_properties, properties);
-}
-static void gis_opengl_dispose(GObject *_self)
-{
- g_debug("GisOpenGL: dispose");
- GisOpenGL *self = GIS_OPENGL(_self);
- if (self->sm_source) {
- g_source_remove(self->sm_source);
- self->sm_source = 0;
- }
- if (self->sphere) {
- roam_sphere_free(self->sphere);
- self->sphere = NULL;
- }
- if (self->world) {
- g_object_unref(self->world);
- self->world = NULL;
- }
- if (self->view) {
- g_object_unref(self->view);
- self->view = NULL;
- }
- G_OBJECT_CLASS(gis_opengl_parent_class)->dispose(_self);
-}
-static void gis_opengl_finalize(GObject *_self)
-{
- g_debug("GisOpenGL: finalize");
- GisOpenGL *self = GIS_OPENGL(_self);
- wms_info_free(self->bmng);
- wms_info_free(self->srtm);
- G_OBJECT_CLASS(gis_opengl_parent_class)->finalize(_self);
-}
-static void gis_opengl_class_init(GisOpenGLClass *klass)
-{
- g_debug("GisOpenGL: class_init");
- GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
- gobject_class->constructor = gis_opengl_constructor;
- gobject_class->dispose = gis_opengl_dispose;
- gobject_class->finalize = gis_opengl_finalize;
-}
+++ /dev/null
-/*
- * 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_OPENGL_H__
-#define __GIS_OPENGL_H__
-
-#include <gtk/gtk.h>
-#include <gtk/gtkgl.h>
-#include <glib-object.h>
-
-/* Type macros */
-#define GIS_TYPE_OPENGL (gis_opengl_get_type())
-#define GIS_OPENGL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GIS_TYPE_OPENGL, GisOpenGL))
-#define GIS_IS_OPENGL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GIS_TYPE_OPENGL))
-#define GIS_OPENGL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIS_TYPE_OPENGL, GisOpenGLClass))
-#define GIS_IS_OPENGL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIS_TYPE_OPENGL))
-#define GIS_OPENGL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIS_TYPE_OPENGL, GisOpenGLClass))
-
-typedef struct _GisOpenGL GisOpenGL;
-typedef struct _GisOpenGLClass GisOpenGLClass;
-
-#include "gis-view.h"
-#include "gis-world.h"
-#include "gis-plugin.h"
-#include "roam.h"
-#include "wms.h"
-
-struct _GisOpenGL {
- GtkDrawingArea parent_instance;
-
- /* instance members */
- GisWorld *world;
- GisView *view;
- GisPlugins *plugins;
- RoamSphere *sphere;
- WmsInfo *bmng;
- WmsInfo *srtm;
- guint sm_source;
-};
-
-struct _GisOpenGLClass {
- GtkDrawingAreaClass parent_class;
-
- /* class members */
-};
-
-GType gis_opengl_get_type(void);
-
-/* Methods */
-GisOpenGL *gis_opengl_new(GisWorld *world, GisView *view, GisPlugins *plugins);
-
-void gis_opengl_center_position(GisOpenGL *gis, gdouble lat, gdouble lon, gdouble elev);
-
-void gis_opengl_redraw(GisOpenGL *gis);
-
-void gis_opengl_begin(GisOpenGL *gis);
-void gis_opengl_end(GisOpenGL *gis);
-void gis_opengl_flush(GisOpenGL *gis);
-
-#endif
+++ /dev/null
-/*
- * 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 <glib.h>
-#include <gmodule.h>
-
-#include "gis-plugin.h"
-
-/********************
- * Plugin interface *
- ********************/
-static void gis_plugin_base_init(gpointer g_class)
-{
- static gboolean is_initialized = FALSE;
- if (!is_initialized) {
- /* add properties and signals to the interface here */
- is_initialized = TRUE;
- }
-}
-
-GType gis_plugin_get_type()
-{
- static GType type = 0;
- if (type == 0) {
- static const GTypeInfo info = {
- sizeof(GisPluginInterface),
- gis_plugin_base_init,
- NULL,
- };
- type = g_type_register_static(G_TYPE_INTERFACE,
- "GisPlugin", &info, 0);
- }
- return type;
-}
-
-void gis_plugin_expose(GisPlugin *self)
-{
- g_return_if_fail(GIS_IS_PLUGIN(self));
- GIS_PLUGIN_GET_INTERFACE(self)->expose(self);
-}
-
-GtkWidget *gis_plugin_get_config(GisPlugin *self)
-{
- g_return_val_if_fail(GIS_IS_PLUGIN(self), NULL);
- return GIS_PLUGIN_GET_INTERFACE(self)->get_config(self);
-}
-
-
-/***************
- * Plugins API *
- ***************/
-typedef struct {
- gchar *name;
- GisPlugin *plugin;
-} GisPluginStore;
-
-GisPlugins *gis_plugins_new()
-{
- return g_ptr_array_new();
-}
-
-void gis_plugins_free(GisPlugins *self)
-{
- for (int i = 0; i < self->len; i++) {
- GisPluginStore *store = g_ptr_array_index(self, i);
- g_object_unref(store->plugin);
- g_free(store->name);
- g_free(store);
- g_ptr_array_remove_index(self, i);
- }
- g_ptr_array_free(self, TRUE);
-}
-
-GList *gis_plugins_available()
-{
- GDir *dir = g_dir_open(PLUGINDIR, 0, NULL);
- if (dir == NULL)
- return NULL;
- GList *list = NULL;
- const gchar *name;
- while ((name = g_dir_read_name(dir))) {
- if (g_pattern_match_simple("*.so", name)) {
- gchar **parts = g_strsplit(name, ".", 2);
- list = g_list_prepend(list, g_strdup(parts[0]));
- g_strfreev(parts);
- }
- }
- return list;
-}
-
-GisPlugin *gis_plugins_load(GisPlugins *self, const char *name,
- GisWorld *world, GisView *view, GisOpenGL *opengl, GisPrefs *prefs)
-{
- gchar *path = g_strdup_printf("%s/%s.%s", PLUGINDIR, name, G_MODULE_SUFFIX);
- GModule *module = g_module_open(path, 0);
- g_free(path);
- if (module == NULL) {
- g_warning("Unable to load module %s: %s", name, g_module_error());
- return NULL;
- }
-
- gpointer constructor_ptr; // GCC 4.1 fix?
- gchar *constructor_str = g_strconcat("gis_plugin_", name, "_new", NULL);
- if (!g_module_symbol(module, constructor_str, &constructor_ptr)) {
- g_warning("Unable to load symbol %s from %s: %s",
- constructor_str, name, g_module_error());
- g_module_close(module);
- g_free(constructor_str);
- return NULL;
- }
- g_free(constructor_str);
- GisPluginConstructor constructor = constructor_ptr;
-
- GisPluginStore *store = g_malloc(sizeof(GisPluginStore));
- store->name = g_strdup(name);
- store->plugin = constructor(world, view, opengl, prefs);
- g_ptr_array_add(self, store);
- return store->plugin;
-}
-
-gboolean gis_plugins_unload(GisPlugins *self, const char *name)
-{
- for (int i = 0; i < self->len; i++) {
- GisPluginStore *store = g_ptr_array_index(self, i);
- if (g_str_equal(store->name, name)) {
- g_object_unref(store->plugin);
- g_free(store->name);
- g_free(store);
- g_ptr_array_remove_index(self, i);
- }
- }
- return FALSE;
-}
-void gis_plugins_foreach(GisPlugins *self, GCallback _callback, gpointer user_data)
-{
- typedef void (*CBFunc)(GisPlugin *, const gchar *, gpointer);
- CBFunc callback = (CBFunc)_callback;
- for (int i = 0; i < self->len; i++) {
- GisPluginStore *store = g_ptr_array_index(self, i);
- callback(store->plugin, store->name, user_data);
- }
-}
+++ /dev/null
-/*
- * 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_PLUGIN_H__
-#define __GIS_PLUGIN_H__
-
-#include <glib-object.h>
-#include <gtk/gtk.h>
-
-#define GIS_TYPE_PLUGIN (gis_plugin_get_type())
-#define GIS_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIS_TYPE_PLUGIN, GisPlugin))
-#define GIS_IS_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIS_TYPE_PLUGIN))
-#define GIS_PLUGIN_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), GIS_TYPE_PLUGIN, GisPluginInterface))
-
-typedef struct _GisPlugin GisPlugin;
-typedef struct _GisPluginInterface GisPluginInterface;
-typedef GPtrArray GisPlugins;
-
-struct _GisPluginInterface
-{
- GTypeInterface parent_iface;
-
- /* Virtual functions */
- void (*expose )(GisPlugin *self);
- GtkWidget *(*get_config)(GisPlugin *self);
-};
-
-GType gis_plugin_get_type();
-
-/* Methods */
-void gis_plugin_expose(GisPlugin *self);
-GtkWidget *gis_plugin_get_config(GisPlugin *self);
-
-/* Plugins API */
-#include "gis-world.h"
-#include "gis-view.h"
-#include "gis-opengl.h"
-#include "gis-prefs.h"
-
-typedef GisPlugin *(*GisPluginConstructor)(GisWorld *world, GisView *view, GisOpenGL *opengl, GisPrefs *prefs);
-
-GisPlugins *gis_plugins_new();
-void gis_plugins_free();
-GList *gis_plugins_available();
-GisPlugin *gis_plugins_load(GisPlugins *self, const char *name,
- GisWorld *world, GisView *view, GisOpenGL *opengl, GisPrefs *prefs);
-gboolean gis_plugins_unload(GisPlugins *self, const char *name);
-void gis_plugins_foreach(GisPlugins *self, GCallback callback, gpointer user_data);
-
-#endif
+++ /dev/null
-/*
- * 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 <glib.h>
-#include "gis-marshal.h"
-#include "gis-prefs.h"
-
-
-enum {
- SIG_PREF_CHANGED,
- NUM_SIGNALS,
-};
-static guint signals[NUM_SIGNALS];
-
-
-/***********
- * Methods *
- ***********/
-GisPrefs *gis_prefs_new(const gchar *prog)
-{
- g_debug("GisPrefs: new - %s", prog);
- GisPrefs *self = g_object_new(GIS_TYPE_PREFS, NULL);
- self->key_path = g_build_filename(g_get_user_config_dir(),
- prog, "config.ini", NULL);
- GError *error = NULL;
- g_key_file_load_from_file(self->key_file, self->key_path,
- G_KEY_FILE_KEEP_COMMENTS, &error);
- if (error) {
- g_debug("GisPrefs: new - Trying %s defaults", prog);
- g_clear_error(&error);
- gchar *tmp = g_build_filename(DATADIR, prog, "defaults.ini", NULL);
- g_key_file_load_from_file(self->key_file, tmp,
- G_KEY_FILE_KEEP_COMMENTS, &error);
- g_free(tmp);
- }
- if (error) {
- g_debug("GisPrefs: new - Trying GIS defaults");
- g_clear_error(&error);
- gchar *tmp = g_build_filename(DATADIR, "gis", "defaults.ini", NULL);
- g_key_file_load_from_file(self->key_file, tmp,
- G_KEY_FILE_KEEP_COMMENTS, &error);
- g_free(tmp);
- }
- if (error) {
- g_clear_error(&error);
- g_warning("GisPrefs: new - Unable to load key file `%s': %s",
- self->key_path, error->message);
- }
- return self;
-}
-
-#define make_pref_type(name, c_type, g_type) \
-c_type gis_prefs_get_##name##_v(GisPrefs *self, \
- const gchar *group, const gchar *key) \
-{ \
- GError *error = NULL; \
- c_type value = g_key_file_get_##name(self->key_file, group, key, &error); \
- if (error && error->code != G_KEY_FILE_ERROR_GROUP_NOT_FOUND) \
- g_warning("GisPrefs: get_value_##name - error getting key %s: %s\n", \
- key, error->message); \
- return value; \
-} \
-c_type gis_prefs_get_##name(GisPrefs *self, const gchar *key) \
-{ \
- gchar **keys = g_strsplit(key, "/", 2); \
- c_type value = gis_prefs_get_##name##_v(self, keys[0], keys[1]); \
- g_strfreev(keys); \
- return value; \
-} \
- \
-void gis_prefs_set_##name##_v(GisPrefs *self, \
- const gchar *group, const gchar *key, const c_type value) \
-{ \
- g_key_file_set_##name(self->key_file, group, key, value); \
- gchar *all = g_strconcat(group, "/", key, NULL); \
- g_signal_emit(self, signals[SIG_PREF_CHANGED], 0, \
- all, g_type, &value); \
- g_free(all); \
-} \
-void gis_prefs_set_##name(GisPrefs *self, const gchar *key, const c_type value) \
-{ \
- gchar **keys = g_strsplit(key, "/", 2); \
- gis_prefs_set_##name##_v(self, keys[0], keys[1], value); \
- g_strfreev(keys); \
-} \
-
-make_pref_type(string, gchar*, G_TYPE_STRING)
-make_pref_type(boolean, gboolean, G_TYPE_BOOLEAN)
-make_pref_type(integer, gint, G_TYPE_INT)
-make_pref_type(double, gdouble, G_TYPE_DOUBLE)
-
-
-/****************
- * GObject code *
- ****************/
-G_DEFINE_TYPE(GisPrefs, gis_prefs, G_TYPE_OBJECT);
-static void gis_prefs_init(GisPrefs *self)
-{
- g_debug("GisPrefs: init");
- self->key_file = g_key_file_new();
-}
-static GObject *gis_prefs_constructor(GType gtype, guint n_properties,
- GObjectConstructParam *properties)
-{
- g_debug("gis_prefs: constructor");
- GObjectClass *parent_class = G_OBJECT_CLASS(gis_prefs_parent_class);
- return parent_class->constructor(gtype, n_properties, properties);
-}
-static void gis_prefs_dispose(GObject *_self)
-{
- g_debug("GisPrefs: dispose");
- GisPrefs *self = GIS_PREFS(_self);
- if (self->key_file) {
- gsize length;
- gchar *dir = g_path_get_dirname(self->key_path);
- g_mkdir_with_parents(dir, 0755);
- gchar *data = g_key_file_to_data(self->key_file, &length, NULL);
- g_file_set_contents(self->key_path, data, length, NULL);
- g_key_file_free(self->key_file);
- g_free(self->key_path);
- g_free(dir);
- g_free(data);
- self->key_file = NULL;
- }
- G_OBJECT_CLASS(gis_prefs_parent_class)->dispose(_self);
-}
-static void gis_prefs_finalize(GObject *_self)
-{
- g_debug("GisPrefs: finalize");
- G_OBJECT_CLASS(gis_prefs_parent_class)->finalize(_self);
-}
-static void gis_prefs_class_init(GisPrefsClass *klass)
-{
- g_debug("GisPrefs: class_init");
- GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
- gobject_class->constructor = gis_prefs_constructor;
- gobject_class->dispose = gis_prefs_dispose;
- gobject_class->finalize = gis_prefs_finalize;
- signals[SIG_PREF_CHANGED] = g_signal_new(
- "pref-changed",
- G_TYPE_FROM_CLASS(gobject_class),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL,
- NULL,
- gis_cclosure_marshal_VOID__STRING_UINT_POINTER,
- G_TYPE_NONE,
- 1,
- G_TYPE_STRING,
- G_TYPE_UINT,
- G_TYPE_POINTER);
-}
+++ /dev/null
-/*
- * 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_PREFS_H__
-#define __GIS_PREFS_H__
-
-#include <glib-object.h>
-
-/* Type macros */
-#define GIS_TYPE_PREFS (gis_prefs_get_type())
-#define GIS_PREFS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GIS_TYPE_PREFS, GisPrefs))
-#define GIS_IS_PREFS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GIS_TYPE_PREFS))
-#define GIS_PREFS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIS_TYPE_PREFS, GisPrefsClass))
-#define GIS_IS_PREFS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIS_TYPE_PREFS))
-#define GIS_PREFS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIS_TYPE_PREFS, GisPrefsClass))
-
-typedef struct _GisPrefs GisPrefs;
-typedef struct _GisPrefsClass GisPrefsClass;
-
-struct _GisPrefs {
- GObject parent_instance;
-
- /* instance members */
- gchar *key_path;
- GKeyFile *key_file;
-};
-
-struct _GisPrefsClass {
- GObjectClass parent_class;
-
- /* class members */
-};
-
-GType gis_prefs_get_type(void);
-
-/* Methods */
-GisPrefs *gis_prefs_new(const gchar *prog);
-
-gchar *gis_prefs_get_string (GisPrefs *prefs, const gchar *key);
-gboolean gis_prefs_get_boolean (GisPrefs *prefs, const gchar *key);
-gint gis_prefs_get_integer (GisPrefs *prefs, const gchar *key);
-gdouble gis_prefs_get_double (GisPrefs *prefs, const gchar *key);
-
-gchar *gis_prefs_get_string_v (GisPrefs *prefs, const gchar *group, const gchar *key);
-gboolean gis_prefs_get_boolean_v(GisPrefs *prefs, const gchar *group, const gchar *key);
-gint gis_prefs_get_integer_v(GisPrefs *prefs, const gchar *group, const gchar *key);
-gdouble gis_prefs_get_double_v (GisPrefs *prefs, const gchar *group, const gchar *key);
-
-void gis_prefs_set_string (GisPrefs *prefs, const gchar *key, const gchar *string);
-void gis_prefs_set_boolean (GisPrefs *prefs, const gchar *key, gboolean value);
-void gis_prefs_set_integer (GisPrefs *prefs, const gchar *key, gint value);
-void gis_prefs_set_double (GisPrefs *prefs, const gchar *key, gdouble value);
-
-void gis_prefs_set_string_v (GisPrefs *prefs, const gchar *group, const gchar *key, const gchar *string);
-void gis_prefs_set_boolean_v(GisPrefs *prefs, const gchar *group, const gchar *key, gboolean value);
-void gis_prefs_set_integer_v(GisPrefs *prefs, const gchar *group, const gchar *key, gint value);
-void gis_prefs_set_double_v (GisPrefs *prefs, const gchar *group, const gchar *key, gdouble value);
-#endif
+++ /dev/null
-/*
- * 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 <glib.h>
-
-#include "gis-marshal.h"
-#include "gis-view.h"
-#include "gis-world.h"
-
-/* Constants */
-enum {
- PROP_0,
- PROP_TIME,
- PROP_SITE,
-};
-enum {
- SIG_TIME_CHANGED,
- SIG_SITE_CHANGED,
- SIG_LOCATION_CHANGED,
- SIG_ROTATION_CHANGED,
- NUM_SIGNALS,
-};
-static guint signals[NUM_SIGNALS];
-
-
-/* Signal helpers */
-static void _gis_view_emit_location_changed(GisView *view)
-{
- g_signal_emit(view, signals[SIG_LOCATION_CHANGED], 0,
- view->location[0],
- view->location[1],
- view->location[2]);
-}
-static void _gis_view_emit_rotation_changed(GisView *view)
-{
- g_signal_emit(view, signals[SIG_ROTATION_CHANGED], 0,
- view->rotation[0],
- view->rotation[1],
- view->rotation[2]);
-}
-static void _gis_view_emit_time_changed(GisView *view)
-{
- g_signal_emit(view, signals[SIG_TIME_CHANGED], 0,
- view->time);
-}
-static void _gis_view_emit_site_changed(GisView *view)
-{
- g_signal_emit(view, signals[SIG_SITE_CHANGED], 0,
- view->site);
-}
-
-
-/***********
- * Methods *
- ***********/
-GisView *gis_view_new()
-{
- g_debug("GisView: new");
- return g_object_new(GIS_TYPE_VIEW, NULL);
-}
-
-void gis_view_set_time(GisView *view, const char *time)
-{
- g_assert(GIS_IS_VIEW(view));
- g_debug("GisView: set_time - time=%s", time);
- g_free(view->time);
- view->time = g_strdup(time);
- _gis_view_emit_time_changed(view);
-}
-
-gchar *gis_view_get_time(GisView *view)
-{
- g_assert(GIS_IS_VIEW(view));
- g_debug("GisView: get_time");
- return view->time;
-}
-
-void gis_view_set_location(GisView *view, gdouble lat, gdouble lon, gdouble elev)
-{
- g_assert(GIS_IS_VIEW(view));
- g_debug("GisView: set_location");
- view->location[0] = lat;
- view->location[1] = lon;
- view->location[2] = elev;
- _gis_view_emit_location_changed(view);
-}
-
-void gis_view_get_location(GisView *view, gdouble *lat, gdouble *lon, gdouble *elev)
-{
- g_assert(GIS_IS_VIEW(view));
- //g_debug("GisView: get_location");
- *lat = view->location[0];
- *lon = view->location[1];
- *elev = view->location[2];
-}
-
-void gis_view_pan(GisView *view, gdouble lat, gdouble lon, gdouble elev)
-{
- g_assert(GIS_IS_VIEW(view));
- g_debug("GisView: pan - lat=%8.3f, lon=%8.3f, elev=%8.3f", lat, lon, elev);
- view->location[0] += lat;
- view->location[1] += lon;
- view->location[2] += elev;
- _gis_view_emit_location_changed(view);
-}
-
-void gis_view_zoom(GisView *view, gdouble scale)
-{
- g_assert(GIS_IS_VIEW(view));
- g_debug("GisView: zoom");
- view->location[2] *= scale;
- _gis_view_emit_location_changed(view);
-}
-
-void gis_view_set_rotation(GisView *view, gdouble x, gdouble y, gdouble z)
-{
- g_assert(GIS_IS_VIEW(view));
- g_debug("GisView: set_rotation");
- view->rotation[0] = x;
- view->rotation[1] = y;
- view->rotation[2] = z;
- _gis_view_emit_rotation_changed(view);
-}
-
-void gis_view_get_rotation(GisView *view, gdouble *x, gdouble *y, gdouble *z)
-{
- g_assert(GIS_IS_VIEW(view));
- g_debug("GisView: get_rotation");
- *x = view->rotation[0];
- *y = view->rotation[1];
- *z = view->rotation[2];
-}
-
-void gis_view_rotate(GisView *view, gdouble x, gdouble y, gdouble z)
-{
- g_assert(GIS_IS_VIEW(view));
- g_debug("GisView: rotate - x=%.0f, y=%.0f, z=%.0f", x, y, z);
- view->rotation[0] += x;
- view->rotation[1] += y;
- view->rotation[2] += z;
- _gis_view_emit_rotation_changed(view);
-}
-
-/* To be deprecated, use {get,set}_location */
-void gis_view_set_site(GisView *view, const gchar *site)
-{
- g_assert(GIS_IS_VIEW(view));
- g_debug("GisView: set_site");
- g_free(view->site);
- view->site = g_strdup(site);
- _gis_view_emit_site_changed(view);
-}
-
-gchar *gis_view_get_site(GisView *view)
-{
- g_assert(GIS_IS_VIEW(view));
- g_debug("GisView: get_site - %s", view->site);
- return view->site;
-}
-
-
-/****************
- * GObject code *
- ****************/
-G_DEFINE_TYPE(GisView, gis_view, G_TYPE_OBJECT);
-static void gis_view_init(GisView *self)
-{
- g_debug("GisView: init");
- /* Default values */
- self->time = g_strdup("");
- self->site = g_strdup("");
- self->location[0] = 40;
- self->location[1] = -100;
- self->location[2] = 1.5*EARTH_R;
- self->rotation[0] = 0;
- self->rotation[1] = 0;
- self->rotation[2] = 0;
-}
-static void gis_view_dispose(GObject *gobject)
-{
- g_debug("GisView: dispose");
- /* Drop references to other GObjects */
- G_OBJECT_CLASS(gis_view_parent_class)->dispose(gobject);
-}
-static void gis_view_finalize(GObject *gobject)
-{
- g_debug("GisView: finalize");
- GisView *self = GIS_VIEW(gobject);
- g_free(self->time);
- g_free(self->site);
- G_OBJECT_CLASS(gis_view_parent_class)->finalize(gobject);
-}
-static void gis_view_set_property(GObject *object, guint property_id,
- const GValue *value, GParamSpec *pspec)
-{
- g_debug("GisView: set_property");
- GisView *self = GIS_VIEW(object);
- switch (property_id) {
- case PROP_TIME: gis_view_set_time(self, g_value_get_string(value)); break;
- case PROP_SITE: gis_view_set_site(self, g_value_get_string(value)); break;
- default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
- }
-}
-static void gis_view_get_property(GObject *object, guint property_id,
- GValue *value, GParamSpec *pspec)
-{
- g_debug("GisView: get_property");
- GisView *self = GIS_VIEW(object);
- switch (property_id) {
- case PROP_TIME: g_value_set_string(value, gis_view_get_time(self)); break;
- case PROP_SITE: g_value_set_string(value, gis_view_get_site(self)); break;
- default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
- }
-}
-static void gis_view_class_init(GisViewClass *klass)
-{
- g_debug("GisView: class_init");
- GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
- gobject_class->dispose = gis_view_dispose;
- gobject_class->finalize = gis_view_finalize;
- gobject_class->get_property = gis_view_get_property;
- gobject_class->set_property = gis_view_set_property;
- g_object_class_install_property(gobject_class, PROP_TIME,
- g_param_spec_pointer(
- "time",
- "time of the current frame",
- "(format unknown)",
- G_PARAM_READWRITE));
- g_object_class_install_property(gobject_class, PROP_SITE,
- g_param_spec_pointer(
- "site",
- "site seen by the viewport",
- "Site of the viewport. Currently this is the name of the radar site.",
- G_PARAM_READWRITE));
- signals[SIG_TIME_CHANGED] = g_signal_new(
- "time-changed",
- G_TYPE_FROM_CLASS(gobject_class),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL,
- NULL,
- g_cclosure_marshal_VOID__STRING,
- G_TYPE_NONE,
- 1,
- G_TYPE_STRING);
- signals[SIG_SITE_CHANGED] = g_signal_new(
- "site-changed",
- G_TYPE_FROM_CLASS(gobject_class),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL,
- NULL,
- g_cclosure_marshal_VOID__STRING,
- G_TYPE_NONE,
- 1,
- G_TYPE_STRING);
- signals[SIG_LOCATION_CHANGED] = g_signal_new(
- "location-changed",
- G_TYPE_FROM_CLASS(gobject_class),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL,
- NULL,
- gis_cclosure_marshal_VOID__DOUBLE_DOUBLE_DOUBLE,
- G_TYPE_NONE,
- 3,
- G_TYPE_DOUBLE,
- G_TYPE_DOUBLE,
- G_TYPE_DOUBLE);
- signals[SIG_ROTATION_CHANGED] = g_signal_new(
- "rotation-changed",
- G_TYPE_FROM_CLASS(gobject_class),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL,
- NULL,
- gis_cclosure_marshal_VOID__DOUBLE_DOUBLE_DOUBLE,
- G_TYPE_NONE,
- 3,
- G_TYPE_DOUBLE,
- G_TYPE_DOUBLE,
- G_TYPE_DOUBLE);
-}
+++ /dev/null
-/*
- * 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_VIEW_H__
-#define __GIS_VIEW_H__
-
-#include <glib-object.h>
-
-/* Type macros */
-#define GIS_TYPE_VIEW (gis_view_get_type())
-#define GIS_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GIS_TYPE_VIEW, GisView))
-#define GIS_IS_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GIS_TYPE_VIEW))
-#define GIS_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIS_TYPE_VIEW, GisViewClass))
-#define GIS_IS_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIS_TYPE_VIEW))
-#define GIS_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIS_TYPE_VIEW, GisViewClass))
-
-typedef struct _GisView GisView;
-typedef struct _GisViewClass GisViewClass;
-
-struct _GisView {
- GObject parent_instance;
-
- /* instance members */
- gchar *time;
- gchar *site;
- gdouble location[3];
- gdouble rotation[3];
-};
-
-struct _GisViewClass {
- GObjectClass parent_class;
-
- /* class members */
-};
-
-GType gis_view_get_type(void);
-
-/* Methods */
-GisView *gis_view_new();
-
-void gis_view_set_time(GisView *view, const gchar *time);
-gchar *gis_view_get_time(GisView *view);
-
-void gis_view_set_location(GisView *view, gdouble lat, gdouble lon, gdouble elev);
-void gis_view_get_location(GisView *view, gdouble *lat, gdouble *lon, gdouble *elev);
-void gis_view_pan (GisView *view, gdouble lat, gdouble lon, gdouble elev);
-void gis_view_zoom (GisView *view, gdouble scale);
-
-void gis_view_set_rotation(GisView *view, gdouble x, gdouble y, gdouble z);
-void gis_view_get_rotation(GisView *view, gdouble *x, gdouble *y, gdouble *z);
-void gis_view_rotate (GisView *view, gdouble x, gdouble y, gdouble z);
-
-/* To be deprecated, use {get,set}_location */
-void gis_view_set_site(GisView *view, const gchar *site);
-gchar *gis_view_get_site(GisView *view);
-
-#endif
+++ /dev/null
-/*
- * 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 <glib.h>
-#include <math.h>
-
-#include "gis-marshal.h"
-#include "gis-world.h"
-
-/* Constants */
-double WGS884_SEMI_MAJOR = 6378137.0; // a
-double WGS884_SEMI_MINOR = 6356752.314245; // b
-double WGS884_INV_FLAT = 298.257223563; // 1/f
-
-enum {
- SIG_REFRESH,
- SIG_OFFLINE,
- NUM_SIGNALS,
-};
-static guint signals[NUM_SIGNALS];
-
-
-/* Signal helpers */
-static void _gis_world_emit_refresh(GisWorld *world)
-{
- g_signal_emit(world, signals[SIG_REFRESH], 0);
-}
-static void _gis_world_emit_offline(GisWorld *world)
-{
- g_signal_emit(world, signals[SIG_OFFLINE], 0,
- world->offline);
-}
-
-/***********
- * Methods *
- ***********/
-GisWorld *gis_world_new()
-{
- g_debug("GisWorld: new");
- return g_object_new(GIS_TYPE_WORLD, NULL);
-}
-
-void gis_world_refresh(GisWorld *world)
-{
- g_debug("GisWorld: refresh");
- _gis_world_emit_refresh(world);
-}
-
-void gis_world_set_offline(GisWorld *world, gboolean offline)
-{
- g_assert(GIS_IS_WORLD(world));
- g_debug("GisWorld: set_offline - %d", offline);
- world->offline = offline;
- _gis_world_emit_offline(world);
-}
-
-gboolean gis_world_get_offline(GisWorld *world)
-{
- g_assert(GIS_IS_WORLD(world));
- g_debug("GisWorld: get_offline - %d", world->offline);
- return world->offline;
-}
-
-
-/****************
- * GObject code *
- ****************/
-G_DEFINE_TYPE(GisWorld, gis_world, G_TYPE_OBJECT);
-static void gis_world_init(GisWorld *self)
-{
- g_debug("GisWorld: init");
- /* Default values */
- self->offline = FALSE;
-}
-static void gis_world_dispose(GObject *gobject)
-{
- g_debug("GisWorld: dispose");
- /* Drop references to other GObjects */
- G_OBJECT_CLASS(gis_world_parent_class)->dispose(gobject);
-}
-static void gis_world_finalize(GObject *gobject)
-{
- g_debug("GisWorld: finalize");
- GisWorld *self = GIS_WORLD(gobject);
- G_OBJECT_CLASS(gis_world_parent_class)->finalize(gobject);
-}
-static void gis_world_class_init(GisWorldClass *klass)
-{
- g_debug("GisWorld: class_init");
- GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
- gobject_class->dispose = gis_world_dispose;
- gobject_class->finalize = gis_world_finalize;
- signals[SIG_REFRESH] = g_signal_new(
- "refresh",
- G_TYPE_FROM_CLASS(gobject_class),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL,
- NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE,
- 0);
- signals[SIG_OFFLINE] = g_signal_new(
- "offline",
- G_TYPE_FROM_CLASS(gobject_class),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL,
- NULL,
- g_cclosure_marshal_VOID__BOOLEAN,
- G_TYPE_NONE,
- 1,
- G_TYPE_BOOLEAN);
-}
-
-
-/******************
- * Global helpers *
- ******************/
-void lle2xyz(gdouble lat, gdouble lon, gdouble elev,
- gdouble *x, gdouble *y, gdouble *z)
-{
- gdouble rad = elev2rad(elev);
- gdouble azim = lon2azim(lon);
- gdouble incl = lat2incl(lat);
- *z = rad * cos(azim) * sin(incl);
- *x = rad * sin(azim) * sin(incl);
- *y = rad * cos(incl);
-}
-
-void xyz2lle(gdouble x, gdouble y, gdouble z,
- gdouble *lat, gdouble *lon, gdouble *elev)
-{
- gdouble rad = sqrt(x*x + y*y + z*z);
- *lat = incl2lat(acos(y / rad));
- *lon = azim2lon(atan2(x,z));
- *elev = rad2elev(rad);
-}
-
-
-gdouble ll2m(gdouble lon_dist, gdouble lat)
-{
- gdouble azim = (-lat+90)/180*M_PI;
- gdouble rad = sin(azim) * EARTH_R;
- gdouble circ = 2 * M_PI * rad;
- return lon_dist/360 * circ;
-}
-
-gdouble distd(gdouble *a, gdouble *b)
-{
- return sqrt((a[0]-b[0])*(a[0]-b[0]) +
- (a[1]-b[1])*(a[1]-b[1]) +
- (a[2]-b[2])*(a[2]-b[2]));
-}
+++ /dev/null
-/*
- * 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_WORLD_H__
-#define __GIS_WORLD_H__
-
-#include <glib-object.h>
-
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
-
-#define EARTH_R (6371000)
-#define EARTH_C (2*M_PI*EARTH_R)
-
-/**
- * Terms
- * -----
- * deg - Degrees
- * rad - Radians, also radius
- * m - Meters, for earth-based distances
- * px - Pixels, for screen-based distances
- *
- * height - Height, the distance above the geoid (ground)
- * elev - Elevation, the distance above the spheroid
- * rad - Radius, the distance from the center of the earth
- *
- * lat - Latitude, amount north-south, -90 (S) .. 90 (N)
- * lon - Longitude, amount east-west, -180 (W) .. 180 (E)
- * incl - Inclination, polar equiv of latitude, Pi .. 0
- * azim - Azimuth, polar equiv of longitude, -Pi .. Pi
- *
- * x - 0° lon is positive
- * y - 90° lon is positive
- * z - North pole is positive
- *
- * llh - lat,lon,height
- * lle - lat,lon,elev
- * llr - lat,lon,rad
- * pol - incl,azim,rad
- * xyz - x,y,z
- */
-
-/**
- * lat lon elev -> x y z
- * lle2xyz: 0.0, 0.0, 0.0 -> 0.0, 0.0, 10.0
- * lle2xyz: 90.0, 0.0, 0.0 -> 0.0, 10.0, 0.0
- * lle2xyz: 0.0, 90.0, 0.0 -> 10.0, 0.0, 0.0
- *
- * x y z -> lat lon elev
- * xyz2lle: 10.0, 0.0, 0.0 -> 0.0, 90.0, 0.0
- * xyz2lle: 0.0, 10.0, 0.0 -> 90.0, 0.0, 0.0
- * xyz2lle: 0.0, 0.0, 10.0 -> 0.0, 0.0, 0.0
- */
-
-#define azim2lon(azim) ((azim)*180/M_PI)
-#define lon2azim(lon) ((lon)*M_PI/180)
-#define incl2lat(incl) (90-(incl)*180/M_PI)
-#define lat2incl(lat) ((90-(lat))*M_PI/180)
-#define rad2elev(rad) ((rad)-EARTH_R)
-#define elev2rad(elev) ((elev)+EARTH_R)
-
-#define deg2rad(deg) (((deg)*M_PI)/180.0)
-#define rad2deg(rad) (((rad)*180.0)/M_PI)
-
-#define FOV_DIST 2000.0
-#define MPPX(dist) (4*dist/FOV_DIST)
-
-void lle2xyz(gdouble lat, gdouble lon, gdouble elev,
- gdouble *x, gdouble *y, gdouble *z);
-
-void xyz2lle(gdouble x, gdouble y, gdouble z,
- gdouble *lat, gdouble *lon, gdouble *elev);
-
-gdouble ll2m(gdouble lon_dist, gdouble lat);
-
-gdouble distd(gdouble *a, gdouble *b);
-
-/************
- * GisWorld *
- ************/
-#define GIS_TYPE_WORLD (gis_world_get_type())
-#define GIS_WORLD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GIS_TYPE_WORLD, GisWorld))
-#define GIS_IS_WORLD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GIS_TYPE_WORLD))
-#define GIS_WORLD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIS_TYPE_WORLD, GisWorldClass))
-#define GIS_IS_WORLD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIS_TYPE_WORLD))
-#define GIS_WORLD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIS_TYPE_WORLD, GisWorldClass))
-
-typedef struct _GisWorld GisWorld;
-typedef struct _GisWorldClass GisWorldClass;
-
-struct _GisWorld {
- GObject parent_instance;
-
- /* instance members */
- gboolean offline;
-};
-
-struct _GisWorldClass {
- GObjectClass parent_class;
-
- /* class members */
-};
-
-GType gis_world_get_type(void);
-
-/* Methods */
-GisWorld *gis_world_new();
-
-void gis_world_refresh(GisWorld *world);
-
-void gis_world_set_offline(GisWorld *world, gboolean offline);
-gboolean gis_world_get_offline(GisWorld *world);
-
-#endif
+++ /dev/null
-/*
- * 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_H__
-#define __GIS_H__
-
-/* GIS Core */
-#include "gis-world.h"
-#include "gis-view.h"
-#include "gis-opengl.h"
-#include "gis-prefs.h"
-
-/* GIS helprs */
-#include "gis-data.h"
-
-/* Plugins */
-#include "gis-plugin.h"
-
-#endif
+++ /dev/null
-/*
- * 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 <gtk/gtk.h>
-#include <gdk/gdkkeysyms.h>
-
-#include "gis.h"
-
-/*************
- * Callbacks *
- *************/
-static gboolean on_key_press(GtkWidget *widget, GdkEventKey *event, gpointer _)
-{
- g_debug("gis: on_key_press - key=%x, state=%x",
- event->keyval, event->state);
- switch (event->keyval) {
- case GDK_q:
- gtk_widget_destroy(widget);
- return TRUE;
- }
- return FALSE;
-}
-
-/***********
- * Methods *
- ***********/
-int main(int argc, char **argv)
-{
- gtk_init(&argc, &argv);
- g_thread_init(NULL);
-
- GisPrefs *prefs = gis_prefs_new("aweather");
- GisPlugins *plugins = gis_plugins_new();
- GisWorld *world = gis_world_new();
- GisView *view = gis_view_new();
- GisOpenGL *opengl = gis_opengl_new(world, view, plugins);
-
- //gis_plugins_load(plugins, "radar", world, view, opengl, prefs);
- //gis_plugins_load(plugins, "ridge", world, view, opengl, prefs);
- //gis_plugins_load(plugins, "example", world, view, opengl, prefs);
-
- GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
- g_signal_connect(window, "key-press-event", G_CALLBACK(on_key_press), NULL);
- gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(opengl));
- gtk_widget_show_all(window);
-
- gis_view_set_site(view, "KLSX");
- gtk_main();
-
- g_object_unref(prefs);
- g_object_unref(world);
- g_object_unref(view);
- g_object_unref(opengl);
- gis_plugins_free(plugins);
- return 0;
-}
+++ /dev/null
-#include <glib.h>
-#include "gpqueue.h"
-
-/**
- * SECTION:priority_queues
- * @short_description: a collection of data entries with associated priority
- * values that returns entries one by one in order of priority
- *
- * <para>
- * The #GPQueue structure and its associated functions provide a sorted
- * collection of objects. Entries can be inserted in any order and at any time,
- * and an entry's priority can be changed after it has been inserted into the
- * queue. Entries are supposed to be removed one at a time in order of priority
- * with g_pqueue_pop(), but deleting entries out of order is possible.
- * </para>
- * <para>
- * The entries <emphasis>cannot</emphasis> be iterated over in any way other
- * than removing them one by one in order of priority, but when doing that,
- * this structure is far more efficient than sorted lists or balanced trees,
- * which on the other hand do not suffer from this restriction.
- * </para>
- * <para>
- * You will want to be very careful with calls that use #GPQueueHandle.
- * Handles immediately become invalid when an entry is removed from a #GPQueue,
- * but the current implementation cannot detect this and will do unfortunate
- * things to undefined memory locations if you try to use an invalid handle.
- * </para>
- * <note>
- * <para>
- * Internally, #GPQueue currently uses a Fibonacci heap to store
- * the entries. This implementation detail may change.
- * </para>
- * </note>
- **/
-
-struct _GPQueueNode {
- GPQueueNode *next;
- GPQueueNode *prev;
- GPQueueNode *parent;
- GPQueueNode *child;
-
- gpointer data;
-
- gint degree;
- gboolean marked;
-};
-
-struct _GPQueue {
- GPQueueNode *root;
- GCompareDataFunc cmp;
- gpointer *cmpdata;
-};
-
-/**
- * g_pqueue_new:
- * @compare_func: the #GCompareDataFunc used to sort the new priority queue.
- * This function is passed two elements of the queue and should return 0 if
- * they are equal, a negative value if the first comes before the second, and
- * a positive value if the second comes before the first.
- * @compare_userdata: user data passed to @compare_func
- *
- * Creates a new #GPQueue.
- *
- * Returns: a new #GPQueue.
- *
- * Since: 2.x
- **/
-GPQueue*
-g_pqueue_new (GCompareDataFunc compare_func,
- gpointer *compare_userdata)
-{
- g_return_val_if_fail (compare_func != NULL, NULL);
-
- GPQueue *pqueue = g_slice_new (GPQueue);
- pqueue->root = NULL;
- pqueue->cmp = compare_func;
- pqueue->cmpdata = compare_userdata;
- return pqueue;
-}
-
-/**
- * g_pqueue_is_empty:
- * @pqueue: a #GPQueue.
- *
- * Returns %TRUE if the queue is empty.
- *
- * Returns: %TRUE if the queue is empty.
- *
- * Since: 2.x
- **/
-gboolean
-g_pqueue_is_empty (GPQueue *pqueue)
-{
- return (pqueue->root == NULL);
-}
-
-static void
-g_pqueue_node_foreach (GPQueueNode *node,
- GPQueueNode *stop,
- GFunc func,
- gpointer user_data)
-{
- if (node == NULL || node == stop) return;
- func(node->data, user_data);
- if (stop == NULL) stop = node;
- g_pqueue_node_foreach (node->next, stop, func, user_data);
- g_pqueue_node_foreach (node->child, NULL, func, user_data);
-}
-
-/**
- * g_pqueue_foreach:
- * @pqueue:Â a #GQueue.
- * @func: the function to call for each element's data
- * @user_data: user data to pass to func
- *
- * Calls func for each element in the pqueue passing user_data to the function.
- *
- * Since: 2.x
- */
-void
-g_pqueue_foreach (GPQueue *pqueue,
- GFunc func,
- gpointer user_data)
-{
- g_pqueue_node_foreach (pqueue->root, NULL, func, user_data);
-}
-
-static void
-g_pqueue_add_ptr_cb (gpointer obj, GPtrArray *ptrs)
-{
- g_ptr_array_add(ptrs, obj);
-}
-/**
- * g_pqueue_get_array:
- * @pqueue:Â a #GQueue.
- *
- * Construct a GPtrArray for the items in pqueue. This can be useful when
- * updating the priorities of all the elements in pqueue.
- *
- * Returns: A GPtrArray containing a pointer to each item in pqueue
- *
- * Since: 2.x
- */
-GPtrArray *
-g_pqueue_get_array (GPQueue *pqueue)
-{
- GPtrArray *ptrs = g_ptr_array_new();
- g_pqueue_foreach(pqueue, (GFunc)g_pqueue_add_ptr_cb, ptrs);
- return ptrs;
-}
-
-static inline gint
-cmp (GPQueue *pqueue,
- GPQueueNode *a,
- GPQueueNode *b)
-{
- return pqueue->cmp (a->data, b->data, pqueue->cmpdata);
-}
-
-static inline void
-g_pqueue_node_cut (GPQueueNode *src)
-{
- src->prev->next = src->next;
- src->next->prev = src->prev;
- src->next = src;
- src->prev = src;
-}
-
-static inline void
-g_pqueue_node_insert_before (GPQueueNode *dest,
- GPQueueNode *src)
-{
- GPQueueNode *prev;
-
- prev = dest->prev;
- dest->prev = src->prev;
- src->prev->next = dest;
- src->prev = prev;
- prev->next = src;
-}
-
-static inline void
-g_pqueue_node_insert_after (GPQueueNode *dest,
- GPQueueNode *src)
-{
- GPQueueNode *next;
-
- next = dest->next;
- dest->next = src;
- src->prev->next = next;
- next->prev = src->prev;
- src->prev = dest;
-}
-
-/**
- * g_pqueue_push:
- * @pqueue: a #GPQueue.
- * @data: the object to insert into the priority queue.
- *
- * Inserts a new entry into a #GPQueue.
- *
- * The returned handle can be used in calls to g_pqueue_remove() and
- * g_pqueue_priority_changed(). Never make such calls for entries that have
- * already been removed from the queue. The same @data can be inserted into
- * a #GPQueue more than once, but remember that in this case,
- * g_pqueue_priority_changed() needs to be called for
- * <emphasis>every</emphasis> handle for that object if its priority changes.
- *
- * Returns: a handle for the freshly inserted entry.
- *
- * Since: 2.x
- **/
-GPQueueHandle
-g_pqueue_push (GPQueue *pqueue,
- gpointer data)
-{
- GPQueueNode *e;
-
- e = g_slice_new (GPQueueNode);
- e->next = e;
- e->prev = e;
- e->parent = NULL;
- e->child = NULL;
- e->data = data;
- e->degree = 0;
- e->marked = FALSE;
-
- if (pqueue->root != NULL) {
- g_pqueue_node_insert_before (pqueue->root, e);
- if (cmp (pqueue, e, pqueue->root) < 0)
- pqueue->root = e;
- } else {
- pqueue->root = e;
- }
-
- return e;
-}
-
-/**
- * g_pqueue_peek:
- * @pqueue: a #GPQueue.
- *
- * Returns the topmost entry's data pointer, or %NULL if the queue is empty.
- *
- * If you need to tell the difference between an empty queue and a queue
- * that happens to have a %NULL pointer at the top, check if the queue is
- * empty first.
- *
- * Returns: the topmost entry's data pointer, or %NULL if the queue is empty.
- *
- * Since: 2.x
- **/
-gpointer
-g_pqueue_peek (GPQueue *pqueue)
-{
- return (pqueue->root != NULL) ? pqueue->root->data : NULL;
-}
-
-static inline GPQueueNode*
-g_pqueue_make_child (GPQueueNode *a,
- GPQueueNode *b)
-{
- g_pqueue_node_cut(b);
- if (a->child != NULL) {
- g_pqueue_node_insert_before (a->child, b);
- a->degree += 1;
- } else {
- a->child = b;
- a->degree = 1;
- }
- b->parent = a;
- return a;
-}
-
-static inline GPQueueNode*
-g_pqueue_join_trees (GPQueue *pqueue,
- GPQueueNode *a,
- GPQueueNode *b)
-{
- if (cmp (pqueue, a, b) < 0)
- return g_pqueue_make_child (a, b);
- return g_pqueue_make_child (b, a);
-}
-
-static void
-g_pqueue_fix_rootlist (GPQueue* pqueue)
-{
- gsize degnode_size;
- GPQueueNode **degnode;
- GPQueueNode sentinel;
- GPQueueNode *current;
- GPQueueNode *minimum;
-
- /* We need to iterate over the circular list we are given and do
- * several things:
- * - Make sure all the elements are unmarked
- * - Make sure to return the element in the list with smallest
- * priority value
- * - Find elements of identical degree and join them into trees
- * The last point is irrelevant for correctness, but essential
- * for performance. If we did not do this, our data structure would
- * degrade into an unsorted linked list.
- */
-
- degnode_size = (8 * sizeof(gpointer) + 1) * sizeof(gpointer);
- degnode = g_slice_alloc0 (degnode_size);
-
- sentinel.next = &sentinel;
- sentinel.prev = &sentinel;
- g_pqueue_node_insert_before (pqueue->root, &sentinel);
-
- current = pqueue->root;
- while (current != &sentinel) {
- current->marked = FALSE;
- current->parent = NULL;
- gint d = current->degree;
- if (degnode[d] == NULL) {
- degnode[d] = current;
- current = current->next;
- } else {
- if (degnode[d] != current) {
- current = g_pqueue_join_trees (pqueue, degnode[d], current);
- degnode[d] = NULL;
- } else {
- current = current->next;
- }
- }
- }
-
- current = sentinel.next;
- minimum = current;
- while (current != &sentinel) {
- if (cmp (pqueue, current, minimum) < 0)
- minimum = current;
- current = current->next;
- }
- pqueue->root = minimum;
-
- g_pqueue_node_cut (&sentinel);
-
- g_slice_free1 (degnode_size, degnode);
-}
-
-static void
-g_pqueue_remove_root (GPQueue *pqueue,
- GPQueueNode *root)
-{
- /* This removes a node at the root _level_ of the structure, which can be,
- * but does not have to be, the actual pqueue->root node. That is why
- * we require an explicit pointer to the node to be removed instead of just
- * removing pqueue->root implictly.
- */
-
- /* Step one:
- * If root has any children, pull them up to root level.
- * At this time, we only deal with their next/prev pointers,
- * further changes are made later in g_pqueue_fix_rootlist().
- */
- if (root->child) {
- g_pqueue_node_insert_after (root, root->child);
- root->child = NULL;
- root->degree = 0;
- }
-
- /* Step two:
- * Cut root out of the list.
- */
- if (root->next != root) {
- pqueue->root = root->next;
- g_pqueue_node_cut (root);
- /* Step three:
- * Clean up the remaining list.
- */
- g_pqueue_fix_rootlist (pqueue);
- } else {
- pqueue->root = NULL;
- }
-
- g_slice_free (GPQueueNode, root);
-}
-
-/**
- * g_pqueue_pop:
- * @pqueue: a #GPQueue.
- *
- * Removes the topmost entry from a #GPQueue and returns its data pointer.
- * Calling this on an empty #GPQueue is not an error, but removes nothing
- * and returns %NULL.
- *
- * If you need to tell the difference between an empty queue and a queue
- * that happens to have a %NULL pointer at the top, check if the queue is
- * empty first.
- *
- * Returns: the topmost entry's data pointer, or %NULL if the queue was empty.
- *
- * Since: 2.x
- **/
-gpointer
-g_pqueue_pop (GPQueue *pqueue)
-{
- gpointer data;
-
- if (pqueue->root == NULL) return NULL;
- data = pqueue->root->data;
- g_pqueue_remove_root (pqueue, pqueue->root);
- return data;
-}
-
-static inline void
-g_pqueue_make_root (GPQueue *pqueue,
- GPQueueNode *entry)
-{
- /* This moves a node up to the root _level_ of the structure.
- * It does not always become the actual root element (pqueue->root).
- */
-
- GPQueueNode *parent;
-
- parent = entry->parent;
- entry->parent = NULL;
- entry->marked = FALSE;
- if (parent != NULL) {
- if (entry->next != entry) {
- if (parent->child == entry) parent->child = entry->next;
- g_pqueue_node_cut (entry);
- parent->degree -= 1;
- } else {
- parent->child = NULL;
- parent->degree = 0;
- }
- g_pqueue_node_insert_before (pqueue->root, entry);
- }
-
- if (cmp (pqueue, entry, pqueue->root) < 0)
- pqueue->root = entry;
-}
-
-static void
-g_pqueue_cut_tree (GPQueue *pqueue,
- GPQueueNode *entry)
-{
- /* This function moves an entry up to the root level of the structure.
- * It extends g_pqueue_make_root() in that the entry's parent, grandparent
- * etc. may also be moved to the root level if they are "marked". This is
- * not essential for correctness, it just maintains the so-called "potential"
- * of the structure, which is necessary for the amortized runtime analysis.
- */
-
- GPQueueNode *current;
- GPQueueNode *parent;
-
- current = entry;
- while ((current != NULL) && (current->parent != NULL)) {
- parent = current->parent;
- g_pqueue_make_root (pqueue, entry);
- if (parent->marked) {
- current = parent;
- } else {
- parent->marked = TRUE;
- current = NULL;
- }
- }
- if (cmp (pqueue, entry, pqueue->root) < 0)
- pqueue->root = entry;
-}
-
-/**
- * g_pqueue_remove:
- * @pqueue: a #GPQueue.
- * @entry: a #GPQueueHandle for an entry in @pqueue.
- *
- * Removes one entry from a #GPQueue.
- *
- * Make sure that @entry refers to an entry that is actually part of
- * @pqueue at the time, otherwise the behavior of this function is
- * undefined (expect crashes).
- *
- * Since: 2.x
- **/
-void
-g_pqueue_remove (GPQueue* pqueue,
- GPQueueHandle entry)
-{
- g_pqueue_cut_tree (pqueue, entry);
- g_pqueue_remove_root (pqueue, entry);
-}
-
-/**
- * g_pqueue_priority_changed:
- * @pqueue: a #GPQueue.
- * @entry: a #GPQueueHandle for an entry in @pqueue.
- *
- * Notifies the #GPQueue that the priority of one entry has changed.
- * The internal representation is updated accordingly.
- *
- * Make sure that @entry refers to an entry that is actually part of
- * @pqueue at the time, otherwise the behavior of this function is
- * undefined (expect crashes).
- *
- * Do not attempt to change the priorities of several entries at once.
- * Every time a single object is changed, the #GPQueue needs to be updated
- * by calling g_pqueue_priority_changed() for that object.
- *
- * Since: 2.x
- **/
-void
-g_pqueue_priority_changed (GPQueue* pqueue,
- GPQueueHandle entry)
-{
- g_pqueue_cut_tree (pqueue, entry);
-
- if (entry->child) {
- g_pqueue_node_insert_after (entry, entry->child);
- entry->child = NULL;
- entry->degree = 0;
- }
-
- g_pqueue_fix_rootlist (pqueue);
-}
-
-/**
- * g_pqueue_priority_decreased:
- * @pqueue: a #GPQueue.
- * @entry: a #GPQueueHandle for an entry in @pqueue.
- *
- * Notifies the #GPQueue that the priority of one entry has
- * <emphasis>decreased</emphasis>.
- *
- * This is a special case of g_pqueue_priority_changed(). If you are absolutely
- * sure that the new priority of @entry is lower than it was before, you
- * may call this function instead of g_pqueue_priority_changed().
- *
- * <note>
- * <para>
- * In the current implementation, an expensive step in
- * g_pqueue_priority_changed() can be skipped if the new priority is known
- * to be lower, leading to an amortized running time of O(1) instead of
- * O(log n). Of course, if the priority is not actually lower, behavior
- * is undefined.
- * </para>
- * </note>
- *
- * Since: 2.x
- **/
-void
-g_pqueue_priority_decreased (GPQueue* pqueue,
- GPQueueHandle entry)
-{
- g_pqueue_cut_tree (pqueue, entry);
-}
-
-static void
-g_pqueue_node_free_all (GPQueueNode *node)
-{
- if (node == NULL) return;
- g_pqueue_node_free_all (node->child);
- node->prev->next = NULL;
- g_pqueue_node_free_all (node->next);
- g_slice_free (GPQueueNode, node);
-}
-
-/**
- * g_pqueue_clear:
- * @pqueue: a #GPQueue.
- *
- * Removes all entries from a @pqueue.
- *
- * Since: 2.x
- **/
-void
-g_pqueue_clear (GPQueue* pqueue)
-{
- g_pqueue_node_free_all (pqueue->root);
- pqueue->root = NULL;
-}
-
-/**
- * g_pqueue_free:
- * @pqueue: a #GPQueue.
- *
- * Deallocates the memory used by @pqueue itself, but not any memory pointed
- * to by the data pointers of its entries.
- *
- * Since: 2.x
- **/
-void
-g_pqueue_free (GPQueue* pqueue)
-{
- g_pqueue_clear (pqueue);
- g_slice_free (GPQueue, pqueue);
-}
+++ /dev/null
-#if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
-#error "Only <glib.h> can be included directly."
-#endif
-
-#ifndef __G_PQUEUE_H__
-#define __G_PQUEUE_H__
-
-G_BEGIN_DECLS
-
-typedef struct _GPQueueNode GPQueueNode;
-
-/**
- * GPQueue:
- *
- * An opaque structure representing a priority queue.
- *
- * Since: 2.x
- **/
-typedef struct _GPQueue GPQueue;
-
-/**
- * GPQueueHandle:
- *
- * An opaque value representing one entry in a #GPQueue.
- *
- * Since: 2.x
- **/
-typedef GPQueueNode* GPQueueHandle;
-
-GPQueue* g_pqueue_new (GCompareDataFunc compare_func,
- gpointer *compare_userdata);
-
-void g_pqueue_free (GPQueue* pqueue);
-
-gboolean g_pqueue_is_empty (GPQueue *pqueue);
-
-void g_pqueue_foreach (GPQueue *pqueue,
- GFunc func,
- gpointer user_data);
-
-GPtrArray* g_pqueue_get_array (GPQueue *pqueue);
-
-GPQueueHandle g_pqueue_push (GPQueue *pqueue,
- gpointer data);
-
-gpointer g_pqueue_peek (GPQueue *pqueue);
-
-gpointer g_pqueue_pop (GPQueue *pqueue);
-
-void g_pqueue_remove (GPQueue* pqueue,
- GPQueueHandle entry);
-
-void g_pqueue_priority_changed (GPQueue* pqueue,
- GPQueueHandle entry);
-
-void g_pqueue_priority_decreased (GPQueue* pqueue,
- GPQueueHandle entry);
-
-void g_pqueue_clear (GPQueue* pqueue);
-
-G_END_DECLS
-
-#endif /* __G_PQUEUE_H__ */
+++ /dev/null
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-
-Name: libgis
-Description: GIS Library for Gtk+ applications
-Version: @VERSION@
-Requires: gmodule-2.0 gtk+-2.0 gtkglext-1.0 libsoup-2.4
-Libs: -L${libdir} -lgis
-Cflags: -I${includedir}/gis
+++ /dev/null
-/*
- * 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 <glib.h>
-#include <math.h>
-#include <string.h>
-#include "gpqueue.h"
-#include <GL/gl.h>
-#include <GL/glu.h>
-
-#include "roam.h"
-
-/**
- * TODO:
- * - Optimize for memory consumption
- * - Profile for computation speed
- * - Target polygon count/detail
- */
-
-/* Misc */
-RoamView *roam_view_get()
-{
- RoamView *view = g_new0(RoamView, 1);
- glGetDoublev (GL_MODELVIEW_MATRIX, view->model);
- glGetDoublev (GL_PROJECTION_MATRIX, view->proj);
- glGetIntegerv(GL_VIEWPORT, view->view);
- return view;
-}
-
-/* For GPQueue comparators */
-static gint tri_cmp(RoamTriangle *a, RoamTriangle *b, gpointer data)
-{
- if (a->error < b->error) return 1;
- else if (a->error > b->error) return -1;
- else return 0;
-}
-static gint dia_cmp(RoamDiamond *a, RoamDiamond *b, gpointer data)
-{
- if (a->error < b->error) return -1;
- else if (a->error > b->error) return 1;
- else return 0;
-}
-
-/*************
- * RoamPoint *
- *************/
-RoamPoint *roam_point_new(double x, double y, double z)
-{
- RoamPoint *self = g_new0(RoamPoint, 1);
- self->x = x;
- self->y = y;
- self->z = z;
- return self;
-}
-RoamPoint *roam_point_dup(RoamPoint *self)
-{
- RoamPoint *new = g_memdup(self, sizeof(RoamPoint));
- new->tris = 0;
- return new;
-}
-void roam_point_add_triangle(RoamPoint *self, RoamTriangle *triangle)
-{
- for (int i = 0; i < 3; i++) {
- self->norm[i] *= self->tris;
- self->norm[i] += triangle->norm[i];
- }
- self->tris++;
- for (int i = 0; i < 3; i++)
- self->norm[i] /= self->tris;
-}
-void roam_point_remove_triangle(RoamPoint *self, RoamTriangle *triangle)
-{
- for (int i = 0; i < 3; i++) {
- self->norm[i] *= self->tris;
- self->norm[i] -= triangle->norm[i];
- }
- self->tris--;
- for (int i = 0; i < 3; i++)
- self->norm[i] /= self->tris;
-}
-void roam_point_update(RoamPoint *self, RoamSphere *sphere, gboolean do_height)
-{
- if (!self->cached) {
- /* Cache height */
- if (do_height)
- sphere->height_func(self, sphere->user_data);
-
- /* Cache projection */
- gluProject(self->x, self->y, self->z,
- sphere->view->model, sphere->view->proj, sphere->view->view,
- &self->px, &self->py, &self->pz);
-
- self->cached = TRUE;
- }
-}
-void roam_point_clear(RoamPoint *self)
-{
- self->cached = FALSE;
-}
-
-/****************
- * RoamTriangle *
- ****************/
-RoamTriangle *roam_triangle_new(RoamPoint *l, RoamPoint *m, RoamPoint *r)
-{
- RoamTriangle *self = g_new0(RoamTriangle, 1);
-
- self->p.l = l;
- self->p.m = m;
- self->p.r = r;
-
- self->error = 0;
-
- /* Update normal */
- double pa[3];
- double pb[3];
- pa[0] = self->p.l->x - self->p.m->x;
- pa[1] = self->p.l->y - self->p.m->y;
- pa[2] = self->p.l->z - self->p.m->z;
-
- pb[0] = self->p.r->x - self->p.m->x;
- pb[1] = self->p.r->y - self->p.m->y;
- pb[2] = self->p.r->z - self->p.m->z;
-
- self->norm[0] = pa[1] * pb[2] - pa[2] * pb[1];
- self->norm[1] = pa[2] * pb[0] - pa[0] * pb[2];
- self->norm[2] = pa[0] * pb[1] - pa[1] * pb[0];
-
- double total = sqrt(self->norm[0] * self->norm[0] +
- self->norm[1] * self->norm[1] +
- self->norm[2] * self->norm[2]);
-
- self->norm[0] /= total;
- self->norm[1] /= total;
- self->norm[2] /= total;
-
- //g_message("roam_triangle_new: %p", self);
- return self;
-}
-
-void roam_triangle_add(RoamTriangle *self,
- RoamTriangle *left, RoamTriangle *base, RoamTriangle *right,
- RoamSphere *sphere)
-{
- self->t.l = left;
- self->t.b = base;
- self->t.r = right;
-
- roam_point_add_triangle(self->p.l, self);
- roam_point_add_triangle(self->p.m, self);
- roam_point_add_triangle(self->p.r, self);
-
- if (sphere->view)
- roam_triangle_update(self, sphere);
-
- self->handle = g_pqueue_push(sphere->triangles, self);
-}
-
-void roam_triangle_remove(RoamTriangle *self, RoamSphere *sphere)
-{
- /* Update vertex normals */
- roam_point_remove_triangle(self->p.l, self);
- roam_point_remove_triangle(self->p.m, self);
- roam_point_remove_triangle(self->p.r, self);
-
- g_pqueue_remove(sphere->triangles, self->handle);
-}
-
-void roam_triangle_sync_neighbors(RoamTriangle *new, RoamTriangle *old, RoamTriangle *neigh)
-{
- if (neigh->t.l == old) neigh->t.l = new;
- else if (neigh->t.b == old) neigh->t.b = new;
- else if (neigh->t.r == old) neigh->t.r = new;
- else g_assert_not_reached();
-}
-
-gboolean roam_point_visible(RoamPoint *self, RoamSphere *sphere)
-{
- gint *view = sphere->view->view;
- return self->px > view[0] && self->px < view[2] &&
- self->py > view[1] && self->py < view[3] &&
- self->pz > 0 && self->pz < 1;
- //double x, y, z;
- //int view[4] = {0,0,1,1};
- //gluProject(self->x, self->y, self->z,
- // sphere->view->model, sphere->view->proj, view,
- // &x, &y, &z);
- //return !(x < 0 || x > 1 ||
- // y < 0 || y > 1 ||
- // z < 0 || z > 1);
-}
-gboolean roam_triangle_visible(RoamTriangle *self, RoamSphere *sphere)
-{
- /* Do this with a bounding box */
- return roam_point_visible(self->p.l, sphere) ||
- roam_point_visible(self->p.m, sphere) ||
- roam_point_visible(self->p.r, sphere);
-}
-
-void roam_triangle_update(RoamTriangle *self, RoamSphere *sphere)
-{
- /* Update points */
- roam_point_update(self->p.l, sphere, TRUE);
- roam_point_update(self->p.m, sphere, TRUE);
- roam_point_update(self->p.r, sphere, TRUE);
-
- /* Not exactly correct, could be out on both sides (middle in) */
- if (!roam_triangle_visible(self, sphere)) {
- self->error = -1;
- } else {
- RoamPoint *l = self->p.l;
- RoamPoint *m = self->p.m;
- RoamPoint *r = self->p.r;
-
- /* TODO: share this with the base */
- RoamPoint base = { (l->x + r->x)/2,
- (l->y + r->y)/2,
- (l->z + r->z)/2 };
- RoamPoint good = base;
- roam_point_update(&base, sphere, FALSE);
- roam_point_update(&good, sphere, TRUE);
-
- self->error = sqrt((base.px - good.px) * (base.px - good.px) +
- (base.py - good.py) * (base.py - good.py));
-
- /* Multiply by size of triangle */
- double size = -( l->px * (m->py - r->py) +
- m->px * (r->py - l->py) +
- r->px * (l->py - m->py) ) / 2.0;
-
- /* Size < 0 == backface */
- self->error *= size;
- }
-}
-
-void roam_triangle_clear(RoamTriangle *self)
-{
- /* Clear points */
- roam_point_clear(self->p.l);
- roam_point_clear(self->p.m);
- roam_point_clear(self->p.r);
-}
-
-void roam_triangle_split(RoamTriangle *self, RoamSphere *sphere)
-{
- //g_message("roam_triangle_split: %p, e=%f\n", self, self->error);
-
- sphere->polys += 2;
-
- if (self != self->t.b->t.b)
- roam_triangle_split(self->t.b, sphere);
-
- RoamTriangle *base = self->t.b;
-
- /* Duplicate midpoint */
- RoamPoint *mid = roam_point_new(
- (self->p.l->x + self->p.r->x)/2,
- (self->p.l->y + self->p.r->y)/2,
- (self->p.l->z + self->p.r->z)/2);
- roam_point_update(mid, sphere, TRUE);
-
- /* Add new triangles */
- RoamTriangle *sl = roam_triangle_new(self->p.m, mid, self->p.l); // Self Left
- RoamTriangle *sr = roam_triangle_new(self->p.r, mid, self->p.m); // Self Right
- RoamTriangle *bl = roam_triangle_new(base->p.m, mid, base->p.l); // Base Left
- RoamTriangle *br = roam_triangle_new(base->p.r, mid, base->p.m); // Base Right
-
- /* tri,l, base, r, sphere */
- roam_triangle_add(sl, sr, self->t.l, br, sphere);
- roam_triangle_add(sr, bl, self->t.r, sl, sphere);
- roam_triangle_add(bl, br, base->t.l, sr, sphere);
- roam_triangle_add(br, sl, base->t.r, bl, sphere);
-
- roam_triangle_sync_neighbors(sl, self, self->t.l);
- roam_triangle_sync_neighbors(sr, self, self->t.r);
- roam_triangle_sync_neighbors(bl, base, base->t.l);
- roam_triangle_sync_neighbors(br, base, base->t.r);
-
- /* Remove old triangles */
- roam_triangle_remove(self, sphere);
- roam_triangle_remove(base, sphere);
-
- /* Add/Remove diamonds */
- RoamDiamond *diamond = roam_diamond_new(self, base, sl, sr, bl, br);
- roam_diamond_update(diamond, sphere);
- roam_diamond_add(diamond, sphere);
- roam_diamond_remove(self->parent, sphere);
- roam_diamond_remove(base->parent, sphere);
-}
-
-void roam_triangle_draw_normal(RoamTriangle *self)
-{
- double center[] = {
- (self->p.l->x + self->p.m->x + self->p.r->x)/3.0,
- (self->p.l->y + self->p.m->y + self->p.r->y)/3.0,
- (self->p.l->z + self->p.m->z + self->p.r->z)/3.0,
- };
- double end[] = {
- center[0]+self->norm[0]/2,
- center[1]+self->norm[1]/2,
- center[2]+self->norm[2]/2,
- };
- glBegin(GL_LINES);
- glVertex3dv(center);
- glVertex3dv(end);
- glEnd();
-}
-
-/***************
- * RoamDiamond *
- ***************/
-RoamDiamond *roam_diamond_new(
- RoamTriangle *parent0, RoamTriangle *parent1,
- RoamTriangle *kid0, RoamTriangle *kid1,
- RoamTriangle *kid2, RoamTriangle *kid3)
-{
- RoamDiamond *self = g_new0(RoamDiamond, 1);
-
- self->kids[0] = kid0;
- self->kids[1] = kid1;
- self->kids[2] = kid2;
- self->kids[3] = kid3;
-
- kid0->parent = self;
- kid1->parent = self;
- kid2->parent = self;
- kid3->parent = self;
-
- self->parents[0] = parent0;
- self->parents[1] = parent1;
-
- return self;
-}
-void roam_diamond_add(RoamDiamond *self, RoamSphere *sphere)
-{
- self->active = TRUE;
- self->error = MAX(self->parents[0]->error, self->parents[1]->error);
- self->handle = g_pqueue_push(sphere->diamonds, self);
-}
-void roam_diamond_remove(RoamDiamond *self, RoamSphere *sphere)
-{
- if (self && self->active) {
- self->active = FALSE;
- g_pqueue_remove(sphere->diamonds, self->handle);
- }
-}
-void roam_diamond_merge(RoamDiamond *self, RoamSphere *sphere)
-{
- //g_message("roam_diamond_merge: %p, e=%f\n", self, self->error);
-
- sphere->polys -= 2;
-
- /* TODO: pick the best split */
- RoamTriangle **kids = self->kids;
-
- /* Create triangles */
- RoamTriangle *tri = self->parents[0];
- RoamTriangle *base = self->parents[1];
-
- roam_triangle_add(tri, kids[0]->t.b, base, kids[1]->t.b, sphere);
- roam_triangle_add(base, kids[2]->t.b, tri, kids[3]->t.b, sphere);
-
- roam_triangle_sync_neighbors(tri, kids[0], kids[0]->t.b);
- roam_triangle_sync_neighbors(tri, kids[1], kids[1]->t.b);
- roam_triangle_sync_neighbors(base, kids[2], kids[2]->t.b);
- roam_triangle_sync_neighbors(base, kids[3], kids[3]->t.b);
-
- /* Remove triangles */
- roam_triangle_remove(kids[0], sphere);
- roam_triangle_remove(kids[1], sphere);
- roam_triangle_remove(kids[2], sphere);
- roam_triangle_remove(kids[3], sphere);
-
- /* Add/Remove triangles */
- if (tri->t.l->t.l == tri->t.r->t.r &&
- tri->t.l->t.l != tri && tri->parent) {
- roam_diamond_update(tri->parent, sphere);
- roam_diamond_add(tri->parent, sphere);
- }
-
- if (base->t.l->t.l == base->t.r->t.r &&
- base->t.l->t.l != base && base->parent) {
- roam_diamond_update(base->parent, sphere);
- roam_diamond_add(base->parent, sphere);
- }
-
- /* Remove and free diamond and child triangles */
- roam_diamond_remove(self, sphere);
- g_assert(self->kids[0]->p.m == self->kids[1]->p.m &&
- self->kids[1]->p.m == self->kids[2]->p.m &&
- self->kids[2]->p.m == self->kids[3]->p.m);
- g_assert(self->kids[0]->p.m->tris == 0);
- g_free(self->kids[0]->p.m);
- g_free(self->kids[0]);
- g_free(self->kids[1]);
- g_free(self->kids[2]);
- g_free(self->kids[3]);
- g_free(self);
-}
-void roam_diamond_update(RoamDiamond *self, RoamSphere *sphere)
-{
- roam_triangle_update(self->parents[0], sphere);
- roam_triangle_update(self->parents[1], sphere);
- self->error = MAX(self->parents[0]->error, self->parents[1]->error);
-}
-
-/**************
- * RoamSphere *
- **************/
-RoamSphere *roam_sphere_new(RoamTriFunc tri_func, RoamHeightFunc height_func, gpointer user_data)
-{
- RoamSphere *self = g_new0(RoamSphere, 1);
- self->tri_func = tri_func;
- self->height_func = height_func;
- self->user_data = user_data;
- self->polys = 12;
- self->triangles = g_pqueue_new((GCompareDataFunc)tri_cmp, NULL);
- self->diamonds = g_pqueue_new((GCompareDataFunc)dia_cmp, NULL);
-
- RoamPoint *vertexes[] = {
- roam_point_new( 1, 1, 1), // 0
- roam_point_new( 1, 1,-1), // 1
- roam_point_new( 1,-1, 1), // 2
- roam_point_new( 1,-1,-1), // 3
- roam_point_new(-1, 1, 1), // 4
- roam_point_new(-1, 1,-1), // 5
- roam_point_new(-1,-1, 1), // 6
- roam_point_new(-1,-1,-1), // 7
- };
- int _triangles[][2][3] = {
- /*lv mv rv ln, bn, rn */
- {{3,2,0}, {10, 1, 7}}, // 0
- {{0,1,3}, { 9, 0, 2}}, // 1
- {{7,3,1}, {11, 3, 1}}, // 2
- {{1,5,7}, { 8, 2, 4}}, // 3
- {{6,7,5}, {11, 5, 3}}, // 4
- {{5,4,6}, { 8, 4, 6}}, // 5
- {{2,6,4}, {10, 7, 5}}, // 6
- {{4,0,2}, { 9, 6, 0}}, // 7
- {{4,5,1}, { 5, 9, 3}}, // 8
- {{1,0,4}, { 1, 8, 7}}, // 9
- {{6,2,3}, { 6,11, 0}}, // 10
- {{3,7,6}, { 2,10, 4}}, // 11
- };
- RoamTriangle *triangles[12];
-
- for (int i = 0; i < 12; i++)
- triangles[i] = roam_triangle_new(
- vertexes[_triangles[i][0][0]],
- vertexes[_triangles[i][0][1]],
- vertexes[_triangles[i][0][2]]);
- for (int i = 0; i < 12; i++)
- roam_triangle_add(triangles[i],
- triangles[_triangles[i][1][0]],
- triangles[_triangles[i][1][1]],
- triangles[_triangles[i][1][2]],
- self);
-
- return self;
-}
-void roam_sphere_update(RoamSphere *self)
-{
- g_debug("RoamSphere: update - polys=%d", self->polys);
- if (self->view) g_free(self->view);
- self->view = roam_view_get();
-
- GPtrArray *tris = g_pqueue_get_array(self->triangles);
- GPtrArray *dias = g_pqueue_get_array(self->diamonds);
-
- for (int i = 0; i < tris->len; i++) {
- /* Note: this also updates points */
- RoamTriangle *tri = tris->pdata[i];
- roam_triangle_clear(tri);
- roam_triangle_update(tri, self);
- g_pqueue_priority_changed(self->triangles, tri->handle);
- }
-
- for (int i = 0; i < dias->len; i++) {
- RoamDiamond *dia = dias->pdata[i];
- roam_diamond_update(dia, self);
- g_pqueue_priority_changed(self->diamonds, dia->handle);
- }
-
- g_ptr_array_free(tris, TRUE);
- g_ptr_array_free(dias, TRUE);
-}
-
-void roam_sphere_split_one(RoamSphere *self)
-{
- RoamTriangle *to_split = g_pqueue_peek(self->triangles);
- if (!to_split) return;
- roam_triangle_split(to_split, self);
-}
-void roam_sphere_merge_one(RoamSphere *self)
-{
- RoamDiamond *to_merge = g_pqueue_peek(self->diamonds);
- if (!to_merge) return;
- roam_diamond_merge(to_merge, self);
-}
-gint roam_sphere_split_merge(RoamSphere *self)
-{
- gint iters = 0, max_iters = 500;
- gint target = 2000;
-
- if (!self->view)
- return 0;
-
- if (target - self->polys > 100)
- while (self->polys < target && iters++ < max_iters)
- roam_sphere_split_one(self);
-
- if (self->polys - target > 100)
- while (self->polys > target && iters++ < max_iters)
- roam_sphere_merge_one(self);
-
- while (((RoamTriangle*)g_pqueue_peek(self->triangles))->error >
- ((RoamDiamond *)g_pqueue_peek(self->diamonds ))->error &&
- iters++ < max_iters) {
- roam_sphere_merge_one(self);
- roam_sphere_split_one(self);
- }
-
- return iters;
-}
-void roam_sphere_draw(RoamSphere *self)
-{
- g_pqueue_foreach(self->triangles, (GFunc)self->tri_func, self->user_data);
-}
-void roam_sphere_draw_normals(RoamSphere *self)
-{
- g_pqueue_foreach(self->triangles, (GFunc)roam_triangle_draw_normal, NULL);
-}
-static void roam_sphere_free_tri(RoamTriangle *tri)
-{
- if (--tri->p.l->tris == 0) g_free(tri->p.l);
- if (--tri->p.m->tris == 0) g_free(tri->p.m);
- if (--tri->p.r->tris == 0) g_free(tri->p.r);
- g_free(tri);
-}
-void roam_sphere_free(RoamSphere *self)
-{
- /* Slow method, but it should work */
- while (self->polys > 12)
- roam_sphere_merge_one(self);
- /* TODO: free points */
- g_pqueue_foreach(self->triangles, (GFunc)roam_sphere_free_tri, NULL);
- g_pqueue_free(self->triangles);
- g_pqueue_free(self->diamonds);
- g_free(self);
-}
+++ /dev/null
-/*
- * 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 __ROAM_H__
-#define __ROAM_H__
-
-#include "gpqueue.h"
-#include "wms.h"
-
-/* Roam */
-typedef struct _RoamView RoamView;
-typedef struct _RoamPoint RoamPoint;
-typedef struct _RoamTriangle RoamTriangle;
-typedef struct _RoamDiamond RoamDiamond;
-typedef struct _RoamSphere RoamSphere;
-typedef void (*RoamTriFunc)(RoamTriangle *triangle, gpointer user_data);
-typedef void (*RoamHeightFunc)(RoamPoint *point, gpointer user_data);
-
-/* Misc */
-struct _RoamView {
- gdouble model[16];
- gdouble proj[16];
- gint view[4];
-};
-
-/*************
- * RoamPoint *
- *************/
-struct _RoamPoint {
- gdouble x,y,z; // Model coordinates
- gdouble px,py,pz; // Projected coordinates
-
- gboolean cached; // Height/projection cached
-
- gint tris; // Associated triangles
- gdouble norm[3]; // Vertex normal
-
- WmsCacheNode *node; // TODO: don't depend on wms
-};
-RoamPoint *roam_point_new(double x, double y, double z);
-void roam_point_add_triangle(RoamPoint *point, RoamTriangle *triangle);
-void roam_point_remove_triangle(RoamPoint *point, RoamTriangle *triangle);
-void roam_point_update(RoamPoint *point, RoamSphere *sphere, gboolean do_height);
-void roam_point_clear(RoamPoint *self);
-
-/****************
- * RoamTriangle *
- ****************/
-struct _RoamTriangle {
- struct { RoamPoint *l,*m,*r; } p;
- struct { RoamTriangle *l,*b,*r; } t;
- RoamDiamond *parent;
- double norm[3];
- double error;
- GPQueueHandle handle;
-
- WmsCacheNode *nodes[5]; // TODO: don't depend on wms
-};
-RoamTriangle *roam_triangle_new(RoamPoint *l, RoamPoint *m, RoamPoint *r);
-void roam_triangle_add(RoamTriangle *triangle,
- RoamTriangle *left, RoamTriangle *base, RoamTriangle *right,
- RoamSphere *sphere);
-void roam_triangle_remove(RoamTriangle *triangle, RoamSphere *sphere);
-void roam_triangle_update(RoamTriangle *triangle, RoamSphere *sphere);
-void roam_triangle_split(RoamTriangle *triangle, RoamSphere *sphere);
-void roam_triangle_draw_normal(RoamTriangle *triangle);
-
-/***************
- * RoamDiamond *
- ***************/
-struct _RoamDiamond {
- RoamTriangle *kids[4];
- RoamTriangle *parents[2];
- double error;
- gboolean active;
- GPQueueHandle handle;
-};
-RoamDiamond *roam_diamond_new(
- RoamTriangle *parent0, RoamTriangle *parent1,
- RoamTriangle *kid0, RoamTriangle *kid1,
- RoamTriangle *kid2, RoamTriangle *kid3);
-void roam_diamond_add(RoamDiamond *diamond, RoamSphere *sphere);
-void roam_diamond_remove(RoamDiamond *diamond, RoamSphere *sphere);
-void roam_diamond_merge(RoamDiamond *diamond, RoamSphere *sphere);
-void roam_diamond_update(RoamDiamond *self, RoamSphere *sphere);
-
-/**************
- * RoamSphere *
- **************/
-struct _RoamSphere {
- GPQueue *triangles;
- GPQueue *diamonds;
- RoamView *view;
- RoamTriFunc tri_func;
- RoamHeightFunc height_func;
- gpointer user_data;
- gint polys;
-};
-RoamSphere *roam_sphere_new(RoamTriFunc tri_func, RoamHeightFunc height_func, gpointer user_data);
-void roam_sphere_update(RoamSphere *sphere);
-void roam_sphere_split_one(RoamSphere *sphere);
-void roam_sphere_merge_one(RoamSphere *sphere);
-gint roam_sphere_split_merge(RoamSphere *sphere);
-void roam_sphere_draw(RoamSphere *sphere);
-void roam_sphere_draw_normals(RoamSphere *sphere);
-void roam_sphere_free(RoamSphere *sphere);
-
-#endif
+++ /dev/null
-/*
- * 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 <string.h>
-#include <stdio.h>
-#include <time.h>
-#include <gtk/gtk.h>
-#include <glib/gstdio.h>
-#include <libsoup/soup.h>
-
-#include "wms.h"
-
-/* TODO: try to remove these */
-#include "gis-world.h"
-#include <GL/gl.h>
-
-gchar *wms_make_uri(WmsInfo *info, gdouble xmin, gdouble ymin, gdouble xmax, gdouble ymax)
-{
- return g_strdup_printf(
- "%s?"
- "SERVICE=WMS&"
- "VERSION=1.1.0&"
- "REQUEST=GetMap&"
- "LAYERS=%s&"
- "STYLES=&"
- "SRS=EPSG:4326&"
- "BBOX=%f,%f,%f,%f&"
- "FORMAT=%s&"
- "WIDTH=%d&"
- "HEIGHT=%d",
- info->uri_prefix,
- info->uri_layer,
- xmin, ymin, xmax, ymax,
- info->uri_format,
- info->width,
- info->height);
-}
-
-/****************
- * WmsCacheNode *
- ****************/
-WmsCacheNode *wms_cache_node_new(WmsCacheNode *parent,
- gdouble xmin, gdouble ymin, gdouble xmax, gdouble ymax, gint width)
-{
- WmsCacheNode *self = g_new0(WmsCacheNode, 1);
- //g_debug("WmsCacheNode: new - %p %+7.3f,%+7.3f,%+7.3f,%+7.3f",
- // self, xmin, ymin, xmax, ymax);
- self->latlon[0] = xmin;
- self->latlon[1] = ymin;
- self->latlon[2] = xmax;
- self->latlon[3] = ymax;
- self->parent = parent;
- if (ymin <= 0 && ymax >= 0)
- self->res = ll2m(xmax-xmin, 0)/width;
- else
- self->res = ll2m(xmax-xmin, MIN(ABS(ymin),ABS(ymax)))/width;
- return self;
-}
-
-void wms_cache_node_free(WmsCacheNode *node, WmsFreeer freeer)
-{
- //g_debug("WmsCacheNode: free - %p", node);
- if (node->data) {
- freeer(node);
- node->data = NULL;
- }
- for (int x = 0; x < 4; x++)
- for (int y = 0; y < 4; y++)
- if (node->children[x][y])
- wms_cache_node_free(node->children[x][y], freeer);
- g_free(node);
-}
-
-/***********
- * WmsInfo *
- ***********/
-WmsInfo *wms_info_new(WmsLoader loader, WmsFreeer freeer,
- gchar *uri_prefix, gchar *uri_layer, gchar *uri_format,
- gchar *cache_prefix, gchar *cache_ext,
- gint resolution, gint width, gint height
-) {
- WmsInfo *self = g_new0(WmsInfo, 1);
- self->loader = loader;
- self->freeer = freeer;
- 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->resolution = resolution;
- self->width = width;
- self->height = height;
-
- self->max_age = 60;
- self->atime = time(NULL);
- self->gc_source = g_timeout_add_seconds(1, (GSourceFunc)wms_info_gc, self);
- self->cache_root = wms_cache_node_new(NULL, -180, -90, 180, 90, width);
- self->soup = soup_session_async_new();
- return self;
-}
-
-struct _CacheImageState {
- WmsInfo *info;
- gchar *path;
- FILE *output;
- WmsCacheNode *node;
- WmsChunkCallback user_chunk_cb;
- WmsDoneCallback user_done_cb;
- gpointer user_data;
-};
-void wms_info_soup_chunk_cb(SoupMessage *message, SoupBuffer *chunk, gpointer _state)
-{
- struct _CacheImageState *state = _state;
- 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, state->output) != 1)
- g_warning("WmsInfo: soup_chunk_cb - eror writing data");
-
- gdouble cur = (gdouble)ftell(state->output);
- if (state->user_chunk_cb)
- state->user_chunk_cb(cur, total, state->user_data);
-}
-void wms_info_soup_done_cb(SoupSession *session, SoupMessage *message, gpointer _state)
-{
- struct _CacheImageState *state = _state;
- if (!SOUP_STATUS_IS_SUCCESSFUL(message->status_code))
- return;
- gchar *dest = g_strndup(state->path, strlen(state->path)-5);
- g_rename(state->path, dest);
- state->node->atime = time(NULL);
- state->info->loader(state->node, dest, state->info->width, state->info->height);
- if (state->user_done_cb)
- state->user_done_cb(state->node, state->user_data);
- state->node->caching = FALSE;
- fclose(state->output);
- g_free(state->path);
- g_free(dest);
- g_free(state);
-}
-gboolean wms_info_cache_loader_cb(gpointer _state)
-{
- struct _CacheImageState *state = _state;
- state->node->atime = time(NULL);
- state->info->loader(state->node, state->path, state->info->width, state->info->height);
- if (state->user_done_cb)
- state->user_done_cb(state->node, state->user_data);
- state->node->caching = FALSE;
- g_free(state->path);
- g_free(state);
- return FALSE;
-}
-/**
- * Cache required tiles
- * 1. Load closest tile that's stored on disk
- * 2. Fetch the correct tile from the remote server
- */
-void wms_info_cache(WmsInfo *info, gdouble resolution, gdouble lat, gdouble lon,
- WmsChunkCallback chunk_callback, WmsDoneCallback done_callback,
- gpointer user_data)
-{
- /* Base cache path */
- gdouble x=lon, y=lat;
- gdouble xmin=-180, ymin=-90, xmax=180, ymax=90;
- gdouble xdist = xmax - xmin;
- gdouble ydist = ymax - ymin;
- int xpos=0, ypos=0;
- gdouble cur_lat = 0;
-
- WmsCacheNode *target_node = info->cache_root;
- WmsCacheNode *approx_node = NULL;
-
- GString *target_path = g_string_new(g_get_user_cache_dir());
- g_string_append(target_path, G_DIR_SEPARATOR_S);
- g_string_append(target_path, "wms");
- g_string_append(target_path, G_DIR_SEPARATOR_S);
- g_string_append(target_path, info->cache_prefix);
- gchar *approx_path = NULL;
-
- /* Create nodes to tiles, determine paths and lat-lon coords */
- while (TRUE) {
- /* Update the best approximation if it exists on disk */
- gchar *tmp = g_strconcat(target_path->str, info->cache_ext, NULL);
- if (g_file_test(tmp, G_FILE_TEST_EXISTS)) {
- g_free(approx_path);
- approx_node = target_node;
- approx_path = tmp;
- } else {
- g_free(tmp);
- }
-
- /* Break if current resolution (m/px) is good enough */
- if (ll2m(xdist, cur_lat)/info->width <= resolution ||
- ll2m(xdist, cur_lat)/info->width <= info->resolution)
- break;
-
- /* Get locations for the correct sub-tile */
- xpos = (int)(((x - xmin) / xdist) * 4);
- ypos = (int)(((y - ymin) / ydist) * 4);
- if (xpos == 4) xpos--;
- if (ypos == 4) ypos--;
- xdist /= 4;
- ydist /= 4;
- xmin = xmin + xdist*(xpos+0);
- ymin = ymin + ydist*(ypos+0);
- xmax = xmin + xdist;
- ymax = ymin + ydist;
- cur_lat = MIN(ABS(ymin), ABS(ymax));
-
- /* Update target for correct sub-tile */
- g_string_append_printf(target_path, "/%d%d", xpos, ypos);
- if (target_node->children[xpos][ypos] == NULL)
- target_node->children[xpos][ypos] =
- wms_cache_node_new(target_node,
- xmin, ymin, xmax, ymax, info->width);
- target_node = target_node->children[xpos][ypos];
- }
-
- /* Load disk on-disk approximation, TODO: async */
- if (approx_node && !approx_node->data && !approx_node->caching) {
- approx_node->caching = TRUE;
- struct _CacheImageState *state = g_new0(struct _CacheImageState, 1);
- state->info = info;
- state->path = approx_path;
- state->node = approx_node;
- state->user_done_cb = done_callback;
- state->user_data = user_data;
- g_idle_add(wms_info_cache_loader_cb, state);
- } else {
- g_free(approx_path);
- }
-
- /* If target image is not on-disk, download it now */
- if (target_node != approx_node && !target_node->caching) {
- target_node->caching = TRUE;
- g_string_append(target_path, info->cache_ext);
- g_string_append(target_path, ".part");
-
- gchar *dirname = g_path_get_dirname(target_path->str);
- g_mkdir_with_parents(dirname, 0755);
- g_free(dirname);
-
- struct _CacheImageState *state = g_new0(struct _CacheImageState, 1);
- state->info = info;
- state->path = target_path->str;
- state->output = fopen(target_path->str, "a");
- state->node = target_node;
- state->user_chunk_cb = chunk_callback;
- state->user_done_cb = done_callback;
- state->user_data = user_data;
-
- gchar *uri = wms_make_uri(info, xmin, ymin, xmax, ymax);
- SoupMessage *message = soup_message_new("GET", uri);
- g_signal_connect(message, "got-chunk", G_CALLBACK(wms_info_soup_chunk_cb), state);
- soup_message_headers_set_range(message->request_headers, ftell(state->output), -1);
-
- soup_session_queue_message(info->soup, message, wms_info_soup_done_cb, state);
-
- g_debug("Caching file: %s -> %s", uri, state->path);
- g_free(uri);
- g_string_free(target_path, FALSE);
- } else {
- g_string_free(target_path, TRUE);
- }
-}
-/* TODO:
- * - Store WmsCacheNode in point and then use parent pointers to go up/down
- * - If resolution doesn't change, tell caller to skip remaining calculations
- */
-WmsCacheNode *wms_info_fetch(WmsInfo *info, WmsCacheNode *root,
- gdouble resolution, gdouble lat, gdouble lon,
- gboolean *correct)
-{
- if (root && root->data && !root->caching &&
- root->latlon[0] <= lon && lon <= root->latlon[2] &&
- root->latlon[1] <= lat && lat <= root->latlon[3] &&
- root->res <= resolution &&
- (!root->parent || root->parent->res > resolution)) {
- *correct = TRUE;
- info->atime = time(NULL);
- root->atime = info->atime;
- return root;
- }
-
- if (info->cache_root == NULL) {
- *correct = FALSE;
- return NULL;
- }
- WmsCacheNode *node = info->cache_root;
- WmsCacheNode *best = (node && node->data ? node : NULL);
- gdouble xmin=-180, ymin=-90, xmax=180, ymax=90, xdist=360, ydist=180;
- gdouble cur_lat = 0;
- int xpos=0, ypos=0;
- gdouble cur_res = ll2m(xdist, cur_lat)/info->width;
- while (cur_res > resolution &&
- cur_res > info->resolution) {
-
- xpos = ((lon - xmin) / xdist) * 4;
- ypos = ((lat - ymin) / ydist) * 4;
- if (xpos == 4) xpos--;
- if (ypos == 4) ypos--;
- xdist /= 4;
- ydist /= 4;
- xmin = xmin + xdist*(xpos+0);
- ymin = ymin + ydist*(ypos+0);
- cur_lat = MIN(ABS(ymin), ABS(ymax));
-
- node = node->children[xpos][ypos];
- if (node == NULL)
- break;
- if (node->data)
- best = node;
-
- cur_res = ll2m(xdist, cur_lat)/info->width;
- }
- if (correct)
- *correct = (node && node == best);
- info->atime = time(NULL);
- if (best)
- best->atime = info->atime;
- return best;
-}
-
-WmsCacheNode *wms_info_fetch_cache(WmsInfo *info, WmsCacheNode *root,
- gdouble res, gdouble lat, gdouble lon,
- WmsChunkCallback chunk_callback, WmsDoneCallback done_callback, gpointer user_data)
-{
- /* Fetch a node, if it isn't cached, cache it, also keep it's parent cached */
- gboolean correct;
- WmsCacheNode *node = wms_info_fetch(info, root, res, lat, lon, &correct);
- if (!node || !correct)
- wms_info_cache(info, res, lat, lon, chunk_callback, done_callback, user_data);
- //else if (node->parent && node->parent->data == NULL)
- // wms_info_cache(info, node->parent->res, lat, lon, chunk_callback, done_callback, user_data);
- //else if (node->parent)
- // node->parent->atime = node->atime;
- return node;
-}
-
-/* Delete unused nodes and prune empty branches */
-static WmsCacheNode *wms_info_gc_cb(WmsInfo *self, WmsCacheNode *node)
-{
- gboolean empty = FALSE;
- if (self->atime - node->atime > self->max_age &&
- node->data && node != self->cache_root && !node->caching) {
- g_debug("WmsInfo: gc - expired node %p", node);
- self->freeer(node);
- node->data = NULL;
- empty = TRUE;
- }
- for (int x = 0; x < 4; x++)
- for (int y = 0; y < 4; y++)
- if (node->children[x][y]) {
- node->children[x][y] =
- wms_info_gc_cb(self, node->children[x][y]);
- empty = FALSE;
- }
- if (empty) {
- g_debug("WmsInfo: gc - empty branch %p", node);
- /*
- * TODO: Don't prune nodes while we're caching WmsCacheNodes in the Roam triangles
- * and points
- g_free(node);
- return NULL;
- */
- return node;
- } else {
- return node;
- }
-}
-
-gboolean wms_info_gc(WmsInfo *self)
-{
- if (!wms_info_gc_cb(self, self->cache_root))
- g_warning("WmsInfo: gc - root not should not be empty");
- return TRUE;
-}
-
-void wms_info_free(WmsInfo *self)
-{
- wms_cache_node_free(self->cache_root, self->freeer);
- g_object_unref(self->soup);
- g_free(self);
-}
-
-
-/************************
- * Blue Marble Next Gen *
- ************************/
-void bmng_opengl_loader(WmsCacheNode *node, const gchar *path, gint width, gint height)
-{
- GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(path, NULL);
- node->data = g_new0(guint, 1);
-
- /* Load image */
- guchar *pixels = gdk_pixbuf_get_pixels(pixbuf);
- int alpha = gdk_pixbuf_get_has_alpha(pixbuf);
- int nchan = 4; // gdk_pixbuf_get_n_channels(pixbuf);
-
- /* Create Texture */
- glGenTextures(1, node->data);
- glBindTexture(GL_TEXTURE_2D, *(guint*)node->data);
-
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- glPixelStorei(GL_PACK_ALIGNMENT, 1);
- glTexImage2D(GL_TEXTURE_2D, 0, nchan, width, height, 0,
- (alpha ? GL_RGBA : GL_RGB), GL_UNSIGNED_BYTE, pixels);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
-
- g_object_unref(pixbuf);
- g_debug("WmsCacheNode: bmng_opengl_loader: %s -> %p", path, node->data);
-}
-void bmng_opengl_freeer(WmsCacheNode *node)
-{
- g_debug("WmsCacheNode: bmng_opengl_freeer: %p", node->data);
- glDeleteTextures(1, node->data);
- g_free(node->data);
-}
-
-void bmng_pixbuf_loader(WmsCacheNode *node, const gchar *path, gint width, gint height)
-{
- node->data = gdk_pixbuf_new_from_file(path, NULL);
- g_debug("WmsCacheNode: bmng_opengl_loader: %s -> %p", path, node->data);
-}
-void bmng_pixbuf_freeer(WmsCacheNode *node)
-{
- g_debug("WmsCacheNode: bmng_opengl_freeer: %p", node->data);
- g_object_unref(node->data);
-}
-
-WmsInfo *wms_info_new_for_bmng(WmsLoader loader, WmsFreeer freeer)
-{
- loader = loader ?: bmng_opengl_loader;
- freeer = freeer ?: bmng_opengl_freeer;
- return wms_info_new(loader, freeer,
- "http://www.nasa.network.com/wms", "bmng200406", "image/jpeg",
- "bmng", ".jpg", 500, 512, 256);
-}
-
-/********************************************
- * Shuttle Radar Topography Mission 30 Plus *
- ********************************************/
-void srtm_bil_loader(WmsCacheNode *node, const gchar *path, gint width, gint height)
-{
- WmsBil *bil = g_new0(WmsBil, 1);
- gchar **char_data = (gchar**)&bil->data;
- g_file_get_contents(path, char_data, NULL, NULL);
- bil->width = width;
- bil->height = height;
- node->data = bil;
- g_debug("WmsCacheNode: srtm_opengl_loader: %s -> %p", path, node->data);
-}
-void srtm_bil_freeer(WmsCacheNode *node)
-{
- g_debug("WmsCacheNode: srtm_opengl_freeer: %p", node);
- g_free(((WmsBil*)node->data)->data);
- g_free(node->data);
-}
-
-void srtm_pixbuf_loader(WmsCacheNode *node, const gchar *path, gint width, gint height)
-{
- GdkPixbuf *pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, width, height);
- guchar *pixels = gdk_pixbuf_get_pixels(pixbuf);
- gint stride = gdk_pixbuf_get_rowstride(pixbuf);
-
- gint16 *data;
- gchar **char_data = (gchar**)&data;
- g_file_get_contents(path, char_data, NULL, NULL);
- for (int r = 0; r < height; r++) {
- for (int c = 0; c < width; c++) {
- gint16 value = data[r*width + c];
- //guchar color = (float)(MAX(value,0))/8848 * 255;
- guchar color = (float)value/8848 * 255;
- pixels[r*stride + c*3 + 0] = color;
- pixels[r*stride + c*3 + 1] = color;
- pixels[r*stride + c*3 + 2] = color;
- }
- }
- g_free(data);
-
- node->data = pixbuf;
- g_debug("WmsCacheNode: srtm_opengl_loader: %s -> %p", path, node->data);
-}
-void srtm_pixbuf_freeer(WmsCacheNode *node)
-{
- g_debug("WmsCacheNode: srtm_opengl_freeer: %p", node);
- g_object_unref(node->data);
-}
-
-WmsInfo *wms_info_new_for_srtm(WmsLoader loader, WmsFreeer freeer)
-{
- loader = loader ?: srtm_bil_loader;
- freeer = freeer ?: srtm_bil_freeer;
- return wms_info_new(loader, freeer,
- "http://www.nasa.network.com/elev", "srtm30", "application/bil",
- "srtm", ".bil", 500, 512, 256);
-}
+++ /dev/null
-/*
- * 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 __WMS_H__
-#define __WMS_H__
-
-#include <math.h>
-#include <time.h>
-#include <libsoup/soup.h>
-
-typedef struct _WmsCacheNode WmsCacheNode;
-typedef struct _WmsInfo WmsInfo;
-
-typedef void (*WmsChunkCallback)(gsize cur, gsize total, gpointer user_data);
-typedef void (*WmsDoneCallback)(WmsCacheNode *node, gpointer user_data);
-typedef void (*WmsLoader)(WmsCacheNode *node, const gchar *path, gint width, gint height);
-typedef void (*WmsFreeer)(WmsCacheNode *node);
-
-/****************
- * WmsCacheNode *
- ****************/
-struct _WmsCacheNode {
- gpointer data;
- gdouble latlon[4]; // xmin,ymin,xmax,ymax
- gdouble res; // xmin,ymin,xmax,ymax
- gboolean caching;
- time_t atime;
- WmsCacheNode *parent;
- WmsCacheNode *children[4][4];
-};
-
-WmsCacheNode *wms_cache_node_new(WmsCacheNode *parent, gdouble xmin, gdouble ymin, gdouble xmax, gdouble ymax, gint width);
-
-void wms_cache_node_free(WmsCacheNode *node, WmsFreeer freeer);
-
-/***********
- * WmsInfo *
- ***********/
-struct _WmsInfo {
- gchar *uri_prefix;
- gchar *uri_layer;
- gchar *uri_format;
- gchar *cache_prefix;
- gchar *cache_ext;
- gint resolution; // m/px
- gint width;
- gint height;
-
- guint max_age;
- guint gc_source;
- time_t atime;
- WmsLoader loader;
- WmsFreeer freeer;
- WmsCacheNode *cache_root;
- SoupSession *soup;
-};
-
-WmsInfo *wms_info_new(WmsLoader loader, WmsFreeer freeer,
- gchar *uri_prefix, gchar *uri_layer, gchar *uri_format,
- gchar *cache_prefix, gchar *cache_ext,
- gint resolution, gint width, gint height);
-
-void wms_info_cache(WmsInfo *info, gdouble resolution, gdouble lat, gdouble lon,
- WmsChunkCallback chunk_callback, WmsDoneCallback done_callback,
- gpointer user_data);
-
-WmsCacheNode *wms_info_fetch(WmsInfo *info, WmsCacheNode *root,
- gdouble resolution, gdouble lat, gdouble lon,
- gboolean *correct);
-
-WmsCacheNode *wms_info_fetch_cache(WmsInfo *info, WmsCacheNode *root,
- gdouble resolution, gdouble lat, gdouble lon,
- WmsChunkCallback chunk_callback, WmsDoneCallback done_callback,
- gpointer user_data);
-
-gboolean wms_info_gc(WmsInfo *self);
-
-void wms_info_free(WmsInfo *info);
-
-
-/********************************
- * Specific things (bmng, srtm) *
- ********************************/
-typedef struct _WmsBil WmsBil;
-struct _WmsBil {
- gint16 *data;
- gint width;
- gint height;
-};
-
-void bmng_opengl_loader(WmsCacheNode *node, const gchar *path, gint width, gint height);
-void bmng_opengl_freeer(WmsCacheNode *node);
-
-void bmng_pixbuf_loader(WmsCacheNode *node, const gchar *path, gint width, gint height);
-void bmng_pixbuf_freeer(WmsCacheNode *node);
-
-WmsInfo *wms_info_new_for_bmng(WmsLoader loader, WmsFreeer freeer);
-
-void srtm_bil_loader(WmsCacheNode *node, const gchar *path, gint width, gint height);
-void srtm_bil_freeer(WmsCacheNode *node);
-
-void srtm_pixbuf_loader(WmsCacheNode *node, const gchar *path, gint width, gint height);
-void srtm_pixbuf_freeer(WmsCacheNode *node);
-
-WmsInfo *wms_info_new_for_srtm(WmsLoader loader, WmsFreeer freeer);
-
-#endif
+++ /dev/null
-#include <gtk/gtk.h>
-#include <gdk/gdkkeysyms.h>
-
-#include "wms.h"
-
-struct CacheState {
- GtkWidget *image;
- GtkWidget *status;
- 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)
-{
- struct CacheState *state = _state;
- g_message("chunk_callback: %d/%d", cur, total);
-
- if (state->progress == NULL) {
- state->progress = gtk_progress_bar_new();
- gtk_box_pack_end(GTK_BOX(state->status), state->progress, FALSE, FALSE, 0);
- gtk_widget_show(state->progress);
- }
-
- if (cur == total)
- gtk_widget_destroy(state->progress);
- else
- gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(state->progress), (gdouble)cur/total);
-}
-
-gboolean key_press_cb(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
-{
- if (event->keyval == GDK_q)
- gtk_main_quit();
- return TRUE;
-}
-
-int main(int argc, char **argv)
-{
- gtk_init(&argc, &argv);
- g_thread_init(NULL);
-
- GtkWidget *win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- GtkWidget *vbox1 = gtk_vbox_new(FALSE, 0);
- GtkWidget *vbox2 = gtk_vbox_new(FALSE, 0);
- GtkWidget *status = gtk_statusbar_new();
- GtkWidget *scroll = gtk_scrolled_window_new(NULL, NULL);
- GtkWidget *bmng_image = gtk_image_new();
- GtkWidget *srtm_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(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);
- 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);
-
- gtk_widget_show_all(win);
- gtk_main();
-
- wms_info_free(bmng_info);
- wms_info_free(srtm_info);
-
- return 0;
-}
AM_CFLAGS = -Wall --std=gnu99 -I../
-AM_CPPFLAGS = $(GLIB_CFLAGS) $(GTK_CFLAGS) $(SOUP_CFLAGS)
+AM_CPPFLAGS = $(GIS_CFLAGS)
AM_LDFLAGS = -module -avoid-version
-LIBS = $(top_srcdir)/src/gis/libgis.la
+LIBS = $(GIS_LIBS)
plugindir = $(libdir)/gis
+++ /dev/null
-.libs
\ No newline at end of file