cindex.c

Go to the documentation of this file.
00001 /*****************************************************************************
00002 *
00003 * MODULE:       Vector library 
00004 *               
00005 * AUTHOR(S):    Radim Blazek
00006 *
00007 * PURPOSE:      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 <string.h>
00018 #include <sys/types.h>
00019 #include <sys/stat.h>
00020 #include <unistd.h>
00021 #include "gis.h"
00022 #include "Vect.h"
00023 
00024 static void check_status ( struct Map_info *Map ){
00025     if ( !Map->plus.cidx_up_to_date ) 
00026         G_fatal_error("Category index is not up to date");
00027 }
00028 
00035 int 
00036 Vect_cidx_get_num_fields ( struct Map_info *Map ) 
00037 {
00038     check_status ( Map );
00039 
00040     return ( Map->plus.n_cidx );
00041 }
00042 
00050 int 
00051 Vect_cidx_get_field_number ( struct Map_info *Map, int index ) 
00052 {
00053     check_status ( Map );
00054 
00055     if ( index >= Map->plus.n_cidx )
00056         G_fatal_error("Field index >= number of fields");
00057     
00058     return ( Map->plus.cidx[index].field );
00059 }
00060 
00068 int 
00069 Vect_cidx_get_field_index ( struct Map_info *Map, int field ) 
00070 {
00071     int i;
00072     struct Plus_head *Plus ;
00073     
00074     G_debug (2, "Vect_cidx_get_field_index() field = %d", field); 
00075 
00076     check_status ( Map );
00077     Plus = &(Map->plus);
00078 
00079     for ( i = 0; i < Plus->n_cidx; i++ ) {
00080         if (  Plus->cidx[i].field == field )
00081             return i;
00082     }
00083 
00084     return (-1);
00085 }
00086 
00094 int 
00095 Vect_cidx_get_num_unique_cats_by_index ( struct Map_info *Map, int index ) 
00096 {
00097     check_status ( Map );
00098     if ( index >= Map->plus.n_cidx )
00099         G_fatal_error("Field index >= number of fields");
00100 
00101     return ( Map->plus.cidx[index].n_ucats );
00102 }
00103 
00111 int 
00112 Vect_cidx_get_num_cats_by_index ( struct Map_info *Map, int index ) 
00113 {
00114     check_status ( Map );
00115     if ( index >= Map->plus.n_cidx )
00116         G_fatal_error("Field index >= number of fields");
00117 
00118     return ( Map->plus.cidx[index].n_cats );
00119 }
00120 
00128 int 
00129 Vect_cidx_get_num_types_by_index ( struct Map_info *Map, int field_index ) 
00130 {
00131     check_status ( Map );
00132     if ( field_index >= Map->plus.n_cidx )
00133         G_fatal_error("Field index >= number of fields");
00134 
00135     return ( Map->plus.cidx[field_index].n_types );
00136 }
00137 
00147 int 
00148 Vect_cidx_get_type_count_by_index ( struct Map_info *Map, int field_index, int type_index, int *type, int *count) 
00149 {
00150     check_status ( Map );
00151     if ( field_index >= Map->plus.n_cidx )
00152         G_fatal_error("Field index >= number of fields");
00153 
00154     *type = Map->plus.cidx[field_index].type[type_index][0];
00155     *count = Map->plus.cidx[field_index].type[type_index][1];
00156     
00157     return (1);
00158 }
00159 
00168 int 
00169 Vect_cidx_get_type_count ( struct Map_info *Map, int field, int type) 
00170 {
00171     int i, fi, count = 0;
00172 
00173     G_debug (3, "Vect_cidx_get_type_count() field = %d, type = %d", field, type); 
00174     
00175     check_status ( Map );
00176     
00177     if ( (fi = Vect_cidx_get_field_index(Map, field)) < 0 ) return 0;  /* field not found */
00178     G_debug (3, "field_index = %d", fi); 
00179     
00180     G_debug (3, "ntypes = %d", Map->plus.cidx[fi].n_types); 
00181     for ( i = 0; i < Map->plus.cidx[fi].n_types; i++ ) {
00182         int tp, cnt;
00183            
00184         tp = Map->plus.cidx[fi].type[i][0];
00185         cnt = Map->plus.cidx[fi].type[i][1];        
00186         if ( tp & type ) count += cnt;
00187         G_debug (3, "%d tp = %d, cnt= %d count = %d", i, tp, cnt, count); 
00188     }
00189     
00190     return (count);
00191 }
00192 
00206 int 
00207 Vect_cidx_get_cat_by_index ( struct Map_info *Map, int field_index, int cat_index, 
00208                              int *cat, int *type, int * id)
00209 {
00210     check_status ( Map ); /* This check is slow ? */
00211 
00212     if ( field_index >= Map->plus.n_cidx || field_index < 0 ||  cat_index >= Map->plus.cidx[field_index].n_cats )
00213         G_fatal_error("Field/cat index out of range");
00214 
00215     *cat = Map->plus.cidx[field_index].cat[cat_index][0];
00216     *type = Map->plus.cidx[field_index].cat[cat_index][1];
00217     *id = Map->plus.cidx[field_index].cat[cat_index][2];
00218 
00219     return 1;
00220 }
00221 
00222 /* Compare by cat */
00223 static int cmp_cat ( const void *pa, const void *pb )
00224 {
00225     int *p1 = (int*) pa;
00226     int *p2 = (int*) pb;
00227 
00228     if ( *p1 < p2[0] ) return -1;
00229     if ( *p1 > p2[0] ) return 1;
00230     return 0;
00231 }   
00232 
00247 int 
00248 Vect_cidx_find_next ( struct Map_info *Map, int field_index, int cat, int type_mask,
00249                                   int start_index, int *type, int *id )
00250 {
00251     int    *catp, cat_index;
00252     struct Cat_index *ci;
00253 
00254     G_debug (3, "Vect_cidx_find_next() cat = %d, type_mask = %d, start_index = %d", cat, type_mask, start_index);
00255 
00256     check_status ( Map ); /* This check is slow ? */
00257     *type = *id = 0;
00258 
00259     if ( field_index >= Map->plus.n_cidx )
00260         G_fatal_error("Field index out of range");
00261 
00262     if ( start_index < 0 ) start_index = 0;
00263     if ( start_index >= Map->plus.cidx[field_index].n_cats ) return -1; /* outside range */
00264     
00265     /* pointer to beginning of searched part of category index */
00266     ci = &(Map->plus.cidx[field_index]);
00267 
00268     catp = bsearch ( &cat, ci->cat + start_index * 3 * sizeof(int), ci->n_cats - start_index, 
00269                      3 * sizeof(int), cmp_cat);
00270 
00271     G_debug (3, "catp = %p", catp);
00272     if ( !catp ) return -1;
00273 
00274     /* get index from pointer, the difference between pointers is using sizeof(int) !!! */
00275     cat_index = (catp - (int *)ci->cat) / 3;
00276     
00277     do {
00278         G_debug (3, "  cat_index = %d", cat_index);
00279         if ( ci->cat[cat_index][1] & type_mask ) {
00280             *type = ci->cat[cat_index][1];
00281             *id = ci->cat[cat_index][2];
00282             G_debug (3, "  type match -> record found");
00283             return cat_index;
00284         }
00285         cat_index++;
00286     } while ( cat_index < ci->n_cats );
00287     
00288     return -1;
00289 }
00290 
00291 #define SEP "------------------------------------------------------------------------------------------\n"
00292 
00300 int 
00301 Vect_cidx_dump ( struct Map_info *Map, FILE *out ) 
00302 {
00303     int i, field, nfields, ntypes;
00304 
00305     G_debug ( 2, "Vect_cidx_dump()"); 
00306     
00307     check_status ( Map );
00308 
00309     nfields = Vect_cidx_get_num_fields ( Map );
00310     fprintf (out, "---------- CATEGORY INDEX DUMP: Number of layers: %d "
00311                   "--------------------------------------\n", nfields );
00312     
00313     for (i = 0; i < nfields; i++ ) {
00314         int j, nucats, ncats; 
00315         
00316         field = Vect_cidx_get_field_number ( Map, i );
00317         nucats = Vect_cidx_get_num_unique_cats_by_index ( Map, i );
00318         ncats = Vect_cidx_get_num_cats_by_index ( Map, i );
00319         ntypes = Vect_cidx_get_num_types_by_index ( Map, i );
00320 
00321         fprintf (out, "Field %6d  number of unique cats: %7d  number of cats: %7d  number of types: %d\n", 
00322                                field, nucats, ncats, ntypes ); 
00323         fprintf (out, SEP);
00324         
00325         fprintf (out, "            type |     count\n" );
00326         for ( j = 0; j < ntypes; j++ ) {
00327             int type, count;
00328             Vect_cidx_get_type_count_by_index ( Map, i, j, &type, &count );
00329             fprintf (out, "           %5d | %9d\n", type, count );
00330         }
00331         
00332         fprintf (out, " category | type | line/area\n" );
00333         for ( j = 0; j < ncats; j++ ) {
00334             int cat, type, id; 
00335             Vect_cidx_get_cat_by_index ( Map, i, j, &cat, &type, &id );
00336             fprintf (out, "%9d | %4d | %9d\n", cat, type, id );
00337         }
00338     
00339         fprintf (out, SEP);
00340     }
00341 
00342     return 1;
00343 }
00344 
00352 int 
00353 Vect_cidx_save ( struct Map_info *Map ) 
00354 {
00355     struct Plus_head *plus ;
00356     char   fname[1024], buf[1024];
00357     GVFILE  fp;
00358 
00359     G_debug (2, "Vect_cidx_save()"); 
00360     check_status ( Map );
00361 
00362     plus = &(Map->plus);
00363     
00364     sprintf (buf, "%s/%s", GRASS_VECT_DIRECTORY, Map->name);
00365     G__file_name (fname, buf, GV_CIDX_ELEMENT, Map->mapset);
00366     G_debug (2, "Open cidx: %s", fname);
00367     dig_file_init ( &fp );
00368     fp.file = fopen( fname, "w");
00369     if ( fp.file ==  NULL) {
00370         G_warning("Can't open cidx file for write: %s\n", fname);
00371         return 1;
00372     }
00373 
00374     /* set portable info */
00375     dig_init_portable ( &(plus->cidx_port), dig__byte_order_out ());
00376 
00377     if ( 0 > dig_write_cidx (&fp, plus) ) {
00378         G_warning ("Error writing out category index file.\n");
00379         return 1;
00380     }
00381     
00382     fclose( fp.file );
00383 
00384     return 0;
00385 }
00386 
00395 int 
00396 Vect_cidx_open ( struct Map_info *Map, int head_only ) 
00397 {
00398     int ret;
00399     char buf[500], file_path[2000];
00400     GVFILE fp;
00401     struct Plus_head *Plus;
00402     struct stat info;
00403     
00404     G_debug (2, "Vect_cidx_open(): name = %s mapset= %s", Map->name, Map->mapset);
00405 
00406     Plus = &(Map->plus);
00407     
00408     sprintf (buf, "%s/%s", GRASS_VECT_DIRECTORY, Map->name);
00409     G__file_name ( file_path, buf, GV_CIDX_ELEMENT, Map->mapset);
00410 
00411     if (stat (file_path, &info) != 0) /* does not exist */
00412         return 1;
00413         
00414 
00415     dig_file_init ( &fp );
00416     fp.file = G_fopen_old (buf, GV_CIDX_ELEMENT, Map->mapset);
00417 
00418     if ( fp.file == NULL ) { /* category index file is not available */
00419         G_warning( "Cannot open category index file for vector '%s@%s'.", Map->name, Map->mapset);
00420         return -1;
00421     }
00422   
00423     /* load category index to memory */
00424     dig_cidx_init ( Plus);
00425     ret = dig_read_cidx ( &fp, Plus, head_only );
00426     
00427     fclose ( fp.file );  
00428     
00429     if ( ret == 1 ) {
00430         G_debug (3, "Cannot read cidx");
00431         return -1;
00432     }
00433 
00434     return 0;
00435 }
00436 

Generated on Mon Jan 1 19:49:16 2007 for GRASS by  doxygen 1.5.1