GRASS GIS 7 Programmer's Manual  7.9.dev(2021)-e5379bbd7
gv3.c
Go to the documentation of this file.
1 /*!
2  \file lib/ogsf/gv3.c
3 
4  \brief OGSF library - loading vector sets (lower level functions)
5 
6  GRASS OpenGL gsurf OGSF Library
7 
8  (C) 1999-2008, 2011 by the GRASS Development Team
9 
10  This program is free software under the GNU General Public License
11  (>=v2). Read the file COPYING that comes with GRASS for details.
12 
13  \author Bill Brown USACERL (December 1993)
14  \author Updated by Martin Landa <landa.martin gmail.com>
15  (doxygenized in May 2008, thematic mapping in August 2011)
16  */
17 
18 #include <stdlib.h>
19 
20 #include <grass/gis.h>
21 #include <grass/colors.h>
22 #include <grass/raster.h>
23 #include <grass/vector.h>
24 #include <grass/dbmi.h>
25 #include <grass/glocale.h>
26 #include <grass/ogsf.h>
27 
28 /*
29  #define TRAK_MEM
30 */
31 
32 #ifdef TRAK_MEM
33 static int Tot_mem = 0;
34 #endif
35 
36 /*!
37  \brief Load vector map to memory
38 
39  The other alternative may be to load to a tmp file
40 
41  \param grassname vector map name
42  \param[out] number of loaded features
43 
44  \return pointer to geoline struct
45  \return NULL on failure
46  */
47 geoline *Gv_load_vect(const char *grassname, int *nlines)
48 {
49  struct Map_info map;
50  struct line_pnts *points;
51  struct line_cats *Cats = NULL;
52  geoline *top, *gln, *prev;
53  int np, i, n, nareas, nl = 0, area, type, is3d;
54  struct Cell_head wind;
55  float vect[2][3];
56  const char *mapset;
57 
58  mapset = G_find_vector2(grassname, "");
59  if (!mapset) {
60  G_warning(_("Vector map <%s> not found"), grassname);
61  return NULL;
62  }
63 
65  if (Vect_open_old(&map, grassname, "") == -1) {
66  G_warning(_("Unable to open vector map <%s>"),
67  G_fully_qualified_name(grassname, mapset));
68  return NULL;
69  }
70 
71  top = gln = (geoline *) G_malloc(sizeof(geoline)); /* G_fatal_error */
72  if (!top) {
73  return NULL;
74  }
75 
76  prev = top;
77 
78 #ifdef TRAK_MEM
79  Tot_mem += sizeof(geoline);
80 #endif
81 
82  points = Vect_new_line_struct();
83  Cats = Vect_new_cats_struct();
84 
85  G_get_set_window(&wind);
86  Vect_set_constraint_region(&map, wind.north, wind.south, wind.east,
88 
89  is3d = Vect_is_3d(&map);
90 
91  /* Read areas */
92  n = Vect_get_num_areas(&map);
93  nareas = 0;
94  G_debug(3, "Reading vector areas (nareas = %d)", n);
95  for (area = 1; area <= n; area++) {
96  G_debug(3, " area %d", area);
97  Vect_get_area_points(&map, area, points);
98  if (points->n_points < 3)
99  continue;
100 
101  /* initialize style */
102  gln->highlighted = 0;
103 
104  gln->type = OGSF_POLYGON;
105  gln->npts = np = points->n_points;
106  G_debug(3, " np = %d", np);
107 
108  if (is3d) {
109  gln->dims = 3;
110  gln->p3 = (Point3 *) G_calloc(np, sizeof(Point3)); /* G_fatal_error */
111  if (!gln->p3) {
112  return (NULL);
113  }
114 #ifdef TRAK_MEM
115  Tot_mem += (np * sizeof(Point3));
116 #endif
117  }
118  else {
119  gln->dims = 2;
120  gln->p2 = (Point2 *) G_calloc(np, sizeof(Point2)); /* G_fatal_error */
121  if (!gln->p2) {
122  return (NULL);
123  }
124 #ifdef TRAK_MEM
125  Tot_mem += (np * sizeof(Point2));
126 #endif
127  }
128 
129  for (i = 0; i < np; i++) {
130  if (is3d) {
131  gln->p3[i][X] = points->x[i];
132  gln->p3[i][Y] = points->y[i];
133  gln->p3[i][Z] = points->z[i];
134  }
135  else {
136  gln->p2[i][X] = points->x[i];
137  gln->p2[i][Y] = points->y[i];
138  }
139  }
140  /* Calc normal (should be average) */
141  if (is3d) {
142  vect[0][X] = (float)(gln->p3[0][X] - gln->p3[1][X]);
143  vect[0][Y] = (float)(gln->p3[0][Y] - gln->p3[1][Y]);
144  vect[0][Z] = (float)(gln->p3[0][Z] - gln->p3[1][Z]);
145  vect[1][X] = (float)(gln->p3[2][X] - gln->p3[1][X]);
146  vect[1][Y] = (float)(gln->p3[2][Y] - gln->p3[1][Y]);
147  vect[1][Z] = (float)(gln->p3[2][Z] - gln->p3[1][Z]);
148  GS_v3cross(vect[1], vect[0], gln->norm);
149 
150  }
151 
152  gln->cats = NULL;
153  gln->next = (geoline *) G_malloc(sizeof(geoline)); /* G_fatal_error */
154  if (!gln->next) {
155  return (NULL);
156  }
157 
158 #ifdef TRAK_MEM
159  Tot_mem += sizeof(geoline);
160 #endif
161 
162  prev = gln;
163  gln = gln->next;
164  nareas++;
165  }
166  G_debug(3, "%d areas loaded", nareas);
167 
168  /* Read all lines */
169  G_debug(3, "Reading vector lines ...");
170  while (-1 < (type = Vect_read_next_line(&map, points, Cats))) {
171  G_debug(3, "line type = %d", type);
172  if (type & (GV_LINES | GV_FACE)) {
173  if (type & (GV_LINES)) {
174  gln->type = OGSF_LINE;
175  }
176  else {
177  gln->type = OGSF_POLYGON;
178  /* Vect_append_point ( points, points->x[0], points->y[0], points->z[0] ); */
179  }
180 
181  /* initialize style */
182  gln->highlighted = 0;
183 
184  gln->npts = np = points->n_points;
185  G_debug(3, " np = %d", np);
186 
187  if (is3d) {
188  gln->dims = 3;
189  gln->p3 = (Point3 *) G_calloc(np, sizeof(Point3)); /* G_fatal_error */
190  if (!gln->p3) {
191  return (NULL);
192  }
193 #ifdef TRAK_MEM
194  Tot_mem += (np * sizeof(Point3));
195 #endif
196  }
197  else {
198  gln->dims = 2;
199  gln->p2 = (Point2 *) G_calloc(np, sizeof(Point2)); /* G_fatal_error */
200  if (!gln->p2) {
201  return (NULL);
202  }
203 #ifdef TRAK_MEM
204  Tot_mem += (np * sizeof(Point2));
205 #endif
206  }
207 
208  for (i = 0; i < np; i++) {
209  if (is3d) {
210  gln->p3[i][X] = points->x[i];
211  gln->p3[i][Y] = points->y[i];
212  gln->p3[i][Z] = points->z[i];
213  }
214  else {
215  gln->p2[i][X] = points->x[i];
216  gln->p2[i][Y] = points->y[i];
217  }
218  }
219  /* Calc normal (should be average) */
220  if (is3d && gln->type == OGSF_POLYGON) {
221  vect[0][X] = (float)(gln->p3[0][X] - gln->p3[1][X]);
222  vect[0][Y] = (float)(gln->p3[0][Y] - gln->p3[1][Y]);
223  vect[0][Z] = (float)(gln->p3[0][Z] - gln->p3[1][Z]);
224  vect[1][X] = (float)(gln->p3[2][X] - gln->p3[1][X]);
225  vect[1][Y] = (float)(gln->p3[2][Y] - gln->p3[1][Y]);
226  vect[1][Z] = (float)(gln->p3[2][Z] - gln->p3[1][Z]);
227  GS_v3cross(vect[1], vect[0], gln->norm);
228  G_debug(3, "norm %f %f %f", gln->norm[0], gln->norm[1],
229  gln->norm[2]);
230  }
231 
232  /* Store category info for thematic display */
233  if (Cats->n_cats > 0) {
234  gln->cats = Cats;
235  Cats = Vect_new_cats_struct();
236  }
237  else {
238  gln->cats = NULL;
239  Vect_reset_cats(Cats);
240  }
241 
242  gln->next = (geoline *) G_malloc(sizeof(geoline)); /* G_fatal_error */
243  if (!gln->next) {
244  return (NULL);
245  }
246 #ifdef TRAK_MEM
247  Tot_mem += sizeof(geoline);
248 #endif
249 
250  prev = gln;
251  gln = gln->next;
252  nl++;
253  }
254  }
255  G_debug(3, "%d lines loaded", nl);
256 
257  nl += nareas;
258 
259  prev->next = NULL;
260  G_free(gln);
261 
262 #ifdef TRAK_MEM
263  Tot_mem -= sizeof(geoline);
264 #endif
265 
266  Vect_close(&map);
267 
268  if (!nl) {
269  G_warning(_("No features from vector map <%s> fall within current region"),
270  G_fully_qualified_name(grassname, mapset));
271  return (NULL);
272  }
273  else {
274  G_message(_("Vector map <%s> loaded (%d features)"),
275  G_fully_qualified_name(grassname, mapset), nl);
276  }
277 
278  *nlines = nl;
279 
280 #ifdef TRAK_MEM
281  G_debug(3, "Total vect memory = %d Kbytes", Tot_mem / 1000);
282 #endif
283 
284  return (top);
285 }
286 
287 /*!
288  \brief Tracking memory
289 
290  \param minus mimus number
291  */
292 void sub_Vectmem(int minus)
293 {
294  G_debug(5, "sub_Vectmem(): minus=%d", minus);
295 #ifdef TRAK_MEM
296  {
297  Tot_mem -= minus;
298  }
299 #endif
300 
301  return;
302 }
303 
304 /*!
305  \brief Load styles for geolines based on thematic mapping
306 
307  \param gv pointer to geovect structure
308  \param colors pointer to Colors structure or NULL
309 
310  \return number of features defined by thematic mapping
311  \return -1 on error
312 */
313 int Gv_load_vect_thematic(geovect *gv, struct Colors *colors)
314 {
315  geoline *gvt;
316 
317  struct Map_info Map;
318  struct field_info *Fi;
319 
320  int nvals, cat, nlines, nskipped;
321  int red, blu, grn;
322  const char *str;
323  const char *mapset;
324 
325  dbDriver *driver;
326  dbValue value;
327 
328  if(!gv || !gv->tstyle || !gv->filename)
329  return -1;
330 
331  mapset = G_find_vector2(gv->filename, "");
332  if (!mapset) {
333  G_fatal_error(_("Vector map <%s> not found"), gv->filename);
334  }
335 
337  if (Vect_open_old(&Map, gv->filename, "") == -1) {
338  G_fatal_error(_("Unable to open vector map <%s>"),
339  G_fully_qualified_name(gv->filename, mapset));
340  }
341 
342  Fi = Vect_get_field(&Map, gv->tstyle->layer);
343  if (!Fi) {
344  G_warning(_("Database connection not defined for layer %d"),
345  gv->tstyle->layer);
346  }
347  else {
348  driver = db_start_driver_open_database(Fi->driver, Fi->database);
349  if (!driver)
350  G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
351  Fi->database, Fi->driver);
352  }
353  G_message(_("Loading thematic vector layer <%s>..."),
354  G_fully_qualified_name(gv->filename, mapset));
355  nlines = nskipped = 0;
356  for(gvt = gv->lines; gvt; gvt = gvt->next) {
357  gvt->style = (gvstyle *) G_malloc(sizeof(gvstyle));
358  G_zero(gvt->style, sizeof(gvstyle));
359 
360  /* use default style */
361  gvt->style->color = gv->style->color;
362  gvt->style->symbol = gv->style->symbol;
363  gvt->style->size = gv->style->size;
364  gvt->style->width = gv->style->width;
365 
366  cat = -1;
367  if (gvt->cats)
368  Vect_cat_get(gvt->cats, gv->tstyle->layer, &cat);
369  if (cat < 0) {
370  nskipped++;
371  continue;
372  }
373 
374  /* color */
375  if (colors) {
376  if (!Rast_get_c_color((const CELL *) &cat, &red, &grn, &blu, colors)) {
377  G_warning(_("No color rule defined for category %d"), cat);
378  gvt->style->color = gv->style->color;
379  }
380  gvt->style->color = (red & RED_MASK) + ((int)((grn) << 8) & GRN_MASK) +
381  ((int)((blu) << 16) & BLU_MASK);
382  }
383 
384  if (gv->tstyle->color_column) {
385  nvals = db_select_value(driver, Fi->table, Fi->key, cat, gv->tstyle->color_column, &value);
386  if (nvals < 1)
387  continue;
388  str = db_get_value_string(&value);
389  if (!str)
390  continue;
391  if (G_str_to_color(str, &red, &grn, &blu) != 1) {
392  G_warning(_("Invalid color definition (%s)"),
393  str);
394  gvt->style->color = gv->style->color;
395  }
396  else {
397  gvt->style->color = (red & RED_MASK) + ((int)((grn) << 8) & GRN_MASK) +
398  ((int)((blu) << 16) & BLU_MASK);
399  }
400  }
401 
402  /* width */
403  if (gv->tstyle->width_column) {
404  nvals = db_select_value(driver, Fi->table, Fi->key, cat, gv->tstyle->width_column, &value);
405  if (nvals < 1)
406  continue;
407  gvt->style->width = db_get_value_int(&value);
408  }
409 
410  nlines++;
411  }
412 
413  if (nskipped > 0)
414  G_warning(_("%d features without category. "
415  "Unable to determine color rules for features without category."),
416  nskipped);
417 
418  return nlines;
419 }
#define G_malloc(n)
Definition: defs/gis.h:112
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
#define BLU_MASK
Definition: ogsf.h:198
const char * G_find_vector2(const char *, const char *)
Find a vector map (look but don&#39;t touch)
Definition: find_vect.c:62
float size
Definition: ogsf.h:290
#define RED_MASK
Definition: ogsf.h:196
2D/3D raster map header (used also for region)
Definition: gis.h:412
signed char highlighted
Definition: ogsf.h:324
double west
Extent coordinates (west)
Definition: gis.h:464
int n_points
Number of points.
Definition: dig_structs.h:1692
int G_str_to_color(const char *, int *, int *, int *)
Parse color string and set red,green,blue.
Definition: color_str.c:112
gvstyle_thematic * tstyle
Definition: ogsf.h:346
char * table
Name of DB table.
Definition: dig_structs.h:155
int color
Definition: ogsf.h:288
gvstyle * style
Definition: ogsf.h:347
void G_free(void *)
Free allocated memory.
Definition: gis/alloc.c:149
int db_get_value_int(dbValue *)
Get integer value.
Definition: value.c:38
float Point2[2]
Definition: ogsf.h:202
struct g_line * next
Definition: ogsf.h:326
dbDriver * db_start_driver_open_database(const char *, const char *)
Open driver/database connection.
Definition: db.c:28
int Vect_close(struct Map_info *)
Close vector map.
float Point3[3]
Definition: ogsf.h:201
geoline * lines
Definition: ogsf.h:340
#define NULL
Definition: ccmath.h:32
gvstyle * style
Definition: ogsf.h:323
geoline * Gv_load_vect(const char *grassname, int *nlines)
Load vector map to memory.
Definition: gv3.c:47
#define OGSF_POLYGON
Definition: ogsf.h:194
struct field_info * Vect_get_field(const struct Map_info *, int)
Get information about link to database (by layer number)
Definition: field.c:506
char * database
Definition: dig_structs.h:151
#define G_calloc(m, n)
Definition: defs/gis.h:113
int Vect_set_constraint_region(struct Map_info *, double, double, double, double, double, double)
Set constraint region.
Definition: constraint.c:47
struct g_line geoline
Feature category info.
Definition: dig_structs.h:1702
void GS_v3cross(float *, float *, float *)
Get the cross product v3 = v1 cross v2.
Definition: gs_util.c:406
double top
Extent coordinates (top) - 3D data.
Definition: gis.h:466
char * color_column
Definition: ogsf.h:307
Layer (old: field) information.
Definition: dig_structs.h:134
void G_message(const char *,...) __attribute__((format(printf
double * x
Array of X coordinates.
Definition: dig_structs.h:1680
Feature geometry info - coordinates.
Definition: dig_structs.h:1675
double north
Extent coordinates (north)
Definition: gis.h:458
#define GV_FACE
Definition: dig_defines.h:186
int width
Definition: ogsf.h:291
char * G_fully_qualified_name(const char *, const char *)
Get fully qualified element name.
Definition: nme_in_mps.c:101
int db_select_value(dbDriver *, const char *, const char *, int, const char *, dbValue *)
Select one (first) value from table/column for key/id.
struct line_pnts * Vect_new_line_struct(void)
Creates and initializes a line_pnts structure.
Definition: line.c:45
double south
Extent coordinates (south)
Definition: gis.h:460
Definition: ogsf.h:330
int n_cats
Number of categories attached to element.
Definition: dig_structs.h:1715
int type
Definition: ogsf.h:316
float norm[3]
Definition: ogsf.h:317
char * width_column
Definition: ogsf.h:310
const struct driver * driver
Definition: driver/init.c:25
plus_t Vect_get_num_areas(const struct Map_info *)
Get number of areas in vector map.
Definition: level_two.c:86
void G_get_set_window(struct Cell_head *)
Get the current working window (region)
int npts
Definition: ogsf.h:318
int Gv_load_vect_thematic(geovect *gv, struct Colors *colors)
Load styles for geolines based on thematic mapping.
Definition: gv3.c:313
int Vect_reset_cats(struct line_cats *)
Reset category structure to make sure cats structure is clean to be re-used.
#define Z
Definition: ogsf.h:139
int Vect_set_open_level(int)
Predetermine level at which a vector map will be opened for reading.
Definition: gis.h:665
Vector map info.
Definition: dig_structs.h:1259
#define PORT_DOUBLE_MAX
Limits for portable types.
Definition: dig_defines.h:66
#define Y
Definition: ogsf.h:138
#define OGSF_LINE
Definition: ogsf.h:193
const char * db_get_value_string(dbValue *)
Get string value.
Definition: value.c:92
double * y
Array of Y coordinates.
Definition: dig_structs.h:1684
char * driver
Name of DB driver (&#39;sqlite&#39;, &#39;dbf&#39;, ...)
Definition: dig_structs.h:147
int Rast_get_c_color(const CELL *, int *, int *, int *, struct Colors *)
Gets color from raster map (CELL)
Definition: color_get.c:68
int Vect_is_3d(const struct Map_info *)
Check if vector map is 3D.
struct line_cats * Vect_new_cats_struct(void)
Creates and initializes line_cats structure.
void G_zero(void *, int)
Zero out a buffer, buf, of length i.
Definition: gis/zero.c:23
int dims
Definition: ogsf.h:318
void G_warning(const char *,...) __attribute__((format(printf
int CELL
Definition: gis.h:602
Point3 * p3
Definition: ogsf.h:319
double east
Extent coordinates (east)
Definition: gis.h:462
struct line_cats * cats
Definition: ogsf.h:322
double * z
Array of Z coordinates.
Definition: dig_structs.h:1688
void sub_Vectmem(int minus)
Tracking memory.
Definition: gv3.c:292
#define _(str)
Definition: glocale.h:10
int Vect_open_old(struct Map_info *, const char *, const char *)
Open existing vector map for reading.
#define X
Definition: ogsf.h:137
#define GV_LINES
Definition: dig_defines.h:192
int symbol
Definition: ogsf.h:289
char * filename
Definition: ogsf.h:337
int Vect_read_next_line(const struct Map_info *, struct line_pnts *, struct line_cats *)
Read next vector feature.
int Vect_get_area_points(const struct Map_info *, int, struct line_pnts *)
Returns polygon array of points (outer ring) of given area.
int G_debug(int, const char *,...) __attribute__((format(printf
Definition: ogsf.h:314
Point2 * p2
Definition: ogsf.h:320
int Vect_cat_get(const struct line_cats *, int, int *)
Get first found category of given field.
#define GRN_MASK
Definition: ogsf.h:197
char * key
Name of key column (usually &#39;cat&#39;)
Definition: dig_structs.h:159