3scan.h 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. /****************************************************************************
  2. *
  3. * MODULE: r.terraflow
  4. *
  5. * COPYRIGHT (C) 2007 Laura Toma
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. *****************************************************************************/
  18. #ifndef __3SCAN_H
  19. #define __3SCAN_H
  20. #include <iostream>
  21. #include <grass/iostream/ami.h>
  22. #include "types.h"
  23. /* ********************************************************************** */
  24. template<class T, class BASETYPE, class FUN>
  25. void
  26. scan3line(FUN &funobj,
  27. AMI_STREAM<T> *prev,
  28. AMI_STREAM<T> *crt,
  29. AMI_STREAM<T> *next,
  30. BASETYPE nodata,
  31. dimension_type i) {
  32. dimension_type j=0;
  33. AMI_err ae;
  34. BASETYPE a[3], b[3], c[3];
  35. T *tmp, center[2];
  36. int done;
  37. /* LOG_DEBUG_ID("scan3line: begin");
  38. if(prev) LOG_DEBUG_ID(prev->sprint());
  39. if(crt) LOG_DEBUG_ID(crt->sprint());
  40. if(next) LOG_DEBUG_ID(next->sprint());
  41. */
  42. /* seek 0 */
  43. if (prev) {
  44. ae = prev->seek(0);
  45. assert(ae == AMI_ERROR_NO_ERROR);
  46. }
  47. assert(crt);
  48. ae = crt->seek(0);
  49. assert(ae == AMI_ERROR_NO_ERROR);
  50. if (next) {
  51. ae = next->seek(0);
  52. assert(ae == AMI_ERROR_NO_ERROR);
  53. }
  54. /* read first 2 elements of each line */
  55. /* read prev */
  56. a[0] = b[0] = c[0] = nodata;
  57. if (prev) {
  58. ae = prev->read_item(&tmp);
  59. assert(ae == AMI_ERROR_NO_ERROR);
  60. a[1] = *tmp;
  61. ae = prev->read_item(&tmp);
  62. assert(ae == AMI_ERROR_NO_ERROR);
  63. a[2] = *tmp;
  64. } else {
  65. a[1] = a[2] = nodata;
  66. }
  67. /* read crt */
  68. ae = crt->read_item(&tmp);
  69. assert(ae == AMI_ERROR_NO_ERROR);
  70. center[0] = *tmp;
  71. b[1] = *tmp;
  72. ae = crt->read_item(&tmp);
  73. assert(ae == AMI_ERROR_NO_ERROR);
  74. center[1] = *tmp;
  75. b[2] = *tmp;
  76. /* read next */
  77. if (next) {
  78. ae = next->read_item(&tmp);
  79. assert(ae == AMI_ERROR_NO_ERROR);
  80. c[1] = *tmp;
  81. ae = next->read_item(&tmp);
  82. assert(ae == AMI_ERROR_NO_ERROR);
  83. c[2] = *tmp;
  84. } else {
  85. c[1] = c[2] = nodata;
  86. }
  87. done = 0;
  88. do {
  89. funobj.processWindow(i, j, center[0], a, b, c); /* process current window*/
  90. /* slide one over */
  91. a[0] = a[1]; a[1] = a[2];
  92. b[0] = b[1]; b[1] = b[2];
  93. center[0] = center[1];
  94. c[0] = c[1]; c[1] = c[2];
  95. j++;
  96. /* read next item from crt and check for EOS */
  97. ae = crt->read_item(&tmp);
  98. if (ae == AMI_ERROR_END_OF_STREAM) {
  99. done = 1;
  100. b[2] = nodata;
  101. center[1] = T();
  102. } else {
  103. assert(ae == AMI_ERROR_NO_ERROR);
  104. b[2] = *tmp;
  105. center[1] = *tmp;
  106. }
  107. /* read next item from prev */
  108. if (prev) {
  109. ae = prev->read_item(&tmp);
  110. if (!done) {
  111. assert(ae == AMI_ERROR_NO_ERROR);
  112. a[2]=*tmp;
  113. } else {
  114. a[2] = nodata;
  115. assert(ae == AMI_ERROR_END_OF_STREAM);
  116. }
  117. } else {
  118. a[2] = nodata;
  119. }
  120. /* read next item from next */
  121. if (next) {
  122. ae = next->read_item(&tmp);
  123. if (!done) {
  124. assert(ae == AMI_ERROR_NO_ERROR);
  125. c[2] = *tmp;
  126. } else {
  127. c[2] = nodata;
  128. assert(ae == AMI_ERROR_END_OF_STREAM);
  129. }
  130. } else {
  131. c[2] = nodata;
  132. }
  133. } while (!done);
  134. /* write last window */
  135. funobj.processWindow(i, j, center[0], a, b, c); /* process current window */
  136. /* LOG_DEBUG_ID("scan3line: end"); */
  137. return;
  138. }
  139. /****************************************************************/
  140. /* amis0 = data (T) in
  141. */
  142. template<class T, class BASETYPE, class FUN>
  143. void
  144. scan3(AMI_STREAM<T> &amis0,
  145. const dimension_type nr, const dimension_type nc, BASETYPE nodata,
  146. FUN &funobj) {
  147. AMI_STREAM<T> *l_prev, *l_crt, *l_next;
  148. AMI_err ae;
  149. ae = amis0.seek(0);
  150. assert( ae == AMI_ERROR_NO_ERROR);
  151. /* scan simultaneously 3 lines in the grid and fill in the windows
  152. use a substream for each line to trigger prefetching */
  153. /* initialize first 2 lines */
  154. ae = amis0.new_substream(AMI_READ_STREAM, 0, nc-1, &l_crt);
  155. assert( ae == AMI_ERROR_NO_ERROR);
  156. ae = amis0.new_substream(AMI_READ_STREAM, nc, 2*nc-1, &l_next);
  157. assert( ae == AMI_ERROR_NO_ERROR);
  158. /* LOG_DEBUG_ID("substreams created"); */
  159. /* process lines, 3 at a time */
  160. l_prev = NULL;
  161. for (dimension_type i=0;i<nr;i++) {
  162. /* process current line */
  163. scan3line(funobj, l_prev, l_crt, l_next, nodata, i);
  164. /* advance lines */
  165. if (l_prev) delete l_prev;
  166. l_prev = l_crt;
  167. l_crt = l_next;
  168. if (i < nr-2) {
  169. ae = amis0.new_substream(AMI_READ_STREAM, (i+2)*nc, (i+3)*nc-1,
  170. &l_next);
  171. assert(ae == AMI_ERROR_NO_ERROR);
  172. } else {
  173. l_next = NULL;
  174. }
  175. }
  176. if (l_prev) delete l_prev;
  177. assert(!l_crt);
  178. /* LOG_DEBUG_ID("scan3: end"); */
  179. return;
  180. }
  181. /* ********************************************************************** */
  182. template<class T>
  183. T *
  184. readLine(T *buf, AMI_STREAM<T> &str, const dimension_type len,
  185. const T &nodata) {
  186. AMI_err ae;
  187. buf[0] = nodata;
  188. buf[len+1] = nodata;
  189. for(dimension_type i=0; i<len; i++) {
  190. T *tmp;
  191. ae = str.read_item(&tmp);
  192. assert(ae==AMI_ERROR_NO_ERROR);
  193. buf[i+1] = *tmp;
  194. }
  195. return buf;
  196. }
  197. /* ********************************************************************** */
  198. template<class T>
  199. T *
  200. setNodata(T *buf, const dimension_type len, const T &nodata) {
  201. for(dimension_type j=0; j<len+2; j++) {
  202. buf[j] = nodata;
  203. }
  204. return buf;
  205. }
  206. /* ********************************************************************** */
  207. /* memoryScan
  208. *
  209. * calls fo.processWindow(i,j, a,b,c) once for each element of the
  210. * grid. i,j are the coordinates in the grid. a,b,c together point
  211. * to the grid surrounding the cell. (b[1] corresponds to cell i,j).
  212. * */
  213. template<class T, class FUN>
  214. void
  215. memoryScan(AMI_STREAM<T> &str,
  216. const dimension_type nrows, const dimension_type ncols,
  217. const T nodata,
  218. FUN &fo) {
  219. T *a, *b, *c;
  220. T *buf[3];
  221. str.seek(0);
  222. assert(nrows > 1);
  223. assert(nrows * ncols == str.stream_len());
  224. buf[0] = new T[ncols+2];
  225. buf[1] = new T[ncols+2];
  226. buf[2] = new T[ncols+2];
  227. unsigned int k;
  228. a = setNodata(buf[0], ncols, nodata);
  229. b = readLine(buf[1], str, ncols, nodata);
  230. k = 2;
  231. for(dimension_type i=0; i<nrows-1; i++) {
  232. c = readLine(buf[k], str, ncols, nodata);
  233. for(dimension_type j=0; j<ncols; j++) {
  234. fo.processWindow(i, j, a+j, b+j, c+j);
  235. }
  236. k = (k+1)%3;
  237. a = b;
  238. b = c;
  239. }
  240. c = setNodata(buf[k], ncols, nodata);
  241. for(dimension_type j=0; j<ncols; j++) {
  242. fo.processWindow(nrows-1, j, a+j, b+j, c+j);
  243. }
  244. delete [] buf[2];
  245. delete [] buf[1];
  246. delete [] buf[0];
  247. }
  248. /* ********************************************************************** */
  249. /* this version uses two streams to make the windows
  250. * FUN should provide a function:
  251. * processWindow(dimension_type i, dimension_type j,
  252. * T1* a1, T1* b1, T1* c1,
  253. * T2* a2, T2* b2, T2* c2)
  254. */
  255. template<class T1, class T2, class FUN>
  256. void
  257. memoryScan(AMI_STREAM<T1> &str1, AMI_STREAM<T2> &str2,
  258. const dimension_type nrows, const dimension_type ncols,
  259. const T1 nodata1, const T2 nodata2,
  260. FUN &fo) {
  261. T1 *a1, *b1, *c1;
  262. T1 *buf1[3];
  263. T2 *a2, *b2, *c2;
  264. T2 *buf2[3];
  265. str1.seek(0);
  266. str2.seek(0);
  267. assert(nrows > 1);
  268. assert(nrows * ncols == str1.stream_len());
  269. assert(nrows * ncols == str2.stream_len());
  270. buf1[0] = new T1[ncols+2];
  271. buf1[1] = new T1[ncols+2];
  272. buf1[2] = new T1[ncols+2];
  273. buf2[0] = new T2[ncols+2];
  274. buf2[1] = new T2[ncols+2];
  275. buf2[2] = new T2[ncols+2];
  276. unsigned int k;
  277. a1 = setNodata(buf1[0], ncols, nodata1);
  278. a2 = setNodata(buf2[0], ncols, nodata2);
  279. b1 = readLine(buf1[1], str1, ncols, nodata1);
  280. b2 = readLine(buf2[1], str2, ncols, nodata2);
  281. k = 2;
  282. for(dimension_type i=0; i<nrows-1; i++) {
  283. c1 = readLine(buf1[k], str1, ncols, nodata1);
  284. c2 = readLine(buf2[k], str2, ncols, nodata2);
  285. for(dimension_type j=0; j<ncols; j++) {
  286. fo.processWindow(i, j, a1+j, b1+j, c1+j,
  287. a2+j, b2+j, c2+j);
  288. }
  289. k = (k+1)%3;
  290. a1 = b1;
  291. a2 = b2;
  292. b1 = c1;
  293. b2 = c2;
  294. }
  295. c1 = setNodata(buf1[k], ncols, nodata1);
  296. c2 = setNodata(buf2[k], ncols, nodata2);
  297. for(dimension_type j=0; j<ncols; j++) {
  298. fo.processWindow(nrows-1, j, a1+j, b1+j, c1+j,
  299. a2+j, b2+j, c2+j);
  300. }
  301. delete [] buf1[2];
  302. delete [] buf1[1];
  303. delete [] buf1[0];
  304. delete [] buf2[2];
  305. delete [] buf2[1];
  306. delete [] buf2[0];
  307. }
  308. #endif