GRASS 8 Programmer's Manual  8.5.0dev(2025)-c070206eb1
histogram.c
Go to the documentation of this file.
1 #include <stdlib.h>
2 
3 #include <grass/gis.h>
4 #include <grass/raster.h>
5 #include <grass/glocale.h>
6 
7 #define LIST struct Histogram_list
8 
9 static FILE *fopen_histogram_new(const char *);
10 static int cmp(const void *, const void *);
11 static int cmp_count(const void *, const void *);
12 
13 /*!
14  * \brief initializes the histogram structure
15  *
16  * initializes the histogram structure for calls to Rast_set_histogram()
17  * and Rast_add_histogram()
18  * \param histogram
19  * \return
20  */
21 void Rast_init_histogram(struct Histogram *histogram)
22 {
23  histogram->num = 0;
24  histogram->list = NULL;
25 }
26 
27 /*!
28  * \brief read the histogram information
29  *
30  * Reads the histogram information associated with map layer "map"
31  * in mapset "mapset" into the structure "histogram".
32  *
33  * note: a warning message is printed if the file is missing or incorrect
34  * \param name: name of map
35  * \param mapset: mapset that map belongs to
36  * \param histogram: struct for histogram
37  * \return 1 if successful,
38  * 0 if no histogram file,
39  */
40 int Rast_read_histogram(const char *name, const char *mapset,
41  struct Histogram *histogram)
42 {
43  FILE *fd = NULL;
44  long cat;
45  long count;
46  char buf[200];
47 
48  Rast_init_histogram(histogram);
49 
50  if (!G_find_file2_misc("cell_misc", "histogram", name, mapset)) {
51  G_warning(_("Histogram for [%s in %s] missing (run r.support)"), name,
52  mapset);
53  return 0;
54  }
55 
56  fd = G_fopen_old_misc("cell_misc", "histogram", name, mapset);
57  if (!fd)
58  G_fatal_error(_("Can't read histogram for [%s in %s]"), name, mapset);
59 
60  while (fgets(buf, sizeof buf, fd)) {
61  if (sscanf(buf, "%ld:%ld", &cat, &count) != 2)
62  G_fatal_error(_("Invalid histogram file for [%s in %s]"), name,
63  mapset);
64  Rast_extend_histogram((CELL)cat, count, histogram);
65  }
66  fclose(fd);
67 
68  if (histogram->num == 0)
69  G_fatal_error(_("Invalid histogram file for [%s in %s]"), name, mapset);
70 
71  Rast_sort_histogram(histogram);
72 
73  return 1;
74 }
75 
76 /*!
77  * \brief Writes the histogram information
78  *
79  * Writes the histogram information associated with map layer "name"
80  * \param name: name of map
81  * \param histogram: struct for histogram
82  * \return void
83  */
84 void Rast_write_histogram(const char *name, const struct Histogram *histogram)
85 {
86  FILE *fp;
87  int n;
88  LIST *list;
89 
90  fp = fopen_histogram_new(name);
91 
92  list = histogram->list;
93  for (n = 0; n < histogram->num; n++) {
94  if (list[n].count)
95  fprintf(fp, "%ld:%ld\n", (long)list[n].cat, list[n].count);
96  }
97 
98  fclose(fp);
99 }
100 
101 /*!
102  * \brief Writes the histogram based on cell statistics to file
103  *
104  * \param name: name of map
105  * \param statf: cell statistics
106  * \return void
107  */
108 void Rast_write_histogram_cs(const char *name, struct Cell_stats *statf)
109 {
110  FILE *fp;
111  CELL cat;
112  long count;
113 
114  fp = fopen_histogram_new(name);
115 
116  Rast_rewind_cell_stats(statf);
117  while (Rast_next_cell_stat(&cat, &count, statf)) {
118  if (count > 0)
119  fprintf(fp, "%ld:%ld\n", (long)cat, count);
120  }
121 
122  fclose(fp);
123 }
124 
125 /*!
126  * \brief Creates histogram based on cell statistics
127  *
128  * \param statf: cell statistics
129  * \param histogram: raster histogram
130  * \return
131  */
133  struct Histogram *histogram)
134 {
135  CELL cat;
136  long count;
137 
138  Rast_init_histogram(histogram);
139  Rast_rewind_cell_stats(statf);
140  while (Rast_next_cell_stat(&cat, &count, statf))
141  Rast_add_histogram(cat, count, histogram);
142 
143  Rast_sort_histogram(histogram);
144 }
145 
146 /*!
147  * \brief Sorts the histogram in ascending order by counts then category
148  *
149  * Sorts the histogram in ascending order by counts then category.
150  * No combining is done.
151  * \param histogram: struct for histogram
152  * \return 1 if successful,
153  * -1 on fail
154  */
155 int Rast_get_histogram_num(const struct Histogram *histogram)
156 {
157  return histogram->num;
158 }
159 
160 /*!
161  * \brief Returns cat for the nth element in the histogram
162  *
163  * Returns cat for the nth element in the histogram
164  * \param n: The nth element in the histogram to get the cat for
165  * \param histogram: struct for histogram
166  * \return CELL
167  */
168 CELL Rast_get_histogram_cat(int n, const struct Histogram *histogram)
169 {
170  if (n < 0 || n >= histogram->num)
171  return 0;
172 
173  return histogram->list[n].cat;
174 }
175 
176 /*!
177  * \brief Returns count for the nth element in the histogram
178  *
179  * Returns count for the nth element in the histogram
180  * \param n: nth element
181  * \param histogram: struct for histogram
182  * \return count
183  */
184 long Rast_get_histogram_count(int n, const struct Histogram *histogram)
185 {
186  if (n < 0 || n >= histogram->num)
187  return 0;
188 
189  return histogram->list[n].count;
190 }
191 
192 /*!
193  * \brief Frees memory allocated for the histogram
194  *
195  * frees the memory allocated for the histogram
196  * \param histogram: struct for histogram
197  * \return
198  */
199 void Rast_free_histogram(struct Histogram *histogram)
200 {
201  if (histogram->num > 0)
202  G_free(histogram->list);
203  histogram->num = 0;
204  histogram->list = NULL;
205 }
206 
207 /*!
208  * \brief Sorts the histogram
209  *
210  * Sorts the histogram in ascending order by category,
211  * combining (by adding) elements that have the same category.
212  * \param histogram: struct for histogram
213  * \return 0 if successful,
214  * 1 on fail
215  */
216 int Rast_sort_histogram(struct Histogram *histogram)
217 {
218  int a, b, n;
219  LIST *list;
220 
221  /* if histogram only has 1 entry, nothing to do */
222  if ((n = histogram->num) <= 1)
223  return 1;
224 
225  list = histogram->list;
226 
227  /* quick check to see if sorting needed */
228  for (a = 1; a < n; a++)
229  if (list[a - 1].cat >= list[a].cat)
230  break;
231  if (a >= n)
232  return 1;
233 
234  /* sort */
235  qsort(list, n, sizeof(LIST), &cmp);
236 
237  /* sum duplicate entries */
238  for (a = 0, b = 1; b < n; b++) {
239  if (list[a].cat != list[b].cat) {
240  a++;
241  list[a].count = list[b].count;
242  list[a].cat = list[b].cat;
243  }
244  else {
245  list[a].count += list[b].count;
246  }
247  }
248  histogram->num = a + 1;
249 
250  return 0;
251 }
252 
253 static int cmp(const void *aa, const void *bb)
254 {
255  const LIST *a = aa, *b = bb;
256 
257  if (a->cat < b->cat)
258  return -1;
259 
260  if (a->cat > b->cat)
261  return 1;
262 
263  return 0;
264 }
265 
266 /*!
267  * \brief Sorts the histogram by counts
268  *
269  * Sorts the histogram in ascending order by counts then category.
270  * No combining is done.
271  * \param histogram: struct for histogram
272  * \return 0 if successful,
273  * 1 on fail
274  */
276 {
277  int n;
278  LIST *list;
279 
280  /* if histogram only has 1 entry, nothing to do */
281  if ((n = histogram->num) <= 1)
282  return 1;
283 
284  list = histogram->list;
285 
286  /* sort */
287  qsort(list, n, sizeof(LIST), &cmp_count);
288 
289  return 0;
290 }
291 
292 static int cmp_count(const void *aa, const void *bb)
293 {
294  const LIST *a = aa, *b = bb;
295 
296  if (a->count < b->count)
297  return -1;
298 
299  if (a->count > b->count)
300  return 1;
301 
302  if (a->cat < b->cat)
303  return -1;
304 
305  if (a->cat > b->cat)
306  return 1;
307 
308  return 0;
309 }
310 
311 static FILE *fopen_histogram_new(const char *name)
312 {
313  FILE *fp;
314 
315  fp = G_fopen_new_misc("cell_misc", "histogram", name);
316  if (!fp)
317  G_fatal_error(_("Unable to create histogram file for <%s>"), name);
318 
319  return fp;
320 }
321 
322 /*!
323  * \brief Removes the histogram
324  *
325  * Removes the histogram information associated with map layer "name"
326  * \param name: name of map
327  * \return
328  */
329 void Rast_remove_histogram(const char *name)
330 {
331  G_remove_misc("cell_misc", "histogram", name);
332 }
333 
334 /*!
335  * \brief adds count to the histogram value for cat
336  *
337  * adds count to the histogram value for cat
338  * \param cat: category
339  * \param count
340  * \param histogram: struct for histogram
341  * \return 0 if successful,
342  * 1 on fail
343  */
344 int Rast_add_histogram(CELL cat, long count, struct Histogram *histogram)
345 {
346  int i;
347 
348  for (i = 0; i < histogram->num; i++) {
349  if (histogram->list[i].cat == cat) {
350  histogram->list[i].count += count;
351  return 1;
352  }
353  }
354  Rast_extend_histogram(cat, count, histogram);
355 
356  return 0;
357 }
358 
359 /*!
360  * \brief sets the histogram value for cat to count
361  *
362  * sets the histogram value for cat to count
363  * \param cat: category
364  * \param count
365  * \param histogram: struct for histogram
366  * \return 0 if successful,
367  * 1 on fail
368  */
369 int Rast_set_histogram(CELL cat, long count, struct Histogram *histogram)
370 {
371  int i;
372 
373  for (i = 0; i < histogram->num; i++) {
374  if (histogram->list[i].cat == cat) {
375  histogram->list[i].count = count;
376  return 1;
377  }
378  }
379  Rast_extend_histogram(cat, count, histogram);
380 
381  return 0;
382 }
383 
384 /*!
385  * \brief Extends histogram struct to accommodate a new value
386  *
387  * \param cat: category
388  * \param count
389  * \param histogram: struct for histogram
390  * \return
391  */
392 void Rast_extend_histogram(CELL cat, long count, struct Histogram *histogram)
393 {
394  histogram->num++;
395  histogram->list =
396  (LIST *)G_realloc(histogram->list, histogram->num * sizeof(LIST));
397  histogram->list[histogram->num - 1].cat = cat;
398  histogram->list[histogram->num - 1].count = count;
399 }
400 
401 /*!
402  * \brief Zero out histogram struct
403  *
404  * \param histogram: struct for histogram
405  * \return
406  */
407 void Rast_zero_histogram(struct Histogram *histogram)
408 {
409  int i;
410 
411  for (i = 0; i < histogram->num; i++)
412  histogram->list[i].count = 0;
413 }
#define NULL
Definition: ccmath.h:32
void G_free(void *)
Free allocated memory.
Definition: gis/alloc.c:147
#define G_realloc(p, n)
Definition: defs/gis.h:96
FILE * G_fopen_old_misc(const char *, const char *, const char *, const char *)
open a database misc file for reading
Definition: open_misc.c:205
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
FILE * G_fopen_new_misc(const char *, const char *, const char *)
open a new database misc file
Definition: open_misc.c:178
const char * G_find_file2_misc(const char *, const char *, const char *, const char *)
Searches for a misc file from the mapset search list or in a specified mapset. (look but don't touch)
Definition: find_file.c:257
int G_remove_misc(const char *, const char *, const char *)
Remove a database misc file.
Definition: remove.c:64
int Rast_rewind_cell_stats(struct Cell_stats *)
Reset/rewind cell stats.
Definition: cell_stats.c:248
int Rast_next_cell_stat(CELL *, long *, struct Cell_stats *)
Retrieve sorted cell stats.
Definition: cell_stats.c:312
int CELL
Definition: gis.h:634
#define _(str)
Definition: glocale.h:10
int Rast_get_histogram_num(const struct Histogram *histogram)
Sorts the histogram in ascending order by counts then category.
Definition: histogram.c:155
void Rast_write_histogram(const char *name, const struct Histogram *histogram)
Writes the histogram information.
Definition: histogram.c:84
int Rast_read_histogram(const char *name, const char *mapset, struct Histogram *histogram)
read the histogram information
Definition: histogram.c:40
void Rast_free_histogram(struct Histogram *histogram)
Frees memory allocated for the histogram.
Definition: histogram.c:199
int Rast_add_histogram(CELL cat, long count, struct Histogram *histogram)
adds count to the histogram value for cat
Definition: histogram.c:344
int Rast_sort_histogram(struct Histogram *histogram)
Sorts the histogram.
Definition: histogram.c:216
void Rast_extend_histogram(CELL cat, long count, struct Histogram *histogram)
Extends histogram struct to accommodate a new value.
Definition: histogram.c:392
void Rast_write_histogram_cs(const char *name, struct Cell_stats *statf)
Writes the histogram based on cell statistics to file.
Definition: histogram.c:108
long Rast_get_histogram_count(int n, const struct Histogram *histogram)
Returns count for the nth element in the histogram.
Definition: histogram.c:184
int Rast_sort_histogram_by_count(struct Histogram *histogram)
Sorts the histogram by counts.
Definition: histogram.c:275
void Rast_make_histogram_cs(struct Cell_stats *statf, struct Histogram *histogram)
Creates histogram based on cell statistics.
Definition: histogram.c:132
int Rast_set_histogram(CELL cat, long count, struct Histogram *histogram)
sets the histogram value for cat to count
Definition: histogram.c:369
CELL Rast_get_histogram_cat(int n, const struct Histogram *histogram)
Returns cat for the nth element in the histogram.
Definition: histogram.c:168
void Rast_zero_histogram(struct Histogram *histogram)
Zero out histogram struct.
Definition: histogram.c:407
void Rast_init_histogram(struct Histogram *histogram)
initializes the histogram structure
Definition: histogram.c:21
void Rast_remove_histogram(const char *name)
Removes the histogram.
Definition: histogram.c:329
#define LIST
Definition: histogram.c:7
int count
const char * name
Definition: named_colr.c:6
double b
Definition: r_raster.c:39
struct list * list
Definition: read_list.c:24
int num
Definition: raster.h:197
struct Histogram::Histogram_list * list
Definition: manage.h:4