GRASS 8 Programmer's Manual  8.5.0dev(2025)-26b3fb6cca
vector/Vlib/cats.c
Go to the documentation of this file.
1 /*!
2  * \file lib/vector/Vlib/cats.c
3  *
4  * \brief Vector library - Category management
5  *
6  * Higher level functions for reading/writing/manipulating vectors.
7  *
8  * (C) 2001-2012 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 Original author CERL, probably Dave Gerdes or Mike Higgins
14  * \author Update to GRASS 5.7 Radim Blazek and David D. Gray.
15  * \author Various updates by Martin Landa <landa.martin gmail.com>
16  * \author Various updates by Markus Metz
17  */
18 
19 #include <stdlib.h>
20 #include <string.h>
21 #include <grass/vector.h>
22 #include <grass/dbmi.h>
23 #include <grass/glocale.h>
24 
25 static int cmp(const void *pa, const void *pb);
26 static struct line_cats *Vect__new_cats_struct(void);
27 
28 /*!
29  \brief Creates and initializes line_cats structure.
30 
31  This structure is used for reading and writing vector cats. The
32  library routines handle all memory allocation.
33 
34  To free allocated memory call Vect_destroy_cats_struct().
35 
36  \return struct line_cats *
37  \return NULL on error
38  */
40 {
41  struct line_cats *p;
42 
43  if (NULL == (p = Vect__new_cats_struct()))
44  G_fatal_error(_("Vect_new_cats_struct(): Out of memory"));
45 
46  return p;
47 }
48 
49 /*!
50  \brief Creates and initializes line_cats structure (lower level fn)
51 
52  This structure is used for reading and writing vector cats. The
53  library routines handle all memory allocation.
54 
55  \return struct line_cats *
56  */
57 static struct line_cats *Vect__new_cats_struct(void)
58 {
59  struct line_cats *p;
60 
61  p = (struct line_cats *)G_malloc(sizeof(struct line_cats));
62 
63  /* n_cats MUST be initialized to zero */
64  if (p)
65  p->n_cats = 0;
66 
67  if (p)
68  p->alloc_cats = 0;
69 
70  return p;
71 }
72 
73 /*!
74  \brief Frees all memory associated with line_cats structure,
75  including the struct itself.
76 
77  \param p line_cats structure
78  */
80 {
81  if (p) { /* probably a moot test */
82  if (p->n_cats) {
83  G_free((void *)p->field);
84  G_free((void *)p->cat);
85  }
86  G_free((void *)p);
87  }
88 }
89 
90 /*!
91  \brief Add new field/cat to category structure if doesn't exist
92  yet.
93 
94  \param[in,out] Cats line_cats structure
95  \param[in] field layer number
96  \param[in] cat category number
97 
98  \return number of categories
99  \return 0 if no space for new category in structure, n_cats would be >
100  GV_NCATS_MAX \return -1 on out of memory \return -2 if field out of range: 1
101  - GV_FIELD_MAX or cat out of range: 1 - GV_CAT_MAX
102  */
103 int Vect_cat_set(struct line_cats *Cats, int field, int cat)
104 {
105  register int n;
106 
107  /* check input values */
108  /* compiler may warn:
109  * comparison is always 0 due to limited range of data type
110  * but remember that limit is set to portable data type length
111  * and machine native size may be longer */
112  /*
113  if (field < 1 || field > GV_FIELD_MAX || cat < 0 || cat > GV_CAT_MAX)
114  return (-2);
115  */
116 
117  /* go through old cats and find if field/category exists */
118  for (n = 0; n < Cats->n_cats; n++) {
119  if (Cats->field[n] == field && Cats->cat[n] == cat)
120  return (1);
121  }
122 
123  /* field was not found so we shall append new cat */
124  /* test if space exist */
125  if (n >= GV_NCATS_MAX) {
127  _("Too many categories (%d), unable to set cat %d (layer %d)"),
128  Cats->n_cats, cat, field);
129  }
130 
131  if (Cats->n_cats == Cats->alloc_cats) {
132  if (0 > dig_alloc_cats(Cats, Cats->n_cats + 100))
133  return (-1);
134  }
135 
136  n = Cats->n_cats;
137  Cats->field[n] = field;
138  Cats->cat[n] = cat;
139  Cats->n_cats++;
140  return (1);
141 }
142 
143 /*!
144  \brief Get first found category of given field.
145 
146  <em>cat</em> is set to first category found or -1 if field was not
147  found
148 
149  \param Cats pointer line_cats structure
150  \param field layer number
151  \param[out] cat pointer to variable where cat will be written (can be NULL)
152 
153  \return number of found cats for given field (first reported)
154  \return 0 layer does not exist
155  */
156 int Vect_cat_get(const struct line_cats *Cats, int field, int *cat)
157 {
158  int n, ret;
159 
160  /* field was not found */
161  ret = 0;
162  if (cat)
163  *cat = -1;
164 
165  /* check input value */
166  if (field < 1 || field > GV_FIELD_MAX)
167  return (0);
168 
169  /* go through cats and find if field exist */
170  for (n = 0; n < Cats->n_cats; n++) {
171  if (Cats->field[n] == field) {
172  if (cat && ret == 0) {
173  *cat = Cats->cat[n];
174  }
175  ret++;
176  }
177  }
178 
179  return ret;
180 }
181 
182 /*!
183  \brief Get list of categories of given field.
184 
185  \param Cats line_cats structure
186  \param field layer number
187  \param[out] cats pointer to list where cats will be written
188 
189  \return number of found categories
190  \return -1 on invalid field
191  */
192 int Vect_field_cat_get(const struct line_cats *Cats, int field,
193  struct ilist *cats)
194 {
195  int n;
196 
197  /* reset list of categories */
198  Vect_reset_list(cats);
199 
200  /* check input value */
201  if (field < 1 || field > GV_FIELD_MAX)
202  return -1;
203 
204  /* go through cats and find if field exist */
205  for (n = 0; n < Cats->n_cats; n++) {
206  if (Cats->field[n] == field)
207  Vect_list_append(cats, Cats->cat[n]);
208  }
209 
210  return cats->n_values;
211 }
212 
213 /*!
214  \brief Delete all categories of given layer
215 
216  \param[in,out] Cats line_cats structure
217  \param field layer number
218 
219  \return number of categories deleted
220  \return 0 layer does not exist
221  */
222 int Vect_cat_del(struct line_cats *Cats, int field)
223 {
224  int n, m, found;
225 
226  /* check input value */
227  /*
228  if (field < 1 || field > GV_FIELD_MAX)
229  return (0);
230  */
231 
232  /* go through cats and find if field exist */
233  m = 0;
234  for (n = 0; n < Cats->n_cats; n++) {
235  if (Cats->field[n] != field) {
236  Cats->field[m] = Cats->field[n];
237  Cats->cat[m] = Cats->cat[n];
238  m++;
239  }
240  }
241  found = Cats->n_cats - m;
242  Cats->n_cats = m;
243 
244  return (found);
245 }
246 
247 /*!
248  \brief Delete field/cat from line_cats structure
249 
250  \param[in,out] Cats line_cats structure
251  \param field layer number
252  \param cat category to be deleted or -1 to delete all cats of given field
253 
254  \return number of categories deleted
255  \return 0 field/category number does not exist
256  */
257 int Vect_field_cat_del(struct line_cats *Cats, int field, int cat)
258 {
259  register int n, m, found;
260 
261  /* check input value */
262  /*
263  if (field < 1 || field > GV_FIELD_MAX)
264  return (0);
265  */
266 
267  if (cat == -1)
268  return Vect_cat_del(Cats, field);
269 
270  /* go through cats and find if field exist */
271  m = 0;
272  for (n = 0; n < Cats->n_cats; n++) {
273  if (Cats->field[n] != field || Cats->cat[n] != cat) {
274  Cats->field[m] = Cats->field[n];
275  Cats->cat[m] = Cats->cat[n];
276  m++;
277  }
278  }
279  found = Cats->n_cats - m;
280  Cats->n_cats = m;
281 
282  return (found);
283 }
284 
285 /*!
286  \brief Reset category structure to make sure cats structure is clean to be
287  re-used.
288 
289  I.e. it has no cats associated with it. Cats must have
290  previously been created with Vect_new_cats_struct()
291 
292  \param[out] Cats line_cats structure
293 
294  \return 0
295  */
296 int Vect_reset_cats(struct line_cats *Cats)
297 {
298  Cats->n_cats = 0;
299 
300  return 0;
301 }
302 
303 /*!
304  \brief Allocate memory for cat_list structure.
305 
306  \return pointer to allocated structure
307  \return NULL if out of memory
308  */
310 {
311  struct cat_list *p;
312 
313  p = (struct cat_list *)G_malloc(sizeof(struct cat_list));
314 
315  /* n_ranges MUST be initialized to zero */
316  if (p)
317  G_zero(p, sizeof(struct cat_list));
318 
319  return p;
320 }
321 
322 /*!
323  \brief Frees allocated cat_list memory.
324 
325  \param p pointer to line_cats structure
326  */
328 {
329  if (p) { /* probably a moot test */
330  if (p->n_ranges) {
331  G_free((void *)p->min);
332  G_free((void *)p->max);
333  }
334  G_free((void *)p);
335  }
336 }
337 
338 /*!
339  \brief Converts string of categories and cat ranges separated by commas to
340  cat_list.
341 
342  \par Examples of string:
343  \verbatim
344  5,6,7
345  3-9
346  2,3,5-9,20\endverbatim
347 
348  \par Example:
349  \code
350  ...
351  str = "2,3,5-9,20"
352  cat_list = Vect_new_cat_list()
353 
354  Vect_str_to_cat_list(str, cat_list)
355  \endcode
356  \verbatim
357  cat_list->field = 0
358  cat_list->n_ranges = 4
359  cat_list->min = {2, 3, 5, 20}
360  cat_list->max = {2, 3, 9, 20}
361  \endverbatim
362 
363  \param str category list as a string
364  \param[in,out] list pointer to cat_list structure
365 
366  \return number of errors in ranges
367  */
368 int Vect_str_to_cat_list(const char *str, struct cat_list *list)
369 {
370  int i, nr, l, err = 0;
371  const char *s, *e;
372  char buf[100];
373  int min, max;
374 
375  G_debug(3, "Vect_str_to_cat_list(): str = %s", str);
376 
377  list->n_ranges = 0;
378  l = strlen(str);
379 
380  /* find number of ranges */
381  nr = 1; /* one range */
382  for (i = 0; i < l; i++)
383  if (str[i] == ',')
384  nr++;
385 
386  /* allocate space */
387  if (list->alloc_ranges == 0) {
388  list->min = (int *)G_malloc(nr * sizeof(int));
389  list->max = (int *)G_malloc(nr * sizeof(int));
390  }
391  else if (nr > list->alloc_ranges) {
392  list->min = (int *)G_realloc((void *)list->min, nr * sizeof(int));
393  list->max = (int *)G_realloc((void *)list->max, nr * sizeof(int));
394  }
395 
396  /* go through string and read ranges */
397  i = 0;
398  s = str;
399 
400  while (s) {
401  e = (char *)strchr(s, ','); /* first comma */
402  if (e) {
403  l = e - s;
404  strncpy(buf, s, l);
405  buf[l] = '\0';
406  s = e + 1;
407  }
408  else {
409  strcpy(buf, s);
410  s = NULL;
411  }
412 
413  G_debug(3, " buf = %s", buf);
414  if (sscanf(buf, "%d-%d", &min, &max) == 2) {
415  }
416  else if (sscanf(buf, "%d", &min) == 1)
417  max = min;
418  else { /* error */
419 
420  G_warning(_("Unable to convert category string '%s' (from '%s') to "
421  "category range"),
422  buf, str);
423  err++;
424  continue;
425  }
426 
427  list->min[i] = min;
428  list->max[i] = max;
429  i++;
430  }
431 
432  list->n_ranges = i;
433 
434  return (err);
435 }
436 
437 /*!
438  \brief Convert ordered array of integers to cat_list structure.
439 
440  \param vals array of integers
441  \param nvals number of values
442  \param[in,out] list pointer to cat_list structure
443 
444  \return number of ranges
445  */
446 int Vect_array_to_cat_list(const int *vals, int nvals, struct cat_list *list)
447 {
448  int i, range;
449 
450  G_debug(1, "Vect_array_to_cat_list()");
451  range = -1;
452  for (i = 0; i < nvals; i++) {
453  if (i == 0 || (vals[i] - list->max[range]) > 1) {
454  range++;
455  if (range == list->alloc_ranges) {
456  list->alloc_ranges += 1000;
457  list->min = (int *)G_realloc((void *)list->min,
458  list->alloc_ranges * sizeof(int));
459  list->max = (int *)G_realloc((void *)list->max,
460  list->alloc_ranges * sizeof(int));
461  }
462  list->min[range] = vals[i];
463  list->max[range] = vals[i];
464  }
465  else {
466  list->max[range] = vals[i];
467  }
468  }
469 
470  list->n_ranges = range + 1;
471 
472  return (list->n_ranges);
473 }
474 
475 /*!
476  \brief Convert cat_list struct to ordered array of unique integers.
477 
478  Output array do not contain duplicate items.
479 
480  Allocated array should be freed by G_free().
481 
482  \param list pointer to cat_list struct
483  \param[out] vals array of integers
484  \param[out] nvals number of values
485 
486  \return 0 on success
487  \return -1 on failure
488  */
489 int Vect_cat_list_to_array(const struct cat_list *list, int **vals, int *nvals)
490 {
491  int i, j, k, n, n_cats, n_ucats, last_cat;
492  int *cats, *ucats;
493 
494  G_debug(1, "Vect_cat_list_to_array()");
495 
496  *nvals = n_cats = 0;
497  cats = NULL;
498  for (i = 0; i < list->n_ranges; i++) {
499  n = list->max[i] - list->min[i] + 1;
500  if (n < 1) {
501  G_free(cats);
502  return -1;
503  }
504 
505  /* realloc array */
506  cats = (int *)G_realloc(cats, sizeof(int) * (n_cats + n));
507 
508  for (j = n_cats, k = 0; j < n_cats + n; j++, k++) {
509  cats[j] = list->min[i] + k;
510  }
511  n_cats += n;
512  }
513 
514  /* sort array */
515  qsort(cats, n_cats, sizeof(int), cmp);
516 
517  /* skip duplicated values */
518  ucats = G_malloc(sizeof(int) * n_cats);
519  last_cat = ucats[0] = cats[0];
520  n_ucats = 1;
521  for (i = 1; i < n_cats; i++) {
522  if (last_cat == cats[i])
523  continue;
524  last_cat = ucats[n_ucats++] = cats[i];
525  }
526  G_free(cats);
527 
528  /* reallocate array for unique values */
529  ucats = (int *)G_realloc(ucats, sizeof(int) * n_ucats);
530 
531  *nvals = n_ucats;
532  *vals = ucats;
533 
534  return 0;
535 }
536 
537 /*!
538  \brief Check if category number is in list.
539 
540  \param cat category number
541  \param list cat_list structure
542 
543  \return TRUE if cat is in list
544  \return FALSE if not
545  */
546 int Vect_cat_in_cat_list(int cat, const struct cat_list *list)
547 {
548  int i;
549 
550  for (i = 0; i < list->n_ranges; i++)
551  if (cat >= list->min[i] && cat <= list->max[i])
552  return (TRUE);
553 
554  return (FALSE);
555 }
556 
557 /*!
558  \brief Set category constraints using 'where' or 'cats' option and layer
559  number.
560 
561  \param Map pointer to Map_info structure
562  \param layer layer number
563  \param where where statement
564  \param catstr category list as string
565 
566  \return pointer to cat_list structure or NULL
567  */
568 struct cat_list *Vect_cats_set_constraint(struct Map_info *Map, int layer,
569  char *where, char *catstr)
570 {
571  struct cat_list *list = NULL;
572  int ret;
573 
574  if (layer < 1) {
575  G_warning(_("Layer number must be > 0 for category constraints"));
576  /* no valid constraints, all categories qualify */
577  return list;
578  }
579 
580  /* where has precedence over cats */
581  if (where) {
582  struct field_info *Fi = NULL;
583  dbDriver *driver = NULL;
584  int ncats, *cats = NULL;
585  int i, j;
586 
587  if (catstr)
588  G_warning(_("'%s' and '%s' parameters were supplied, cats will be "
589  "ignored"),
590  "where", "cats");
591 
592  Fi = Vect_get_field(Map, layer);
593  if (!Fi) {
594  G_fatal_error(_("Database connection not defined for layer %d"),
595  layer);
596  }
597 
598  G_verbose_message(_("Loading categories from table <%s>..."),
599  Fi->table);
600 
602  if (driver == NULL)
603  G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
604  Fi->database, Fi->driver);
605 
606  ncats = db_select_int(driver, Fi->table, Fi->key, where, &cats);
607  if (ncats == -1)
608  G_fatal_error(_("Unable select records from table <%s>"),
609  Fi->table);
611  n_("One category loaded", "%d categories loaded", ncats), ncats);
612 
614 
615  /* sort */
616  qsort(cats, ncats, sizeof(int), cmp);
617 
618  /* remove duplicates */
619  j = 1;
620  for (i = 1; i < ncats; i++) {
621  if (cats[i] != cats[j - 1]) {
622  cats[j] = cats[i];
623  j++;
624  }
625  }
626  ncats = j;
627 
628  /* convert to cat list */
630 
631  ret = Vect_array_to_cat_list(cats, ncats, list);
632  if (ret == 0)
633  G_warning(_("No categories selected with '%s' option"), "where");
634 
635  if (cats)
636  G_free(cats);
637  }
638  else if (catstr) {
640 
641  ret = Vect_str_to_cat_list(catstr, list);
642  if (ret > 0)
643  G_warning(_("%d errors in '%s' option"), ret, "cats");
644  }
645 
646  if (list) {
647  if (list->n_ranges < 1) {
649  list = NULL;
650  }
651  else
652  list->field = layer;
653  }
654 
655  return list;
656 }
657 
658 /*!
659  \brief Check if categories match with category constraints.
660 
661  \param Cats line_cats structure
662  \param layer layer number
663  \param list cat_list structure
664 
665  \return 0 no match, categories are outside constraints
666  \return 1 match, categories are inside constraints
667  */
668 /* TODO:
669  * for GRASS 8, change return type:
670  * return a list of all category numbers that match the constraints
671  * return NULL if no category number matches the constraints
672  */
673 int Vect_cats_in_constraint(struct line_cats *Cats, int layer,
674  struct cat_list *list)
675 {
676  int i;
677 
678  if (layer < 1) {
679  G_warning(_("Layer number must be > 0 for category constraints"));
680  /* no valid constraint, all categories qualify */
681  return 1;
682  }
683 
684  if (list) {
685  for (i = 0; i < Cats->n_cats; i++) {
686  if (Cats->field[i] == layer &&
687  Vect_cat_in_cat_list(Cats->cat[i], list)) {
688  return 1;
689  }
690  }
691  return 0;
692  }
693 
694  for (i = 0; i < Cats->n_cats; i++) {
695  if (Cats->field[i] == layer)
696  return 1;
697  }
698 
699  return 0;
700 }
701 
702 /*!
703  \brief Check if category is in ordered array of integers.
704 
705  \param cat category number
706  \param array ordered array of integers
707  \param ncats number of categories in array
708 
709  \return TRUE if cat is in list
710  \return FALSE if it is not
711  */
712 int Vect_cat_in_array(int cat, const int *array, int ncats)
713 {
714  int *i;
715 
716  i = bsearch((void *)&cat, (void *)array, (size_t)ncats, sizeof(int), cmp);
717 
718  return (i != NULL);
719 }
720 
721 /* return -1 if *p1 < *p2
722  * return 1 if *p1 > *p2
723  * return 0 if *p1 == *p2 */
724 static int cmp(const void *pa, const void *pb)
725 {
726  int *p1 = (int *)pa;
727  int *p2 = (int *)pb;
728 
729  if (*p1 < *p2)
730  return -1;
731  return (*p1 > *p2);
732 }
#define NULL
Definition: ccmath.h:32
Main header of GRASS DataBase Management Interface.
dbDriver * db_start_driver_open_database(const char *, const char *)
Open driver/database connection.
Definition: db.c:28
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.
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:147
#define G_realloc(p, n)
Definition: defs/gis.h:96
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
#define G_malloc(n)
Definition: defs/gis.h:94
void void G_verbose_message(const char *,...) __attribute__((format(printf
int G_debug(int, const char *,...) __attribute__((format(printf
int Vect_list_append(struct ilist *, int)
Append new item to the end of list if not yet present.
struct field_info * Vect_get_field(struct Map_info *, int)
Get information about link to database (by layer number)
Definition: field.c:515
int Vect_reset_list(struct ilist *)
Reset ilist structure.
#define GV_FIELD_MAX
Maximum field.
Definition: dig_defines.h:217
#define GV_NCATS_MAX
Maximum number of categories for one element.
Definition: dig_defines.h:215
int dig_alloc_cats(struct line_cats *, int)
Allocate room for 'num' fields and category arrays in struct line_cats.
Definition: struct_alloc.c:380
#define min(x, y)
Definition: draw2.c:29
#define max(x, y)
Definition: draw2.c:30
#define TRUE
Definition: gis.h:78
#define FALSE
Definition: gis.h:82
#define n_(strs, strp, num)
Definition: glocale.h:11
#define _(str)
Definition: glocale.h:10
#define strcpy
Definition: parson.c:62
double l
Definition: r_raster.c:39
struct list * list
Definition: read_list.c:24
Vector map info.
Definition: dig_structs.h:1243
Category list.
Definition: dig_structs.h:1697
int n_ranges
Number of ranges.
Definition: dig_structs.h:1713
int * min
Array of minimum values.
Definition: dig_structs.h:1705
int * max
Array of maximum values.
Definition: dig_structs.h:1709
Definition: driver.h:27
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
List of integers.
Definition: gis.h:715
int n_values
Number of values in the list.
Definition: gis.h:723
Feature category info.
Definition: dig_structs.h:1677
int * field
Array of layers (fields)
Definition: dig_structs.h:1681
int alloc_cats
Allocated space for categories.
Definition: dig_structs.h:1693
int * cat
Array of categories.
Definition: dig_structs.h:1685
int n_cats
Number of categories attached to element.
Definition: dig_structs.h:1689
Definition: manage.h:4
SYMBOL * err(FILE *fp, SYMBOL *s, char *msg)
Definition: symbol/read.c:216
struct cat_list * Vect_new_cat_list(void)
Allocate memory for cat_list structure.
struct cat_list * Vect_cats_set_constraint(struct Map_info *Map, int layer, char *where, char *catstr)
Set category constraints using 'where' or 'cats' option and layer number.
void Vect_destroy_cats_struct(struct line_cats *p)
Frees all memory associated with line_cats structure, including the struct itself.
int Vect_cat_get(const struct line_cats *Cats, int field, int *cat)
Get first found category of given field.
int Vect_reset_cats(struct line_cats *Cats)
Reset category structure to make sure cats structure is clean to be re-used.
int Vect_field_cat_del(struct line_cats *Cats, int field, int cat)
Delete field/cat from line_cats structure.
int Vect_array_to_cat_list(const int *vals, int nvals, struct cat_list *list)
Convert ordered array of integers to cat_list structure.
int Vect_cat_in_array(int cat, const int *array, int ncats)
Check if category is in ordered array of integers.
int Vect_str_to_cat_list(const char *str, struct cat_list *list)
Converts string of categories and cat ranges separated by commas to cat_list.
int Vect_cat_in_cat_list(int cat, const struct cat_list *list)
Check if category number is in list.
int Vect_cat_list_to_array(const struct cat_list *list, int **vals, int *nvals)
Convert cat_list struct to ordered array of unique integers.
int Vect_field_cat_get(const struct line_cats *Cats, int field, struct ilist *cats)
Get list of categories of given field.
int Vect_cats_in_constraint(struct line_cats *Cats, int layer, struct cat_list *list)
Check if categories match with category constraints.
int Vect_cat_del(struct line_cats *Cats, int field)
Delete all categories of given layer.
struct line_cats * Vect_new_cats_struct(void)
Creates and initializes line_cats structure.
void Vect_destroy_cat_list(struct cat_list *p)
Frees allocated cat_list memory.
int Vect_cat_set(struct line_cats *Cats, int field, int cat)
Add new field/cat to category structure if doesn't exist yet.