main.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. /****************************************************************************
  2. *
  3. * MODULE: r.carve
  4. *
  5. * AUTHOR(S): Original author Bill Brown, UIUC GIS Laboratory
  6. * Brad Douglas <rez touchofmadness com>
  7. *
  8. * PURPOSE: Takes vector stream data, converts it to 3D raster and
  9. * subtracts a specified depth
  10. *
  11. * COPYRIGHT: (C) 2006, 2010 by the GRASS Development Team
  12. *
  13. * This program is free software under the GNU General Public
  14. * License (>=v2). Read the file COPYING that comes with GRASS
  15. * for details.
  16. *
  17. ****************************************************************************/
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <errno.h>
  21. #include <math.h>
  22. #include <grass/gis.h>
  23. #include <grass/raster.h>
  24. #include <grass/glocale.h>
  25. #include "enforce.h"
  26. /*
  27. Note: Use rast input type for rast output
  28. Read vect file,
  29. for each line,
  30. use a shadow line struct to represent stream profile,
  31. where x is distance along stream and y is elevation,
  32. adding each point to lobf as it's created.
  33. find trend using lobf
  34. from high to low, lower any points forming dams
  35. when next pnt elev increases,
  36. find next point <= than last confirmed pt
  37. just use linear interp for now
  38. write line to new raster
  39. Use orig line struct for XYs, shadow struct Y for cell val
  40. if new raster already has value there, use lower?
  41. actually probably want to use val for trunk stream
  42. and then verify branch in reverse
  43. - for now maybe create a conflict map
  44. After that's working, add width to lines?
  45. or use r.grow
  46. */
  47. /* function prototypes */
  48. static int init_projection(struct Cell_head *window, int *wrap_ncols);
  49. int main(int argc, char **argv)
  50. {
  51. struct GModule *module;
  52. struct parms parm;
  53. struct Option *width, *depth;
  54. struct Flag *noflat;
  55. const char *vmapset, *rmapset;
  56. int infd, outfd;
  57. struct Map_info Map;
  58. struct Map_info outMap;
  59. struct Cell_head win;
  60. /* start GIS engine */
  61. G_gisinit(argv[0]);
  62. module = G_define_module();
  63. G_add_keyword(_("raster"));
  64. G_add_keyword(_("hydrology"));
  65. module->label = _("Generates stream channels.");
  66. module->description = _("Takes vector stream data, transforms it "
  67. "to raster and subtracts depth from the output DEM.");
  68. parm.inrast = G_define_standard_option(G_OPT_R_INPUT);
  69. parm.inrast->key = "raster";
  70. parm.inrast->description = _("Name of input raster elevation map");
  71. parm.invect = G_define_standard_option(G_OPT_V_INPUT);
  72. parm.invect->key = "vector";
  73. parm.invect->label =
  74. _("Name of input vector map containing stream(s)");
  75. parm.outrast = G_define_standard_option(G_OPT_R_OUTPUT);
  76. parm.outvect = G_define_standard_option(G_OPT_V_OUTPUT);
  77. parm.outvect->key = "points";
  78. parm.outvect->required = NO;
  79. parm.outvect->description =
  80. _("Name for output vector map for adjusted stream points");
  81. width = G_define_option();
  82. width->key = "width";
  83. width->type = TYPE_DOUBLE;
  84. width->label = _("Stream width (in meters)");
  85. width->description = _("Default is raster cell width");
  86. depth = G_define_option();
  87. depth->key = "depth";
  88. depth->type = TYPE_DOUBLE;
  89. depth->description = _("Additional stream depth (in meters)");
  90. noflat = G_define_flag();
  91. noflat->key = 'n';
  92. noflat->description = _("No flat areas allowed in flow direction");
  93. /* parse options */
  94. if (G_parser(argc, argv))
  95. exit(EXIT_FAILURE);
  96. G_check_input_output_name(parm.inrast->answer, parm.outrast->answer,
  97. G_FATAL_EXIT);
  98. if (parm.outvect->answer)
  99. Vect_check_input_output_name(parm.invect->answer, parm.outvect->answer,
  100. G_FATAL_EXIT);
  101. /* setup lat/lon projection and distance calculations */
  102. init_projection(&win, &parm.wrap);
  103. /* default width - one cell at center */
  104. if (width->answer == NULL) {
  105. parm.swidth = G_distance((win.east + win.west) / 2,
  106. (win.north + win.south) / 2,
  107. ((win.east + win.west) / 2) + win.ew_res,
  108. (win.north + win.south) / 2);
  109. }
  110. else {
  111. if (sscanf(width->answer, "%lf", &parm.swidth) != 1) {
  112. G_warning(_("Invalid width value '%s' - using default."),
  113. width->answer);
  114. parm.swidth =
  115. G_distance((win.east + win.west) / 2,
  116. (win.north + win.south) / 2,
  117. ((win.east + win.west) / 2) + win.ew_res,
  118. (win.north + win.south) / 2);
  119. }
  120. }
  121. if (depth->answer == NULL)
  122. parm.sdepth = 0.0;
  123. else {
  124. if (sscanf(depth->answer, "%lf", &parm.sdepth) != 1) {
  125. G_warning(_("Invalid depth value '%s' - using default."),
  126. depth->answer);
  127. parm.sdepth = 0.0;
  128. }
  129. }
  130. parm.noflat = noflat->answer;
  131. /* open input files */
  132. if ((vmapset = G_find_vector2(parm.invect->answer, "")) == NULL)
  133. G_fatal_error(_("Vector map <%s> not found"), parm.invect->answer);
  134. Vect_set_open_level(2);
  135. if (Vect_open_old(&Map, parm.invect->answer, vmapset) < 0)
  136. G_fatal_error(_("Unable to open vector map <%s>"), parm.invect->answer);
  137. if ((rmapset = G_find_file2("cell", parm.inrast->answer, "")) == NULL)
  138. G_fatal_error(_("Raster map <%s> not found"), parm.inrast->answer);
  139. infd = Rast_open_old(parm.inrast->answer, rmapset);
  140. parm.raster_type = Rast_get_map_type(infd);
  141. /* open new map for output */
  142. outfd = Rast_open_new(parm.outrast->answer, parm.raster_type);
  143. /* if specified, open vector for output */
  144. if (parm.outvect->answer)
  145. open_new_vect(&outMap, parm.outvect->answer);
  146. enforce_downstream(infd, outfd, &Map, &outMap, &parm);
  147. Rast_close(infd);
  148. Rast_close(outfd);
  149. close_vect(&Map, 0);
  150. if (parm.outvect->answer)
  151. close_vect(&outMap, 1);
  152. /* write command line to history file */
  153. update_rast_history(&parm);
  154. return EXIT_SUCCESS;
  155. }
  156. static int init_projection(struct Cell_head *window, int *wrap_ncols)
  157. {
  158. #if 0
  159. double a, e2;
  160. #endif
  161. G_get_set_window(window);
  162. if (((window->west == (window->east - 360.0)) ||
  163. (window->east == (window->west - 360.0))) &&
  164. (G_projection() == PROJECTION_LL)) {
  165. #if 0
  166. G_get_ellipsoid_parameters(&a, &e2);
  167. G_begin_geodesic_distance(a, e2);
  168. /* add 1.1, not 1.0, to ensure that we round up */
  169. *wrap_ncols =
  170. (360.0 - (window->east - window->west)) / window->ew_res + 1.1;
  171. #else
  172. G_fatal_error(_("Lat/Long location is not supported by %s. Please reproject map first."),
  173. G_program_name());
  174. #endif
  175. }
  176. else {
  177. *wrap_ncols = 0;
  178. }
  179. G_begin_distance_calculations();
  180. return 0;
  181. }