process.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. /*****************************************************************************/
  2. /*** ***/
  3. /*** process() ***/
  4. /*** Reads in a raster map row by row for processing. ***/
  5. /*** Jo Wood, Project ASSIST, V1.0 7th February 1993 ***/
  6. /*** ***/
  7. /*****************************************************************************/
  8. #include <stdlib.h>
  9. #include <grass/gis.h>
  10. #include <grass/raster.h>
  11. #include <grass/glocale.h>
  12. #include <grass/gmath.h>
  13. #include "param.h"
  14. #include "nrutil.h"
  15. void process(void)
  16. {
  17. /*--------------------------------------------------------------------------*/
  18. /* INITIALISE */
  19. /*--------------------------------------------------------------------------*/
  20. DCELL *row_in, /* Buffer large enough to hold `wsize' */
  21. *row_out = NULL, /* raster rows. When GRASS reads in a */
  22. /* raster row, each element is of type */
  23. /* DCELL */
  24. *window_ptr, /* Stores local terrain window. */
  25. centre, /* Elevation of central cell in window. */
  26. *window_cell; /* Stores last read cell in window. */
  27. CELL *featrow_out = NULL; /* store features in CELL */
  28. struct Cell_head region; /* Structure to hold region information */
  29. int nrows, /* Will store the current number of */
  30. ncols, /* rows and columns in the raster. */
  31. row, col, /* Counts through each row and column */
  32. /* of the input raster. */
  33. wind_row, /* Counts through each row and column */
  34. wind_col, /* of the local neighbourhood window. */
  35. *index_ptr; /* Row permutation vector for LU decomp. */
  36. double **normal_ptr, /* Cross-products matrix. */
  37. *obs_ptr, /* Observed vector. */
  38. temp; /* Unused */
  39. double *weight_ptr; /* Weighting matrix for observed values. */
  40. int found_null; /* If null was found among window cells */
  41. /*--------------------------------------------------------------------------*/
  42. /* GET RASTER AND WINDOW DETAILS */
  43. /*--------------------------------------------------------------------------*/
  44. G_get_window(&region); /* Fill out the region structure (the */
  45. /* geographical limits etc.) */
  46. nrows = Rast_window_rows(); /* Find out the number of rows and */
  47. ncols = Rast_window_cols(); /* columns of the raster. */
  48. if ((region.ew_res / region.ns_res >= 1.01) || /* If EW and NS resolns are */
  49. (region.ns_res / region.ew_res >= 1.01)) { /* >1% different, warn user. */
  50. G_warning(_("E-W and N-S grid resolutions are different. Taking average."));
  51. resoln = (region.ns_res + region.ew_res) / 2;
  52. }
  53. else
  54. resoln = region.ns_res;
  55. /*--------------------------------------------------------------------------*/
  56. /* RESERVE MEMORY TO HOLD Z VALUES AND MATRICES */
  57. /*--------------------------------------------------------------------------*/
  58. row_in = (DCELL *) G_malloc(ncols * sizeof(DCELL) * wsize);
  59. /* Reserve `wsize' rows of memory. */
  60. if (mparam != FEATURE) {
  61. row_out = Rast_allocate_buf(DCELL_TYPE); /* Initialise output row buffer. */
  62. Rast_set_d_null_value(row_out, ncols);
  63. }
  64. else {
  65. featrow_out = Rast_allocate_buf(CELL_TYPE); /* Initialise output row buffer. */
  66. Rast_set_c_null_value(featrow_out, ncols);
  67. }
  68. window_ptr = (DCELL *) G_malloc(SQR(wsize) * sizeof(DCELL));
  69. /* Reserve enough memory for local wind. */
  70. weight_ptr = (double *)G_malloc(SQR(wsize) * sizeof(double));
  71. /* Reserve enough memory weights matrix. */
  72. normal_ptr = dmatrix(0, 5, 0, 5); /* Allocate memory for 6*6 matrix */
  73. index_ptr = ivector(0, 5); /* and for 1D vector holding indices */
  74. obs_ptr = dvector(0, 5); /* and for 1D vector holding observed z */
  75. /* ---------------------------------------------------------------- */
  76. /* - CALCULATE LEAST SQUARES COEFFICIENTS - */
  77. /* ---------------------------------------------------------------- */
  78. /*--- Calculate weighting matrix. ---*/
  79. find_weight(weight_ptr);
  80. /* Initial coefficients need only be found once since they are
  81. constant for any given window size. The only element that
  82. changes is the observed vector (RHS of normal equations). */
  83. /*--- Find normal equations in matrix form. ---*/
  84. find_normal(normal_ptr, weight_ptr);
  85. /*--- Apply LU decomposition to normal equations. ---*/
  86. if (constrained) {
  87. G_ludcmp(normal_ptr, 5, index_ptr, &temp);
  88. /* To constrain the quadtratic
  89. through the central cell, ignore
  90. the calculations involving the
  91. coefficient f. Since these are
  92. all in the last row and column of
  93. the matrix, simply redimension. */
  94. /* disp_matrix(normal_ptr,obs_ptr,obs_ptr,5);
  95. */
  96. }
  97. else {
  98. G_ludcmp(normal_ptr, 6, index_ptr, &temp);
  99. /* disp_matrix(normal_ptr,obs_ptr,obs_ptr,6);
  100. */
  101. }
  102. /*--------------------------------------------------------------------------*/
  103. /* PROCESS INPUT RASTER AND WRITE OUT RASTER LINE BY LINE */
  104. /*--------------------------------------------------------------------------*/
  105. if (mparam != FEATURE)
  106. for (wind_row = 0; wind_row < EDGE; wind_row++)
  107. Rast_put_row(fd_out, row_out, DCELL_TYPE); /* Write out the edge cells as NULL. */
  108. else
  109. for (wind_row = 0; wind_row < EDGE; wind_row++)
  110. Rast_put_row(fd_out, featrow_out, CELL_TYPE); /* Write out the edge cells as NULL. */
  111. for (wind_row = 0; wind_row < wsize - 1; wind_row++)
  112. Rast_get_row(fd_in, row_in + (wind_row * ncols), wind_row,
  113. DCELL_TYPE);
  114. /* Read in enough of the first rows to */
  115. /* allow window to be examined. */
  116. for (row = EDGE; row < (nrows - EDGE); row++) {
  117. G_percent(row + 1, nrows - EDGE, 2);
  118. Rast_get_row(fd_in, row_in + ((wsize - 1) * ncols), row + EDGE,
  119. DCELL_TYPE);
  120. for (col = EDGE; col < (ncols - EDGE); col++) {
  121. /* Find central z value */
  122. centre = *(row_in + EDGE * ncols + col);
  123. /* Test for no data and propagate */
  124. if (Rast_is_d_null_value(&centre)) {
  125. if (mparam == FEATURE)
  126. Rast_set_c_null_value(featrow_out + col, 1);
  127. else {
  128. Rast_set_d_null_value(row_out + col, 1);
  129. }
  130. continue;
  131. }
  132. found_null = FALSE;
  133. for (wind_row = 0; wind_row < wsize; wind_row++) {
  134. if (found_null)
  135. break;
  136. for (wind_col = 0; wind_col < wsize; wind_col++) {
  137. /* Express all window values relative */
  138. /* to the central elevation. */
  139. window_cell = row_in + (wind_row * ncols) + col + wind_col - EDGE;
  140. /* Test for no data and propagate */
  141. if (Rast_is_d_null_value(window_cell)) {
  142. if (mparam == FEATURE)
  143. Rast_set_c_null_value(featrow_out + col, 1);
  144. else {
  145. Rast_set_d_null_value(row_out + col, 1);
  146. }
  147. found_null = TRUE;
  148. break;
  149. }
  150. *(window_ptr + (wind_row * wsize) + wind_col) =
  151. *(window_cell) - centre;
  152. }
  153. }
  154. if (found_null)
  155. continue;
  156. /*--- Use LU back substitution to solve normal equations. ---*/
  157. find_obs(window_ptr, obs_ptr, weight_ptr);
  158. /* disp_wind(window_ptr);
  159. disp_matrix(normal_ptr,obs_ptr,obs_ptr,6);
  160. */
  161. if (constrained) {
  162. G_lubksb(normal_ptr, 5, index_ptr, obs_ptr);
  163. /*
  164. disp_matrix(normal_ptr,obs_ptr,obs_ptr,5);
  165. */
  166. }
  167. else {
  168. G_lubksb(normal_ptr, 6, index_ptr, obs_ptr);
  169. /*
  170. disp_matrix(normal_ptr,obs_ptr,obs_ptr,6);
  171. */
  172. }
  173. /*--- Calculate terrain parameter based on quad. coefficients. ---*/
  174. if (mparam == FEATURE)
  175. *(featrow_out + col) = (CELL) feature(obs_ptr);
  176. else
  177. *(row_out + col) = param(mparam, obs_ptr);
  178. if (mparam == ELEV)
  179. *(row_out + col) += centre; /* Add central elevation back */
  180. }
  181. if (mparam != FEATURE)
  182. Rast_put_row(fd_out, row_out, DCELL_TYPE); /* Write the row buffer to the output */
  183. /* raster. */
  184. else /* write FEATURE to CELL */
  185. Rast_put_row(fd_out, featrow_out, CELL_TYPE); /* Write the row buffer to the output */
  186. /* raster. */
  187. /* 'Shuffle' rows down one, and read in */
  188. /* one new row. */
  189. for (wind_row = 0; wind_row < wsize - 1; wind_row++)
  190. for (col = 0; col < ncols; col++)
  191. *(row_in + (wind_row * ncols) + col) =
  192. *(row_in + ((wind_row + 1) * ncols) + col);
  193. }
  194. if (mparam != FEATURE)
  195. Rast_set_d_null_value(row_out, ncols);
  196. else
  197. Rast_set_c_null_value(featrow_out, ncols);
  198. for (wind_row = 0; wind_row < EDGE; wind_row++) {
  199. if (mparam != FEATURE)
  200. Rast_put_row(fd_out, row_out, DCELL_TYPE); /* Write out the edge cells as NULL. */
  201. else
  202. Rast_put_row(fd_out, featrow_out, CELL_TYPE); /* Write out the edge cells as NULL. */
  203. }
  204. /*--------------------------------------------------------------------------*/
  205. /* FREE MEMORY USED TO STORE RASTER ROWS, LOCAL WINDOW AND MATRICES */
  206. /*--------------------------------------------------------------------------*/
  207. G_free(row_in);
  208. if (mparam != FEATURE)
  209. G_free(row_out);
  210. else
  211. G_free(featrow_out);
  212. G_free(window_ptr);
  213. free_dmatrix(normal_ptr, 0, 5, 0, 5);
  214. free_dvector(obs_ptr, 0, 5);
  215. free_ivector(index_ptr, 0, 5);
  216. }