/*! \file lib/nviz/nviz.c \brief Nviz library -- Data management Based on visualization/nviz/src/ (C) 2008, 2010 by the GRASS Development Team This program is free software under the GNU General Public License (>=v2). Read the file COPYING that comes with GRASS for details. \author Updated/modified by Martin Landa (Google SoC 2008/2010) */ #include #include #include #include /*! \brief Initialize Nviz data \param data nviz data */ void Nviz_init_data(nv_data * data) { unsigned int i; /* data range */ data->zrange = 0; data->xyrange = 0; /* clip planes, turn off by default */ data->num_cplanes = 0; data->cur_cplane = 0; for (i = 0; i < MAX_CPLANES; i++) { Nviz_new_cplane(data, i); Nviz_off_cplane(data, i); } /* lights */ GS_set_light_reset(1); for (i = 0; i < MAX_LIGHTS - 1; i++) { Nviz_new_light(data); } /* fringe */ data->num_fringes = 0; data->fringe = NULL; /* north arrow */ data->draw_arrow = 0; data->arrow = NULL; /* scale bar*/ data->num_scalebars = 0; data->scalebar = NULL; return; } /*! \brief Free allocated space by nv_data struct \param data nviz data */ void Nviz_destroy_data(nv_data *data) { int i; for (i = 0; data->num_fringes; i++) { G_free(data->fringe[i]); data->fringe[i] = NULL; } data->num_fringes = 0; data->fringe = NULL; if (data->arrow) { G_free(data->arrow); data->arrow = NULL; data->draw_arrow = 0; } for (i = 0; data->num_scalebars; i++) { G_free(data->scalebar[i]); data->scalebar[i] = NULL; } data->num_scalebars = 0; data->scalebar = NULL; } /*! \brief Set background color \param data nviz data \param color color value */ void Nviz_set_bgcolor(nv_data * data, int color) { data->bgcolor = color; return; } /*! \brief Get background color \param data nviz data \return color color value */ int Nviz_get_bgcolor(nv_data * data) { return data->bgcolor; } /*! \brief Get color value from color string (name or RGB triplet) \param color_str color string \return color value */ int Nviz_color_from_str(const char *color_str) { int red, grn, blu; if (G_str_to_color(color_str, &red, &grn, &blu) != 1) { G_warning(_("Invalid color (%s), using \"white\" as default"), color_str); red = grn = blu = 255; } return (red & RED_MASK) + ((int)((grn) << 8) & GRN_MASK) + ((int)((blu) << 16) & BLU_MASK); } /*! Add new fringe \param data nviz data \param id surface id \param color color \param elev fringe elevation \param nw,ne,sw,se 1 (turn on) 0 (turn off) \return pointer to allocated fringe_data structure \return NULL on error */ struct fringe_data *Nviz_new_fringe(nv_data *data, int id, unsigned long color, double elev, int nw, int ne, int sw, int se) { int num; int *surf; struct fringe_data *f; if (!GS_surf_exists(id)) { /* select first surface from the list */ surf = GS_get_surf_list(&num); if (num < 1) return NULL; id = surf[0]; G_free(surf); } f = (struct fringe_data *) G_malloc(sizeof(struct fringe_data)); f->id = id; f->color = color; f->elev = elev; f->where[0] = nw; f->where[1] = ne; f->where[2] = sw; f->where[3] = se; data->fringe = (struct fringe_data **) G_realloc(data->fringe, data->num_fringes + 1 * sizeof(struct fringe_data *)); data->fringe[data->num_fringes++] = f; return f; } /*! Set fringe \param data nviz data \param id surface id \param color color \param elev fringe elevation \param nw,ne,sw,se 1 (turn on) 0 (turn off) \return pointer to allocated fringe_data structure \return NULL on error */ struct fringe_data *Nviz_set_fringe(nv_data *data, int id, unsigned long color, double elev, int nw, int ne, int sw, int se) { int i, num; int *surf; struct fringe_data *f; if (!GS_surf_exists(id)) { /* select first surface from the list */ surf = GS_get_surf_list(&num); if (num < 1) return NULL; id = surf[0]; G_free(surf); } for (i = 0; i < data->num_fringes; i++) { f = data->fringe[i]; if (f->id == id) { f->color = color; f->elev = elev; f->where[0] = nw; f->where[1] = ne; f->where[2] = sw; f->where[3] = se; return f; } } f = Nviz_new_fringe(data, id, color, elev, nw, ne, sw, se); return f; } /*! Draw fringe \param data nviz data */ void Nviz_draw_fringe(nv_data *data) { int i; for (i = 0; i < data->num_fringes; i++) { struct fringe_data *f = data->fringe[i]; GS_draw_fringe(f->id, f->color, f->elev, f->where); } } /*! \brief Sets the North Arrow position and return world coords \param data nviz data \param sx,sy screen coordinates \param size arrow length \param color arrow/text color */ int Nviz_set_arrow(nv_data *data, int sx, int sy, float size, unsigned int color) { int id, pt[2]; int *surf_list, num_surfs; float coords[3]; struct arrow_data *arw; if (GS_num_surfs() > 0) { surf_list = GS_get_surf_list(&num_surfs); id = surf_list[0]; G_free(surf_list); pt[0] = sx; pt[1] = sy; GS_set_Narrow(pt, id, coords); if (data->arrow) { data->arrow->color = color; data->arrow->size = size; data->arrow->where[0] = coords[0]; data->arrow->where[1] = coords[1]; data->arrow->where[2] = coords[2]; } else { arw = (struct arrow_data *) G_malloc(sizeof(struct arrow_data)); arw->color = color; arw->size = size; arw->where[0] = coords[0]; arw->where[1] = coords[1]; arw->where[2] = coords[2]; data->arrow = arw; } return 1; } return 0; } /*! \brief Draws the North Arrow \param data nviz data */ int Nviz_draw_arrow(nv_data *data) { struct arrow_data *arw = data->arrow; GLuint FontBase = 0; /* don't know how to get fontbase*/ data->draw_arrow = 1; gsd_north_arrow(arw->where, arw->size, FontBase, arw->color, arw->color); return 1; } /*! \brief Deletes the North Arrow \param data nviz data */ void Nviz_delete_arrow(nv_data *data) { data->draw_arrow = 0; return; } /*! Add new scalebar \param data nviz data \param bar_id scale bar id \param coords real(?) coordinates \param size scale bar length \param color scalebar/text color \return pointer to allocated scalebar_data structure \return NULL on error */ struct scalebar_data *Nviz_new_scalebar(nv_data *data, int bar_id, float *coords, float size, unsigned int color) { struct scalebar_data *s; s = (struct scalebar_data *) G_malloc(sizeof(struct scalebar_data)); s->id = bar_id; s->color = color; s->size = size; s->where[0] = coords[0]; s->where[1] = coords[1]; s->where[2] = coords[2]; data->scalebar = (struct scalebar_data **) G_realloc(data->scalebar, (data->num_scalebars + 1) * sizeof(struct scalebar_data *)); data->scalebar[data->num_scalebars++] = s; return s; } /*! \brief Sets the scale bar position and return world coords \param data nviz data \param bar_id scale bar id \param sx,sy screen coordinates \param size scale bar length \param color scalebar/text color \return pointer to allocated scalebar_data structure \return NULL when there's no surface */ struct scalebar_data *Nviz_set_scalebar(nv_data *data, int bar_id, int sx, int sy, float size, unsigned int color) { int i, id, pt[2]; int *surf_list, num_surfs; float coords[3]; struct scalebar_data *s; if (GS_num_surfs() > 0) { surf_list = GS_get_surf_list(&num_surfs); id = surf_list[0]; G_free(surf_list); pt[0] = sx; pt[1] = sy; GS_set_Narrow(pt, id, coords); /* the same like arrow */ for (i = 0; i < data->num_scalebars; i++) { if (data->scalebar[i]) { s = data->scalebar[i]; if (s->id == bar_id) { s->color = color; s->size = size; s->where[0] = coords[0]; s->where[1] = coords[1]; s->where[2] = coords[2]; return s; } } } s = Nviz_new_scalebar(data, bar_id, coords, size, color); return s; } return NULL; } /*! \brief Draws the Scale bar \param data nviz data */ void Nviz_draw_scalebar(nv_data *data) { int i; GLuint FontBase = 0; /* don't know how to get fontbase*/ for (i = 0; i < data->num_scalebars; i++) { if (data->scalebar[i]) { struct scalebar_data *s = data->scalebar[i]; gsd_scalebar_v2(s->where, s->size, FontBase, s->color, s->color); } } } /*! \brief Deletes scale bar When scalebar is freed, array then contains NULL, which must be tested during drawing. \param data nviz data */ void Nviz_delete_scalebar(nv_data *data, int bar_id) { if (bar_id < data->num_scalebars && data->scalebar[bar_id] != NULL) { G_free(data->scalebar[bar_id]); data->scalebar[bar_id] = NULL; } }