GRASS Programmer's Manual 6.4.1(2011)
Vlib/cindex.c
Go to the documentation of this file.
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 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines