00001 #include <grass/gis.h>
00002 #include <grass/glocale.h>
00003 #include <stdlib.h>
00004
00005
00006 #define LIST struct Histogram_list
00007
00008 static FILE *fopen_histogram_new(const char *);
00009 static int cmp(const void *, const void *);
00010 static int cmp_count(const void *, const void *);
00011
00012
00022 int G_init_histogram(struct Histogram *histogram)
00023 {
00024 histogram->num = 0;
00025 histogram->list = NULL;
00026
00027 return 0;
00028 }
00029
00030
00046 int G_read_histogram(const char *name, const char *mapset,
00047 struct Histogram *histogram)
00048 {
00049 FILE *fd = NULL;
00050 long cat;
00051 long count;
00052 char buf[200];
00053
00054 G_init_histogram(histogram);
00055
00056 if (G_find_file2_misc("cell_misc", "histogram", name, mapset) == NULL) {
00057 G_warning(_("Histogram for [%s in %s] missing (run r.support)"), name,
00058 mapset);
00059
00060 return 0;
00061 }
00062
00063 fd = G_fopen_old_misc("cell_misc", "histogram", name, mapset);
00064 if (!fd) {
00065 G_warning(_("Can't read histogram for [%s in %s]"), name, mapset);
00066
00067 return -1;
00068 }
00069
00070 while (fgets(buf, sizeof buf, fd)) {
00071 if (sscanf(buf, "%ld:%ld", &cat, &count) != 2) {
00072 G_free_histogram(histogram);
00073 fclose(fd);
00074 G_warning(_("Invalid histogram file for [%s in %s]"), name,
00075 mapset);
00076
00077 return -1;
00078 }
00079 G_extend_histogram((CELL) cat, count, histogram);
00080 }
00081 fclose(fd);
00082
00083 if (histogram->num == 0) {
00084 G_warning(_("Invalid histogram file for [%s in %s]"), name, mapset);
00085
00086 return -1;
00087 }
00088
00089 G_sort_histogram(histogram);
00090
00091 return 1;
00092 }
00093
00094
00105 int G_write_histogram(const char *name, const struct Histogram *histogram)
00106 {
00107 FILE *fd;
00108 int n;
00109 LIST *list;
00110
00111 fd = fopen_histogram_new(name);
00112 if (fd == NULL)
00113 return -1;
00114
00115 list = histogram->list;
00116 for (n = 0; n < histogram->num; n++) {
00117 if (list[n].count)
00118 fprintf(fd, "%ld:%ld\n", (long)list[n].cat, list[n].count);
00119 }
00120 fclose(fd);
00121
00122 return 1;
00123 }
00124
00125
00135 int G_write_histogram_cs(const char *name, struct Cell_stats *statf)
00136 {
00137 FILE *fd;
00138 CELL cat;
00139 long count;
00140
00141 fd = fopen_histogram_new(name);
00142 if (fd == NULL)
00143 return -1;
00144
00145 G_rewind_cell_stats(statf);
00146 while (G_next_cell_stat(&cat, &count, statf)) {
00147 if (count > 0)
00148 fprintf(fd, "%ld:%ld\n", (long)cat, count);
00149 }
00150 fclose(fd);
00151
00152 return 1;
00153 }
00154
00155
00163 int G_make_histogram_cs(struct Cell_stats *statf, struct Histogram *histogram)
00164 {
00165 CELL cat;
00166 long count;
00167
00168 G_init_histogram(histogram);
00169 G_rewind_cell_stats(statf);
00170 while (G_next_cell_stat(&cat, &count, statf))
00171 G_add_histogram(cat, count, histogram);
00172
00173 G_sort_histogram(histogram);
00174
00175 return 0;
00176 }
00177
00178
00188 int G_get_histogram_num(const struct Histogram *histogram)
00189 {
00190 return histogram->num;
00191 }
00192
00193
00201 CELL G_get_histogram_cat(int n, const struct Histogram * histogram)
00202 {
00203 if (n < 0 || n >= histogram->num)
00204 return 0;
00205
00206 return histogram->list[n].cat;
00207 }
00208
00209
00218 long G_get_histogram_count(int n, const struct Histogram *histogram)
00219 {
00220 if (n < 0 || n >= histogram->num)
00221 return 0;
00222
00223 return histogram->list[n].count;
00224 }
00225
00226
00234 int G_free_histogram(struct Histogram *histogram)
00235 {
00236 if (histogram->num > 0)
00237 G_free(histogram->list);
00238 histogram->num = 0;
00239 histogram->list = NULL;
00240
00241 return 1;
00242 }
00243
00253 int G_sort_histogram(struct Histogram *histogram)
00254 {
00255 int a, b, n;
00256 LIST *list;
00257
00258
00259 if ((n = histogram->num) <= 1)
00260 return 1;
00261
00262 list = histogram->list;
00263
00264
00265 for (a = 1; a < n; a++)
00266 if (list[a - 1].cat >= list[a].cat)
00267 break;
00268 if (a >= n)
00269 return 1;
00270
00271
00272 qsort(list, n, sizeof(LIST), &cmp);
00273
00274
00275 for (a = 0, b = 1; b < n; b++) {
00276 if (list[a].cat != list[b].cat) {
00277 a++;
00278 list[a].count = list[b].count;
00279 list[a].cat = list[b].cat;
00280 }
00281 else {
00282 list[a].count += list[b].count;
00283 }
00284 }
00285 histogram->num = a + 1;
00286
00287 return 0;
00288 }
00289
00290
00291 static int cmp(const void *aa, const void *bb)
00292 {
00293 const LIST *a = aa, *b = bb;
00294
00295 if (a->cat < b->cat)
00296 return -1;
00297
00298 if (a->cat > b->cat)
00299 return 1;
00300
00301 return 0;
00302 }
00303
00313 int G_sort_histogram_by_count(struct Histogram *histogram)
00314 {
00315 int n;
00316 LIST *list;
00317
00318
00319 if ((n = histogram->num) <= 1)
00320 return 1;
00321
00322 list = histogram->list;
00323
00324
00325 qsort(list, n, sizeof(LIST), &cmp_count);
00326
00327 return 0;
00328 }
00329
00330
00331 static int cmp_count(const void *aa, const void *bb)
00332 {
00333 const LIST *a = aa, *b = bb;
00334
00335 if (a->count < b->count)
00336 return -1;
00337
00338 if (a->count > b->count)
00339 return 1;
00340
00341 if (a->cat < b->cat)
00342 return -1;
00343
00344 if (a->cat > b->cat)
00345 return 1;
00346
00347 return 0;
00348 }
00349
00350 static FILE *fopen_histogram_new(const char *name)
00351 {
00352 FILE *fd;
00353
00354 fd = G_fopen_new_misc("cell_misc", "histogram", name);
00355 if (fd == NULL)
00356 G_warning(_("can't create histogram for [%s in %s]"), name,
00357 G_mapset());
00358
00359 return fd;
00360 }
00361
00362
00371 int G_remove_histogram(const char *name)
00372 {
00373 G_remove_misc("cell_misc", "histogram", name);
00374
00375 return 0;
00376 }
00377
00378
00389 int G_add_histogram(CELL cat, long count, struct Histogram *histogram)
00390 {
00391 int i;
00392
00393 for (i = 0; i < histogram->num; i++) {
00394 if (histogram->list[i].cat == cat) {
00395 histogram->list[i].count += count;
00396 return 1;
00397 }
00398 }
00399 G_extend_histogram(cat, count, histogram);
00400
00401 return 0;
00402 }
00403
00404
00415 int G_set_histogram(CELL cat, long count, struct Histogram *histogram)
00416 {
00417 int i;
00418
00419 for (i = 0; i < histogram->num; i++) {
00420 if (histogram->list[i].cat == cat) {
00421 histogram->list[i].count = count;
00422 return 1;
00423 }
00424 }
00425 G_extend_histogram(cat, count, histogram);
00426
00427 return 0;
00428 }
00429
00430
00439 int G_extend_histogram(CELL cat, long count, struct Histogram *histogram)
00440 {
00441 histogram->num++;
00442 histogram->list =
00443 (LIST *) G_realloc((char *)histogram->list,
00444 histogram->num * sizeof(LIST));
00445 histogram->list[histogram->num - 1].cat = cat;
00446 histogram->list[histogram->num - 1].count = count;
00447
00448 return 0;
00449 }
00450
00451
00458 int G_zero_histogram(struct Histogram *histogram)
00459 {
00460 int i;
00461
00462 for (i = 0; i < histogram->num; i++)
00463 histogram->list[i].count = 0;
00464
00465 return 0;
00466 }