Loading...
Searching...
No Matches
gv3.c
Go to the documentation of this file.
/*!
\file lib/ogsf/gv3.c
\brief OGSF library - loading vector sets (lower level functions)
GRASS OpenGL gsurf OGSF Library
(C) 1999-2008, 2011 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 Bill Brown USACERL (December 1993)
\author Updated by Martin Landa <landa.martin gmail.com>
(doxygenized in May 2008, thematic mapping in August 2011)
*/
#include <stdlib.h>
#include <grass/gis.h>
#include <grass/colors.h>
#include <grass/raster.h>
#include <grass/vector.h>
#include <grass/dbmi.h>
#include <grass/glocale.h>
#include <grass/ogsf.h>
/*
#define TRAK_MEM
*/
#ifdef TRAK_MEM
static int Tot_mem = 0;
#endif
/*!
\brief Load vector map to memory
The other alternative may be to load to a tmp file
\param grassname vector map name
\param[out] nlines number of loaded features
\return pointer to geoline struct
\return NULL on failure
*/
geoline *Gv_load_vect(const char *grassname, int *nlines)
{
struct Map_info map;
struct line_pnts *points;
struct line_cats *Cats = NULL;
geoline *top, *gln, *prev;
int np, i, n, nareas, nl = 0, area, type, is3d;
struct Cell_head wind;
float vect[2][3];
const char *mapset;
mapset = G_find_vector2(grassname, "");
if (!mapset) {
G_warning(_("Vector map <%s> not found"), grassname);
return NULL;
}
Vect_set_open_level(2);
if (Vect_open_old(&map, grassname, "") == -1) {
G_warning(_("Unable to open vector map <%s>"),
G_fully_qualified_name(grassname, mapset));
return NULL;
}
top = gln = (geoline *)G_malloc(sizeof(geoline)); /* G_fatal_error */
if (!top) {
return NULL;
}
prev = top;
#ifdef TRAK_MEM
Tot_mem += sizeof(geoline);
#endif
points = Vect_new_line_struct();
Cats = Vect_new_cats_struct();
G_get_set_window(&wind);
Vect_set_constraint_region(&map, wind.north, wind.south, wind.east,
wind.west, PORT_DOUBLE_MAX, -PORT_DOUBLE_MAX);
is3d = Vect_is_3d(&map);
/* Read areas */
n = Vect_get_num_areas(&map);
nareas = 0;
G_debug(3, "Reading vector areas (nareas = %d)", n);
for (area = 1; area <= n; area++) {
G_debug(3, " area %d", area);
Vect_get_area_points(&map, area, points);
if (points->n_points < 3)
continue;
/* initialize style */
gln->highlighted = 0;
gln->type = OGSF_POLYGON;
gln->npts = np = points->n_points;
G_debug(3, " np = %d", np);
if (is3d) {
gln->dims = 3;
gln->p3 =
(Point3 *)G_calloc(np, sizeof(Point3)); /* G_fatal_error */
if (!gln->p3) {
return (NULL);
}
#ifdef TRAK_MEM
Tot_mem += (np * sizeof(Point3));
#endif
}
else {
gln->dims = 2;
gln->p2 =
(Point2 *)G_calloc(np, sizeof(Point2)); /* G_fatal_error */
if (!gln->p2) {
return (NULL);
}
#ifdef TRAK_MEM
Tot_mem += (np * sizeof(Point2));
#endif
}
for (i = 0; i < np; i++) {
if (is3d) {
gln->p3[i][X] = points->x[i];
gln->p3[i][Y] = points->y[i];
gln->p3[i][Z] = points->z[i];
}
else {
gln->p2[i][X] = points->x[i];
gln->p2[i][Y] = points->y[i];
}
}
/* Calc normal (should be average) */
if (is3d) {
vect[0][X] = (float)(gln->p3[0][X] - gln->p3[1][X]);
vect[0][Y] = (float)(gln->p3[0][Y] - gln->p3[1][Y]);
vect[0][Z] = (float)(gln->p3[0][Z] - gln->p3[1][Z]);
vect[1][X] = (float)(gln->p3[2][X] - gln->p3[1][X]);
vect[1][Y] = (float)(gln->p3[2][Y] - gln->p3[1][Y]);
vect[1][Z] = (float)(gln->p3[2][Z] - gln->p3[1][Z]);
GS_v3cross(vect[1], vect[0], gln->norm);
}
gln->cats = NULL;
gln->next = (geoline *)G_malloc(sizeof(geoline)); /* G_fatal_error */
if (!gln->next) {
return (NULL);
}
#ifdef TRAK_MEM
Tot_mem += sizeof(geoline);
#endif
prev = gln;
gln = gln->next;
nareas++;
}
G_debug(3, "%d areas loaded", nareas);
/* Read all lines */
G_debug(3, "Reading vector lines ...");
while (-1 < (type = Vect_read_next_line(&map, points, Cats))) {
G_debug(3, "line type = %d", type);
if (type & (GV_LINES | GV_FACE)) {
if (type & (GV_LINES)) {
gln->type = OGSF_LINE;
}
else {
gln->type = OGSF_POLYGON;
/* Vect_append_point ( points, points->x[0], points->y[0],
* points->z[0] ); */
}
/* initialize style */
gln->highlighted = 0;
gln->npts = np = points->n_points;
G_debug(3, " np = %d", np);
if (is3d) {
gln->dims = 3;
gln->p3 =
(Point3 *)G_calloc(np, sizeof(Point3)); /* G_fatal_error */
if (!gln->p3) {
return (NULL);
}
#ifdef TRAK_MEM
Tot_mem += (np * sizeof(Point3));
#endif
}
else {
gln->dims = 2;
gln->p2 =
(Point2 *)G_calloc(np, sizeof(Point2)); /* G_fatal_error */
if (!gln->p2) {
return (NULL);
}
#ifdef TRAK_MEM
Tot_mem += (np * sizeof(Point2));
#endif
}
for (i = 0; i < np; i++) {
if (is3d) {
gln->p3[i][X] = points->x[i];
gln->p3[i][Y] = points->y[i];
gln->p3[i][Z] = points->z[i];
}
else {
gln->p2[i][X] = points->x[i];
gln->p2[i][Y] = points->y[i];
}
}
/* Calc normal (should be average) */
if (is3d && gln->type == OGSF_POLYGON) {
vect[0][X] = (float)(gln->p3[0][X] - gln->p3[1][X]);
vect[0][Y] = (float)(gln->p3[0][Y] - gln->p3[1][Y]);
vect[0][Z] = (float)(gln->p3[0][Z] - gln->p3[1][Z]);
vect[1][X] = (float)(gln->p3[2][X] - gln->p3[1][X]);
vect[1][Y] = (float)(gln->p3[2][Y] - gln->p3[1][Y]);
vect[1][Z] = (float)(gln->p3[2][Z] - gln->p3[1][Z]);
GS_v3cross(vect[1], vect[0], gln->norm);
G_debug(3, "norm %f %f %f", gln->norm[0], gln->norm[1],
gln->norm[2]);
}
/* Store category info for thematic display */
if (Cats->n_cats > 0) {
gln->cats = Cats;
Cats = Vect_new_cats_struct();
}
else {
gln->cats = NULL;
Vect_reset_cats(Cats);
}
gln->next =
(geoline *)G_malloc(sizeof(geoline)); /* G_fatal_error */
if (!gln->next) {
return (NULL);
}
#ifdef TRAK_MEM
Tot_mem += sizeof(geoline);
#endif
prev = gln;
gln = gln->next;
nl++;
}
}
G_debug(3, "%d lines loaded", nl);
nl += nareas;
prev->next = NULL;
G_free(gln);
#ifdef TRAK_MEM
Tot_mem -= sizeof(geoline);
#endif
Vect_close(&map);
if (!nl) {
G_warning(
_("No features from vector map <%s> fall within current region"),
G_fully_qualified_name(grassname, mapset));
return (NULL);
}
else {
G_message(_("Vector map <%s> loaded (%d features)"),
G_fully_qualified_name(grassname, mapset), nl);
}
*nlines = nl;
#ifdef TRAK_MEM
G_debug(3, "Total vect memory = %d Kbytes", Tot_mem / 1000);
#endif
return (top);
}
/*!
\brief Tracking memory
\param minus mimus number
*/
void sub_Vectmem(int minus)
{
G_debug(5, "sub_Vectmem(): minus=%d", minus);
#ifdef TRAK_MEM
{
Tot_mem -= minus;
}
#endif
return;
}
/*!
\brief Load styles for geolines based on thematic mapping
\param gv pointer to geovect structure
\param colors pointer to Colors structure or NULL
\return number of features defined by thematic mapping
\return -1 on error
*/
int Gv_load_vect_thematic(geovect *gv, struct Colors *colors)
{
geoline *gvt;
struct Map_info Map;
struct field_info *Fi;
int nvals, cat, nlines, nskipped;
int red, blu, grn;
const char *str;
const char *mapset;
dbDriver *driver;
dbValue value;
if (!gv || !gv->tstyle || !gv->filename)
return -1;
mapset = G_find_vector2(gv->filename, "");
if (!mapset) {
G_fatal_error(_("Vector map <%s> not found"), gv->filename);
}
Vect_set_open_level(1);
if (Vect_open_old(&Map, gv->filename, "") == -1) {
G_fatal_error(_("Unable to open vector map <%s>"),
G_fully_qualified_name(gv->filename, mapset));
}
Fi = Vect_get_field(&Map, gv->tstyle->layer);
if (!Fi) {
G_warning(_("Database connection not defined for layer %d"),
gv->tstyle->layer);
}
else {
driver = db_start_driver_open_database(Fi->driver, Fi->database);
if (!driver)
G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
Fi->database, Fi->driver);
}
G_message(_("Loading thematic vector layer <%s>..."),
G_fully_qualified_name(gv->filename, mapset));
nlines = nskipped = 0;
for (gvt = gv->lines; gvt; gvt = gvt->next) {
gvt->style = (gvstyle *)G_malloc(sizeof(gvstyle));
G_zero(gvt->style, sizeof(gvstyle));
/* use default style */
gvt->style->color = gv->style->color;
gvt->style->symbol = gv->style->symbol;
gvt->style->size = gv->style->size;
gvt->style->width = gv->style->width;
cat = -1;
if (gvt->cats)
Vect_cat_get(gvt->cats, gv->tstyle->layer, &cat);
if (cat < 0) {
nskipped++;
continue;
}
/* color */
if (colors) {
if (!Rast_get_c_color((const CELL *)&cat, &red, &grn, &blu,
colors)) {
G_warning(_("No color rule defined for category %d"), cat);
gvt->style->color = gv->style->color;
}
gvt->style->color = (red & RED_MASK) +
((int)((grn) << 8) & GRN_MASK) +
((int)((blu) << 16) & BLU_MASK);
}
if (gv->tstyle->color_column) {
nvals = db_select_value(driver, Fi->table, Fi->key, cat,
gv->tstyle->color_column, &value);
if (nvals < 1)
continue;
str = db_get_value_string(&value);
if (!str)
continue;
if (G_str_to_color(str, &red, &grn, &blu) != 1) {
G_warning(_("Invalid color definition (%s)"), str);
gvt->style->color = gv->style->color;
}
else {
gvt->style->color = (red & RED_MASK) +
((int)((grn) << 8) & GRN_MASK) +
((int)((blu) << 16) & BLU_MASK);
}
}
/* width */
if (gv->tstyle->width_column) {
nvals = db_select_value(driver, Fi->table, Fi->key, cat,
gv->tstyle->width_column, &value);
if (nvals < 1)
continue;
gvt->style->width = db_get_value_int(&value);
}
nlines++;
}
if (nskipped > 0)
G_warning(
_("%d features without category. "
"Unable to determine color rules for features without category."),
nskipped);
return nlines;
}
G_free
void G_free(void *buf)
Free allocated memory.
Definition alloc.c:147
NULL
#define NULL
Definition ccmath.h:32
G_str_to_color
int G_str_to_color(const char *str, int *red, int *grn, int *blu)
Parse color string and set red,green,blue.
Definition color_str.c:103
G_debug
int G_debug(int level, const char *msg,...)
Print debugging message.
Definition debug.c:66
G_find_vector2
const char * G_find_vector2(const char *name, const char *mapset)
Find a vector map (look but don't touch).
Definition find_vect.c:62
G_fatal_error
void G_fatal_error(const char *msg,...)
Print a fatal error message to stderr.
Definition gis/error.c:159
G_message
void G_message(const char *msg,...)
Print a message to stderr.
Definition gis/error.c:89
G_warning
void G_warning(const char *msg,...)
Print a warning message to stderr.
Definition gis/error.c:203
G_get_set_window
void G_get_set_window(struct Cell_head *window)
Get the current working window (region).
Definition gis/set_window.c:35
GS_v3cross
void GS_v3cross(float *v1, float *v2, float *v3)
Get the cross product v3 = v1 cross v2.
Definition gs_util.c:403
RED_MASK
#define RED_MASK
Definition gsd_prim.c:48
BLU_MASK
#define BLU_MASK
Definition gsd_prim.c:50
GRN_MASK
#define GRN_MASK
Definition gsd_prim.c:49
Gv_load_vect_thematic
int Gv_load_vect_thematic(geovect *gv, struct Colors *colors)
Load styles for geolines based on thematic mapping.
Definition gv3.c:319
sub_Vectmem
void sub_Vectmem(int minus)
Tracking memory.
Definition gv3.c:298
Gv_load_vect
geoline * Gv_load_vect(const char *grassname, int *nlines)
Load vector map to memory.
Definition gv3.c:47
G_fully_qualified_name
char * G_fully_qualified_name(const char *name, const char *mapset)
Get fully qualified element name.
Definition nme_in_mps.c:101
driver
Definition driver.h:27
X
#define X(j)
Y
#define Y(j)
G_zero
void G_zero(void *buf, int i)
Zero out a buffer, buf, of length i.
Definition zero.c:23