GRASS GIS 8 Programmer's Manual  8.5.0dev(2024)-36359e2344
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 =
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 
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 {
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 }
#define NULL
Definition: ccmath.h:32
int G_str_to_color(const char *, int *, int *, int *)
Parse color string and set red,green,blue.
Definition: color_str.c:101
const char * db_get_value_string(dbValue *)
Get string value.
Definition: value.c:92
int db_select_value(dbDriver *, const char *, const char *, int, const char *, dbValue *)
Select one (first) value from table/column for key/id.
dbDriver * db_start_driver_open_database(const char *, const char *)
Open driver/database connection.
Definition: db.c:28
int db_get_value_int(dbValue *)
Get integer value.
Definition: value.c:38
const char * G_find_vector2(const char *, const char *)
Find a vector map (look but don't touch)
Definition: find_vect.c:62
void G_zero(void *, int)
Zero out a buffer, buf, of length i.
Definition: gis/zero.c:23
void G_free(void *)
Free allocated memory.
Definition: gis/alloc.c:150
#define G_calloc(m, n)
Definition: defs/gis.h:95
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
void G_get_set_window(struct Cell_head *)
Get the current working window (region)
#define G_malloc(n)
Definition: defs/gis.h:94
char * G_fully_qualified_name(const char *, const char *)
Get fully qualified element name.
Definition: nme_in_mps.c:101
void G_message(const char *,...) __attribute__((format(printf
int G_debug(int, const char *,...) __attribute__((format(printf
void GS_v3cross(float *, float *, float *)
Get the cross product v3 = v1 cross v2.
Definition: gs_util.c:403
int Rast_get_c_color(const CELL *, int *, int *, int *, struct Colors *)
Gets color from raster map (CELL)
Definition: color_get.c:67
plus_t Vect_get_num_areas(struct Map_info *)
Get number of areas in vector map.
Definition: level_two.c:87
int Vect_reset_cats(struct line_cats *)
Reset category structure to make sure cats structure is clean to be re-used.
int Vect_cat_get(const struct line_cats *, int, int *)
Get first found category of given field.
int Vect_set_constraint_region(struct Map_info *, double, double, double, double, double, double)
Set constraint region.
Definition: constraint.c:48
int Vect_get_area_points(struct Map_info *, int, struct line_pnts *)
Returns polygon array of points (outer ring) of given area.
int Vect_close(struct Map_info *)
Close vector map.
int Vect_open_old(struct Map_info *, const char *, const char *)
Open existing vector map for reading.
struct field_info * Vect_get_field(struct Map_info *, int)
Get information about link to database (by layer number)
Definition: field.c:515
struct line_pnts * Vect_new_line_struct(void)
Creates and initializes a line_pnts structure.
Definition: line.c:45
int Vect_read_next_line(struct Map_info *, struct line_pnts *, struct line_cats *)
Read next vector feature.
struct line_cats * Vect_new_cats_struct(void)
Creates and initializes line_cats structure.
int Vect_set_open_level(int)
Predetermine level at which a vector map will be opened for reading.
int Vect_is_3d(struct Map_info *)
Check if vector map is 3D.
#define GV_LINES
Definition: dig_defines.h:193
#define GV_FACE
Definition: dig_defines.h:187
#define PORT_DOUBLE_MAX
Limits for portable types.
Definition: dig_defines.h:66
const struct driver * driver
Definition: driver/init.c:25
int CELL
Definition: gis.h:628
#define _(str)
Definition: glocale.h:10
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
struct g_line geoline
#define RED_MASK
Definition: ogsf.h:200
#define X
Definition: ogsf.h:140
#define BLU_MASK
Definition: ogsf.h:202
float Point2[2]
Definition: ogsf.h:206
float Point3[3]
Definition: ogsf.h:205
#define Z
Definition: ogsf.h:142
#define GRN_MASK
Definition: ogsf.h:201
#define Y
Definition: ogsf.h:141
#define OGSF_LINE
Definition: ogsf.h:197
#define OGSF_POLYGON
Definition: ogsf.h:198
2D/3D raster map header (used also for region)
Definition: gis.h:440
double north
Extent coordinates (north)
Definition: gis.h:486
double east
Extent coordinates (east)
Definition: gis.h:490
double top
Extent coordinates (top) - 3D data.
Definition: gis.h:494
double south
Extent coordinates (south)
Definition: gis.h:488
double west
Extent coordinates (west)
Definition: gis.h:492
Definition: gis.h:686
Vector map info.
Definition: dig_structs.h:1243
Definition: driver.h:21
Layer (old: field) information.
Definition: dig_structs.h:131
char * table
Name of DB table.
Definition: dig_structs.h:151
char * driver
Name of DB driver ('sqlite', 'dbf', ...)
Definition: dig_structs.h:143
char * database
Definition: dig_structs.h:147
char * key
Name of key column (usually 'cat')
Definition: dig_structs.h:155
Definition: ogsf.h:312
signed char highlighted
Definition: ogsf.h:322
float norm[3]
Definition: ogsf.h:314
Point3 * p3
Definition: ogsf.h:316
struct g_line * next
Definition: ogsf.h:324
int npts
Definition: ogsf.h:315
gvstyle * style
Definition: ogsf.h:321
int type
Definition: ogsf.h:313
Point2 * p2
Definition: ogsf.h:317
int dims
Definition: ogsf.h:315
struct line_cats * cats
Definition: ogsf.h:319
char * color_column
Definition: ogsf.h:305
char * width_column
Definition: ogsf.h:308
int color
Definition: ogsf.h:286
int symbol
Definition: ogsf.h:287
float size
Definition: ogsf.h:288
int width
Definition: ogsf.h:289
Definition: ogsf.h:328
char * filename
Definition: ogsf.h:334
gvstyle_thematic * tstyle
Definition: ogsf.h:343
gvstyle * style
Definition: ogsf.h:344
geoline * lines
Definition: ogsf.h:337
Feature category info.
Definition: dig_structs.h:1677
int n_cats
Number of categories attached to element.
Definition: dig_structs.h:1689
Feature geometry info - coordinates.
Definition: dig_structs.h:1651
double * y
Array of Y coordinates.
Definition: dig_structs.h:1659
double * x
Array of X coordinates.
Definition: dig_structs.h:1655
int n_points
Number of points.
Definition: dig_structs.h:1667
double * z
Array of Z coordinates.
Definition: dig_structs.h:1663