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 "gis.h"
00021 #include "Vect.h"
00022 
00023 static int cmp();
00024 struct line_cats *Vect__new_cats_struct (void);
00025 
00034 struct line_cats *
00035 Vect_new_cats_struct ()
00036 {
00037   struct line_cats *p;
00038 
00039   if (NULL == (p = Vect__new_cats_struct ()))
00040     G_fatal_error ("New_line: Out of memory");
00041 
00042   return p;
00043 }
00044 
00045 struct line_cats *
00046 Vect__new_cats_struct ()
00047 {
00048   struct line_cats *p;
00049 
00050   p = (struct line_cats *) malloc (sizeof (struct line_cats));
00051 
00052   /* n_cats MUST be initialized to zero */
00053   if (p)
00054     p->n_cats = 0;
00055 
00056   if (p)
00057     p->alloc_cats = 0;
00058   
00059   return p;
00060 }
00061 
00068 int 
00069 Vect_destroy_cats_struct (struct line_cats *p)
00070 {
00071   if (p)                        /* probably a moot test */
00072     {
00073       if (p->n_cats)
00074         {
00075           free ((char *) p->field);
00076           free ((char *) p->cat);
00077         }
00078       free ((char *) p);
00079     }
00080 
00081   return 0;
00082 }
00083 
00095 int 
00096 Vect_cat_set (struct line_cats *Cats, int field, int cat)
00097 {
00098   register int n;
00099 
00100   /* check input values */
00101   /* compiler may warn: 
00102    * comparison is always 0 due to limited range of data type
00103    * but remember that limit is set to portable data type length
00104    * and machine native size may be longer */
00105   /*
00106   if (field < 1 || field > GV_FIELD_MAX || cat < 0 || cat > GV_CAT_MAX)
00107     return (-2);
00108    */
00109     
00110   /* go through old cats and find if field/category exists */
00111   for (n = 0; n < Cats->n_cats; n++) {
00112       if (Cats->field[n] == field && Cats->cat[n] == cat )
00113           return (1);
00114   }
00115 
00116   /* field was not found so we shall append new cat */
00117   /* test if space exist */
00118   if (n >= GV_NCATS_MAX) {
00119       G_fatal_error ( "Too many categories (%d), cannot set cat %d (field %d).", Cats->n_cats, cat, field);
00120   }
00121 
00122   if ( Cats->n_cats == Cats->alloc_cats ) {
00123       if (0 > dig_alloc_cats (Cats, Cats->n_cats + 100))
00124         return (-1);
00125   }
00126 
00127   n = Cats->n_cats;
00128   Cats->field[n] = field;
00129   Cats->cat[n] = cat;
00130   Cats->n_cats++;
00131   return (1);
00132 }
00133 
00143 int 
00144 Vect_cat_get (struct line_cats *Cats, int field, int *cat)
00145 {
00146   register int n;
00147 
00148   /* check input value */
00149   /*
00150   if (field < 1 || field > GV_FIELD_MAX)
00151     return (0);
00152   */
00153 
00154   *cat = -1;
00155     
00156   /* go through cats and find if field exist */
00157   for (n = 0; n < Cats->n_cats; n++)
00158     {
00159       if (Cats->field[n] == field)
00160         {
00161           *cat = Cats->cat[n];
00162           return (1);
00163         }
00164     }
00165 
00166   /* field was not found */
00167   return (0);
00168 }
00169 
00177 int 
00178 Vect_cat_del (struct line_cats *Cats, int field)
00179 {
00180   int n, m, found = 0;
00181 
00182   /* check input value */
00183   /*
00184   if (field < 1 || field > GV_FIELD_MAX)
00185     return (0);
00186    */
00187     
00188   /* go through cats and find if field exist */
00189   for (n = 0; n < Cats->n_cats; n++) {
00190       if (Cats->field[n] == field) {
00191           for (m = n; m < Cats->n_cats - 1; m++) {
00192               Cats->field[m] = Cats->field[m + 1];
00193               Cats->cat[m] = Cats->cat[m + 1];
00194           }
00195           Cats->n_cats--;
00196           found = 1;
00197           n--; /* check again this position */
00198       }
00199   }
00200 
00201   return (found);
00202 }
00203 
00212 int 
00213 Vect_field_cat_del (struct line_cats *Cats, int field, int cat)
00214 {
00215   register int n, m, found = 0;
00216 
00217   /* check input value */
00218   /*
00219   if (field < 1 || field > GV_FIELD_MAX)
00220     return (0);
00221    */
00222     
00223   /* go through cats and find if field exist */
00224   for (n = 0; n < Cats->n_cats; n++) {
00225       if (Cats->field[n] == field && ( Cats->cat[n] == cat || cat == -1) ) {
00226           for (m = n; m < Cats->n_cats - 1; m++) {
00227               Cats->field[m] = Cats->field[m + 1];
00228               Cats->cat[m] = Cats->cat[m + 1];
00229           }
00230           Cats->n_cats--;
00231           found = 1;
00232       }
00233   }
00234 
00235   return (found);
00236 }
00237 
00246 int 
00247 Vect_reset_cats (struct line_cats *Cats)
00248 {
00249   Cats->n_cats = 0;
00250 
00251   return 0;
00252 }
00253 
00260 struct cat_list *
00261 Vect_new_cat_list ()
00262 {
00263   struct cat_list *p;
00264 
00265   p = (struct cat_list *) malloc (sizeof (struct cat_list));
00266 
00267   /* n_ranges MUST be initialized to zero */
00268   if (p) {
00269     p->n_ranges = 0;
00270     p->alloc_ranges = 0;
00271     p->field = 0;
00272     p->min = NULL;
00273     p->max = NULL;
00274   }
00275   
00276   return p;
00277 }
00278 
00279 
00286 int 
00287 Vect_destroy_cat_list (struct cat_list *p)
00288 {
00289   if (p)                        /* probably a moot test */
00290     {
00291       if (p->n_ranges)
00292         {
00293           free ((char *) p->min);
00294           free ((char *) p->max);
00295         }
00296       free ((char *) p);
00297     }
00298 
00299   return 0;
00300 }
00301 
00302 
00311 int 
00312 Vect_str_to_cat_list (char *str, struct cat_list *list)
00313 {
00314   int i, nr, l, err = 0;
00315   char *s, *e, buf[100];
00316   int min, max;
00317   
00318   G_debug (3, "Vect_str_to_cat_list(): str = %s", str);
00319   
00320   list->n_ranges = 0;
00321   l = strlen (str); 
00322   
00323   /* find number of ranges */
00324   nr = 1; /* one range */
00325   for ( i=0; i < l; i++)  
00326       if (str[i] == ',')
00327            nr++;
00328           
00329   /* allocate space */
00330   if ( list->alloc_ranges == 0 )
00331     {       
00332       list->min = (int *) G_malloc (nr * sizeof(int));
00333       list->max = (int *) G_malloc (nr * sizeof(int));
00334     }
00335   else if (nr > list->alloc_ranges)
00336     {
00337       list->min = (int *) G_realloc ((void *)list->min, 
00338                                         nr * sizeof(int));
00339       list->max = (int *) G_realloc ((void *)list->max, 
00340                                         nr * sizeof(int));
00341     }
00342     
00343   /* go through string and read ranges */
00344   i = 0;  
00345   s = str;  
00346   
00347   while (s)
00348     {
00349       e = (char *) strchr (s, ','); /* first comma */
00350       if( e )
00351         {
00352           l = e - s;
00353           strncpy (buf, s, l);
00354           buf[l] = '\0';
00355           s = e + 1;
00356         }
00357       else
00358         {
00359           strcpy (buf, s);
00360           s = NULL;
00361         }
00362       
00363       G_debug (3, "  buf = %s", buf);
00364       if ( sscanf (buf, "%d-%d", &min, &max) == 2 ) {}
00365       else if ( sscanf (buf, "%d", &min) == 1 )
00366           max = min;
00367       else  /* error */ 
00368         {
00369           G_warning ("Cannot convert category string '%s' (from '%s') to category range", buf, str);
00370           err++;        
00371           continue;
00372         }
00373   
00374       list->min[i] = min;  
00375       list->max[i] = max;
00376       i++;
00377     }  
00378       
00379   list->n_ranges = i;
00380   
00381   return (err);
00382 }
00383 
00390 int
00391 Vect_array_to_cat_list (int *vals, int nvals, struct cat_list *list)
00392 {
00393     int i, range;
00394 
00395     G_debug (1, "Vect_array_to_cat_list()");
00396     range = -1;
00397     for (i = 0; i < nvals; i++)
00398       {
00399         if ( i == 0 || (vals[i] - list->max[range]) > 1 )
00400           {
00401             range++;
00402             if ( range == list->alloc_ranges)
00403               {
00404                 list->alloc_ranges += 1000;       
00405                 list->min = (int *) G_realloc ((void *)list->min, 
00406                                         list->alloc_ranges * sizeof(int));
00407                 list->max = (int *) G_realloc ((void *)list->max, 
00408                                         list->alloc_ranges * sizeof(int));
00409               }
00410             list->min[range] = vals[i];
00411             list->max[range] = vals[i];
00412           }
00413         else
00414           {
00415             list->max[range] = vals[i];
00416           }
00417       }
00418     
00419     list->n_ranges = range+1;
00420 
00421     return (list->n_ranges);
00422 }
00423 
00430 int 
00431 Vect_cat_in_cat_list (int cat, struct cat_list *list)
00432 {
00433   int i;
00434   
00435   for ( i=0; i < list->n_ranges; i++)  
00436       if ( cat >= list->min[i] && cat <= list->max[i] )
00437            return (TRUE);
00438           
00439   return (FALSE);
00440 }
00441 
00448 int 
00449 Vect_cat_in_array (int cat, int *array, int ncats)
00450 {
00451   int *i;
00452   
00453   i = bsearch ( (void *) &cat, (void *) array, ncats,
00454                 sizeof (int), cmp);
00455 
00456   if ( i != NULL ) return (TRUE);
00457   
00458   return (FALSE);
00459 }
00460 
00461 
00462 int cmp ( const void *pa, const void *pb)
00463 {
00464     int *p1 = (int *) pa;
00465     int *p2 = (int *) pb;
00466          
00467     if( *p1 < *p2 )
00468        return -1;
00469     if( *p1 > *p2 )
00470        return 1;
00471     return 0;
00472 }

Generated on Wed Aug 23 17:49:00 2006 for GRASS by  doxygen 1.4.7