123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433 |
- #include <stdlib.h>
- #include <grass/gis.h>
- #include <grass/raster.h>
- #include <grass/glocale.h>
- #define LIST struct Histogram_list
- static FILE *fopen_histogram_new(const char *);
- static int cmp(const void *, const void *);
- static int cmp_count(const void *, const void *);
- /*!
- * \brief initializes the histogram structure
- *
- * initializes the histogram structure for calls to Rast_set_histogram()
- * and Rast_add_histogram()
- * \param histogram
- * \return
- */
- void Rast_init_histogram(struct Histogram *histogram)
- {
- histogram->num = 0;
- histogram->list = NULL;
- }
- /*!
- * \brief read the histogram information
- *
- * Reads the histogram information associated with map layer "map"
- * in mapset "mapset" into the structure "histogram".
- *
- * note: a warning message is printed if the file is missing or incorrect
- * \param name: name of map
- * \param mapset: mapset that map belongs to
- * \param histogram: struct for histogram
- * \return 1 if successful,
- * 0 if no histogram file,
- */
- int Rast_read_histogram(const char *name, const char *mapset,
- struct Histogram *histogram)
- {
- FILE *fd = NULL;
- long cat;
- long count;
- char buf[200];
- Rast_init_histogram(histogram);
- if (!G_find_file2_misc("cell_misc", "histogram", name, mapset)) {
- G_warning(_("Histogram for [%s in %s] missing (run r.support)"), name,
- mapset);
- return 0;
- }
- fd = G_fopen_old_misc("cell_misc", "histogram", name, mapset);
- if (!fd)
- G_fatal_error(_("Can't read histogram for [%s in %s]"), name, mapset);
- while (fgets(buf, sizeof buf, fd)) {
- if (sscanf(buf, "%ld:%ld", &cat, &count) != 2)
- G_fatal_error(_("Invalid histogram file for [%s in %s]"),
- name, mapset);
- Rast_extend_histogram((CELL) cat, count, histogram);
- }
- fclose(fd);
- if (histogram->num == 0)
- G_fatal_error(_("Invalid histogram file for [%s in %s]"), name, mapset);
- Rast_sort_histogram(histogram);
- return 1;
- }
- /*!
- * \brief Writes the histogram information
- *
- * Writes the histogram information associated with map layer "name"
- * \param name: name of map
- * \param histogram: struct for histogram
- * \return void
- */
- void Rast_write_histogram(const char *name, const struct Histogram *histogram)
- {
- FILE *fp;
- int n;
- LIST *list;
- fp = fopen_histogram_new(name);
- list = histogram->list;
- for (n = 0; n < histogram->num; n++) {
- if (list[n].count)
- fprintf(fp, "%ld:%ld\n", (long)list[n].cat, list[n].count);
- }
- fclose(fp);
- }
- /*!
- * \brief Writes the histogram based on cell statistics to file
- *
- * \param name: name of map
- * \param statf: cell statistics
- * \return void
- */
- void Rast_write_histogram_cs(const char *name, struct Cell_stats *statf)
- {
- FILE *fp;
- CELL cat;
- long count;
- fp = fopen_histogram_new(name);
- Rast_rewind_cell_stats(statf);
- while (Rast_next_cell_stat(&cat, &count, statf)) {
- if (count > 0)
- fprintf(fp, "%ld:%ld\n", (long)cat, count);
- }
- fclose(fp);
- }
- /*!
- * \brief Creates histogram based on cell statistics
- *
- * \param statf: cell statistics
- * \param histogram: raster histogram
- * \return
- */
- void Rast_make_histogram_cs(struct Cell_stats *statf,
- struct Histogram *histogram)
- {
- CELL cat;
- long count;
- Rast_init_histogram(histogram);
- Rast_rewind_cell_stats(statf);
- while (Rast_next_cell_stat(&cat, &count, statf))
- Rast_add_histogram(cat, count, histogram);
- Rast_sort_histogram(histogram);
- }
- /*!
- * \brief Sorts the histogram in ascending order by counts then category
- *
- * Sorts the histogram in ascending order by counts then category.
- * No combining is done.
- * \param histogram: struct for histogram
- * \return 1 if successful,
- * -1 on fail
- */
- int Rast_get_histogram_num(const struct Histogram *histogram)
- {
- return histogram->num;
- }
- /*!
- * \brief Returns cat for the nth element in the histogram
- *
- * Returns cat for the nth element in the histogram
- * \param histogram: struct for histogram
- * \return CELL
- */
- CELL Rast_get_histogram_cat(int n, const struct Histogram * histogram)
- {
- if (n < 0 || n >= histogram->num)
- return 0;
- return histogram->list[n].cat;
- }
- /*!
- * \brief Returns count for the nth element in the histogram
- *
- * Returns count for the nth element in the histogram
- * \param n: nth element
- * \param histogram: struct for histogram
- * \return count
- */
- long Rast_get_histogram_count(int n, const struct Histogram *histogram)
- {
- if (n < 0 || n >= histogram->num)
- return 0;
- return histogram->list[n].count;
- }
- /*!
- * \brief Frees memory allocated for the histogram
- *
- * frees the memory allocated for the histogram
- * \param histogram: struct for histogram
- * \return
- */
- void Rast_free_histogram(struct Histogram *histogram)
- {
- if (histogram->num > 0)
- G_free(histogram->list);
- histogram->num = 0;
- histogram->list = NULL;
- }
- /*!
- * \brief Sorts the histogram
- *
- * Sorts the histogram in ascending order by category,
- * combining (by adding) elements that have the same category.
- * \param histogram: struct for histogram
- * \return 0 if successful,
- * 1 on fail
- */
- int Rast_sort_histogram(struct Histogram *histogram)
- {
- int a, b, n;
- LIST *list;
- /* if histogram only has 1 entry, nothing to do */
- if ((n = histogram->num) <= 1)
- return 1;
- list = histogram->list;
- /* quick check to see if sorting needed */
- for (a = 1; a < n; a++)
- if (list[a - 1].cat >= list[a].cat)
- break;
- if (a >= n)
- return 1;
- /* sort */
- qsort(list, n, sizeof(LIST), &cmp);
- /* sum duplicate entries */
- for (a = 0, b = 1; b < n; b++) {
- if (list[a].cat != list[b].cat) {
- a++;
- list[a].count = list[b].count;
- list[a].cat = list[b].cat;
- }
- else {
- list[a].count += list[b].count;
- }
- }
- histogram->num = a + 1;
- return 0;
- }
- static int cmp(const void *aa, const void *bb)
- {
- const LIST *a = aa, *b = bb;
- if (a->cat < b->cat)
- return -1;
- if (a->cat > b->cat)
- return 1;
- return 0;
- }
- /*!
- * \brief Sorts the histogram by counts
- *
- * Sorts the histogram in ascending order by counts then category.
- * No combining is done.
- * \param histogram: struct for histogram
- * \return 0 if successful,
- * 1 on fail
- */
- int Rast_sort_histogram_by_count(struct Histogram *histogram)
- {
- int n;
- LIST *list;
- /* if histogram only has 1 entry, nothing to do */
- if ((n = histogram->num) <= 1)
- return 1;
- list = histogram->list;
- /* sort */
- qsort(list, n, sizeof(LIST), &cmp_count);
- return 0;
- }
- static int cmp_count(const void *aa, const void *bb)
- {
- const LIST *a = aa, *b = bb;
- if (a->count < b->count)
- return -1;
- if (a->count > b->count)
- return 1;
- if (a->cat < b->cat)
- return -1;
- if (a->cat > b->cat)
- return 1;
- return 0;
- }
- static FILE *fopen_histogram_new(const char *name)
- {
- FILE *fp;
- fp = G_fopen_new_misc("cell_misc", "histogram", name);
- if (!fp)
- G_fatal_error(_("Unable to create histogram file for <%s>"), name);
- return fp;
- }
- /*!
- * \brief Removes the histogram
- *
- * Removes the histogram information associated with map layer "name"
- * \param name: name of map
- * \return
- */
- void Rast_remove_histogram(const char *name)
- {
- G_remove_misc("cell_misc", "histogram", name);
- }
- /*!
- * \brief adds count to the histogram value for cat
- *
- * adds count to the histogram value for cat
- * \param cat: category
- * \param count
- * \param histogram: struct for histogram
- * \return 0 if successful,
- * 1 on fail
- */
- int Rast_add_histogram(CELL cat, long count, struct Histogram *histogram)
- {
- int i;
- for (i = 0; i < histogram->num; i++) {
- if (histogram->list[i].cat == cat) {
- histogram->list[i].count += count;
- return 1;
- }
- }
- Rast_extend_histogram(cat, count, histogram);
- return 0;
- }
- /*!
- * \brief sets the histogram value for cat to count
- *
- * sets the histogram value for cat to count
- * \param cat: category
- * \param count
- * \param histogram: struct for histogram
- * \return 0 if successful,
- * 1 on fail
- */
- int Rast_set_histogram(CELL cat, long count, struct Histogram *histogram)
- {
- int i;
- for (i = 0; i < histogram->num; i++) {
- if (histogram->list[i].cat == cat) {
- histogram->list[i].count = count;
- return 1;
- }
- }
- Rast_extend_histogram(cat, count, histogram);
- return 0;
- }
- /*!
- * \brief Extends histogram struct to accommodate a new value
- *
- * \param cat: category
- * \param count
- * \param histogram: struct for histogram
- * \return
- */
- void Rast_extend_histogram(CELL cat, long count, struct Histogram *histogram)
- {
- histogram->num++;
- histogram->list =
- (LIST *) G_realloc(histogram->list, histogram->num * sizeof(LIST));
- histogram->list[histogram->num - 1].cat = cat;
- histogram->list[histogram->num - 1].count = count;
- }
- /*!
- * \brief Zero out histogram struct
- *
- * \param histogram: struct for histogram
- * \return
- */
- void Rast_zero_histogram(struct Histogram *histogram)
- {
- int i;
- for (i = 0; i < histogram->num; i++)
- histogram->list[i].count = 0;
- }
|