diglib/cindex.c

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

Generated on Sun Apr 6 17:32:44 2008 for GRASS by  doxygen 1.5.5