Vlib/cats.c

Go to the documentation of this file.
00001 
00021 #include <stdlib.h>
00022 #include <string.h>
00023 #include <grass/gis.h>
00024 #include <grass/Vect.h>
00025 #include <grass/glocale.h>
00026 
00027 static int cmp(const void *pa, const void *pb);
00028 struct line_cats *Vect__new_cats_struct(void);
00029 
00030 
00040 struct line_cats *Vect_new_cats_struct()
00041 {
00042     struct line_cats *p;
00043 
00044     if (NULL == (p = Vect__new_cats_struct()))
00045         G_fatal_error(_("Vect_new_cats_struct(): Out of memory"));
00046 
00047     return p;
00048 }
00049 
00058 struct line_cats *Vect__new_cats_struct()
00059 {
00060     struct line_cats *p;
00061 
00062     p = (struct line_cats *)G_malloc(sizeof(struct line_cats));
00063 
00064     /* n_cats MUST be initialized to zero */
00065     if (p)
00066         p->n_cats = 0;
00067 
00068     if (p)
00069         p->alloc_cats = 0;
00070 
00071     return p;
00072 }
00073 
00081 int Vect_destroy_cats_struct(struct line_cats *p)
00082 {
00083     if (p) {                    /* probably a moot test */
00084         if (p->n_cats) {
00085             G_free((void *)p->field);
00086             G_free((void *)p->cat);
00087         }
00088         G_free((void *)p);
00089     }
00090 
00091     return 0;
00092 }
00093 
00106 int Vect_cat_set(struct line_cats *Cats, int field, int cat)
00107 {
00108     register int n;
00109 
00110     /* check input values */
00111     /* compiler may warn: 
00112      * comparison is always 0 due to limited range of data type
00113      * but remember that limit is set to portable data type length
00114      * and machine native size may be longer */
00115     /*
00116        if (field < 1 || field > GV_FIELD_MAX || cat < 0 || cat > GV_CAT_MAX)
00117        return (-2);
00118      */
00119 
00120     /* go through old cats and find if field/category exists */
00121     for (n = 0; n < Cats->n_cats; n++) {
00122         if (Cats->field[n] == field && Cats->cat[n] == cat)
00123             return (1);
00124     }
00125 
00126     /* field was not found so we shall append new cat */
00127     /* test if space exist */
00128     if (n >= GV_NCATS_MAX) {
00129         G_fatal_error(_("Too many categories (%d), unable to set cat %d (layer %d)"),
00130                       Cats->n_cats, cat, field);
00131     }
00132 
00133     if (Cats->n_cats == Cats->alloc_cats) {
00134         if (0 > dig_alloc_cats(Cats, Cats->n_cats + 100))
00135             return (-1);
00136     }
00137 
00138     n = Cats->n_cats;
00139     Cats->field[n] = field;
00140     Cats->cat[n] = cat;
00141     Cats->n_cats++;
00142     return (1);
00143 }
00144 
00157 int Vect_cat_get(struct line_cats *Cats, int field, int *cat)
00158 {
00159     register int n;
00160 
00161     /* check input value */
00162     /*
00163        if (field < 1 || field > GV_FIELD_MAX)
00164        return (0);
00165      */
00166 
00167     *cat = -1;
00168 
00169     /* go through cats and find if field exist */
00170     for (n = 0; n < Cats->n_cats; n++) {
00171         if (Cats->field[n] == field) {
00172             *cat = Cats->cat[n];
00173             return (1);
00174         }
00175     }
00176 
00177     /* field was not found */
00178     return (0);
00179 }
00180 
00191 int Vect_field_cat_get(struct line_cats *Cats, int field, struct ilist *cats)
00192 {
00193     int n;
00194     
00195     /* reset list of categories */
00196     Vect_reset_list(cats);
00197 
00198     /* check input value */
00199     if (field < 1 || field > GV_FIELD_MAX)
00200         return -1;
00201     
00202     /* go through cats and find if field exist */
00203     for (n = 0; n < Cats->n_cats; n++) {
00204         if (Cats->field[n] != field)
00205             continue;
00206         Vect_list_append(cats, Cats->cat[n]);
00207     }
00208 
00209     return cats->n_values;
00210 }
00211 
00221 int Vect_cat_del(struct line_cats *Cats, int field)
00222 {
00223     int n, m, found = 0;
00224 
00225     /* check input value */
00226     /*
00227        if (field < 1 || field > GV_FIELD_MAX)
00228        return (0);
00229      */
00230 
00231     /* go through cats and find if field exist */
00232     for (n = 0; n < Cats->n_cats; n++) {
00233         if (Cats->field[n] == field) {
00234             for (m = n; m < Cats->n_cats - 1; m++) {
00235                 Cats->field[m] = Cats->field[m + 1];
00236                 Cats->cat[m] = Cats->cat[m + 1];
00237             }
00238             Cats->n_cats--;
00239             found = 1;
00240             n--;                /* check again this position */
00241         }
00242     }
00243 
00244     return (found);
00245 }
00246 
00257 int Vect_field_cat_del(struct line_cats *Cats, int field, int cat)
00258 {
00259     register int n, m, found = 0;
00260 
00261     /* check input value */
00262     /*
00263        if (field < 1 || field > GV_FIELD_MAX)
00264        return (0);
00265      */
00266 
00267     /* go through cats and find if field exist */
00268     for (n = 0; n < Cats->n_cats; n++) {
00269         if (Cats->field[n] == field && (Cats->cat[n] == cat || cat == -1)) {
00270             for (m = n; m < Cats->n_cats - 1; m++) {
00271                 Cats->field[m] = Cats->field[m + 1];
00272                 Cats->cat[m] = Cats->cat[m + 1];
00273             }
00274             Cats->n_cats--;
00275             found = 1;
00276         }
00277     }
00278 
00279     return (found);
00280 }
00281 
00292 int Vect_reset_cats(struct line_cats *Cats)
00293 {
00294     Cats->n_cats = 0;
00295 
00296     return 0;
00297 }
00298 
00305 struct cat_list *Vect_new_cat_list()
00306 {
00307     struct cat_list *p;
00308 
00309     p = (struct cat_list *)G_malloc(sizeof(struct cat_list));
00310 
00311     /* n_ranges MUST be initialized to zero */
00312     if (p) {
00313         p->n_ranges = 0;
00314         p->alloc_ranges = 0;
00315         p->field = 0;
00316         p->min = NULL;
00317         p->max = NULL;
00318     }
00319 
00320     return p;
00321 }
00322 
00323 
00331 int Vect_destroy_cat_list(struct cat_list *p)
00332 {
00333     if (p) {                    /* probably a moot test */
00334         if (p->n_ranges) {
00335             G_free((void *)p->min);
00336             G_free((void *)p->max);
00337         }
00338         G_free((void *)p);
00339     }
00340 
00341     return 0;
00342 }
00343 
00344 
00355 int Vect_str_to_cat_list(const char *str, struct cat_list *list)
00356 {
00357     int i, nr, l, err = 0;
00358     const char *s, *e;
00359     char buf[100];
00360     int min, max;
00361 
00362     G_debug(3, "Vect_str_to_cat_list(): str = %s", str);
00363 
00364     list->n_ranges = 0;
00365     l = strlen(str);
00366 
00367     /* find number of ranges */
00368     nr = 1;                     /* one range */
00369     for (i = 0; i < l; i++)
00370         if (str[i] == ',')
00371             nr++;
00372 
00373     /* allocate space */
00374     if (list->alloc_ranges == 0) {
00375         list->min = (int *)G_malloc(nr * sizeof(int));
00376         list->max = (int *)G_malloc(nr * sizeof(int));
00377     }
00378     else if (nr > list->alloc_ranges) {
00379         list->min = (int *)G_realloc((void *)list->min, nr * sizeof(int));
00380         list->max = (int *)G_realloc((void *)list->max, nr * sizeof(int));
00381     }
00382 
00383     /* go through string and read ranges */
00384     i = 0;
00385     s = str;
00386 
00387     while (s) {
00388         e = (char *)strchr(s, ',');     /* first comma */
00389         if (e) {
00390             l = e - s;
00391             strncpy(buf, s, l);
00392             buf[l] = '\0';
00393             s = e + 1;
00394         }
00395         else {
00396             strcpy(buf, s);
00397             s = NULL;
00398         }
00399 
00400         G_debug(3, "  buf = %s", buf);
00401         if (sscanf(buf, "%d-%d", &min, &max) == 2) {
00402         }
00403         else if (sscanf(buf, "%d", &min) == 1)
00404             max = min;
00405         else {                  /* error */
00406 
00407             G_warning(_("Unable to convert category string '%s' (from '%s') to category range"),
00408                       buf, str);
00409             err++;
00410             continue;
00411         }
00412 
00413         list->min[i] = min;
00414         list->max[i] = max;
00415         i++;
00416     }
00417 
00418     list->n_ranges = i;
00419 
00420     return (err);
00421 }
00422 
00432 int Vect_array_to_cat_list(int *vals, int nvals, struct cat_list *list)
00433 {
00434     int i, range;
00435 
00436     G_debug(1, "Vect_array_to_cat_list()");
00437     range = -1;
00438     for (i = 0; i < nvals; i++) {
00439         if (i == 0 || (vals[i] - list->max[range]) > 1) {
00440             range++;
00441             if (range == list->alloc_ranges) {
00442                 list->alloc_ranges += 1000;
00443                 list->min = (int *)G_realloc((void *)list->min,
00444                                              list->alloc_ranges *
00445                                              sizeof(int));
00446                 list->max =
00447                     (int *)G_realloc((void *)list->max,
00448                                      list->alloc_ranges * sizeof(int));
00449             }
00450             list->min[range] = vals[i];
00451             list->max[range] = vals[i];
00452         }
00453         else {
00454             list->max[range] = vals[i];
00455         }
00456     }
00457 
00458     list->n_ranges = range + 1;
00459 
00460     return (list->n_ranges);
00461 }
00462 
00472 int Vect_cat_in_cat_list(int cat, struct cat_list *list)
00473 {
00474     int i;
00475 
00476     for (i = 0; i < list->n_ranges; i++)
00477         if (cat >= list->min[i] && cat <= list->max[i])
00478             return (TRUE);
00479 
00480     return (FALSE);
00481 }
00482 
00493 int Vect_cat_in_array(int cat, int *array, int ncats)
00494 {
00495     int *i;
00496 
00497     i = bsearch((void *)&cat, (void *)array, (size_t) ncats,
00498                 sizeof(int), cmp);
00499 
00500     if (i != NULL)
00501         return (TRUE);
00502 
00503     return (FALSE);
00504 }
00505 
00506 static int cmp(const void *pa, const void *pb)
00507 {
00508     int *p1 = (int *)pa;
00509     int *p2 = (int *)pb;
00510 
00511     if (*p1 < *p2)
00512         return -1;
00513     if (*p1 > *p2)
00514         return 1;
00515     return 0;
00516 }
Generated on Tue Apr 6 13:28:09 2010 for GRASS Programmer's Manual by  doxygen 1.6.3