Vlib/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 <grass/gis.h>
00022 #include <grass/Vect.h>
00023 
00024 
00025 static int cmp_cat(const void *pa, const void *pb);
00026 
00027 
00028 static void check_status ( struct Map_info *Map ){
00029     if ( !Map->plus.cidx_up_to_date ) 
00030         G_fatal_error("Category index is not up to date");
00031 }
00032 
00039 int 
00040 Vect_cidx_get_num_fields ( struct Map_info *Map ) 
00041 {
00042     check_status ( Map );
00043 
00044     return ( Map->plus.n_cidx );
00045 }
00046 
00054 int 
00055 Vect_cidx_get_field_number ( struct Map_info *Map, int index ) 
00056 {
00057     check_status ( Map );
00058 
00059     if ( index >= Map->plus.n_cidx )
00060         G_fatal_error("Field index >= number of fields");
00061     
00062     return ( Map->plus.cidx[index].field );
00063 }
00064 
00072 int 
00073 Vect_cidx_get_field_index ( struct Map_info *Map, int field ) 
00074 {
00075     int i;
00076     struct Plus_head *Plus ;
00077     
00078     G_debug (2, "Vect_cidx_get_field_index() field = %d", field); 
00079 
00080     check_status ( Map );
00081     Plus = &(Map->plus);
00082 
00083     for ( i = 0; i < Plus->n_cidx; i++ ) {
00084         if (  Plus->cidx[i].field == field )
00085             return i;
00086     }
00087 
00088     return (-1);
00089 }
00090 
00098 int 
00099 Vect_cidx_get_num_unique_cats_by_index ( struct Map_info *Map, int index ) 
00100 {
00101     check_status ( Map );
00102     if ( index >= Map->plus.n_cidx )
00103         G_fatal_error("Field index >= number of fields");
00104 
00105     return ( Map->plus.cidx[index].n_ucats );
00106 }
00107 
00115 int 
00116 Vect_cidx_get_num_cats_by_index ( struct Map_info *Map, int index ) 
00117 {
00118     check_status ( Map );
00119     if ( index >= Map->plus.n_cidx )
00120         G_fatal_error("Field index >= number of fields");
00121 
00122     return ( Map->plus.cidx[index].n_cats );
00123 }
00124 
00132 int 
00133 Vect_cidx_get_num_types_by_index ( struct Map_info *Map, int field_index ) 
00134 {
00135     check_status ( Map );
00136     if ( field_index >= Map->plus.n_cidx )
00137         G_fatal_error("Field index >= number of fields");
00138 
00139     return ( Map->plus.cidx[field_index].n_types );
00140 }
00141 
00151 int 
00152 Vect_cidx_get_type_count_by_index ( struct Map_info *Map, int field_index, int type_index, int *type, int *count) 
00153 {
00154     check_status ( Map );
00155     if ( field_index >= Map->plus.n_cidx )
00156         G_fatal_error("Field index >= number of fields");
00157 
00158     *type = Map->plus.cidx[field_index].type[type_index][0];
00159     *count = Map->plus.cidx[field_index].type[type_index][1];
00160     
00161     return (1);
00162 }
00163 
00172 int 
00173 Vect_cidx_get_type_count ( struct Map_info *Map, int field, int type) 
00174 {
00175     int i, fi, count = 0;
00176 
00177     G_debug (3, "Vect_cidx_get_type_count() field = %d, type = %d", field, type); 
00178     
00179     check_status ( Map );
00180     
00181     if ( (fi = Vect_cidx_get_field_index(Map, field)) < 0 ) return 0;  /* field not found */
00182     G_debug (3, "field_index = %d", fi); 
00183     
00184     G_debug (3, "ntypes = %d", Map->plus.cidx[fi].n_types); 
00185     for ( i = 0; i < Map->plus.cidx[fi].n_types; i++ ) {
00186         int tp, cnt;
00187            
00188         tp = Map->plus.cidx[fi].type[i][0];
00189         cnt = Map->plus.cidx[fi].type[i][1];        
00190         if ( tp & type ) count += cnt;
00191         G_debug (3, "%d tp = %d, cnt= %d count = %d", i, tp, cnt, count); 
00192     }
00193     
00194     return (count);
00195 }
00196 
00210 int 
00211 Vect_cidx_get_cat_by_index ( struct Map_info *Map, int field_index, int cat_index, 
00212                              int *cat, int *type, int * id)
00213 {
00214     check_status ( Map ); /* This check is slow ? */
00215 
00216     if ( field_index >= Map->plus.n_cidx || field_index < 0 ||  cat_index >= Map->plus.cidx[field_index].n_cats )
00217         G_fatal_error("Field/cat index out of range");
00218 
00219     *cat = Map->plus.cidx[field_index].cat[cat_index][0];
00220     *type = Map->plus.cidx[field_index].cat[cat_index][1];
00221     *id = Map->plus.cidx[field_index].cat[cat_index][2];
00222 
00223     return 1;
00224 }
00225 
00226 /* Compare by cat */
00227 static int cmp_cat ( const void *pa, const void *pb )
00228 {
00229     int *p1 = (int*) pa;
00230     int *p2 = (int*) pb;
00231 
00232     if ( *p1 < p2[0] ) return -1;
00233     if ( *p1 > p2[0] ) return 1;
00234     return 0;
00235 }   
00236 
00251 int 
00252 Vect_cidx_find_next ( struct Map_info *Map, int field_index, int cat, int type_mask,
00253                                   int start_index, int *type, int *id )
00254 {
00255     int    *catp, cat_index;
00256     struct Cat_index *ci;
00257 
00258     G_debug (3, "Vect_cidx_find_next() cat = %d, type_mask = %d, start_index = %d", cat, type_mask, start_index);
00259 
00260     check_status ( Map ); /* This check is slow ? */
00261     *type = *id = 0;
00262 
00263     if ( field_index >= Map->plus.n_cidx )
00264         G_fatal_error("Field index out of range");
00265 
00266     if ( start_index < 0 ) start_index = 0;
00267     if ( start_index >= Map->plus.cidx[field_index].n_cats ) return -1; /* outside range */
00268     
00269     /* pointer to beginning of searched part of category index */
00270     ci = &(Map->plus.cidx[field_index]);
00271 
00272     /* calc with pointers is using sizeof(int) !!! */
00273     catp = bsearch ( &cat, (int *)ci->cat + start_index * 3, 
00274                      (size_t)ci->n_cats - start_index, 
00275                      3 * sizeof(int), cmp_cat);
00276 
00277     G_debug (3, "catp = %p", catp);
00278     if ( !catp ) return -1;
00279 
00280     /* get index from pointer, the difference between pointers is using sizeof(int) !!! */
00281     cat_index = (catp - (int *)ci->cat) / 3;
00282     
00283     G_debug (4, "cat_index = %d", cat_index);
00284 
00285     /* Go down to the first if multiple */
00286     while ( cat_index > start_index ) {
00287         if ( ci->cat[cat_index-1][0] != cat ) {
00288             break;
00289         }
00290         cat_index--;
00291     }
00292     G_debug (4, "cat_index = %d", cat_index);
00293     
00294     do {
00295         G_debug (3, "  cat_index = %d", cat_index);
00296         if ( ci->cat[cat_index][0] == cat && ci->cat[cat_index][1] & type_mask ) {
00297             *type = ci->cat[cat_index][1];
00298             *id = ci->cat[cat_index][2];
00299             G_debug (3, "  type match -> record found");
00300             return cat_index;
00301         }
00302         cat_index++;
00303     } while ( cat_index < ci->n_cats );
00304     
00305     return -1;
00306 }
00307 
00308 #define SEP "------------------------------------------------------------------------------------------\n"
00309 
00317 int 
00318 Vect_cidx_dump ( struct Map_info *Map, FILE *out ) 
00319 {
00320     int i, field, nfields, ntypes;
00321 
00322     G_debug ( 2, "Vect_cidx_dump()"); 
00323     
00324     check_status ( Map );
00325 
00326     nfields = Vect_cidx_get_num_fields ( Map );
00327     fprintf (out, "---------- CATEGORY INDEX DUMP: Number of layers: %d "
00328                   "--------------------------------------\n", nfields );
00329     
00330     for (i = 0; i < nfields; i++ ) {
00331         int j, nucats, ncats; 
00332         
00333         field = Vect_cidx_get_field_number ( Map, i );
00334         nucats = Vect_cidx_get_num_unique_cats_by_index ( Map, i );
00335         ncats = Vect_cidx_get_num_cats_by_index ( Map, i );
00336         ntypes = Vect_cidx_get_num_types_by_index ( Map, i );
00337 
00338         fprintf (out, "Field %6d  number of unique cats: %7d  number of cats: %7d  number of types: %d\n", 
00339                                field, nucats, ncats, ntypes ); 
00340         fprintf (out, SEP);
00341         
00342         fprintf (out, "            type |     count\n" );
00343         for ( j = 0; j < ntypes; j++ ) {
00344             int type, count;
00345             Vect_cidx_get_type_count_by_index ( Map, i, j, &type, &count );
00346             fprintf (out, "           %5d | %9d\n", type, count );
00347         }
00348         
00349         fprintf (out, " category | type | line/area\n" );
00350         for ( j = 0; j < ncats; j++ ) {
00351             int cat, type, id; 
00352             Vect_cidx_get_cat_by_index ( Map, i, j, &cat, &type, &id );
00353             fprintf (out, "%9d | %4d | %9d\n", cat, type, id );
00354         }
00355     
00356         fprintf (out, SEP);
00357     }
00358 
00359     return 1;
00360 }
00361 
00369 int 
00370 Vect_cidx_save ( struct Map_info *Map ) 
00371 {
00372     struct Plus_head *plus ;
00373     char   fname[1024], buf[1024];
00374     GVFILE  fp;
00375 
00376     G_debug (2, "Vect_cidx_save()"); 
00377     check_status ( Map );
00378 
00379     plus = &(Map->plus);
00380     
00381     sprintf (buf, "%s/%s", GRASS_VECT_DIRECTORY, Map->name);
00382     G__file_name (fname, buf, GV_CIDX_ELEMENT, Map->mapset);
00383     G_debug (2, "Open cidx: %s", fname);
00384     dig_file_init ( &fp );
00385     fp.file = fopen( fname, "w");
00386     if ( fp.file ==  NULL) {
00387         G_warning("Can't open cidx file for write: %s\n", fname);
00388         return 1;
00389     }
00390 
00391     /* set portable info */
00392     dig_init_portable ( &(plus->cidx_port), dig__byte_order_out ());
00393 
00394     if ( 0 > dig_write_cidx (&fp, plus) ) {
00395         G_warning ("Error writing out category index file.\n");
00396         return 1;
00397     }
00398     
00399     fclose( fp.file );
00400 
00401     return 0;
00402 }
00403 
00412 int 
00413 Vect_cidx_open ( struct Map_info *Map, int head_only ) 
00414 {
00415     int ret;
00416     char buf[500], file_path[2000];
00417     GVFILE fp;
00418     struct Plus_head *Plus;
00419     struct stat info;
00420     
00421     G_debug (2, "Vect_cidx_open(): name = %s mapset= %s", Map->name, Map->mapset);
00422 
00423     Plus = &(Map->plus);
00424     
00425     sprintf (buf, "%s/%s", GRASS_VECT_DIRECTORY, Map->name);
00426     G__file_name ( file_path, buf, GV_CIDX_ELEMENT, Map->mapset);
00427 
00428     if (stat (file_path, &info) != 0) /* does not exist */
00429         return 1;
00430         
00431 
00432     dig_file_init ( &fp );
00433     fp.file = G_fopen_old (buf, GV_CIDX_ELEMENT, Map->mapset);
00434 
00435     if ( fp.file == NULL ) { /* category index file is not available */
00436         G_warning( "Cannot open category index file for vector '%s@%s'.", Map->name, Map->mapset);
00437         return -1;
00438     }
00439   
00440     /* load category index to memory */
00441     dig_cidx_init ( Plus);
00442     ret = dig_read_cidx ( &fp, Plus, head_only );
00443     
00444     fclose ( fp.file );  
00445     
00446     if ( ret == 1 ) {
00447         G_debug (3, "Cannot read cidx");
00448         return -1;
00449     }
00450 
00451     return 0;
00452 }
00453 

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