Example #1
0
int seg_calculate_drop(SEGMENT *output, int number_of_streams,
		       int downstream)
{
    int r, c;
    int i, j;
    double init;
    double output_cell;
    STREAM *SA;

    SA = stream_attributes;

    for (i = 1; i < number_of_streams; ++i) {
	if (!downstream) {
	    init = SA[i].elevation[1];
	    for (j = 1; j < SA[i].number_of_cells - 1; ++j) {
		r = (int)SA[i].points[j] / ncols;
		c = (int)SA[i].points[j] % ncols;
		output_cell = init - SA[i].elevation[j];
		Segment_put(output, &output_cell, r, c);
	    }
	}
	else {
	    init = SA[i].elevation[SA[i].number_of_cells - 2];
	    for (j = SA[i].number_of_cells - 2; j > 0; --j) {
		r = (int)SA[i].points[j] / ncols;
		c = (int)SA[i].points[j] % ncols;
		output_cell = SA[i].elevation[j] - init;
		Segment_put(output, &output_cell, r, c);
	    }
	}
    }

    return 0;
}
Example #2
0
int seg_calculate_distance(SEGMENT *output, int number_of_streams,
			   int downstream)
{
    int r, c;
    double cum_length;
    int i, j;
    STREAM *SA;

    SA = stream_attributes;

    for (i = 1; i < number_of_streams; ++i) {
	cum_length = 0;
	if (!downstream)
	    for (j = 1; j < SA[i].number_of_cells - 1; ++j) {
		cum_length += SA[i].distance[j];
		r = (int)SA[i].points[j] / ncols;
		c = (int)SA[i].points[j] % ncols;
		Segment_put(output, &cum_length, r, c);
	    }
	else
	    for (j = SA[i].number_of_cells - 2; j > 0; --j) {
		cum_length += SA[i].distance[j];
		r = (int)SA[i].points[j] / ncols;
		c = (int)SA[i].points[j] % ncols;
		Segment_put(output, &cum_length, r, c);
	    }
    }

    return 0;
}
Example #3
0
int seg_fill_basins(OUTLET outlet, SEGMENT * distance, SEGMENT * dirs)
{
    /* fill empty spaces with zeros but leave -1 as a markers of NULL */
    int r, c, i, j;
    int next_r, next_c;
    double stop, val;
    POINT n_cell;
    CELL dirs_cell;
    DCELL distance_cell;

    tail = 0;
    head = -1;
    r = outlet.r;
    c = outlet.c;
    val = 1;
    stop = 0;

    Segment_put(distance, &stop, r, c);

    while (tail != head) {

	for (i = 1; i < 9; ++i) {
	    if (NOT_IN_REGION(i))
		continue;	/* out of border */

	    j = DIAG(i);
	    next_r = NR(i);
	    next_c = NC(i);

	    Segment_get(dirs, &dirs_cell, next_r, next_c);

	    if (dirs_cell == j) {	/* countributing cell */

		Segment_get(distance, &distance_cell, next_r, next_c);
		distance_cell = (distance_cell == stop) ? stop : val;
		Segment_put(distance, &distance_cell, next_r, next_c);
		n_cell.r = next_r;
		n_cell.c = next_c;
		fifo_insert(n_cell);

	    }
	}			/* end for i... */

	n_cell = fifo_return_del();
	r = n_cell.r;
	c = n_cell.c;
    }

    return 0;
}
Example #4
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 #5
0
int seg_calculate_curvature(SEGMENT *output, int number_of_streams,
			    int downstream)
{
    int r, c;
    int i, j;
    double output_cell;
    STREAM *SA;
    double first_derivative, second_derivative;

    G_debug(3, "seg_calculate_curvature(): downstream=%d", downstream);
    SA = stream_attributes;

    for (i = 1; i < number_of_streams; ++i) {
	for (j = 1; j < SA[i].number_of_cells - 1; ++j) {
	    r = (int)SA[i].points[j] / ncols;
	    c = (int)SA[i].points[j] % ncols;
	    first_derivative =
		(SA[i].elevation[j - 1] -
		 SA[i].elevation[j + 1]) / (SA[i].distance[j - 1] +
					    SA[i].distance[j]);
	    second_derivative =
		((SA[i].elevation[j - 1] - SA[i].elevation[j]) -
		 (SA[i].elevation[j] -
		  SA[i].elevation[j + 1])) / (SA[i].distance[j - 1] +
					      SA[i].distance[j]);
	    output_cell =
		first_derivative /
		pow((1 + second_derivative * second_derivative), 1.5);
	    Segment_put(output, &output_cell, r, c);
	}
    }

    return 0;
}
Example #6
0
int seg_calculate_local_gradient(SEGMENT *output, int number_of_streams,
				 int downstream)
{
    int r, c;
    int i, j;
    double elev_diff;
    double output_cell;
    STREAM *SA;

    G_debug(3, "seg_calculate_local_gradient(): downstream=%d", downstream);
    SA = stream_attributes;

    for (i = 1; i < number_of_streams; ++i) {
	for (j = 1; j < SA[i].number_of_cells - 1; ++j) {
	    r = (int)SA[i].points[j] / ncols;
	    c = (int)SA[i].points[j] % ncols;
	    elev_diff =
		(SA[i].elevation[j] - SA[i].elevation[j + 1]) <
		0 ? 0 : (SA[i].elevation[j] - SA[i].elevation[j + 1]);
	    output_cell = elev_diff / SA[i].distance[j];
	    Segment_put(output, &output_cell, r, c);
	}
    }

    return 0;
}
Example #7
0
int dseg_put(DSEG * dseg, double *value, GW_LARGE_INT row, GW_LARGE_INT col)
{
    if (Segment_put(&(dseg->seg), (DCELL *) value, row, col) < 0) {
	G_warning("dseg_put(): could not write segment file");
	return -1;
    }
    return 0;
}
Example #8
0
int seg_calculate_gradient(SEGMENT *output, int number_of_streams,
			   int downstream)
{
    int r, c;
    int i, j;
    double init;
    double output_cell;
    double cum_length;
    STREAM *SA;

    SA = stream_attributes;

    for (i = 1; i < number_of_streams; ++i) {
	cum_length = 0;
	if (!downstream) {
	    init = SA[i].elevation[1];
	    for (j = 1; j < SA[i].number_of_cells - 1; ++j) {
		cum_length += SA[i].distance[j];
		r = (int)SA[i].points[j] / ncols;
		c = (int)SA[i].points[j] % ncols;
		output_cell = (init - SA[i].elevation[j]) / cum_length;
		Segment_put(output, &output_cell, r, c);

	    }
	}
	else {
	    init = SA[i].elevation[SA[i].number_of_cells - 2];
	    for (j = SA[i].number_of_cells - 2; j > 0; --j) {
		cum_length += SA[i].distance[j];
		r = (int)SA[i].points[j] / ncols;
		c = (int)SA[i].points[j] % ncols;
		output_cell = (SA[i].elevation[j] - init) / cum_length;
		Segment_put(output, &output_cell, r, c);
	    }
	}
    }

    return 0;
}
Example #9
0
int seg_set_null_output(SEGMENT *output)
{
    int r, c;
    double output_cell;

    for (r = 0; r < nrows; ++r) {
	for (c = 0; c < ncols; ++c) {
	    Rast_set_d_null_value(&output_cell, 1);
	    Segment_put(output, &output_cell, r, c);
	}
    }

    return 0;
}
Example #10
0
int seg_fill_streams(SEGMENT *unique_streams, int number_of_streams)
{
    int r, c;
    int i, j;
    STREAM *SA;

    SA = stream_attributes;

    for (i = 1; i < number_of_streams; ++i) {
	for (j = 1; j < SA[i].number_of_cells - 1; ++j) {
	    r = (int)SA[i].points[j] / ncols;
	    c = (int)SA[i].points[j] % ncols;
	    Segment_put(unique_streams, &SA[i].stream, r, c);
	}
    }
    return 0;
}
Example #11
0
int seg_calculate_identifiers(SEGMENT *identifier, int number_of_streams,
			      int downstream)
{
    int r, c;
    int i, j;
    STREAM *SA;

    G_debug(3, "seg_calculate_identifiers(): downstream=%d", downstream);
    SA = stream_attributes;

    for (i = 1; i < number_of_streams; ++i) {
	for (j = 1; j < SA[i].number_of_cells - 1; ++j) {
	    r = (int)SA[i].points[j] / ncols;
	    c = (int)SA[i].points[j] % ncols;
	    Segment_put(identifier, &(SA[i].stream_num), r, c);
	}
    }

    return 0;
}
Example #12
0
int seg_calculate_cell(SEGMENT *output, int number_of_streams,
		       int downstream)
{
    int r, c;
    int i, j, k;
    double output_cell;
    STREAM *SA;

    SA = stream_attributes;

    for (i = 1; i < number_of_streams; ++i) {

	k = SA[i].number_of_cells - 2;
	for (j = 1; j < SA[i].number_of_cells - 1; ++j, --k) {
	    r = (int)SA[i].points[j] / ncols;
	    c = (int)SA[i].points[j] % ncols;
	    output_cell = downstream ? k : j;
	    Segment_put(output, &output_cell, r, c);
	}
    }

    return 0;
}
Example #13
0
int seg_calculate_difference(SEGMENT *output, int number_of_streams,
			     int downstream)
{
    int r, c;
    int i, j;
    double output_cell;
    STREAM *SA;

    SA = stream_attributes;

    for (i = 1; i < number_of_streams; ++i) {

	for (j = 1; j < SA[i].number_of_cells - 1; ++j) {
	    output_cell = downstream ?
		SA[i].elevation[j - 1] - SA[i].elevation[j] :
		SA[i].elevation[j] - SA[i].elevation[j + 1];
	    r = (int)SA[i].points[j] / ncols;
	    c = (int)SA[i].points[j] % ncols;
	    Segment_put(output, &output_cell, r, c);
	}
    }

    return 0;
}
Example #14
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 #15
0
int seg_calculate_upstream(SEGMENT * distance, SEGMENT * dirs,
			   SEGMENT * elevation, SEGMENT * tmp_elevation,
			   int near)
{
    int r, c;
    int next_r, next_c;
    double easting, northing;
    double cell_easting, cell_northing;
    int i, j, k, d, d_next;
    DCELL minus_one_cell = -1;
    DCELL zero_cell = 0;
    int done;
    int counter;
    int n_inits = 0;
    double cur_dist;
    POINT *d_inits;
    double tmp_dist = 0;
    double target_elev = 0;
    CELL dirs_cell;
    DCELL distance_cell, elevation_cell, tmp_elevation_cell;
    /* size_t elevation_data_size; */
    struct Cell_head window;

    Rast_get_window(&window);

    if (elevation) {
        /* elevation_data_size = Rast_cell_size(DCELL_TYPE); */
	for (r = 0; r < nrows; ++r)
	    for (c = 0; c < ncols; ++c) {
		Segment_get(elevation, &elevation_cell, r, c);
		Segment_put(tmp_elevation, &elevation_cell, r, c);
	    }
    }

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

	    Segment_get(distance, &distance_cell, r, c);

	    for (i = 1; i < 9; ++i) {
		if (NOT_IN_REGION(i))
		    continue;	/* out of border */

		j = DIAG(i);
		next_r = NR(i);
		next_c = NC(i);

		Segment_get(dirs, &dirs_cell, next_r, next_c);

		if (dirs_cell == j && distance_cell != 0) {	/* is contributing cell */
		    Segment_put(distance, &minus_one_cell, r, c);
		    break;
		}
	    }			/* end for i */

	    Segment_get(distance, &distance_cell, r, c);
	    Segment_get(dirs, &dirs_cell, r, c);
	    if (distance_cell == 1) {
		if (distance_cell == 1 && dirs_cell > 0)
		    n_inits++;
		else if (dirs_cell > 0)
		    Segment_put(distance, &minus_one_cell, r, c);
	    }

	}

    d_inits = (POINT *) G_malloc(n_inits * sizeof(POINT));

    k = 0;
    for (r = 0; r < nrows; ++r)
	for (c = 0; c < ncols; ++c) {

	    Segment_get(distance, &distance_cell, r, c);
	    if (distance_cell == 1) {

		Segment_put(distance, &zero_cell, r, c);
		if (elevation)
		    Segment_put(elevation, &zero_cell, r, c);

		Segment_get(dirs, &d, r, c);
		Segment_get(dirs, &d_next, NR(d), NR(d));

		if (d_next < 0)
		    continue;

		d_inits[k].r = r;
		d_inits[k].c = c;
		d_inits[k].cur_dist = 0;

		if (elevation)
		    Segment_get(tmp_elevation, &(d_inits[k].target_elev), r,
				c);
		k++;
	    }
	}

    counter = n_inits = k;

    G_message(_("Calculate upstream parameters..."));
    while (n_inits > 0) {
	k = 0;
	G_percent((counter - n_inits), counter, 10);

	for (i = 0; i < n_inits; ++i) {
	    r = d_inits[i].r;
	    c = d_inits[i].c;

	    Segment_get(dirs, &d, r, c);
	    next_r = NR(d);
	    next_c = NC(d);
	    tmp_dist = d_inits[i].cur_dist;

	    if (elevation)
		target_elev = d_inits[i].target_elev;

	    easting = window.west + (c + 0.5) * window.ew_res;
	    northing = window.north - (r + 0.5) * window.ns_res;
	    cell_easting = window.west + (next_c + 0.5) * window.ew_res;
	    cell_northing = window.north - (next_r + 0.5) * window.ns_res;

	    cur_dist = tmp_dist +
		G_distance(easting, northing, cell_easting, cell_northing);

	    Segment_get(distance, &distance_cell, next_r, next_c);

	    if (near)
		done = (distance_cell > cur_dist ||
			distance_cell <= 0) ? 1 : 0;
	    else
		done = (distance_cell < cur_dist ||
			distance_cell <= 0) ? 1 : 0;

	    if (done) {
		Segment_put(distance, &cur_dist, next_r, next_c);
		if (elevation) {
		    Segment_get(tmp_elevation, &tmp_elevation_cell, next_r,
				next_c);
		    tmp_elevation_cell = target_elev - tmp_elevation_cell;
		    Segment_put(elevation, &tmp_elevation_cell, next_r,
				next_c);
		}

		Segment_get(dirs, &dirs_cell, NR(d), NC(d));
		if (dirs_cell < 1)
		    continue;

		d_inits[k].r = next_r;
		d_inits[k].c = next_c;
		d_inits[k].cur_dist = cur_dist;

		if (elevation)
		    d_inits[k].target_elev = target_elev;
		k++;
	    }			/* end of if done */
	}
	n_inits = k;
    }
    G_percent(1, 1, 1);
    return 0;
}
Example #16
0
int seg_calculate_downstream(SEGMENT *dirs, SEGMENT * distance,
			     SEGMENT *elevation, OUTLET outlet, int outs)
{

    int r, c, i, j;
    int next_r, next_c;
    POINT n_cell;
    double cur_dist = 0;
    double tmp_dist = 0;
    double target_elev;		/* eleavation at stream or outlet */
    double easting, northing;
    double cell_easting, cell_northing;
    CELL dirs_cell;
    DCELL distance_cell, elevation_cell;
    DCELL zero_cell = 0;
    struct Cell_head window;

    Rast_get_window(&window);

    tail = 0;
    head = -1;
    r = outlet.r;
    c = outlet.c;

    if (elevation) {
	Segment_get(elevation, &target_elev, r, c);
	Segment_put(elevation, &zero_cell, r, c);
    }

    while (tail != head) {
	easting = window.west + (c + .5) * window.ew_res;
	northing = window.north - (r + .5) * window.ns_res;

	for (i = 1; i < 9; ++i) {

	    if (NOT_IN_REGION(i))
		continue;	/* border */

	    j = DIAG(i);
	    next_r = NR(i);
	    next_c = NC(i);

	    Segment_get(dirs, &dirs_cell, next_r, next_c);
	    if (dirs_cell == j) {	/* countributing cell, reset distance and elevation */

		if (outs) {	/* outlet mode */
		    Segment_get(distance, &distance_cell, next_r, next_c);
		    if (distance_cell == 0)
			continue;	/* continue loop, point is not added to the queue! */
		    else {
			cell_northing =
			    window.north - (next_r + .5) * window.ns_res;
			cell_easting =
			    window.west + (next_c + .5) * window.ew_res;
			cur_dist =
			    tmp_dist + G_distance(easting, northing,
						  cell_easting,
						  cell_northing);
			Segment_put(distance, &cur_dist, next_r, next_c);

		    }

		}
		else {		/* stream mode */
		    Segment_get(distance, &distance_cell, next_r, next_c);
		    if (distance_cell == 0) {
			cur_dist = 0;
			if (elevation)
			    Segment_get(elevation, &target_elev, next_r,
					next_c);
		    }
		    else {
			cell_northing =
			    window.north - (next_r + .5) * window.ns_res;
			cell_easting =
			    window.west + (next_c + .5) * window.ew_res;
			cur_dist =
			    tmp_dist + G_distance(easting, northing,
						  cell_easting,
						  cell_northing);
			Segment_put(distance, &cur_dist, next_r, next_c);
		    }
		}		/* end stream mode */

		if (elevation) {
		    Segment_get(elevation, &elevation_cell, next_r, next_c);
		    elevation_cell -= target_elev;
		    Segment_put(elevation, &elevation_cell, next_r, next_c);
		    n_cell.target_elev = target_elev;
		}

		n_cell.r = next_r;
		n_cell.c = next_c;
		n_cell.cur_dist = cur_dist;
		fifo_insert(n_cell);
	    }
	}			/* end for i... */

	n_cell = fifo_return_del();
	r = n_cell.r;
	c = n_cell.c;
	tmp_dist = n_cell.cur_dist;
	target_elev = n_cell.target_elev;

    }				/* end while */
    return 0;
}
Example #17
0
/*--------------------------------------------------------------------*/
int main(int argc, char *argv[])
{
    /* Variable declarations */
    int nsply, nsplx, nrows, ncols, nsplx_adj, nsply_adj;
    int nsubregion_col, nsubregion_row, subregion_row, subregion_col;
    int subregion = 0, nsubregions = 0;
    int last_row, last_column, grid, bilin, ext, flag_auxiliar, cross;	/* booleans */
    double stepN, stepE, lambda, mean;
    double N_extension, E_extension, edgeE, edgeN;

    const char *mapset, *drv, *db, *vector, *map;
    char table_name[GNAME_MAX], title[64];
    char xname[GNAME_MAX], xmapset[GMAPSET_MAX];

    int dim_vect, nparameters, BW;
    int *lineVect;		/* Vector restoring primitive's ID */
    double *TN, *Q, *parVect;	/* Interpolating and least-square vectors */
    double **N, **obsVect;	/* Interpolation and least-square matrix */

    SEGMENT out_seg, mask_seg;
    const char *out_file, *mask_file;
    int out_fd, mask_fd;
    double seg_size;
    int seg_mb, segments_in_memory;
    int have_mask;

    /* Structs declarations */
    int raster;
    struct Map_info In, In_ext, Out;
    struct History history;

    struct GModule *module;
    struct Option *in_opt, *in_ext_opt, *out_opt, *out_map_opt, *stepE_opt,
               *stepN_opt, *lambda_f_opt, *type_opt, *dfield_opt, *col_opt, *mask_opt,
               *memory_opt, *solver, *error, *iter;
    struct Flag *cross_corr_flag, *spline_step_flag;

    struct Reg_dimens dims;
    struct Cell_head elaboration_reg, original_reg;
    struct bound_box general_box, overlap_box, original_box;

    struct Point *observ;
    struct line_cats *Cats;
    dbCatValArray cvarr;

    int with_z;
    int nrec, ctype = 0;
    struct field_info *Fi;
    dbDriver *driver, *driver_cats;

    /*----------------------------------------------------------------*/
    /* Options declarations */
    module = G_define_module();
    G_add_keyword(_("vector"));
    G_add_keyword(_("surface"));
    G_add_keyword(_("interpolation"));
    G_add_keyword(_("LIDAR"));
    module->description =
        _("Performs bicubic or bilinear spline interpolation with Tykhonov regularization.");

    cross_corr_flag = G_define_flag();
    cross_corr_flag->key = 'c';
    cross_corr_flag->description =
        _("Find the best Tykhonov regularizing parameter using a \"leave-one-out\" cross validation method");

    spline_step_flag = G_define_flag();
    spline_step_flag->key = 'e';
    spline_step_flag->label = _("Estimate point density and distance");
    spline_step_flag->description =
        _("Estimate point density and distance for the input vector points within the current region extends and quit");

    in_opt = G_define_standard_option(G_OPT_V_INPUT);
    in_opt->label = _("Name of input vector point map");

    dfield_opt = G_define_standard_option(G_OPT_V_FIELD);
    dfield_opt->guisection = _("Settings");

    col_opt = G_define_standard_option(G_OPT_DB_COLUMN);
    col_opt->required = NO;
    col_opt->label =
        _("Name of the attribute column with values to be used for approximation");
    col_opt->description = _("If not given and input is 3D vector map then z-coordinates are used.");
    col_opt->guisection = _("Settings");

    in_ext_opt = G_define_standard_option(G_OPT_V_INPUT);
    in_ext_opt->key = "sparse_input";
    in_ext_opt->required = NO;
    in_ext_opt->label =
        _("Name of input vector map with sparse points");

    out_opt = G_define_standard_option(G_OPT_V_OUTPUT);
    out_opt->required = NO;
    out_opt->guisection = _("Outputs");

    out_map_opt = G_define_standard_option(G_OPT_R_OUTPUT);
    out_map_opt->key = "raster_output";
    out_map_opt->required = NO;
    out_map_opt->guisection = _("Outputs");

    mask_opt = G_define_standard_option(G_OPT_R_INPUT);
    mask_opt->key = "mask";
    mask_opt->label = _("Raster map to use for masking (applies to raster output only)");
    mask_opt->description = _("Only cells that are not NULL and not zero are interpolated");
    mask_opt->required = NO;

    stepE_opt = G_define_option();
    stepE_opt->key = "ew_step";
    stepE_opt->type = TYPE_DOUBLE;
    stepE_opt->required = NO;
    stepE_opt->answer = "4";
    stepE_opt->description =
        _("Length of each spline step in the east-west direction");
    stepE_opt->guisection = _("Settings");

    stepN_opt = G_define_option();
    stepN_opt->key = "ns_step";
    stepN_opt->type = TYPE_DOUBLE;
    stepN_opt->required = NO;
    stepN_opt->answer = "4";
    stepN_opt->description =
        _("Length of each spline step in the north-south direction");
    stepN_opt->guisection = _("Settings");

    type_opt = G_define_option();
    type_opt->key = "method";
    type_opt->description = _("Spline interpolation algorithm");
    type_opt->type = TYPE_STRING;
    type_opt->options = "bilinear,bicubic";
    type_opt->answer = "bilinear";
    type_opt->guisection = _("Settings");
    G_asprintf((char **) &(type_opt->descriptions),
               "bilinear;%s;bicubic;%s",
               _("Bilinear interpolation"),
               _("Bicubic interpolation"));

    lambda_f_opt = G_define_option();
    lambda_f_opt->key = "lambda_i";
    lambda_f_opt->type = TYPE_DOUBLE;
    lambda_f_opt->required = NO;
    lambda_f_opt->description = _("Tykhonov regularization parameter (affects smoothing)");
    lambda_f_opt->answer = "0.01";
    lambda_f_opt->guisection = _("Settings");

    solver = N_define_standard_option(N_OPT_SOLVER_SYMM);
    solver->options = "cholesky,cg";
    solver->answer = "cholesky";

    iter = N_define_standard_option(N_OPT_MAX_ITERATIONS);

    error = N_define_standard_option(N_OPT_ITERATION_ERROR);

    memory_opt = G_define_option();
    memory_opt->key = "memory";
    memory_opt->type = TYPE_INTEGER;
    memory_opt->required = NO;
    memory_opt->answer = "300";
    memory_opt->label = _("Maximum memory to be used (in MB)");
    memory_opt->description = _("Cache size for raster rows");

    /*----------------------------------------------------------------*/
    /* Parsing */
    G_gisinit(argv[0]);
    if (G_parser(argc, argv))
        exit(EXIT_FAILURE);

    vector = out_opt->answer;
    map = out_map_opt->answer;

    if (vector && map)
        G_fatal_error(_("Choose either vector or raster output, not both"));

    if (!vector && !map && !cross_corr_flag->answer)
        G_fatal_error(_("No raster or vector or cross-validation output"));

    if (!strcmp(type_opt->answer, "linear"))
        bilin = P_BILINEAR;
    else
        bilin = P_BICUBIC;

    stepN = atof(stepN_opt->answer);
    stepE = atof(stepE_opt->answer);
    lambda = atof(lambda_f_opt->answer);

    flag_auxiliar = FALSE;

    drv = db_get_default_driver_name();
    if (!drv) {
        if (db_set_default_connection() != DB_OK)
            G_fatal_error(_("Unable to set default DB connection"));
        drv = db_get_default_driver_name();
    }
    db = db_get_default_database_name();
    if (!db)
        G_fatal_error(_("No default DB defined"));

    /* Set auxiliary table's name */
    if (vector) {
        if (G_name_is_fully_qualified(out_opt->answer, xname, xmapset)) {
            sprintf(table_name, "%s_aux", xname);
        }
        else
            sprintf(table_name, "%s_aux", out_opt->answer);
    }

    /* Something went wrong in a previous v.surf.bspline execution */
    if (db_table_exists(drv, db, table_name)) {
        /* Start driver and open db */
        driver = db_start_driver_open_database(drv, db);
        if (driver == NULL)
            G_fatal_error(_("No database connection for driver <%s> is defined. Run db.connect."),
                          drv);
        db_set_error_handler_driver(driver);

        if (P_Drop_Aux_Table(driver, table_name) != DB_OK)
            G_fatal_error(_("Old auxiliary table could not be dropped"));
        db_close_database_shutdown_driver(driver);
    }

    /* Open input vector */
    if ((mapset = G_find_vector2(in_opt->answer, "")) == NULL)
        G_fatal_error(_("Vector map <%s> not found"), in_opt->answer);

    Vect_set_open_level(1);	/* WITHOUT TOPOLOGY */
    if (1 > Vect_open_old(&In, in_opt->answer, mapset))
        G_fatal_error(_("Unable to open vector map <%s> at the topological level"),
                      in_opt->answer);

    bspline_field = 0; /* assume 3D input */
    bspline_column = col_opt->answer;

    with_z = !bspline_column && Vect_is_3d(&In);

    if (Vect_is_3d(&In)) {
        if (!with_z)
            G_verbose_message(_("Input is 3D: using attribute values instead of z-coordinates for approximation"));
        else
            G_verbose_message(_("Input is 3D: using z-coordinates for approximation"));
    }
    else { /* 2D */
        if (!bspline_column)
            G_fatal_error(_("Input vector map is 2D. Parameter <%s> required."), col_opt->key);
    }

    if (!with_z) {
        bspline_field = Vect_get_field_number(&In, dfield_opt->answer);
    }

    /* Estimate point density and mean distance for current region */
    if (spline_step_flag->answer) {
        double dens, dist;
        if (P_estimate_splinestep(&In, &dens, &dist) == 0) {
            fprintf(stdout, _("Estimated point density: %.4g"), dens);
            fprintf(stdout, _("Estimated mean distance between points: %.4g"), dist);
        }
        else {
            fprintf(stdout, _("No points in current region"));
        }

        Vect_close(&In);
        exit(EXIT_SUCCESS);
    }

    /*----------------------------------------------------------------*/
    /* Cross-correlation begins */
    if (cross_corr_flag->answer) {
        G_debug(1, "CrossCorrelation()");
        cross = cross_correlation(&In, stepE, stepN);

        if (cross != TRUE)
            G_fatal_error(_("Cross validation didn't finish correctly"));
        else {
            G_debug(1, "Cross validation finished correctly");

            Vect_close(&In);

            G_done_msg(_("Cross validation finished for ew_step = %f and ns_step = %f"), stepE, stepN);
            exit(EXIT_SUCCESS);
        }
    }

    /* Open input ext vector */
    ext = FALSE;
    if (in_ext_opt->answer) {
        ext = TRUE;
        G_message(_("Vector map <%s> of sparse points will be interpolated"),
                  in_ext_opt->answer);

        if ((mapset = G_find_vector2(in_ext_opt->answer, "")) == NULL)
            G_fatal_error(_("Vector map <%s> not found"), in_ext_opt->answer);

        Vect_set_open_level(1);	/* WITHOUT TOPOLOGY */
        if (1 > Vect_open_old(&In_ext, in_ext_opt->answer, mapset))
            G_fatal_error(_("Unable to open vector map <%s> at the topological level"),
                          in_opt->answer);
    }

    /* Open output map */
    /* vector output */
    if (vector && !map) {
        if (strcmp(drv, "dbf") == 0)
            G_fatal_error(_("Sorry, the <%s> driver is not compatible with "
                            "the vector output of this module. "
                            "Try with raster output or another driver."), drv);

        Vect_check_input_output_name(in_opt->answer, out_opt->answer,
                                     G_FATAL_EXIT);
        grid = FALSE;

        if (0 > Vect_open_new(&Out, out_opt->answer, WITH_Z))
            G_fatal_error(_("Unable to create vector map <%s>"),
                          out_opt->answer);

        /* Copy vector Head File */
        if (ext == FALSE) {
            Vect_copy_head_data(&In, &Out);
            Vect_hist_copy(&In, &Out);
        }
        else {
            Vect_copy_head_data(&In_ext, &Out);
            Vect_hist_copy(&In_ext, &Out);
        }
        Vect_hist_command(&Out);

        G_verbose_message(_("Points in input vector map <%s> will be interpolated"),
                          vector);
    }


    /* read z values from attribute table */
    if (bspline_field > 0) {
        G_message(_("Reading values from attribute table..."));
        db_CatValArray_init(&cvarr);
        Fi = Vect_get_field(&In, bspline_field);
        if (Fi == NULL)
            G_fatal_error(_("Cannot read layer info"));

        driver_cats = db_start_driver_open_database(Fi->driver, Fi->database);
        /*G_debug (0, _("driver=%s db=%s"), Fi->driver, Fi->database); */

        if (driver_cats == NULL)
            G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
                          Fi->database, Fi->driver);
        db_set_error_handler_driver(driver_cats);

        nrec =
            db_select_CatValArray(driver_cats, Fi->table, Fi->key,
                                  col_opt->answer, NULL, &cvarr);
        G_debug(3, "nrec = %d", nrec);

        ctype = cvarr.ctype;
        if (ctype != DB_C_TYPE_INT && ctype != DB_C_TYPE_DOUBLE)
            G_fatal_error(_("Column type not supported"));

        if (nrec < 0)
            G_fatal_error(_("Unable to select data from table"));

        G_verbose_message(_("%d records selected from table"), nrec);

        db_close_database_shutdown_driver(driver_cats);
    }

    /*----------------------------------------------------------------*/
    /* Interpolation begins */
    G_debug(1, "Interpolation()");

    /* Open driver and database */
    driver = db_start_driver_open_database(drv, db);
    if (driver == NULL)
        G_fatal_error(_("No database connection for driver <%s> is defined. "
                        "Run db.connect."), drv);
    db_set_error_handler_driver(driver);

    /* Create auxiliary table */
    if (vector) {
        if ((flag_auxiliar = P_Create_Aux4_Table(driver, table_name)) == FALSE) {
            P_Drop_Aux_Table(driver, table_name);
            G_fatal_error(_("Interpolation: Creating table: "
                            "It was impossible to create table <%s>."),
                          table_name);
        }
        /* db_create_index2(driver, table_name, "ID"); */
        /* sqlite likes that ??? */
        db_close_database_shutdown_driver(driver);
        driver = db_start_driver_open_database(drv, db);
    }

    /* raster output */
    raster = -1;
    Rast_set_fp_type(DCELL_TYPE);
    if (!vector && map) {
        grid = TRUE;
        raster = Rast_open_fp_new(out_map_opt->answer);

        G_verbose_message(_("Cells for raster map <%s> will be interpolated"),
                          map);
    }

    /* Setting regions and boxes */
    G_debug(1, "Interpolation: Setting regions and boxes");
    G_get_window(&original_reg);
    G_get_window(&elaboration_reg);
    Vect_region_box(&original_reg, &original_box);
    Vect_region_box(&elaboration_reg, &overlap_box);
    Vect_region_box(&elaboration_reg, &general_box);

    nrows = Rast_window_rows();
    ncols = Rast_window_cols();

    /* Alloc raster matrix */
    have_mask = 0;
    out_file = mask_file = NULL;
    out_fd = mask_fd = -1;
    if (grid == TRUE) {
        int row;
        DCELL *drastbuf;

        seg_mb = atoi(memory_opt->answer);
        if (seg_mb < 3)
            G_fatal_error(_("Memory in MB must be >= 3"));

        if (mask_opt->answer)
            seg_size = sizeof(double) + sizeof(char);
        else
            seg_size = sizeof(double);

        seg_size = (seg_size * SEGSIZE * SEGSIZE) / (1 << 20);
        segments_in_memory = seg_mb / seg_size + 0.5;
        G_debug(1, "%d %dx%d segments held in memory", segments_in_memory, SEGSIZE, SEGSIZE);

        out_file = G_tempfile();
        out_fd = creat(out_file, 0666);
        if (Segment_format(out_fd, nrows, ncols, SEGSIZE, SEGSIZE, sizeof(double)) != 1)
            G_fatal_error(_("Can not create temporary file"));
        close(out_fd);

        out_fd = open(out_file, 2);
        if (Segment_init(&out_seg, out_fd, segments_in_memory) != 1)
            G_fatal_error(_("Can not initialize temporary file"));

        /* initialize output */
        G_message(_("Initializing output..."));

        drastbuf = Rast_allocate_buf(DCELL_TYPE);
        Rast_set_d_null_value(drastbuf, ncols);
        for (row = 0; row < nrows; row++) {
            G_percent(row, nrows, 2);
            Segment_put_row(&out_seg, drastbuf, row);
        }
        G_percent(row, nrows, 2);

        if (mask_opt->answer) {
            int row, col, maskfd;
            DCELL dval, *drastbuf;
            char mask_val;

            G_message(_("Load masking map"));

            mask_file = G_tempfile();
            mask_fd = creat(mask_file, 0666);
            if (Segment_format(mask_fd, nrows, ncols, SEGSIZE, SEGSIZE, sizeof(char)) != 1)
                G_fatal_error(_("Can not create temporary file"));
            close(mask_fd);

            mask_fd = open(mask_file, 2);
            if (Segment_init(&mask_seg, mask_fd, segments_in_memory) != 1)
                G_fatal_error(_("Can not initialize temporary file"));

            maskfd = Rast_open_old(mask_opt->answer, "");
            drastbuf = Rast_allocate_buf(DCELL_TYPE);

            for (row = 0; row < nrows; row++) {
                G_percent(row, nrows, 2);
                Rast_get_d_row(maskfd, drastbuf, row);
                for (col = 0; col < ncols; col++) {
                    dval = drastbuf[col];
                    if (Rast_is_d_null_value(&dval) || dval == 0)
                        mask_val = 0;
                    else
                        mask_val = 1;

                    Segment_put(&mask_seg, &mask_val, row, col);
                }
            }

            G_percent(row, nrows, 2);
            G_free(drastbuf);
            Rast_close(maskfd);

            have_mask = 1;
        }
    }

    /*------------------------------------------------------------------
      | Subdividing and working with tiles:
      | Each original region will be divided into several subregions.
      | Each one will be overlaped by its neighbouring subregions.
      | The overlapping is calculated as a fixed OVERLAP_SIZE times
      | the largest spline step plus 2 * edge
      ----------------------------------------------------------------*/

    /* Fixing parameters of the elaboration region */
    P_zero_dim(&dims);		/* Set dim struct to zero */

    nsplx_adj = NSPLX_MAX;
    nsply_adj = NSPLY_MAX;
    if (stepN > stepE)
        dims.overlap = OVERLAP_SIZE * stepN;
    else
        dims.overlap = OVERLAP_SIZE * stepE;
    P_get_edge(bilin, &dims, stepE, stepN);
    P_set_dim(&dims, stepE, stepN, &nsplx_adj, &nsply_adj);

    G_verbose_message(_("Adjusted EW splines %d"), nsplx_adj);
    G_verbose_message(_("Adjusted NS splines %d"), nsply_adj);

    /* calculate number of subregions */
    edgeE = dims.ew_size - dims.overlap - 2 * dims.edge_v;
    edgeN = dims.sn_size - dims.overlap - 2 * dims.edge_h;

    N_extension = original_reg.north - original_reg.south;
    E_extension = original_reg.east - original_reg.west;

    nsubregion_col = ceil(E_extension / edgeE) + 0.5;
    nsubregion_row = ceil(N_extension / edgeN) + 0.5;

    if (nsubregion_col < 0)
        nsubregion_col = 0;
    if (nsubregion_row < 0)
        nsubregion_row = 0;

    nsubregions = nsubregion_row * nsubregion_col;

    /* Creating line and categories structs */
    Cats = Vect_new_cats_struct();
    Vect_cat_set(Cats, 1, 0);

    subregion_row = 0;
    elaboration_reg.south = original_reg.north;
    last_row = FALSE;

    while (last_row == FALSE) {	/* For each subregion row */
        subregion_row++;
        P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims,
                      GENERAL_ROW);

        if (elaboration_reg.north > original_reg.north) {	/* First row */

            P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims,
                          FIRST_ROW);
        }

        if (elaboration_reg.south <= original_reg.south) {	/* Last row */

            P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims,
                          LAST_ROW);
            last_row = TRUE;
        }

        nsply =
            ceil((elaboration_reg.north -
                  elaboration_reg.south) / stepN) + 0.5;
        G_debug(1, "Interpolation: nsply = %d", nsply);
        /*
        if (nsply > NSPLY_MAX)
            nsply = NSPLY_MAX;
        */
        elaboration_reg.east = original_reg.west;
        last_column = FALSE;
        subregion_col = 0;

        /* TODO: process each subregion using its own thread (via OpenMP or pthreads) */
        /*     I'm not sure about pthreads, but you can tell OpenMP to start all at the
        	same time and it will keep num_workers supplied with the next job as free
        	cpus become available */
        while (last_column == FALSE) {	/* For each subregion column */
            int npoints = 0;
            /* needed for sparse points interpolation */
            int npoints_ext, *lineVect_ext = NULL;
            double **obsVect_ext;	/*, mean_ext = .0; */
            struct Point *observ_ext;

            subregion_col++;
            subregion++;
            if (nsubregions > 1)
                G_message(_("Processing subregion %d of %d..."), subregion, nsubregions);

            P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims,
                          GENERAL_COLUMN);

            if (elaboration_reg.west < original_reg.west) {	/* First column */

                P_set_regions(&elaboration_reg, &general_box, &overlap_box,
                              dims, FIRST_COLUMN);
            }

            if (elaboration_reg.east >= original_reg.east) {	/* Last column */

                P_set_regions(&elaboration_reg, &general_box, &overlap_box,
                              dims, LAST_COLUMN);
                last_column = TRUE;
            }
            nsplx =
                ceil((elaboration_reg.east -
                      elaboration_reg.west) / stepE) + 0.5;
            G_debug(1, "Interpolation: nsplx = %d", nsplx);
            /*
            if (nsplx > NSPLX_MAX)
            nsplx = NSPLX_MAX;
            */
            G_debug(1, "Interpolation: (%d,%d): subregion bounds",
                    subregion_row, subregion_col);
            G_debug(1, "Interpolation: \t\tNORTH:%.2f\t",
                    elaboration_reg.north);
            G_debug(1, "Interpolation: WEST:%.2f\t\tEAST:%.2f",
                    elaboration_reg.west, elaboration_reg.east);
            G_debug(1, "Interpolation: \t\tSOUTH:%.2f",
                    elaboration_reg.south);

