int overland_cells_recursive(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; bas[SEG_INDEX(bas_seg, row, col)] = basin_num; haf[SEG_INDEX(haf_seg, row, col)] = haf_num; 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) { if (r == row && c == col) continue; value = asp[SEG_INDEX(asp_seg, r, c)]; if (value == drain[rr][cc]) { overland_cells(r, c, basin_num, haf_num, &new_ele); } } } } /* if (arm_flag) { if (new_max_ele == BIGNEG) { *hih_ele = alt[SEG_INDEX(alt_seg, row, col)]; } else { *hih_ele = new_max_ele; } } */ return 0; }
/* non-recursive version */ int overland_cells(int row, int col, CELL basin_num, CELL haf_num, CELL * hih_ele) { int r, c, rr, cc, next_r, next_c; int top = 0, idx; /* put root on stack */ ocs[top].row = row; ocs[top].col = col; idx = SEG_INDEX(bas_seg, row, col); bas[idx] = basin_num; haf[idx] = haf_num; top++; while (top) { top--; next_r = ocs[top].row; next_c = ocs[top].col; for (r = next_r - 1, rr = 0; r <= next_r + 1; r++, rr++) { for (c = next_c - 1, cc = 0; c <= next_c + 1; c++, cc++) { if (r >= 0 && c >= 0 && r < nrows && c < ncols) { if (r == row && c == col) continue; idx = SEG_INDEX(bas_seg, r, c); if (asp[idx] == drain[rr][cc]) { if (top >= ocs_alloced) { ocs_alloced += bas_thres; ocs = (OC_STACK *)G_realloc(ocs, ocs_alloced * sizeof(OC_STACK)); } ocs[top].row = r; ocs[top].col = c; bas[idx] = basin_num; haf[idx] = haf_num; top++; } } } } } /* if (arm_flag) { 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; G_message(_("SECTION 4: RUSLE LS and/or S factor determination.")); if (ril_flag) ril_buf = Rast_allocate_c_buf(); for (r = 0; r < nrows; r++) { G_percent(r, nrows, 3); if (ril_flag) { Rast_get_c_row(ril_fd, ril_buf, r); } for (c = 0; c < ncols; c++) { low_elev = alt[SEG_INDEX(alt_seg, r, c)]; hih_elev = r_h[SEG_INDEX(r_h_seg, r, c)]; length = s_l[SEG_INDEX(s_l_seg, 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 (sg_flag) s_g[SEG_INDEX(s_g_seg, r, c)] = S; if (ls_flag) { length *= METER_TO_FOOT; len_slp_equ(length, sin_theta, S, r, c); } } } G_percent(nrows, nrows, 1); /* finish it */ if (ril_flag) { G_free(ril_buf); Rast_close(ril_fd); } return 0; }
idn_result_t idn_ucsset_lookup(idn_ucsset_t ctx, unsigned long v, int *found) { int idx; segment_t *segments; assert(ctx != NULL && ctx->refcnt > 0 && found != NULL); TRACE(("idn_ucsset_lookup(v=U+%lX)\n", v)); /* Make sure it is fixed. */ if (!ctx->fixed) { WARNING(("idn_ucsset_lookup: not fixed yet\n")); return (idn_failure); } /* Check the given code point. */ if (v >= UCS_MAX) return (idn_invalid_codepoint); /* Get the segment 'v' belongs to. */ segments = ctx->segments; idx = SEG_INDEX(v); /* Do binary search. */ *found = 0; if (segments[idx].range_start >= 0) { int lo = segments[idx].range_start; int hi = segments[idx].range_end; range_t *ranges = ctx->ranges; while (lo <= hi) { int mid = (lo + hi) / 2; if (v < ranges[mid].from) { hi = mid - 1; } else if (v > ranges[mid].to) { lo = mid + 1; } else { *found = 1; break; } } } return (idn_success); }
int len_slp_equ(double slope_length, double sin_theta, double S, int r, int c) { double ril, s_l_exp, /* m */ rill_ratio, /* Beta */ L; rill_ratio = (sin_theta / 0.0896) / (3.0 * pow(sin_theta, 0.8) + 0.56); if (ril_flag) { ril = ril_buf[c]; } else if (ril_value >= 0.0) { ril = ril_value; } else ril = 0.0; /* rill_ratio equation from Steve Warren */ rill_ratio *= .5 + .005 * ril + .0001 * ril * ril; s_l_exp = rill_ratio / (1 + rill_ratio); L = pow((slope_length / 72.6), s_l_exp); l_s[SEG_INDEX(l_s_seg, r, c)] = L * S; return 0; }
int close_array_seg(void) { struct Colors colors; int incr, max, red, green, blue, rd, gr, bl, flag; int c, r, map_fd; CELL *cellrow, value; CELL *theseg; RAMSEG thesegseg; cellrow = Rast_allocate_c_buf(); if (seg_flag || bas_flag || haf_flag) { if (seg_flag) { theseg = bas; thesegseg = bas_seg; } else if (bas_flag) { theseg = bas; thesegseg = bas_seg; } else { theseg = haf; thesegseg = haf_seg; } max = n_basins; G_debug(1, "%d basins created", max); Rast_init_colors(&colors); if (max > 0) Rast_make_random_colors(&colors, 1, max); else { G_warning(_("No basins were created. Verify threshold and region settings.")); Rast_make_random_colors(&colors, 1, 2); } if (max < 1000 && max > 0) { Rast_set_c_color((CELL) 0, 0, 0, 0, &colors); r = 1; incr = 0; while (incr >= 0) { G_percent(r, max, 2); for (gr = 130 + incr; gr <= 255; gr += 20) { for (rd = 90 + incr; rd <= 255; rd += 30) { for (bl = 90 + incr; bl <= 255; bl += 40) { flag = 1; while (flag) { Rast_get_c_color(&r, &red, &green, &blue, &colors); /* if existing rule is too dark then append a new rule to override it */ if ((blue * .11 + red * .30 + green * .59) < 100) { Rast_set_c_color(r, rd, gr, bl, &colors); flag = 0; } if (++r > max) { gr = rd = bl = 300; flag = 0; incr = -1; } } } } } if (incr >= 0) { incr += 15; if (incr > 120) incr = 7; } } G_percent(r - 1, max, 3); /* finish it */ } else G_debug(1, "Too many subbasins to reasonably check for color brightness"); /* using the existing stack of while/for/for/for/while loops ... */ } /* stream segments map */ if (seg_flag) { map_fd = Rast_open_c_new(seg_name); for (r = 0; r < nrows; r++) { Rast_set_c_null_value(cellrow, ncols); /* reset row to all NULL */ for (c = 0; c < ncols; c++) { value = FLAG_GET(swale, r, c); if (value) cellrow[c] = bas[SEG_INDEX(bas_seg, r, c)]; } Rast_put_row(map_fd, cellrow, CELL_TYPE); } Rast_close(map_fd); Rast_write_colors(seg_name, this_mapset, &colors); } /* basins map */ if (bas_flag) { map_fd = Rast_open_c_new(bas_name); for (r = 0; r < nrows; r++) { for (c = 0; c < ncols; c++) { cellrow[c] = bas[SEG_INDEX(bas_seg, r, c)]; if (cellrow[c] == 0) Rast_set_c_null_value(cellrow + c, 1); } Rast_put_row(map_fd, cellrow, CELL_TYPE); } Rast_close(map_fd); Rast_write_colors(bas_name, this_mapset, &colors); } /* half_basins map */ if (haf_flag) { map_fd = Rast_open_c_new(haf_name); for (r = 0; r < nrows; r++) { for (c = 0; c < ncols; c++) { cellrow[c] = haf[SEG_INDEX(haf_seg, r, c)]; if (cellrow[c] == 0) Rast_set_c_null_value(cellrow + c, 1); } Rast_put_row(map_fd, cellrow, CELL_TYPE); } Rast_close(map_fd); Rast_write_colors(haf_name, this_mapset, &colors); } if (seg_flag || bas_flag || haf_flag) Rast_free_colors(&colors); G_free(haf); G_free(bas); G_free(cellrow); if (arm_flag) fclose(fp); close_maps(); return 0; }
void idn_ucsset_fix(idn_ucsset_t ctx) { int nranges; range_t *ranges; segment_t *segments; int i, j; assert(ctx != NULL && ctx->refcnt > 0); TRACE(("idn_ucsset_fix()\n")); nranges = ctx->nranges; ranges = ctx->ranges; segments = ctx->segments; if (ctx->fixed) return; ctx->fixed = 1; /* Initialize segment array */ for (i = 0; i < SEG_LEN; i++) { segments[i].range_start = -1; segments[i].range_end = -1; } /* If the set is empty, there's nothing to be done. */ if (nranges == 0) return; /* Sort ranges. */ qsort(ranges, nranges, sizeof(range_t), comp_range); /* Merge overlapped/continuous ranges. */ for (i = 0, j = 1; j < nranges; j++) { if (ranges[i].to + 1 >= ranges[j].from) { /* can be merged */ if (ranges[i].to < ranges[j].to) { ranges[i].to = ranges[j].to; } } else { i++; if (i < j) ranges[i] = ranges[j]; } } /* 'i' points the last range in the array. */ ctx->nranges = nranges = ++i; /* Create segment array. */ for (i = 0; i < nranges; i++) { int fidx = SEG_INDEX(ranges[i].from); int tidx = SEG_INDEX(ranges[i].to); for (j = fidx; j <= tidx; j++) { if (segments[j].range_start < 0) segments[j].range_start = i; segments[j].range_end = i; } } #if 0 /* * Does the standard guarantee realloc() always succeeds * when shrinking? */ /* Shrink malloc'ed space if possible. */ ctx->ranges = realloc(ctx->ranges, ctx->nranges * sizeof(range_t)); #endif }
int do_cum_mfd(void) { int r, c, dr, dc; CELL is_swale; DCELL value, valued, tci_div, sum_contour, cell_size; int killer, threshold; /* MFD */ int mfd_cells, stream_cells, swale_cells, astar_not_set, is_null; double *dist_to_nbr, *contour, *weight, sum_weight, max_weight; int r_nbr, c_nbr, r_max, c_max, ct_dir, np_side; CELL ele, ele_nbr, aspect, is_worked; double prop, max_val; int workedon, edge, flat; 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 }; int this_index, down_index, nbr_index; G_message(_("SECTION 3a: Accumulating Surface Flow with MFD.")); G_debug(1, "MFD convergence factor set to %d.", c_fac); /* distances to neighbours, weights, contour lengths */ dist_to_nbr = (double *)G_malloc(sides * sizeof(double)); weight = (double *)G_malloc(sides * sizeof(double)); contour = (double *)G_malloc(sides * sizeof(double)); cell_size = get_dist(dist_to_nbr, contour); flag_clear_all(worked); workedon = 0; if (bas_thres <= 0) threshold = 60; else threshold = bas_thres; for (killer = 1; killer <= do_points; killer++) { G_percent(killer, do_points, 1); this_index = astar_pts[killer]; seg_index_rc(alt_seg, this_index, &r, &c); FLAG_SET(worked, r, c); aspect = asp[this_index]; if (aspect) { dr = r + asp_r[ABS(aspect)]; dc = c + asp_c[ABS(aspect)]; } else dr = dc = -1; if (dr >= 0 && dr < nrows && dc >= 0 && dc < ncols) { /* if ((dr = astar_pts[killer].downr) > -1) { */ value = wat[this_index]; down_index = SEG_INDEX(wat_seg, dr, dc); /* get weights */ max_weight = 0; sum_weight = 0; np_side = -1; mfd_cells = 0; astar_not_set = 1; ele = alt[this_index]; is_null = 0; edge = 0; /* this loop is needed to get the sum of weights */ for (ct_dir = 0; ct_dir < sides; ct_dir++) { /* get r, c (r_nbr, c_nbr) for neighbours */ r_nbr = r + nextdr[ct_dir]; c_nbr = c + nextdc[ct_dir]; weight[ct_dir] = -1; if (dr == r_nbr && dc == c_nbr) np_side = ct_dir; /* check that neighbour is within region */ if (r_nbr >= 0 && r_nbr < nrows && c_nbr >= 0 && c_nbr < ncols) { nbr_index = SEG_INDEX(wat_seg, r_nbr, c_nbr); valued = wat[nbr_index]; ele_nbr = alt[nbr_index]; is_worked = FLAG_GET(worked, r_nbr, c_nbr); if (is_worked == 0) { is_null = Rast_is_c_null_value(&ele_nbr); edge = is_null; if (!is_null && ele_nbr <= ele) { if (ele_nbr < ele) { weight[ct_dir] = mfd_pow(((ele - ele_nbr) / dist_to_nbr[ct_dir]), c_fac); } if (ele_nbr == ele) { weight[ct_dir] = mfd_pow((0.5 / dist_to_nbr[ct_dir]), c_fac); } sum_weight += weight[ct_dir]; mfd_cells++; if (weight[ct_dir] > max_weight) { max_weight = weight[ct_dir]; } if (dr == r_nbr && dc == c_nbr) { astar_not_set = 0; } if (value < 0 && valued > 0) wat[nbr_index] = -valued; } } } else edge = 1; if (edge) break; } /* do not distribute flow along edges, this causes artifacts */ if (edge) { continue; } /* honour A * path * mfd_cells == 0: fine, SFD along A * path * mfd_cells == 1 && astar_not_set == 0: fine, SFD along A * path * mfd_cells > 0 && astar_not_set == 1: A * path not included, add to mfd_cells */ /* MFD, A * path not included, add to mfd_cells */ if (mfd_cells > 0 && astar_not_set == 1) { mfd_cells++; sum_weight += max_weight; weight[np_side] = max_weight; } /* set flow accumulation for neighbours */ max_val = -1; tci_div = sum_contour = 0.; if (mfd_cells > 1) { prop = 0.0; for (ct_dir = 0; ct_dir < sides; ct_dir++) { r_nbr = r + nextdr[ct_dir]; c_nbr = c + nextdc[ct_dir]; /* check that neighbour is within region */ if (r_nbr >= 0 && r_nbr < nrows && c_nbr >= 0 && c_nbr < ncols && weight[ct_dir] > -0.5) { is_worked = FLAG_GET(worked, r_nbr, c_nbr); if (is_worked == 0) { nbr_index = SEG_INDEX(wat_seg, r_nbr, c_nbr); weight[ct_dir] = weight[ct_dir] / sum_weight; /* check everything adds up to 1.0 */ prop += weight[ct_dir]; if (atanb_flag) { sum_contour += contour[ct_dir]; tci_div += get_slope_tci(ele, alt[nbr_index], dist_to_nbr[ct_dir]) * weight[ct_dir]; } valued = wat[nbr_index]; if (value > 0) { if (valued > 0) valued += value * weight[ct_dir]; else valued -= value * weight[ct_dir]; } else { if (valued < 0) valued += value * weight[ct_dir]; else valued = value * weight[ct_dir] - valued; } wat[nbr_index] = valued; } else if (ct_dir == np_side) { /* check for consistency with A * path */ workedon++; } } } if (ABS(prop - 1.0) > 5E-6f) { G_warning(_("MFD: cumulative proportion of flow distribution not 1.0 but %f"), prop); } } /* SFD-like accumulation */ else { valued = wat[down_index]; if (value > 0) { if (valued > 0) valued += value; else valued -= value; } else { if (valued < 0) valued += value; else valued = value - valued; } wat[down_index] = valued; if (atanb_flag) { sum_contour = contour[np_side]; tci_div = get_slope_tci(ele, alt[down_index], dist_to_nbr[np_side]); } } /* topographic wetness index ln(a / tan(beta)) and * stream power index a * tan(beta) */ if (atanb_flag) { sca[this_index] = fabs(wat[this_index]) * (cell_size / sum_contour); tanb[this_index] = tci_div; } } } if (workedon) G_warning(n_("MFD: A * path already processed when distributing flow: %d of %d cell", "MFD: A * path already processed when distributing flow: %d of %d cells", do_points), workedon, do_points); G_message(_("SECTION 3b: Adjusting drainage directions.")); for (killer = 1; killer <= do_points; killer++) { G_percent(killer, do_points, 1); this_index = astar_pts[killer]; seg_index_rc(alt_seg, this_index, &r, &c); FLAG_UNSET(worked, r, c); aspect = asp[this_index]; if (aspect) { dr = r + asp_r[ABS(aspect)]; dc = c + asp_c[ABS(aspect)]; } else dr = dc = -1; if (dr >= 0 && dr < nrows && dc >= 0 && dc < ncols) { /* if ((dr = astar_pts[killer].downr) > -1) { */ value = wat[this_index]; down_index = SEG_INDEX(wat_seg, dr, dc); r_max = dr; c_max = dc; /* get max flow accumulation */ max_val = -1; stream_cells = 0; swale_cells = 0; ele = alt[this_index]; is_null = 0; edge = 0; flat = 1; for (ct_dir = 0; ct_dir < sides; ct_dir++) { /* get r, c (r_nbr, c_nbr) for neighbours */ r_nbr = r + nextdr[ct_dir]; c_nbr = c + nextdc[ct_dir]; /* check that neighbour is within region */ if (r_nbr >= 0 && r_nbr < nrows && c_nbr >= 0 && c_nbr < ncols) { nbr_index = SEG_INDEX(wat_seg, r_nbr, c_nbr); /* check for swale or stream cells */ is_swale = FLAG_GET(swale, r_nbr, c_nbr); if (is_swale) swale_cells++; valued = wat[nbr_index]; ele_nbr = alt[nbr_index]; edge = Rast_is_c_null_value(&ele_nbr); if ((ABS(valued) + 0.5) >= threshold && ele_nbr > ele) stream_cells++; is_worked = !(FLAG_GET(worked, r_nbr, c_nbr)); if (is_worked == 0) { if (ele_nbr != ele) flat = 0; is_null = Rast_is_c_null_value(&ele_nbr); edge = is_null; if (!is_null && ABS(valued) > max_val) { max_val = ABS(valued); r_max = r_nbr; c_max = c_nbr; } } } else edge = 1; if (edge) break; } /* do not distribute flow along edges, this causes artifacts */ if (edge) { is_swale = FLAG_GET(swale, r, c); if (is_swale && aspect > 0) { aspect = -1 * drain[r - r_nbr + 1][c - c_nbr + 1]; asp[this_index] = aspect; } continue; } /* update asp */ if (dr != r_max || dc != c_max) { aspect = drain[r - r_max + 1][c - c_max + 1]; if (asp[this_index] < 0) aspect = -aspect; asp[this_index] = aspect; } is_swale = FLAG_GET(swale, r, c); /* start new stream */ value = ABS(value) + 0.5; if (!is_swale && (int)value >= threshold && stream_cells < 1 && swale_cells < 1 && !flat) { FLAG_SET(swale, r, c); is_swale = 1; } /* continue stream */ if (is_swale) { FLAG_SET(swale, r_max, c_max); } else { if (er_flag && !is_swale) slope_length(r, c, r_max, c_max); } } } G_free(astar_pts); flag_destroy(worked); G_free(dist_to_nbr); G_free(weight); return 0; }
int do_cum(void) { int r, c, dr, dc; int r_nbr, c_nbr, ct_dir, np_side, edge; CELL is_swale, aspect, ele_nbr; DCELL value, valued; int killer, threshold; 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 }; int this_index, down_index, nbr_index; double *dist_to_nbr, *contour; double cell_size; G_message(_("SECTION 3: Accumulating Surface Flow with SFD.")); /* distances to neighbours, contour lengths */ dist_to_nbr = (double *)G_malloc(sides * sizeof(double)); contour = (double *)G_malloc(sides * sizeof(double)); cell_size = get_dist(dist_to_nbr, contour); if (bas_thres <= 0) threshold = 60; else threshold = bas_thres; for (killer = 1; killer <= do_points; killer++) { G_percent(killer, do_points, 1); this_index = astar_pts[killer]; aspect = asp[this_index]; seg_index_rc(alt_seg, this_index, &r, &c); if (aspect) { dr = r + asp_r[ABS(aspect)]; dc = c + asp_c[ABS(aspect)]; } /* skip user-defined depressions */ else dr = dc = -1; if (dr >= 0 && dr < nrows && dc >= 0 && dc < ncols) { /* if ((dr = astar_pts[killer].downr) > -1) { */ down_index = SEG_INDEX(wat_seg, dr, dc); value = wat[this_index]; if (fabs(value) >= threshold) FLAG_SET(swale, r, c); valued = wat[down_index]; edge = 0; np_side = -1; for (ct_dir = 0; ct_dir < sides; ct_dir++) { /* get r, c (r_nbr, c_nbr) for neighbours */ r_nbr = r + nextdr[ct_dir]; c_nbr = c + nextdc[ct_dir]; if (dr == r_nbr && dc == c_nbr) np_side = ct_dir; /* check that neighbour is within region */ if (r_nbr >= 0 && r_nbr < nrows && c_nbr >= 0 && c_nbr < ncols) { nbr_index = SEG_INDEX(wat_seg, r_nbr, c_nbr); ele_nbr = alt[nbr_index]; if (Rast_is_c_null_value(&ele_nbr)) edge = 1; } else edge = 1; if (edge) break; } /* do not distribute flow along edges, this causes artifacts */ if (edge) { is_swale = FLAG_GET(swale, r, c); if (is_swale && aspect > 0) { aspect = -1 * drain[r - r_nbr + 1][c - c_nbr + 1]; asp[this_index] = aspect; } if (valued > 0) wat[down_index] = -valued; continue; } if (value > 0) { if (valued > 0) valued += value; else valued -= value; } else { if (valued < 0) valued += value; else valued = value - valued; } wat[down_index] = valued; /* topographic wetness index ln(a / tan(beta)) and * stream power index a * tan(beta) */ if (atanb_flag) { sca[this_index] = fabs(wat[this_index]) * (cell_size / contour[np_side]); tanb[this_index] = get_slope_tci(alt[this_index], alt[down_index], dist_to_nbr[np_side]); } is_swale = FLAG_GET(swale, r, c); if (is_swale || fabs(valued) >= threshold) { FLAG_SET(swale, dr, dc); } else { if (er_flag && !is_swale) slope_length(r, c, dr, dc); } } } G_free(astar_pts); return 0; }
/* * return 0 if nothing was modidied * return 1 if elevation was modified */ int do_flatarea(int index, CELL ele, CELL *alt_org, CELL *alt_new) { int upr, upc, r, c, ct_dir; CELL is_in_list, is_worked, this_in_list; int index_doer, index_up; int n_flat_cells = 0, counter; CELL ele_nbr, min_ele_diff; int uphill_order, downhill_order, max_uphill_order, max_downhill_order; int last_order; struct pq *up_pq = pq_create(); struct pq *down_pq = pq_create(); struct orders inc_order, *order_found, *nbr_order_found; struct RB_TREE *order_tree = rbtree_create(cmp_orders, sizeof(struct orders)); pq_add(index, down_pq); pq_add(index, up_pq); inc_order.downhill = -1; inc_order.uphill = 0; inc_order.index = index; inc_order.flag = 0; rbtree_insert(order_tree, &inc_order); n_flat_cells = 1; min_ele_diff = INT_MAX; max_uphill_order = max_downhill_order = 0; /* get uphill start points */ G_debug(2, "get uphill start points"); counter = 0; while (down_pq->size) { if ((index_doer = pq_drop(down_pq)) == -1) G_fatal_error("get start points: no more points in down queue"); seg_index_rc(alt_seg, index_doer, &r, &c); FLAG_SET(flat_done, r, c); /* check all neighbours, breadth first search */ for (ct_dir = 0; ct_dir < sides; ct_dir++) { /* get r, c (upr, upc) for this neighbour */ upr = r + nextdr[ct_dir]; upc = c + nextdc[ct_dir]; /* check if r, c are within region */ if (upr >= 0 && upr < nrows && upc >= 0 && upc < ncols) { index_up = SEG_INDEX(alt_seg, upr, upc); is_in_list = FLAG_GET(in_list, upr, upc); is_worked = FLAG_GET(worked, upr, upc); ele_nbr = alt_org[index_up]; if (ele_nbr == ele && !is_worked) { inc_order.downhill = -1; inc_order.uphill = -1; inc_order.index = index_up; inc_order.flag = 0; /* not yet added to queue */ if ((order_found = rbtree_find(order_tree, &inc_order)) == NULL) { n_flat_cells++; /* add to down queue if not yet in there */ pq_add(index_up, down_pq); /* add to up queue if not yet in there */ if (is_in_list) { pq_add(index_up, up_pq); /* set uphill order to 0 */ inc_order.uphill = 0; counter++; } rbtree_insert(order_tree, &inc_order); } } } } } /* flat area too small, not worth the effort */ if (n_flat_cells < 5) { /* clean up */ pq_destroy(up_pq); pq_destroy(down_pq); rbtree_destroy(order_tree); return 0; } G_debug(2, "%d flat cells, %d cells in tree, %d start cells", n_flat_cells, (int)order_tree->count, counter); pq_destroy(down_pq); down_pq = pq_create(); /* got uphill start points, do uphill correction */ G_debug(2, "got uphill start points, do uphill correction"); counter = 0; uphill_order = 1; while (up_pq->size) { int is_in_down_queue = 0; if ((index_doer = pq_drop(up_pq)) == -1) G_fatal_error("uphill order: no more points in up queue"); seg_index_rc(alt_seg, index_doer, &r, &c); this_in_list = FLAG_GET(in_list, r, c); /* get uphill order for this point */ inc_order.index = index_doer; if ((order_found = rbtree_find(order_tree, &inc_order)) == NULL) G_fatal_error(_("flat cell escaped for uphill correction")); last_order = uphill_order - 1; uphill_order = order_found->uphill; if (last_order > uphill_order) G_warning(_("queue error: last uphill order %d > current uphill order %d"), last_order, uphill_order); /* debug */ if (uphill_order == -1) G_fatal_error(_("uphill order not set")); if (max_uphill_order < uphill_order) max_uphill_order = uphill_order; uphill_order++; counter++; /* check all neighbours, breadth first search */ for (ct_dir = 0; ct_dir < sides; ct_dir++) { /* get r, c (upr, upc) for this neighbour */ upr = r + nextdr[ct_dir]; upc = c + nextdc[ct_dir]; /* check if r, c are within region */ if (upr >= 0 && upr < nrows && upc >= 0 && upc < ncols) { index_up = SEG_INDEX(alt_seg, upr, upc); is_in_list = FLAG_GET(in_list, upr, upc); is_worked = FLAG_GET(worked, upr, upc); ele_nbr = alt_org[index_up]; /* all cells that are in_list should have been added * previously as uphill start points */ if (ele_nbr == ele && !is_worked) { inc_order.index = index_up; if ((nbr_order_found = rbtree_find(order_tree, &inc_order)) == NULL) { G_fatal_error(_("flat cell escaped in uphill correction")); } /* not yet added to queue */ if (nbr_order_found->uphill == -1) { if (is_in_list) G_warning("cell should be in queue"); /* add to up queue */ pq_add(index_up, up_pq); /* set nbr uphill order = current uphill order + 1 */ nbr_order_found->uphill = uphill_order; } } /* add focus cell to down queue */ if (!this_in_list && !is_in_down_queue && ele_nbr != ele && !is_in_list && !is_worked) { pq_add(index_doer, down_pq); /* set downhill order to 0 */ order_found->downhill = 0; is_in_down_queue = 1; } if (ele_nbr > ele && min_ele_diff > ele_nbr - ele) min_ele_diff = ele_nbr - ele; } } } /* debug: all flags should be set to 0 */ pq_destroy(up_pq); up_pq = pq_create(); /* got downhill start points, do downhill correction */ G_debug(2, "got downhill start points, do downhill correction"); downhill_order = 1; while (down_pq->size) { if ((index_doer = pq_drop(down_pq)) == -1) G_fatal_error(_("downhill order: no more points in down queue")); seg_index_rc(alt_seg, index_doer, &r, &c); this_in_list = FLAG_GET(in_list, r, c); /* get downhill order for this point */ inc_order.index = index_doer; if ((order_found = rbtree_find(order_tree, &inc_order)) == NULL) G_fatal_error(_("flat cell escaped for downhill correction")); last_order = downhill_order - 1; downhill_order = order_found->downhill; if (last_order > downhill_order) G_warning(_("queue error: last downhill order %d > current downhill order %d"), last_order, downhill_order); /* debug */ if (downhill_order == -1) G_fatal_error(_("downhill order: downhill order not set")); if (max_downhill_order < downhill_order) max_downhill_order = downhill_order; downhill_order++; /* check all neighbours, breadth first search */ for (ct_dir = 0; ct_dir < sides; ct_dir++) { /* get r, c (upr, upc) for this neighbour */ upr = r + nextdr[ct_dir]; upc = c + nextdc[ct_dir]; /* check if r, c are within region */ if (upr >= 0 && upr < nrows && upc >= 0 && upc < ncols) { index_up = SEG_INDEX(alt_seg, upr, upc); is_in_list = FLAG_GET(in_list, upr, upc); is_worked = FLAG_GET(worked, upr, upc); ele_nbr = alt_org[index_up]; if (ele_nbr == ele && !is_worked) { inc_order.index = index_up; if ((nbr_order_found = rbtree_find(order_tree, &inc_order)) == NULL) G_fatal_error(_("flat cell escaped in downhill correction")); /* not yet added to queue */ if (nbr_order_found->downhill == -1) { /* add to down queue */ pq_add(index_up, down_pq); /* set nbr downhill order = current downhill order + 1 */ nbr_order_found->downhill = downhill_order; /* add to up queue */ if (is_in_list) { pq_add(index_up, up_pq); /* set flag */ nbr_order_found->flag = 1; } } } } } } /* got uphill and downhill order, adjust ele */ /* increment: ele += uphill_order + max_downhill_order - downhill_order */ /* decrement: ele += uphill_order - max_uphill_order - downhill_order */ G_debug(2, "adjust ele"); while (up_pq->size) { if ((index_doer = pq_drop(up_pq)) == -1) G_fatal_error("no more points in up queue"); seg_index_rc(alt_seg, index_doer, &r, &c); this_in_list = FLAG_GET(in_list, r, c); /* get uphill and downhill order for this point */ inc_order.index = index_doer; if ((order_found = rbtree_find(order_tree, &inc_order)) == NULL) G_fatal_error(_("flat cell escaped for adjustment")); uphill_order = order_found->uphill; downhill_order = order_found->downhill; /* debug */ if (uphill_order == -1) G_fatal_error(_("adjustment: uphill order not set")); if (!this_in_list && downhill_order == -1) G_fatal_error(_("adjustment: downhill order not set")); /* increment */ if (this_in_list) { downhill_order = max_downhill_order; uphill_order = 0; } alt_new[index_doer] += (uphill_order + (double)(max_downhill_order - downhill_order) / 2.0 + 0.5) / 2.0 + 0.5; /* check all neighbours, breadth first search */ for (ct_dir = 0; ct_dir < sides; ct_dir++) { /* get r, c (upr, upc) for this neighbour */ upr = r + nextdr[ct_dir]; upc = c + nextdc[ct_dir]; /* check if r, c are within region */ if (upr >= 0 && upr < nrows && upc >= 0 && upc < ncols) { index_up = SEG_INDEX(alt_seg, upr, upc); is_in_list = FLAG_GET(in_list, upr, upc); is_worked = FLAG_GET(worked, upr, upc); ele_nbr = alt_org[index_up]; if (ele_nbr == ele && !is_worked) { inc_order.index = index_up; if ((nbr_order_found = rbtree_find(order_tree, &inc_order)) == NULL) G_fatal_error(_("flat cell escaped in adjustment")); /* not yet added to queue */ if (nbr_order_found->flag == 0) { if (is_in_list) G_warning("adjustment: in_list cell should be in queue"); /* add to up queue */ pq_add(index_up, up_pq); nbr_order_found->flag = 1; } } } } } /* clean up */ pq_destroy(up_pq); pq_destroy(down_pq); rbtree_destroy(order_tree); return 1; }
CELL split_stream(int row, int col, int new_r[], int new_c[], int ct, CELL basin_num, double stream_length, CELL old_elev) { CELL downdir, old_basin, new_elev, aspect; double slope, easting, northing; SHORT doit, ctr, updir, splitdir[9]; SHORT thisdir, leftflag, riteflag; int r, c, rr, cc; for (ctr = 1; ctr <= ct; ctr++) splitdir[ctr] = drain[row - new_r[ctr] + 1][col - new_c[ctr] + 1]; updir = splitdir[1]; downdir = asp[SEG_INDEX(asp_seg, row, col)]; if (downdir < 0) downdir = -downdir; riteflag = leftflag = 0; for (r = row - 1, rr = 0; rr < 3; r++, rr++) { for (c = col - 1, cc = 0; cc < 3; c++, cc++) { if (r >= 0 && c >= 0 && r < nrows && c < ncols) { aspect = asp[SEG_INDEX(asp_seg, r, c)]; if (aspect == drain[rr][cc]) { doit = 1; thisdir = updrain[rr][cc]; for (ctr = 1; ctr <= ct; ctr++) { if (thisdir == splitdir[ctr]) { doit = 0; ctr = ct; } } if (doit) { thisdir = updrain[rr][cc]; switch (haf_basin_side (updir, (SHORT) downdir, thisdir)) { case LEFT: overland_cells(r, c, basin_num, basin_num - 1, &new_elev); leftflag++; break; case RITE: overland_cells(r, c, basin_num, basin_num, &new_elev); riteflag++; break; } } } } } } if (leftflag >= riteflag) { haf[SEG_INDEX(haf_seg, row, col)] = basin_num - 1; } else { haf[SEG_INDEX(haf_seg, row, col)] = basin_num; } old_basin = basin_num; new_elev = alt[SEG_INDEX(alt_seg, row, col)]; if ((slope = (new_elev - old_elev) / stream_length) < MIN_SLOPE) slope = MIN_SLOPE; if (arm_flag) fprintf(fp, " %f %f\n", slope, stream_length); for (r = 1; r <= ct; r++) { basin_num += 2; easting = window.west + (new_c[r] + .5) * window.ew_res; northing = window.north - (new_r[r] + .5) * window.ns_res; if (arm_flag) { fprintf(fp, "%5d drains into %5d at %3d %3d %.3f %.3f", (int)basin_num, old_basin, new_r[r], new_c[r], easting, northing); } if (new_r[r] != row && new_c[r] != col) basin_num = def_basin(new_r[r], new_c[r], basin_num, diag, new_elev); else if (new_r[r] != row) basin_num = def_basin(new_r[r], new_c[r], basin_num, window.ns_res, new_elev); else basin_num = def_basin(new_r[r], new_c[r], basin_num, window.ew_res, new_elev); } return (basin_num); }