GRASS Programmer's Manual 6.4.1(2011)
|
00001 00017 #include <stdlib.h> 00018 #include <string.h> 00019 #include <sys/types.h> 00020 #include <sys/stat.h> 00021 #include <unistd.h> 00022 #include <grass/gis.h> 00023 #include <grass/Vect.h> 00024 #include <grass/glocale.h> 00025 00026 static int cmp_cat(const void *pa, const void *pb); 00027 00028 static void check_status(struct Map_info *Map) 00029 { 00030 if (!Map->plus.cidx_up_to_date) 00031 G_fatal_error(_("Category index is not up to date")); 00032 } 00033 00041 int Vect_cidx_get_num_fields(struct Map_info *Map) 00042 { 00043 check_status(Map); 00044 00045 return (Map->plus.n_cidx); 00046 } 00047 00056 int Vect_cidx_get_field_number(struct Map_info *Map, int index) 00057 { 00058 check_status(Map); 00059 00060 if (index >= Map->plus.n_cidx) 00061 G_fatal_error(_("Invalid layer index (index >= number of layers)")); 00062 00063 return (Map->plus.cidx[index].field); 00064 } 00065 00075 int Vect_cidx_get_field_index(struct Map_info *Map, int field) 00076 { 00077 int i; 00078 struct Plus_head *Plus; 00079 00080 G_debug(2, "Vect_cidx_get_field_index() field = %d", field); 00081 00082 check_status(Map); 00083 Plus = &(Map->plus); 00084 00085 for (i = 0; i < Plus->n_cidx; i++) { 00086 if (Plus->cidx[i].field == field) 00087 return i; 00088 } 00089 00090 return (-1); 00091 } 00092 00102 int Vect_cidx_get_num_unique_cats_by_index(struct Map_info *Map, int index) 00103 { 00104 check_status(Map); 00105 00106 if (index < 0 || index >= Map->plus.n_cidx) 00107 G_fatal_error(_("Invalid layer index (index < 0 or index >= number of layers)")); 00108 00109 return (Map->plus.cidx[index].n_ucats); 00110 } 00111 00121 int Vect_cidx_get_num_cats_by_index(struct Map_info *Map, int index) 00122 { 00123 check_status(Map); 00124 if (index >= Map->plus.n_cidx) 00125 G_fatal_error(_("Invalid layer index (index >= number of layers)")); 00126 00127 return (Map->plus.cidx[index].n_cats); 00128 } 00129 00139 int Vect_cidx_get_num_types_by_index(struct Map_info *Map, int field_index) 00140 { 00141 check_status(Map); 00142 if (field_index >= Map->plus.n_cidx) 00143 G_fatal_error(_("Invalid layer index (index >= number of layers)")); 00144 00145 return (Map->plus.cidx[field_index].n_types); 00146 } 00147 00160 int 00161 Vect_cidx_get_type_count_by_index(struct Map_info *Map, int field_index, 00162 int type_index, int *type, int *count) 00163 { 00164 check_status(Map); 00165 if (field_index >= Map->plus.n_cidx) 00166 G_fatal_error(_("Invalid layer index (index >= number of layers)")); 00167 00168 *type = Map->plus.cidx[field_index].type[type_index][0]; 00169 *count = Map->plus.cidx[field_index].type[type_index][1]; 00170 00171 return (1); 00172 } 00173 00184 int Vect_cidx_get_type_count(struct Map_info *Map, int field, int type) 00185 { 00186 int i, fi, count = 0; 00187 00188 G_debug(3, "Vect_cidx_get_type_count() field = %d, type = %d", field, 00189 type); 00190 00191 check_status(Map); 00192 00193 if ((fi = Vect_cidx_get_field_index(Map, field)) < 0) 00194 return 0; /* field not found */ 00195 G_debug(3, "field_index = %d", fi); 00196 00197 G_debug(3, "ntypes = %d", Map->plus.cidx[fi].n_types); 00198 for (i = 0; i < Map->plus.cidx[fi].n_types; i++) { 00199 int tp, cnt; 00200 00201 tp = Map->plus.cidx[fi].type[i][0]; 00202 cnt = Map->plus.cidx[fi].type[i][1]; 00203 if (tp & type) 00204 count += cnt; 00205 G_debug(3, "%d tp = %d, cnt= %d count = %d", i, tp, cnt, count); 00206 } 00207 00208 return (count); 00209 } 00210 00224 int 00225 Vect_cidx_get_cat_by_index(struct Map_info *Map, int field_index, 00226 int cat_index, int *cat, int *type, int *id) 00227 { 00228 check_status(Map); /* This check is slow ? */ 00229 00230 if (field_index >= Map->plus.n_cidx || field_index < 0 || 00231 cat_index >= Map->plus.cidx[field_index].n_cats) 00232 G_fatal_error(_("Layer or category index out of range")); 00233 00234 *cat = Map->plus.cidx[field_index].cat[cat_index][0]; 00235 *type = Map->plus.cidx[field_index].cat[cat_index][1]; 00236 *id = Map->plus.cidx[field_index].cat[cat_index][2]; 00237 00238 return 1; 00239 } 00240 00241 /* Compare by cat */ 00242 static int cmp_cat(const void *pa, const void *pb) 00243 { 00244 int *p1 = (int *)pa; 00245 int *p2 = (int *)pb; 00246 00247 if (*p1 < p2[0]) 00248 return -1; 00249 if (*p1 > p2[0]) 00250 return 1; 00251 return 0; 00252 } 00253 00268 int 00269 Vect_cidx_find_next(struct Map_info *Map, int field_index, int cat, 00270 int type_mask, int start_index, int *type, int *id) 00271 { 00272 int *catp, cat_index; 00273 struct Cat_index *ci; 00274 00275 G_debug(3, 00276 "Vect_cidx_find_next() cat = %d, type_mask = %d, start_index = %d", 00277 cat, type_mask, start_index); 00278 00279 check_status(Map); /* This check is slow ? */ 00280 *type = *id = 0; 00281 00282 if (field_index >= Map->plus.n_cidx) 00283 G_fatal_error(_("Layer index out of range")); 00284 00285 if (start_index < 0) 00286 start_index = 0; 00287 if (start_index >= Map->plus.cidx[field_index].n_cats) 00288 return -1; /* outside range */ 00289 00290 /* pointer to beginning of searched part of category index */ 00291 ci = &(Map->plus.cidx[field_index]); 00292 00293 /* calc with pointers is using sizeof(int) !!! */ 00294 catp = bsearch(&cat, (int *)ci->cat + start_index * 3, 00295 (size_t) ci->n_cats - start_index, 00296 3 * sizeof(int), cmp_cat); 00297 00298 G_debug(3, "catp = %p", catp); 00299 if (!catp) 00300 return -1; 00301 00302 /* get index from pointer, the difference between pointers is using sizeof(int) !!! */ 00303 cat_index = (catp - (int *)ci->cat) / 3; 00304 00305 G_debug(4, "cat_index = %d", cat_index); 00306 00307 /* Go down to the first if multiple */ 00308 while (cat_index > start_index) { 00309 if (ci->cat[cat_index - 1][0] != cat) { 00310 break; 00311 } 00312 cat_index--; 00313 } 00314 G_debug(4, "cat_index = %d", cat_index); 00315 00316 do { 00317 G_debug(3, " cat_index = %d", cat_index); 00318 if (ci->cat[cat_index][0] == cat && ci->cat[cat_index][1] & type_mask) { 00319 *type = ci->cat[cat_index][1]; 00320 *id = ci->cat[cat_index][2]; 00321 G_debug(3, " type match -> record found"); 00322 return cat_index; 00323 } 00324 cat_index++; 00325 } while (cat_index < ci->n_cats); 00326 00327 return -1; 00328 } 00329 00330 00342 void Vect_cidx_find_all(struct Map_info *Map, int layer, int type_mask, 00343 int cat, struct ilist *lines) 00344 { 00345 int type, line; 00346 struct Cat_index *ci; 00347 int field_index, idx; 00348 00349 Vect_reset_list(lines); 00350 field_index = Vect_cidx_get_field_index(Map, layer); 00351 00352 if (field_index == -1) { 00353 /* not found */ 00354 return; 00355 } 00356 ci = &(Map->plus.cidx[field_index]); 00357 00358 idx = Vect_cidx_find_next(Map, field_index, cat, 00359 type_mask, 0, &type, &line); 00360 00361 if (idx == -1) { 00362 return; 00363 } 00364 00365 do { 00366 if (!(ci->cat[idx][1] & type_mask) 00367 || ci->cat[idx][0] != cat) { 00368 break; 00369 } 00370 Vect_list_append(lines, ci->cat[idx][2]); 00371 idx++; 00372 } while (idx < ci->n_cats); 00373 return; 00374 } 00375 00376 00377 #define SEP "------------------------------------------------------------------------------------------\n" 00378 00388 int Vect_cidx_dump(struct Map_info *Map, FILE * out) 00389 { 00390 int i, field, nfields, ntypes; 00391 00392 G_debug(2, "Vect_cidx_dump()"); 00393 00394 check_status(Map); 00395 00396 nfields = Vect_cidx_get_num_fields(Map); 00397 fprintf(out, "---------- CATEGORY INDEX DUMP: Number of layers: %d " 00398 "--------------------------------------\n", nfields); 00399 00400 for (i = 0; i < nfields; i++) { 00401 int j, nucats, ncats; 00402 00403 field = Vect_cidx_get_field_number(Map, i); 00404 nucats = Vect_cidx_get_num_unique_cats_by_index(Map, i); 00405 ncats = Vect_cidx_get_num_cats_by_index(Map, i); 00406 ntypes = Vect_cidx_get_num_types_by_index(Map, i); 00407 00408 fprintf(out, 00409 "Layer %6d number of unique cats: %7d number of cats: %7d number of types: %d\n", 00410 field, nucats, ncats, ntypes); 00411 fprintf(out, SEP); 00412 00413 fprintf(out, " type | count\n"); 00414 for (j = 0; j < ntypes; j++) { 00415 int type, count; 00416 00417 Vect_cidx_get_type_count_by_index(Map, i, j, &type, &count); 00418 fprintf(out, " %5d | %9d\n", type, count); 00419 } 00420 00421 fprintf(out, " category | type | line/area\n"); 00422 for (j = 0; j < ncats; j++) { 00423 int cat, type, id; 00424 00425 Vect_cidx_get_cat_by_index(Map, i, j, &cat, &type, &id); 00426 fprintf(out, "%9d | %4d | %9d\n", cat, type, id); 00427 } 00428 00429 fprintf(out, SEP); 00430 } 00431 00432 return 1; 00433 } 00434 00443 int Vect_cidx_save(struct Map_info *Map) 00444 { 00445 struct Plus_head *plus; 00446 char fname[1024], buf[1024]; 00447 GVFILE fp; 00448 00449 G_debug(2, "Vect_cidx_save()"); 00450 check_status(Map); 00451 00452 plus = &(Map->plus); 00453 00454 sprintf(buf, "%s/%s", GRASS_VECT_DIRECTORY, Map->name); 00455 G__file_name(fname, buf, GV_CIDX_ELEMENT, Map->mapset); 00456 G_debug(2, "Open cidx: %s", fname); 00457 dig_file_init(&fp); 00458 fp.file = fopen(fname, "w"); 00459 if (fp.file == NULL) { 00460 G_warning(_("Unable to open cidx file <%s> for write"), fname); 00461 return 1; 00462 } 00463 00464 /* set portable info */ 00465 dig_init_portable(&(plus->cidx_port), dig__byte_order_out()); 00466 00467 if (0 > dig_write_cidx(&fp, plus)) { 00468 G_warning(_("Error writing out category index file <%s>"), fname); 00469 return 1; 00470 } 00471 00472 fclose(fp.file); 00473 00474 return 0; 00475 } 00476 00487 int Vect_cidx_open(struct Map_info *Map, int head_only) 00488 { 00489 int ret; 00490 char buf[500], file_path[2000]; 00491 GVFILE fp; 00492 struct Plus_head *Plus; 00493 struct stat info; 00494 00495 G_debug(2, "Vect_cidx_open(): name = %s mapset= %s", Map->name, 00496 Map->mapset); 00497 00498 Plus = &(Map->plus); 00499 00500 sprintf(buf, "%s/%s", GRASS_VECT_DIRECTORY, Map->name); 00501 G__file_name(file_path, buf, GV_CIDX_ELEMENT, Map->mapset); 00502 00503 if (stat(file_path, &info) != 0) /* does not exist */ 00504 return 1; 00505 00506 00507 dig_file_init(&fp); 00508 fp.file = G_fopen_old(buf, GV_CIDX_ELEMENT, Map->mapset); 00509 00510 if (fp.file == NULL) { /* category index file is not available */ 00511 G_warning(_("Unable to open category index file for vector map <%s@%s>"), 00512 Map->name, Map->mapset); 00513 return -1; 00514 } 00515 00516 /* load category index to memory */ 00517 dig_cidx_init(Plus); 00518 ret = dig_read_cidx(&fp, Plus, head_only); 00519 00520 fclose(fp.file); 00521 00522 if (ret == 1) { 00523 G_debug(3, "Cannot read cidx"); 00524 return -1; 00525 } 00526 00527 return 0; 00528 }