Example #1
0
int esys_release(struct esys* esys, ocn_entity_token_t token)
{
    if(token >= OCN_MAX_ENTITIES)
        return OCN_ENTITY_ERR_RANGE;

    pthread_spin_lock(&esys->lock);

    struct entityslot* slot = &esys->slots[token];

    if(!FLAG_GET(slot->flags, ENTITYSLOT_FLAG_USED))
    {
        pthread_spin_unlock(&esys->lock);
        return OCN_ENTITY_ERR_NONEXIST;
    }

    if(!FLAG_GET(slot->flags, ENTITYSLOT_FLAG_ISOLATED))
    {
        pthread_spin_unlock(&esys->lock);
        return OCN_ENTITY_ERR_ISOLATED;
    }

    /* --- */

    FLAG_UNSET(slot->flags, ENTITYSLOT_FLAG_ISOLATED);

    /* --- */

    pthread_spin_unlock(&esys->lock);

    return OCN_OK;
}
Example #2
0
int esys_del(struct esys* esys, ocn_entity_token_t token)
{
    if(token >= OCN_MAX_ENTITIES)
        return OCN_ENTITY_ERR_RANGE;

    pthread_spin_lock(&esys->lock);

    struct entityslot* slot = &esys->slots[token];

    if(!FLAG_GET(slot->flags, ENTITYSLOT_FLAG_USED))
    {
        pthread_spin_unlock(&esys->lock);
        return OCN_ENTITY_ERR_NONEXIST;
    }

    if(FLAG_GET(slot->flags, ENTITYSLOT_FLAG_ISOLATED))
    {
        pthread_spin_unlock(&esys->lock);
        return OCN_ENTITY_ERR_ISOLATED;
    }

    /* --- */

    entity_t* entity = &slot->entity;
    slot->flags = 0lu;
    esys->count--;

    /* --- */

    pthread_spin_unlock(&esys->lock);

    entity_destroy(entity);

    return OCN_OK;
}
Example #3
0
int esys_unlink(struct esys* esys, ocn_entity_token_t token, ocn_entity_offset_t offset)
{
    if(token >= OCN_MAX_ENTITIES)
        return OCN_ENTITY_ERR_RANGE;

    pthread_spin_lock(&esys->lock);

    struct entityslot* slot = &esys->slots[token];

    if(!FLAG_GET(slot->flags, ENTITYSLOT_FLAG_USED))
    {
        pthread_spin_unlock(&esys->lock);
        return OCN_ENTITY_ERR_NONEXIST;
    }

    if(offset >= OCN_ENTITY_MAX_REFS)
    {
        pthread_spin_unlock(&esys->lock);
        return OCN_ENTITY_ERR_OFFSET;
    }

    /* --- */

    slot->entity.refs[offset] = 0lu;

    /* --- */

    pthread_spin_unlock(&esys->lock);

    return OCN_OK;
}
Example #4
0
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;
}
Example #5
0
int		loop_hook(t_env *e)
{
	if (FLAG_GET(e->flag, MASK_RECALC))
	{
		recalc_scene(e);
		ft_post_processing(e);
		ft_printelapsed(e);
		FLAG_UNSET(e->flag, MASK_RECALC);
	}
	mlx_put_image_to_window(e->mlx, e->win, e->screen->img, 0, 0);
	return (0);
}
Example #6
0
void lsys_log(lsys_t* lsys, int type, const char* format, ...)
{
	ocn_spin_lock(&lsys->lock);

	if(!FLAG_GET(lsys->flags, OCN_LOGGING))
	{
		ocn_spin_unlock(&lsys->lock);
		return;
	}

	//ocn_time_current(&lsys->time);
	uint32_t timestamp = ocn_get_ticks();
	snprintf(&lsys->data[lsys->head][0], LOGGER_HEADER_SIZE + 1, "(%08x)(%04u)[%s]: ",
        timestamp, lsys->head + 1, lsys_type_string(type));

	va_list args;
	va_start(args, format);
	vsnprintf(&lsys->data[lsys->head][LOGGER_HEADER_SIZE], (OCN_LOGGER_MSG_SIZE + 1), format, args);
	va_end(args);

	// for now we also write the entry to stdout (this is bad, because I/O is slow)
	if(FLAG_GET(lsys->flags, OCN_LOGGING_STDOUT))
	{
		fprintf(stdout, lsys->data[lsys->head]);
		fprintf(stdout, "\n");
		//fflush(stdout);
	}

	// set head to next entry or rotate around
	if(lsys->head == (OCN_LOGGER_MAX - 1))
		lsys->head = 0;
	else
		lsys->head++;

	ocn_spin_unlock(&lsys->lock);
}
Example #7
0
static int update_rid(struct globals *globals, int row, int col, int new_id)
{
    int rown, coln, n;
    int neighbors[8][2];
    int this_id;
    int ngbr_id;
    struct rc next;
    struct rclist rilist;
    int no_check;

    /* get this ID */
    Segment_get(&globals->rid_seg, (void *) &this_id, row, col);
    Segment_put(&globals->rid_seg, (void *) &new_id, row, col);

    /* breadth-first search */
    next.row = row;
    next.col = col;
    rclist_init(&rilist);

    do {
	globals->find_neighbors(next.row, next.col, neighbors);
	n = globals->nn - 1;
	do {
	    rown = neighbors[n][0];
	    coln = neighbors[n][1];
	    no_check = 0;
	    if (rown < globals->row_min || rown >= globals->row_max ||
		coln < globals->col_min || coln >= globals->col_max)
		no_check = 1;
	    if (!no_check && (FLAG_GET(globals->null_flag, rown, coln)))
		no_check = 1;

	    if (!no_check) {
		/* get neighbour ID */
		Segment_get(&globals->rid_seg, (void *) &ngbr_id, rown, coln);
		/* same neighbour */
		if (ngbr_id == this_id) {
		    rclist_add(&rilist, rown, coln);
		    Segment_put(&globals->rid_seg, (void *) &new_id, rown, coln);
		}
	    }
	} while (n--);    /* end do loop - next neighbor */
    } while (rclist_drop(&rilist, &next));   /* while there are cells to check */

    rclist_destroy(&rilist);

    return 1;
}
Example #8
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;
}
Example #9
0
static int find_best_neighbour(struct globals *globals, int row, int col,
                               int this_id, struct NB_TREE *nbtree,
			       int *reg_size, struct ngbr_stats **Rbest,
			       int *best_n_row, int *best_n_col)
{
    int rown, coln, n, count;
    int neighbors[8][2];
    struct rc next, ngbr_rc;
    struct rclist rilist;
    int no_check;
    int ngbr_id;
    struct RB_TREE *visited;
    struct ngbr_stats Ri, Rk, *Rfound;
    double sim, best_sim;
    int best_n_id;
    int have_Ri;

    Ri.mean = G_malloc(globals->datasize);
    Rk.mean = G_malloc(globals->datasize);

    nbtree_clear(nbtree);
    FLAG_UNSET(globals->candidate_flag, row, col);

    visited = rbtree_create(cmp_rc, sizeof(struct rc));
    ngbr_rc.row = row;
    ngbr_rc.col = col;
    rbtree_insert(visited, &ngbr_rc);

    /* breadth-first search */
    next.row = row;
    next.col = col;
    rclist_init(&rilist);
    count = 1;
    best_n_id = -1;
    best_sim = 2;
    
    do {
	have_Ri = 0;
	globals->find_neighbors(next.row, next.col, neighbors);
	n = globals->nn - 1;
	do {
	    rown = neighbors[n][0];
	    coln = neighbors[n][1];
	    no_check = 0;
	    if (rown < globals->row_min || rown >= globals->row_max ||
		coln < globals->col_min || coln >= globals->col_max)
		no_check = 1;
	    if (!no_check && (FLAG_GET(globals->null_flag, rown, coln)))
		no_check = 1;

	    ngbr_rc.row = rown;
	    ngbr_rc.col = coln;

	    if (!no_check && !rbtree_find(visited, &ngbr_rc)) {
		rbtree_insert(visited, &ngbr_rc);

		/* get neighbor ID */
		Segment_get(&globals->rid_seg, (void *) &ngbr_id, rown, coln);
		/* same neighbour */
		if (ngbr_id == this_id) {
		    count++;
		    rclist_add(&rilist, rown, coln);
		    FLAG_UNSET(globals->candidate_flag, rown, coln);
		}
		else { /* different neighbour */
		    /* compare to this cell next.row, next.col */
		    if (!have_Ri) {
			Segment_get(globals->bands_out, (void *) Ri.mean, next.row, next.col);
			have_Ri = 1;
		    }
		    Segment_get(globals->bands_out, (void *) Rk.mean, rown, coln);
		    sim = globals->calculate_similarity(&Ri, &Rk, globals);
		    if (best_sim > sim) {
			best_sim = sim;
			best_n_id = ngbr_id;
			*best_n_row = rown;
			*best_n_col = coln;
		    }

		    /* find in neighbor tree */
		    Rk.id = ngbr_id;
		    if ((Rfound = nbtree_find(nbtree, &Rk))) {
			Rfound->count++;
			if (*Rbest && (*Rbest)->count < Rfound->count)
			    *Rbest = Rfound;
		    }
		    else {
			Rk.count = 1;
			Rk.row = rown;
			Rk.col = coln;
			nbtree_insert(nbtree, &Rk);
			if (!(*Rbest))
			    *Rbest = nbtree_find(nbtree, &Rk);
		    }
		}
	    }
	} while (n--);    /* end do loop - next neighbor */
    } while (rclist_drop(&rilist, &next));   /* while there are cells to check */

    rclist_destroy(&rilist);
    rbtree_destroy(visited);
    G_free(Ri.mean);
    G_free(Rk.mean);
    
    *reg_size = count;

    return best_n_id;
}
Example #10
0
int mean_shift(struct globals *globals)
{
    int row, col, t, n;
    int mwrow, mwrow1, mwrow2, mwnrows, mwcol, mwcol1, mwcol2, mwncols, radiusc;
    double hspat, hspec, hspat2, hspec2, sigmaspat2, sigmaspec2;
    double hspecad, hspecad2;
    double ka2;
    double w, wsum;
    LARGEINT n_changes;
    double alpha2, maxdiff2;
    struct ngbr_stats Rin, Rout, Rn;
    double diff, diff2;
    SEGMENT *seg_tmp;
    double mindiff, mindiffzero, mindiffavg, mindiffzeroavg;
    double avgdiff, avgdiffavg;
    LARGEINT nvalid, count;
    int do_gauss = 0, do_adaptive, do_progressive;

    Rin.mean = G_malloc(globals->datasize);
    Rout.mean = G_malloc(globals->datasize);
    Rn.mean = G_malloc(globals->datasize);

    alpha2 = globals->alpha * globals->alpha;
    do_adaptive = globals->ms_adaptive;
    do_progressive = globals->ms_progressive;
    
    globals->candidate_count = 0;
    flag_clear_all(globals->candidate_flag);

    /* Set candidate flag to true/1 for all non-NULL cells */
    for (row = globals->row_min; row < globals->row_max; row++) {
	for (col = globals->col_min; col < globals->col_max; col++) {
	    if (!(FLAG_GET(globals->null_flag, row, col))) {
		
		FLAG_SET(globals->candidate_flag, row, col);
		globals->candidate_count++;
	    }
	}
    }

    /* spatial bandwidth */
    hspat = globals->hs;
    if (hspat < 1) {
	hspat = 1.5;
	globals->hs = hspat;
    }

    hspat2 = hspat * hspat;
    sigmaspat2 = hspat2 / 9.;
    radiusc = hspat;	/* radius in cells truncated to integer */
    mwnrows = mwncols = radiusc * 2 + 1;

    /* estimate spectral bandwidth for given spatial bandwidth */
    mindiffavg = mindiffzeroavg = 0;
    avgdiffavg = 0;
    nvalid = 0;

    G_message(_("Estimating spectral bandwidth for spatial bandwidth %g..."), hspat);
    G_percent_reset();
    for (row = globals->row_min; row < globals->row_max; row++) {
	G_percent(row - globals->row_min,
		  globals->row_max - globals->row_min, 4);

	mwrow1 = row - radiusc;
	mwrow2 = mwrow1 + mwnrows;
	if (mwrow1 < globals->row_min)
	    mwrow1 = globals->row_min;
	if (mwrow2 > globals->row_max)
	    mwrow2 = globals->row_max;

	for (col = globals->col_min; col < globals->col_max; col++) {
	    if ((FLAG_GET(globals->null_flag, row, col)))
		continue;

	    /* get current band values */
	    Segment_get(globals->bands_in, (void *)Rin.mean,
			row, col);

	    mwcol1 = col - radiusc;
	    mwcol2 = mwcol1 + mwncols;
	    if (mwcol1 < globals->col_min)
		mwcol1 = globals->col_min;
	    if (mwcol2 > globals->col_max)
		mwcol2 = globals->col_max;
	    
	    /* get minimum spectral distance for this cell */
	    count = 0;
	    mindiff = globals->max_diff;
	    mindiffzero = globals->max_diff;
	    avgdiff = 0;
	    for (mwrow = mwrow1; mwrow < mwrow2; mwrow++) {
		for (mwcol = mwcol1; mwcol < mwcol2; mwcol++) {
		    if ((FLAG_GET(globals->null_flag, mwrow, mwcol)))
			continue;
		    if (mwrow == row && mwcol == col)
			continue;

		    diff = mwrow - row;
		    diff2 = diff * diff;
		    diff = mwcol - col;
		    diff2 += diff * diff;

		    if (diff2 <= hspat2) {

			Segment_get(globals->bands_in, (void *)Rn.mean,
				    mwrow, mwcol);

			/* get spectral distance */
			diff2 = (globals->calculate_similarity)(&Rin, &Rn, globals);

			if (mindiff > diff2)
			    mindiff = diff2;
			if (mindiffzero > diff2 && diff2 > 0)
			    mindiffzero = diff2;
			avgdiff += sqrt(diff2);
			count++;
		    }
		}
	    }
	    if (count) {
		nvalid++;
		if (mindiff > 0)
		    mindiffavg += sqrt(mindiff);
		mindiffzeroavg += sqrt(mindiffzero);
		if (avgdiff > 0)
		    avgdiffavg += avgdiff / count;
	    }
	}
    }
    G_percent(1, 1, 1);
    if (!nvalid) {
	G_fatal_error(_("Empty moving windows"));
    }

    mindiffavg /= nvalid;
    mindiffzeroavg /= nvalid;
    avgdiffavg /= nvalid;
    G_debug(1, "Average minimum difference to neighbours: %g", mindiffavg);
    G_debug(1, "Average minimum difference excl zero to neighbours: %g", mindiffzeroavg);
    G_debug(1, "Average average difference to neighbours: %g", avgdiffavg);

    /* use avgdiffavg as hspec for adaptive bandwidth */

    hspec = globals->hr;
    if (hspec < 0 || hspec >= 1) {
	hspec = sqrt(avgdiffavg / 10.0);
	hspec = avgdiffavg;
	hspec = mindiffzeroavg;
	
	if (do_progressive)
	    G_message(_("Initial range bandwidth: %g"), hspec);
	else
	    G_message(_("Estimated range bandwidth: %g"), hspec);
	globals->hr = hspec;
    }
    else {
	G_message(_("Estimated range bandwidth: %g"), mindiffzeroavg);
    }
    if (do_adaptive) {
	/* bandwidth is now standard deviation for adaptive bandwidth 
	 * using a gaussian function with range bandwith used as 
	 * bandwidth for the gaussian function
	 * the aim is to produce similar but improved results with 
	 * adaptive bandwidth
	 * thus increase bandwidth */
	hspec = sqrt(hspec);
    }

    hspec2 = hspec * hspec;
    sigmaspec2 = hspec2 / 9.;

    if (!do_progressive) {
	G_message(_("Spatial bandwidth: %g"), hspat);
	G_message(_("Range bandwidth: %g"), hspec);
    }

    G_debug(4, "Starting to process %ld candidate cells",
	    globals->candidate_count);

    t = 0;
    n_changes = 1;
    maxdiff2 = 0;
    while (t < globals->end_t && n_changes > 0) {

	G_message(_("Processing pass %d..."), ++t);

	/* cells within an object should become more similar with each pass
	 * therefore the spectral bandwidth could be decreased
	 * and the spatial bandwidth could be increased */

	/* spatial bandwidth: double the area covered by the moving window
	 * area = M_PI * hspat * hspat
	 * new hspat = sqrt(M_PI * hspat * hspat * 2 / M_PI)
	 * no good, too large increases */

	if (do_progressive) {
	    if (t > 1)
		hspat *= 1.1;
	    hspat2 = hspat * hspat;
	    sigmaspat2 = hspat2 / 9.;
	    radiusc = hspat;	/* radius in cells truncated to integer */
	    mwnrows = mwncols = radiusc * 2 + 1;

	    /* spectral bandwidth: reduce by 0.7 */
	    if (t > 1)
		hspec *= 0.9;
	    hspec2 = hspec * hspec;
	    sigmaspec2 = hspec2 / 9.;

	    G_verbose_message(_("Spatial bandwidth: %g"), hspat);
	    G_verbose_message(_("Range bandwidth: %g"), hspec);
	}

	n_changes = 0;
	maxdiff2 = 0;

	/* swap input and output */
	seg_tmp = globals->bands_in;
	globals->bands_in = globals->bands_out;
	globals->bands_out = seg_tmp;

	/*process candidate cells */
	G_percent_reset();
	for (row = globals->row_min; row < globals->row_max; row++) {
	    G_percent(row - globals->row_min,
	              globals->row_max - globals->row_min, 4);

	    mwrow1 = row - radiusc;
	    mwrow2 = mwrow1 + mwnrows;
	    if (mwrow1 < globals->row_min)
		mwrow1 = globals->row_min;
	    if (mwrow2 > globals->row_max)
		mwrow2 = globals->row_max;

	    for (col = globals->col_min; col < globals->col_max; col++) {
		if ((FLAG_GET(globals->null_flag, row, col)))
		    continue;

		/* get current band values */
		Segment_get(globals->bands_in, (void *)Rin.mean,
			    row, col);
		
		/* init output */
		for (n = 0; n < globals->nbands; n++)
		    Rout.mean[n] = 0.;

		mwcol1 = col - radiusc;
		mwcol2 = mwcol1 + mwncols;
		if (mwcol1 < globals->col_min)
		    mwcol1 = globals->col_min;
		if (mwcol2 > globals->col_max)
		    mwcol2 = globals->col_max;

		hspecad2 = hspec2;
		
		if (do_adaptive) {
		    /* adapt initial range bandwith */
		    
		    ka2 = hspec2; 	/* OTB: conductance parameter */
		    
		    avgdiff = 0;
		    count = 0;
		    for (mwrow = mwrow1; mwrow < mwrow2; mwrow++) {
			for (mwcol = mwcol1; mwcol < mwcol2; mwcol++) {
			    if ((FLAG_GET(globals->null_flag, mwrow, mwcol)))
				continue;
			    if (mwrow == row && mwcol == col)
				continue;

			    diff = mwrow - row;
			    diff2 = diff * diff;
			    diff = mwcol - col;
			    diff2 += diff * diff;

			    if (diff2 <= hspat2) {

				Segment_get(globals->bands_in, (void *)Rn.mean,
					    mwrow, mwcol);

				/* get spectral distance */
				diff2 = (globals->calculate_similarity)(&Rin, &Rn, globals);

				avgdiff += sqrt(diff2);
				count++;
			    }
			}
		    }
		    hspecad2 = 0;
		    if (avgdiff > 0) {
			avgdiff /= count;
			hspecad = hspec;
			/* OTB-like, contrast enhancing */
			hspecad = exp(-avgdiff * avgdiff / (2 * ka2)) * avgdiff;
			/* preference for large regions, from Perona Malik 1990 
			 * if the settings are right, it could be used to reduce noise */
			/* hspecad = 1 / (1 + (avgdiff * avgdiff / (2 * hspec2))); */
			hspecad2 = hspecad * hspecad;
			G_debug(1, "avg spectral diff: %g", avgdiff);
			G_debug(1, "initial hspec2: %g", hspec2);
			G_debug(1, "adapted hspec2: %g", hspecad2);
		    }
		}
		
		/* actual mean shift */
		wsum = 0;
		for (mwrow = mwrow1; mwrow < mwrow2; mwrow++) {
		    for (mwcol = mwcol1; mwcol < mwcol2; mwcol++) {
			if ((FLAG_GET(globals->null_flag, mwrow, mwcol)))
			    continue;
			diff = mwrow - row;
			diff2 = diff * diff;
			diff = mwcol - col;
			diff2 += diff * diff;

			if (diff2 <= hspat2) {
			    w = 1;
			    if (do_gauss)
				w = gauss_kernel(diff2, sigmaspat2);

			    Segment_get(globals->bands_in, (void *)Rn.mean,
					mwrow, mwcol);

			    /* check spectral distance */
			    diff2 = (globals->calculate_similarity)(&Rin, &Rn, globals);
			    if (diff2 <= hspecad2) {
				if (do_gauss)
				    w *= gauss_kernel(diff2, sigmaspec2);
				wsum += w;
				for (n = 0; n < globals->nbands; n++)
				    Rout.mean[n] += w * Rn.mean[n];
			    }
			}
		    }
		}
		
		if (wsum > 0) {
		    for (n = 0; n < globals->nbands; n++)
			Rout.mean[n] /= wsum;
		}
		else {
		    for (n = 0; n < globals->nbands; n++)
			Rout.mean[n] = Rin.mean[n];
		}

		/* put new band values */
		Segment_put(globals->bands_out, (void *)Rout.mean,
			    row, col);

		/* if the squared difference between old and new band values 
		 * is larger than alpha2, then increase n_changes */
		
		diff2 = (globals->calculate_similarity)(&Rin, &Rout, globals);
		if (diff2 > alpha2)
		    n_changes++;
		if (maxdiff2 < diff2)
		    maxdiff2 = diff2;
	    }
	}
	G_percent(1, 1, 1);
	G_message(_("Changes > threshold: %d, largest change: %g"), n_changes, sqrt(maxdiff2));
    }
    if (n_changes > 1)
	G_message(_("Mean shift stopped at %d due to reaching max iteration limit, more changes may be possible"), t);
    else
	G_message(_("Mean shift converged after %d iterations"), t);

    /* identify connected components */
    cluster_bands(globals);

    /* remove small regions */
    remove_small_clumps(globals);
    
    return TRUE;
}
Example #11
0
int init_vars(int argc, char *argv[])
{
    int r, c;
    int ele_fd, wat_fd, fd = -1;
    int seg_rows, seg_cols, num_cseg_total, num_open_segs, num_open_array_segs;
    double memory_divisor, heap_mem, seg_factor, disk_space;

    /* int page_block, num_cseg; */
    int max_bytes;
    CELL *buf, alt_value, *alt_value_buf, block_value;
    char asp_value;
    DCELL wat_value;
    DCELL dvalue;
    WAT_ALT wa, *wabuf;
    ASP_FLAG af, af_nbr, *afbuf;
    char MASK_flag;
    void *elebuf, *ptr, *watbuf, *watptr;
    int ele_map_type, wat_map_type;
    size_t ele_size, wat_size;
    int ct_dir, r_nbr, c_nbr;

    G_gisinit(argv[0]);
    /* input */
    ele_flag = pit_flag = run_flag = ril_flag = 0;
    /* output */
    wat_flag = asp_flag = bas_flag = seg_flag = haf_flag = tci_flag = 0;
    bas_thres = 0;
    /* shed, unused */
    arm_flag = dis_flag = 0;
    /* RUSLE */
    ob_flag = st_flag = sl_flag = sg_flag = ls_flag = er_flag = 0;
    nxt_avail_pt = 0;
    /* dep_flag = 0; */
    max_length = d_zero = 0.0;
    d_one = 1.0;
    ril_value = -1.0;
    /* dep_slope = 0.0; */
    max_bytes = 0;
    sides = 8;
    mfd = 1;
    c_fac = 5;
    abs_acc = 0;
    ele_scale = 1;
    segs_mb = 300;
    /* scan options */
    for (r = 1; r < argc; r++) {
	if (sscanf(argv[r], "elevation=%s", ele_name) == 1)
	    ele_flag++;
	else if (sscanf(argv[r], "accumulation=%s", wat_name) == 1)
	    wat_flag++;
	else if (sscanf(argv[r], "tci=%s", tci_name) == 1)
	    tci_flag++;
	else if (sscanf(argv[r], "drainage=%s", asp_name) == 1)
	    asp_flag++;
	else if (sscanf(argv[r], "depression=%s", pit_name) == 1)
	    pit_flag++;
	else if (sscanf(argv[r], "threshold=%d", &bas_thres) == 1) ;
	else if (sscanf(argv[r], "max_slope_length=%lf", &max_length) == 1) ;
	else if (sscanf(argv[r], "basin=%s", bas_name) == 1)
	    bas_flag++;
	else if (sscanf(argv[r], "stream=%s", seg_name) == 1)
	    seg_flag++;
	else if (sscanf(argv[r], "half_basin=%s", haf_name) == 1)
	    haf_flag++;
	else if (sscanf(argv[r], "flow=%s", run_name) == 1)
	    run_flag++;
	else if (sscanf(argv[r], "ar=%s", arm_name) == 1)
	    arm_flag++;
	/* slope length
	else if (sscanf(argv[r], "slope_length=%s", sl_name) == 1)
	    sl_flag++; */
	else if (sscanf(argv[r], "slope_steepness=%s", sg_name) == 1)
	    sg_flag++;
	else if (sscanf(argv[r], "length_slope=%s", ls_name) == 1)
	    ls_flag++;
	else if (sscanf(argv[r], "blocking=%s", ob_name) == 1)
	    ob_flag++;
	else if (sscanf(argv[r], "memory=%lf", &segs_mb) == 1) ;
	else if (sscanf(argv[r], "disturbed_land=%s", ril_name) == 1) {
	    if (sscanf(ril_name, "%lf", &ril_value) == 0) {
		ril_value = -1.0;
		ril_flag++;
	    }
	}
	/* slope deposition
	else if (sscanf (argv[r], "sd=%[^\n]", dep_name) == 1) dep_flag++; */
	else if (sscanf(argv[r], "-%d", &sides) == 1) {
	    if (sides != 4)
		usage(argv[0]);
	}
	else if (sscanf(argv[r], "convergence=%d", &c_fac) == 1) ;
	else if (strcmp(argv[r], "-s") == 0)
	    mfd = 0;
	else if (strcmp(argv[r], "-a") == 0)
	    abs_acc = 1;
	else
	    usage(argv[0]);
    }
    /* check options */
    if (mfd == 1 && (c_fac < 1 || c_fac > 10)) {
	G_fatal_error("Convergence factor must be between 1 and 10.");
    }
    if ((ele_flag != 1)
	||
	((arm_flag == 1) &&
	 ((bas_thres <= 0) || ((haf_flag != 1) && (bas_flag != 1))))
	||
	((bas_thres <= 0) &&
	 ((bas_flag == 1) || (seg_flag == 1) || (haf_flag == 1) ||
	  (sl_flag == 1) || (sg_flag == 1) || (ls_flag == 1)))
	)
	usage(argv[0]);
    tot_parts = 4;
    if (sl_flag || sg_flag || ls_flag)
	er_flag = 1;
    /* do RUSLE */
    if (er_flag)
	tot_parts++;
    /* define basins */
    if (seg_flag || bas_flag || haf_flag)
	tot_parts++;

    G_message(_n("SECTION 1 beginning: Initiating Variables. %d section total.", 
        "SECTION 1 beginning: Initiating Variables. %d sections total.", 
        tot_parts),
	      tot_parts);

    this_mapset = G_mapset();
    /* for sd factor
       if (dep_flag)        {
       if (sscanf (dep_name, "%lf", &dep_slope) != 1)       {
       dep_flag = -1;
       }
       }
     */
    G_get_set_window(&window);
    nrows = Rast_window_rows();
    ncols = Rast_window_cols();
    if (max_length <= d_zero)
	max_length = 10 * nrows * window.ns_res + 10 * ncols * window.ew_res;
    if (window.ew_res < window.ns_res)
	half_res = .5 * window.ew_res;
    else
	half_res = .5 * window.ns_res;
    diag = sqrt(window.ew_res * window.ew_res +
		window.ns_res * window.ns_res);
    if (sides == 4)
	diag *= 0.5;

    /* Segment rows and cols: 64 */

    seg_rows = SROW;
    seg_cols = SCOL;
    /* seg_factor * <size in bytes> = segment size in KB */
    seg_factor = seg_rows * seg_rows / 1024.;

    if (segs_mb < 3.0) {
	segs_mb = 3;
	G_warning(_("Maximum memory to be used was smaller than 3 MB,"
	            " set to 3 MB."));
    }

    /* balance segment files */
    /* elevation + accumulation: * 2 */
    memory_divisor = sizeof(WAT_ALT) * 2;
    disk_space = sizeof(WAT_ALT);
    /* aspect and flags: * 4 */
    memory_divisor += sizeof(ASP_FLAG) * 4;
    disk_space += sizeof(ASP_FLAG);
    /* astar_points: / 16 */
    /* ideally only a few but large segments */
    memory_divisor += sizeof(POINT) / 16.;
    disk_space += sizeof(POINT);
    /* heap points: / 4 */
    memory_divisor += sizeof(HEAP_PNT) / 4.;
    disk_space += sizeof(HEAP_PNT);
    /* TCI: as is */
    if (tci_flag) {
	memory_divisor += sizeof(double);
	disk_space += sizeof(double);
    }
    /* RUSLE */
    if (er_flag) {
	/* r_h */
	memory_divisor += 4;
	disk_space += 4;
	/* s_l */
	memory_divisor += 8;
	disk_space += 8;
	/* s_g */
	if (sg_flag) {
	    memory_divisor += 8;
	    disk_space += 8;
	}
	/* l_s */
	if (ls_flag) {
	    memory_divisor += 8;
	    disk_space += 8;
	}
	/* ril */
	if (ril_flag) {
	    memory_divisor += 8;
	    disk_space += 8;
	}
    }
    
    /* KB -> MB */
    memory_divisor = memory_divisor * seg_factor / 1024.;
    disk_space = disk_space * seg_factor / 1024.;
    num_open_segs = segs_mb / memory_divisor;
    heap_mem = num_open_segs * seg_factor * sizeof(HEAP_PNT) / (4. * 1024.);

    G_debug(1, "segs MB: %.0f", segs_mb);
    G_debug(1, "region rows: %d", nrows);
    G_debug(1, "seg rows: %d", seg_rows);
    G_debug(1, "region cols: %d", ncols);
    G_debug(1, "seg cols: %d", seg_cols);

    num_cseg_total = nrows / SROW + 1;
    G_debug(1, "   row segments:\t%d", num_cseg_total);

    num_cseg_total = ncols / SCOL + 1;
    G_debug(1, "column segments:\t%d", num_cseg_total);

    num_cseg_total = (ncols / seg_cols + 1) * (nrows / seg_rows + 1);
    G_debug(1, " total segments:\t%d", num_cseg_total);
    G_debug(1, "  open segments:\t%d", num_open_segs);

    /* nonsense to have more segments open than exist */
    if (num_open_segs > num_cseg_total)
	num_open_segs = num_cseg_total;
    G_debug(1, "  open segments after adjusting:\t%d", num_open_segs);

    disk_space *= num_cseg_total;
    if (disk_space < 1024.0)
	G_verbose_message(_("Will need up to %.2f MB of disk space"), disk_space);
    else
	G_verbose_message(_("Will need up to %.2f GB (%.0f MB) of disk space"),
	           disk_space / 1024.0, disk_space);

    if (er_flag) {
	cseg_open(&r_h, seg_rows, seg_cols, num_open_segs);
	cseg_read_cell(&r_h, ele_name, "");
    }
    
    /* read elevation input and mark NULL/masked cells */

    /* scattered access: alt, watalt, bitflags, asp */
    seg_open(&watalt, nrows, ncols, seg_rows, seg_cols, num_open_segs * 2, sizeof(WAT_ALT));
    seg_open(&aspflag, nrows, ncols, seg_rows, seg_cols, num_open_segs * 4, sizeof(ASP_FLAG));

    if (tci_flag)
	dseg_open(&tci, seg_rows, seg_cols, num_open_segs);

    /* open elevation input */
    ele_fd = Rast_open_old(ele_name, "");

    ele_map_type = Rast_get_map_type(ele_fd);
    ele_size = Rast_cell_size(ele_map_type);
    elebuf = Rast_allocate_buf(ele_map_type);
    afbuf = G_malloc(ncols * sizeof(ASP_FLAG));

    if (ele_map_type == FCELL_TYPE || ele_map_type == DCELL_TYPE)
	ele_scale = 1000; 	/* should be enough to do the trick */

    /* initial flow accumulation */
    if (run_flag) {
	wat_fd = Rast_open_old(run_name, "");

	wat_map_type = Rast_get_map_type(ele_fd);
	wat_size = Rast_cell_size(ele_map_type);
	watbuf = Rast_allocate_buf(ele_map_type);
    }
    else {
	watbuf = watptr = NULL;
	wat_fd = wat_size = wat_map_type = -1;
    }
    wabuf = G_malloc(ncols * sizeof(WAT_ALT));
    alt_value_buf = Rast_allocate_buf(CELL_TYPE);

    /* read elevation input and mark NULL/masked cells */
    G_message("SECTION 1a: Mark masked and NULL cells");
    MASK_flag = 0;
    do_points = (GW_LARGE_INT) nrows * ncols;
    for (r = 0; r < nrows; r++) {
	G_percent(r, nrows, 1);
	Rast_get_row(ele_fd, elebuf, r, ele_map_type);
	ptr = elebuf;

	if (run_flag) {
	    Rast_get_row(wat_fd, watbuf, r, wat_map_type);
	    watptr = watbuf;
	}
	
	for (c = 0; c < ncols; c++) {

	    afbuf[c].flag = 0;
	    afbuf[c].asp = 0;

	    /* check for masked and NULL cells */
	    if (Rast_is_null_value(ptr, ele_map_type)) {
		FLAG_SET(afbuf[c].flag, NULLFLAG);
		FLAG_SET(afbuf[c].flag, INLISTFLAG);
		FLAG_SET(afbuf[c].flag, WORKEDFLAG);
		Rast_set_c_null_value(&alt_value, 1);
		/* flow accumulation */
		Rast_set_d_null_value(&wat_value, 1);
		do_points--;
	    }
	    else {
		if (ele_map_type == CELL_TYPE) {
		    alt_value = *((CELL *)ptr);
		}
		else if (ele_map_type == FCELL_TYPE) {
		    dvalue = *((FCELL *)ptr);
		    dvalue *= ele_scale;
		    alt_value = ele_round(dvalue);
		}
		else if (ele_map_type == DCELL_TYPE) {
		    dvalue = *((DCELL *)ptr);
		    dvalue *= ele_scale;
		    alt_value = ele_round(dvalue);
		}

		/* flow accumulation */
		if (run_flag) {
		    if (Rast_is_null_value(watptr, wat_map_type)) {
			wat_value = 0;    /* ok ? */
		    }
		    else {
			if (wat_map_type == CELL_TYPE) {
			    wat_value = *((CELL *)watptr);
			}
			else if (wat_map_type == FCELL_TYPE) {
			    wat_value = *((FCELL *)watptr);
			}
			else if (wat_map_type == DCELL_TYPE) {
			    wat_value = *((DCELL *)watptr);
			}
		    }
		}
		else {
		    wat_value = 1;
		}
	    }
	    wabuf[c].wat = wat_value;
	    wabuf[c].ele = alt_value;
	    alt_value_buf[c] = alt_value;
	    ptr = G_incr_void_ptr(ptr, ele_size);
	    if (run_flag) {
		watptr = G_incr_void_ptr(watptr, wat_size);
	    }
	}
	seg_put_row(&watalt, (char *) wabuf, r);
	seg_put_row(&aspflag, (char *)afbuf, r);
	
	if (er_flag) {
	    cseg_put_row(&r_h, alt_value_buf, r);
	}
    }
    G_percent(nrows, nrows, 1);    /* finish it */
    Rast_close(ele_fd);
    G_free(wabuf);
    G_free(afbuf);
    
    if (run_flag) {
	Rast_close(wat_fd);
	G_free(watbuf);
    }

    MASK_flag = (do_points < nrows * ncols);
    
    /* do RUSLE */
    if (er_flag) {
	if (ob_flag) {
	    fd = Rast_open_old(ob_name, "");
	    buf = Rast_allocate_c_buf();
	    for (r = 0; r < nrows; r++) {
		G_percent(r, nrows, 1);
		Rast_get_c_row(fd, buf, r);
		for (c = 0; c < ncols; c++) {
		    block_value = buf[c];
		    if (!Rast_is_c_null_value(&block_value) && block_value) {
			seg_get(&aspflag, (char *)&af, r, c);
			FLAG_SET(af.flag, RUSLEBLOCKFLAG);
			seg_put(&aspflag, (char *)&af, r, c);
		    }
		}
	    }
	    G_percent(nrows, nrows, 1);    /* finish it */
	    Rast_close(fd);
	    G_free(buf);
	}

	if (ril_flag) {
	    dseg_open(&ril, seg_rows, seg_cols, num_open_segs);
	    dseg_read_cell(&ril, ril_name, "");
	}
	
	/* dseg_open(&slp, SROW, SCOL, num_open_segs); */

	dseg_open(&s_l, seg_rows, seg_cols, num_open_segs);
	if (sg_flag)
	    dseg_open(&s_g, seg_rows, seg_cols, num_open_segs);
	if (ls_flag)
	    dseg_open(&l_s, seg_rows, seg_cols, num_open_segs);
    }

    G_debug(1, "open segments for A* points");
    /* columns per segment */
    seg_cols = seg_rows * seg_rows;
    num_cseg_total = do_points / seg_cols;
    if (do_points % seg_cols > 0)
	num_cseg_total++;
    /* no need to have more segments open than exist */
    num_open_array_segs = num_open_segs / 16.;
    if (num_open_array_segs > num_cseg_total)
	num_open_array_segs = num_cseg_total;
    if (num_open_array_segs < 1)
	num_open_array_segs = 1;
    
    seg_open(&astar_pts, 1, do_points, 1, seg_cols, num_open_array_segs,
	     sizeof(POINT));

    /* one-based d-ary search_heap with astar_pts */
    G_debug(1, "open segments for A* search heap");
    G_debug(1, "heap memory %.2f MB", heap_mem);
    /* columns per segment */
    /* larger is faster */
    seg_cols = seg_rows * seg_rows;
    num_cseg_total = do_points / seg_cols;
    if (do_points % seg_cols > 0)
	num_cseg_total++;
    /* no need to have more segments open than exist */
    num_open_array_segs = (1 << 20) * heap_mem / (seg_cols * sizeof(HEAP_PNT));
    if (num_open_array_segs > num_cseg_total)
	num_open_array_segs = num_cseg_total;
    if (num_open_array_segs < 2)
	num_open_array_segs = 2;

    G_debug(1, "A* search heap open segments %d, total %d",
            num_open_array_segs, num_cseg_total);
    /* the search heap will not hold more than 5% of all points at any given time ? */
    /* chances are good that the heap will fit into one large segment */
    seg_open(&search_heap, 1, do_points + 1, 1, seg_cols,
	     num_open_array_segs, sizeof(HEAP_PNT));

    G_message(_("SECTION 1b: Determining Offmap Flow."));

    /* heap is empty */
    heap_size = 0;

    if (pit_flag) {
	buf = Rast_allocate_c_buf();
	fd = Rast_open_old(pit_name, "");
    }
    else
	buf = NULL;
    first_astar = first_cum = -1;

    for (r = 0; r < nrows; r++) {
	G_percent(r, nrows, 1);
	if (pit_flag)
	    Rast_get_c_row(fd, buf, r);
	for (c = 0; c < ncols; c++) {
	    seg_get(&aspflag, (char *)&af, r, c);
	    if (!FLAG_GET(af.flag, NULLFLAG)) {
		if (er_flag)
		    dseg_put(&s_l, &half_res, r, c);
		asp_value = af.asp;
		if (r == 0 || c == 0 || r == nrows - 1 ||
		    c == ncols - 1) {
		    /* dseg_get(&wat, &wat_value, r, c); */
		    seg_get(&watalt, (char *)&wa, r, c);
		    wat_value = wa.wat;
		    if (wat_value > 0) {
			wat_value = -wat_value;
			/* dseg_put(&wat, &wat_value, r, c); */
			wa.wat = wat_value;
			seg_put(&watalt, (char *)&wa, r, c);
		    }
		    if (r == 0)
			asp_value = -2;
		    else if (c == 0)
			asp_value = -4;
		    else if (r == nrows - 1)
			asp_value = -6;
		    else if (c == ncols - 1)
			asp_value = -8;
		    /* cseg_get(&alt, &alt_value, r, c); */
		    alt_value = wa.ele;
		    add_pt(r, c, alt_value);
		    FLAG_SET(af.flag, INLISTFLAG);
		    FLAG_SET(af.flag, EDGEFLAG);
		    af.asp = asp_value;
		    seg_put(&aspflag, (char *)&af, r, c);
		}
		else {
		    seg_get(&watalt, (char *)&wa, r, c);
		    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];

			seg_get(&aspflag, (char *)&af_nbr, r_nbr, c_nbr);
			if (FLAG_GET(af_nbr.flag, NULLFLAG)) {
			    af.asp = -1 * drain[r - r_nbr + 1][c - c_nbr + 1];
			    add_pt(r, c, wa.ele);
			    FLAG_SET(af.flag, INLISTFLAG);
			    FLAG_SET(af.flag, EDGEFLAG);
			    seg_put(&aspflag, (char *)&af, r, c);
			    wat_value = wa.wat;
			    if (wat_value > 0) {
				wa.wat = -wat_value;
				seg_put(&watalt, (char *)&wa, r, c);
			    }
			    break;
			}
		    }
		}
		/* real depression ? */
		if (pit_flag && asp_value == 0) {
		    if (!Rast_is_c_null_value(&buf[c]) && buf[c] != 0) {

			seg_get(&watalt, (char *)&wa, r, c);
			add_pt(r, c, wa.ele);

			FLAG_SET(af.flag, INLISTFLAG);
			FLAG_SET(af.flag, EDGEFLAG);
			seg_put(&aspflag, (char *)&af, r, c);
			wat_value = wa.wat;
			if (wat_value > 0) {
			    wa.wat = -wat_value;
			    seg_put(&watalt, (char *)&wa, r, c);
			}
		    }
		}

	    }  /* end non-NULL cell */
	}  /* end column */
    }
    G_percent(r, nrows, 1);	/* finish it */

    return 0;
}
Example #12
0
static int read_seed(struct globals *globals, SEGMENT *seeds_seg, struct rc *Ri, int new_id)
{
    int n, i, Ri_id, Rk_id;
    struct rc ngbr_rc, next;
    struct rclist rilist;
    int neighbors[8][2];

    G_debug(4, "read_seed()");

    /* get Ri's segment ID from input seeds */
    Segment_get(seeds_seg, &Ri_id, Ri->row, Ri->col);
    
    /* set new segment id */
    if (Segment_put(&globals->rid_seg, &new_id, Ri->row, Ri->col) != 1)
	G_fatal_error(_("Unable to write to temporary file"));
    /* set candidate flag */
    FLAG_SET(globals->candidate_flag, Ri->row, Ri->col);

    /* initialize region stats */
    globals->rs.count = 1;

    globals->rs.id = new_id;
    Segment_get(&globals->bands_seg, (void *)globals->bands_val,
		Ri->row, Ri->col);

    for (i = 0; i < globals->nbands; i++) {
	globals->rs.sum[i] = globals->bands_val[i];
	globals->rs.mean[i] = globals->bands_val[i];
    }

    /* go through seed, spreading outwards from head */
    rclist_init(&rilist);
    rclist_add(&rilist, Ri->row, Ri->col);

    while (rclist_drop(&rilist, &next)) {

	G_debug(5, "find_pixel_neighbors for row: %d , col %d",
		next.row, next.col);

	globals->find_neighbors(next.row, next.col, neighbors);
	
	for (n = 0; n < globals->nn; n++) {

	    ngbr_rc.row = neighbors[n][0];
	    ngbr_rc.col = neighbors[n][1];

	    if (ngbr_rc.row < 0 || ngbr_rc.row >= globals->nrows ||
		ngbr_rc.col < 0 || ngbr_rc.col >= globals->ncols) {
		continue;
	    }

	    if (FLAG_GET(globals->null_flag, ngbr_rc.row, ngbr_rc.col)) {
		continue;
	    }

	    if (FLAG_GET(globals->candidate_flag, ngbr_rc.row, ngbr_rc.col)) {
		continue;
	    }

	    Segment_get(seeds_seg, (void *) &Rk_id, ngbr_rc.row, ngbr_rc.col);
		
	    G_debug(5, "Rk ID = %d Ri ID = %d", Rk_id, Ri_id);

	    if (Rk_id != Ri_id) {
		continue;
	    }

	    /* set segment id */
	    if (Segment_put(&globals->rid_seg,
	                    &new_id, ngbr_rc.row, ngbr_rc.col) != 1)
		G_fatal_error(_("Unable to write to temporary file"));
	    
	    /* set candidate flag */
	    FLAG_SET(globals->candidate_flag, ngbr_rc.row, ngbr_rc.col);
    
	    /* add to list of cells to check */
	    rclist_add(&rilist, ngbr_rc.row, ngbr_rc.col);
	    
	    /* update region stats */
	    Segment_get(&globals->bands_seg, (void *)globals->bands_val,
			ngbr_rc.row, ngbr_rc.col);

	    for (i = 0; i < globals->nbands; i++) {
		globals->rs.sum[i] += globals->bands_val[i];
	    }
	    globals->rs.count++;
	}
    }

    if (rgtree_find(globals->reg_tree, &(globals->rs)) != NULL) {
	G_fatal_error(_("Segment %d is already registered!"), new_id);
    }
    
    /* insert into region tree */
    if (globals->rs.count >= globals->min_reg_size) {
	for (i = 0; i < globals->nbands; i++)
	    globals->rs.mean[i] = globals->rs.sum[i] / globals->rs.count;

	rgtree_insert(globals->reg_tree, &(globals->rs));
    }
    else {
	if (globals->rs.count > 1)
	    update_band_vals(Ri->row, Ri->col, &(globals->rs), globals);
    }
    if (globals->rs.count > 1)
	globals->n_regions -= (globals->rs.count - 1);

    return 1;
}
Example #13
0
static int load_seeds(struct globals *globals, int srows, int scols, int nseg)
{
    int row, col;
    SEGMENT seeds_seg;
    CELL *seeds_buf, seeds_val;
    int seeds_fd;
    int spos, sneg, have_seeds;
    struct rc Ri;

    G_debug(1, "load_seeds()");
    
    G_message(_("Loading seeds from raster map <%s>..."), globals->seeds);

    if (Segment_open
	(&seeds_seg, G_tempfile(), globals->nrows, globals->ncols,
	 srows, scols, sizeof(CELL), nseg) != TRUE)
	G_fatal_error("Unable to create bounds temporary files");

    seeds_fd = Rast_open_old(globals->seeds, "");
    seeds_buf = Rast_allocate_c_buf();
    
    have_seeds = 0;

    /* load seeds map to segment structure */
    for (row = 0; row < globals->nrows; row++) {
	Rast_get_c_row(seeds_fd, seeds_buf, row);
	for (col = 0; col < globals->ncols; col++) {
	    if (FLAG_GET(globals->null_flag, row, col)) {
		Rast_set_c_null_value(&seeds_val, 1);
	    }
	    else {
		seeds_val = seeds_buf[col];
		if (!Rast_is_c_null_value(&seeds_val))
		    have_seeds = 1;
	    }
	    if (Segment_put(&seeds_seg, &seeds_val, row, col) != 1)
		G_fatal_error(_("Unable to write to temporary file"));
	}
    }

    if (!have_seeds) {
	G_warning(_("No seeds found in '%s'!"), globals->seeds);
	G_free(seeds_buf);
	Rast_close(seeds_fd);
	Segment_close(&seeds_seg);
	return 0;
    }

    spos = 1;
    sneg = -1;

    /* convert seeds to regions */
    G_debug(1, "convert seeds to regions");
    Rast_set_c_null_value(&seeds_val, 1);
    for (row = 0; row < globals->nrows; row++) {
	Rast_get_c_row(seeds_fd, seeds_buf, row);
	for (col = 0; col < globals->ncols; col++) {
	    if (!(FLAG_GET(globals->null_flag, row, col)) && 
	        !(FLAG_GET(globals->candidate_flag, row, col))) {

		if (Rast_is_c_null_value(&(seeds_buf[col]))) {
		    if (Segment_put(&globals->rid_seg, &sneg, row, col) != 1)
			G_fatal_error(_("Unable to write to temporary file"));
		    sneg--;
		    globals->n_regions--;
		}
		else {
		    Ri.row = row;
		    Ri.col = col;
		    read_seed(globals, &seeds_seg, &Ri, spos);
		    spos++;
		}
	    }
	}
    }

    G_free(seeds_buf);
    Rast_close(seeds_fd);
    Segment_close(&seeds_seg);

    globals->n_regions = spos - 1;
    
    flag_clear_all(globals->candidate_flag);
    
    return 1;
}
Example #14
0
int open_files(struct globals *globals)
{
    struct Ref Ref;		/* group reference list */
    int *in_fd, bounds_fd, is_null;
    int n, row, col, srows, scols, inlen, outlen, nseg;
    DCELL **inbuf;		/* buffers to store lines from each of the imagery group rasters */
    CELL *boundsbuf, bounds_val;
    int have_bounds = 0;
    CELL s, id;
    struct Range range;	/* min/max values of bounds map */
    struct FPRange *fp_range;	/* min/max values of each input raster */
    DCELL *min, *max;
    struct ngbr_stats Ri, Rk;

    /*allocate memory for flags */
    globals->null_flag = flag_create(globals->nrows, globals->ncols);
    globals->candidate_flag = flag_create(globals->nrows, globals->ncols);

    flag_clear_all(globals->null_flag);
    flag_clear_all(globals->candidate_flag);

    G_debug(1, "Checking image group...");

    /* ****** open the input rasters ******* */

    if (!I_get_group_ref(globals->image_group, &Ref))
	G_fatal_error(_("Group <%s> not found in the current mapset"),
		      globals->image_group);

    if (Ref.nfiles <= 0)
	G_fatal_error(_("Group <%s> contains no raster maps"),
		      globals->image_group);

    /* Read Imagery Group */

    in_fd = G_malloc(Ref.nfiles * sizeof(int));
    inbuf = (DCELL **) G_malloc(Ref.nfiles * sizeof(DCELL *));
    fp_range = G_malloc(Ref.nfiles * sizeof(struct FPRange));
    min = G_malloc(Ref.nfiles * sizeof(DCELL));
    max = G_malloc(Ref.nfiles * sizeof(DCELL));

    G_debug(1, "Opening input rasters...");
    for (n = 0; n < Ref.nfiles; n++) {
	inbuf[n] = Rast_allocate_d_buf();
	in_fd[n] = Rast_open_old(Ref.file[n].name, Ref.file[n].mapset);
    }

    /* Get min/max values of each input raster for scaling */

    globals->max_diff = 0.;
    globals->nbands = Ref.nfiles;

    for (n = 0; n < Ref.nfiles; n++) {
	/* returns -1 on error, 2 on empty range, quitting either way. */
	if (Rast_read_fp_range(Ref.file[n].name, Ref.file[n].mapset, &fp_range[n]) != 1)
	    G_fatal_error(_("No min/max found in raster map <%s>"),
			  Ref.file[n].name);
	Rast_get_fp_range_min_max(&(fp_range[n]), &min[n], &max[n]);

	G_debug(1, "Range for layer %d: min = %f, max = %f",
		    n, min[n], max[n]);
	
    }
    if (globals->weighted == FALSE)
	globals->max_diff = Ref.nfiles;
    else {
	/* max difference with selected similarity method */
	Ri.mean = max;
	Rk.mean = min;
	globals->max_diff = 1;
	globals->max_diff = (*globals->calculate_similarity) (&Ri, &Rk, globals);
    }

    /* ********** find out file segmentation size ************ */
    G_debug(1, "Calculate temp file sizes...");

    /* size of each element to be stored */

    inlen = sizeof(DCELL) * Ref.nfiles;
    outlen = sizeof(CELL);
    G_debug(1, "data element size, in: %d , out: %d ", inlen, outlen);
    globals->datasize = sizeof(double) * globals->nbands;

    /* count non-null cells */
    globals->notnullcells = (long)globals->nrows * globals->ncols;
    for (row = 0; row < globals->nrows; row++) {
	for (n = 0; n < Ref.nfiles; n++) {
	    Rast_get_d_row(in_fd[n], inbuf[n], row);
	}
	for (col = 0; col < globals->ncols; col++) {

	    is_null = 0;	/*Assume there is data */
	    for (n = 0; n < Ref.nfiles; n++) {
		if (Rast_is_d_null_value(&inbuf[n][col])) {
		    is_null = 1;
		}
	    }
	    if (is_null) {
		globals->notnullcells--;
		FLAG_SET(globals->null_flag, row, col);
	    }
	}
    }
    G_verbose_message(_("Non-NULL cells: %ld"), globals->notnullcells);
    if (globals->notnullcells < 2)
	G_fatal_error(_("Insufficient number of non-NULL cells in current region"));

    /* segment lib segment size */
    srows = 64;
    scols = 64;

    nseg = manage_memory(srows, scols, globals);

    /* create segment structures */
    if (Segment_open
	(&globals->bands_seg, G_tempfile(), globals->nrows, globals->ncols, srows,
	 scols, inlen, nseg) != 1)
	G_fatal_error("Unable to create input temporary files");

    if (Segment_open
	(&globals->rid_seg, G_tempfile(), globals->nrows, globals->ncols, srows,
	 scols, outlen, nseg * 2) != 1)
	G_fatal_error("Unable to create input temporary files");

    /* load input bands to segment structure */
    if (Ref.nfiles > 1)
	G_message(_("Loading input bands..."));
    else
	G_message(_("Loading input band..."));

    globals->bands_val = (double *)G_malloc(inlen);
    globals->second_val = (double *)G_malloc(inlen);
    /* initial segment ID */
    s = 1;

    globals->row_min = globals->nrows;
    globals->row_max = 0;
    globals->col_min = globals->ncols;
    globals->col_max = 0;
    for (row = 0; row < globals->nrows; row++) {
	G_percent(row, globals->nrows, 4);
	for (n = 0; n < Ref.nfiles; n++) {
	    Rast_get_d_row(in_fd[n], inbuf[n], row);
	}
	for (col = 0; col < globals->ncols; col++) {

	    is_null = 0;	/*Assume there is data */
	    for (n = 0; n < Ref.nfiles; n++) {
		globals->bands_val[n] = inbuf[n][col];
		if (Rast_is_d_null_value(&inbuf[n][col])) {
		    is_null = 1;
		}
		else {
		    if (globals->weighted == FALSE)
		    	/* scaled version */
			globals->bands_val[n] = (inbuf[n][col] - min[n]) / (max[n] - min[n]);
		}
	    }
	    if (Segment_put(&globals->bands_seg,
	                    (void *)globals->bands_val, row, col) != 1)
		G_fatal_error(_("Unable to write to temporary file"));

	    if (!is_null) {
		if (!globals->seeds) {
		    /* sequentially number all cells with a unique segment ID */
		    id = s;
		    s++;
		}

		/* get min/max row/col to narrow the processing window */
		if (globals->row_min > row)
		    globals->row_min = row;
		if (globals->row_max < row)
		    globals->row_max = row;
		if (globals->col_min > col)
		    globals->col_min = col;
		if (globals->col_max < col)
		    globals->col_max = col;
	    }
	    else {
		/* all input bands NULL */
		Rast_set_c_null_value(&id, 1);
		FLAG_SET(globals->null_flag, row, col);
	    }
	    if (!globals->seeds || is_null) {
		if (Segment_put(&globals->rid_seg,
		                (void *)&id, row, col) != 1)
		    G_fatal_error(_("Unable to write to temporary file"));
	    }
	}
    }
    G_percent(1, 1, 1);
    G_debug(1, "nrows: %d, min row: %d, max row %d",
	       globals->nrows, globals->row_min, globals->row_max);
    G_debug(1, "ncols: %d, min col: %d, max col %d",
               globals->ncols, globals->col_min, globals->col_max);
    
    globals->row_max++;
    globals->col_max++;
    globals->ncells = (long)(globals->row_max - globals->row_min) *
			    (globals->col_max - globals->col_min);

    /* bounds/constraints */

    Rast_set_c_null_value(&globals->upper_bound, 1);
    Rast_set_c_null_value(&globals->lower_bound, 1);

    if (globals->bounds_map != NULL) {
	if (Segment_open
	    (&globals->bounds_seg, G_tempfile(), globals->nrows, globals->ncols,
	     srows, scols, sizeof(CELL), nseg) != TRUE)
	    G_fatal_error("Unable to create bounds temporary files");

	if (Rast_read_range(globals->bounds_map, globals->bounds_mapset, &range) != 1)
	    G_fatal_error(_("No min/max found in raster map <%s>"),
			  globals->bounds_map);
	Rast_get_range_min_max(&range, &globals->upper_bound,
				       &globals->lower_bound);

	if (Rast_is_c_null_value(&globals->upper_bound) ||
	    Rast_is_c_null_value(&globals->lower_bound)) {
	    
	    G_fatal_error(_("No min/max found in raster map <%s>"),
	                  globals->bounds_map);
	}

	bounds_fd = Rast_open_old(globals->bounds_map, globals->bounds_mapset);
	boundsbuf = Rast_allocate_c_buf();

	for (row = 0; row < globals->nrows; row++) {
	    Rast_get_c_row(bounds_fd, boundsbuf, row);
	    for (col = 0; col < globals->ncols; col++) {
		bounds_val = boundsbuf[col];
		if (FLAG_GET(globals->null_flag, row, col)) {
		    Rast_set_c_null_value(&bounds_val, 1);
		}
		else {
		    if (!Rast_is_c_null_value(&bounds_val)) {
			have_bounds = 1;
			if (globals->lower_bound > bounds_val)
			    globals->lower_bound = bounds_val;
			if (globals->upper_bound < bounds_val)
			    globals->upper_bound = bounds_val;
		    }
		}
		if (Segment_put(&globals->bounds_seg, &bounds_val, row, col) != 1)
		    G_fatal_error(_("Unable to write to temporary file"));
	    }
	}
	Rast_close(bounds_fd);
	G_free(boundsbuf);

	if (!have_bounds) {
	    G_warning(_("There are no boundary constraints in '%s'"), globals->bounds_map);
	    Rast_set_c_null_value(&globals->upper_bound, 1);
	    Rast_set_c_null_value(&globals->lower_bound, 1);
	    Segment_close(&globals->bounds_seg);
	    globals->bounds_map = NULL;
	    globals->bounds_mapset = NULL;
	}
    }
    else {
	G_debug(1, "no boundary constraint supplied.");
    }

    /* other info */
    globals->candidate_count = 0;	/* counter for remaining candidate pixels */

    /* Free memory */

    for (n = 0; n < Ref.nfiles; n++) {
	G_free(inbuf[n]);
	Rast_close(in_fd[n]);
    }

    globals->rs.sum = G_malloc(globals->datasize);
    globals->rs.mean = G_malloc(globals->datasize);

    globals->reg_tree = rgtree_create(globals->nbands, globals->datasize);
    globals->n_regions = s - 1;

    if (globals->seeds) {
	load_seeds(globals, srows, scols, nseg);
    }

    G_debug(1, "Number of initial regions: %d", globals->n_regions);

    G_free(inbuf);
    G_free(in_fd);
    G_free(fp_range);
    G_free(min);
    G_free(max);

    return TRUE;
}
Example #15
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;
}
Example #16
0
int do_astar(void)
{
    int doer, count;
    int upr, upc, r = -1, c = -1, ct_dir;
    CELL alt_val, alt_nbr[8];
    WAT_ALT wa;
    char asp_val;
    char flag_value, is_in_list, is_worked;
    HEAP_PNT heap_p;

    /* sides
     * |7|1|4|
     * |2| |3|
     * |5|0|6|
     */
    int nbr_ew[8] = { 0, 1, 2, 3, 1, 0, 0, 1 };
    int nbr_ns[8] = { 0, 1, 2, 3, 3, 2, 3, 2 };
    double dx, dy, dist_to_nbr[8], ew_res, ns_res;
    double slope[8];
    int skip_diag;
    int count_edge = 0, count_diag = 0, count_edge_sink = 0, count_diag_sink = 0;

    G_message(_("SECTION 2: A* Search."));

    for (ct_dir = 0; ct_dir < sides; ct_dir++) {
	/* get r, c (upr, upc) for neighbours */
	upr = nextdr[ct_dir];
	upc = nextdc[ct_dir];
	/* account for rare cases when ns_res != ew_res */
	dy = ABS(upr) * window.ns_res;
	dx = ABS(upc) * window.ew_res;
	if (ct_dir < 4)
	    dist_to_nbr[ct_dir] = dx + dy;
	else
	    dist_to_nbr[ct_dir] = sqrt(dx * dx + dy * dy);
    }
    ew_res = window.ew_res;
    ns_res = window.ns_res;

    if (heap_size == 0)
	G_fatal_error(_("No seeds for A* Search"));

    G_debug(1, "heap size %d, points %d", heap_size, do_points);

    count = 0;

    doer = do_points - 1;

    /* A* Search: search uphill, get downhill paths */
    while (heap_size > 0) {
	G_percent(count++, do_points, 1);

	heap_p = drop_pt();

	r = heap_p.pnt.r;
	c = heap_p.pnt.c;
	G_debug(3, "heap size %d, r %d, c %d", heap_size, r, c);

	alt_val = heap_p.ele;

	/* 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];
	    slope[ct_dir] = alt_nbr[ct_dir] = 0;
	    /* check if upr, upc are within region */
	    if (upr >= 0 && upr < nrows && upc >= 0 && upc < ncols) {
		bseg_get(&bitflags, &flag_value, upr, upc);
		is_in_list = FLAG_GET(flag_value, INLISTFLAG);
		is_worked = FLAG_GET(flag_value, WORKEDFLAG);
		skip_diag = 0;
		/* avoid diagonal flow direction bias */
		if (!is_worked) {
		    seg_get(&watalt, (char *)&wa, upr, upc);
		    alt_nbr[ct_dir] = wa.ele;
		    slope[ct_dir] =
			get_slope2(alt_val, alt_nbr[ct_dir],
				   dist_to_nbr[ct_dir]);
		}
		if (!is_in_list) {
		    if (ct_dir > 3 && slope[ct_dir] > 0) {
			if (slope[nbr_ew[ct_dir]] > 0) {
			    /* slope to ew nbr > slope to center */
			    if (slope[ct_dir] <
				get_slope2(alt_nbr[nbr_ew[ct_dir]],
					   alt_nbr[ct_dir], ew_res))
				skip_diag = 1;
			}
			if (!skip_diag && slope[nbr_ns[ct_dir]] > 0) {
			    /* slope to ns nbr > slope to center */
			    if (slope[ct_dir] <
				get_slope2(alt_nbr[nbr_ns[ct_dir]],
					   alt_nbr[ct_dir], ns_res))
				skip_diag = 1;
			}
		    }
		}

		/* add neighbour as new point if not in the list */
		if (is_in_list == 0 && skip_diag == 0) {
		    /* set flow direction */
		    asp_val = drain[upr - r + 1][upc - c + 1];
		    add_pt(upr, upc, alt_nbr[ct_dir]);
		    bseg_put(&asp, &asp_val, upr, upc);
		    FLAG_SET(flag_value, INLISTFLAG);
		    bseg_put(&bitflags, &flag_value, upr, upc);

		    if (alt_nbr[ct_dir] < alt_val) {
			if (ct_dir < 4)
			    count_edge_sink++;
			else
			    count_diag_sink++;
		    }
		    /* includes flat areas */
		    else {
			if (ct_dir < 4)
			    count_edge++;
			else
			    count_diag++;
		    }
		}
		else if (is_in_list && is_worked == 0 &&
			 FLAG_GET(flag_value, EDGEFLAG)) {
		    /* neighbour is edge in list, not yet worked */
		    bseg_get(&asp, &asp_val, upr, upc);
		    if (asp_val < 0) {
			/* adjust flow direction for edge cell */
			asp_val = drain[upr - r + 1][upc - c + 1];
			bseg_put(&asp, &asp_val, upr, upc);
			seg_get(&watalt, (char *)&wa, r, c);
			if (wa.wat > 0) {
			    wa.wat = -wa.wat;
			    seg_put(&watalt, (char *)&wa, r, c);
			}
		    }
		    /* neighbour is inside real depression, not yet worked */
		    else if (asp_val == 0) {
			asp_val = drain[upr - r + 1][upc - c + 1];
			bseg_put(&asp, &asp_val, upr, upc);
		    }
		}
	    }
	}
	/* add astar points to sorted list for flow accumulation */
	seg_put(&astar_pts, (char *)&heap_p.pnt, 0, doer);
	doer--;
	bseg_get(&bitflags, &flag_value, r, c);
	FLAG_SET(flag_value, WORKEDFLAG);
	bseg_put(&bitflags, &flag_value, r, c);
    }
    if (doer != -1)
	G_fatal_error(_("bug in A* Search: doer %d heap size %d count %d"),
		      doer, heap_size, count);

    seg_close(&search_heap);

    G_percent(count, do_points, 1);	/* finish it */

    G_debug(1, "edge direction: %d (%.2f%%)", count_edge, (double) 100. * count_edge / (count_edge + count_diag));
    G_debug(1, "diag direction: %d (%.2f%%)", count_diag, (double) 100. * count_diag / (count_edge + count_diag));
    G_debug(1, "edge out of depression: %d (%.2f%%)", count_edge_sink, (double) 100. * count_edge_sink / (count_edge_sink + count_diag_sink));
    G_debug(1, "diag out of depression: %d (%.2f%%)", count_diag_sink, (double) 100. * count_diag_sink / (count_edge_sink + count_diag_sink));

    return 0;
}
Example #17
0
int remove_small_clumps(struct globals *globals)
{
    int row, col, i;
    struct NB_TREE *nbtree;
    int this_id;
    struct ngbr_stats *Rbest;
    int best_n_id, best_n_row, best_n_col;
    int reg_size;
    CELL *renumber, n_regions, min_rid;

    /* two possible modes
     * best (most similar) neighbor
     * neighbor with longest shared boundary 
     */

    if (globals->min_segment_size < 2)
	return 0;

    G_message(_("Merging segments smaller than %d cells..."), globals->min_segment_size);

    /* init renumber */
    renumber = (CELL *) G_malloc(sizeof(CELL) * (globals->max_rid + 1));
    for (i = 0; i <= globals->max_rid; i++)
	renumber[i] = 0;

    /* clear candidate flag */
    flag_clear_all(globals->candidate_flag);

    min_rid = globals->max_rid;

    /* Set candidate flag to true/1 for all non-NULL cells */
    for (row = globals->row_min; row < globals->row_max; row++) {
	for (col = globals->col_min; col < globals->col_max; col++) {
	    if (!(FLAG_GET(globals->null_flag, row, col))) {
		FLAG_SET(globals->candidate_flag, row, col);
		Segment_get(&globals->rid_seg, (void *) &this_id, row, col);
		/* renumber is region size */
		if (renumber[this_id] <= globals->min_segment_size) {
		    renumber[this_id]++;
		    if (min_rid > this_id)
			min_rid = this_id;
		}
	    }
	}
    }
    min_rid--;

    nbtree = nbtree_create(globals->nbands, globals->datasize);

    /* go through all cells */
    G_percent_reset();
    for (row = globals->row_min; row < globals->row_max; row++) {
	G_percent(row - globals->row_min,
		  globals->row_max - globals->row_min, 2);
	for (col = globals->col_min; col < globals->col_max; col++) {
	    if ((FLAG_GET(globals->null_flag, row, col)))
		continue;
	    if (!(FLAG_GET(globals->candidate_flag, row, col)))
		continue;

	    /* get this ID */
	    Segment_get(&globals->rid_seg, (void *) &this_id, row, col);

	    reg_size = renumber[this_id];
	    best_n_id = 1;

	    while (reg_size < globals->min_segment_size && best_n_id > 0) {

		Rbest = NULL;
		reg_size = 1;
		best_n_row = best_n_col = -1;

		best_n_id = find_best_neighbour(globals, row, col, this_id,
		                                nbtree, &reg_size, &Rbest,
						&best_n_row, &best_n_col);

		/* Rbest: pointer to most common neighbour
		 * best_n_id, best_n_[row|col]: most similar neighbour */

		if (reg_size < globals->min_segment_size && best_n_id > 0) {
		    /* update rid */
		    update_rid(globals, row, col, best_n_id);
		    /* mark as merged */
		    renumber[best_n_id] += renumber[this_id];
		    reg_size = renumber[best_n_id];
		    renumber[this_id] = 0;
		    this_id = best_n_id;
		}
	    }
	}
    }
    G_percent(1, 1, 1);

    n_regions = 0;
    /* renumber becomes new region ID */
    for (i = 1; i <= globals->max_rid; i++) {
	if (renumber[i] > 0) {
	    renumber[i] = ++n_regions;
	}
    }

    G_message(_("Renumbering remaining %d segments..."), n_regions);

    for (row = globals->row_min; row < globals->row_max; row++) {
	G_percent(row - globals->row_min,
		  globals->row_max - globals->row_min, 4);
	for (col = globals->col_min; col < globals->col_max; col++) {
	    if ((FLAG_GET(globals->null_flag, row, col)))
		continue;

	    /* get this ID */
	    Segment_get(&globals->rid_seg, (void *) &this_id, row, col);
	    
	    if (Rast_is_c_null_value(&this_id) || this_id < 1)
		continue;

	    this_id = renumber[this_id] + min_rid;
	    Segment_put(&globals->rid_seg, (void *) &this_id, row, col);
	}
    }
    G_percent(1, 1, 1);
    
    globals->max_rid = n_regions + min_rid;
    G_free(renumber);
    nbtree_clear(nbtree);

    return 1;
}
Example #18
0
int init_search(int depr_fd)
{
    int r, c, r_nbr, c_nbr, ct_dir;
    CELL *depr_buf, ele_value;
    int nextdr[8] = { 1, -1, 0, 0, -1, 1, 1, -1 };
    int nextdc[8] = { 0, 0, -1, 1, 1, -1, 1, -1 };
    char asp_value, is_null;
    WAT_ALT wa;
    ASP_FLAG af, af_nbr;
    GW_LARGE_INT n_depr_cells = 0;

    nxt_avail_pt = heap_size = 0;

    /* load edge cells and real depressions to A* heap */
    if (depr_fd >= 0)
	depr_buf = Rast_allocate_buf(CELL_TYPE);
    else
	depr_buf = NULL;

    G_message(_("Initializing A* search..."));
    for (r = 0; r < nrows; r++) {
	G_percent(r, nrows, 2);

	if (depr_fd >= 0) {
	    Rast_get_row(depr_fd, depr_buf, r, CELL_TYPE);
	}

	for (c = 0; c < ncols; c++) {

	    seg_get(&aspflag, (char *)&af, r, c);
	    is_null = FLAG_GET(af.flag, NULLFLAG);

	    if (is_null)
		continue;

	    asp_value = 0;
	    if (r == 0 || r == nrows - 1 || c == 0 || c == ncols - 1) {

		if (r == 0 && c == 0)
		    asp_value = -7;
		else if (r == 0 && c == ncols - 1)
		    asp_value = -5;
		else if (r == nrows - 1 && c == 0)
		    asp_value = -1;
		else if (r == nrows - 1 && c == ncols - 1)
		    asp_value = -3;
		else if (r == 0)
		    asp_value = -2;
		else if (c == 0)
		    asp_value = -4;
		else if (r == nrows - 1)
		    asp_value = -6;
		else if (c == ncols - 1)
		    asp_value = -8;

		seg_get(&watalt, (char *)&wa, r, c);
		ele_value = wa.ele;
		heap_add(r, c, ele_value);
		FLAG_SET(af.flag, INLISTFLAG);
		FLAG_SET(af.flag, EDGEFLAG);
		af.asp = asp_value;
		seg_put(&aspflag, (char *)&af, r, c);
		continue;
	    }

	    /* any neighbour NULL ? */
	    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];

		seg_get(&aspflag, (char *)&af_nbr, r_nbr, c_nbr);
		is_null = FLAG_GET(af_nbr.flag, NULLFLAG);

		if (is_null) {
		    asp_value = -1 * drain[r - r_nbr + 1][c - c_nbr + 1];
		    seg_get(&watalt, (char *)&wa, r, c);
		    ele_value = wa.ele;
		    heap_add(r, c, ele_value);
		    FLAG_SET(af.flag, INLISTFLAG);
		    FLAG_SET(af.flag, EDGEFLAG);
		    af.asp = asp_value;
		    seg_put(&aspflag, (char *)&af, r, c);

		    break;
		}
	    }
	    if (asp_value) /* some neighbour was NULL, point added to list */
		continue;
	    
	    /* real depression ? */
	    if (depr_fd >= 0) {
		if (!Rast_is_c_null_value(&depr_buf[c]) && depr_buf[c] != 0) {
		    seg_get(&watalt, (char *)&wa, r, c);
		    ele_value = wa.ele;
		    heap_add(r, c, ele_value);
		    FLAG_SET(af.flag, INLISTFLAG);
		    FLAG_SET(af.flag, DEPRFLAG);
		    af.asp = asp_value;
		    seg_put(&aspflag, (char *)&af, r, c);
		    n_depr_cells++;
		}
	    }
	}
    }
    G_percent(nrows, nrows, 2);	/* finish it */

    if (depr_fd >= 0) {
	Rast_close(depr_fd);
	G_free(depr_buf);
    }

    G_debug(1, "%lld edge cells", heap_size - n_depr_cells);
    if (n_depr_cells)
	G_debug(1, "%lld cells in depressions", n_depr_cells);

    return 1;
}
Example #19
0
int do_cum_mfd(void)
{
    int r, c, dr, dc;
    DCELL value, valued, *wat_nbr;
    POINT point;
    WAT_ALT wa;
    int killer, threshold;

    /* MFD */
    int mfd_cells, stream_cells, swale_cells, astar_not_set, is_null;
    double *dist_to_nbr, *weight, sum_weight, max_weight;
    int r_nbr, c_nbr, r_max, c_max, ct_dir, np_side, max_side;
    double dx, dy;
    CELL ele, *ele_nbr;
    char asp_val, asp_val_down;
    double prop, max_acc;
    int workedon, edge, is_swale, flat;
    char *flag_nbr, this_flag_value, flag_value;
    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 };

    G_message(_("SECTION 3: Accumulating Surface Flow with MFD."));
    G_debug(1, "MFD convergence factor set to %d.", c_fac);

    /* distances to neighbours */
    dist_to_nbr = (double *)G_malloc(sides * sizeof(double));
    weight = (double *)G_malloc(sides * sizeof(double));

    for (ct_dir = 0; ct_dir < sides; ct_dir++) {
	/* get r, c (r_nbr, c_nbr) for neighbours */
	r_nbr = nextdr[ct_dir];
	c_nbr = nextdc[ct_dir];
	/* account for rare cases when ns_res != ew_res */
	dy = ABS(r_nbr) * window.ns_res;
	dx = ABS(c_nbr) * window.ew_res;
	if (ct_dir < 4)
	    dist_to_nbr[ct_dir] = dx + dy;
	else
	    dist_to_nbr[ct_dir] = sqrt(dx * dx + dy * dy);
    }

    flag_nbr = (char *)G_malloc(sides * sizeof(char));
    wat_nbr = (DCELL *)G_malloc(sides * sizeof(DCELL));
    ele_nbr = (CELL *)G_malloc(sides * sizeof(CELL));

    workedon = 0;

    if (bas_thres <= 0)
	threshold = 60;
    else
	threshold = bas_thres;

    for (killer = 0; killer < do_points; killer++) {
	G_percent(killer, do_points, 1);
	seg_get(&astar_pts, (char *)&point, 0, killer);
	r = point.r;
	c = point.c;
	bseg_get(&asp, &asp_val, r, c);
	if (asp_val) {
	    dr = r + asp_r[ABS(asp_val)];
	    dc = c + asp_c[ABS(asp_val)];
	}
	/* skip user-defined depressions */
	else
	    dr = dc = -1;

	/* WORKEDFLAG has been set during A* Search
	 * reversed meaning here: 0 = done, 1 = not yet done */
	bseg_get(&bitflags, &this_flag_value, r, c);
	FLAG_UNSET(this_flag_value, WORKEDFLAG);
	
	if (dr >= 0 && dr < nrows && dc >= 0 && dc < ncols) {
	    r_max = dr;
	    c_max = dc;

	    seg_get(&watalt, (char *)&wa, r, c);
	    value = wa.wat;

	    /* get weights */
	    max_weight = 0;
	    sum_weight = 0;
	    np_side = -1;
	    mfd_cells = 0;
	    stream_cells = 0;
	    swale_cells = 0;
	    astar_not_set = 1;
	    ele = wa.ele;
	    is_null = 0;
	    edge = 0;
	    flat = 1;
	    /* 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;

		wat_nbr[ct_dir] = 0;
		ele_nbr[ct_dir] = 0;

		/* check if neighbour is within region */
		if (r_nbr >= 0 && r_nbr < nrows && c_nbr >= 0 &&
		    c_nbr < ncols) {

		    if (dr == r_nbr && dc == c_nbr)
			np_side = ct_dir;

		    bseg_get(&bitflags, &flag_nbr[ct_dir], r_nbr, c_nbr);
		    seg_get(&watalt, (char *)&wa, r_nbr, c_nbr);
		    wat_nbr[ct_dir] = wa.wat;
		    ele_nbr[ct_dir] = wa.ele;

		    /* check for swale or stream cells */
		    is_swale = FLAG_GET(flag_nbr[ct_dir], SWALEFLAG);
		    if (is_swale)
			swale_cells++;
		    if ((ABS(wat_nbr[ct_dir]) + 0.5) >= threshold &&
		        ct_dir != np_side && ele_nbr[ct_dir] > ele)
			stream_cells++;

		    if (FLAG_GET(flag_nbr[ct_dir], WORKEDFLAG)) {

			if (ele_nbr[ct_dir] != ele)
			    flat = 0;

			edge = is_null = FLAG_GET(flag_nbr[ct_dir], NULLFLAG);
			if (!is_null && ele_nbr[ct_dir] <= ele) {
			    if (ele_nbr[ct_dir] < ele) {
				weight[ct_dir] =
				    mfd_pow(((ele -
					      ele_nbr[ct_dir]) / dist_to_nbr[ct_dir]),
					    c_fac);
			    }
			    if (ele_nbr[ct_dir] == 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;
			    }
			}
		    }
		}
		else
		    edge = 1;
		if (edge)
		    break;
	    }
	    /* do not continue streams along edges, this causes artifacts */
	    if (edge) {
		is_swale = FLAG_GET(this_flag_value, SWALEFLAG);
		if (is_swale && asp_val > 0) {
		    asp_val = -1 * drain[r - r_nbr + 1][c - c_nbr + 1];
		    bseg_put(&asp, &asp_val, r, c);
		}
		bseg_put(&bitflags, &this_flag_value, r, c);
		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;
		max_side = np_side;
	    }

	    /* set flow accumulation for neighbours */
	    max_acc = -1;
	    max_side = np_side;

	    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 if neighbour is within region */
		    if (r_nbr >= 0 && r_nbr < nrows && c_nbr >= 0 &&
			c_nbr < ncols && weight[ct_dir] > -0.5) {

			if (FLAG_GET(flag_nbr[ct_dir], WORKEDFLAG)) {

			    weight[ct_dir] = weight[ct_dir] / sum_weight;
			    /* check everything adds up to 1.0 */
			    prop += weight[ct_dir];

			    if (value > 0) {
				if (wat_nbr[ct_dir] > 0)
				    wat_nbr[ct_dir] += value * weight[ct_dir];
				else
				    wat_nbr[ct_dir] -= value * weight[ct_dir];
			    }
			    else {
				if (wat_nbr[ct_dir] < 0)
				    wat_nbr[ct_dir] += value * weight[ct_dir];
				else
				    wat_nbr[ct_dir] = value * weight[ct_dir] - wat_nbr[ct_dir];
			    }
			    valued = wat_nbr[ct_dir];
			    wa.wat = valued;
			    wa.ele = ele_nbr[ct_dir];
			    seg_put(&watalt, (char *)&wa, r_nbr, c_nbr);

			    /* get main drainage direction */
			    if (ABS(wat_nbr[ct_dir]) >= max_acc) {
				max_acc = ABS(wat_nbr[ct_dir]);
				r_max = r_nbr;
				c_max = c_nbr;
				max_side = ct_dir;
			    }
			}
			else if (ct_dir == np_side) {
			    /* check for consistency with A * path */
			    workedon++;
			}
		    }
		}

		/* adjust main drainage direction to A* path if possible */
		/*if (fabs(wat_nbr[np_side]) >= max_acc) {
		    max_acc = fabs(wat_nbr[np_side]);
		    r_max = dr;
		    c_max = dc;
		} */

		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_nbr[np_side];
		if (value > 0) {
		    if (valued > 0)
			valued += value;
		    else
			valued -= value;
		}
		else {
		    if (valued < 0)
			valued += value;
		    else
			valued = value - valued;
		}
		wa.wat = valued;
		wa.ele = ele_nbr[np_side];
		seg_put(&watalt, (char *)&wa, dr, dc);
	    }

	    /* update asp */
	    if (dr != r_max || dc != c_max) {
		if (asp_val < 0) {
		    asp_val = -1 * drain[r - r_max + 1][c - c_max + 1];
		}
		else
		    asp_val = drain[r - r_max + 1][c - c_max + 1];
		    
		bseg_put(&asp, &asp_val, r, c);
	    }
	    is_swale = FLAG_GET(this_flag_value, SWALEFLAG);
	    /* start new stream */
	    value = ABS(value) + 0.5;
	    if (!is_swale && (int)value >= threshold && stream_cells < 1 &&
		swale_cells < 1 && !flat) {
		FLAG_SET(this_flag_value, SWALEFLAG);
		is_swale = 1;
	    }
	    /* continue stream */
	    if (is_swale) {
		flag_value = flag_nbr[max_side];
		FLAG_SET(flag_value, SWALEFLAG);
		bseg_put(&bitflags, &flag_value, r_max, c_max);
	    }
	    else {
		if (er_flag && !is_swale && !FLAG_GET(this_flag_value, RUSLEBLOCKFLAG))
		    slope_length(r, c, r_max, c_max);
	    }
	}
	bseg_put(&bitflags, &this_flag_value, r, c);
    }
    G_percent(do_points, do_points, 1);	/* finish it */
    
    if (workedon)
	G_warning(_("MFD: A * path already processed when distributing flow: %d of %d cells"),
		  workedon, do_points);

    seg_close(&astar_pts);
    
    G_free(dist_to_nbr);
    G_free(weight);
    G_free(wat_nbr);
    G_free(ele_nbr);
    G_free(flag_nbr);

    return 0;
}
Example #20
0
void* rsys_render(void* ptr)
{
    /*
        I didn't want to use any locks in here, but
        it's impossible without. So ... one lock is
        needed for the queue, and one for the flags
        of the renderer.
    */

    struct rsys* rsys = ptr;

    /* make ctt1 the context for this thread */
    if(rsys->table.ctt1_make != NULL)
        rsys->table.ctt1_make();

    int running = 1;
    while(running)
	{
		frame_begin(&rsys->frame);

        /* ### FRAME BEGIN ### */

        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_ACCUM_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
        glClearColor(rsys->bg_red, rsys->bg_green, rsys->bg_blue, 1.0f); /* read from rsys instead of this */

        //glUseProgram(rsys->vsh);
        //glUseProgram(rsys->fsh);

        /* pull one request from queue per frame */

        rsys_req_t* req = NULL;

        ocn_spin_lock(&rsys->render_reqs_lock);
        queue_pull(&rsys->render_reqs, (void*)&req);
        ocn_spin_unlock(&rsys->render_reqs_lock);

        /*
            Requests with token equal to 0 are NOT! treated special.
            The request struct uses a flag field now ...
        */

        if(req != NULL)
        {
            if(FLAG_GET(req->flags, RSYS_REQ_RENDERER))
            {
                switch(req->type)
                {
                case RSYS_REQ_TYPE_QUIT:
                    running = 0;
                    break;

                case RSYS_REQ_TYPE_BG:
                    break;

                case RSYS_REQ_TYPE_ADD:
                    /* add to render list */
                    break;

                default:
                    break;
                }
            }
        }

        LIST_FOREACH_BEGIN(&rsys->ros)
        ro_entity_t* ro = LIST_ENTRY_DATA;

        if(req != NULL)
        {
            if(!FLAG_GET(req->flags, RSYS_REQ_RENDERER))
            {
                if(ro->token == req->token)
                {
                    switch(req->type)
                    {
                    case RSYS_REQ_TYPE_DEL:
                        break;
                    case RSYS_REQ_TYPE_MAP:
                        break;
                    case RSYS_REQ_TYPE_UNMAP:
                        break;
                    default:
                        break;
                    }
                }
            }
        }

        /* call render function */
/*
        switch(ro->type)
        {
        case RO_TYPE_STATIC_MESH:
            ro_static_mesh_render(&ro->static_mesh);
            break;

        default:
            break;
        }
*/
        LIST_FOREACH_END

        // bad idea... but for now we leave this like this
        // we could make a second queue for cleaning up requests
        free(req);

		if(rsys->table.win_swap != NULL)
            rsys->table.win_swap();

        /* call frame callback */

        //if(ocn.funcs.frame_callback != NULL)
        //    ocn.funcs.frame_callback(0);

        /* ### FRAME END ### */

        frame_wait(&rsys->frame);
        frame_end (&rsys->frame);
        frame_calc(&rsys->frame);
	}

	return NULL;
}
Example #21
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;
}
Example #22
0
static int check_reg_size(struct globals *globals, int minsize, int row, int col)
{
    int rown, coln, n;
    int neighbors[8][2];
    int this_id;
    int ngbr_id;
    LARGEINT reg_size;
    struct RB_TREE *visited;
    struct rc next, ngbr_rc;
    struct rclist rilist;
    int no_check;
    
    if (!(FLAG_GET(globals->candidate_flag, row, col)))
	return minsize;

    FLAG_UNSET(globals->candidate_flag, row, col);

    visited = rbtree_create(cmp_rc, sizeof(struct rc));
    ngbr_rc.row = row;
    ngbr_rc.col = col;
    rbtree_insert(visited, &ngbr_rc);

    /* get this ID */
    Segment_get(&globals->rid_seg, (void *) &this_id, row, col);

    /* breadth-first search */
    next.row = row;
    next.col = col;
    rclist_init(&rilist);
    reg_size = 1;

    do {
	globals->find_neighbors(next.row, next.col, neighbors);
	n = globals->nn - 1;
	do {
	    rown = neighbors[n][0];
	    coln = neighbors[n][1];
	    no_check = 0;
	    if (rown < globals->row_min || rown >= globals->row_max ||
		coln < globals->col_min || coln >= globals->col_max)
		no_check = 1;
	    if (!no_check && (FLAG_GET(globals->null_flag, rown, coln)))
		no_check = 1;

	    ngbr_rc.row = rown;
	    ngbr_rc.col = coln;

	    if (!no_check && !rbtree_find(visited, &ngbr_rc)) {
		rbtree_insert(visited, &ngbr_rc);

		/* get neighbour ID */
		Segment_get(&globals->rid_seg, (void *) &ngbr_id, rown, coln);
		/* same neighbour */
		if (ngbr_id == this_id) {
		    reg_size++;
		    rclist_add(&rilist, rown, coln);
		    FLAG_UNSET(globals->candidate_flag, rown, coln);
		}
	    }
	} while (n--);    /* end do loop - next neighbor */
    } while (rclist_drop(&rilist, &next));   /* while there are cells to check */

    rclist_destroy(&rilist);
    rbtree_destroy(visited);

    return reg_size;
}
Example #23
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;
}
Example #24
0
int do_cum(void)
{
    int r, c, dr, dc;
    char asp_val, asp_val_down;
    char is_swale, this_flag_value, flag_value;
    DCELL value, valued;
    POINT point;
    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 };
    WAT_ALT wa, wadown;

    G_message(_("SECTION 3: Accumulating Surface Flow with SFD."));

    if (bas_thres <= 0)
	threshold = 60;
    else
	threshold = bas_thres;
    for (killer = 0; killer < do_points; killer++) {
	G_percent(killer, do_points, 1);
	seg_get(&astar_pts, (char *)&point, 0, killer);
	r = point.r;
	c = point.c;
	bseg_get(&asp, &asp_val, r, c);
	if (asp_val) {
	    dr = r + asp_r[ABS(asp_val)];
	    dc = c + asp_c[ABS(asp_val)];
	}
	/* skip user-defined depressions */
	else
	    dr = dc = -1;

	bseg_get(&bitflags, &this_flag_value, r, c);
	FLAG_UNSET(this_flag_value, WORKEDFLAG);

	if (dr >= 0 && dr < nrows && dc >= 0 && dc < ncols) {
	    /* TODO: do not distribute flow along edges, this causes artifacts */
	    seg_get(&watalt, (char *)&wa, r, c);
	    value = wa.wat;
	    is_swale = FLAG_GET(this_flag_value, SWALEFLAG);
	    if (fabs(value) >= threshold && !is_swale) {
		is_swale = 1;
		FLAG_SET(this_flag_value, SWALEFLAG);
	    }
	    seg_get(&watalt, (char *)&wadown, dr, dc);
	    valued = wadown.wat;
	    if (value > 0) {
		if (valued > 0)
		    valued += value;
		else
		    valued -= value;
	    }
	    else {
		if (valued < 0)
		    valued += value;
		else
		    valued = value - valued;
	    }
	    wadown.wat = valued;
	    seg_put(&watalt, (char *)&wadown, dr, dc);
	    /* update asp for depression */
	    if (is_swale || fabs(valued) >= threshold) {
		bseg_get(&bitflags, &flag_value, dr, dc);
		FLAG_SET(flag_value, SWALEFLAG);
		bseg_put(&bitflags, &flag_value, dr, dc);
		is_swale = 1;
	    }
	    else {
		if (er_flag && !is_swale && !FLAG_GET(this_flag_value, RUSLEBLOCKFLAG))
		    slope_length(r, c, dr, dc);
	    }
	}
	bseg_put(&bitflags, &this_flag_value, r, c);
    }
    G_percent(do_points, do_points, 1);	/* finish it */

    seg_close(&astar_pts);

    return 0;
}
Example #25
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;
}
Example #26
0
int do_astar(void)
{
    int r, c, r_nbr, c_nbr, ct_dir;
    GW_LARGE_INT first_cum, count;
    int nextdr[8] = { 1, -1, 0, 0, -1, 1, 1, -1 };
    int nextdc[8] = { 0, 0, -1, 1, 1, -1, 1, -1 };
    CELL ele_val, ele_up, ele_nbr[8];
    WAT_ALT wa;
    ASP_FLAG af;
    char is_in_list, is_worked;
    HEAP_PNT heap_p;
    /* sides
     * |7|1|4|
     * |2| |3|
     * |5|0|6|
     */
    int nbr_ew[8] = { 0, 1, 2, 3, 1, 0, 0, 1 };
    int nbr_ns[8] = { 0, 1, 2, 3, 3, 2, 3, 2 };
    double dx, dy, dist_to_nbr[8], ew_res, ns_res;
    double slope[8];
    struct Cell_head window;
    int skip_diag;

    count = 0;

    first_cum = n_points;

    G_message(_("A* Search..."));

    Rast_get_window(&window);

    for (ct_dir = 0; ct_dir < sides; ct_dir++) {
	/* get r, c (r_nbr, c_nbr) for neighbours */
	r_nbr = nextdr[ct_dir];
	c_nbr = nextdc[ct_dir];
	/* account for rare cases when ns_res != ew_res */
	dy = abs(r_nbr) * window.ns_res;
	dx = abs(c_nbr) * window.ew_res;
	if (ct_dir < 4)
	    dist_to_nbr[ct_dir] = dx + dy;
	else
	    dist_to_nbr[ct_dir] = sqrt(dx * dx + dy * dy);
    }
    ew_res = window.ew_res;
    ns_res = window.ns_res;
    
    while (heap_size > 0) {
	G_percent(count++, n_points, 1);
	if (count > n_points)
	    G_fatal_error(_("%lld surplus points"),
	                  heap_size);

	if (heap_size > n_points)
	    G_fatal_error
		(_("Too many points in heap %lld, should be %lld"),
		 heap_size, n_points);

	heap_p = heap_drop();

	r = heap_p.pnt.r;
	c = heap_p.pnt.c;

	ele_val = heap_p.ele;

	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];
	    slope[ct_dir] = ele_nbr[ct_dir] = 0;
	    skip_diag = 0;

	    /* check that neighbour is within region */
	    if (r_nbr < 0 || r_nbr >= nrows || c_nbr < 0 || c_nbr >= ncols)
		continue;

	    seg_get(&aspflag, (char *)&af, r_nbr, c_nbr);
	    is_in_list = FLAG_GET(af.flag, INLISTFLAG);
	    is_worked = FLAG_GET(af.flag, WORKEDFLAG);
	    if (!is_worked) {
		seg_get(&watalt, (char *)&wa, r_nbr, c_nbr);
		ele_nbr[ct_dir] = wa.ele;
		slope[ct_dir] = get_slope(ele_val, ele_nbr[ct_dir],
			                  dist_to_nbr[ct_dir]);
	    }
	    /* avoid diagonal flow direction bias */
	    if (!is_in_list) {
		if (ct_dir > 3 && slope[ct_dir] > 0) {
		    if (slope[nbr_ew[ct_dir]] > 0) {
			/* slope to ew nbr > slope to center */
			if (slope[ct_dir] <
			    get_slope(ele_nbr[nbr_ew[ct_dir]],
				       ele_nbr[ct_dir], ew_res))
			    skip_diag = 1;
		    }
		    if (!skip_diag && slope[nbr_ns[ct_dir]] > 0) {
			/* slope to ns nbr > slope to center */
			if (slope[ct_dir] <
			    get_slope(ele_nbr[nbr_ns[ct_dir]],
				       ele_nbr[ct_dir], ns_res))
			    skip_diag = 1;
		    }
		}
	    }

	    if (!skip_diag) {
		if (is_in_list == 0) {
		    ele_up = ele_nbr[ct_dir];
		    af.asp = drain[r_nbr - r + 1][c_nbr - c + 1];
		    heap_add(r_nbr, c_nbr, ele_up);
		    FLAG_SET(af.flag, INLISTFLAG);
		    seg_put(&aspflag, (char *)&af, r_nbr, c_nbr);
		}
		else if (is_in_list && is_worked == 0) {
		    if (FLAG_GET(af.flag, EDGEFLAG)) {
			/* neighbour is edge in list, not yet worked */
			if (af.asp < 0) {
			    /* adjust flow direction for edge cell */
			    af.asp = drain[r_nbr - r + 1][c_nbr - c + 1];
			    seg_put(&aspflag, (char *)&af, r_nbr, c_nbr);
			}
		    }
		    else if (FLAG_GET(af.flag, DEPRFLAG)) {
			G_debug(3, "real depression");
			/* neighbour is inside real depression, not yet worked */
			if (af.asp == 0 && ele_val <= ele_nbr[ct_dir]) {
			    af.asp = drain[r_nbr - r + 1][c_nbr - c + 1];
			    FLAG_UNSET(af.flag, DEPRFLAG);
			    seg_put(&aspflag, (char *)&af, r_nbr, c_nbr);
			}
		    }
		}
	    }
	}    /* end neighbours */
	/* add astar points to sorted list for flow accumulation and stream extraction */
	first_cum--;
	seg_put(&astar_pts, (char *)&heap_p.pnt, 0, first_cum);
	seg_get(&aspflag, (char *)&af, r, c);
	FLAG_SET(af.flag, WORKEDFLAG);
	seg_put(&aspflag, (char *)&af, r, c);
    }    /* end A* search */

    G_percent(n_points, n_points, 1);	/* finish it */

    return 1;
}
Example #27
0
int main(int argc, char *argv[])
{
    int r, c;
    DCELL con1, con2;
    double d1, d2;
    DCELL *alt_row;
    const char *con_name, *alt_name;
    int file_fd;
    DCELL value;
    struct History history;
    struct GModule *module;
    struct Option *opt1, *opt2;

    G_gisinit(argv[0]);

    module = G_define_module();
    G_add_keyword(_("raster"));
    G_add_keyword(_("surface"));
    G_add_keyword(_("interpolation"));
    module->description =
	_("Generates surface raster map from rasterized contours.");

    opt1 = G_define_standard_option(G_OPT_R_INPUT);
    opt1->description = _("Name of input raster map containing contours");

    opt2 = G_define_standard_option(G_OPT_R_OUTPUT);

    if (G_parser(argc, argv))
	exit(EXIT_FAILURE);
    
    con_name = opt1->answer;
    alt_name = opt2->answer;

    nrows = Rast_window_rows();
    ncols = Rast_window_cols();
    i_val_l_f = nrows + ncols;
    con = read_cell(con_name);
    alt_row = (DCELL *) G_malloc(ncols * sizeof(DCELL));
    seen = flag_create(nrows, ncols);
    mask = flag_create(nrows, ncols);
    if (NULL != G_find_file("cell", "MASK", G_mapset())) {
	file_fd = Rast_open_old("MASK", G_mapset());
	for (r = 0; r < nrows; r++) {
	    Rast_get_d_row_nomask(file_fd, alt_row, r);
	    for (c = 0; c < ncols; c++)
		if (Rast_is_d_null_value(&(alt_row[c])) || alt_row[c] == 0)
		    FLAG_SET(mask, r, c);
	}
	Rast_close(file_fd);
    }
    zero = (NODE *) G_malloc(INIT_AR * sizeof(NODE));
    minc = minr = 0;
    maxc = ncols - 1;
    maxr = nrows - 1;
    array_size = INIT_AR;
    file_fd = Rast_open_new(alt_name, DCELL_TYPE);
    for (r = 0; r < nrows; r++) {
	G_percent(r, nrows, 1);
	Rast_set_d_null_value(alt_row, ncols);
	for (c = 0; c < ncols; c++) {
	    if (FLAG_GET(mask, r, c))
		continue;
	    value = con[r][c];
	    if (!Rast_is_d_null_value(&value)) {
		alt_row[c] = value;
		continue;
	    }
	    find_con(r, c, &d1, &d2, &con1, &con2);
	    if (!Rast_is_d_null_value(&con2))
		alt_row[c] = d2 * con1 / (d1 + d2) + 
		             d1 * con2 / (d1 + d2);
	    else
		alt_row[c] = con1;
	}
	Rast_put_row(file_fd, alt_row, DCELL_TYPE);
    }
    G_percent(1, 1, 1);
    
    free_cell(con);
    flag_destroy(seen);
    flag_destroy(mask);
    Rast_close(file_fd);
    
    Rast_short_history(alt_name, "raster", &history);
    Rast_command_history(&history);
    Rast_write_history(alt_name, &history);

    exit(EXIT_SUCCESS);
}
Example #28
0
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;
}
Example #29
0
int mean_shift(struct globals *globals)
{
    int row, col, t;
    int n_changes;
    double alpha2;
    struct ngbr_stats Rin, Rout;
    double diff2;

    G_fatal_error(_("Mean shift is not yet implemented"));
    return FALSE;


    Rin.mean = G_malloc(globals->datasize);
    Rout.mean = G_malloc(globals->datasize);

    /* TODO: need another segment structure holding output
     * for mean shift, output of the previous iteration becomes input of the next iteration
     * initially, input and output are original band values */

    alpha2 = globals->alpha * globals->alpha;
    
    t = 0;
    n_changes = 1;
    while (t < globals->end_t && n_changes > 0) {

	G_message(_("Processing pass %d..."), ++t);

	n_changes = 0;
	globals->candidate_count = 0;
	flag_clear_all(globals->candidate_flag);

	/* Set candidate flag to true/1 for all non-NULL cells */
	for (row = globals->row_min; row < globals->row_max; row++) {
	    for (col = globals->col_min; col < globals->col_max; col++) {
		if (!(FLAG_GET(globals->null_flag, row, col))) {
		    
		    FLAG_SET(globals->candidate_flag, row, col);
		    globals->candidate_count++;
		}
	    }
	}

	G_debug(4, "Starting to process %ld candidate cells",
		globals->candidate_count);

	/*process candidate cells */
	G_percent_reset();
	for (row = globals->row_min; row < globals->row_max; row++) {
	    G_percent(row - globals->row_min,
	              globals->row_max - globals->row_min, 4);
	    for (col = globals->col_min; col < globals->col_max; col++) {
		if (!(FLAG_GET(globals->candidate_flag, row, col)))
		    continue;

		/* get current band values */
		Segment_get(&globals->bands_seg, (void *)Rin.mean,
			    row, col);

		/* adapt initial spatial and range bandwiths */

		/* calculate new band values */
		
		/* if the squared difference between old and new band values 
		 * is larger than alpha2, then increase n_changes */
		
		diff2 = (globals->calculate_similarity)(&Rin, &Rout, globals);
		if (diff2 > alpha2)
		    n_changes++;
	    }
	}
    }
    if (n_changes > 1)
	G_message(_("Mean shift stopped at %d due to reaching max iteration limit, more changes may be possible"), t);
    else
	G_message(_("Mean shift converged after %d iterations"), t);
    
    /* identify connected components */
    
    return TRUE;
}