00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
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;
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 );
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
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 );
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;
00268
00269
00270 ci = &(Map->plus.cidx[field_index]);
00271
00272
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
00281 cat_index = (catp - (int *)ci->cat) / 3;
00282
00283 G_debug (4, "cat_index = %d", cat_index);
00284
00285
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
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)
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 ) {
00436 G_warning( "Cannot open category index file for vector '%s@%s'.", Map->name, Map->mapset);
00437 return -1;
00438 }
00439
00440
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