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 "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;
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 );
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
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 );
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;
00264
00265
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
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
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)
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 ) {
00419 G_warning( "Cannot open category index file for vector '%s@%s'.", Map->name, Map->mapset);
00420 return -1;
00421 }
00422
00423
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