X-Git-Url: http://pileus.org/git/?p=aweather;a=blobdiff_plain;f=src%2Fplugins%2Flevel2.c;h=66eb172a4c4431743c4b7fc265dd6764f5adee49;hp=dec504a21ade699753a490e560b0af7582511dd8;hb=30d0024157f9db987ce11254e9448b5c8667331f;hpb=80644a86249dab69441a11cbb41b2599b546c373 diff --git a/src/plugins/level2.c b/src/plugins/level2.c index dec504a..66eb172 100644 --- a/src/plugins/level2.c +++ b/src/plugins/level2.c @@ -24,6 +24,8 @@ #include "level2.h" +#define ISO_MIN 30 +#define ISO_MAX 80 /************************** * Data loading functions * @@ -46,18 +48,22 @@ static void _bscan_sweep(Sweep *sweep, AWeatherColormap *colormap, 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) { + float value = ray->h.f(ray->range[bi]); + + /* Check for bad values */ + if (value == BADVAL || value == RFVAL || value == APFLAG || + value == NOTFOUND_H || value == NOTFOUND_V || value == NOECHO) { buf[buf_i+3] = 0x00; // transparent + continue; } + + /* Copy color to buffer */ + guint8 *data = colormap_get(colormap, value); + buf[buf_i+0] = data[0]; + buf[buf_i+1] = data[1]; + buf[buf_i+2] = data[2]; + buf[buf_i+3] = data[3]*0.75; // TESTING } } @@ -68,20 +74,20 @@ static void _bscan_sweep(Sweep *sweep, AWeatherColormap *colormap, } /* Load a sweep into an OpenGL texture */ -static void _load_sweep_gl(AWeatherLevel2 *self) +static void _load_sweep_gl(AWeatherLevel2 *level2) { g_debug("AWeatherLevel2: _load_sweep_gl"); guint8 *data; gint width, height; - _bscan_sweep(self->sweep, self->sweep_colors, &data, &width, &height); + _bscan_sweep(level2->sweep, level2->sweep_colors, &data, &width, &height); gint tex_width = pow(2, ceil(log(width )/log(2))); gint tex_height = pow(2, ceil(log(height)/log(2))); - self->sweep_coords[0] = (double)width / tex_width; - self->sweep_coords[1] = (double)height / tex_height; + level2->sweep_coords[0] = (double)width / tex_width; + level2->sweep_coords[1] = (double)height / tex_height; - if (!self->sweep_tex) - glGenTextures(1, &self->sweep_tex); - glBindTexture(GL_TEXTURE_2D, self->sweep_tex); + if (!level2->sweep_tex) + glGenTextures(1, &level2->sweep_tex); + glBindTexture(GL_TEXTURE_2D, level2->sweep_tex); glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tex_width, tex_height, 0, @@ -126,18 +132,85 @@ static gboolean _decompress_radar(const gchar *file, const gchar *raw) return TRUE; } +/* Load the radar into a Grits Volume */ +static void _cart_to_sphere(VolCoord *out, VolCoord *in) +{ + gdouble angle = in->x; + gdouble dist = in->y; + gdouble tilt = in->z; + gdouble lx = sin(angle); + gdouble ly = cos(angle); + gdouble lz = sin(tilt); + //out->x = (ly*dist)/20000; + //out->y = (lz*dist)/10000-0.5; + //out->z = (lx*dist)/20000-1.5; + out->x = (lx*dist); + out->y = (ly*dist); + out->z = (lz*dist); +} + +static VolGrid *_load_grid(Volume *vol) +{ + g_debug("AWeatherLevel2: _load_grid"); + + Sweep *sweep = vol->sweep[0]; + Ray *ray = sweep->ray[0]; + gint nsweeps = vol->h.nsweeps; + gint nrays = sweep->h.nrays/(1/sweep->h.beam_width)+1; + gint nbins = ray->h.nbins /(1000/ray->h.gate_size); + nbins = MIN(nbins, 150); + + VolGrid *grid = vol_grid_new(nrays, nbins, nsweeps); + + gint rs, bs, val; + gint si=0, ri=0, bi=0; + for (si = 0; si < nsweeps; si++) { + sweep = vol->sweep[si]; + rs = 1.0/sweep->h.beam_width; + for (ri = 0; ri < nrays; ri++) { + /* TODO: missing rays, pick ri based on azmith */ + ray = sweep->ray[(ri*rs) % sweep->h.nrays]; + bs = 1000/ray->h.gate_size; + for (bi = 0; bi < nbins; bi++) { + if (bi*bs >= ray->h.nbins) + break; + val = ray->h.f(ray->range[bi*bs]); + if (val == BADVAL || val == RFVAL || + val == APFLAG || val == NOECHO || + val == NOTFOUND_H || val == NOTFOUND_V || + val > 80) + val = 0; + VolPoint *point = vol_grid_get(grid, ri, bi, si); + point->value = val; + point->c.x = deg2rad(ray->h.azimuth); + point->c.y = bi*bs*ray->h.gate_size + ray->h.range_bin1; + point->c.z = deg2rad(ray->h.elev); + } } } + + for (si = 0; si < nsweeps; si++) + for (ri = 0; ri < nrays; ri++) + for (bi = 0; bi < nbins; bi++) { + VolPoint *point = vol_grid_get(grid, ri, bi, si); + if (point->c.y == 0) + point->value = nan(""); + else + _cart_to_sphere(&point->c, &point->c); + } + return grid; +} + /********************* * Drawing functions * *********************/ -void aweather_level2_draw(GritsObject *_self, GritsOpenGL *opengl) +void aweather_level2_draw(GritsObject *_level2, GritsOpenGL *opengl) { - AWeatherLevel2 *self = AWEATHER_LEVEL2(_self); - if (!self->sweep || !self->sweep_tex) + AWeatherLevel2 *level2 = AWEATHER_LEVEL2(_level2); + if (!level2->sweep || !level2->sweep_tex) return; /* Draw wsr88d */ - Sweep *sweep = self->sweep; + Sweep *sweep = level2->sweep; glDisable(GL_ALPHA_TEST); glDisable(GL_CULL_FACE); glDisable(GL_LIGHTING); @@ -147,9 +220,9 @@ void aweather_level2_draw(GritsObject *_self, GritsOpenGL *opengl) glColor4f(1,1,1,1); /* Draw the rays */ - gdouble xscale = self->sweep_coords[0]; - gdouble yscale = self->sweep_coords[1]; - glBindTexture(GL_TEXTURE_2D, self->sweep_tex); + gdouble xscale = level2->sweep_coords[0]; + gdouble yscale = level2->sweep_coords[1]; + glBindTexture(GL_TEXTURE_2D, level2->sweep_tex); glBegin(GL_TRIANGLE_STRIP); for (int ri = 0; ri <= sweep->h.nrays; ri++) { Ray *ray = NULL; @@ -166,8 +239,8 @@ void aweather_level2_draw(GritsObject *_self, GritsOpenGL *opengl) 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; + double near_dist = ray->h.range_bin1 - ((double)ray->h.gate_size/2.); + double far_dist = near_dist + (double)ray->h.nbins*ray->h.gate_size; /* (find middle of bin) / scale for opengl */ // near left @@ -192,64 +265,101 @@ void aweather_level2_draw(GritsObject *_self, GritsOpenGL *opengl) //glEnd(); } +void aweather_level2_hide(GritsObject *_level2, gboolean hidden) +{ + AWeatherLevel2 *level2 = AWEATHER_LEVEL2(_level2); + if (level2->volume) + grits_object_hide(GRITS_OBJECT(level2->volume), hidden); +} + /*********** * Methods * ***********/ -static gboolean _set_sweep_cb(gpointer _self) +static gboolean _set_sweep_cb(gpointer _level2) { g_debug("AWeatherLevel2: _set_sweep_cb"); - AWeatherLevel2 *self = _self; - _load_sweep_gl(self); - gtk_widget_queue_draw(GTK_WIDGET(self->viewer)); - g_object_unref(self); + AWeatherLevel2 *level2 = _level2; + _load_sweep_gl(level2); + grits_object_queue_draw(_level2); + g_object_unref(level2); return FALSE; } -void aweather_level2_set_sweep(AWeatherLevel2 *self, +void aweather_level2_set_sweep(AWeatherLevel2 *level2, int type, float elev) { g_debug("AWeatherLevel2: set_sweep - %d %f", type, elev); /* Find sweep */ - Volume *volume = RSL_get_volume(self->radar, type); + Volume *volume = RSL_get_volume(level2->radar, type); if (!volume) return; - self->sweep = RSL_get_closest_sweep(volume, elev, 90); - if (!self->sweep) return; + level2->sweep = RSL_get_closest_sweep(volume, elev, 90); + if (!level2->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; + level2->sweep_colors = NULL; + for (int i = 0; level2->colormap[i].file; i++) + if (level2->colormap[i].type == type) + level2->sweep_colors = &level2->colormap[i]; + if (!level2->sweep_colors) { + g_warning("AWeatherLevel2: set_sweep - missing colormap[%d]", type); + level2->sweep_colors = &level2->colormap[0]; + } /* Load data */ - g_object_ref(self); - g_idle_add(_set_sweep_cb, self); + g_object_ref(level2); + g_idle_add(_set_sweep_cb, level2); } -AWeatherLevel2 *aweather_level2_new(GritsViewer *viewer, - AWeatherColormap *colormap, Radar *radar) +void aweather_level2_set_iso(AWeatherLevel2 *level2, gfloat level) +{ + g_debug("AWeatherLevel2: set_iso - %f", level); + + if (!level2->volume) { + g_debug("AWeatherLevel2: set_iso - creating new volume"); + Volume *rvol = RSL_get_volume(level2->radar, DZ_INDEX); + VolGrid *grid = _load_grid(rvol); + GritsVolume *vol = grits_volume_new(grid); + vol->proj = GRITS_VOLUME_CARTESIAN; + vol->disp = GRITS_VOLUME_SURFACE; + GRITS_OBJECT(vol)->center = GRITS_OBJECT(level2)->center; + grits_viewer_add(GRITS_OBJECT(level2)->viewer, + GRITS_OBJECT(vol), GRITS_LEVEL_WORLD, TRUE); + level2->volume = vol; + } + if (ISO_MIN < level && level < ISO_MAX) { + guint8 *data = colormap_get(&level2->colormap[0], level); + level2->volume->color[0] = data[0]; + level2->volume->color[1] = data[1]; + level2->volume->color[2] = data[2]; + level2->volume->color[3] = data[3]; + grits_volume_set_level(level2->volume, level); + grits_object_hide(GRITS_OBJECT(level2->volume), FALSE); + } else { + grits_object_hide(GRITS_OBJECT(level2->volume), TRUE); + } +} + +AWeatherLevel2 *aweather_level2_new(Radar *radar, AWeatherColormap *colormap) { g_debug("AWeatherLevel2: new - %s", radar->h.radar_name); - 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); + RSL_sort_radar(radar); + AWeatherLevel2 *level2 = g_object_new(AWEATHER_TYPE_LEVEL2, NULL); + level2->radar = radar; + level2->colormap = colormap; + aweather_level2_set_sweep(level2, DZ_INDEX, 0); GritsPoint center; Radar_header *h = &radar->h; center.lat = (double)h->latd + (double)h->latm/60 + (double)h->lats/(60*60); center.lon = (double)h->lond + (double)h->lonm/60 + (double)h->lons/(60*60); center.elev = h->height; - GRITS_OBJECT(self)->center = center; - return self; + GRITS_OBJECT(level2)->center = center; + return level2; } -AWeatherLevel2 *aweather_level2_new_from_file(GritsViewer *viewer, - AWeatherColormap *colormap, - const gchar *file, const gchar *site) +AWeatherLevel2 *aweather_level2_new_from_file(const gchar *file, const gchar *site, + AWeatherColormap *colormap) { g_debug("AWeatherLevel2: new_from_file %s %s", site, file); @@ -276,16 +386,25 @@ AWeatherLevel2 *aweather_level2_new_from_file(GritsViewer *viewer, if (!radar) return NULL; - return aweather_level2_new(viewer, colormaps, radar); + return aweather_level2_new(radar, colormaps); } static void _on_sweep_clicked(GtkRadioButton *button, gpointer _level2) { AWeatherLevel2 *level2 = _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; + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button))) { + 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); + //level2->colormap = level2->sweep_colors; + } +} + +static void _on_iso_changed(GtkRange *range, gpointer _level2) +{ + AWeatherLevel2 *level2 = _level2; + gfloat level = gtk_range_get_value(range); + aweather_level2_set_iso(level2, level); } GtkWidget *aweather_level2_get_config(AWeatherLevel2 *level2) @@ -293,7 +412,7 @@ GtkWidget *aweather_level2_get_config(AWeatherLevel2 *level2) Radar *radar = level2->radar; g_debug("AWeatherLevel2: get_config - %p, %p", level2, radar); /* Clear existing items */ - gdouble elev; + gfloat elev; guint rows = 1, cols = 1, cur_cols; gchar row_label_str[64], col_label_str[64], button_str[64]; GtkWidget *row_label, *col_label, *button = NULL, *elev_box = NULL; @@ -309,6 +428,7 @@ GtkWidget *aweather_level2_get_config(AWeatherLevel2 *level2) 0,1, 0,1, GTK_FILL,GTK_FILL, 5,0); g_free(date_str); + /* Add sweeps */ for (guint vi = 0; vi < radar->h.nvolumes; vi++) { Volume *vol = radar->v[vi]; if (vol == NULL) continue; @@ -362,6 +482,25 @@ GtkWidget *aweather_level2_get_config(AWeatherLevel2 *level2) g_signal_connect(button, "clicked", G_CALLBACK(_on_sweep_clicked), level2); } } + + /* Add Iso-surface volume */ + g_object_get(table, "n-columns", &cols, NULL); + row_label = gtk_label_new("Isosurface:"); + gtk_label_set_use_markup(GTK_LABEL(row_label), TRUE); + gtk_misc_set_alignment(GTK_MISC(row_label), 1, 0.5); + gtk_table_attach(GTK_TABLE(table), row_label, + 0,1, rows,rows+1, GTK_FILL,GTK_FILL, 5,0); + GtkWidget *scale = gtk_hscale_new_with_range(ISO_MIN, ISO_MAX, 0.5); + gtk_widget_set_size_request(scale, -1, 26); + gtk_scale_set_value_pos(GTK_SCALE(scale), GTK_POS_LEFT); + gtk_range_set_inverted(GTK_RANGE(scale), TRUE); + gtk_range_set_value(GTK_RANGE(scale), ISO_MAX); + g_signal_connect(scale, "value-changed", G_CALLBACK(_on_iso_changed), level2); + gtk_table_attach(GTK_TABLE(table), scale, + 1,cols+1, rows,rows+1, GTK_FILL|GTK_EXPAND,GTK_FILL, 0,0); + /* Shove all the buttons to the left, but keep the slider expanded */ + gtk_table_attach(GTK_TABLE(table), gtk_label_new(""), + cols,cols+1, 0,1, GTK_FILL|GTK_EXPAND,GTK_FILL, 0,0); return table; } @@ -369,20 +508,33 @@ GtkWidget *aweather_level2_get_config(AWeatherLevel2 *level2) * GObject code * ****************/ G_DEFINE_TYPE(AWeatherLevel2, aweather_level2, GRITS_TYPE_OBJECT); -static void aweather_level2_init(AWeatherLevel2 *self) +static void aweather_level2_init(AWeatherLevel2 *level2) { } -static void aweather_level2_finalize(GObject *_self) +static void aweather_level2_dispose(GObject *_level2) +{ + AWeatherLevel2 *level2 = AWEATHER_LEVEL2(_level2); + g_debug("AWeatherLevel2: dispose - %p", _level2); + if (level2->volume) { + grits_viewer_remove(GRITS_OBJECT(level2->volume)->viewer, + GRITS_OBJECT(level2->volume)); + level2->volume = NULL; + } + G_OBJECT_CLASS(aweather_level2_parent_class)->dispose(_level2); +} +static void aweather_level2_finalize(GObject *_level2) { - AWeatherLevel2 *self = AWEATHER_LEVEL2(_self); - g_debug("AWeatherLevel2: finalize - %p", _self); - RSL_free_radar(self->radar); - if (self->sweep_tex) - glDeleteTextures(1, &self->sweep_tex); - G_OBJECT_CLASS(aweather_level2_parent_class)->finalize(_self); + AWeatherLevel2 *level2 = AWEATHER_LEVEL2(_level2); + g_debug("AWeatherLevel2: finalize - %p", _level2); + RSL_free_radar(level2->radar); + if (level2->sweep_tex) + glDeleteTextures(1, &level2->sweep_tex); + G_OBJECT_CLASS(aweather_level2_parent_class)->finalize(_level2); } static void aweather_level2_class_init(AWeatherLevel2Class *klass) { + G_OBJECT_CLASS(klass)->dispose = aweather_level2_dispose; G_OBJECT_CLASS(klass)->finalize = aweather_level2_finalize; - GRITS_OBJECT_CLASS(klass)->draw = aweather_level2_draw; + GRITS_OBJECT_CLASS(klass)->draw = aweather_level2_draw; + GRITS_OBJECT_CLASS(klass)->hide = aweather_level2_hide; }