select_linksB.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /************************************************************************
  2. *
  3. * select_linksB.c in ~/r.spread
  4. *
  5. * function to select cell links for elliptical spread and to put
  6. * the destinated cell of a link in a simple linked list of type
  7. * cell_ptrHa.
  8. *
  9. * The selection rule is: cells in an enlarged spread ellipse
  10. * centered at the current spread cell. The apogee is 1 cell plus
  11. * the integer number of cells of the ratio of the maximum rate
  12. * of spread (ROS) to the base (perpendicular to the max) ROS.
  13. *
  14. * By Jianping Xu, Rutgers University.
  15. * 06/22/93
  16. *
  17. *************************************************************************/
  18. #include <stdio.h>
  19. #include <math.h>
  20. #include <grass/gis.h>
  21. #include <grass/raster.h>
  22. #include "costHa.h"
  23. #include "cell_ptrHa.h"
  24. #include "local_proto.h"
  25. #ifndef PI
  26. #define PI M_PI
  27. #endif
  28. #define DATA(map, r, c) (map)[(r) * ncols + (c)]
  29. /*#define DEBUG */
  30. void select_linksB(struct costHa *pres_cell, int least, float comp_dens)
  31. {
  32. extern CELL *map_max, *map_dir, *map_base; /*for ellipse */
  33. extern CELL *map_visit; /*for avoiding redundancy */
  34. extern int BARRIER;
  35. extern int nrows, ncols;
  36. extern struct cell_ptrHa *front_cell, *rear_cell;
  37. float angle; /*that of a link cell to spread cell */
  38. float dir_angle; /*that of the maximum ROS */
  39. float cos_dir_angle, sin_dir_angle;
  40. float polar_len; /*polar distance of the ellipse */
  41. float distance;
  42. int n = 0, s = 0, e = 0, w = 0; /*parameters defining a rectangule */
  43. int ros_max, ros_base, dir; /*3 params defining an elps */
  44. int row, col;
  45. #ifdef DEBUG
  46. printf("\nin select pres(%d,%d) ", pres_cell->row, pres_cell->col);
  47. #endif
  48. #ifdef DEBUG
  49. for (row = 0; row < nrows; row++) {
  50. printf("\nrow %d: ", row);
  51. for (col = 0; col < ncols; col++)
  52. printf("%d ", DATA(map_base, row, col));
  53. }
  54. #endif
  55. ros_max = DATA(map_max, pres_cell->row, pres_cell->col);
  56. ros_base = DATA(map_base, pres_cell->row, pres_cell->col);
  57. dir = DATA(map_dir, pres_cell->row, pres_cell->col);
  58. dir_angle = dir % 360 * PI / 180;
  59. sin_dir_angle = sin(dir_angle);
  60. cos_dir_angle = cos(dir_angle);
  61. /* identifies a rectangular just enclosing the ellipse,
  62. * thus avoiding redundant work in selection */
  63. if (dir_angle >= 7 * PI / 4 || dir_angle < PI / 4) { /*down mainly N */
  64. n = (ros_max / ros_base - 1) * comp_dens + least;
  65. s = least;
  66. w = (ros_max / ros_base - 1) * comp_dens + least;
  67. e = (ros_max / ros_base - 1) * comp_dens + least;
  68. }
  69. if (dir_angle >= PI / 4 && dir_angle < 3 * PI / 4) { /*down mainly E */
  70. n = (ros_max / ros_base - 1) * comp_dens + least;
  71. s = (ros_max / ros_base - 1) * comp_dens + least;
  72. w = least;
  73. e = (ros_max / ros_base - 1) * comp_dens + least;
  74. }
  75. if (dir_angle >= 3 * PI / 4 && dir_angle < 5 * PI / 4) { /*down mainly S */
  76. n = least;
  77. s = (ros_max / ros_base - 1) * comp_dens + least;
  78. w = (ros_max / ros_base - 1) * comp_dens + least;
  79. e = (ros_max / ros_base - 1) * comp_dens + least;
  80. }
  81. if (dir_angle >= 5 * PI / 4 && dir_angle < 7 * PI / 4) { /*down mainly W */
  82. n = (ros_max / ros_base - 1) * comp_dens + least;
  83. s = (ros_max / ros_base - 1) * comp_dens + least;
  84. w = (ros_max / ros_base - 1) * comp_dens + least;
  85. e = least;
  86. }
  87. if (n > least)
  88. n--;
  89. if (n > least)
  90. n--;
  91. if (s > least)
  92. s--;
  93. if (s > least)
  94. s--;
  95. if (e > least)
  96. e--;
  97. if (e > least)
  98. e--;
  99. if (w > least)
  100. w--;
  101. if (w > least)
  102. w--;
  103. /* collect cells in the elliptical templet, put into a list */
  104. for (row = pres_cell->row - n; row <= pres_cell->row + s; row++) {
  105. if (row < 0 || row >= nrows) /*outside n,s */
  106. continue;
  107. for (col = pres_cell->col - w; col <= pres_cell->col + e; col++) {
  108. G_debug(4,
  109. "(%d, %d) max=%d base=%d dir=%d least=%d n=%d s=%d e=%d w=%d base=%d BARRIER=%d",
  110. row, col, ros_max, ros_base, dir, least, n, s, e, w,
  111. DATA(map_base, row, col), BARRIER);
  112. if (col < 0 || col >= ncols) /*outside e,w */
  113. continue;
  114. G_debug(4,
  115. "(%d, %d) max=%d base=%d dir=%d least=%d n=%d s=%d e=%d w=%d base=%d BARRIER=%d",
  116. row, col, ros_max, ros_base, dir, least, n, s, e, w,
  117. DATA(map_base, row, col), BARRIER);
  118. if (row == pres_cell->row && col == pres_cell->col)
  119. continue; /*spread cell */
  120. G_debug(4,
  121. "(%d, %d) max=%d base=%d dir=%d least=%d n=%d s=%d e=%d w=%d base=%d BARRIER=%d",
  122. row, col, ros_max, ros_base, dir, least, n, s, e, w,
  123. DATA(map_base, row, col), BARRIER);
  124. if (DATA(map_visit, row, col)) /*visited? */
  125. continue;
  126. G_debug(4,
  127. "(%d, %d) max=%d base=%d dir=%d least=%d n=%d s=%d e=%d w=%d base=%d BARRIER=%d",
  128. row, col, ros_max, ros_base, dir, least, n, s, e, w,
  129. DATA(map_base, row, col), BARRIER);
  130. if (DATA(map_base, row, col) == BARRIER) /*barriers */
  131. continue;
  132. G_debug(4,
  133. "(%d, %d) max=%d base=%d dir=%d least=%d n=%d s=%d e=%d w=%d",
  134. row, col, ros_max, ros_base, dir, least, n, s, e, w);
  135. angle =
  136. atan2((double)(col - pres_cell->col),
  137. (double)(pres_cell->row - row));
  138. /*the polar (square) distance of enlarged ellipse */
  139. polar_len =
  140. (1 / (1 - (1 - ros_base / (float)ros_max)
  141. * cos(angle - dir_angle))) *
  142. (1 / (1 - (1 - ros_base / (float)ros_max) *
  143. cos(angle - dir_angle))) + 2 * least * least;
  144. /*the (square) distance to this cell */
  145. distance =
  146. (float)(row - pres_cell->row) * (row - pres_cell->row) +
  147. (col - pres_cell->col) * (col - pres_cell->col);
  148. /*applies the selection rule */
  149. if (distance > polar_len)
  150. continue;
  151. insert2Ha(&front_cell, &rear_cell, (float)angle, row, col);
  152. }
  153. }
  154. }