cats.c

Go to the documentation of this file.
00001 /*
00002 ****************************************************************************
00003 *
00004 * MODULE:       Vector library 
00005 *               
00006 * AUTHOR(S):    Original author CERL, probably Dave Gerdes or Mike Higgins.
00007 *               Update to GRASS 5.7 Radim Blazek and David D. Gray.
00008 *
00009 * PURPOSE:      Higher level functions for reading/writing/manipulating vectors.
00010 *
00011 * COPYRIGHT:    (C) 2001 by the GRASS Development Team
00012 *
00013 *               This program is free software under the GNU General Public
00014 *               License (>=v2). Read the file COPYING that comes with GRASS
00015 *               for details.
00016 *
00017 *****************************************************************************/
00018 #include <stdlib.h>
00019 #include <string.h>
00020 #include <grass/gis.h>
00021 #include <grass/Vect.h>
00022 
00023 
00024 static int cmp(const void *pa, const void *pb);
00025 struct line_cats *Vect__new_cats_struct (void);
00026 
00027 
00036 struct line_cats *
00037 Vect_new_cats_struct ()
00038 {
00039   struct line_cats *p;
00040 
00041   if (NULL == (p = Vect__new_cats_struct ()))
00042     G_fatal_error ("New_line: Out of memory");
00043 
00044   return p;
00045 }
00046 
00047 struct line_cats *
00048 Vect__new_cats_struct ()
00049 {
00050   struct line_cats *p;
00051 
00052   p = (struct line_cats *) malloc (sizeof (struct line_cats));
00053 
00054   /* n_cats MUST be initialized to zero */
00055   if (p)
00056     p->n_cats = 0;
00057 
00058   if (p)
00059     p->alloc_cats = 0;
00060   
00061   return p;
00062 }
00063 
00070 int 
00071 Vect_destroy_cats_struct (struct line_cats *p)
00072 {
00073   if (p)                        /* probably a moot test */
00074     {
00075       if (p->n_cats)
00076         {
00077           free ((char *) p->field);
00078           free ((char *) p->cat);
00079         }
00080       free ((char *) p);
00081     }
00082 
00083   return 0;
00084 }
00085 
00097 int 
00098 Vect_cat_set (struct line_cats *Cats, int field, int cat)
00099 {
00100   register int n;
00101 
00102   /* check input values */
00103   /* compiler may warn: 
00104    * comparison is always 0 due to limited range of data type
00105    * but remember that limit is set to portable data type length
00106    * and machine native size may be longer */
00107   /*
00108   if (field < 1 || field > GV_FIELD_MAX || cat < 0 || cat > GV_CAT_MAX)
00109     return (-2);
00110    */
00111     
00112   /* go through old cats and find if field/category exists */
00113   for (n = 0; n < Cats->n_cats; n++) {
00114       if (Cats->field[n] == field && Cats->cat[n] == cat )
00115           return (1);
00116   }
00117 
00118   /* field was not found so we shall append new cat */
00119   /* test if space exist */
00120   if (n >= GV_NCATS_MAX) {
00121       G_fatal_error ( "Too many categories (%d), cannot set cat %d (field %d).", Cats->n_cats, cat, field);
00122   }
00123 
00124   if ( Cats->n_cats == Cats->alloc_cats ) {
00125       if (0 > dig_alloc_cats (Cats, Cats->n_cats + 100))
00126         return (-1);
00127   }
00128 
00129   n = Cats->n_cats;
00130   Cats->field[n] = field;
00131   Cats->cat[n] = cat;
00132   Cats->n_cats++;
00133   return (1);
00134 }
00135 
00145 int 
00146 Vect_cat_get (struct line_cats *Cats, int field, int *cat)
00147 {
00148   register int n;
00149 
00150   /* check input value */
00151   /*
00152   if (field < 1 || field > GV_FIELD_MAX)
00153     return (0);
00154   */
00155 
00156   *cat = -1;
00157     
00158   /* go through cats and find if field exist */
00159   for (n = 0; n < Cats->n_cats; n++)
00160     {
00161       if (Cats->field[n] == field)
00162         {
00163           *cat = Cats->cat[n];
00164           return (1);
00165         }
00166     }
00167 
00168   /* field was not found */
00169   return (0);
00170 }
00171 
00179 int 
00180 Vect_cat_del (struct line_cats *Cats, int field)
00181 {
00182   int n, m, found = 0;
00183 
00184   /* check input value */
00185   /*
00186   if (field < 1 || field > GV_FIELD_MAX)
00187     return (0);
00188    */
00189     
00190   /* go through cats and find if field exist */
00191   for (n = 0; n < Cats->n_cats; n++) {
00192       if (Cats->field[n] == field) {
00193           for (m = n; m < Cats->n_cats - 1; m++) {
00194               Cats->field[m] = Cats->field[m + 1];
00195               Cats->cat[m] = Cats->cat[m + 1];
00196           }
00197           Cats->n_cats--;
00198           found = 1;
00199           n--; /* check again this position */
00200       }
00201   }
00202 
00203   return (found);
00204 }
00205 
00214 int 
00215 Vect_field_cat_del (struct line_cats *Cats, int field, int cat)
00216 {
00217   register int n, m, found = 0;
00218 
00219   /* check input value */
00220   /*
00221   if (field < 1 || field > GV_FIELD_MAX)
00222     return (0);
00223    */
00224     
00225   /* go through cats and find if field exist */
00226   for (n = 0; n < Cats->n_cats; n++) {
00227       if (Cats->field[n] == field && ( Cats->cat[n] == cat || cat == -1) ) {
00228           for (m = n; m < Cats->n_cats - 1; m++) {
00229               Cats->field[m] = Cats->field[m + 1];
00230               Cats->cat[m] = Cats->cat[m + 1];
00231           }
00232           Cats->n_cats--;
00233           found = 1;
00234       }
00235   }
00236 
00237   return (found);
00238 }
00239 
00248 int 
00249 Vect_reset_cats (struct line_cats *Cats)
00250 {
00251   Cats->n_cats = 0;
00252 
00253   return 0;
00254 }
00255 
00262 struct cat_list *
00263 Vect_new_cat_list ()
00264 {
00265   struct cat_list *p;
00266 
00267   p = (struct cat_list *) malloc (sizeof (struct cat_list));
00268 
00269   /* n_ranges MUST be initialized to zero */
00270   if (p) {
00271     p->n_ranges = 0;
00272     p->alloc_ranges = 0;
00273     p->field = 0;
00274     p->min = NULL;
00275     p->max = NULL;
00276   }
00277   
00278   return p;
00279 }
00280 
00281 
00288 int 
00289 Vect_destroy_cat_list (struct cat_list *p)
00290 {
00291   if (p)                        /* probably a moot test */
00292     {
00293       if (p->n_ranges)
00294         {
00295           free ((char *) p->min);
00296           free ((char *) p->max);
00297         }
00298       free ((char *) p);
00299     }
00300 
00301   return 0;
00302 }
00303 
00304 
00313 int 
00314 Vect_str_to_cat_list (char *str, struct cat_list *list)
00315 {
00316   int i, nr, l, err = 0;
00317   char *s, *e, buf[100];
00318   int min, max;
00319   
00320   G_debug (3, "Vect_str_to_cat_list(): str = %s", str);
00321   
00322   list->n_ranges = 0;
00323   l = strlen (str); 
00324   
00325   /* find number of ranges */
00326   nr = 1; /* one range */
00327   for ( i=0; i < l; i++)  
00328       if (str[i] == ',')
00329            nr++;
00330           
00331   /* allocate space */
00332   if ( list->alloc_ranges == 0 )
00333     {       
00334       list->min = (int *) G_malloc (nr * sizeof(int));
00335       list->max = (int *) G_malloc (nr * sizeof(int));
00336     }
00337   else if (nr > list->alloc_ranges)
00338     {
00339       list->min = (int *) G_realloc ((void *)list->min, 
00340                                         nr * sizeof(int));
00341       list->max = (int *) G_realloc ((void *)list->max, 
00342                                         nr * sizeof(int));
00343     }
00344     
00345   /* go through string and read ranges */
00346   i = 0;  
00347   s = str;  
00348   
00349   while (s)
00350     {
00351       e = (char *) strchr (s, ','); /* first comma */
00352       if( e )
00353         {
00354           l = e - s;
00355           strncpy (buf, s, l);
00356           buf[l] = '\0';
00357           s = e + 1;
00358         }
00359       else
00360         {
00361           strcpy (buf, s);
00362           s = NULL;
00363         }
00364       
00365       G_debug (3, "  buf = %s", buf);
00366       if ( sscanf (buf, "%d-%d", &min, &max) == 2 ) {}
00367       else if ( sscanf (buf, "%d", &min) == 1 )
00368           max = min;
00369       else  /* error */ 
00370         {
00371           G_warning ("Cannot convert category string '%s' (from '%s') to category range", buf, str);
00372           err++;        
00373           continue;
00374         }
00375   
00376       list->min[i] = min;  
00377       list->max[i] = max;
00378       i++;
00379     }  
00380       
00381   list->n_ranges = i;
00382   
00383   return (err);
00384 }
00385 
00392 int
00393 Vect_array_to_cat_list (int *vals, int nvals, struct cat_list *list)
00394 {
00395     int i, range;
00396 
00397     G_debug (1, "Vect_array_to_cat_list()");
00398     range = -1;
00399     for (i = 0; i < nvals; i++)
00400       {
00401         if ( i == 0 || (vals[i] - list->max[range]) > 1 )
00402           {
00403             range++;
00404             if ( range == list->alloc_ranges)
00405               {
00406                 list->alloc_ranges += 1000;       
00407                 list->min = (int *) G_realloc ((void *)list->min, 
00408                                         list->alloc_ranges * sizeof(int));
00409                 list->max = (int *) G_realloc ((void *)list->max, 
00410                                         list->alloc_ranges * sizeof(int));
00411               }
00412             list->min[range] = vals[i];
00413             list->max[range] = vals[i];
00414           }
00415         else
00416           {
00417             list->max[range] = vals[i];
00418           }
00419       }
00420     
00421     list->n_ranges = range+1;
00422 
00423     return (list->n_ranges);
00424 }
00425 
00432 int 
00433 Vect_cat_in_cat_list (int cat, struct cat_list *list)
00434 {
00435   int i;
00436   
00437   for ( i=0; i < list->n_ranges; i++)  
00438       if ( cat >= list->min[i] && cat <= list->max[i] )
00439            return (TRUE);
00440           
00441   return (FALSE);
00442 }
00443 
00450 int 
00451 Vect_cat_in_array (int cat, int *array, int ncats)
00452 {
00453   int *i;
00454   
00455   i = bsearch ( (void *) &cat, (void *) array, (size_t)ncats,
00456                 sizeof (int), cmp);
00457 
00458   if ( i != NULL ) return (TRUE);
00459   
00460   return (FALSE);
00461 }
00462 
00463 
00464 static int cmp ( const void *pa, const void *pb)
00465 {
00466     int *p1 = (int *) pa;
00467     int *p2 = (int *) pb;
00468          
00469     if( *p1 < *p2 )
00470        return -1;
00471     if( *p1 > *p2 )
00472        return 1;
00473     return 0;
00474 }

Generated on Sun Apr 6 17:32:44 2008 for GRASS by  doxygen 1.5.5