diglib/cindex.c

Go to the documentation of this file.
00001 
00002 /*****************************************************************************
00003 *
00004 * MODULE:       Vector library 
00005 *               
00006 * AUTHOR(S):    Radim Blazek
00007 *
00008 * PURPOSE:      Lower level functions for reading/writing/manipulating vectors.
00009 *
00010 * COPYRIGHT:    (C) 2001 by the GRASS Development Team
00011 *
00012 *               This program is free software under the GNU General Public
00013 *               License (>=v2). Read the file COPYING that comes with GRASS
00014 *               for details.
00015 *
00016 *****************************************************************************/
00017 #include <stdlib.h>
00018 #include <string.h>
00019 #include <grass/gis.h>
00020 #include <grass/Vect.h>
00021 
00022 /* 
00023  *  dig_cidx_init ()
00024  *  initit cat index
00025  *
00026  *  returns 1 OK
00027  *          0 on error      
00028  */
00029 int dig_cidx_init(struct Plus_head *Plus)
00030 {
00031     G_debug(3, "dig_cidx_init()");
00032 
00033     Plus->n_cidx = 0;
00034     Plus->a_cidx = 5;
00035     Plus->cidx =
00036         (struct Cat_index *)G_malloc(Plus->a_cidx * sizeof(struct Cat_index));
00037     if (!Plus->cidx)
00038         return 0;
00039     Plus->cidx_up_to_date = 0;
00040     return 1;
00041 }
00042 
00043 /* Free category index */
00044 void dig_cidx_free(struct Plus_head *Plus)
00045 {
00046     int i;
00047     struct Cat_index *ci;
00048 
00049     G_debug(2, "dig_cidx_free()");
00050     for (i = 0; i < Plus->n_cidx; i++) {
00051         ci = &(Plus->cidx[0]);
00052         G_free(ci->cat);
00053         ci->cat = NULL;
00054         ci->field = ci->n_cats = ci->a_cats = ci->n_types = 0;
00055     }
00056     Plus->n_cidx = 0;
00057     Plus->cidx_up_to_date = 0;
00058 }
00059 
00060 /* 
00061  *  dig_cidx_add_cat ()
00062  *  add new field - cat - line record, space is allocated if necessary 
00063  *
00064  *  returns 1 OK
00065  *          0 on error      
00066  */
00067 int
00068 dig_cidx_add_cat(struct Plus_head *Plus, int field, int cat, int line,
00069                  int type)
00070 {
00071     int i, si, found;
00072     struct Cat_index *ci;
00073 
00074     G_debug(3, "dig_cidx_add_cat(): field = %d cat = %d line = %d type = %d",
00075             field, cat, line, type);
00076 
00077     /* Find field or add new */
00078     si = -1;
00079     for (i = 0; i < Plus->n_cidx; i++) {
00080         if (Plus->cidx[i].field == field) {
00081             si = i;
00082         }
00083     }
00084     if (si == -1) {             /* not found add new */
00085         if (Plus->n_cidx == Plus->a_cidx) {
00086             Plus->a_cidx += 10;
00087             Plus->cidx =
00088                 (struct Cat_index *)G_realloc(Plus->cidx,
00089                                               Plus->a_cidx *
00090                                               sizeof(struct Cat_index));
00091             if (!Plus->cidx)
00092                 return 0;
00093         }
00094         si = Plus->n_cidx;
00095         ci = &(Plus->cidx[si]);
00096         ci->field = field;
00097         ci->n_cats = ci->a_cats = 0;
00098         ci->cat = NULL;
00099         ci->n_types = 0;
00100         ci->offset = 0;
00101         Plus->n_cidx++;
00102     }
00103 
00104     /* Add new cat - line record */
00105     ci = &(Plus->cidx[si]);
00106     if (ci->n_cats == ci->a_cats) {
00107         ci->a_cats += 5000;
00108         ci->cat = G_realloc(ci->cat, ci->a_cats * 3 * sizeof(int));
00109     }
00110 
00111     ci->cat[ci->n_cats][0] = cat;
00112     ci->cat[ci->n_cats][1] = type;
00113     ci->cat[ci->n_cats][2] = line;
00114     ci->n_cats++;
00115 
00116     /* Add type */
00117     found = 0;
00118     for (i = 0; i < ci->n_types; i++) {
00119         if (ci->type[i][0] == type) {
00120             ci->type[i][1]++;
00121             found = 1;
00122         }
00123     }
00124     if (!found) {
00125         ci->type[ci->n_types][0] = type;
00126         ci->type[ci->n_types][1] = 1;
00127         ci->n_types++;
00128     }
00129 
00130     return 1;
00131 }
00132 
00133 /* Compare by cat */
00134 static int cmp_cat(const void *pa, const void *pb)
00135 {
00136     int *p1 = (int *)pa;
00137     int *p2 = (int *)pb;
00138 
00139     if (p1[0] < p2[0])
00140         return -1;
00141     if (p1[0] > p2[0])
00142         return 1;
00143     return 0;
00144 }
00145 
00146 /* Compare by field */
00147 static int cmp_field(const void *pa, const void *pb)
00148 {
00149     struct Cat_index *p1 = (struct Cat_index *)pa;
00150     struct Cat_index *p2 = (struct Cat_index *)pb;
00151 
00152     if (p1->field < p2->field)
00153         return -1;
00154     if (p1->field > p2->field)
00155         return 1;
00156     return 0;
00157 }
00158 
00159 /* 
00160  *  dig_cidx_add_cat_sorted ()
00161  *  add new field - cat - line record to sorted category index, space is allocated if necessary 
00162  *  
00163  *  returns 1 OK
00164  *          0 on error      
00165  */
00166 int
00167 dig_cidx_add_cat_sorted(struct Plus_head *Plus, int field, int cat, int line,
00168                         int type)
00169 {
00170     int i, si, found, position;
00171     struct Cat_index *ci;
00172 
00173     G_debug(3,
00174             "dig_cidx_add_cat_sorted(): field = %d cat = %d line = %d type = %d",
00175             field, cat, line, type);
00176 
00177     /* Find field or add new */
00178     si = -1;
00179     for (i = 0; i < Plus->n_cidx; i++) {
00180         if (Plus->cidx[i].field == field) {
00181             si = i;
00182         }
00183     }
00184     if (si == -1) {             /* not found add new */
00185         if (Plus->n_cidx == Plus->a_cidx) {
00186             Plus->a_cidx += 10;
00187             Plus->cidx =
00188                 (struct Cat_index *)G_realloc(Plus->cidx,
00189                                               Plus->a_cidx *
00190                                               sizeof(struct Cat_index));
00191             if (!Plus->cidx)
00192                 return 0;
00193         }
00194         si = Plus->n_cidx;
00195         ci = &(Plus->cidx[si]);
00196         ci->field = field;
00197         ci->n_cats = ci->a_cats = 0;
00198         ci->cat = NULL;
00199         ci->n_types = 0;
00200         ci->offset = 0;
00201         Plus->n_cidx++;
00202     }
00203 
00204     /* Add new cat - line record */
00205     ci = &(Plus->cidx[si]);
00206     if (ci->n_cats == ci->a_cats) {
00207         ci->a_cats += 5000;
00208         ci->cat = G_realloc(ci->cat, ci->a_cats * 3 * sizeof(int));
00209     }
00210 
00211     /* Find position */
00212     for (position = 0; position < ci->n_cats; position++) {
00213         if (ci->cat[position][0] >= cat) {
00214             break;
00215         }
00216     }
00217 
00218     G_debug(4, "position = %d", position);
00219 
00220     /* Move */
00221     for (i = ci->n_cats; i > position; i--) {
00222         ci->cat[i][0] = ci->cat[i - 1][0];
00223         ci->cat[i][1] = ci->cat[i - 1][1];
00224         ci->cat[i][2] = ci->cat[i - 1][2];
00225     }
00226 
00227     ci->cat[position][0] = cat;
00228     ci->cat[position][1] = type;
00229     ci->cat[position][2] = line;
00230     ci->n_cats++;
00231 
00232     /* Add type */
00233     found = 0;
00234     for (i = 0; i < ci->n_types; i++) {
00235         if (ci->type[i][0] == type) {
00236             ci->type[i][1]++;
00237             found = 1;
00238         }
00239     }
00240     if (!found) {
00241         ci->type[ci->n_types][0] = type;
00242         ci->type[ci->n_types][1] = 1;
00243         ci->n_types++;
00244     }
00245 
00246     /* Sort by field */
00247     qsort(Plus->cidx, Plus->n_cidx, sizeof(struct Cat_index), cmp_field);
00248 
00249     G_debug(3, "Added new category to index");
00250 
00251     return 1;
00252 }
00253 
00254 /* 
00255  *  dig_cidx_del_cat ()
00256  *  delete old field - cat - line record from _sorted_ category index
00257  *
00258  *  returns 1 OK
00259  *          0 on error      
00260  */
00261 int
00262 dig_cidx_del_cat(struct Plus_head *Plus, int field, int cat, int line,
00263                  int type)
00264 {
00265     int i, position;
00266     struct Cat_index *ci;
00267 
00268     G_debug(3, "dig_cidx_del_cat(): field = %d cat = %d line = %d", field,
00269             cat, line);
00270 
00271     /* Find field or add new */
00272     ci = NULL;
00273     for (i = 0; i < Plus->n_cidx; i++) {
00274         if (Plus->cidx[i].field == field) {
00275             ci = &(Plus->cidx[i]);
00276         }
00277     }
00278     if (ci == NULL) {           /* should not happen */
00279         G_warning("BUG: Category index not found for field %d.", field);
00280         return 0;
00281     }
00282 
00283     /* Find position */
00284     G_debug(3, "n_cats = %d", ci->n_cats);
00285     for (position = 0; position < ci->n_cats; position++) {
00286         if (ci->cat[position][0] == cat && ci->cat[position][1] == type &&
00287             ci->cat[position][2] == line) {
00288             break;
00289         }
00290     }
00291 
00292     G_debug(4, "position = %d", position);
00293 
00294     if (position == ci->n_cats) {
00295         G_warning("BUG: Category not found in category index.");
00296         return 0;
00297     }
00298 
00299     /* Delete */
00300     for (i = position; i < ci->n_cats - 1; i++) {
00301         ci->cat[i][0] = ci->cat[i + 1][0];
00302         ci->cat[i][1] = ci->cat[i + 1][1];
00303         ci->cat[i][2] = ci->cat[i + 1][2];
00304     }
00305 
00306     ci->n_cats--;
00307 
00308     for (i = 0; i < ci->n_types; i++) {
00309         if (ci->type[i][0] == type) {
00310             ci->type[i][1]--;
00311         }
00312     }
00313 
00314     G_debug(3, "Deleted from category index");
00315     return 1;
00316 }
00317 
00318 /* 
00319  *  dig_cidx_sort ()
00320  *  sort all records in cat index  
00321  *
00322  */
00323 void dig_cidx_sort(struct Plus_head *Plus)
00324 {
00325     int f;
00326     struct Cat_index *ci;
00327 
00328     G_debug(2, "dig_cidx_sort()");
00329 
00330     for (f = 0; f < Plus->n_cidx; f++) {
00331         int c, nucats = 0;
00332 
00333         ci = &(Plus->cidx[f]);
00334 
00335         /* Sort by category */
00336         qsort(ci->cat, ci->n_cats, 3 * sizeof(int), cmp_cat);
00337 
00338         /* Calculate number of unique cats */
00339         if (ci->n_cats > 0)
00340             nucats++;
00341         for (c = 1; c < ci->n_cats; c++) {
00342             if (ci->cat[c][0] != ci->cat[c - 1][0])
00343                 nucats++;
00344         }
00345         ci->n_ucats = nucats;
00346     }
00347 
00348     /* Sort by field */
00349     qsort(Plus->cidx, Plus->n_cidx, sizeof(struct Cat_index), cmp_field);
00350 }