GRASS GIS 8 Programmer's Manual  8.3.2(2024)-exported
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 
64  Vect_set_open_level(2);
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,
87  wind.west, PORT_DOUBLE_MAX, -PORT_DOUBLE_MAX);
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 =
111  (Point3 *)G_calloc(np, sizeof(Point3)); /* G_fatal_error */
112  if (!gln->p3) {
113  return (NULL);
114  }
115 #ifdef TRAK_MEM
116  Tot_mem += (np * sizeof(Point3));
117 #endif
118  }
119  else {
120  gln->dims = 2;
121  gln->p2 =
122  (Point2 *)G_calloc(np, sizeof(Point2)); /* G_fatal_error */
123  if (!gln->p2) {
124  return (NULL);
125  }
126 #ifdef TRAK_MEM
127  Tot_mem += (np * sizeof(Point2));
128 #endif
129  }
130 
131  for (i = 0; i < np; i++) {
132  if (is3d) {
133  gln->p3[i][X] = points->x[i];
134  gln->p3[i][Y] = points->y[i];
135  gln->p3[i][Z] = points->z[i];
136  }
137  else {
138  gln->p2[i][X] = points->x[i];
139  gln->p2[i][Y] = points->y[i];
140  }
141  }
142  /* Calc normal (should be average) */
143  if (is3d) {
144  vect[0][X] = (float)(gln->p3[0][X] - gln->p3[1][X]);
145  vect[0][Y] = (float)(gln->p3[0][Y] - gln->p3[1][Y]);
146  vect[0][Z] = (float)(gln->p3[0][Z] - gln->p3[1][Z]);
147  vect[1][X] = (float)(gln->p3[2][X] - gln->p3[1][X]);
148  vect[1][Y] = (float)(gln->p3[2][Y] - gln->p3[1][Y]);
149  vect[1][Z] = (float)(gln->p3[2][Z] - gln->p3[1][Z]);
150  GS_v3cross(vect[1], vect[0], gln->norm);
151  }
152 
153  gln->cats = NULL;
154  gln->next = (geoline *)G_malloc(sizeof(geoline)); /* G_fatal_error */
155  if (!gln->next) {
156  return (NULL);
157  }
158 
159 #ifdef TRAK_MEM
160  Tot_mem += sizeof(geoline);
161 #endif
162 
163  prev = gln;
164  gln = gln->next;
165  nareas++;
166  }
167  G_debug(3, "%d areas loaded", nareas);
168 
169  /* Read all lines */
170  G_debug(3, "Reading vector lines ...");
171  while (-1 < (type = Vect_read_next_line(&map, points, Cats))) {
172  G_debug(3, "line type = %d", type);
173  if (type & (GV_LINES | GV_FACE)) {
174  if (type & (GV_LINES)) {
175  gln->type = OGSF_LINE;
176  }
177  else {
178  gln->type = OGSF_POLYGON;
179  /* Vect_append_point ( points, points->x[0], points->y[0],
180  * points->z[0] ); */
181  }
182 
183  /* initialize style */
184  gln->highlighted = 0;
185 
186  gln->npts = np = points->n_points;
187  G_debug(3, " np = %d", np);
188 
189  if (is3d) {
190  gln->dims = 3;
191  gln->p3 =
192  (Point3 *)G_calloc(np, sizeof(Point3)); /* G_fatal_error */
193  if (!gln->p3) {
194  return (NULL);
195  }
196 #ifdef TRAK_MEM
197  Tot_mem += (np * sizeof(Point3));
198 #endif
199  }
200  else {
201  gln->dims = 2;
202  gln->p2 =
203  (Point2 *)G_calloc(np, sizeof(Point2)); /* G_fatal_error */
204  if (!gln->p2) {
205  return (NULL);
206  }
207 #ifdef TRAK_MEM
208  Tot_mem += (np * sizeof(Point2));
209 #endif
210  }
211 
212  for (i = 0; i < np; i++) {
213  if (is3d) {
214  gln->p3[i][X] = points->x[i];
215  gln->p3[i][Y] = points->y[i];
216  gln->p3[i][Z] = points->z[i];
217  }
218  else {
219  gln->p2[i][X] = points->x[i];
220  gln->p2[i][Y] = points->y[i];
221  }
222  }
223  /* Calc normal (should be average) */
224  if (is3d && gln->type == OGSF_POLYGON) {
225  vect[0][X] = (float)(gln->p3[0][X] - gln->p3[1][X]);
226  vect[0][Y] = (float)(gln->p3[0][Y] - gln->p3[1][Y]);
227  vect[0][Z] = (float)(gln->p3[0][Z] - gln->p3[1][Z]);
228  vect[1][X] = (float)(gln->p3[2][X] - gln->p3[1][X]);
229  vect[1][Y] = (float)(gln->p3[2][Y] - gln->p3[1][Y]);
230  vect[1][Z] = (float)(gln->p3[2][Z] - gln->p3[1][Z]);
231  GS_v3cross(vect[1], vect[0], gln->norm);
232  G_debug(3, "norm %f %f %f", gln->norm[0], gln->norm[1],
233  gln->norm[2]);
234  }
235 
236  /* Store category info for thematic display */
237  if (Cats->n_cats > 0) {
238  gln->cats = Cats;
239  Cats = Vect_new_cats_struct();
240  }
241  else {
242  gln->cats = NULL;
243  Vect_reset_cats(Cats);
244  }
245 
246  gln->next =
247  (geoline *)G_malloc(sizeof(geoline)); /* G_fatal_error */
248  if (!gln->next) {
249  return (NULL);
250  }
251 #ifdef TRAK_MEM
252  Tot_mem += sizeof(geoline);
253 #endif
254 
255  prev = gln;
256  gln = gln->next;
257  nl++;
258  }
259  }
260  G_debug(3, "%d lines loaded", nl);
261 
262  nl += nareas;
263 
264  prev->next = NULL;
265  G_free(gln);
266 
267 #ifdef TRAK_MEM
268  Tot_mem -= sizeof(geoline);
269 #endif
270 
271  Vect_close(&map);
272 
273  if (!nl) {
274  G_warning(
275  _("No features from vector map <%s> fall within current region"),
276  G_fully_qualified_name(grassname, mapset));
277  return (NULL);
278  }
279  else {
280  G_message(_("Vector map <%s> loaded (%d features)"),
281  G_fully_qualified_name(grassname, mapset), nl);
282  }
283 
284  *nlines = nl;
285 
286 #ifdef TRAK_MEM
287  G_debug(3, "Total vect memory = %d Kbytes", Tot_mem / 1000);
288 #endif
289 
290  return (top);
291 }
292 
293 /*!
294  \brief Tracking memory
295 
296  \param minus mimus number
297  */
298 void sub_Vectmem(int minus)
299 {
300  G_debug(5, "sub_Vectmem(): minus=%d", minus);
301 #ifdef TRAK_MEM
302  {
303  Tot_mem -= minus;
304  }
305 #endif
306 
307  return;
308 }
309 
310 /*!
311  \brief Load styles for geolines based on thematic mapping
312 
313  \param gv pointer to geovect structure
314  \param colors pointer to Colors structure or NULL
315 
316  \return number of features defined by thematic mapping
317  \return -1 on error
318  */
319 int Gv_load_vect_thematic(geovect *gv, struct Colors *colors)
320 {
321  geoline *gvt;
322 
323  struct Map_info Map;
324  struct field_info *Fi;
325 
326  int nvals, cat, nlines, nskipped;
327  int red, blu, grn;
328  const char *str;
329  const char *mapset;
330 
331  dbDriver *driver;
332  dbValue value;
333 
334  if (!gv || !gv->tstyle || !gv->filename)
335  return -1;
336 
337  mapset = G_find_vector2(gv->filename, "");
338  if (!mapset) {
339  G_fatal_error(_("Vector map <%s> not found"), gv->filename);
340  }
341 
342  Vect_set_open_level(1);
343  if (Vect_open_old(&Map, gv->filename, "") == -1) {
344  G_fatal_error(_("Unable to open vector map <%s>"),
345  G_fully_qualified_name(gv->filename, mapset));
346  }
347 
348  Fi = Vect_get_field(&Map, gv->tstyle->layer);
349  if (!Fi) {
350  G_warning(_("Database connection not defined for layer %d"),
351  gv->tstyle->layer);
352  }
353  else {
354  driver = db_start_driver_open_database(Fi->driver, Fi->database);
355  if (!driver)
356  G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
357  Fi->database, Fi->driver);
358  }
359  G_message(_("Loading thematic vector layer <%s>..."),
360  G_fully_qualified_name(gv->filename, mapset));
361  nlines = nskipped = 0;
362  for (gvt = gv->lines; gvt; gvt = gvt->next) {
363  gvt->style = (gvstyle *)G_malloc(sizeof(gvstyle));
364  G_zero(gvt->style, sizeof(gvstyle));
365 
366  /* use default style */
367  gvt->style->color = gv->style->color;
368  gvt->style->symbol = gv->style->symbol;
369  gvt->style->size = gv->style->size;
370  gvt->style->width = gv->style->width;
371 
372  cat = -1;
373  if (gvt->cats)
374  Vect_cat_get(gvt->cats, gv->tstyle->layer, &cat);
375  if (cat < 0) {
376  nskipped++;
377  continue;
378  }
379 
380  /* color */
381  if (colors) {
382  if (!Rast_get_c_color((const CELL *)&cat, &red, &grn, &blu,
383  colors)) {
384  G_warning(_("No color rule defined for category %d"), cat);
385  gvt->style->color = gv->style->color;
386  }
387  gvt->style->color = (red & RED_MASK) +
388  ((int)((grn) << 8) & GRN_MASK) +
389  ((int)((blu) << 16) & BLU_MASK);
390  }
391 
392  if (gv->tstyle->color_column) {
393  nvals = db_select_value(driver, Fi->table, Fi->key, cat,
394  gv->tstyle->color_column, &value);
395  if (nvals < 1)
396  continue;
397  str = db_get_value_string(&value);
398  if (!str)
399  continue;
400  if (G_str_to_color(str, &red, &grn, &blu) != 1) {
401  G_warning(_("Invalid color definition (%s)"), str);
402  gvt->style->color = gv->style->color;
403  }
404  else {
405  gvt->style->color = (red & RED_MASK) +
406  ((int)((grn) << 8) & GRN_MASK) +
407  ((int)((blu) << 16) & BLU_MASK);
408  }
409  }
410 
411  /* width */
412  if (gv->tstyle->width_column) {
413  nvals = db_select_value(driver, Fi->table, Fi->key, cat,
414  gv->tstyle->width_column, &value);
415  if (nvals < 1)
416  continue;
417  gvt->style->width = db_get_value_int(&value);
418  }
419 
420  nlines++;
421  }
422 
423  if (nskipped > 0)
424  G_warning(
425  _("%d features without category. "
426  "Unable to determine color rules for features without category."),
427  nskipped);
428 
429  return nlines;
430 }
void G_free(void *buf)
Free allocated memory.
Definition: alloc.c:150
#define NULL
Definition: ccmath.h:32
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:101
int G_debug(int level, const char *msg,...)
Print debugging message.
Definition: debug.c:66
const struct driver * driver
Definition: driver/init.c:25
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
void G_fatal_error(const char *msg,...)
Print a fatal error message to stderr.
Definition: gis/error.c:159
void G_message(const char *msg,...)
Print a message to stderr.
Definition: gis/error.c:89
void G_warning(const char *msg,...)
Print a warning message to stderr.
Definition: gis/error.c:203
void G_get_set_window(struct Cell_head *window)
Get the current working window (region)
void GS_v3cross(float *v1, float *v2, float *v3)
Get the cross product v3 = v1 cross v2.
Definition: gs_util.c:403
#define RED_MASK
Definition: gsd_prim.c:48
#define BLU_MASK
Definition: gsd_prim.c:50
#define GRN_MASK
Definition: gsd_prim.c:49
geoline * Gv_load_vect(const char *grassname, int *nlines)
Load vector map to memory.
Definition: gv3.c:47
int Gv_load_vect_thematic(geovect *gv, struct Colors *colors)
Load styles for geolines based on thematic mapping.
Definition: gv3.c:319
void sub_Vectmem(int minus)
Tracking memory.
Definition: gv3.c:298
char * G_fully_qualified_name(const char *name, const char *mapset)
Get fully qualified element name.
Definition: nme_in_mps.c:101
Definition: driver.h:21
#define X(j)
#define Y(j)
void G_zero(void *buf, int i)
Zero out a buffer, buf, of length i.
Definition: zero.c:23