#ifdef DEBUG_SUBREGIONS
            fprintf(stdout, "B 5\n");
            fprintf(stdout, " %.11g %.11g\n", elaboration_reg.east, elaboration_reg.north);
            fprintf(stdout, " %.11g %.11g\n", elaboration_reg.west, elaboration_reg.north);
            fprintf(stdout, " %.11g %.11g\n", elaboration_reg.west, elaboration_reg.south);
            fprintf(stdout, " %.11g %.11g\n", elaboration_reg.east, elaboration_reg.south);
            fprintf(stdout, " %.11g %.11g\n", elaboration_reg.east, elaboration_reg.north);
            fprintf(stdout, "C 1 1\n");
            fprintf(stdout, " %.11g %.11g\n", (elaboration_reg.west + elaboration_reg.east) / 2,
                    (elaboration_reg.south + elaboration_reg.north) / 2);
            fprintf(stdout, " 1 %d\n", subregion);
#endif



            /* reading points in interpolation region */
            dim_vect = nsplx * nsply;
            observ_ext = NULL;
            if (grid == FALSE && ext == TRUE) {
                observ_ext =
                    P_Read_Vector_Region_Map(&In_ext,
                                             &elaboration_reg,
                                             &npoints_ext, dim_vect,
                                             1);
            }
            else
                npoints_ext = 1;

            if (grid == TRUE && have_mask) {
                /* any unmasked cells in general region ? */
                mean = 0;
                observ_ext =
                    P_Read_Raster_Region_masked(&mask_seg, &original_reg,
                                                original_box, general_box,
                                                &npoints_ext, dim_vect, mean);
            }

            observ = NULL;
            if (npoints_ext > 0) {
                observ =
                    P_Read_Vector_Region_Map(&In, &elaboration_reg, &npoints,
                                             dim_vect, bspline_field);
            }
            else
                npoints = 1;

            G_debug(1,
                    "Interpolation: (%d,%d): Number of points in <elaboration_box> is %d",
                    subregion_row, subregion_col, npoints);
            if (npoints > 0)
                G_verbose_message(_("%d points found in this subregion"), npoints);
            /* only interpolate if there are any points in current subregion */
            if (npoints > 0 && npoints_ext > 0) {
                int i;

                nparameters = nsplx * nsply;
                BW = P_get_BandWidth(bilin, nsply);

                /* Least Squares system */
                N = G_alloc_matrix(nparameters, BW);	/* Normal matrix */
                TN = G_alloc_vector(nparameters);	/* vector */
                parVect = G_alloc_vector(nparameters);	/* Parameters vector */
                obsVect = G_alloc_matrix(npoints, 3);	/* Observation vector */
                Q = G_alloc_vector(npoints);	/* "a priori" var-cov matrix */
                lineVect = G_alloc_ivector(npoints);	/*  */

                for (i = 0; i < npoints; i++) {	/* Setting obsVect vector & Q matrix */
                    double dval;

                    Q[i] = 1;	/* Q=I */
                    lineVect[i] = observ[i].lineID;
                    obsVect[i][0] = observ[i].coordX;
                    obsVect[i][1] = observ[i].coordY;

                    /* read z coordinates from attribute table */
                    if (bspline_field > 0) {
                        int cat, ival, ret;

                        cat = observ[i].cat;
                        if (cat < 0)
                            continue;

                        if (ctype == DB_C_TYPE_INT) {
                            ret =
                                db_CatValArray_get_value_int(&cvarr, cat,
                                                             &ival);
                            obsVect[i][2] = ival;
                            observ[i].coordZ = ival;
                        }
                        else {	/* DB_C_TYPE_DOUBLE */
                            ret =
                                db_CatValArray_get_value_double(&cvarr, cat,
                                                                &dval);
                            obsVect[i][2] = dval;
                            observ[i].coordZ = dval;
                        }
                        if (ret != DB_OK) {
                            G_warning(_("Interpolation: (%d,%d): No record for point (cat = %d)"),
                                      subregion_row, subregion_col, cat);
                            continue;
                        }
                    }
                    /* use z coordinates of 3D vector */
                    else {
                        obsVect[i][2] = observ[i].coordZ;
                    }
                }

                /* Mean calculation for every point */
                mean = P_Mean_Calc(&elaboration_reg, observ, npoints);

                G_debug(1, "Interpolation: (%d,%d): mean=%lf",
                        subregion_row, subregion_col, mean);

                G_free(observ);

                for (i = 0; i < npoints; i++)
                    obsVect[i][2] -= mean;

                /* Bilinear interpolation */
                if (bilin) {
                    G_debug(1,
                            "Interpolation: (%d,%d): Bilinear interpolation...",
                            subregion_row, subregion_col);
                    normalDefBilin(N, TN, Q, obsVect, stepE, stepN, nsplx,
                                   nsply, elaboration_reg.west,
                                   elaboration_reg.south, npoints,
                                   nparameters, BW);
                    nCorrectGrad(N, lambda, nsplx, nsply, stepE, stepN);
                }
                /* Bicubic interpolation */
                else {
                    G_debug(1,
                            "Interpolation: (%d,%d): Bicubic interpolation...",
                            subregion_row, subregion_col);
                    normalDefBicubic(N, TN, Q, obsVect, stepE, stepN, nsplx,
                                     nsply, elaboration_reg.west,
                                     elaboration_reg.south, npoints,
                                     nparameters, BW);
                    nCorrectGrad(N, lambda, nsplx, nsply, stepE, stepN);
                }

                if(G_strncasecmp(solver->answer, "cg", 2) == 0)
                    G_math_solver_cg_sband(N, parVect, TN, nparameters, BW, atoi(iter->answer), atof(error->answer));
                else
                    G_math_solver_cholesky_sband(N, parVect, TN, nparameters, BW);


                G_free_matrix(N);
                G_free_vector(TN);
                G_free_vector(Q);

                if (grid == TRUE) {	/* GRID INTERPOLATION ==> INTERPOLATION INTO A RASTER */
                    G_debug(1, "Interpolation: (%d,%d): Regular_Points...",
                            subregion_row, subregion_col);

                    if (!have_mask) {
                        P_Regular_Points(&elaboration_reg, &original_reg, general_box,
                                         overlap_box, &out_seg, parVect,
                                         stepN, stepE, dims.overlap, mean,
                                         nsplx, nsply, nrows, ncols, bilin);
                    }
                    else {
                        P_Sparse_Raster_Points(&out_seg,
                                               &elaboration_reg, &original_reg,
                                               general_box, overlap_box,
                                               observ_ext, parVect,
                                               stepE, stepN,
                                               dims.overlap, nsplx, nsply,
                                               npoints_ext, bilin, mean);
                    }
                }
                else {		/* OBSERVATION POINTS INTERPOLATION */
                    if (ext == FALSE) {
                        G_debug(1, "Interpolation: (%d,%d): Sparse_Points...",
                                subregion_row, subregion_col);
                        P_Sparse_Points(&Out, &elaboration_reg, general_box,
                                        overlap_box, obsVect, parVect,
                                        lineVect, stepE, stepN,
                                        dims.overlap, nsplx, nsply, npoints,
                                        bilin, Cats, driver, mean,
                                        table_name);
                    }
                    else {	/* FLAG_EXT == TRUE */

                        /* done that earlier */
                        /*
                        int npoints_ext, *lineVect_ext = NULL;
                        double **obsVect_ext;
                        struct Point *observ_ext;

                        observ_ext =
                            P_Read_Vector_Region_Map(&In_ext,
                        			     &elaboration_reg,
                        			     &npoints_ext, dim_vect,
                        			     1);
                        */

                        obsVect_ext = G_alloc_matrix(npoints_ext, 3);	/* Observation vector_ext */
                        lineVect_ext = G_alloc_ivector(npoints_ext);

                        for (i = 0; i < npoints_ext; i++) {	/* Setting obsVect_ext vector & Q matrix */
                            obsVect_ext[i][0] = observ_ext[i].coordX;
                            obsVect_ext[i][1] = observ_ext[i].coordY;
                            obsVect_ext[i][2] = observ_ext[i].coordZ - mean;
                            lineVect_ext[i] = observ_ext[i].lineID;
                        }

                        G_free(observ_ext);

                        G_debug(1, "Interpolation: (%d,%d): Sparse_Points...",
                                subregion_row, subregion_col);
                        P_Sparse_Points(&Out, &elaboration_reg, general_box,
                                        overlap_box, obsVect_ext, parVect,
                                        lineVect_ext, stepE, stepN,
                                        dims.overlap, nsplx, nsply,
                                        npoints_ext, bilin, Cats, driver,
                                        mean, table_name);

                        G_free_matrix(obsVect_ext);
                        G_free_ivector(lineVect_ext);
                    }		/* END FLAG_EXT == TRUE */
                }		/* END GRID == FALSE */
                G_free_vector(parVect);
                G_free_matrix(obsVect);
                G_free_ivector(lineVect);
            }
            else {
                if (observ)
                    G_free(observ);
                if (observ_ext)
                    G_free(observ_ext);
                if (npoints == 0)
                    G_warning(_("No data within this subregion. "
                                "Consider increasing spline step values."));
            }
        }			/*! END WHILE; last_column = TRUE */
    }				/*! END WHILE; last_row = TRUE */

    G_verbose_message(_("Writing output..."));
    /* Writing the output raster map */
    if (grid == TRUE) {
        int row, col;
        DCELL *drastbuf, dval;


        if (have_mask) {
            Segment_release(&mask_seg);	/* release memory  */
            close(mask_fd);
            unlink(mask_file);
        }

        drastbuf = Rast_allocate_buf(DCELL_TYPE);
        for (row = 0; row < nrows; row++) {
            G_percent(row, nrows, 2);
            for (col = 0; col < ncols; col++) {
                Segment_get(&out_seg, &dval, row, col);
                drastbuf[col] = dval;
            }
            Rast_put_d_row(raster, drastbuf);
        }

        Rast_close(raster);

        Segment_release(&out_seg);	/* release memory  */
        close(out_fd);
        unlink(out_file);
        /* set map title */
        sprintf(title, "%s interpolation with Tykhonov regularization",
                type_opt->answer);
        Rast_put_cell_title(out_map_opt->answer, title);
        /* write map history */
        Rast_short_history(out_map_opt->answer, "raster", &history);
        Rast_command_history(&history);
        Rast_write_history(out_map_opt->answer, &history);
    }
    /* Writing to the output vector map the points from the overlapping zones */
    else if (flag_auxiliar == TRUE) {
        if (ext == FALSE)
            P_Aux_to_Vector(&In, &Out, driver, table_name);
        else
            P_Aux_to_Vector(&In_ext, &Out, driver, table_name);

        /* Drop auxiliary table */
        G_debug(1, "%s: Dropping <%s>", argv[0], table_name);
        if (P_Drop_Aux_Table(driver, table_name) != DB_OK)
            G_fatal_error(_("Auxiliary table could not be dropped"));
    }

    db_close_database_shutdown_driver(driver);

    Vect_close(&In);
    if (ext != FALSE)
        Vect_close(&In_ext);
    if (vector)
        Vect_close(&Out);

    G_done_msg(" ");

    exit(EXIT_SUCCESS);
}				/*END MAIN */
Example #18
0
int P_Sparse_Raster_Points(SEGMENT *out_seg, struct Cell_head *Elaboration,
		struct Cell_head *Original, struct bound_box General, struct bound_box Overlap,
		struct Point *obs, double *param, double pe, double pn,
		double overlap, int nsplx, int nsply, int num_points,
		int bilin, double mean)
{
    int i, row, col;
    double X, Y, interpolation, csi, eta, weight, dval;
    int points_in_box = 0;

    /* Reading points inside output region and inside general box */
    /* all points available here are inside the output box,
     * selected by P_Read_Raster_Region_Nulls(), no check needed */

    for (i = 0; i < num_points; i++) {

	X = obs[i].coordX;
	Y = obs[i].coordY;

	/* X,Y are cell center cordinates, MUST be inside General box */
	row = (int) (floor(Rast_northing_to_row(Y, Original)) + 0.1);
	col = (int) (floor((X - Original->west) / Original->ew_res) + 0.1);

	if (row < 0 || row >= Original->rows) {
	    G_fatal_error("row index out of range");
	    continue;
	}

	if (col < 0 || col >= Original->cols) {
	    G_fatal_error("col index out of range");
	    continue;
	}
	points_in_box++;

	G_debug(3, "P_Sparse_Raster_Points: interpolate point %d...", i);
	if (bilin)
	    interpolation =
		dataInterpolateBilin(X, Y, pe, pn, nsplx,
				     nsply, Elaboration->west,
				     Elaboration->south, param);
	else
	    interpolation =
		dataInterpolateBicubic(X, Y, pe, pn, nsplx,
				       nsply, Elaboration->west,
				       Elaboration->south, param);

	interpolation += mean;

	if (Vect_point_in_box(X, Y, interpolation, &Overlap)) {	/* (5) */
	    dval = interpolation;
	}
	else {
	    Segment_get(out_seg, &dval, row, col);
	    if ((X > Overlap.E) && (X < General.E)) {
		if ((Y > Overlap.N) && (Y < General.N)) {	/* (3) */
		    csi = (General.E - X) / overlap;
		    eta = (General.N - Y) / overlap;
		    weight = csi * eta;
		    interpolation *= weight;
		    dval += interpolation;
		}
		else if ((Y < Overlap.S) && (Y > General.S)) {	/* (1) */
		    csi = (General.E - X) / overlap;
		    eta = (Y - General.S) / overlap;
		    weight = csi * eta;
		    interpolation *= weight;
		    dval = interpolation;
		}
		else if ((Y >= Overlap.S) && (Y <= Overlap.N)) {	/* (1) */
		    weight = (General.E - X ) / overlap;
		    interpolation *= weight;
		    dval = interpolation;
		}
	    }
	    else if ((X < Overlap.W) && (X > General.W)) {
		if ((Y > Overlap.N) && (Y < General.N)) {	/* (4) */
		    csi = (X - General.W) / overlap;
		    eta = (General.N - Y) / overlap;
		    weight = eta * csi;
		    interpolation *= weight;
		    dval += interpolation;
		}
		else if ((Y < Overlap.S) && (Y > General.S)) {	/* (2) */
		    csi = (X - General.W) / overlap;
		    eta = (Y - General.S) / overlap;
		    weight = csi * eta;
		    interpolation *= weight;
		    dval += interpolation;
		}
		else if ((Y >= Overlap.S) && (Y <= Overlap.N)) {	/* (2) */
		    weight = (X - General.W) / overlap;
		    interpolation *= weight;
		    dval += interpolation;
		}
	    }
	    else if ((X >= Overlap.W) && (X <= Overlap.E)) {
		if ((Y > Overlap.N) && (Y < General.N)) {	/* (3) */
		    weight = (General.N - Y) / overlap;
		    interpolation *= weight;
		    dval += interpolation;
		}
		else if ((Y < Overlap.S) && (Y > General.S)) {	/* (1) */
		    weight = (Y - General.S) / overlap;
		    interpolation *= weight;
		    dval = interpolation;
		}
	    }
	} /* end not in overlap */
	Segment_put(out_seg, &dval, row, col);
    }  /* for num_points */

    return 1;
}
Example #19
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 #20
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 #21
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 #22
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;
}