--- /dev/null
+/*
+ * Copyright (C) 2009-2010 Andy Spencer <andy753421@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * 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 <math.h>
+#include <GL/gl.h>
+#include <glib/gstdio.h>
+#include <gis.h>
+#include <rsl.h>
+
+#include "level2.h"
+
+
+/**************************
+ * Data loading functions *
+ **************************/
+/* Convert a sweep to an 2d array of data points */
+static void _bscan_sweep(Sweep *sweep, AWeatherColormap *colormap,
+ guint8 **data, int *width, int *height)
+{
+ g_debug("AWeatherLevel2: _bscan_sweep - %p, %p, %p",
+ sweep, colormap, data);
+ /* Calculate max number of bins */
+ int max_bins = 0;
+ for (int i = 0; i < sweep->h.nrays; i++)
+ max_bins = MAX(max_bins, sweep->ray[i]->h.nbins);
+
+ /* Allocate buffer using max number of bins for each ray */
+ guint8 *buf = g_malloc0(sweep->h.nrays * max_bins * 4);
+
+ /* Fill the data */
+ for (int ri = 0; ri < sweep->h.nrays; ri++) {
+ Ray *ray = sweep->ray[ri];
+ for (int bi = 0; bi < ray->h.nbins; bi++) {
+ /* copy RGBA into buffer */
+ //guint val = dz_f(ray->range[bi]);
+ guint8 val = (guint8)ray->h.f(ray->range[bi]);
+ guint buf_i = (ri*max_bins+bi)*4;
+ buf[buf_i+0] = colormap->data[val][0];
+ buf[buf_i+1] = colormap->data[val][1];
+ buf[buf_i+2] = colormap->data[val][2];
+ buf[buf_i+3] = colormap->data[val][3]*0.75; // TESTING
+ if (val == BADVAL || val == RFVAL || val == APFLAG ||
+ val == NOTFOUND_H || val == NOTFOUND_V || val == NOECHO) {
+ buf[buf_i+3] = 0x00; // transparent
+ }
+ }
+ }
+
+ /* set output */
+ *width = max_bins;
+ *height = sweep->h.nrays;
+ *data = buf;
+}
+
+/* Load a sweep into an OpenGL texture */
+static void _load_sweep_gl(Sweep *sweep, AWeatherColormap *colormap, guint *tex)
+{
+ g_debug("AWeatherLevel2: _load_sweep_gl");
+ int height, width;
+ guint8 *data;
+ _bscan_sweep(sweep, colormap, &data, &width, &height);
+ glGenTextures(1, tex);
+ glBindTexture(GL_TEXTURE_2D, *tex);
+ glPixelStorei(GL_PACK_ALIGNMENT, 1);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, data);
+ g_free(data);
+}
+
+/* Decompress a radar file using wsr88dec */
+static gboolean _decompress_radar(const gchar *file, const gchar *raw)
+{
+ g_debug("AWeatherLevel2: _decompress_radar - \n\t%s\n\t%s", file, raw);
+ char *argv[] = {"wsr88ddec", (gchar*)file, (gchar*)raw, NULL};
+ gint status;
+ GError *error = NULL;
+ g_spawn_sync(
+ NULL, // const gchar *working_directory
+ argv, // gchar **argv
+ NULL, // gchar **envp
+ G_SPAWN_SEARCH_PATH, // GSpawnFlags flags
+ NULL, // GSpawnChildSetupFunc child_setup
+ NULL, // gpointer user_data
+ NULL, // gchar *standard_output
+ NULL, // gchar *standard_output
+ &status, // gint *exit_status
+ &error); // GError **error
+ if (error) {
+ g_warning("AWeatherLevel2: _decompress_radar - %s", error->message);
+ g_error_free(error);
+ return FALSE;
+ }
+ if (status != 0) {
+ gchar *msg = g_strdup_printf("wsr88ddec exited with status %d", status);
+ g_warning("AWeatherLevel2: _decompress_radar - %s", msg);
+ g_free(msg);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+/*********************
+ * Drawing functions *
+ *********************/
+static gpointer _draw_radar(GisCallback *_self, gpointer _viewer)
+{
+ AWeatherLevel2 *self = AWEATHER_LEVEL2(_self);
+ if (!self->sweep || !self->sweep_tex)
+ return NULL;
+
+ /* Draw wsr88d */
+ Sweep *sweep = self->sweep;
+ Radar_header *h = &self->radar->h;
+ gdouble lat = (double)h->latd + (double)h->latm/60 + (double)h->lats/(60*60);
+ gdouble lon = (double)h->lond + (double)h->lonm/60 + (double)h->lons/(60*60);
+ gdouble elev = h->height;
+ gis_viewer_center_position(self->viewer, lat, lon, elev);
+
+ glDisable(GL_ALPHA_TEST);
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_LIGHTING);
+ glEnable(GL_TEXTURE_2D);
+ glEnable(GL_POLYGON_OFFSET_FILL);
+ glPolygonOffset(1.0, -2.0);
+ glColor4f(1,1,1,1);
+
+ /* Draw the rays */
+ glBindTexture(GL_TEXTURE_2D, self->sweep_tex);
+ g_message("Tex = %d", self->sweep_tex);
+ glBegin(GL_TRIANGLE_STRIP);
+ for (int ri = 0; ri <= sweep->h.nrays; ri++) {
+ Ray *ray = NULL;
+ double angle = 0;
+ if (ri < sweep->h.nrays) {
+ ray = sweep->ray[ri];
+ angle = deg2rad(ray->h.azimuth - ((double)ray->h.beam_width/2.));
+ } else {
+ /* Do the right side of the last sweep */
+ ray = sweep->ray[ri-1];
+ angle = deg2rad(ray->h.azimuth + ((double)ray->h.beam_width/2.));
+ }
+
+ double lx = sin(angle);
+ double ly = cos(angle);
+
+ double near_dist = ray->h.range_bin1;
+ double far_dist = ray->h.nbins*ray->h.gate_size + ray->h.range_bin1;
+
+ /* (find middle of bin) / scale for opengl */
+ // near left
+ glTexCoord2f(0.0, (double)ri/sweep->h.nrays-0.01);
+ glVertex3f(lx*near_dist, ly*near_dist, 2.0);
+
+ // far left
+ // todo: correct range-height function
+ double height = sin(deg2rad(ray->h.elev)) * far_dist;
+ glTexCoord2f(1.0, (double)ri/sweep->h.nrays-0.01);
+ glVertex3f(lx*far_dist, ly*far_dist, height);
+ }
+ glEnd();
+ //g_print("ri=%d, nr=%d, bw=%f\n", _ri, sweep->h.nrays, sweep->h.beam_width);
+
+ /* Texture debug */
+ //glBegin(GL_QUADS);
+ //glTexCoord2d( 0., 0.); glVertex3f(-500., 0., 0.); // bot left
+ //glTexCoord2d( 0., 1.); glVertex3f(-500., 500., 0.); // top left
+ //glTexCoord2d( 1., 1.); glVertex3f( 0., 500., 3.); // top right
+ //glTexCoord2d( 1., 0.); glVertex3f( 0., 0., 3.); // bot right
+ //glEnd();
+
+ return NULL;
+}
+
+
+/***********
+ * Methods *
+ ***********/
+static gboolean _set_sweep_cb(gpointer _self)
+{
+ g_debug("AWeatherLevel2: _set_sweep_cb");
+ AWeatherLevel2 *self = _self;
+ if (self->sweep_tex)
+ glDeleteTextures(1, &self->sweep_tex);
+ _load_sweep_gl(self->sweep, self->sweep_colors, &self->sweep_tex);
+ gtk_widget_queue_draw(GTK_WIDGET(self->viewer));
+ return FALSE;
+}
+void aweather_level2_set_sweep(AWeatherLevel2 *self,
+ int type, float elev)
+{
+ g_debug("AWeatherLevel2: set_sweep - %d %f", type, elev);
+
+ /* Find sweep */
+ Volume *volume = RSL_get_volume(self->radar, type);
+ if (!volume) return;
+ self->sweep = RSL_get_closest_sweep(volume, elev, 90);
+ if (!self->sweep) return;
+
+ /* Find colormap */
+ self->sweep_colors = NULL;
+ for (int i = 0; self->colormap[i].name; i++)
+ if (self->colormap[i].type == type)
+ self->sweep_colors = &self->colormap[i];
+ if (!self->sweep_colors) return;
+
+ /* Load data */
+ g_idle_add(_set_sweep_cb, self);
+}
+
+AWeatherLevel2 *aweather_level2_new(GisViewer *viewer,
+ AWeatherColormap *colormap, Radar *radar)
+{
+ g_debug("AWeatherLevel2: new");
+ AWeatherLevel2 *self = g_object_new(AWEATHER_TYPE_LEVEL2, NULL);
+ self->viewer = viewer;
+ self->radar = radar;
+ self->colormap = colormap;
+ aweather_level2_set_sweep(self, DZ_INDEX, 0);
+ return self;
+}
+
+AWeatherLevel2 *aweather_level2_new_from_file(GisViewer *viewer,
+ AWeatherColormap *colormap,
+ const gchar *file, const gchar *site)
+{
+ g_debug("AWeatherLevel2: new_from_file %s %s", site, file);
+
+ /* Decompress radar */
+ gchar *raw = g_strconcat(file, ".raw", NULL);
+ if (g_file_test(raw, G_FILE_TEST_EXISTS)) {
+ struct stat files, raws;
+ g_stat(file, &files);
+ g_stat(raw, &raws);
+ if (files.st_mtime < raws.st_mtime)
+ if (!_decompress_radar(file, raw))
+ return NULL;
+ } else {
+ if (!_decompress_radar(file, raw))
+ return NULL;
+ }
+
+ /* Load the radar file */
+ RSL_read_these_sweeps("all", NULL);
+ Radar *radar = RSL_wsr88d_to_radar(raw, (gchar*)site);
+ g_free(raw);
+ if (!radar)
+ return NULL;
+
+ return aweather_level2_new(viewer, colormaps, radar);
+}
+
+
+/****************
+ * GObject code *
+ ****************/
+G_DEFINE_TYPE(AWeatherLevel2, aweather_level2, GIS_TYPE_CALLBACK);
+static void aweather_level2_init(AWeatherLevel2 *self)
+{
+ GIS_CALLBACK(self)->callback = _draw_radar;
+ GIS_CALLBACK(self)->user_data = self;
+}
+
+static void aweather_level2_class_init(AWeatherLevel2Class *klass)
+{
+}
+
#include <gis.h>
#include "radar.h"
+#include "level2.h"
#include "../aweather-location.h"
-
-/**************************
- * Data loading functions *
- **************************/
-/* Convert a sweep to an 2d array of data points */
-static void _bscan_sweep(GisPluginRadar *self, Sweep *sweep, colormap_t *colormap,
- guint8 **data, int *width, int *height)
+/* Drawing functions */
+static gpointer _draw_hud(GisCallback *callback, gpointer _self)
{
- g_debug("GisPluginRadar: _bscan_sweep - %p, %p, %p",
- sweep, colormap, data);
- /* Calculate max number of bins */
- int max_bins = 0;
- for (int i = 0; i < sweep->h.nrays; i++)
- max_bins = MAX(max_bins, sweep->ray[i]->h.nbins);
-
- /* Allocate buffer using max number of bins for each ray */
- guint8 *buf = g_malloc0(sweep->h.nrays * max_bins * 4);
-
- /* Fill the data */
- for (int ri = 0; ri < sweep->h.nrays; ri++) {
- Ray *ray = sweep->ray[ri];
- for (int bi = 0; bi < ray->h.nbins; bi++) {
- /* copy RGBA into buffer */
- //guint val = dz_f(ray->range[bi]);
- guint8 val = (guint8)ray->h.f(ray->range[bi]);
- guint buf_i = (ri*max_bins+bi)*4;
- buf[buf_i+0] = colormap->data[val][0];
- buf[buf_i+1] = colormap->data[val][1];
- buf[buf_i+2] = colormap->data[val][2];
- buf[buf_i+3] = colormap->data[val][3]*0.75; // TESTING
- if (val == BADVAL || val == RFVAL || val == APFLAG ||
- val == NOTFOUND_H || val == NOTFOUND_V || val == NOECHO) {
- buf[buf_i+3] = 0x00; // transparent
- }
- }
- }
-
- /* set output */
- *width = max_bins;
- *height = sweep->h.nrays;
- *data = buf;
-}
+ GisPluginRadar *self = GIS_PLUGIN_RADAR(_self);
+ if (!self->colormap)
+ return NULL;
-/* Load a sweep as the active texture */
-static gboolean _load_sweep(gpointer _self)
-{
- GisPluginRadar *self = _self;
- if (!self->cur_sweep)
- return FALSE;
- g_debug("GisPluginRadar: _load_sweep - %p", self->cur_sweep);
- int height, width;
- guint8 *data;
- _bscan_sweep(self, self->cur_sweep, self->cur_colormap, &data, &width, &height);
- glDeleteTextures(1, &self->cur_sweep_tex);
- glGenTextures(1, &self->cur_sweep_tex);
- glBindTexture(GL_TEXTURE_2D, self->cur_sweep_tex);
- glPixelStorei(GL_PACK_ALIGNMENT, 1);
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0,
- GL_RGBA, GL_UNSIGNED_BYTE, data);
- g_free(data);
- gtk_widget_queue_draw(GTK_WIDGET(self->viewer));
- return FALSE;
-}
+ g_debug("GisPluginRadar: _draw_hud");
+ /* Print the color table */
+ glMatrixMode(GL_MODELVIEW ); glLoadIdentity();
+ glMatrixMode(GL_PROJECTION); glLoadIdentity();
+ glDisable(GL_TEXTURE_2D);
+ glDisable(GL_ALPHA_TEST);
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_LIGHTING);
+ glEnable(GL_COLOR_MATERIAL);
+ glBegin(GL_QUADS);
+ int i;
+ for (i = 0; i < 256; i++) {
+ glColor4ubv(self->colormap->data[i]);
+ glVertex3f(-1.0, (float)((i ) - 256/2)/(256/2), 0.0); // bot left
+ glVertex3f(-1.0, (float)((i+1) - 256/2)/(256/2), 0.0); // top left
+ glVertex3f(-0.9, (float)((i+1) - 256/2)/(256/2), 0.0); // top right
+ glVertex3f(-0.9, (float)((i ) - 256/2)/(256/2), 0.0); // bot right
+ }
+ glEnd();
-/* Load the colormap for a sweep */
-static void _load_colormap(GisPluginRadar *self, gchar *table)
-{
- g_debug("GisPluginRadar: _load_colormap - %s", table);
- /* Set colormap so we can draw it on expose */
- for (int i = 0; colormaps[i].name; i++)
- if (g_str_equal(colormaps[i].name, table))
- self->cur_colormap = &colormaps[i];
+ return NULL;
}
/***************
* GUI loading *
***************/
+/* Clear the config area */
+static void _load_gui_clear(GisPluginRadar *self)
+{
+ GtkWidget *child = gtk_bin_get_child(GTK_BIN(self->config_body));
+ if (child)
+ gtk_widget_destroy(child);
+}
+
/* Setup a loading screen in the tab */
static void _load_gui_pre(GisPluginRadar *self)
{
g_debug("GisPluginRadar: _load_gui_pre");
- gdk_threads_enter();
/* Set up progress bar */
- GtkWidget *child = gtk_bin_get_child(GTK_BIN(self->config_body));
- if (child)
- gtk_widget_destroy(child);
-
+ _load_gui_clear(self);
GtkWidget *vbox = gtk_vbox_new(FALSE, 10);
gtk_container_set_border_width(GTK_CONTAINER(vbox), 10);
self->progress_bar = gtk_progress_bar_new();
gtk_box_pack_start(GTK_BOX(vbox), self->progress_label, FALSE, FALSE, 0);
gtk_container_add(GTK_CONTAINER(self->config_body), vbox);
gtk_widget_show_all(self->config_body);
-
- /* Clear radar */
- if (self->cur_radar)
- RSL_free_radar(self->cur_radar);
- self->cur_radar = NULL;
- self->cur_sweep = NULL;
- gtk_widget_queue_draw(GTK_WIDGET(self->viewer));
- gdk_threads_leave();
}
/* Update pogress bar of loading screen */
//g_debug("GisPluginRadar: cache_chunk_cb - %lld/%lld = %.2f%%",
// cur, total, percent*100);
- gdk_threads_enter();
gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(self->progress_bar), MIN(percent, 1.0));
gchar *msg = g_strdup_printf("Loading radar... %5.1f%% (%.2f/%.2f MB)",
percent*100, (double)cur/1000000, (double)total/1000000);
gtk_label_set_text(GTK_LABEL(self->progress_label), msg);
- gdk_threads_leave();
g_free(msg);
}
gchar *msg = g_strdup_printf(
"GisPluginRadar: error loading radar - %s", error);
g_warning("%s", msg);
- gdk_threads_enter();
- GtkWidget *child = gtk_bin_get_child(GTK_BIN(self->config_body));
- if (child)
- gtk_widget_destroy(child);
+ _load_gui_clear(self);
gtk_container_add(GTK_CONTAINER(self->config_body), gtk_label_new(msg));
gtk_widget_show_all(self->config_body);
- gdk_threads_leave();
g_free(msg);
}
/* Clear loading screen and add sweep selectors */
static void _on_sweep_clicked(GtkRadioButton *button, gpointer _self);
-static void _load_gui_success(GisPluginRadar *self, Radar *radar)
+static void _load_gui_success(GisPluginRadar *self, AWeatherLevel2 *level2)
{
+ Radar *radar = level2->radar;
g_debug("GisPluginRadar: _load_gui_success - %p", radar);
/* Clear existing items */
- gdk_threads_enter();
- GtkWidget *child = gtk_bin_get_child(GTK_BIN(self->config_body));
- if (child)
- gtk_widget_destroy(child);
+ _load_gui_clear(self);
gdouble elev;
guint rows = 1, cols = 1, cur_cols;
g_object_set(button, "draw-indicator", FALSE, NULL);
gtk_box_pack_end(GTK_BOX(elev_box), button, TRUE, TRUE, 0);
- g_object_set_data(G_OBJECT(button), "type", vol->h.type_str);
- g_object_set_data(G_OBJECT(button), "sweep", sweep);
+ g_object_set_data(G_OBJECT(button), "level2", (gpointer)level2);
+ g_object_set_data(G_OBJECT(button), "type", (gpointer)vi);
+ g_object_set_data(G_OBJECT(button), "elev", (gpointer)(int)(elev*100));
g_signal_connect(button, "clicked", G_CALLBACK(_on_sweep_clicked), self);
}
}
gtk_container_add(GTK_CONTAINER(self->config_body), table);
gtk_widget_show_all(table);
- gdk_threads_leave();
}
-
-/*****************
- * Radar caching *
- *****************/
-/* Download a compressed radar file from the remote server */
static gchar *_download_radar(GisPluginRadar *self, const gchar *site, const gchar *time)
{
g_debug("GisPluginRadar: _download_radar - %s, %s", site, time);
gchar *local = g_strdup_printf("%s/%s_%s", site, site, time);
gchar *uri = g_strconcat(base, "/", local, NULL);
GisCacheType mode = gis_viewer_get_offline(self->viewer) ? GIS_LOCAL : GIS_UPDATE;
- return gis_http_fetch(self->http, uri, local, mode, _load_gui_update, self);
+ gchar *file = gis_http_fetch(self->http, uri, local, mode, _load_gui_update, self);
+ g_free(base);
+ g_free(local);
+ g_free(uri);
+ return file;
}
-/* Decompress a radar file using wsr88dec */
-static gchar *_decompress_radar(GisPluginRadar *self, char *compressed)
-{
- char *decompressed = g_strconcat(compressed, ".raw", NULL);
- if (g_file_test(decompressed, G_FILE_TEST_EXISTS)) {
- struct stat comp, dec;
- g_stat(compressed, &comp);
- g_stat(decompressed, &dec);
- if (dec.st_mtime >= comp.st_mtime)
- return decompressed;
- }
- g_debug("GisPluginRadar: _decompress_radar - %s", decompressed);
- char *argv[] = {"wsr88ddec", compressed, decompressed, NULL};
- gint status;
- GError *error = NULL;
- g_spawn_sync(
- NULL, // const gchar *working_directory
- argv, // gchar **argv
- NULL, // gchar **envp
- G_SPAWN_SEARCH_PATH, // GSpawnFlags flags
- NULL, // GSpawnChildSetupFunc child_setup
- NULL, // gpointer user_data
- NULL, // gchar *standard_output
- NULL, // gchar *standard_output
- &status, // gint *exit_status
- &error); // GError **error
- if (error) {
- g_warning("GisPluginRadar: _decompress_radar - %s", error->message);
- g_error_free(error);
- return NULL;
- }
- if (status != 0) {
- gchar *msg = g_strdup_printf("wsr88ddec exited with status %d", status);
- g_warning("GisPluginRadar: _decompress_radar - %s", msg);
- g_free(msg);
- return NULL;
- }
- return decompressed;
-}
-
-
-/****************
- * Misc helpers *
- ****************/
-/* Set the radar file based on cur_site andcur_time
- * This should be run in a separatet hread */
-static gboolean _set_radar_cb(GisPluginRadar *self)
+struct SetRadarData {
+ GisPluginRadar *self;
+ gchar *site;
+ gchar *time;
+};
+static gpointer _set_radar_cb(gpointer _data)
{
g_debug("GisPluginRadar: _set_radar_cb");
+ struct SetRadarData *data = _data;
+ GisPluginRadar *self = data->self;
+ gdk_threads_enter();
_load_gui_pre(self);
-
- /* Download and decompress the radar */
- gchar *compressed = _download_radar(self,
- self->cur_site, self->cur_time);
- if (!compressed) {
- _load_gui_error(self, "Download failed");
- goto fail;
- }
-
- /* Decompress radar */
- gchar *decompressed = _decompress_radar(self, compressed);
- g_free(compressed);
- if (!decompressed) {
- _load_gui_error(self, "Decompression failed");
- goto fail;
- }
-
- /* Load the radar file */
- g_debug("GisPluginRadar: _set_radar_cb - loading %s", decompressed);
- RSL_read_these_sweeps("all", NULL);
- self->cur_radar = RSL_wsr88d_to_radar(decompressed, self->cur_site);
- g_free(decompressed);
- if (!self->cur_radar) {
- _load_gui_error(self, "Loading failed");
- goto fail;
+ if (self->radar) {
+ gis_viewer_remove(self->viewer, self->radar);
+ self->radar = NULL;
}
-
- /* Load the first sweep by default */
- Radar *radar = self->cur_radar;
- Sweep *sweep = NULL;
- gchar *type_str = NULL;
- for (int vi = 0; vi < radar->h.nvolumes; vi++) {
- if (radar->v[vi] == NULL)
- continue;
- for (int si = 0; si < radar->v[vi]->h.nsweeps; si++) {
- if (radar->v[vi]->sweep[si] == NULL)
- continue;
- sweep = radar->v[vi]->sweep[si];
- type_str = radar->v[vi]->h.type_str;
- break;
- }
- break;
+ gchar *file = _download_radar(self, data->site, data->time);
+ if (!file) {
+ _load_gui_error(self, "Download failed");
+ goto out;
}
- if (!type_str) {
- _load_gui_error(self, "No sweeps found");
- goto fail;
+ AWeatherLevel2 *level2 = aweather_level2_new_from_file(
+ self->viewer, colormaps, file, data->site);
+ if (!level2) {
+ _load_gui_error(self, "Loading radar failed");
+ //g_remove(file);
+ goto out;
}
+ self->colormap = level2->sweep_colors;
+ self->radar = gis_viewer_add(self->viewer, GIS_OBJECT(level2), GIS_LEVEL_WORLD, TRUE);
+ _load_gui_success(self, level2);
- /* Load weep */
- g_debug("GisPluginRadar: _set_radar_cb - setting sweep");
- self->cur_sweep = sweep;
- _load_colormap(self, type_str);
- g_idle_add(_load_sweep, self);
- _load_gui_success(self, radar);
-
- /* Let other threads go */
- g_mutex_unlock(self->load_mutex);
- return TRUE;
-
-fail:
- g_mutex_unlock(self->load_mutex);
- return TRUE;
+out:
+ gdk_threads_leave();
+ g_free(file);
+ g_free(data->site);
+ g_free(data->time);
+ g_free(data);
+ return NULL;
}
-
-static void _set_radar(GisPluginRadar *self,
- gchar *site, gchar *time)
+static void _set_radar(GisPluginRadar *self, const gchar *site, const gchar *time)
{
- if (site) self->cur_site = site;
- if (time) self->cur_time = time;
- if (!self->cur_site || !self->cur_time)
+ if (!site || !time)
return;
-
- /* Abort any current downloads */
- soup_session_abort(self->http->soup);
-
- g_mutex_lock(self->load_mutex);
-
- g_thread_create((GThreadFunc)_set_radar_cb, self, FALSE, NULL);
+ //soup_session_abort(self->http->soup);
+ //g_mutex_lock(self->load_mutex);
+ struct SetRadarData *data = g_new(struct SetRadarData, 1);
+ data->self = self;
+ data->site = g_strdup(site);
+ data->time = g_strdup(time);
+ g_thread_create(_set_radar_cb, data, FALSE, NULL);
}
-
/*************
* Callbacks *
*************/
static void _on_sweep_clicked(GtkRadioButton *button, gpointer _self)
{
- GisPluginRadar *self = GIS_PLUGIN_RADAR(_self);
- _load_colormap(self, g_object_get_data(G_OBJECT(button), "type"));
- self->cur_sweep = g_object_get_data(G_OBJECT(button), "sweep");
- _load_sweep(self);
+ GisPluginRadar *self = GIS_PLUGIN_RADAR(_self);
+ AWeatherLevel2 *level2 = g_object_get_data(G_OBJECT(button), "level2");
+ gint type = (gint)g_object_get_data(G_OBJECT(button), "type");
+ gint elev = (gint)g_object_get_data(G_OBJECT(button), "elev");
+ aweather_level2_set_sweep(level2, type, (float)elev/100);
+ self->colormap = level2->sweep_colors;
}
static void _on_time_changed(GisViewer *viewer, const char *time, gpointer _self)
{
g_debug("GisPluginRadar: _on_time_changed");
GisPluginRadar *self = GIS_PLUGIN_RADAR(_self);
- _set_radar(self, self->cur_site, g_strdup(time));
+ self->cur_time = g_strdup(time);
+ _set_radar(self, self->cur_site, self->cur_time);
}
static void _on_location_changed(GisViewer *viewer,
}
}
static city_t *last_city = NULL;
- if (min_city && min_city != last_city)
- _set_radar(self, min_city->code, self->cur_time);
- last_city = min_city;
-}
-
-static gpointer _draw_radar(GisCallback *callback, gpointer _self)
-{
- GisPluginRadar *self = GIS_PLUGIN_RADAR(_self);
-
- /* Draw wsr88d */
- if (self->cur_sweep == NULL)
- return NULL;
- g_debug("GisPluginRadar: _draw_radar");
- Sweep *sweep = self->cur_sweep;
-
- g_debug("GisPluginRadar: _draw_radar - setting camera");
- Radar_header *h = &self->cur_radar->h;
- gdouble lat = (double)h->latd + (double)h->latm/60 + (double)h->lats/(60*60);
- gdouble lon = (double)h->lond + (double)h->lonm/60 + (double)h->lons/(60*60);
- gdouble elev = h->height;
- gis_viewer_center_position(self->viewer, lat, lon, elev);
-
- glDisable(GL_ALPHA_TEST);
- glDisable(GL_CULL_FACE);
- glDisable(GL_LIGHTING);
- glEnable(GL_TEXTURE_2D);
- glEnable(GL_POLYGON_OFFSET_FILL);
- glPolygonOffset(1.0, -2.0);
- glColor4f(1,1,1,1);
-
- /* Draw the rays */
- glBindTexture(GL_TEXTURE_2D, self->cur_sweep_tex);
- g_message("Tex = %d", self->cur_sweep_tex);
- glBegin(GL_TRIANGLE_STRIP);
- for (int ri = 0; ri <= sweep->h.nrays; ri++) {
- Ray *ray = NULL;
- double angle = 0;
- if (ri < sweep->h.nrays) {
- ray = sweep->ray[ri];
- angle = deg2rad(ray->h.azimuth - ((double)ray->h.beam_width/2.));
- } else {
- /* Do the right side of the last sweep */
- ray = sweep->ray[ri-1];
- angle = deg2rad(ray->h.azimuth + ((double)ray->h.beam_width/2.));
- }
-
- double lx = sin(angle);
- double ly = cos(angle);
-
- double near_dist = ray->h.range_bin1;
- double far_dist = ray->h.nbins*ray->h.gate_size + ray->h.range_bin1;
-
- /* (find middle of bin) / scale for opengl */
- // near left
- glTexCoord2f(0.0, (double)ri/sweep->h.nrays-0.01);
- glVertex3f(lx*near_dist, ly*near_dist, 2.0);
-
- // far left
- // todo: correct range-height function
- double height = sin(deg2rad(ray->h.elev)) * far_dist;
- glTexCoord2f(1.0, (double)ri/sweep->h.nrays-0.01);
- glVertex3f(lx*far_dist, ly*far_dist, height);
+ if (min_city && min_city != last_city){
+ self->cur_site = min_city->code;
+ _set_radar(self, self->cur_site, self->cur_time);
}
- glEnd();
- //g_print("ri=%d, nr=%d, bw=%f\n", _ri, sweep->h.nrays, sweep->h.beam_width);
-
- /* Texture debug */
- //glBegin(GL_QUADS);
- //glTexCoord2d( 0., 0.); glVertex3f(-500., 0., 0.); // bot left
- //glTexCoord2d( 0., 1.); glVertex3f(-500., 500., 0.); // top left
- //glTexCoord2d( 1., 1.); glVertex3f( 0., 500., 3.); // top right
- //glTexCoord2d( 1., 0.); glVertex3f( 0., 0., 3.); // bot right
- //glEnd();
-
- return NULL;
-}
-
-static gpointer _draw_hud(GisCallback *callback, gpointer _self)
-{
- GisPluginRadar *self = GIS_PLUGIN_RADAR(_self);
- if (self->cur_sweep == NULL)
- return NULL;
- g_debug("GisPluginRadar: _draw_hud");
-
- /* Print the color table */
- glMatrixMode(GL_MODELVIEW ); glLoadIdentity();
- glMatrixMode(GL_PROJECTION); glLoadIdentity();
- glDisable(GL_TEXTURE_2D);
- glDisable(GL_ALPHA_TEST);
- glDisable(GL_CULL_FACE);
- glDisable(GL_LIGHTING);
- glEnable(GL_COLOR_MATERIAL);
- glBegin(GL_QUADS);
- int i;
- for (i = 0; i < 256; i++) {
- glColor4ubv(self->cur_colormap->data[i]);
- glVertex3f(-1.0, (float)((i ) - 256/2)/(256/2), 0.0); // bot left
- glVertex3f(-1.0, (float)((i+1) - 256/2)/(256/2), 0.0); // top left
- glVertex3f(-0.9, (float)((i+1) - 256/2)/(256/2), 0.0); // top right
- glVertex3f(-0.9, (float)((i ) - 256/2)/(256/2), 0.0); // bot right
- }
- glEnd();
-
- return NULL;
+ last_city = min_city;
}
gis_viewer_add(self->viewer, GIS_OBJECT(marker), GIS_LEVEL_OVERLAY, FALSE);
}
- /* Add renderers */
- GisCallback *radar_cb = gis_callback_new(_draw_radar, self);
- GisCallback *hud_cb = gis_callback_new(_draw_hud, self);
-
- gis_viewer_add(viewer, GIS_OBJECT(radar_cb), GIS_LEVEL_WORLD, TRUE);
- gis_viewer_add(viewer, GIS_OBJECT(hud_cb), GIS_LEVEL_HUD, FALSE);
+ GisCallback *hud_cb = gis_callback_new(_draw_hud, self);
+ gis_viewer_add(viewer, GIS_OBJECT(hud_cb), GIS_LEVEL_HUD, FALSE);
return self;
}
/* Set defaults */
self->http = gis_http_new("/nexrad/level2/");
self->config_body = gtk_alignment_new(0, 0, 1, 1);
- self->load_mutex = g_mutex_new();
+ //self->load_mutex = g_mutex_new();
gtk_container_set_border_width(GTK_CONTAINER(self->config_body), 5);
gtk_container_add(GTK_CONTAINER(self->config_body), gtk_label_new("No radar loaded"));
}
GisPluginRadar *self = GIS_PLUGIN_RADAR(gobject);
/* Free data */
gis_http_free(self->http);
- g_mutex_free(self->load_mutex);
+ //g_mutex_free(self->load_mutex);
G_OBJECT_CLASS(gis_plugin_radar_parent_class)->finalize(gobject);
}