GRASS GIS 8 Programmer's Manual 8.2.1RC1(2022)-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
33static 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 */
47geoline *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 = (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 */
292void 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*/
313int 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
336 Vect_set_open_level(1);
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}
void G_free(void *buf)
Free allocated memory.
Definition: alloc.c:149
#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:112
int G_debug(int level, const char *msg,...)
Print debugging message.
Definition: debug.c:65
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:160
void G_message(const char *msg,...)
Print a message to stderr.
Definition: gis/error.c:90
void G_warning(const char *msg,...)
Print a warning message to stderr.
Definition: gis/error.c:204
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:406
#define RED_MASK
Definition: gsd_prim.c:47
#define BLU_MASK
Definition: gsd_prim.c:49
#define GRN_MASK
Definition: gsd_prim.c:48
int Gv_load_vect_thematic(geovect *gv, struct Colors *colors)
Load styles for geolines based on thematic mapping.
Definition: gv3.c:313
void sub_Vectmem(int minus)
Tracking memory.
Definition: gv3.c:292
geoline * Gv_load_vect(const char *grassname, int *nlines)
Load vector map to memory.
Definition: gv3.c:47
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:23
#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