precomp.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /*
  2. ** Original Algorithm: H. Mitasova, L. Mitas, J. Hofierka, M. Zlocha
  3. ** GRASS Implementation: J. Caplan, M. Ruesink 1995
  4. **
  5. ** US Army Construction Engineering Research Lab, University of Illinois
  6. **
  7. ** Copyright M. Ruesink, J. Caplan, H. Mitasova, L. Mitas, J. Hofierka,
  8. ** M. Zlocha 1995
  9. **
  10. **This program is free software; you can redistribute it and/or
  11. **modify it under the terms of the GNU General Public License
  12. **as published by the Free Software Foundation; either version 2
  13. **of the License, or (at your option) any later version.
  14. **
  15. **This program is distributed in the hope that it will be useful,
  16. **but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. **MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. **GNU General Public License for more details.
  19. **
  20. **You should have received a copy of the GNU General Public License
  21. **along with this program; if not, write to the Free Software
  22. **Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  23. **
  24. */
  25. #include <grass/gis.h>
  26. #include <grass/raster.h>
  27. #include <grass/glocale.h>
  28. #include "r.flow.h"
  29. #include "io.h"
  30. #include "mem.h"
  31. #include "aspect.h"
  32. /* Function prototypes */
  33. static void precompute_aspects(void);
  34. static void reflect_and_sentinel(void);
  35. static void interpolate_border(void);
  36. static void upslope_correction(void);
  37. static void precompute_epsilons(void);
  38. static void precompute_ew_dists(void);
  39. /**************************** PRECOMPUTATION ****************************/
  40. void precompute(void)
  41. {
  42. G_verbose_message(_("Precomputing e/w distances..."));
  43. precompute_ew_dists();
  44. G_verbose_message(_("Precomputing quantization tolerances..."));
  45. precompute_epsilons();
  46. if (parm.up) {
  47. G_verbose_message(_("Precomputing inverted elevations..."));
  48. upslope_correction();
  49. }
  50. if (!parm.aspin) {
  51. G_verbose_message(_("Precomputing interpolated border elevations..."));
  52. interpolate_border();
  53. }
  54. if (!parm.mem) {
  55. if (parm.aspin) {
  56. G_verbose_message(_("Precomputing re-oriented aspects..."));
  57. reflect_and_sentinel();
  58. }
  59. else {
  60. G_verbose_message(_("Precomputing aspects..."));
  61. precompute_aspects();
  62. }
  63. }
  64. }
  65. static void precompute_ew_dists(void)
  66. {
  67. int row;
  68. double northing;
  69. G_begin_distance_calculations();
  70. if (G_projection() == PROJECTION_LL) {
  71. for (row = 0; row < region.rows; row++) {
  72. northing = Rast_row_to_northing(row + 0.5, &region);
  73. ew_dist[row] = G_distance(Rast_col_to_easting(0., &region), northing,
  74. Rast_col_to_easting(1., &region),
  75. northing);
  76. }
  77. }
  78. else
  79. for (row = 0; row < region.rows; row++)
  80. ew_dist[row] = region.ew_res;
  81. }
  82. static void precompute_epsilons(void)
  83. {
  84. int row;
  85. double x, y, t, a;
  86. for (row = 0; row < region.rows; row++) {
  87. x = ew_dist[row];
  88. y = region.ns_res;
  89. if (x < y) {
  90. t = y;
  91. y = x;
  92. x = t;
  93. }
  94. if ((a = atan2(y, x)) <= 0.5 * DEG2RAD) {
  95. if ((G_projection() == PROJECTION_LL))
  96. /* probably this doesn't work at all with LatLong? -MN 2005 */
  97. G_fatal_error(_("Resolution too unbalanced:\n"
  98. "atan2(%f deg, %f deg) =%f < %f tolerance\n"
  99. "please resample input map"),
  100. region.ew_res, region.ns_res, a, 0.5 * DEG2RAD);
  101. else
  102. G_fatal_error(_("Resolution too unbalanced (%f x %f); "
  103. "please resample input map"),
  104. region.ew_res, region.ns_res);
  105. }
  106. epsilon[HORIZ][row] = (y / tan(a - 0.5 * DEG2RAD)) - x;
  107. epsilon[VERT][row] = (x * tan(a + 0.5 * DEG2RAD)) - y;
  108. G_debug(3, "ROW %d: HORIZ %f, VERT %f\n", row, epsilon[HORIZ][row],
  109. epsilon[VERT][row]);
  110. }
  111. }
  112. static void upslope_correction(void)
  113. {
  114. int row, col;
  115. for (row = 0; row < region.rows; row++)
  116. for (col = 0; col < region.cols; col++)
  117. put(el, row, col, -get(el, row, col));
  118. /* rotation of 180 degrees */
  119. if (parm.aspin) {
  120. for (row = 0; row < region.rows; row++) {
  121. for (col = 0; col < region.cols; col++) {
  122. if (aspect(row, col) <= 180)
  123. put(as, row, col, aspect(row, col) + 180);
  124. else if (aspect(row, col) <= 360)
  125. put(as, row, col, aspect(row, col) - 180);
  126. }
  127. }
  128. }
  129. }
  130. static void interpolate_border(void)
  131. {
  132. int i, r = region.rows, c = region.cols;
  133. for (i = 0; i < c; i++) {
  134. put(el, -1, i, get(el, 0, i) * 2 - get(el, 1, i));
  135. put(el, r, i, get(el, r - 1, i) * 2 - get(el, r - 2, i));
  136. }
  137. for (i = 0; i < r; i++) {
  138. put(el, i, -1, get(el, i, 0) * 2 - get(el, i, 1));
  139. put(el, i, c, get(el, i, c - 1) * 2 - get(el, i, c - 2));
  140. }
  141. put(el, -1, -1, 3 * get(el, 0, 0) - get(el, 0, 1) - get(el, 1, 0));
  142. put(el, -1, c,
  143. 3 * get(el, 0, c - 1) - get(el, 0, c - 2) - get(el, 1, c - 1));
  144. put(el, r, -1,
  145. 3 * get(el, r - 1, 0) - get(el, r - 2, 0) - get(el, r - 1, 1));
  146. put(el, r, c,
  147. 3 * get(el, r - 1, c - 1) - get(el, r - 2, c - 1) - get(el, r - 1,
  148. c - 2));
  149. }
  150. static void reflect_and_sentinel(void)
  151. {
  152. int row, col;
  153. /* reflection along diagonal y = x, sentineling of 0 cells */
  154. for (row = 0; row < region.rows; row++) {
  155. for (col = 0; col < region.cols; col++) {
  156. if (aspect(row, col) == 0)
  157. /* put(as, row, col, (int) UNDEF); */
  158. Rast_set_d_null_value(&(as.buf[row][col]), 1);
  159. else if (aspect(row, col) < 90)
  160. put(as, row, col, 90 - aspect(row, col));
  161. else
  162. put(as, row, col, 450 - aspect(row, col));
  163. }
  164. }
  165. }
  166. static void precompute_aspects(void)
  167. {
  168. int row, col;
  169. double d;
  170. DCELL *n, *c, *s, temp;
  171. for (row = 0; row < region.rows; row++) {
  172. n = get_row(el, row - 1);
  173. c = get_row(el, row);
  174. s = get_row(el, row + 1);
  175. d = ew_dist[row];
  176. for (col = 0; col < region.cols; col++) {
  177. temp = aspect_fly(n++, c++, s++, d);
  178. if (temp == UNDEF)
  179. Rast_set_d_null_value(&(as.buf[row][col]), 1);
  180. else
  181. put(as, row, col, temp);
  182. }
  183. }
  184. }