int find_pourpts(void) { int row, col; double easting, northing, stream_length; CELL old_elev, basin_num, no_basin, curr_basin; WAT_ALT wa; ASP_FLAG af; char is_swale; ocs_alloced = 2 * bas_thres; ocs = (OC_STACK *)G_malloc(ocs_alloced * sizeof(OC_STACK)); basin_num = 0; Rast_set_c_null_value(&no_basin, 1); stream_length = old_elev = 0; for (row = 0; row < nrows; row++) { G_percent(row, nrows, 1); northing = window.north - (row + .5) * window.ns_res; for (col = 0; col < ncols; col++) { seg_get(&aspflag, (char *)&af, row, col); cseg_get(&bas, &curr_basin, row, col); if (curr_basin == 0) cseg_put(&bas, &no_basin, row, col); cseg_get(&haf, &curr_basin, row, col); if (curr_basin == 0) cseg_put(&haf, &no_basin, row, col); is_swale = FLAG_GET(af.flag, SWALEFLAG); if (af.asp <= 0 && is_swale > 0) { basin_num += 2; if (arm_flag) { easting = window.west + (col + .5) * window.ew_res; fprintf(fp, "%5d drains into %5d at %3d %3d %.3f %.3f", (int)basin_num, 0, row, col, easting, northing); if (col == 0 || col == ncols - 1) { stream_length = .5 * window.ew_res; } else if (row == 0 || row == nrows - 1) { stream_length = .5 * window.ns_res; } else { stream_length = 0.0; } seg_get(&watalt, (char *) &wa, row, col); old_elev = wa.ele; } basin_num = def_basin(row, col, basin_num, stream_length, old_elev); } } } G_percent(nrows, nrows, 1); /* finish it */ n_basins = basin_num; G_free(ocs); return 0; }
int slope_length(int r, int c, int dr, int dc) { CELL top_alt, bot_alt, ridge; char asp_value; double res, top_ls, bot_ls; WAT_ALT wa; if (sides == 8) { if (r == dr) res = window.ns_res; else if (c == dc) res = window.ew_res; else res = diag; } else { /* sides == 4 */ bseg_get(&asp, &asp_value, dr, dc); if (r == dr) { if (asp_value == 2 || asp_value == 6) res = window.ns_res; else /* asp_value == 4, 8, -2, -4, -6, or -8 */ res = diag; /* how can res be diag with sides == 4??? */ } else { /* c == dc */ if (asp_value == 4 || asp_value == 8) res = window.ew_res; else /* asp_value == 2, 6, -2, -4, -6, or -8 */ res = diag; } } dseg_get(&s_l, &top_ls, r, c); if (top_ls == half_res) top_ls = res; else top_ls += res; dseg_put(&s_l, &top_ls, r, c); seg_get(&watalt, (char *) &wa, r, c); top_alt = wa.ele; seg_get(&watalt, (char *) &wa, dr, dc); bot_alt = wa.ele; if (top_alt > bot_alt) { dseg_get(&s_l, &bot_ls, dr, dc); if (top_ls > bot_ls) { bot_ls = top_ls + res; dseg_put(&s_l, &bot_ls, dr, dc); cseg_get(&r_h, &ridge, r, c); cseg_put(&r_h, &ridge, dr, dc); } } return 0; }
int overland_cells(int row, int col, CELL basin_num, CELL haf_num, CELL * hih_ele) { int r, rr, c, cc; CELL new_ele, new_max_ele, value; cseg_put(&bas, &basin_num, row, col); cseg_put(&haf, &haf_num, row, col); new_max_ele = BIGNEG; for (r = row - 1, rr = 0; r <= row + 1; r++, rr++) { for (c = col - 1, cc = 0; c <= col + 1; c++, cc++) { if (r >= 0 && c >= 0 && r < nrows && c < ncols) { cseg_get(&asp, &value, r, c); if (value == drain[rr][cc]) { if (r != row && c != col) { overland_cells(r, c, basin_num, haf_num, &new_ele); } else if (r != row) { overland_cells(r, c, basin_num, haf_num, &new_ele); } else { overland_cells(r, c, basin_num, haf_num, &new_ele); } } } } } if (new_max_ele == BIGNEG) { cseg_get(&alt, hih_ele, row, col); } else { *hih_ele = new_max_ele; } return 0; }
int sg_factor(void) { int r, c; CELL low_elev, hih_elev; double height, length, S, sin_theta; WAT_ALT wa; ASP_FLAG af; G_message(_("SECTION 5: RUSLE LS and/or S factor determination.")); for (r = nrows - 1; r >= 0; r--) { G_percent(nrows - r, nrows, 3); for (c = ncols - 1; c >= 0; c--) { seg_get(&aspflag, (char *)&af, r, c); if (FLAG_GET(af.flag, NULLFLAG)) continue; seg_get(&watalt, (char *) &wa, r, c); low_elev = wa.ele; cseg_get(&r_h, &hih_elev, r, c); dseg_get(&s_l, &length, r, c); height = 1.0 * (hih_elev - low_elev) / ele_scale; if (length > max_length) { height *= max_length / length; length = max_length; } sin_theta = height / sqrt(height * height + length * length); if (height / length < .09) S = 10.8 * sin_theta + .03; else S = 16.8 * sin_theta - .50; if (ls_flag) { length *= METER_TO_FOOT; len_slp_equ(length, sin_theta, S, r, c); } if (sg_flag) { dseg_put(&s_g, &S, r, c); } } } G_percent(nrows, nrows, 1); /* finish it */ return 0; }
int close_streamvect(char *stream_vect) { int r, c, r_nbr, c_nbr, done; GW_LARGE_INT i; CELL stream_id, stream_nbr; ASP_FLAG af; int next_node; struct sstack { int stream_id; int next_trib; } *nodestack; int top = 0, stack_step = 1000; int asp_r[9] = { 0, -1, -1, -1, 0, 1, 1, 1, 0 }; int asp_c[9] = { 0, 1, 0, -1, -1, -1, 0, 1, 1 }; struct Map_info Out; static struct line_pnts *Points; struct line_cats *Cats; dbDriver *driver; dbHandle handle; dbString table_name, dbsql, valstr; struct field_info *Fi; char *cat_col_name = "cat", buf[2000]; struct Cell_head window; double north_offset, west_offset, ns_res, ew_res; int next_cat; G_message(_("Writing vector map <%s>..."), stream_vect); if (Vect_open_new(&Out, stream_vect, 0) < 0) G_fatal_error(_("Unable to create vector map <%s>"), stream_vect); nodestack = (struct sstack *)G_malloc(stack_step * sizeof(struct sstack)); Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); G_get_set_window(&window); ns_res = window.ns_res; ew_res = window.ew_res; north_offset = window.north - 0.5 * ns_res; west_offset = window.west + 0.5 * ew_res; next_cat = n_stream_nodes + 1; for (i = 0; i < n_outlets; i++, next_cat++) { G_percent(i, n_outlets, 2); r = outlets[i].r; c = outlets[i].c; cseg_get(&stream, &stream_id, r, c); if (!stream_id) continue; Vect_reset_line(Points); Vect_reset_cats(Cats); /* outlet */ Vect_cat_set(Cats, 1, stream_id); Vect_cat_set(Cats, 2, 2); Vect_append_point(Points, west_offset + c * ew_res, north_offset - r * ns_res, 0); Vect_write_line(&Out, GV_POINT, Points, Cats); /* add root node to stack */ G_debug(3, "add root node"); top = 0; nodestack[top].stream_id = stream_id; nodestack[top].next_trib = 0; /* depth first post order traversal */ G_debug(3, "traverse"); while (top >= 0) { done = 1; stream_id = nodestack[top].stream_id; G_debug(3, "stream_id %d", stream_id); if (nodestack[top].next_trib < stream_node[stream_id].n_trib) { /* add to stack */ next_node = stream_node[stream_id].trib[nodestack[top].next_trib]; G_debug(3, "add to stack: next %d, trib %d, n trib %d", next_node, nodestack[top].next_trib, stream_node[stream_id].n_trib); nodestack[top].next_trib++; top++; if (top >= stack_step) { /* need more space */ stack_step += 1000; nodestack = (struct sstack *)G_realloc(nodestack, stack_step * sizeof(struct sstack)); } nodestack[top].next_trib = 0; nodestack[top].stream_id = next_node; done = 0; G_debug(3, "go further down"); } if (done) { G_debug(3, "write stream segment"); Vect_reset_line(Points); Vect_reset_cats(Cats); r_nbr = stream_node[stream_id].r; c_nbr = stream_node[stream_id].c; cseg_get(&stream, &stream_nbr, r_nbr, c_nbr); if (stream_nbr <= 0) G_fatal_error(_("Stream id %d not set, top is %d, parent is %d"), stream_id, top, nodestack[top - 1].stream_id); Vect_cat_set(Cats, 1, stream_id); if (stream_node[stream_id].n_trib == 0) Vect_cat_set(Cats, 2, 0); else Vect_cat_set(Cats, 2, 1); Vect_append_point(Points, west_offset + c_nbr * ew_res, north_offset - r_nbr * ns_res, 0); Vect_write_line(&Out, GV_POINT, Points, Cats); seg_get(&aspflag, (char *)&af, r_nbr, c_nbr); while (af.asp > 0) { r_nbr = r_nbr + asp_r[(int)af.asp]; c_nbr = c_nbr + asp_c[(int)af.asp]; cseg_get(&stream, &stream_nbr, r_nbr, c_nbr); if (stream_nbr <= 0) G_fatal_error(_("Stream id not set while tracing")); Vect_append_point(Points, west_offset + c_nbr * ew_res, north_offset - r_nbr * ns_res, 0); if (stream_nbr != stream_id) { /* first point of parent stream */ break; } seg_get(&aspflag, (char *)&af, r_nbr, c_nbr); } Vect_write_line(&Out, GV_LINE, Points, Cats); top--; } } } G_percent(n_outlets, n_outlets, 1); /* finish it */ G_message(_("Writing attribute data...")); /* Prepeare strings for use in db_* calls */ db_init_string(&dbsql); db_init_string(&valstr); db_init_string(&table_name); db_init_handle(&handle); /* Preparing database for use */ /* Create database for new vector map */ Fi = Vect_default_field_info(&Out, 1, NULL, GV_1TABLE); driver = db_start_driver_open_database(Fi->driver, Vect_subst_var(Fi->database, &Out)); if (driver == NULL) { G_fatal_error(_("Unable to start driver <%s>"), Fi->driver); } db_set_error_handler_driver(driver); G_debug(1, "table: %s", Fi->table); G_debug(1, "driver: %s", Fi->driver); G_debug(1, "database: %s", Fi->database); sprintf(buf, "create table %s (%s integer, stream_type varchar(20), type_code integer)", Fi->table, cat_col_name); db_set_string(&dbsql, buf); if (db_execute_immediate(driver, &dbsql) != DB_OK) { db_close_database(driver); db_shutdown_driver(driver); G_fatal_error(_("Unable to create table: '%s'"), db_get_string(&dbsql)); } if (db_create_index2(driver, Fi->table, cat_col_name) != DB_OK) G_warning(_("Unable to create index on table <%s>"), Fi->table); if (db_grant_on_table(driver, Fi->table, DB_PRIV_SELECT, DB_GROUP | DB_PUBLIC) != DB_OK) G_fatal_error(_("Unable to grant privileges on table <%s>"), Fi->table); db_begin_transaction(driver); /* stream nodes */ for (i = 1; i <= n_stream_nodes; i++) { sprintf(buf, "insert into %s values ( %lld, \'%s\', %d )", Fi->table, i, (stream_node[i].n_trib > 0 ? "intermediate" : "start"), (stream_node[i].n_trib > 0)); db_set_string(&dbsql, buf); if (db_execute_immediate(driver, &dbsql) != DB_OK) { db_close_database(driver); db_shutdown_driver(driver); G_fatal_error(_("Unable to insert new row: '%s'"), db_get_string(&dbsql)); } } db_commit_transaction(driver); db_close_database_shutdown_driver(driver); Vect_map_add_dblink(&Out, 1, NULL, Fi->table, cat_col_name, Fi->database, Fi->driver); G_debug(1, "close vector"); Vect_hist_command(&Out); Vect_build(&Out); Vect_close(&Out); G_free(nodestack); return 1; }
int close_maps(char *stream_rast, char *stream_vect, char *dir_rast) { int stream_fd, dir_fd, r, c, i; CELL *cell_buf1, *cell_buf2; struct History history; CELL stream_id; ASP_FLAG af; /* cheating... */ stream_fd = dir_fd = -1; cell_buf1 = cell_buf2 = NULL; G_message(_("Writing output raster maps...")); /* write requested output rasters */ if (stream_rast) { stream_fd = Rast_open_new(stream_rast, CELL_TYPE); cell_buf1 = Rast_allocate_c_buf(); } if (dir_rast) { dir_fd = Rast_open_new(dir_rast, CELL_TYPE); cell_buf2 = Rast_allocate_c_buf(); } for (r = 0; r < nrows; r++) { G_percent(r, nrows, 2); if (stream_rast) Rast_set_c_null_value(cell_buf1, ncols); /* reset row to all NULL */ if (dir_rast) Rast_set_c_null_value(cell_buf2, ncols); /* reset row to all NULL */ for (c = 0; c < ncols; c++) { if (stream_rast) { cseg_get(&stream, &stream_id, r, c); if (stream_id) cell_buf1[c] = stream_id; } if (dir_rast) { seg_get(&aspflag, (char *)&af, r, c); if (!FLAG_GET(af.flag, NULLFLAG)) { cell_buf2[c] = af.asp; } } } if (stream_rast) Rast_put_row(stream_fd, cell_buf1, CELL_TYPE); if (dir_rast) Rast_put_row(dir_fd, cell_buf2, CELL_TYPE); } G_percent(nrows, nrows, 2); /* finish it */ if (stream_rast) { Rast_close(stream_fd); G_free(cell_buf1); Rast_short_history(stream_rast, "raster", &history); Rast_command_history(&history); Rast_write_history(stream_rast, &history); } if (dir_rast) { struct Colors colors; Rast_close(dir_fd); G_free(cell_buf2); Rast_short_history(dir_rast, "raster", &history); Rast_command_history(&history); Rast_write_history(dir_rast, &history); Rast_init_colors(&colors); Rast_make_aspect_colors(&colors, -8, 8); Rast_write_colors(dir_rast, G_mapset(), &colors); } /* close stream vector */ if (stream_vect) { if (close_streamvect(stream_vect) < 0) G_fatal_error(_("Unable to write vector map <%s>"), stream_vect); } /* rearranging desk chairs on the Titanic... */ G_free(outlets); /* free stream nodes */ for (i = 1; i <= n_stream_nodes; i++) { if (stream_node[i].n_alloc > 0) { G_free(stream_node[i].trib); } } G_free(stream_node); return 1; }
int thin_streams(void) { int i, j, r, c, done; CELL stream_id; int next_node; struct sstack { int stream_id; int next_trib; } *nodestack; int top = 0, stack_step = 1000; int n_trib_total; int n_thinned = 0; G_message(_("Thinning stream segments...")); nodestack = (struct sstack *)G_malloc(stack_step * sizeof(struct sstack)); for (i = 0; i < n_outlets; i++) { G_percent(i, n_outlets, 2); r = outlets[i].r; c = outlets[i].c; cseg_get(&stream, &stream_id, r, c); if (stream_id == 0) continue; /* add root node to stack */ G_debug(2, "add root node"); top = 0; nodestack[top].stream_id = stream_id; nodestack[top].next_trib = 0; /* depth first post order traversal */ G_debug(2, "traverse"); while (top >= 0) { done = 1; stream_id = nodestack[top].stream_id; G_debug(3, "stream_id %d, top %d", stream_id, top); if (nodestack[top].next_trib < stream_node[stream_id].n_trib) { /* add to stack */ G_debug(3, "get next node"); next_node = stream_node[stream_id].trib[nodestack[top].next_trib]; G_debug(3, "add to stack: next %d, trib %d, n trib %d", next_node, nodestack[top].next_trib, stream_node[stream_id].n_trib); nodestack[top].next_trib++; top++; if (top >= stack_step) { /* need more space */ stack_step += 1000; nodestack = (struct sstack *)G_realloc(nodestack, stack_step * sizeof(struct sstack)); } nodestack[top].next_trib = 0; nodestack[top].stream_id = next_node; done = 0; G_debug(3, "go further down"); } if (done) { /* thin stream segment */ G_debug(3, "thin stream segment %d", stream_id); if (thin_seg(stream_id) == 0) G_debug(3, "segment %d not thinned", stream_id); else { G_debug(3, "segment %d thinned", stream_id); n_thinned++; } top--; /* count tributaries */ if (top >= 0) { n_trib_total = 0; stream_id = nodestack[top].stream_id; for (j = 0; j < stream_node[stream_id].n_trib; j++) { /* intermediate */ if (stream_node[stream_node[stream_id].trib[j]]. n_trib > 0) n_trib_total += stream_node[stream_node[stream_id].trib[j]]. n_trib_total; /* start */ else n_trib_total++; } stream_node[stream_id].n_trib_total = n_trib_total; } } } } G_percent(n_outlets, n_outlets, 1); /* finish it */ G_free(nodestack); G_verbose_message(_("%d of %lld stream segments were thinned"), n_thinned, n_stream_nodes); return 1; }
int thin_seg(int stream_id) { int thinned = 0; int r, c, r_nbr, c_nbr, last_r, last_c; CELL curr_stream, no_stream = 0; int asp_r[9] = { 0, -1, -1, -1, 0, 1, 1, 1, 0 }; int asp_c[9] = { 0, 1, 0, -1, -1, -1, 0, 1, 1 }; ASP_FLAG af; r = stream_node[stream_id].r; c = stream_node[stream_id].c; cseg_get(&stream, &curr_stream, r, c); seg_get(&aspflag, (char *)&af, r, c); if (af.asp > 0) { /* get downstream point */ last_r = r + asp_r[(int)af.asp]; last_c = c + asp_c[(int)af.asp]; cseg_get(&stream, &curr_stream, last_r, last_c); if (curr_stream != stream_id) return thinned; /* get next downstream point */ seg_get(&aspflag, (char *)&af, last_r, last_c); while (af.asp > 0) { r_nbr = last_r + asp_r[(int)af.asp]; c_nbr = last_c + asp_c[(int)af.asp]; if (r_nbr == last_r && c_nbr == last_c) return thinned; if (r_nbr < 0 || r_nbr >= nrows || c_nbr < 0 || c_nbr >= ncols) return thinned; cseg_get(&stream, &curr_stream, r_nbr, c_nbr); if (curr_stream != stream_id) return thinned; if (abs(r_nbr - r) < 2 && abs(c_nbr - c) < 2) { /* eliminate last point */ cseg_put(&stream, &no_stream, last_r, last_c); FLAG_UNSET(af.flag, STREAMFLAG); seg_put(&aspflag, (char *)&af, last_r, last_c); /* update start point */ seg_get(&aspflag, (char *)&af, r, c); af.asp = drain[r - r_nbr + 1][c - c_nbr + 1]; seg_put(&aspflag, (char *)&af, r, c); thinned = 1; } else { /* nothing to eliminate, continue from last point */ r = last_r; c = last_c; } last_r = r_nbr; last_c = c_nbr; seg_get(&aspflag, (char *)&af, last_r, last_c); } } return thinned; }