예제 #1
0
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;
}
예제 #2
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;
}
예제 #3
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;
}
예제 #4
0
파일: ucsset.c 프로젝트: svagionitis/libwww
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);
}
예제 #5
0
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;
}
예제 #6
0
파일: close_maps2.c 프로젝트: caomw/grass
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;
}
예제 #7
0
파일: ucsset.c 프로젝트: svagionitis/libwww
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
}
예제 #8
0
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;
}
예제 #9
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;
}
예제 #10
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;
}
예제 #11
0
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);
}