GRASS GIS 8 Programmer's Manual 8.3.2(2024)-exported
Loading...
Searching...
No Matches
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 =
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 */
298void 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 */
319int 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
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
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
#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