GRASS Programmer's Manual 6.4.1(2011)
|
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 }