main.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. /*
  2. *
  3. *****************************************************************************
  4. *
  5. * MODULE: r.fill.dir
  6. * AUTHOR(S): Original author unknown - Raghavan Srinivasan Nov, 1991
  7. * (srin@ecn.purdue.edu) Agricultural Engineering,
  8. * Purdue University
  9. * Markus Neteler: update to FP (C-code)
  10. * : update to FP (Fortran)
  11. * Roger Miller: rewrite all code in C, complient with GRASS 5
  12. * PURPOSE: fills a DEM to become a depression-less DEM
  13. * This creates two layers from a user specified elevation map.
  14. * The output maps are filled elevation or rectified elevation
  15. * map and a flow direction map based on one of the type
  16. * specified. The filled or rectified elevation map generated
  17. * will be filled for depression, removed any circularity or
  18. * conflict flow direction is resolved. This program helps to
  19. * get a proper elevation map that could be used for
  20. * delineating watershed using r.watershed module. However, the
  21. * boundaries may have problem and could be resolved using
  22. * the cell editor d.rast.edit
  23. * Options have been added to produce a map of undrained areas
  24. * and to run without filling undrained areas except single-cell
  25. * pits. Not all problems can be solved in a single pass. The
  26. * program can be run repeatedly, using the output elevations from
  27. * one run as input to the next run until all problems are
  28. * resolved.
  29. * COPYRIGHT: (C) 2001, 2010 by the GRASS Development Team
  30. *
  31. * This program is free software under the GNU General Public
  32. * License (>=v2). Read the file COPYING that comes with GRASS
  33. * for details.
  34. *
  35. *****************************************************************************/
  36. #include <stdlib.h>
  37. #include <stdio.h>
  38. #include <string.h>
  39. #include <math.h>
  40. /* for using the "open" statement */
  41. #include <sys/types.h>
  42. #include <sys/stat.h>
  43. #include <fcntl.h>
  44. /* for using the close statement */
  45. #include <unistd.h>
  46. #include <grass/gis.h>
  47. #include <grass/raster.h>
  48. #include <grass/glocale.h>
  49. #define DEBUG
  50. #include "tinf.h"
  51. #include "local.h"
  52. static int dir_type(int type, int dir);
  53. int main(int argc, char **argv)
  54. {
  55. int fe, fd, fm;
  56. int i, j, type;
  57. int new_id;
  58. int nrows, ncols, nbasins;
  59. int map_id, dir_id, bas_id;
  60. char map_name[GNAME_MAX], new_map_name[GNAME_MAX];
  61. const char *tempfile1, *tempfile2, *tempfile3;
  62. char dir_name[GNAME_MAX];
  63. char bas_name[GNAME_MAX];
  64. struct Cell_head window;
  65. struct GModule *module;
  66. struct Option *opt1, *opt2, *opt3, *opt4, *opt5;
  67. struct Flag *flag1;
  68. int in_type, bufsz;
  69. void *in_buf;
  70. CELL *out_buf;
  71. struct band3 bnd, bndC;
  72. struct Colors colors;
  73. /* Initialize the GRASS environment variables */
  74. G_gisinit(argv[0]);
  75. module = G_define_module();
  76. G_add_keyword(_("raster"));
  77. G_add_keyword(_("hydrology"));
  78. G_add_keyword(_("sink"));
  79. G_add_keyword(_("fill sinks"));
  80. G_add_keyword(_("depressions"));
  81. module->description =
  82. _("Filters and generates a depressionless elevation map and a "
  83. "flow direction map from a given elevation raster map.");
  84. opt1 = G_define_standard_option(G_OPT_R_ELEV);
  85. opt1->key = "input";
  86. opt2 = G_define_standard_option(G_OPT_R_OUTPUT);
  87. opt2->description = _("Name for output depressionless elevation raster map");
  88. opt4 = G_define_standard_option(G_OPT_R_OUTPUT);
  89. opt4->key = "direction";
  90. opt4->description = _("Name for output flow direction map for depressionless elevation raster map");
  91. opt5 = G_define_standard_option(G_OPT_R_OUTPUT);
  92. opt5->key = "areas";
  93. opt5->required = NO;
  94. opt5->description = _("Name for output raster map of problem areas");
  95. opt3 = G_define_option();
  96. opt3->key = "format";
  97. opt3->type = TYPE_STRING;
  98. opt3->required = NO;
  99. opt3->description =
  100. _("Aspect direction format");
  101. opt3->options = "agnps,answers,grass";
  102. opt3->answer = "grass";
  103. flag1 = G_define_flag();
  104. flag1->key = 'f';
  105. flag1->description = _("Find unresolved areas only");
  106. if (G_parser(argc, argv))
  107. exit(EXIT_FAILURE);
  108. if (flag1->answer && opt5->answer == NULL) {
  109. G_fatal_error(_("The '%c' flag requires '%s'to be specified"),
  110. flag1->key, opt5->key);
  111. }
  112. type = 0;
  113. strcpy(map_name, opt1->answer);
  114. strcpy(new_map_name, opt2->answer);
  115. strcpy(dir_name, opt4->answer);
  116. if (opt5->answer != NULL)
  117. strcpy(bas_name, opt5->answer);
  118. if (strcmp(opt3->answer, "agnps") == 0)
  119. type = 1;
  120. else if (strcmp(opt3->answer, "answers") == 0)
  121. type = 2;
  122. else if (strcmp(opt3->answer, "grass") == 0)
  123. type = 3;
  124. G_debug(1, "output type (1=AGNPS, 2=ANSWERS, 3=GRASS): %d", type);
  125. if (type == 3)
  126. G_verbose_message(_("Direction map is D8 resolution, i.e. 45 degrees"));
  127. /* open the maps and get their file id */
  128. map_id = Rast_open_old(map_name, "");
  129. if (Rast_read_colors(map_name, "", &colors) < 0)
  130. G_warning(_("Unable to read color table for raster map <%s>"), map_name);
  131. /* allocate cell buf for the map layer */
  132. in_type = Rast_get_map_type(map_id);
  133. /* set the pointers for multi-typed functions */
  134. set_func_pointers(in_type);
  135. /* get the window information */
  136. G_get_window(&window);
  137. nrows = Rast_window_rows();
  138. ncols = Rast_window_cols();
  139. /* buffers for internal use */
  140. bndC.ns = ncols;
  141. bndC.sz = sizeof(CELL) * ncols;
  142. bndC.b[0] = G_calloc(ncols, sizeof(CELL));
  143. bndC.b[1] = G_calloc(ncols, sizeof(CELL));
  144. bndC.b[2] = G_calloc(ncols, sizeof(CELL));
  145. /* buffers for external use */
  146. bnd.ns = ncols;
  147. bnd.sz = ncols * bpe();
  148. bnd.b[0] = G_calloc(ncols, bpe());
  149. bnd.b[1] = G_calloc(ncols, bpe());
  150. bnd.b[2] = G_calloc(ncols, bpe());
  151. in_buf = get_buf();
  152. tempfile1 = G_tempfile();
  153. tempfile2 = G_tempfile();
  154. tempfile3 = G_tempfile();
  155. fe = open(tempfile1, O_RDWR | O_CREAT, 0666); /* elev */
  156. fd = open(tempfile2, O_RDWR | O_CREAT, 0666); /* dirn */
  157. fm = open(tempfile3, O_RDWR | O_CREAT, 0666); /* problems */
  158. G_message(_("Reading input elevation raster map..."));
  159. for (i = 0; i < nrows; i++) {
  160. G_percent(i, nrows, 2);
  161. get_row(map_id, in_buf, i);
  162. write(fe, in_buf, bnd.sz);
  163. }
  164. G_percent(1, 1, 1);
  165. Rast_close(map_id);
  166. /* fill single-cell holes and take a first stab at flow directions */
  167. G_message(_("Filling sinks..."));
  168. filldir(fe, fd, nrows, &bnd);
  169. /* determine flow directions for ambiguous cases */
  170. G_message(_("Determining flow directions for ambiguous cases..."));
  171. resolve(fd, nrows, &bndC);
  172. /* mark and count the sinks in each internally drained basin */
  173. nbasins = dopolys(fd, fm, nrows, ncols);
  174. if (!flag1->answer) {
  175. /* determine the watershed for each sink */
  176. wtrshed(fm, fd, nrows, ncols, 4);
  177. /* fill all of the watersheds up to the elevation necessary for drainage */
  178. ppupdate(fe, fm, nrows, nbasins, &bnd, &bndC);
  179. /* repeat the first three steps to get the final directions */
  180. G_message(_("Repeat to get the final directions..."));
  181. filldir(fe, fd, nrows, &bnd);
  182. resolve(fd, nrows, &bndC);
  183. nbasins = dopolys(fd, fm, nrows, ncols);
  184. }
  185. G_free(bndC.b[0]);
  186. G_free(bndC.b[1]);
  187. G_free(bndC.b[2]);
  188. G_free(bnd.b[0]);
  189. G_free(bnd.b[1]);
  190. G_free(bnd.b[2]);
  191. out_buf = Rast_allocate_c_buf();
  192. bufsz = ncols * sizeof(CELL);
  193. lseek(fe, 0, SEEK_SET);
  194. new_id = Rast_open_new(new_map_name, in_type);
  195. lseek(fd, 0, SEEK_SET);
  196. dir_id = Rast_open_new(dir_name, CELL_TYPE);
  197. if (opt5->answer != NULL) {
  198. lseek(fm, 0, SEEK_SET);
  199. bas_id = Rast_open_new(bas_name, CELL_TYPE);
  200. for (i = 0; i < nrows; i++) {
  201. read(fm, out_buf, bufsz);
  202. Rast_put_row(bas_id, out_buf, CELL_TYPE);
  203. }
  204. Rast_close(bas_id);
  205. close(fm);
  206. }
  207. G_important_message(_("Writing output raster maps..."));
  208. for (i = 0; i < nrows; i++) {
  209. G_percent(i, nrows, 5);
  210. read(fe, in_buf, bnd.sz);
  211. put_row(new_id, in_buf);
  212. read(fd, out_buf, bufsz);
  213. for (j = 0; j < ncols; j += 1)
  214. out_buf[j] = dir_type(type, out_buf[j]);
  215. Rast_put_row(dir_id, out_buf, CELL_TYPE);
  216. }
  217. G_percent(1, 1, 1);
  218. /* copy color table from input */
  219. Rast_write_colors(new_map_name, G_mapset(), &colors);
  220. Rast_close(new_id);
  221. close(fe);
  222. Rast_close(dir_id);
  223. close(fd);
  224. unlink(tempfile1);
  225. unlink(tempfile2);
  226. unlink(tempfile3);
  227. G_free(in_buf);
  228. G_free(out_buf);
  229. exit(EXIT_SUCCESS);
  230. }
  231. static int dir_type(int type, int dir)
  232. {
  233. if (type == 1) { /* AGNPS aspect format */
  234. if (dir == 128)
  235. return (1);
  236. else if (dir == 1)
  237. return (2);
  238. else if (dir == 2)
  239. return (3);
  240. else if (dir == 4)
  241. return (4);
  242. else if (dir == 8)
  243. return (5);
  244. else if (dir == 16)
  245. return (6);
  246. else if (dir == 32)
  247. return (7);
  248. else if (dir == 64)
  249. return (8);
  250. else
  251. return (dir);
  252. }
  253. else if (type == 2) { /* ANSWERS aspect format */
  254. if (dir == 128)
  255. return (90);
  256. else if (dir == 1)
  257. return (45);
  258. else if (dir == 2)
  259. return (360);
  260. else if (dir == 4)
  261. return (315);
  262. else if (dir == 8)
  263. return (270);
  264. else if (dir == 16)
  265. return (225);
  266. else if (dir == 32)
  267. return (180);
  268. else if (dir == 64)
  269. return (135);
  270. else
  271. return (dir);
  272. }
  273. else { /* [new] GRASS aspect format */
  274. if (dir == 128)
  275. return (90);
  276. else if (dir == 1)
  277. return (45);
  278. else if (dir == 2)
  279. return (360);
  280. else if (dir == 4)
  281. return (315);
  282. else if (dir == 8)
  283. return (270);
  284. else if (dir == 16)
  285. return (225);
  286. else if (dir == 32)
  287. return (180);
  288. else if (dir == 64)
  289. return (135);
  290. else
  291. return (dir);
  292. }
  293. }