o_median.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. #include <stdlib.h>
  2. #include <unistd.h>
  3. #include <grass/gis.h>
  4. #include <grass/raster.h>
  5. #include "method.h"
  6. /* function prototypes */
  7. static long median(struct stats *);
  8. int o_median(const char *basemap, const char *covermap, const char *outputmap,
  9. int usecats, struct Categories *cats)
  10. {
  11. struct Popen stats_child, reclass_child;
  12. FILE *stats_fp, *reclass_fp;
  13. int first;
  14. long basecat, covercat, catb, catc;
  15. double area;
  16. struct stats stats;
  17. stats_fp = run_stats(&stats_child, basemap, covermap, "-an");
  18. reclass_fp = run_reclass(&reclass_child, basemap, outputmap);
  19. first = 1;
  20. while (read_stats(stats_fp, &basecat, &covercat, &area)) {
  21. if (first) {
  22. stats.n = 0;
  23. stats.nalloc = 16;
  24. stats.cat = (long *)
  25. G_calloc(stats.nalloc, sizeof(long));
  26. stats.area = (double *)
  27. G_calloc(stats.nalloc, sizeof(double));
  28. first = 0;
  29. catb = basecat;
  30. }
  31. if (basecat != catb) {
  32. catc = median(&stats);
  33. write_reclass(reclass_fp, catb, catc, Rast_get_c_cat((CELL *) &catc, cats),
  34. usecats);
  35. catb = basecat;
  36. stats.n = 0;
  37. }
  38. stats.n++;
  39. if (stats.n > stats.nalloc) {
  40. stats.nalloc *= 2;
  41. stats.cat = (long *)
  42. G_realloc(stats.cat, stats.nalloc * sizeof(long));
  43. stats.area = (double *)
  44. G_realloc(stats.area, stats.nalloc * sizeof(double));
  45. }
  46. stats.cat[stats.n - 1] = covercat;
  47. stats.area[stats.n - 1] = area;
  48. }
  49. if (!first) {
  50. catc = median(&stats);
  51. write_reclass(reclass_fp, catb, catc, Rast_get_c_cat((CELL *) &catc, cats), usecats);
  52. }
  53. G_popen_close(&stats_child);
  54. G_popen_close(&reclass_child);
  55. return 0;
  56. }
  57. static long median(struct stats *stats)
  58. {
  59. double total, sum;
  60. int i;
  61. total = 0;
  62. for (i = 0; i < stats->n; i++)
  63. total += stats->area[i];
  64. total /= 2.0;
  65. sum = 0;
  66. for (i = 0; i < stats->n; i++) {
  67. sum += stats->area[i];
  68. if (sum > total)
  69. break;
  70. }
  71. if (i == stats->n)
  72. i--;
  73. if (i < 0)
  74. return ((long)0);
  75. return (stats->cat[i]);
  76. }