GRASS Programmer's Manual
6.4.2(2012)
|
00001 00021 #include <stdlib.h> 00022 #include <string.h> 00023 #include <grass/gis.h> 00024 #include <grass/Vect.h> 00025 #include <grass/glocale.h> 00026 00027 static int cmp(const void *pa, const void *pb); 00028 struct line_cats *Vect__new_cats_struct(void); 00029 00030 00040 struct line_cats *Vect_new_cats_struct() 00041 { 00042 struct line_cats *p; 00043 00044 if (NULL == (p = Vect__new_cats_struct())) 00045 G_fatal_error(_("Vect_new_cats_struct(): Out of memory")); 00046 00047 return p; 00048 } 00049 00058 struct line_cats *Vect__new_cats_struct() 00059 { 00060 struct line_cats *p; 00061 00062 p = (struct line_cats *)G_malloc(sizeof(struct line_cats)); 00063 00064 /* n_cats MUST be initialized to zero */ 00065 if (p) 00066 p->n_cats = 0; 00067 00068 if (p) 00069 p->alloc_cats = 0; 00070 00071 return p; 00072 } 00073 00081 int Vect_destroy_cats_struct(struct line_cats *p) 00082 { 00083 if (p) { /* probably a moot test */ 00084 if (p->n_cats) { 00085 G_free((void *)p->field); 00086 G_free((void *)p->cat); 00087 } 00088 G_free((void *)p); 00089 } 00090 00091 return 0; 00092 } 00093 00106 int Vect_cat_set(struct line_cats *Cats, int field, int cat) 00107 { 00108 register int n; 00109 00110 /* check input values */ 00111 /* compiler may warn: 00112 * comparison is always 0 due to limited range of data type 00113 * but remember that limit is set to portable data type length 00114 * and machine native size may be longer */ 00115 /* 00116 if (field < 1 || field > GV_FIELD_MAX || cat < 0 || cat > GV_CAT_MAX) 00117 return (-2); 00118 */ 00119 00120 /* go through old cats and find if field/category exists */ 00121 for (n = 0; n < Cats->n_cats; n++) { 00122 if (Cats->field[n] == field && Cats->cat[n] == cat) 00123 return (1); 00124 } 00125 00126 /* field was not found so we shall append new cat */ 00127 /* test if space exist */ 00128 if (n >= GV_NCATS_MAX) { 00129 G_fatal_error(_("Too many categories (%d), unable to set cat %d (layer %d)"), 00130 Cats->n_cats, cat, field); 00131 } 00132 00133 if (Cats->n_cats == Cats->alloc_cats) { 00134 if (0 > dig_alloc_cats(Cats, Cats->n_cats + 100)) 00135 return (-1); 00136 } 00137 00138 n = Cats->n_cats; 00139 Cats->field[n] = field; 00140 Cats->cat[n] = cat; 00141 Cats->n_cats++; 00142 return (1); 00143 } 00144 00157 int Vect_cat_get(struct line_cats *Cats, int field, int *cat) 00158 { 00159 register int n; 00160 00161 /* check input value */ 00162 /* 00163 if (field < 1 || field > GV_FIELD_MAX) 00164 return (0); 00165 */ 00166 00167 *cat = -1; 00168 00169 /* go through cats and find if field exist */ 00170 for (n = 0; n < Cats->n_cats; n++) { 00171 if (Cats->field[n] == field) { 00172 *cat = Cats->cat[n]; 00173 return (1); 00174 } 00175 } 00176 00177 /* field was not found */ 00178 return (0); 00179 } 00180 00191 int Vect_field_cat_get(struct line_cats *Cats, int field, struct ilist *cats) 00192 { 00193 int n; 00194 00195 /* reset list of categories */ 00196 Vect_reset_list(cats); 00197 00198 /* check input value */ 00199 if (field < 1 || field > GV_FIELD_MAX) 00200 return -1; 00201 00202 /* go through cats and find if field exist */ 00203 for (n = 0; n < Cats->n_cats; n++) { 00204 if (Cats->field[n] != field) 00205 continue; 00206 Vect_list_append(cats, Cats->cat[n]); 00207 } 00208 00209 return cats->n_values; 00210 } 00211 00221 int Vect_cat_del(struct line_cats *Cats, int field) 00222 { 00223 int n, m, found = 0; 00224 00225 /* check input value */ 00226 /* 00227 if (field < 1 || field > GV_FIELD_MAX) 00228 return (0); 00229 */ 00230 00231 /* go through cats and find if field exist */ 00232 for (n = 0; n < Cats->n_cats; n++) { 00233 if (Cats->field[n] == field) { 00234 for (m = n; m < Cats->n_cats - 1; m++) { 00235 Cats->field[m] = Cats->field[m + 1]; 00236 Cats->cat[m] = Cats->cat[m + 1]; 00237 } 00238 Cats->n_cats--; 00239 found = 1; 00240 n--; /* check again this position */ 00241 } 00242 } 00243 00244 return (found); 00245 } 00246 00257 int Vect_field_cat_del(struct line_cats *Cats, int field, int cat) 00258 { 00259 register int n, m, found = 0; 00260 00261 /* check input value */ 00262 /* 00263 if (field < 1 || field > GV_FIELD_MAX) 00264 return (0); 00265 */ 00266 00267 /* go through cats and find if field exist */ 00268 for (n = 0; n < Cats->n_cats; n++) { 00269 if (Cats->field[n] == field && (Cats->cat[n] == cat || cat == -1)) { 00270 for (m = n; m < Cats->n_cats - 1; m++) { 00271 Cats->field[m] = Cats->field[m + 1]; 00272 Cats->cat[m] = Cats->cat[m + 1]; 00273 } 00274 Cats->n_cats--; 00275 found = 1; 00276 } 00277 } 00278 00279 return (found); 00280 } 00281 00292 int Vect_reset_cats(struct line_cats *Cats) 00293 { 00294 Cats->n_cats = 0; 00295 00296 return 0; 00297 } 00298 00305 struct cat_list *Vect_new_cat_list() 00306 { 00307 struct cat_list *p; 00308 00309 p = (struct cat_list *)G_malloc(sizeof(struct cat_list)); 00310 00311 /* n_ranges MUST be initialized to zero */ 00312 if (p) { 00313 p->n_ranges = 0; 00314 p->alloc_ranges = 0; 00315 p->field = 0; 00316 p->min = NULL; 00317 p->max = NULL; 00318 } 00319 00320 return p; 00321 } 00322 00323 00331 int Vect_destroy_cat_list(struct cat_list *p) 00332 { 00333 if (p) { /* probably a moot test */ 00334 if (p->n_ranges) { 00335 G_free((void *)p->min); 00336 G_free((void *)p->max); 00337 } 00338 G_free((void *)p); 00339 } 00340 00341 return 0; 00342 } 00343 00344 00355 int Vect_str_to_cat_list(const char *str, struct cat_list *list) 00356 { 00357 int i, nr, l, err = 0; 00358 const char *s, *e; 00359 char buf[100]; 00360 int min, max; 00361 00362 G_debug(3, "Vect_str_to_cat_list(): str = %s", str); 00363 00364 list->n_ranges = 0; 00365 l = strlen(str); 00366 00367 /* find number of ranges */ 00368 nr = 1; /* one range */ 00369 for (i = 0; i < l; i++) 00370 if (str[i] == ',') 00371 nr++; 00372 00373 /* allocate space */ 00374 if (list->alloc_ranges == 0) { 00375 list->min = (int *)G_malloc(nr * sizeof(int)); 00376 list->max = (int *)G_malloc(nr * sizeof(int)); 00377 } 00378 else if (nr > list->alloc_ranges) { 00379 list->min = (int *)G_realloc((void *)list->min, nr * sizeof(int)); 00380 list->max = (int *)G_realloc((void *)list->max, nr * sizeof(int)); 00381 } 00382 00383 /* go through string and read ranges */ 00384 i = 0; 00385 s = str; 00386 00387 while (s) { 00388 e = (char *)strchr(s, ','); /* first comma */ 00389 if (e) { 00390 l = e - s; 00391 strncpy(buf, s, l); 00392 buf[l] = '\0'; 00393 s = e + 1; 00394 } 00395 else { 00396 strcpy(buf, s); 00397 s = NULL; 00398 } 00399 00400 G_debug(3, " buf = %s", buf); 00401 if (sscanf(buf, "%d-%d", &min, &max) == 2) { 00402 } 00403 else if (sscanf(buf, "%d", &min) == 1) 00404 max = min; 00405 else { /* error */ 00406 00407 G_warning(_("Unable to convert category string '%s' (from '%s') to category range"), 00408 buf, str); 00409 err++; 00410 continue; 00411 } 00412 00413 list->min[i] = min; 00414 list->max[i] = max; 00415 i++; 00416 } 00417 00418 list->n_ranges = i; 00419 00420 return (err); 00421 } 00422 00432 int Vect_array_to_cat_list(int *vals, int nvals, struct cat_list *list) 00433 { 00434 int i, range; 00435 00436 G_debug(1, "Vect_array_to_cat_list()"); 00437 range = -1; 00438 for (i = 0; i < nvals; i++) { 00439 if (i == 0 || (vals[i] - list->max[range]) > 1) { 00440 range++; 00441 if (range == list->alloc_ranges) { 00442 list->alloc_ranges += 1000; 00443 list->min = (int *)G_realloc((void *)list->min, 00444 list->alloc_ranges * 00445 sizeof(int)); 00446 list->max = 00447 (int *)G_realloc((void *)list->max, 00448 list->alloc_ranges * sizeof(int)); 00449 } 00450 list->min[range] = vals[i]; 00451 list->max[range] = vals[i]; 00452 } 00453 else { 00454 list->max[range] = vals[i]; 00455 } 00456 } 00457 00458 list->n_ranges = range + 1; 00459 00460 return (list->n_ranges); 00461 } 00462 00472 int Vect_cat_in_cat_list(int cat, struct cat_list *list) 00473 { 00474 int i; 00475 00476 for (i = 0; i < list->n_ranges; i++) 00477 if (cat >= list->min[i] && cat <= list->max[i]) 00478 return (TRUE); 00479 00480 return (FALSE); 00481 } 00482 00493 int Vect_cat_in_array(int cat, int *array, int ncats) 00494 { 00495 int *i; 00496 00497 i = bsearch((void *)&cat, (void *)array, (size_t) ncats, 00498 sizeof(int), cmp); 00499 00500 if (i != NULL) 00501 return (TRUE); 00502 00503 return (FALSE); 00504 } 00505 00506 static int cmp(const void *pa, const void *pb) 00507 { 00508 int *p1 = (int *)pa; 00509 int *p2 = (int *)pb; 00510 00511 if (*p1 < *p2) 00512 return -1; 00513 if (*p1 > *p2) 00514 return 1; 00515 return 0; 00516 }