close.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. #include <grass/raster.h>
  2. #include <grass/glocale.h>
  3. #include <grass/vector.h>
  4. #include <grass/dbmi.h>
  5. #include "local_proto.h"
  6. int close_streamvect(char *stream_vect)
  7. {
  8. int r, c, r_nbr, c_nbr, done;
  9. GW_LARGE_INT i;
  10. CELL stream_id, stream_nbr;
  11. ASP_FLAG af;
  12. int next_node;
  13. struct sstack
  14. {
  15. int stream_id;
  16. int next_trib;
  17. } *nodestack;
  18. int top = 0, stack_step = 1000;
  19. int asp_r[9] = { 0, -1, -1, -1, 0, 1, 1, 1, 0 };
  20. int asp_c[9] = { 0, 1, 0, -1, -1, -1, 0, 1, 1 };
  21. struct Map_info Out;
  22. static struct line_pnts *Points;
  23. struct line_cats *Cats;
  24. dbDriver *driver;
  25. dbHandle handle;
  26. dbString table_name, dbsql, valstr;
  27. struct field_info *Fi;
  28. char *cat_col_name = "cat", buf[2000];
  29. struct Cell_head window;
  30. double north_offset, west_offset, ns_res, ew_res;
  31. int next_cat;
  32. G_message(_("Writing vector map <%s>..."), stream_vect);
  33. if (Vect_open_new(&Out, stream_vect, 0) < 0)
  34. G_fatal_error(_("Unable to create vector map <%s>"), stream_vect);
  35. nodestack = (struct sstack *)G_malloc(stack_step * sizeof(struct sstack));
  36. Points = Vect_new_line_struct();
  37. Cats = Vect_new_cats_struct();
  38. G_get_set_window(&window);
  39. ns_res = window.ns_res;
  40. ew_res = window.ew_res;
  41. north_offset = window.north - 0.5 * ns_res;
  42. west_offset = window.west + 0.5 * ew_res;
  43. next_cat = n_stream_nodes + 1;
  44. for (i = 0; i < n_outlets; i++, next_cat++) {
  45. G_percent(i, n_outlets, 2);
  46. r = outlets[i].r;
  47. c = outlets[i].c;
  48. cseg_get(&stream, &stream_id, r, c);
  49. if (!stream_id)
  50. continue;
  51. Vect_reset_line(Points);
  52. Vect_reset_cats(Cats);
  53. /* outlet */
  54. Vect_cat_set(Cats, 1, stream_id);
  55. Vect_cat_set(Cats, 2, 2);
  56. Vect_append_point(Points, west_offset + c * ew_res,
  57. north_offset - r * ns_res, 0);
  58. Vect_write_line(&Out, GV_POINT, Points, Cats);
  59. /* add root node to stack */
  60. G_debug(3, "add root node");
  61. top = 0;
  62. nodestack[top].stream_id = stream_id;
  63. nodestack[top].next_trib = 0;
  64. /* depth first post order traversal */
  65. G_debug(3, "traverse");
  66. while (top >= 0) {
  67. done = 1;
  68. stream_id = nodestack[top].stream_id;
  69. G_debug(3, "stream_id %d", stream_id);
  70. if (nodestack[top].next_trib < stream_node[stream_id].n_trib) {
  71. /* add to stack */
  72. next_node =
  73. stream_node[stream_id].trib[nodestack[top].next_trib];
  74. G_debug(3, "add to stack: next %d, trib %d, n trib %d",
  75. next_node, nodestack[top].next_trib,
  76. stream_node[stream_id].n_trib);
  77. nodestack[top].next_trib++;
  78. top++;
  79. if (top >= stack_step) {
  80. /* need more space */
  81. stack_step += 1000;
  82. nodestack =
  83. (struct sstack *)G_realloc(nodestack,
  84. stack_step *
  85. sizeof(struct sstack));
  86. }
  87. nodestack[top].next_trib = 0;
  88. nodestack[top].stream_id = next_node;
  89. done = 0;
  90. G_debug(3, "go further down");
  91. }
  92. if (done) {
  93. G_debug(3, "write stream segment");
  94. Vect_reset_line(Points);
  95. Vect_reset_cats(Cats);
  96. r_nbr = stream_node[stream_id].r;
  97. c_nbr = stream_node[stream_id].c;
  98. cseg_get(&stream, &stream_nbr, r_nbr, c_nbr);
  99. if (stream_nbr <= 0)
  100. G_fatal_error(_("Stream id %d not set, top is %d, parent is %d"),
  101. stream_id, top, nodestack[top - 1].stream_id);
  102. Vect_cat_set(Cats, 1, stream_id);
  103. if (stream_node[stream_id].n_trib == 0)
  104. Vect_cat_set(Cats, 2, 0);
  105. else
  106. Vect_cat_set(Cats, 2, 1);
  107. Vect_append_point(Points, west_offset + c_nbr * ew_res,
  108. north_offset - r_nbr * ns_res, 0);
  109. Vect_write_line(&Out, GV_POINT, Points, Cats);
  110. seg_get(&aspflag, (char *)&af, r_nbr, c_nbr);
  111. while (af.asp > 0) {
  112. r_nbr = r_nbr + asp_r[(int)af.asp];
  113. c_nbr = c_nbr + asp_c[(int)af.asp];
  114. cseg_get(&stream, &stream_nbr, r_nbr, c_nbr);
  115. if (stream_nbr <= 0)
  116. G_fatal_error(_("Stream id not set while tracing"));
  117. Vect_append_point(Points, west_offset + c_nbr * ew_res,
  118. north_offset - r_nbr * ns_res, 0);
  119. if (stream_nbr != stream_id) {
  120. /* first point of parent stream */
  121. break;
  122. }
  123. seg_get(&aspflag, (char *)&af, r_nbr, c_nbr);
  124. }
  125. Vect_write_line(&Out, GV_LINE, Points, Cats);
  126. top--;
  127. }
  128. }
  129. }
  130. G_percent(n_outlets, n_outlets, 1); /* finish it */
  131. G_message(_("Writing attribute data..."));
  132. /* Prepeare strings for use in db_* calls */
  133. db_init_string(&dbsql);
  134. db_init_string(&valstr);
  135. db_init_string(&table_name);
  136. db_init_handle(&handle);
  137. /* Preparing database for use */
  138. /* Create database for new vector map */
  139. Fi = Vect_default_field_info(&Out, 1, NULL, GV_1TABLE);
  140. driver = db_start_driver_open_database(Fi->driver,
  141. Vect_subst_var(Fi->database,
  142. &Out));
  143. if (driver == NULL) {
  144. G_fatal_error(_("Unable to start driver <%s>"), Fi->driver);
  145. }
  146. db_set_error_handler_driver(driver);
  147. G_debug(1, "table: %s", Fi->table);
  148. G_debug(1, "driver: %s", Fi->driver);
  149. G_debug(1, "database: %s", Fi->database);
  150. sprintf(buf,
  151. "create table %s (%s integer, stream_type varchar(20), type_code integer)",
  152. Fi->table, cat_col_name);
  153. db_set_string(&dbsql, buf);
  154. if (db_execute_immediate(driver, &dbsql) != DB_OK) {
  155. db_close_database(driver);
  156. db_shutdown_driver(driver);
  157. G_fatal_error(_("Unable to create table: '%s'"), db_get_string(&dbsql));
  158. }
  159. if (db_create_index2(driver, Fi->table, cat_col_name) != DB_OK)
  160. G_warning(_("Unable to create index on table <%s>"), Fi->table);
  161. if (db_grant_on_table(driver, Fi->table, DB_PRIV_SELECT,
  162. DB_GROUP | DB_PUBLIC) != DB_OK)
  163. G_fatal_error(_("Unable to grant privileges on table <%s>"), Fi->table);
  164. db_begin_transaction(driver);
  165. /* stream nodes */
  166. for (i = 1; i <= n_stream_nodes; i++) {
  167. sprintf(buf, "insert into %s values ( %lld, \'%s\', %d )",
  168. Fi->table, i,
  169. (stream_node[i].n_trib > 0 ? "intermediate" : "start"),
  170. (stream_node[i].n_trib > 0));
  171. db_set_string(&dbsql, buf);
  172. if (db_execute_immediate(driver, &dbsql) != DB_OK) {
  173. db_close_database(driver);
  174. db_shutdown_driver(driver);
  175. G_fatal_error(_("Unable to insert new row: '%s'"),
  176. db_get_string(&dbsql));
  177. }
  178. }
  179. db_commit_transaction(driver);
  180. db_close_database_shutdown_driver(driver);
  181. Vect_map_add_dblink(&Out, 1, NULL, Fi->table,
  182. cat_col_name, Fi->database, Fi->driver);
  183. G_debug(1, "close vector");
  184. Vect_hist_command(&Out);
  185. Vect_build(&Out);
  186. Vect_close(&Out);
  187. G_free(nodestack);
  188. return 1;
  189. }
  190. int close_maps(char *stream_rast, char *stream_vect, char *dir_rast)
  191. {
  192. int stream_fd, dir_fd, r, c, i;
  193. CELL *cell_buf1, *cell_buf2;
  194. struct History history;
  195. CELL stream_id;
  196. ASP_FLAG af;
  197. /* cheating... */
  198. stream_fd = dir_fd = -1;
  199. cell_buf1 = cell_buf2 = NULL;
  200. G_message(_("Writing output raster maps..."));
  201. /* write requested output rasters */
  202. if (stream_rast) {
  203. stream_fd = Rast_open_new(stream_rast, CELL_TYPE);
  204. cell_buf1 = Rast_allocate_c_buf();
  205. }
  206. if (dir_rast) {
  207. dir_fd = Rast_open_new(dir_rast, CELL_TYPE);
  208. cell_buf2 = Rast_allocate_c_buf();
  209. }
  210. for (r = 0; r < nrows; r++) {
  211. G_percent(r, nrows, 2);
  212. if (stream_rast)
  213. Rast_set_c_null_value(cell_buf1, ncols); /* reset row to all NULL */
  214. if (dir_rast)
  215. Rast_set_c_null_value(cell_buf2, ncols); /* reset row to all NULL */
  216. for (c = 0; c < ncols; c++) {
  217. if (stream_rast) {
  218. cseg_get(&stream, &stream_id, r, c);
  219. if (stream_id)
  220. cell_buf1[c] = stream_id;
  221. }
  222. if (dir_rast) {
  223. seg_get(&aspflag, (char *)&af, r, c);
  224. if (!FLAG_GET(af.flag, NULLFLAG)) {
  225. cell_buf2[c] = af.asp;
  226. }
  227. }
  228. }
  229. if (stream_rast)
  230. Rast_put_row(stream_fd, cell_buf1, CELL_TYPE);
  231. if (dir_rast)
  232. Rast_put_row(dir_fd, cell_buf2, CELL_TYPE);
  233. }
  234. G_percent(nrows, nrows, 2); /* finish it */
  235. if (stream_rast) {
  236. Rast_close(stream_fd);
  237. G_free(cell_buf1);
  238. Rast_short_history(stream_rast, "raster", &history);
  239. Rast_command_history(&history);
  240. Rast_write_history(stream_rast, &history);
  241. }
  242. if (dir_rast) {
  243. struct Colors colors;
  244. Rast_close(dir_fd);
  245. G_free(cell_buf2);
  246. Rast_short_history(dir_rast, "raster", &history);
  247. Rast_command_history(&history);
  248. Rast_write_history(dir_rast, &history);
  249. Rast_init_colors(&colors);
  250. Rast_make_aspect_colors(&colors, -8, 8);
  251. Rast_write_colors(dir_rast, G_mapset(), &colors);
  252. }
  253. /* close stream vector */
  254. if (stream_vect) {
  255. if (close_streamvect(stream_vect) < 0)
  256. G_fatal_error(_("Unable to write vector map <%s>"), stream_vect);
  257. }
  258. /* rearranging desk chairs on the Titanic... */
  259. G_free(outlets);
  260. /* free stream nodes */
  261. for (i = 1; i <= n_stream_nodes; i++) {
  262. if (stream_node[i].n_alloc > 0) {
  263. G_free(stream_node[i].trib);
  264. }
  265. }
  266. G_free(stream_node);
  267. return 1;
  268. }