main.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /****************************************************************************
  2. *
  3. * MODULE: r.li.patchdensity
  4. * AUTHOR(S): Claudio Porta and Lucio Davide Spano (original contributors)
  5. * students of Computer Science University of Pisa (Italy)
  6. * Commission from Faunalia Pontedera (PI) www.faunalia.it
  7. * Fixes: Serena Pallecchi, Markus Neteler <neteler itc.it>
  8. * PURPOSE: calculates patch density index
  9. * COPYRIGHT: (C) 2006-2007 by the GRASS Development Team
  10. *
  11. * This program is free software under the GNU General Public
  12. * License (>=v2). Read the file COPYING that comes with GRASS
  13. * for details.
  14. *
  15. *****************************************************************************/
  16. #include <stdlib.h>
  17. #include <fcntl.h>
  18. #include <grass/gis.h>
  19. #include <grass/raster.h>
  20. #include <grass/glocale.h>
  21. #include "../r.li.daemon/daemon.h"
  22. #include "../r.li.daemon/defs.h"
  23. int main(int argc, char *argv[])
  24. {
  25. struct Option *raster, *conf, *output;
  26. struct GModule *module;
  27. G_gisinit(argv[0]);
  28. module = G_define_module();
  29. module->description =
  30. _("Calculates patch density index on a raster map, using a 4 neighbour algorithm");
  31. G_add_keyword(_("raster"));
  32. G_add_keyword(_("landscape structure analysis"));
  33. G_add_keyword(_("patch index"));
  34. /* define options */
  35. raster = G_define_standard_option(G_OPT_R_INPUT);
  36. conf = G_define_standard_option(G_OPT_F_INPUT);
  37. conf->key = "config";
  38. conf->description = _("Configuration file");
  39. conf->required = YES;
  40. output = G_define_standard_option(G_OPT_R_OUTPUT);
  41. /**add other options for index parameters here */
  42. if (G_parser(argc, argv))
  43. exit(EXIT_FAILURE);
  44. return calculateIndex(conf->answer, patch_density, NULL, raster->answer,
  45. output->answer);
  46. }
  47. int patch_density(int fd, char **par, struct area_entry *ad, double *result)
  48. {
  49. CELL *buf, *sup;
  50. int count = 0, i, j, connected = 0, complete_line = 1, other_above = 0;
  51. double area;
  52. struct Cell_head hd;
  53. CELL complete_value;
  54. double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
  55. int mask_fd = -1, *mask_buf, *mask_sup, null_count = 0;
  56. Rast_set_c_null_value(&complete_value, 1);
  57. Rast_get_cellhd(ad->raster, "", &hd);
  58. sup = Rast_allocate_c_buf();
  59. /* open mask if needed */
  60. if (ad->mask == 1) {
  61. if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
  62. return 0;
  63. mask_buf = malloc(ad->cl * sizeof(int));
  64. mask_sup = malloc(ad->cl * sizeof(int));
  65. }
  66. /*calculate distance */
  67. G_begin_distance_calculations();
  68. /* EW Dist at North edge */
  69. EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
  70. /* EW Dist at South Edge */
  71. EW_DIST2 = G_distance(hd.east, hd.south, hd.west, hd.south);
  72. /* NS Dist at East edge */
  73. NS_DIST1 = G_distance(hd.east, hd.north, hd.east, hd.south);
  74. /* NS Dist at West edge */
  75. NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
  76. /*calculate number of patch */
  77. for (i = 0; i < ad->rl; i++) {
  78. buf = RLI_get_cell_raster_row(fd, i + ad->y, ad);
  79. if (i > 0) {
  80. sup = RLI_get_cell_raster_row(fd, i - 1 + ad->y, ad);
  81. }
  82. /* mask values */
  83. if (ad->mask == 1) {
  84. int k;
  85. if (i > 0) {
  86. int *tmp;
  87. tmp = mask_sup;
  88. mask_buf = mask_sup;
  89. }
  90. if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
  91. return 0;
  92. for (k = 0; k < ad->cl; k++) {
  93. if (mask_buf[k] == 0) {
  94. Rast_set_c_null_value(mask_buf + k, 1);
  95. null_count++;
  96. }
  97. }
  98. }
  99. if (complete_line) {
  100. if (!Rast_is_null_value(&(buf[ad->x]), CELL_TYPE) &&
  101. buf[ad->x] != complete_value)
  102. count++;
  103. for (j = 0; j < ad->cl - 1; j++) {
  104. if (buf[j + ad->x] != buf[j + 1 + ad->x]) {
  105. complete_line = 0;
  106. if (!Rast_is_null_value(&(buf[j + 1 + ad->x]), CELL_TYPE)
  107. && buf[j + 1 + ad->x] != complete_value)
  108. count++;
  109. }
  110. }
  111. if (complete_line) {
  112. complete_value = buf[ad->x];
  113. }
  114. }
  115. else {
  116. complete_line = 1;
  117. connected = 0;
  118. other_above = 0;
  119. for (j = 0; j < ad->cl; j++) {
  120. if (sup[j + ad->x] == buf[j + ad->x]) {
  121. connected = 1;
  122. if (other_above) {
  123. other_above = 0;
  124. count--;
  125. }
  126. }
  127. else {
  128. if (connected &&
  129. !Rast_is_null_value(&(buf[j + ad->x]), CELL_TYPE))
  130. other_above = 1;
  131. }
  132. if (j < ad->cl - 1 && buf[j + ad->x] != buf[j + 1 + ad->x]) {
  133. complete_line = 0;
  134. if (!connected &&
  135. !Rast_is_null_value(&(buf[j + ad->x]), CELL_TYPE)) {
  136. count++;
  137. connected = 0;
  138. other_above = 0;
  139. }
  140. else {
  141. connected = 0;
  142. other_above = 0;
  143. }
  144. }
  145. }
  146. if (!connected &&
  147. sup[ad->cl - 1 + ad->x] != buf[ad->cl - 1 + ad->x]) {
  148. if (!Rast_is_null_value
  149. (&(buf[ad->cl - 1 + ad->x]), CELL_TYPE)) {
  150. count++;
  151. complete_line = 0;
  152. }
  153. }
  154. if (complete_line)
  155. complete_value = buf[ad->x];
  156. }
  157. }
  158. area = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
  159. (((NS_DIST1 + NS_DIST2) / 2) / hd.rows) *
  160. (ad->rl *ad->cl - null_count);
  161. if (area != 0)
  162. *result = (count / area) * 1000000;
  163. else
  164. *result = -1;
  165. G_free(sup);
  166. return RLI_OK;
  167. }