#include "plugin-ridge.h"
#include "plugin-example.h"
-static void destroy(GtkWidget *widget, gpointer data)
-{
- gtk_main_quit();
-}
-
-static gboolean delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
-{
- destroy(widget, data);
- return FALSE;
-}
-
-static gboolean key_press(GtkWidget *widget, GdkEventKey *event, gpointer data)
+gboolean on_window_key_press_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
{
if (event->keyval == GDK_q)
- destroy(widget, data);
+ gtk_main_quit();
return TRUE;
}
gtk_init(&argc, &argv);
gtk_gl_init(&argc, &argv);
- /* Set up window */
- GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- gtk_window_set_default_size(GTK_WINDOW(window), 800, 600);
- g_signal_connect(G_OBJECT(window), "delete-event", G_CALLBACK(delete_event), NULL);
- g_signal_connect(G_OBJECT(window), "key-press-event", G_CALLBACK(key_press), NULL);
+ GError *error = NULL;
+ GtkBuilder *builder = gtk_builder_new();
+ if (!gtk_builder_add_from_file(builder, DATADIR "/aweather/aweather.xml", &error))
+ g_error("Failed to create gtk builder: %s", error->message);
+ gtk_builder_connect_signals(builder, NULL);
- /* Set up layout */
- GtkWidget *vbox = gtk_vbox_new(FALSE, 0);
- gtk_container_add(GTK_CONTAINER(window), vbox);
- GtkWidget *paned = gtk_vpaned_new();
- gtk_box_pack_end(GTK_BOX(vbox), paned, TRUE, TRUE, 0);
-
- /* Set up menu bar */
- GtkWidget *menu = gtk_menu_bar_new();
- GtkWidget *menu_file = gtk_menu_item_new_with_label("File");
- GtkWidget *menu_file_menu = gtk_menu_new();
- GtkWidget *menu_file_menu_quit = gtk_menu_item_new_with_label("Quit");
- gtk_box_pack_start(GTK_BOX(vbox), menu, FALSE, FALSE, 0);
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_file);
- gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_file), menu_file_menu);
- gtk_menu_shell_append(GTK_MENU_SHELL(menu_file_menu), menu_file_menu_quit);
- g_signal_connect(G_OBJECT(menu_file_menu_quit), "activate", G_CALLBACK(destroy), NULL);
+ GtkWidget *window = GTK_WIDGET(gtk_builder_get_object(builder, "window"));
+ GtkWidget *drawing = GTK_WIDGET(gtk_builder_get_object(builder, "drawing"));
+ GtkWidget *tabs = GTK_WIDGET(gtk_builder_get_object(builder, "tabs"));
+ if (window == NULL) g_error("window is null");
+ if (drawing == NULL) g_error("drawing is null");
+ if (tabs == NULL) g_error("tabs is null");
/* Set up darwing area */
- GtkWidget *drawing = gtk_drawing_area_new();
- gtk_paned_pack1(GTK_PANED(paned), drawing, TRUE, FALSE);
- //gtk_box_pack_end(GTK_BOX(vbox), drawing, TRUE, TRUE, 0);
GdkGLConfig *glconfig = gdk_gl_config_new_by_mode(
- GDK_GL_MODE_RGBA |
- GDK_GL_MODE_DEPTH |
- GDK_GL_MODE_DOUBLE |
- GDK_GL_MODE_ALPHA);
+ GDK_GL_MODE_RGBA | GDK_GL_MODE_DEPTH |
+ GDK_GL_MODE_DOUBLE | GDK_GL_MODE_ALPHA);
if (!glconfig)
g_assert_not_reached();
if (!gtk_widget_set_gl_capability(drawing, glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE))
g_assert_not_reached();
- /* Set up tab area */
- GtkWidget *tab_area = gtk_notebook_new();
- gtk_notebook_set_tab_pos(GTK_NOTEBOOK(tab_area), GTK_POS_BOTTOM);
- gtk_paned_pack2(GTK_PANED(paned), tab_area, FALSE, FALSE);
- //GtkWidget *label = gtk_label_new("Hello");
- //GtkWidget *contents = gtk_label_new("World");
- //gtk_notebook_append_page(GTK_NOTEBOOK(tab_area), contents, label);
-
/* Load plugins */
- opengl_init (GTK_DRAWING_AREA(drawing), GTK_NOTEBOOK(tab_area));
- radar_init (GTK_DRAWING_AREA(drawing), GTK_NOTEBOOK(tab_area));
- ridge_init (GTK_DRAWING_AREA(drawing), GTK_NOTEBOOK(tab_area));
- example_init(GTK_DRAWING_AREA(drawing), GTK_NOTEBOOK(tab_area));
+ opengl_init (GTK_DRAWING_AREA(drawing), GTK_NOTEBOOK(tabs));
+ radar_init (GTK_DRAWING_AREA(drawing), GTK_NOTEBOOK(tabs));
+ ridge_init (GTK_DRAWING_AREA(drawing), GTK_NOTEBOOK(tabs));
+ example_init(GTK_DRAWING_AREA(drawing), GTK_NOTEBOOK(tabs));
gtk_widget_show_all(window);
gtk_main();
--- /dev/null
+#include <config.h>
+#include <gtk/gtk.h>
+#include <GL/gl.h>
+#include <math.h>
+
+#include "rsl.h"
+
+#include "plugin-radar.h"
+
+GtkWidget *drawing;
+static Sweep *cur_sweep = NULL; // make this not global
+static int nred, ngreen, nblue;
+static char red[256], green[256], blue[256];
+static guint sweep_tex = 0;
+
+static guint8 get_alpha(guint8 db)
+{
+ if (db == BADVAL) return 0;
+ if (db == RFVAL ) return 0;
+ if (db == APFLAG) return 0;
+ if (db == NOECHO) return 0;
+ if (db == 0 ) return 0;
+ //if (db > 60) return 0;
+ //else if (db < 10) return 0;
+ //else if (db < 25) return (db-10)*(255.0/15);
+ else return 255;
+}
+
+//#ifdef USE_TWO_BYTE_PRECISION
+//#define F_FACTOR 100.0
+//#define F_DR_FACTOR 1000.0
+//#define F_DZ_RANGE_OFFSET 50
+//#else
+//#define F_FACTOR 2.0
+//#define F_DR_FACTOR 10.0
+//#define F_DZ_RANGE_OFFSET 32
+//#endif
+//#define F_OFFSET 4
+//static float dz_f(Range x)
+//{
+// if (x >= F_OFFSET)
+// return (((float)x-F_OFFSET)/F_FACTOR - F_DZ_RANGE_OFFSET);
+// if (x == 0) return BADVAL;
+// if (x == 1) return RFVAL;
+// if (x == 2) return APFLAG;
+// if (x == 3) return NOECHO;
+// return BADVAL;
+//}
+
+/* Convert a sweep to an 2d array of data points */
+static void bscan_sweep(Sweep *sweep, guint8 **data, int *width, int *height)
+{
+ /* Calculate max number of bins */
+ int i, max_bins = 0;
+ for (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 */
+ int ri, bi;
+ for (ri = 0; ri < sweep->h.nrays; ri++) {
+ Ray *ray = sweep->ray[ri];
+ for (bi = 0; bi < ray->h.nbins; bi++) {
+ /* copy RGBA into buffer */
+ //guint val = dz_f(ray->range[bi]);
+ guint val = ray->h.f(ray->range[bi]);
+ guint buf_i = (ri*max_bins+bi)*4;
+ buf[buf_i+0] = red[val];
+ buf[buf_i+1] = green[val];
+ buf[buf_i+2] = blue[val];
+ buf[buf_i+3] = get_alpha(val);
+ }
+ }
+
+ /* set output */
+ *width = max_bins;
+ *height = sweep->h.nrays;
+ *data = buf;
+}
+
+/* Load a sweep as the active texture */
+static void load_sweep(Sweep *sweep)
+{
+ cur_sweep = sweep;
+ int height, width;
+ guint8 *data;
+ bscan_sweep(sweep, &data, &width, &height);
+ glGenTextures(1, &sweep_tex);
+ glBindTexture(GL_TEXTURE_2D, 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_LINEAR);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ g_free(data);
+ gdk_window_invalidate_rect(drawing->window, &drawing->allocation, FALSE);
+ gdk_window_process_updates(drawing->window, FALSE);
+}
+
+/* Load the default sweep */
+static gboolean configure(GtkWidget *da, GdkEventConfigure *event, gpointer user_data)
+{
+ Sweep *first = (Sweep*)user_data;
+ if (cur_sweep == NULL)
+ load_sweep(first);
+ return FALSE;
+}
+
+static gboolean expose(GtkWidget *da, GdkEventExpose *event, gpointer user_data)
+{
+ g_message("radar:expose");
+ Sweep *sweep = cur_sweep;
+
+ /* Draw the rays */
+
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glBindTexture(GL_TEXTURE_2D, sweep_tex);
+ glEnable(GL_TEXTURE_2D);
+ glColor4f(1,1,1,1);
+ glBegin(GL_QUAD_STRIP);
+ for (int ri = 0; ri <= sweep->h.nrays+1; ri++) {
+ /* Do the first sweep twice to complete the last Quad */
+ Ray *ray = sweep->ray[ri % sweep->h.nrays];
+
+ /* right and left looking out from radar */
+ double left = ((ray->h.azimuth - ((double)ray->h.beam_width/2.))*M_PI)/180.0;
+ //double right = ((ray->h.azimuth + ((double)ray->h.beam_width/2.))*M_PI)/180.0;
+
+ double lx = sin(left);
+ double ly = cos(left);
+
+ 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);
+ glVertex3f(lx*near_dist, ly*near_dist, 2.0);
+
+ // far left
+ glTexCoord2f(1.0, (double)ri/sweep->h.nrays);
+ glVertex3f(lx*far_dist, ly*far_dist, 2.0);
+ }
+ //g_print("ri=%d, nr=%d, bw=%f\n", _ri, sweep->h.nrays, sweep->h.beam_width);
+ glEnd();
+ glPopMatrix();
+
+ /* Texture debug */
+ //glBegin(GL_QUADS);
+ //glTexCoord2d( 0., 0.); glVertex3f(-1., 0., 0.); // bot left
+ //glTexCoord2d( 0., 1.); glVertex3f(-1., 1., 0.); // top left
+ //glTexCoord2d( 1., 1.); glVertex3f( 0., 1., 0.); // top right
+ //glTexCoord2d( 1., 0.); glVertex3f( 0., 0., 0.); // bot right
+ //glEnd();
+
+ /* Print the color table */
+ //glDisable(GL_TEXTURE_2D);
+ //glMatrixMode(GL_MODELVIEW ); glPushMatrix(); glLoadIdentity();
+ //glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity();
+ //glBegin(GL_QUADS);
+ //int i;
+ //for (i = 0; i < nred; i++) {
+ // glColor4ub(red[i], green[i], blue[i], get_alpha(i));
+ // glVertex3f(-1.0, (float)((i ) - nred/2)/(nred/2), 0.0); // bot left
+ // glVertex3f(-1.0, (float)((i+1) - nred/2)/(nred/2), 0.0); // top left
+ // glVertex3f(-0.9, (float)((i+1) - nred/2)/(nred/2), 0.0); // top right
+ // glVertex3f(-0.9, (float)((i ) - nred/2)/(nred/2), 0.0); // bot right
+ //}
+ //glEnd();
+ //glMatrixMode(GL_PROJECTION); glPopMatrix();
+ //glMatrixMode(GL_MODELVIEW ); glPopMatrix();
+
+ return FALSE;
+}
+
+gboolean radar_init(GtkDrawingArea *_drawing, GtkNotebook *config)
+{
+ drawing = GTK_WIDGET(_drawing);
+
+ /* Parse hard coded file.. */
+ RSL_read_these_sweeps("all", NULL);
+ //RSL_read_these_sweeps("all", NULL);
+ Radar *radar = RSL_wsr88d_to_radar("/scratch/aweather/data/level2/KNQA_20090501_1925.raw", "KNQA");
+ RSL_load_refl_color_table();
+ RSL_get_color_table(RSL_RED_TABLE, red, &nred);
+ RSL_get_color_table(RSL_GREEN_TABLE, green, &ngreen);
+ RSL_get_color_table(RSL_BLUE_TABLE, blue, &nblue);
+ if (radar->h.nvolumes < 1 || radar->v[0]->h.nsweeps < 1)
+ g_print("No sweeps found\n");
+
+ /* Add configuration tab */
+ GtkWidget *hbox = gtk_hbox_new(TRUE, 0);
+ GtkWidget *button = NULL;
+ int vi = 0, si = 0;
+ for (vi = 0; vi < radar->h.nvolumes; vi++) {
+ Volume *vol = radar->v[vi];
+ if (vol == NULL) continue;
+ GtkWidget *vbox = gtk_vbox_new(TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
+ for (si = 0; si < vol->h.nsweeps; si++) {
+ Sweep *sweep = vol->sweep[si];
+ if (sweep == NULL) continue;
+ char *label = g_strdup_printf("Tilt: %.2f (%s)", sweep->h.elev, vol->h.type_str);
+ button = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(button), label);
+ g_signal_connect_swapped(button, "clicked", G_CALLBACK(load_sweep), sweep);
+ gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0);
+ g_free(label);
+ }
+ }
+ GtkWidget *label = gtk_label_new("Radar");
+ gtk_notebook_append_page(GTK_NOTEBOOK(config), hbox, label);
+
+ /* Set up OpenGL Stuff */
+ g_signal_connect(drawing, "expose-event", G_CALLBACK(expose), NULL);
+ g_signal_connect(drawing, "configure-event", G_CALLBACK(configure), radar->v[0]->sweep[0]);
+
+ return TRUE;
+}