GRASS 8 Programmer's Manual 8.6.0dev(2026)-4bb960b182
Loading...
Searching...
No Matches
array.c
Go to the documentation of this file.
1/*!
2 \file lib/vector/Vlib/array.c
3
4 \brief Vector library - category array
5
6 Higher level functions for reading/writing/manipulating vectors.
7
8 SPDX-FileCopyrightText: 2001-2009 GRASS Development Team
9 SPDX-License-Identifier: GPL-2.0-or-later
10
11 \author Radim Blazek
12 */
13
14#include <stdlib.h>
15#include <grass/dbmi.h>
16#include <grass/vector.h>
17#include <grass/glocale.h>
18
19/* function prototypes */
20static int cmp(const void *pa, const void *pb);
21static int in_array(int *cats, size_t ncats, int cat);
22
23/*!
24 \brief Create new struct varray and allocate space for given number of items.
25
26 Space allocated is 'size + 1' so that lines are accessed by line id.
27 Array values are set to 0.
28
29 \param size size of array
30
31 \return pointer to new struct varray
32 \return NULL if failed
33 */
35{
36 struct varray *p;
37
38 p = (struct varray *)G_malloc(sizeof(struct varray));
39
40 if (p == NULL)
41 return NULL;
42
43 p->size = size;
44 p->c = (int *)G_calloc(sizeof(char) * size + 1, sizeof(int));
45
46 if (p->c == NULL) {
47 G_free(p);
48 return NULL;
49 }
50
51 return p;
52}
53
54/*!
55 \brief Set values in 'varray' to 'value' from category string.
56
57 If category of object of given type is in <em>cstring</em> (string
58 representing category list like: '1,3,5-7'). <em>type</em> may be
59 either: GV_AREA or: GV_POINT | GV_LINE | GV_BOUNDARY | GV_CENTROID
60
61 Array is not reset to zero before, but old values (if any > 0) are
62 overwritten. Array must be initialised by Vect_new_varray() call.
63
64 \param Map vector map
65 \param field layer number
66 \param cstring pointer to string with categories
67 \param type feature type
68 \param value value to set up
69 \param[out] varray varray structure to modify
70
71 \return number of items set
72 \return -1 on error
73 */
75 const char *cstring, int type, int value,
76 struct varray *varray)
77{
78 int ret;
79 struct cat_list *Clist;
80
81 G_debug(4, "Vect_set_varray_from_cat_string(): cstring = '%s'", cstring);
82
84
86
87 if (ret > 0)
88 G_warning(_("%d errors in category string"), ret);
89
90 G_debug(4, " %d ranges in clist", Clist->n_ranges);
91
93
95
96 return ret;
97}
98
99/*!
100 \brief Set values in 'varray' to 'value' from category list
101
102 If category of object of given type is in <em>clist</em> (category
103 list). <em>type</em> may be either: GV_AREA or: GV_POINT | GV_LINE
104 | GV_BOUNDARY | GV_CENTROID
105
106 Array is not reset to zero before, but old values (if any > 0) are
107 overwritten. Array must be initialised by Vect_new_varray() call.
108
109 \param Map vector map
110 \param field layer number
111 \param clist list of categories
112 \param type feature type
113 \param value value to set up
114 \param[out] varray varray structure to modify
115
116 \return number of items set
117 \return -1 on error
118 */
120 struct cat_list *clist, int type, int value,
121 struct varray *varray)
122{
123 int i, n, centr, cat;
124 int ni = 0; /* number of items set */
125 int ltype; /* line type */
126 struct line_cats *Cats;
127
128 G_debug(4, "Vect_set_varray_from_cat_list(): field = %d", field);
129
130 /* Check type */
131 if ((type & GV_AREA) && (type & (GV_POINTS | GV_LINES))) {
132 G_warning(_("Mixed area and other type requested for vector array"));
133 return 0;
134 }
135
137
138 if (type & GV_AREA) { /* Areas */
140
141 if (n > varray->size) { /* not enough space */
142 G_warning(_("Not enough space in vector array"));
144 return 0;
145 }
146
147 for (i = 1; i <= n; i++) {
149 if (centr <= 0)
150 continue; /* No centroid */
151
153 if (!Vect_cat_get(Cats, field, &cat))
154 continue; /* No such field */
155
156 if (Vect_cat_in_cat_list(cat, clist)) { /* cat is in list */
157 varray->c[i] = value;
158 ni++;
159 }
160 }
161 }
162 else { /* Lines */
164
165 if (n > varray->size) { /* not enough space */
166 G_warning(_("Not enough space in vector array"));
168 return 0;
169 }
170
171 for (i = 1; i <= n; i++) {
173
174 if (!(ltype & type))
175 continue; /* is not specified type */
176
177 if (!Vect_cat_get(Cats, field, &cat))
178 continue; /* No such field */
179
180 if (Vect_cat_in_cat_list(cat, clist)) { /* cat is in list */
181 varray->c[i] = value;
182 ni++;
183 }
184 }
185 }
186
188
189 return ni;
190}
191
192/* compare 2 integers in array */
193static int cmp(const void *pa, const void *pb)
194{
195 int *p1 = (int *)pa;
196 int *p2 = (int *)pb;
197
198 if (*p1 < *p2)
199 return -1;
200 if (*p1 > *p2)
201 return 1;
202 return 0;
203}
204
205/* check if cat is in array */
206static int in_array(int *cats, size_t ncats, int cat)
207{
208 int *p;
209
210 p = (int *)bsearch((void *)&cat, cats, ncats, sizeof(int), cmp);
211
212 if (p == NULL)
213 return 0;
214
215 return 1;
216}
217
218/*!
219 \brief Set values in 'varray' to 'value' from DB (where statement)
220
221 I category of object of given type is in categories selected from
222 DB based on where statement (given without where). <em>type</em>
223 may be either: GV_AREA or: GV_POINT | GV_LINE | GV_BOUNDARY |
224 GV_CENTROID
225
226 Array is not reset to zero before, but old values (if any > 0) are
227 overwritten. Array must be initialised by Vect_new_varray() call.
228
229 \param Map vector map
230 \param field layer number
231 \param where where statement
232 \param type feature type
233 \param value value to set up
234 \param[out] varray varray structure to modify
235
236 \return number of items set
237 \return -1 on error
238 */
239int Vect_set_varray_from_db(struct Map_info *Map, int field, const char *where,
240 int type, int value, struct varray *varray)
241{
242 int i, n, c, centr, *cats;
243 int ncats;
244 int ni = 0; /* number of items set */
245 int ltype; /* line type */
246 struct line_cats *Cats;
247 struct field_info *Fi;
249
250 G_debug(4, "Vect_set_varray_from_db(): field = %d where = '%s'", field,
251 where);
252
253 /* Note: use category index once available */
254
255 /* Check type */
256 if ((type & GV_AREA) && (type & (GV_POINTS | GV_LINES))) {
257 G_warning(_("Mixed area and other type requested for vector array"));
258 return 0;
259 }
260
261 /* Select categories from DB to array */
262 Fi = Vect_get_field(Map, field);
263 if (Fi == NULL) {
264 G_warning(_("Database connection not defined for layer %d"), field);
265 return -1;
266 }
267
268 driver = db_start_driver_open_database(Fi->driver, Fi->database);
269 if (driver == NULL) {
270 G_warning(_("Unable to open database <%s> by driver <%s>"),
271 Fi->database, Fi->driver);
273 return -1;
274 }
275
276 ncats = db_select_int(driver, Fi->table, Fi->key, where, &cats);
277
279
280 if (ncats == -1) {
281 G_warning(
282 _("Unable to select record from table <%s> (key %s, where %s)"),
283 Fi->table, Fi->key, where);
285 return -1;
286 }
289
290 if (type & GV_AREA) { /* Areas */
292
293 /* IMHO varray should be allocated only when it's required AND only as
294 large as required as WHERE will create a small subset of all vector
295 features and thus on large datasets it's waste of memory to allocate
296 it for all features. */
297 if (n > varray->size) { /* not enough space */
298 G_warning(_("Not enough space in vector array"));
300 G_free(cats);
301 return 0;
302 }
303
304 for (i = 1; i <= n; i++) {
306 if (centr <= 0)
307 continue; /* No centroid */
308
310 /*if ( !Vect_cat_get(Cats, field, &cat) ) continue; No such field */
311 for (c = 0; c < Cats->n_cats; c++) {
312 if (Cats->field[c] == field &&
313 in_array(cats, ncats, Cats->cat[c])) {
314 varray->c[i] = value;
315 ni++;
316 break;
317 }
318 }
319
320 /*
321 if ( in_array ( cats, ncats, cat ) ) {
322 varray->c[i] = value;
323 ni++;
324 }
325 */
326 }
327 }
328 else { /* Lines */
330
331 if (n > varray->size) { /* not enough space */
332 G_warning(_("Not enough space in vector array"));
334 G_free(cats);
335 return 0;
336 }
337
338 for (i = 1; i <= n; i++) {
340
341 if (!(ltype & type))
342 continue; /* is not specified type */
343
344 /* if ( !Vect_cat_get(Cats, field, &cat) ) continue; No such field
345 */
346 for (c = 0; c < Cats->n_cats; c++) {
347 if (Cats->field[c] == field &&
348 in_array(cats, ncats, Cats->cat[c])) {
349 varray->c[i] = value;
350 ni++;
351 break;
352 }
353 }
354 /*
355 if ( in_array ( cats, ncats, cat ) ) {
356 varray->c[i] = value;
357 ni++;
358 }
359 */
360 }
361 }
362
363 G_free(cats);
365
366 return ni;
367}
int Vect_set_varray_from_cat_string(struct Map_info *Map, int field, const char *cstring, int type, int value, struct varray *varray)
Set values in 'varray' to 'value' from category string.
Definition array.c:74
struct varray * Vect_new_varray(int size)
Create new struct varray and allocate space for given number of items.
Definition array.c:34
int Vect_set_varray_from_cat_list(struct Map_info *Map, int field, struct cat_list *clist, int type, int value, struct varray *varray)
Set values in 'varray' to 'value' from category list.
Definition array.c:119
int Vect_set_varray_from_db(struct Map_info *Map, int field, const char *where, int type, int value, struct varray *varray)
Set values in 'varray' to 'value' from DB (where statement)
Definition array.c:239
#define NULL
Definition ccmath.h:32
Main header of GRASS DataBase Management Interface.
int db_close_database_shutdown_driver(dbDriver *)
Close driver/database connection.
Definition db.c:58
int db_select_int(dbDriver *, const char *, const char *, const char *, int **)
Select array of ordered integers from table/column.
dbDriver * db_start_driver_open_database(const char *, const char *)
Open driver/database connection.
Definition db.c:25
void G_free(void *)
Free allocated memory.
Definition gis/alloc.c:145
#define G_calloc(m, n)
Definition defs/gis.h:137
void G_warning(const char *,...) __attribute__((format(printf
#define G_malloc(n)
Definition defs/gis.h:136
int G_debug(int, const char *,...) __attribute__((format(printf
plus_t Vect_get_num_lines(struct Map_info *)
Fetch number of features (points, lines, boundaries, centroids) in vector map.
Definition level_two.c:73
plus_t Vect_get_num_areas(struct Map_info *)
Get number of areas in vector map.
Definition level_two.c:85
int Vect_cat_in_cat_list(int, const struct cat_list *)
Check if category number is in list.
int Vect_str_to_cat_list(const char *, struct cat_list *)
Converts string of categories and cat ranges separated by commas to cat_list.
int Vect_cat_get(const struct line_cats *, int, int *)
Get first found category of given field.
void Vect_destroy_cats_struct(struct line_cats *)
Frees all memory associated with line_cats structure, including the struct itself.
struct field_info * Vect_get_field(struct Map_info *, int)
Get information about link to database (by layer number)
Definition field.c:508
int Vect_read_line(struct Map_info *, struct line_pnts *, struct line_cats *, int)
Read vector feature (topological level required)
struct line_cats * Vect_new_cats_struct(void)
Creates and initializes line_cats structure.
struct cat_list * Vect_new_cat_list(void)
Allocate memory for cat_list structure.
void Vect_destroy_field_info(struct field_info *)
Free a struct field_info and all memory associated with it.
Definition field.c:626
void Vect_destroy_cat_list(struct cat_list *)
Frees allocated cat_list memory.
int Vect_get_area_centroid(struct Map_info *, int)
Returns centroid id for given area.
#define GV_LINES
#define GV_POINTS
#define GV_AREA
#define _(str)
Definition glocale.h:10
Vector map info.
Category list.
int field
Category layer (field)
Layer (old: field) information.
char * driver
Name of DB driver ('sqlite', 'dbf', ...)
Feature category info.
int * field
Array of layers (fields)
int * cat
Array of categories.
Vector array.
int * c
Array.
int size
Array size.