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;
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);
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
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);
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;
00289
00290
00291 ci = &(Map->plus.cidx[field_index]);
00292
00293
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
00303 cat_index = (catp - (int *)ci->cat) / 3;
00304
00305 G_debug(4, "cat_index = %d", cat_index);
00306
00307
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
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
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)
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) {
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
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 }