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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
/*--------------------------------------------------------------------*/ 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 */
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; }
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, ®_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; }
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; }
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; }
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; }