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