array.c

Go to the documentation of this file.
00001 /*****************************************************************************
00002 *
00003 * MODULE:       Vector library 
00004 *               
00005 * AUTHOR(S):    Radim Blazek
00006 *
00007 * PURPOSE:      Higher level functions for reading/writing/manipulating vectors.
00008 *
00009 * COPYRIGHT:    (C) 2001 by the GRASS Development Team
00010 *
00011 *               This program is free software under the GNU General Public
00012 *               License (>=v2). Read the file COPYING that comes with GRASS
00013 *               for details.
00014 *
00015 *****************************************************************************/
00016 #include <stdlib.h>
00017 #include "gis.h"
00018 #include "dbmi.h"
00019 #include "Vect.h"
00020 
00021 /* 
00022  *  Create new VARRAY and allocate space for given number of items.
00023  *  Space allocated is 'size + 1' so that lines are accessed by line id.
00024  *  Array values are set to 0.
00025  *  Returns : pointer to new VARRAY
00026  *            NULL if failed
00027  */
00028 
00029 VARRAY *
00030 Vect_new_varray (int size)
00031 {
00032     VARRAY *p;
00033 
00034     p = (VARRAY *) G_malloc (sizeof (VARRAY));
00035  
00036     if ( p == NULL ) return NULL;
00037   
00038     p->size = size;
00039     p->c = (int *) G_calloc ( size + 1, sizeof(int) );
00040     
00041     if ( p->c == NULL ) {
00042         G_free (p);
00043         return NULL;
00044     }
00045   
00046     return p;
00047 }
00048 
00049 /* 
00050  *  Set values in 'varray' to 'value' if category of object of given type is in 
00051  *  'cstring' (string representing category list like: '1,3,5-7').
00052  *  'type' may be either: GV_AREA
00053  *                    or: GV_POINT | GV_LINE | GV_BOUNDARY | GV_CENTROID  
00054  *
00055  *  Array is not reset to zero before, but old values (if any > 0) are overwritten.
00056  * 
00057  *  Return: number of items set
00058  *          -1 on error
00059  */
00060 int 
00061 Vect_set_varray_from_cat_string ( struct Map_info *Map, int field, char *cstring,
00062                                 int type, int value, VARRAY *varray )
00063 {
00064     int ret;
00065     struct cat_list *Clist;
00066     
00067     G_debug (4, "Vect_set_varray_from_cat_string(): cstring = '%s'", cstring);
00068 
00069     Clist = Vect_new_cat_list ();
00070         
00071     ret = Vect_str_to_cat_list ( cstring, Clist);
00072 
00073     if ( ret > 0 ) G_warning ( "%d errors in category string.", ret);
00074     
00075     G_debug (4, "  %d ranges in clist", Clist->n_ranges);
00076 
00077     ret = Vect_set_varray_from_cat_list ( Map, field, Clist, type, value, varray );
00078     
00079     Vect_destroy_cat_list (Clist);
00080 
00081     return ret;
00082 }
00083 
00084 /* 
00085  *  Set values in 'varray' to 'value' if category of object of given type is in 'clist' (category list).
00086  *  'type' may be either: GV_AREA
00087  *                    or: GV_POINT | GV_LINE | GV_BOUNDARY | GV_CENTROID  
00088  *
00089  *  Array is not reset to zero before, but old values (if any > 0) are overwritten.
00090  * 
00091  *  Return: number of items set
00092  *          -1 on error
00093  */
00094 int 
00095 Vect_set_varray_from_cat_list ( struct Map_info *Map, int field, struct cat_list *clist,
00096                                 int type, int value, VARRAY *varray )
00097 {
00098     int i, n, centr, cat;
00099     int ni = 0; /* number of items set */
00100     int ltype; /* line type */
00101     struct line_cats *Cats;
00102 
00103     G_debug (4, "Vect_set_varray_from_cat_list(): field = %d", field);
00104     
00105     /* Check type */
00106     if ( (type & GV_AREA) && (type & (GV_POINTS | GV_LINES)) ) {
00107         G_warning ("Mixed area and other type requested for vector array.");
00108         return 0;
00109     }
00110     
00111     Cats = Vect_new_cats_struct ();
00112     
00113     if ( type & GV_AREA ) { /* Areas */
00114         n = Vect_get_num_areas (Map);
00115         
00116         if ( n > varray->size ) { /* not enough space */
00117             G_warning ("Not enough space in vector array.");
00118             return 0;
00119         }
00120             
00121         for ( i = 1; i <= n; i++ ) {
00122             centr = Vect_get_area_centroid ( Map, i );
00123             if ( centr <= 0 ) continue; /* No centroid */
00124             
00125             Vect_read_line (Map, NULL, Cats, centr);
00126             if ( !Vect_cat_get(Cats, field, &cat) ) continue; /* No such field */
00127             
00128             if ( Vect_cat_in_cat_list (cat, clist) ) { /* cat is in list */
00129                 varray->c[i] = value;
00130                 ni++;
00131             }
00132         }
00133     } else { /* Lines */
00134         n = Vect_get_num_lines (Map);
00135         
00136         if ( n > varray->size ) { /* not enough space */
00137             G_warning ("Not enough space in vector array.");
00138             return 0;
00139         }
00140             
00141         for ( i = 1; i <= n; i++ ) {
00142             ltype = Vect_read_line (Map, NULL, Cats, i);
00143         
00144             if ( !(ltype & type) ) continue; /* is not specified type */
00145             
00146             if ( !Vect_cat_get(Cats, field, &cat) ) continue; /* No such field */
00147 
00148             if ( Vect_cat_in_cat_list (cat, clist) ) { /* cat is in list */
00149                 varray->c[i] = value;
00150                 ni++;
00151             }
00152         }
00153 
00154     }
00155 
00156     Vect_destroy_cats_struct (Cats);
00157 
00158     return ni;
00159 }
00160 
00161 /* compare 2 integers in array */
00162 int cmp ( const void *pa, const void *pb)
00163 {
00164     int *p1 = (int *) pa;
00165     int *p2 = (int *) pb;
00166              
00167     if( *p1 < *p2 ) return -1;
00168     if( *p1 > *p2 ) return 1;
00169     return 0;
00170 }
00171 
00172 /* check if cat is in array */
00173 int
00174 in_array ( int *cats, int ncats, int cat ) 
00175 {
00176     int *p;
00177     
00178     p = (int *) bsearch((void *) &cat, cats, ncats, sizeof(int), cmp); 
00179 
00180     if ( p == NULL ) return 0;
00181     return 1;
00182 }
00183 
00184 /* 
00185  *  Set values in 'varray' to 'value' if category of object of given type is in 
00186  *  categories selected from DB based on where statement (given without where).
00187  *  'type' may be either: GV_AREA
00188  *                    or: GV_POINT | GV_LINE | GV_BOUNDARY | GV_CENTROID  
00189  *
00190  *  Array is not reset to zero before, but old values (if any > 0) are overwritten.
00191  * 
00192  *  Return: number of items set
00193  *          -1 on error
00194  */
00195 int 
00196 Vect_set_varray_from_db ( struct Map_info *Map, int field, char *where,
00197                                 int type, int value, VARRAY *varray )
00198 {
00199     int i, n, c, centr, cat, *cats, ncats;
00200     int ni = 0; /* number of items set */
00201     int ltype; /* line type */
00202     struct line_cats *Cats;
00203     struct field_info *Fi;
00204     dbDriver *driver;
00205 
00206     G_debug (4, "Vect_set_varray_from_db(): field = %d where = '%s'", field, where);
00207 
00208     /* Note: use category index once available */
00209     
00210     /* Check type */
00211     if ( (type & GV_AREA) && (type & (GV_POINTS | GV_LINES)) ) {
00212         G_warning ("Mixed area and other type requested for vector array.");
00213         return 0;
00214     }
00215     
00216     Cats = Vect_new_cats_struct ();
00217 
00218     /* Select categories from DB to array */
00219     Fi = Vect_get_field ( Map, field);
00220     if ( Fi == NULL ) {
00221         G_warning ( "Cannot get field info" );
00222         return -1;
00223     }
00224     
00225     driver = db_start_driver_open_database ( Fi->driver, Fi->database );
00226     if ( driver == NULL ) {
00227         G_warning ( "Cannot open database" );
00228         return -1;
00229     }
00230         
00231     ncats = db_select_int( driver, Fi->table, Fi->key, where, &cats);
00232 
00233     db_close_database_shutdown_driver ( driver );
00234 
00235     if ( type & GV_AREA ) { /* Areas */
00236         n = Vect_get_num_areas (Map);
00237         
00238         if ( n > varray->size ) { /* not enough space */
00239             G_warning ("Not enough space in vector array.");
00240             return 0;
00241         }
00242             
00243         for ( i = 1; i <= n; i++ ) {
00244             centr = Vect_get_area_centroid ( Map, i );
00245             if ( centr <= 0 ) continue; /* No centroid */
00246             
00247             Vect_read_line (Map, NULL, Cats, centr);
00248             /*if ( !Vect_cat_get(Cats, field, &cat) ) continue; No such field */
00249             for (c = 0; c < Cats->n_cats; c++) {
00250               if (Cats->field[c] == field && in_array ( cats, ncats, Cats->cat[c] )) {
00251                 cat = Cats->cat[c];
00252                 varray->c[i] = value;
00253                 ni++;
00254                 break;
00255               }
00256             }
00257 
00258             /*
00259             if ( in_array ( cats, ncats, cat ) ) {
00260                 varray->c[i] = value;
00261                 ni++;
00262             }
00263             */
00264         }
00265     } else { /* Lines */
00266         n = Vect_get_num_lines (Map);
00267         
00268         if ( n > varray->size ) { /* not enough space */
00269             G_warning ("Not enough space in vector array.");
00270             return 0;
00271         }
00272             
00273         for ( i = 1; i <= n; i++ ) {
00274             ltype = Vect_read_line (Map, NULL, Cats, i);
00275         
00276             if ( !(ltype & type) ) continue; /* is not specified type */
00277             
00278             /* if ( !Vect_cat_get(Cats, field, &cat) ) continue;  No such field */
00279             for (c = 0; c < Cats->n_cats; c++) {
00280               if (Cats->field[c] == field && in_array ( cats, ncats, Cats->cat[c] )) {
00281                 cat = Cats->cat[c];
00282                 varray->c[i] = value;
00283                 ni++;
00284                 break;
00285               }
00286             }
00287             /*
00288             if ( in_array ( cats, ncats, cat ) ) {
00289                 varray->c[i] = value;
00290                 ni++;
00291             }
00292             */
00293         }
00294 
00295     }
00296 
00297     G_free ( cats );
00298     Vect_destroy_cats_struct (Cats);
00299 
00300     return ni;
00301 }
00302 

Generated on Sat Jul 22 22:05:56 2006 for GRASS by  doxygen 1.4.7