main.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. /****************************************************************************
  2. *
  3. * MODULE: front end
  4. * AUTHOR(S): Charles Ehlschlaeger, CERL (original contributor)
  5. * Brad Douglas <rez touchofmadness.com>,
  6. * Hamish Bowman <hamish_b yahoo.com>
  7. * Markus Metz <markus.metz.giswork gmail.com>
  8. * PURPOSE: Hydrological analysis
  9. * COPYRIGHT: (C) 1999-2009 by the GRASS Development Team
  10. *
  11. * This program is free software under the GNU General Public
  12. * License (>=v2). Read the file COPYING that comes with GRASS
  13. * for details.
  14. *
  15. *****************************************************************************/
  16. #include <stdlib.h>
  17. #include <stdio.h>
  18. #include <string.h>
  19. #include <grass/gis.h>
  20. #include <grass/raster.h>
  21. #include <grass/glocale.h>
  22. #include <grass/spawn.h>
  23. static void write_hist(char *, char *, char *, int, int);
  24. static const char *new_argv[22];
  25. static int new_argc;
  26. static void do_opt(const struct Option *opt)
  27. {
  28. char *buf;
  29. if (!opt->answer)
  30. return;
  31. buf = G_malloc(strlen(opt->key) + 1 + strlen(opt->answer) + 1);
  32. sprintf(buf, "%s=%s", opt->key, opt->answer);
  33. new_argv[new_argc++] = buf;
  34. }
  35. int main(int argc, char *argv[])
  36. {
  37. char command[GPATH_MAX];
  38. int err, ret;
  39. struct Option *opt1;
  40. struct Option *opt2;
  41. struct Option *opt3;
  42. struct Option *opt4;
  43. struct Option *opt5;
  44. struct Option *opt6;
  45. struct Option *opt7;
  46. struct Option *opt8;
  47. struct Option *opt9;
  48. struct Option *opt10;
  49. struct Option *opt11;
  50. struct Option *opt12;
  51. struct Option *opt13;
  52. struct Option *opt14;
  53. struct Option *opt15;
  54. struct Option *opt16;
  55. struct Option *opt17;
  56. struct Flag *flag_sfd;
  57. struct Flag *flag_flow;
  58. struct Flag *flag_seg;
  59. struct Flag *flag_abs;
  60. struct Flag *flag_flat;
  61. struct GModule *module;
  62. G_gisinit(argv[0]);
  63. /* Set description */
  64. module = G_define_module();
  65. G_add_keyword(_("raster"));
  66. G_add_keyword(_("hydrology"));
  67. G_add_keyword(_("watershed"));
  68. module->description = _("Calculates hydrological parameters and RUSLE factors.");
  69. opt1 = G_define_standard_option(G_OPT_R_ELEV);
  70. opt1->guisection = _("Inputs");
  71. opt2 = G_define_standard_option(G_OPT_R_INPUT);
  72. opt2->key = "depression";
  73. opt2->label = _("Name of input depressions raster map");
  74. opt2->description = _("All non-NULL and non-zero cells are considered as real depressions");
  75. opt2->required = NO;
  76. opt2->guisection = _("Inputs");
  77. opt3 = G_define_standard_option(G_OPT_R_INPUT);
  78. opt3->key = "flow";
  79. opt3->description = _("Name of input raster representing amount of overland flow per cell");
  80. opt3->required = NO;
  81. opt3->guisection = _("Inputs");
  82. opt4 = G_define_standard_option(G_OPT_R_INPUT);
  83. opt4->key = "disturbed_land";
  84. opt4->label = _("Name of input raster map percent of disturbed land");
  85. opt4->description = _("For USLE");
  86. opt4->required = NO;
  87. opt4->guisection = _("Inputs");
  88. opt5 = G_define_standard_option(G_OPT_R_INPUT);
  89. opt5->key = "blocking";
  90. opt5->label =
  91. _("Name of input raster map blocking overland surface flow");
  92. opt5->description =
  93. _("For USLE. All non-NULL and non-zero cells are considered as blocking terrain.");
  94. opt5->required = NO;
  95. opt5->guisection = _("Inputs");
  96. opt6 = G_define_option();
  97. opt6->key = "threshold";
  98. opt6->description =
  99. _("Minimum size of exterior watershed basin");
  100. opt6->required = NO;
  101. opt6->type = TYPE_INTEGER;
  102. opt6->guisection = _("Inputs");
  103. opt7 = G_define_option();
  104. opt7->key = "max_slope_length";
  105. opt7->label =
  106. _("Maximum length of surface flow in map units");
  107. opt7->description = _("For USLE");
  108. opt7->required = NO;
  109. opt7->type = TYPE_DOUBLE;
  110. opt7->guisection = _("Inputs");
  111. opt8 = G_define_standard_option(G_OPT_R_OUTPUT);
  112. opt8->key = "accumulation";
  113. opt8->label =
  114. _("Name for output accumulation raster map");
  115. opt8->description =
  116. _("Number of cells that drain through each cell");
  117. opt8->required = NO;
  118. opt8->guisection = _("Outputs");
  119. opt17 = G_define_standard_option(G_OPT_R_OUTPUT);
  120. opt17->key = "tci";
  121. opt17->label =
  122. _("Topographic index ln(a / tan(b))");
  123. opt17->required = NO;
  124. opt17->guisection = _("Outputs");
  125. opt9 = G_define_standard_option(G_OPT_R_OUTPUT);
  126. opt9->key = "drainage";
  127. opt9->description = _("Name for output drainage direction raster map");
  128. opt9->required = NO;
  129. opt9->guisection = _("Outputs");
  130. opt10 = G_define_standard_option(G_OPT_R_OUTPUT);
  131. opt10->key = "basin";
  132. opt10->description =
  133. _("Name for basins raster map");
  134. opt10->description = _("Unique label for each watershed basin");
  135. opt10->required = NO;
  136. opt10->guisection = _("Outputs");
  137. opt11 = G_define_standard_option(G_OPT_R_OUTPUT);
  138. opt11->key = "stream";
  139. opt11->description = _("Name for output stream segments raster map");
  140. opt11->required = NO;
  141. opt11->guisection = _("Outputs");
  142. opt12 = G_define_standard_option(G_OPT_R_OUTPUT);
  143. opt12->key = "half_basin";
  144. opt12->label = _("Name for output half basins raster map");
  145. opt12->description =
  146. _("Each half-basin is given a unique value");
  147. opt12->required = NO;
  148. opt12->guisection = _("Outputs");
  149. opt13 = G_define_standard_option(G_OPT_R_OUTPUT);
  150. opt13->key = "length_slope";
  151. opt13->label = _("Name for output slope length raster map");
  152. opt13->description =
  153. _("Slope length and steepness (LS) factor for USLE");
  154. opt13->required = NO;
  155. opt13->guisection = _("Outputs");
  156. opt14 = G_define_standard_option(G_OPT_R_OUTPUT);
  157. opt14->key = "slope_steepness";
  158. opt14->label = _("Name for output slope steepness raster map");
  159. opt14->description = _("Slope steepness (S) factor for USLE");
  160. opt14->required = NO;
  161. opt14->guisection = _("Outputs");
  162. opt15 = G_define_option();
  163. opt15->key = "convergence";
  164. opt15->type = TYPE_INTEGER;
  165. opt15->required = NO;
  166. opt15->answer = "5";
  167. opt15->label = _("Convergence factor for MFD (1-10)");
  168. opt15->description =
  169. _("1 = most diverging flow, 10 = most converging flow. Recommended: 5");
  170. opt16 = G_define_option();
  171. opt16->key = "memory";
  172. opt16->type = TYPE_INTEGER;
  173. opt16->required = NO;
  174. opt16->answer = "300"; /* 300MB default value, please keep r.terraflow in sync */
  175. opt16->description = _("Maximum memory to be used with -m flag (in MB)");
  176. flag_sfd = G_define_flag();
  177. flag_sfd->key = 's';
  178. flag_sfd->label = _("SFD (D8) flow (default is MFD)");
  179. flag_sfd->description =
  180. _("SFD: single flow direction, MFD: multiple flow direction");
  181. flag_flow = G_define_flag();
  182. flag_flow->key = '4';
  183. flag_flow->description =
  184. _("Allow only horizontal and vertical flow of water");
  185. flag_seg = G_define_flag();
  186. flag_seg->key = 'm';
  187. flag_seg->label =
  188. _("Enable disk swap memory option: Operation is slow");
  189. flag_seg->description =
  190. _("Only needed if memory requirements exceed available RAM; see manual on how to calculate memory requirements");
  191. flag_abs = G_define_flag();
  192. flag_abs->key = 'a';
  193. flag_abs->label =
  194. _("Use positive flow accumulation even for likely underestimates");
  195. flag_abs->description =
  196. _("See manual for a detailed description of flow accumulation output");
  197. flag_flat = G_define_flag();
  198. flag_flat->key = 'b';
  199. flag_flat->label =
  200. _("Beautify flat areas");
  201. flag_flat->description =
  202. _("Flow direction in flat areas is modified to look prettier");
  203. if (G_parser(argc, argv))
  204. exit(EXIT_FAILURE);
  205. /* Check option combinations */
  206. /* Check for some output map */
  207. if ((opt8->answer == NULL)
  208. && (opt9->answer == NULL)
  209. && (opt10->answer == NULL)
  210. && (opt11->answer == NULL)
  211. && (opt12->answer == NULL)
  212. && (opt14->answer == NULL)
  213. && (opt15->answer == NULL)) {
  214. G_fatal_error(_("Sorry, you must choose an output map."));
  215. }
  216. /* basin threshold */
  217. if (opt6->answer) {
  218. if (atoi(opt6->answer) <= 0)
  219. G_fatal_error(_("The basin threshold must be a positive number."));
  220. }
  221. err = 0;
  222. /* basin and basin threshold */
  223. err += (opt10->answer != NULL && opt6->answer == NULL);
  224. /* stream and basin threshold */
  225. err += (opt11->answer != NULL && opt6->answer == NULL);
  226. /* half_basin and basin threshold */
  227. err += (opt12->answer != NULL && opt6->answer == NULL);
  228. /* LS factor and basin threshold */
  229. err += (opt13->answer != NULL && opt6->answer == NULL);
  230. /* S factor and basin threshold */
  231. err += (opt14->answer != NULL && opt6->answer == NULL);
  232. if (err) {
  233. G_message(_("Sorry, if any of the following options are set:\n"
  234. " basin, stream, half_basin, length_slope, or slope_steepness\n"
  235. " you MUST provide a value for the basin "
  236. "threshold parameter."));
  237. G_usage();
  238. exit(EXIT_FAILURE);
  239. }
  240. /* Build command line */
  241. sprintf(command, "%s/etc/r.watershed/%s",
  242. G_gisbase(),
  243. flag_seg->answer ? "seg" : "ram");
  244. new_argv[new_argc++] = command;
  245. if (flag_sfd->answer)
  246. new_argv[new_argc++] = "-s";
  247. if (flag_flow->answer)
  248. new_argv[new_argc++] = "-4";
  249. if (flag_abs->answer)
  250. new_argv[new_argc++] = "-a";
  251. if (flag_flat->answer && !flag_seg->answer)
  252. new_argv[new_argc++] = "-b";
  253. if (flag_flat->answer && flag_seg->answer)
  254. G_message(_("Beautify flat areas is not yet supported for disk swap mode"));
  255. do_opt(opt1);
  256. do_opt(opt2);
  257. do_opt(opt3);
  258. do_opt(opt4);
  259. do_opt(opt5);
  260. do_opt(opt6);
  261. do_opt(opt7);
  262. do_opt(opt8);
  263. do_opt(opt17);
  264. do_opt(opt9);
  265. do_opt(opt10);
  266. do_opt(opt11);
  267. do_opt(opt12);
  268. do_opt(opt13);
  269. do_opt(opt14);
  270. do_opt(opt15);
  271. if (flag_seg->answer)
  272. do_opt(opt16);
  273. new_argv[new_argc++] = NULL;
  274. G_debug(1, "Mode: %s", flag_seg->answer ? "Segmented" : "All in RAM");
  275. ret = G_vspawn_ex(new_argv[0], new_argv);
  276. if (ret != EXIT_SUCCESS)
  277. G_warning(_("Subprocess failed with exit code %d"), ret);
  278. /* record map metadata/history info */
  279. if (opt8->answer)
  280. write_hist(opt8->answer,
  281. "Watershed accumulation: overland flow that traverses each cell",
  282. opt1->answer, flag_seg->answer, flag_sfd->answer);
  283. if (opt17->answer)
  284. write_hist(opt17->answer,
  285. "Watershed accumulation: topographic index ln(a / tan b)",
  286. opt1->answer, flag_seg->answer, flag_sfd->answer);
  287. if (opt9->answer)
  288. write_hist(opt9->answer,
  289. "Watershed drainage direction (CCW from East divided by 45deg)",
  290. opt1->answer, flag_seg->answer, flag_sfd->answer);
  291. if (opt10->answer)
  292. write_hist(opt10->answer,
  293. "Watershed basins", opt1->answer, flag_seg->answer,
  294. flag_sfd->answer);
  295. if (opt11->answer)
  296. write_hist(opt11->answer,
  297. "Watershed stream segments", opt1->answer,
  298. flag_seg->answer, flag_sfd->answer);
  299. if (opt12->answer)
  300. write_hist(opt12->answer,
  301. "Watershed half-basins", opt1->answer, flag_seg->answer,
  302. flag_sfd->answer);
  303. if (opt13->answer)
  304. write_hist(opt13->answer,
  305. "Watershed slope length and steepness (LS) factor",
  306. opt1->answer, flag_seg->answer, flag_sfd->answer);
  307. if (opt14->answer)
  308. write_hist(opt14->answer,
  309. "Watershed slope steepness (S) factor",
  310. opt1->answer, flag_seg->answer, flag_sfd->answer);
  311. exit(ret);
  312. }
  313. /* record map history info */
  314. static void write_hist(char *map_name, char *title, char *source_name, int mode, int sfd)
  315. {
  316. struct History history;
  317. Rast_put_cell_title(map_name, title);
  318. Rast_short_history(map_name, "raster", &history);
  319. Rast_set_history(&history, HIST_DATSRC_1, source_name);
  320. Rast_append_format_history(
  321. &history, "Processing mode: %s", sfd ? "SFD (D8)" : "MFD");
  322. Rast_append_format_history(
  323. &history, "Memory mode: %s", mode ? "Segmented" : "All in RAM");
  324. Rast_command_history(&history);
  325. Rast_write_history(map_name, &history);
  326. }