int read_range(void) { struct FPRange drange; struct Range range; CELL tmp_min, tmp_max; DCELL tmp_dmin, tmp_dmax; char buff[1024]; int i; /* read the fpranges and ranges of all input maps */ for (i = 0; i < noi; i++) { if (Rast_read_fp_range(name[i], G_mapset(), &drange) <= 0) { sprintf(buff, "Can't read f_range for map %s", name[i]); G_fatal_error("%s", buff); } Rast_get_fp_range_min_max(&drange, &tmp_dmin, &tmp_dmax); if (Rast_read_range(name[i], G_mapset(), &range) <= 0) { sprintf(buff, "Can't read range for map %s", name[i]); G_fatal_error("%s", buff); } Rast_get_range_min_max(&range, &tmp_min, &tmp_max); if (!i || tmp_max > old_max || Rast_is_c_null_value(&old_max)) old_max = tmp_max; if (!i || tmp_min < old_min || Rast_is_c_null_value(&old_min)) old_min = tmp_min; if (!i || tmp_dmax > old_dmax || Rast_is_d_null_value(&old_dmax)) old_dmax = tmp_dmax; if (!i || tmp_dmin < old_dmin || Rast_is_d_null_value(&old_dmin)) old_dmin = tmp_dmin; } /* for loop */ return 0; }
static void fft_colors(const char *name) { struct Colors colors; struct FPRange range; DCELL min, max; /* make a real component color table */ Rast_read_fp_range(name, G_mapset(), &range); Rast_get_fp_range_min_max(&range, &min, &max); Rast_make_grey_scale_fp_colors(&colors, min, max); Rast_write_colors(name, G_mapset(), &colors); }
void update_input_region(char* raster, char* region, struct Cell_head &window, double &offset, bool ®ion3D) { if (region){ /* region= */ G_get_element_window(&window, "windows", region, ""); offset = window.bottom; if (window.top != window.bottom) region3D = true; } else if (raster) { struct FPRange range; double zmin, zmax; Rast_get_cellhd(raster, "", &window); Rast_read_fp_range(raster, "", &range); Rast_get_fp_range_min_max(&range, &zmin, &zmax); offset = zmin; } else { // current region G_get_set_window(&window); offset = 0; } }
static void make_gmt_header( struct GRD_HEADER *header, const char *name, const char *outfile, const struct Cell_head *region, double null_val) { struct FPRange range; DCELL z_min, z_max; Rast_read_fp_range(name, "", &range); Rast_get_fp_range_min_max(&range, &z_min, &z_max); header->nx = region->cols; header->ny = region->rows; header->node_offset = 1; /* 1 is pixel registration */ header->x_min = region->west; header->x_max = region->east; header->y_min = region->south; header->y_max = region->north; header->z_min = (double) z_min; header->z_max = (double) z_max; header->x_inc = region->ew_res; header->y_inc = region->ns_res; header->z_scale_factor = 1.0; header->z_add_offset = 0.0; if (region->proj == PROJECTION_LL) { strcpy(header->x_units, "degrees"); strcpy(header->y_units, "degrees"); } else { strcpy(header->x_units, "Meters"); strcpy(header->y_units, "Meters"); } strcpy(header->z_units, "elevation"); strcpy(header->title, name); sprintf(header->command, "r.out.bin -h input=%s output=%s", name, outfile); sprintf(header->remark, "%g used for NULL", null_val); }
static void get_map_range(void) { if (Rast_map_type(mapname, "") == CELL_TYPE) { struct Range range; CELL xmin, xmax; if (Rast_read_range(mapname, "", &range) <= 0) G_fatal_error(_("Unable to read range for %s"), mapname); Rast_get_range_min_max(&range, &xmin, &xmax); max = xmax; min = xmin; } else { struct FPRange fprange; if (Rast_read_fp_range(mapname, "", &fprange) <= 0) G_fatal_error(_("Unable to read FP range for %s"), mapname); Rast_get_fp_range_min_max(&fprange, &min, &max); } }
int parse_layer(char *s) { char name[GNAME_MAX]; const char *mapset; struct FPRange fp_range; int n; strcpy(name, s); mapset = G_find_raster2(name, ""); if (mapset == NULL) G_fatal_error(_("Raster map <%s> not found"), s); n = nlayers++; layers = (LAYER *) G_realloc(layers, nlayers * sizeof(LAYER)); is_fp = (int *)G_realloc(is_fp, (nlayers + 1) * sizeof(int)); DMAX = (DCELL *) G_realloc(DMAX, (nlayers + 1) * sizeof(DCELL)); DMIN = (DCELL *) G_realloc(DMIN, (nlayers + 1) * sizeof(DCELL)); if (!as_int) is_fp[n] = Rast_map_is_fp(name, mapset); else is_fp[n] = 0; if (is_fp[n]) { if (Rast_read_fp_range(name, mapset, &fp_range) < 0) G_fatal_error(_("Unable to read fp range for raster map <%s>"), name); Rast_get_fp_range_min_max(&fp_range, &DMIN[n], &DMAX[n]); } layers[n].name = G_store(name); layers[n].mapset = mapset; if (Rast_read_cats(name, mapset, &layers[n].labels) < 0) G_fatal_error(_("Unable to read category file of raster map <%s@%s>"), name, mapset); return 0; }
int report_range(void) { struct FPRange drange; struct Range range; char buff[1024], buff2[300]; RASTER_MAP_TYPE inp_type; inp_type = Rast_map_type(name, ""); if (inp_type != CELL_TYPE) { if (Rast_read_fp_range(name, "", &drange) <= 0) G_fatal_error(_("Unable to read f_range for map %s"), name); Rast_get_fp_range_min_max(&drange, &old_dmin, &old_dmax); if (Rast_is_d_null_value(&old_dmin) || Rast_is_d_null_value(&old_dmax)) G_message(_("Data range is empty")); else { sprintf(buff, "%.10f", old_dmin); sprintf(buff2, "%.10f", old_dmax); G_trim_decimal(buff); G_trim_decimal(buff2); G_message(_("Data range of %s is %s to %s (entire map)"), name, buff, buff2); } } if (Rast_read_range(name, "", &range) <= 0) G_fatal_error(_("Unable to read range for map <%s>"), name); Rast_get_range_min_max(&range, &old_min, &old_max); if (Rast_is_c_null_value(&old_min) || Rast_is_c_null_value(&old_max)) G_message(_("Integer data range of %s is empty"), name); else G_message(_("Integer data range of %s is %d to %d"), name, (int)old_min, (int)old_max); return 0; }
int main(int argc, char *argv[]) { int m1; struct FPRange range; DCELL cellmin, cellmax; FCELL *cellrow, fcellmin; struct GModule *module; struct { struct Option *input, *elev, *slope, *aspect, *pcurv, *tcurv, *mcurv, *smooth, *maskmap, *zmult, *fi, *segmax, *npmin, *res_ew, *res_ns, *overlap, *theta, *scalex; } parm; struct { struct Flag *deriv, *cprght; } flag; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("raster")); G_add_keyword(_("resample")); module->description = _("Reinterpolates and optionally computes topographic analysis from " "input raster map to a new raster map (possibly with " "different resolution) using regularized spline with " "tension and smoothing."); parm.input = G_define_standard_option(G_OPT_R_INPUT); parm.res_ew = G_define_option(); parm.res_ew->key = "ew_res"; parm.res_ew->type = TYPE_DOUBLE; parm.res_ew->required = YES; parm.res_ew->description = _("Desired east-west resolution"); parm.res_ns = G_define_option(); parm.res_ns->key = "ns_res"; parm.res_ns->type = TYPE_DOUBLE; parm.res_ns->required = YES; parm.res_ns->description = _("Desired north-south resolution"); parm.elev = G_define_option(); parm.elev->key = "elev"; parm.elev->type = TYPE_STRING; parm.elev->required = NO; parm.elev->gisprompt = "new,cell,raster"; parm.elev->description = _("Output z-file (elevation) map"); parm.elev->guisection = _("Output"); parm.slope = G_define_option(); parm.slope->key = "slope"; parm.slope->type = TYPE_STRING; parm.slope->required = NO; parm.slope->gisprompt = "new,cell,raster"; parm.slope->description = _("Output slope map (or fx)"); parm.slope->guisection = _("Output"); parm.aspect = G_define_option(); parm.aspect->key = "aspect"; parm.aspect->type = TYPE_STRING; parm.aspect->required = NO; parm.aspect->gisprompt = "new,cell,raster"; parm.aspect->description = _("Output aspect map (or fy)"); parm.aspect->guisection = _("Output"); parm.pcurv = G_define_option(); parm.pcurv->key = "pcurv"; parm.pcurv->type = TYPE_STRING; parm.pcurv->required = NO; parm.pcurv->gisprompt = "new,cell,raster"; parm.pcurv->description = _("Output profile curvature map (or fxx)"); parm.pcurv->guisection = _("Output"); parm.tcurv = G_define_option(); parm.tcurv->key = "tcurv"; parm.tcurv->type = TYPE_STRING; parm.tcurv->required = NO; parm.tcurv->gisprompt = "new,cell,raster"; parm.tcurv->description = _("Output tangential curvature map (or fyy)"); parm.tcurv->guisection = _("Output"); parm.mcurv = G_define_option(); parm.mcurv->key = "mcurv"; parm.mcurv->type = TYPE_STRING; parm.mcurv->required = NO; parm.mcurv->gisprompt = "new,cell,raster"; parm.mcurv->description = _("Output mean curvature map (or fxy)"); parm.mcurv->guisection = _("Output"); parm.smooth = G_define_option(); parm.smooth->key = "smooth"; parm.smooth->type = TYPE_STRING; parm.smooth->required = NO; parm.smooth->gisprompt = "old,cell,raster"; parm.smooth->description = _("Name of raster map containing smoothing"); parm.smooth->guisection = _("Settings"); parm.maskmap = G_define_option(); parm.maskmap->key = "maskmap"; parm.maskmap->type = TYPE_STRING; parm.maskmap->required = NO; parm.maskmap->gisprompt = "old,cell,raster"; parm.maskmap->description = _("Name of raster map to be used as mask"); parm.maskmap->guisection = _("Settings"); parm.overlap = G_define_option(); parm.overlap->key = "overlap"; parm.overlap->type = TYPE_INTEGER; parm.overlap->required = NO; parm.overlap->answer = OVERLAP; parm.overlap->description = _("Rows/columns overlap for segmentation"); parm.overlap->guisection = _("Settings"); parm.zmult = G_define_option(); parm.zmult->key = "zmult"; parm.zmult->type = TYPE_DOUBLE; parm.zmult->answer = ZMULT; parm.zmult->required = NO; parm.zmult->description = _("Multiplier for z-values"); parm.zmult->guisection = _("Settings"); parm.fi = G_define_option(); parm.fi->key = "tension"; parm.fi->type = TYPE_DOUBLE; parm.fi->answer = TENSION; parm.fi->required = NO; parm.fi->description = _("Spline tension value"); parm.fi->guisection = _("Settings"); parm.theta = G_define_option(); parm.theta->key = "theta"; parm.theta->type = TYPE_DOUBLE; parm.theta->required = NO; parm.theta->description = _("Anisotropy angle (in degrees)"); parm.theta->guisection = _("Anisotropy"); parm.scalex = G_define_option(); parm.scalex->key = "scalex"; parm.scalex->type = TYPE_DOUBLE; parm.scalex->required = NO; parm.scalex->description = _("Anisotropy scaling factor"); parm.scalex->guisection = _("Anisotropy"); flag.cprght = G_define_flag(); flag.cprght->key = 't'; flag.cprght->description = _("Use dnorm independent tension"); flag.deriv = G_define_flag(); flag.deriv->key = 'd'; flag.deriv->description = _("Output partial derivatives instead of topographic parameters"); flag.deriv->guisection = _("Output"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); G_get_set_window(&winhd); inp_ew_res = winhd.ew_res; inp_ns_res = winhd.ns_res; inp_cols = winhd.cols; inp_rows = winhd.rows; inp_x_orig = winhd.west; inp_y_orig = winhd.south; input = parm.input->answer; smooth = parm.smooth->answer; maskmap = parm.maskmap->answer; elev = parm.elev->answer; slope = parm.slope->answer; aspect = parm.aspect->answer; pcurv = parm.pcurv->answer; tcurv = parm.tcurv->answer; mcurv = parm.mcurv->answer; cond2 = ((pcurv != NULL) || (tcurv != NULL) || (mcurv != NULL)); cond1 = ((slope != NULL) || (aspect != NULL) || cond2); deriv = flag.deriv->answer; dtens = flag.cprght->answer; ertre = 0.1; if (!G_scan_resolution(parm.res_ew->answer, &ew_res, winhd.proj)) G_fatal_error(_("Unable to read ew_res value")); if (!G_scan_resolution(parm.res_ns->answer, &ns_res, winhd.proj)) G_fatal_error(_("Unable to read ns_res value")); if (sscanf(parm.fi->answer, "%lf", &fi) != 1) G_fatal_error(_("Invalid value for tension")); if (sscanf(parm.zmult->answer, "%lf", &zmult) != 1) G_fatal_error(_("Invalid value for zmult")); if (sscanf(parm.overlap->answer, "%d", &overlap) != 1) G_fatal_error(_("Invalid value for overlap")); if (parm.theta->answer) { if (sscanf(parm.theta->answer, "%lf", &theta) != 1) G_fatal_error(_("Invalid value for theta")); } if (parm.scalex->answer) { if (sscanf(parm.scalex->answer, "%lf", &scalex) != 1) G_fatal_error(_("Invalid value for scalex")); if (!parm.theta->answer) G_fatal_error(_("When using anisotropy both theta and scalex must be specified")); } /* * G_set_embedded_null_value_mode(1); */ outhd.ew_res = ew_res; outhd.ns_res = ns_res; outhd.east = winhd.east; outhd.west = winhd.west; outhd.north = winhd.north; outhd.south = winhd.south; outhd.proj = winhd.proj; outhd.zone = winhd.zone; G_adjust_Cell_head(&outhd, 0, 0); ew_res = outhd.ew_res; ns_res = outhd.ns_res; nsizc = outhd.cols; nsizr = outhd.rows; disk = nsizc * nsizr * sizeof(int); az = G_alloc_vector(nsizc + 1); if (cond1) { adx = G_alloc_vector(nsizc + 1); ady = G_alloc_vector(nsizc + 1); if (cond2) { adxx = G_alloc_vector(nsizc + 1); adyy = G_alloc_vector(nsizc + 1); adxy = G_alloc_vector(nsizc + 1); } } if (smooth != NULL) { fdsmooth = Rast_open_old(smooth, ""); Rast_get_cellhd(smooth, "", &smhd); if ((winhd.ew_res != smhd.ew_res) || (winhd.ns_res != smhd.ns_res)) G_fatal_error(_("Map <%s> is the wrong resolution"), smooth); if (Rast_read_fp_range(smooth, "", &range) >= 0) Rast_get_fp_range_min_max(&range, &cellmin, &cellmax); fcellmin = (float)cellmin; if (Rast_is_f_null_value(&fcellmin) || fcellmin < 0.0) G_fatal_error(_("Smoothing values can not be negative or NULL")); } Rast_get_cellhd(input, "", &inphd); if ((winhd.ew_res != inphd.ew_res) || (winhd.ns_res != inphd.ns_res)) G_fatal_error(_("Input map resolution differs from current region resolution!")); fdinp = Rast_open_old(input, ""); sdisk = 0; if (elev != NULL) sdisk += disk; if (slope != NULL) sdisk += disk; if (aspect != NULL) sdisk += disk; if (pcurv != NULL) sdisk += disk; if (tcurv != NULL) sdisk += disk; if (mcurv != NULL) sdisk += disk; G_message(_("Processing all selected output files will require")); if (sdisk > 1024) { if (sdisk > 1024 * 1024) { if (sdisk > 1024 * 1024 * 1024) { G_message(_("%.2f GB of disk space for temp files."), sdisk / (1024. * 1024. * 1024.)); } else G_message(_("%.2f MB of disk space for temp files."), sdisk / (1024. * 1024.)); } else G_message(_("%.2f KB of disk space for temp files."), sdisk / 1024.); } else G_message(_("%d bytes of disk space for temp files."), sdisk); fstar2 = fi * fi / 4.; tfsta2 = fstar2 + fstar2; deltx = winhd.east - winhd.west; delty = winhd.north - winhd.south; xmin = winhd.west; xmax = winhd.east; ymin = winhd.south; ymax = winhd.north; if (smooth != NULL) smc = -9999; else smc = 0.01; if (Rast_read_fp_range(input, "", &range) >= 0) { Rast_get_fp_range_min_max(&range, &cellmin, &cellmax); } else { cellrow = Rast_allocate_f_buf(); for (m1 = 0; m1 < inp_rows; m1++) { Rast_get_f_row(fdinp, cellrow, m1); Rast_row_update_fp_range(cellrow, m1, &range, FCELL_TYPE); } Rast_get_fp_range_min_max(&range, &cellmin, &cellmax); } fcellmin = (float)cellmin; if (Rast_is_f_null_value(&fcellmin)) G_fatal_error(_("Maximum value of a raster map is NULL.")); zmin = (double)cellmin *zmult; zmax = (double)cellmax *zmult; G_debug(1, "zmin=%f, zmax=%f", zmin, zmax); if (fd4 != NULL) fprintf(fd4, "deltx,delty %f %f \n", deltx, delty); create_temp_files(); IL_init_params_2d(¶ms, NULL, 1, 1, zmult, KMIN, KMAX, maskmap, outhd.rows, outhd.cols, az, adx, ady, adxx, adyy, adxy, fi, MAXPOINTS, SCIK1, SCIK2, SCIK3, smc, elev, slope, aspect, pcurv, tcurv, mcurv, dmin, inp_x_orig, inp_y_orig, deriv, theta, scalex, Tmp_fd_z, Tmp_fd_dx, Tmp_fd_dy, Tmp_fd_xx, Tmp_fd_yy, Tmp_fd_xy, NULL, NULL, 0, NULL); /* In the above line, the penultimate argument is supposed to be a * deviations file pointer. None is obvious, so I used NULL. */ /* The 3rd and 4th argument are int-s, elatt and smatt (from the function * definition. The value 1 seemed like a good placeholder... or not. */ IL_init_func_2d(¶ms, IL_grid_calc_2d, IL_matrix_create, IL_check_at_points_2d, IL_secpar_loop_2d, IL_crst, IL_crstg, IL_write_temp_2d); G_message(_("Temporarily changing the region to desired resolution ...")); Rast_set_window(&outhd); bitmask = IL_create_bitmask(¶ms); /* change region to initial region */ G_message(_("Changing back to the original region ...")); Rast_set_window(&winhd); ertot = 0.; cursegm = 0; G_message(_("Percent complete: ")); NPOINT = IL_resample_interp_segments_2d(¶ms, bitmask, zmin, zmax, &zminac, &zmaxac, &gmin, &gmax, &c1min, &c1max, &c2min, &c2max, &ertot, nsizc, &dnorm, overlap, inp_rows, inp_cols, fdsmooth, fdinp, ns_res, ew_res, inp_ns_res, inp_ew_res, dtens); G_message(_("dnorm in mainc after grid before out1= %f"), dnorm); if (NPOINT < 0) { clean(); G_fatal_error(_("split_and_interpolate() failed")); } if (fd4 != NULL) fprintf(fd4, "max. error found = %f \n", ertot); G_free_vector(az); if (cond1) { G_free_vector(adx); G_free_vector(ady); if (cond2) { G_free_vector(adxx); G_free_vector(adyy); G_free_vector(adxy); } } G_message(_("dnorm in mainc after grid before out2= %f"), dnorm); if (IL_resample_output_2d(¶ms, zmin, zmax, zminac, zmaxac, c1min, c1max, c2min, c2max, gmin, gmax, ertot, input, &dnorm, &outhd, &winhd, smooth, NPOINT) < 0) { clean(); G_fatal_error(_("Unable to write raster maps -- try increasing cell size")); } G_free(zero_array_cell); clean(); if (fd4) fclose(fd4); Rast_close(fdinp); if (smooth != NULL) Rast_close(fdsmooth); G_done_msg(" "); exit(EXIT_SUCCESS); }
CELL clump_n(int *in_fd, char **inname, int nin, double threshold, int out_fd, int diag, int print) { register int col; register int i, n; /* input */ DCELL **prev_in, **cur_in, **temp_in; int bcol; DCELL *rng, maxdiff; double thresh2; /* output */ CELL OLD, NEW; CELL *temp_clump, *out_cell, *out_cellp; CELL *prev_clump, *cur_clump; CELL *index, *renumber; CELL label; int nrows, ncols; int row; int isnull; int len; int nalloc; long cur_time; char *cname; int cfd, csize; CELL cat; G_message(_("%d-band clumping with threshold %g"), nin, threshold); nrows = Rast_window_rows(); ncols = Rast_window_cols(); thresh2 = threshold * threshold; /* allocate clump index */ nalloc = INCR; index = (CELL *) G_malloc(nalloc * sizeof(CELL)); index[0] = 0; renumber = NULL; /* allocate DCELL buffers two columns larger than current window */ len = (ncols + 2) * sizeof(DCELL); prev_in = (DCELL **) G_malloc(sizeof(DCELL *) * nin); cur_in = (DCELL **) G_malloc(sizeof(DCELL *) * nin); rng = G_malloc(sizeof(DCELL) * nin); maxdiff = 0; for (i = 0; i < nin; i++) { struct FPRange fp_range; /* min/max values of each input raster */ DCELL min, max; if (Rast_read_fp_range(inname[i], "", &fp_range) != 1) G_fatal_error(_("No min/max found in raster map <%s>"), inname[i]); Rast_get_fp_range_min_max(&fp_range, &min, &max); rng[i] = max - min; maxdiff += rng[i] * rng[i]; prev_in[i] = (DCELL *) G_malloc(len); cur_in[i] = (DCELL *) G_malloc(len); /* fake a previous row which is all NULL */ Rast_set_d_null_value(prev_in[i], ncols + 2); /* set left and right edge to NULL */ Rast_set_d_null_value(&cur_in[i][0], 1); Rast_set_d_null_value(&cur_in[i][ncols + 1], 1); } G_debug(1, "maximum possible difference: %g", maxdiff); /* allocate CELL buffers two columns larger than current window */ len = (ncols + 2) * sizeof(CELL); prev_clump = (CELL *) G_malloc(len); cur_clump = (CELL *) G_malloc(len); out_cell = (CELL *) G_malloc(len); /* temp file for initial clump IDs */ cname = G_tempfile(); if ((cfd = open(cname, O_RDWR | O_CREAT | O_EXCL, 0600)) < 0) G_fatal_error(_("Unable to open temp file")); csize = ncols * sizeof(CELL); time(&cur_time); /* initialize clump labels */ G_zero(cur_clump, len); G_zero(prev_clump, len); label = 0; /**************************************************** * PASS 1 * * pass thru the input, create initial clump labels * ****************************************************/ G_message(_("Pass 1 of 2...")); for (row = 0; row < nrows; row++) { G_percent(row, nrows, 2); for (i = 0; i < nin; i++) { Rast_get_d_row(in_fd[i], cur_in[i] + 1, row); } for (col = 1; col <= ncols; col++) { isnull = 0; for (i = 0; i < nin; i++) { if (Rast_is_d_null_value(&cur_in[i][col])) { /* don't clump NULL data */ cur_clump[col] = 0; isnull = 1; break; } } if (isnull) continue; /* * if the cell values are different to the left and above * (diagonal: and above left and above right) * then we must start a new clump * * this new clump may eventually collide with another * clump and will have to be merged */ /* try to connect the current cell to an existing clump */ OLD = NEW = 0; /* same clump as to the left */ if (cmp_cells(cur_in, col, cur_in, col - 1, rng, nin, thresh2)) { OLD = cur_clump[col] = cur_clump[col - 1]; } if (diag) { /* check above right, center, left, in that order */ temp_clump = prev_clump + col + 1; bcol = col + 1; do { if (cmp_cells(cur_in, col, prev_in, bcol, rng, nin, thresh2)) { cur_clump[col] = *temp_clump; if (OLD == 0) { OLD = *temp_clump; } else { NEW = *temp_clump; /* threshold > 0 and diagonal requires a bit of extra work * because of bridge cells: * A similar to B, B similar to C, but A not similar to C * -> B is bridge cell */ if (NEW != OLD) { CELL *temp_clump2; /* conflict! preserve NEW clump ID and change OLD clump ID. * Must go back to the left in the current row and to the right * in the previous row to change all the clump values as well. */ /* left of the current row from 1 to col - 1 */ temp_clump2 = cur_clump; n = col - 1; while (n-- > 0) { temp_clump2++; /* skip left edge */ if (*temp_clump2 == OLD) *temp_clump2 = NEW; } /* right of previous row from col - 1 to ncols */ temp_clump2 = prev_clump + col - 1; n = ncols - col + 2; while (n-- > 0) { if (*temp_clump2 == OLD) *temp_clump2 = NEW; temp_clump2++; } /* modify the OLD index */ index[OLD] = NEW; OLD = NEW; NEW = 0; } } } temp_clump--; } while (bcol-- > col - 1); } else { /* check above */ if (cmp_cells(cur_in, col, prev_in, col, rng, nin, thresh2)) { temp_clump = prev_clump + col; cur_clump[col] = *temp_clump; if (OLD == 0) { OLD = *temp_clump; } else { NEW = *temp_clump; if (NEW != OLD) { /* conflict! preserve NEW clump ID and change OLD clump ID. * Must go back to the left in the current row and to the right * in the previous row to change all the clump values as well. */ /* left of the current row from 1 to col - 1 */ temp_clump = cur_clump; n = col - 1; while (n-- > 0) { temp_clump++; /* skip left edge */ if (*temp_clump == OLD) *temp_clump = NEW; } /* right of previous row from col + 1 to ncols */ temp_clump = prev_clump + col; n = ncols - col; while (n-- > 0) { temp_clump++; /* skip col */ if (*temp_clump == OLD) *temp_clump = NEW; } /* modify the OLD index */ index[OLD] = NEW; OLD = NEW; NEW = 0; } } } } if (NEW == 0 || OLD == NEW) { /* ok */ if (OLD == 0) { /* start a new clump */ label++; cur_clump[col] = label; if (label >= nalloc) { nalloc += INCR; index = (CELL *) G_realloc(index, nalloc * sizeof(CELL)); } index[label] = label; } } /* else the relabelling above failed */ } /* write initial clump IDs */ /* this works also with writing out cur_clump, but only * prev_clump is complete and will not change any more */ if (row > 0) { if (write(cfd, prev_clump + 1, csize) != csize) G_fatal_error(_("Unable to write to temp file")); } /* switch the buffers so that the current buffer becomes the previous */ temp_in = cur_in; cur_in = prev_in; prev_in = temp_in; temp_clump = cur_clump; cur_clump = prev_clump; prev_clump = temp_clump; } /* write last row with initial clump IDs */ if (write(cfd, prev_clump + 1, csize) != csize) G_fatal_error(_("Unable to write to temp file")); G_percent(1, 1, 1); /* generate a renumbering scheme */ G_message(_("Generating renumbering scheme...")); G_debug(1, "%d initial labels", label); /* allocate final clump ID */ renumber = (CELL *) G_malloc((label + 1) * sizeof(CELL)); renumber[0] = 0; cat = 1; G_percent(0, label, 1); for (n = 1; n <= label; n++) { G_percent(n, label, 1); OLD = n; NEW = index[n]; if (OLD != NEW) { renumber[n] = 0; /* find valid clump ID */ while (OLD != NEW) { OLD = NEW; NEW = index[OLD]; if (NEW == n) G_fatal_error("Circular relabelling for %d", n); } index[n] = NEW; } else /* set final clump id */ renumber[n] = cat++; } /* rewind temp file */ lseek(cfd, 0, SEEK_SET); if (print) { fprintf(stdout, "clumps=%d\n", cat - 1); } else { /**************************************************** * PASS 2 * * apply renumbering scheme to initial clump labels * ****************************************************/ /* the input raster is no longer needed, * using instead the temp file with initial clump labels */ G_message(_("Pass 2 of 2...")); for (row = 0; row < nrows; row++) { G_percent(row, nrows, 2); if (read(cfd, cur_clump, csize) != csize) G_fatal_error(_("Unable to read from temp file")); temp_clump = cur_clump; out_cellp = out_cell; for (col = 0; col < ncols; col++) { *out_cellp = renumber[index[*temp_clump]]; if (*out_cellp == 0) Rast_set_c_null_value(out_cellp, 1); temp_clump++; out_cellp++; } Rast_put_row(out_fd, out_cell, CELL_TYPE); } G_percent(1, 1, 1); } close(cfd); unlink(cname); print_time(&cur_time); return 0; }
/* actual raster band export * returns 0 on success * -1 on raster data read/write error * */ int export_band(GDALDatasetH hMEMDS, int band, const char *name, const char *mapset, struct Cell_head *cellhead, RASTER_MAP_TYPE maptype, double nodataval, int suppress_main_colortable) { struct Colors sGrassColors; GDALColorTableH hCT; int iColor; int bHaveMinMax; double dfCellMin; double dfCellMax; struct FPRange sRange; int fd; int cols = cellhead->cols; int rows = cellhead->rows; int ret = 0; char value[200]; /* Open GRASS raster */ fd = Rast_open_old(name, mapset); /* Get raster band */ GDALRasterBandH hBand = GDALGetRasterBand(hMEMDS, band); if (hBand == NULL) { G_warning(_("Unable to get raster band")); return -1; } /* Get min/max values. */ if (Rast_read_fp_range(name, mapset, &sRange) == -1) { bHaveMinMax = FALSE; } else { bHaveMinMax = TRUE; Rast_get_fp_range_min_max(&sRange, &dfCellMin, &dfCellMax); } sprintf(value, "GRASS GIS %s", GRASS_VERSION_NUMBER); GDALSetMetadataItem(hBand, "Generated_with", value, NULL); /* use default color rules if no color rules are given */ if (Rast_read_colors(name, mapset, &sGrassColors) >= 0) { int maxcolor, i; CELL min, max; char key[200]; int rcount; Rast_get_c_color_range(&min, &max, &sGrassColors); if (bHaveMinMax) { if (max < dfCellMax) { maxcolor = max; } else { maxcolor = (int)ceil(dfCellMax); } if (maxcolor > GRASS_MAX_COLORS) { maxcolor = GRASS_MAX_COLORS; G_warning("Too many values, color table cut to %d entries", maxcolor); } } else { if (max < GRASS_MAX_COLORS) { maxcolor = max; } else { maxcolor = GRASS_MAX_COLORS; G_warning("Too many values, color table set to %d entries", maxcolor); } } rcount = Rast_colors_count(&sGrassColors); G_debug(3, "dfCellMin: %f, dfCellMax: %f, maxcolor: %d", dfCellMin, dfCellMax, maxcolor); if (!suppress_main_colortable) { hCT = GDALCreateColorTable(GPI_RGB); for (iColor = 0; iColor <= maxcolor; iColor++) { int nRed, nGreen, nBlue; GDALColorEntry sColor; if (Rast_get_c_color(&iColor, &nRed, &nGreen, &nBlue, &sGrassColors)) { sColor.c1 = nRed; sColor.c2 = nGreen; sColor.c3 = nBlue; sColor.c4 = 255; G_debug(3, "Rast_get_c_color: Y, rcount %d, nRed %d, nGreen %d, nBlue %d", rcount, nRed, nGreen, nBlue); GDALSetColorEntry(hCT, iColor, &sColor); } else { sColor.c1 = 0; sColor.c2 = 0; sColor.c3 = 0; sColor.c4 = 0; G_debug(3, "Rast_get_c_color: N, rcount %d, nRed %d, nGreen %d, nBlue %d", rcount, nRed, nGreen, nBlue); GDALSetColorEntry(hCT, iColor, &sColor); } } GDALSetRasterColorTable(hBand, hCT); } if (rcount > 0) { /* Create metadata entries for color table rules */ sprintf(value, "%d", rcount); GDALSetMetadataItem(hBand, "COLOR_TABLE_RULES_COUNT", value, NULL); } /* Add the rules in reverse order */ /* This can cause a GDAL warning with many rules, something like * Warning 1: Lost metadata writing to GeoTIFF ... too large to fit in tag. */ for (i = rcount - 1; i >= 0; i--) { DCELL val1, val2; unsigned char r1, g1, b1, r2, g2, b2; Rast_get_fp_color_rule(&val1, &r1, &g1, &b1, &val2, &r2, &g2, &b2, &sGrassColors, i); sprintf(key, "COLOR_TABLE_RULE_RGB_%d", rcount - i - 1); sprintf(value, "%e %e %d %d %d %d %d %d", val1, val2, r1, g1, b1, r2, g2, b2); GDALSetMetadataItem(hBand, key, value, NULL); } } /* Create GRASS raster buffer */ void *bufer = Rast_allocate_buf(maptype); if (bufer == NULL) { G_warning(_("Unable to allocate buffer for reading raster map")); return -1; } /* the following routine must be kept identical to exact_checks */ /* Copy data form GRASS raster to GDAL raster */ int row, col; int n_nulls = 0; /* Better use selected GDAL datatype instead of * the best match with GRASS raster map types ? */ if (maptype == FCELL_TYPE) { /* Source datatype understandable by GDAL */ GDALDataType datatype = GDT_Float32; FCELL fnullval = (FCELL) nodataval; G_debug(1, "FCELL nodata val: %f", fnullval); for (row = 0; row < rows; row++) { Rast_get_row(fd, bufer, row, maptype); for (col = 0; col < cols; col++) { if (Rast_is_f_null_value(&((FCELL *) bufer)[col])) { ((FCELL *) bufer)[col] = fnullval; if (n_nulls == 0) { GDALSetRasterNoDataValue(hBand, nodataval); } n_nulls++; } } if (GDALRasterIO (hBand, GF_Write, 0, row, cols, 1, bufer, cols, 1, datatype, 0, 0) >= CE_Failure) { G_warning(_("Unable to write GDAL raster file")); return -1; } G_percent(row + 1, rows, 2); } } else if (maptype == DCELL_TYPE) { GDALDataType datatype = GDT_Float64; DCELL dnullval = (DCELL) nodataval; G_debug(1, "DCELL nodata val: %f", dnullval); for (row = 0; row < rows; row++) { Rast_get_row(fd, bufer, row, maptype); for (col = 0; col < cols; col++) { if (Rast_is_d_null_value(&((DCELL *) bufer)[col])) { ((DCELL *) bufer)[col] = dnullval; if (n_nulls == 0) { GDALSetRasterNoDataValue(hBand, nodataval); } n_nulls++; } } if (GDALRasterIO (hBand, GF_Write, 0, row, cols, 1, bufer, cols, 1, datatype, 0, 0) >= CE_Failure) { G_warning(_("Unable to write GDAL raster file")); return -1; } G_percent(row + 1, rows, 2); } } else { GDALDataType datatype = GDT_Int32; CELL inullval = (CELL) nodataval; G_debug(1, "CELL nodata val: %d", inullval); for (row = 0; row < rows; row++) { Rast_get_row(fd, bufer, row, maptype); for (col = 0; col < cols; col++) { if (Rast_is_c_null_value(&((CELL *) bufer)[col])) { ((CELL *) bufer)[col] = inullval; if (n_nulls == 0) { GDALSetRasterNoDataValue(hBand, nodataval); } n_nulls++; } } if (GDALRasterIO (hBand, GF_Write, 0, row, cols, 1, bufer, cols, 1, datatype, 0, 0) >= CE_Failure) { G_warning(_("Unable to write GDAL raster file")); return -1; } G_percent(row + 1, rows, 2); } } Rast_close(fd); G_free(bufer); return ret; }
int main(int argc, char *argv[]) { int *fd; char **names; char **ptr; char *name; /* flags */ int raw_data; int with_coordinates; int with_xy; int with_percents; int with_counts; int with_areas; int with_labels; /* printf format */ char fmt[20]; int dp; struct Range range; struct FPRange fp_range; struct Quant q; CELL min, max, null_set = 0; DCELL dmin, dmax; struct GModule *module; struct { struct Flag *A; /* print averaged values instead of intervals */ struct Flag *a; /* area */ struct Flag *c; /* cell counts */ struct Flag *p; /* percents */ struct Flag *l; /* with labels */ struct Flag *q; /* quiet */ struct Flag *n; /* Suppress reporting of any NULLs */ struct Flag *N; /* Suppress reporting of NULLs when all values are NULL */ struct Flag *one; /* one cell per line */ struct Flag *x; /* with row/col */ struct Flag *g; /* with east/north */ struct Flag *i; /* use quant rules for fp map, i.e. read it as int */ struct Flag *r; /* raw output: when nsteps option is used, report indexes of ranges instead of ranges themselves; when -C (cats) option is used reports indexes of fp ranges = ind. of labels */ struct Flag *C; /* report stats for labeled ranges in cats files */ } flag; struct { struct Option *cell; struct Option *fs; struct Option *nv; struct Option *output; struct Option *nsteps; /* divide data range into nsteps and report stats for these ranges: only for fp maps NOTE: when -C flag is used, and there are explicit fp ranges in cats or when the map is int, nsteps is ignored */ } option; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("raster")); G_add_keyword(_("statistics")); module->description = _("Generates area statistics for raster map layers."); /* Define the different options */ option.cell = G_define_standard_option(G_OPT_R_INPUTS); option.output = G_define_standard_option(G_OPT_F_OUTPUT); option.output->required = NO; option.output->description = _("Name for output file (if omitted or \"-\" output to stdout)"); option.fs = G_define_standard_option(G_OPT_F_SEP); option.fs->key_desc = "character|space|tab"; option.fs->answer = "space"; option.fs->description = _("Output field separator"); option.nv = G_define_option(); option.nv->key = "nv"; option.nv->type = TYPE_STRING; option.nv->required = NO; option.nv->multiple = NO; option.nv->answer = "*"; option.nv->description = _("String representing no data cell value"); option.nsteps = G_define_option(); option.nsteps->key = "nsteps"; option.nsteps->type = TYPE_INTEGER; option.nsteps->required = NO; option.nsteps->multiple = NO; option.nsteps->answer = "255"; option.nsteps->description = _("Number of fp subranges to collect stats from"); /* Define the different flags */ flag.one = G_define_flag(); flag.one->key = '1'; flag.one->description = _("One cell (range) per line"); flag.A = G_define_flag(); flag.A->key = 'A'; flag.A->description = _("Print averaged values instead of intervals"); flag.A->guisection = _("Print"); flag.a = G_define_flag(); flag.a->key = 'a'; flag.a->description = _("Print area totals"); flag.a->guisection = _("Print"); flag.c = G_define_flag(); flag.c->key = 'c'; flag.c->description = _("Print cell counts"); flag.c->guisection = _("Print"); flag.p = G_define_flag(); flag.p->key = 'p'; flag.p->description = _("Print APPROXIMATE percents (total percent may not be 100%)"); flag.p->guisection = _("Print"); flag.l = G_define_flag(); flag.l->key = 'l'; flag.l->description = _("Print category labels"); flag.l->guisection = _("Print"); flag.g = G_define_flag(); flag.g->key = 'g'; flag.g->description = _("Print grid coordinates (east and north)"); flag.g->guisection = _("Print"); flag.x = G_define_flag(); flag.x->key = 'x'; flag.x->description = _("Print x and y (column and row)"); flag.x->guisection = _("Print"); flag.r = G_define_flag(); flag.r->key = 'r'; flag.r->description = _("Print raw indexes of fp ranges (fp maps only)"); flag.r->guisection = _("Print"); flag.n = G_define_flag(); flag.n->key = 'n'; flag.n->description = _("Suppress reporting of any NULLs"); flag.N = G_define_flag(); flag.N->key = 'N'; flag.N->description = _("Suppress reporting of NULLs when all values are NULL"); flag.C = G_define_flag(); flag.C->key = 'C'; flag.C->description = _("Report for cats fp ranges (fp maps only)"); flag.i = G_define_flag(); flag.i->key = 'i'; flag.i->description = _("Read fp map as integer (use map's quant rules)"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); name = option.output->answer; if (name != NULL && strcmp(name, "-") != 0) { if (NULL == freopen(name, "w", stdout)) { G_fatal_error(_("Unable to open file <%s> for writing"), name); } } sscanf(option.nsteps->answer, "%d", &nsteps); if (nsteps <= 0) { G_warning(_("'%s' must be greater than zero; using %s=255"), option.nsteps->key, option.nsteps->key); nsteps = 255; } cat_ranges = flag.C->answer; averaged = flag.A->answer; raw_output = flag.r->answer; as_int = flag.i->answer; nrows = Rast_window_rows(); ncols = Rast_window_cols(); fd = NULL; nfiles = 0; dp = -1; with_percents = flag.p->answer; with_counts = flag.c->answer; with_areas = flag.a->answer; with_labels = flag.l->answer; no_nulls = flag.n->answer; no_nulls_all = flag.N->answer; no_data_str = option.nv->answer; raw_data = flag.one->answer; with_coordinates = flag.g->answer; with_xy = flag.x->answer; if (with_coordinates || with_xy) raw_data = 1; /* get field separator */ strcpy(fs, " "); if (option.fs->answer) { if (strcmp(option.fs->answer, "space") == 0) *fs = ' '; else if (strcmp(option.fs->answer, "tab") == 0) *fs = '\t'; else if (strcmp(option.fs->answer, "\\t") == 0) *fs = '\t'; else *fs = *option.fs->answer; } /* open all raster maps */ if (option.cell->answers[0] == NULL) G_fatal_error(_("Raster map not found")); names = option.cell->answers; ptr = option.cell->answers; for (; *ptr != NULL; ptr++) { name = *ptr; fd = (int *)G_realloc(fd, (nfiles + 1) * sizeof(int)); is_fp = (int *)G_realloc(is_fp, (nfiles + 1) * sizeof(int)); DMAX = (DCELL *) G_realloc(DMAX, (nfiles + 1) * sizeof(DCELL)); DMIN = (DCELL *) G_realloc(DMIN, (nfiles + 1) * sizeof(DCELL)); fd[nfiles] = Rast_open_old(name, ""); if (!as_int) is_fp[nfiles] = Rast_map_is_fp(name, ""); else { is_fp[nfiles] = 0; if (cat_ranges || nsteps != 255) G_warning(_("Raster map <%s> is reading as integer map! " "Flag '-%c' and/or '%s' option will be ignored."), name, flag.C->key, option.nsteps->key); } if (with_labels || (cat_ranges && is_fp[nfiles])) { labels = (struct Categories *) G_realloc(labels, (nfiles + 1) * sizeof(struct Categories)); if (Rast_read_cats(name, "", &labels[nfiles]) < 0) Rast_init_cats("", &labels[nfiles]); } if (is_fp[nfiles]) /* floating point map */ { Rast_quant_init(&q); if (cat_ranges) { if (!Rast_quant_nof_rules(&labels[nfiles].q)) { G_warning(_("Cats for raster map <%s> are either missing or have no explicit labels. " "Using %s=%d."), name, option.nsteps->key, nsteps); cat_ranges = 0; } else if (nsteps != 255) G_warning(_("Flag '-%c' was given, using cats fp ranges of raster map <%s>, " "ignoring '%s' option"), flag.C->key, name, option.nsteps->key); } if (!cat_ranges) { /* DO NOT use else here, cat_ranges can change */ if (Rast_read_fp_range(name, "", &fp_range) < 0) G_fatal_error(_("Unable to read fp range of raster map <%s>"), name); Rast_get_fp_range_min_max(&fp_range, &DMIN[nfiles], &DMAX[nfiles]); G_debug(3, "file %2d: dmin=%f dmax=%f", nfiles, DMIN[nfiles], DMAX[nfiles]); Rast_quant_add_rule(&q, DMIN[nfiles], DMAX[nfiles], 1, nsteps+1); /* set the quant rules for reading the map */ Rast_set_quant_rules(fd[nfiles], &q); Rast_quant_get_limits(&q, &dmin, &dmax, &min, &max); G_debug(2, "overall: dmin=%f dmax=%f, qmin=%d qmax=%d", dmin, dmax, min, max); Rast_quant_free(&q); } else { /* cats ranges */ /* set the quant rules for reading the map */ Rast_set_quant_rules(fd[nfiles], &labels[nfiles].q); Rast_quant_get_limits(&labels[nfiles].q, &dmin, &dmax, &min, &max); } } else { if (Rast_read_range(name, "", &range) < 0) G_fatal_error(_("Unable to read range for map <%s>"), name); Rast_get_range_min_max(&range, &min, &max); } if (!null_set) { null_set = 1; NULL_CELL = max + 1; } else if (NULL_CELL < max + 1) NULL_CELL = max + 1; nfiles++; } if (dp < 0) strcpy(fmt, "%lf"); else sprintf(fmt, "%%.%dlf", dp); if (raw_data) raw_stats(fd, with_coordinates, with_xy, with_labels); else cell_stats(fd, with_percents, with_counts, with_areas, with_labels, fmt); exit(EXIT_SUCCESS); }
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; }
/*! * \brief Read raster range (CELL) * * This routine reads the range information for the raster map * <i>name</i> in <i>mapset</i> into the <i>range</i> structure. * * A diagnostic message is printed and -1 is returned if there is an error * reading the range file. Otherwise, 0 is returned. * * Old range file (those with 4 numbers) should treat zeros in this * file as NULL-values. New range files (those with just 2 numbers) * should treat these numbers as real data (zeros are real data in * this case). An empty range file indicates that the min, max are * undefined. This is a valid case, and the result should be an * initialized range struct with no defined min/max. If the range file * is missing and the map is a floating-point map, this function will * create a default range by calling G_construct_default_range(). * * \param name map name * \param mapset mapset name * \param[out] range pointer to Range structure which holds range info * * \return -1 on error * \return 1 on success * \return 2 if range is empty * \return 3 if raster map is floating-point, get range from quant rules */ int Rast_read_range(const char *name, const char *mapset, struct Range *range) { FILE *fd; CELL x[4]; char buf[200]; int n, count; struct Quant quant; struct FPRange drange; Rast_init_range(range); fd = NULL; /* if map is not integer, read quant rules, and get limits */ if (Rast_map_type(name, mapset) != CELL_TYPE) { DCELL dmin, dmax; if (Rast_read_quant(name, mapset, &quant) < 0) { G_warning(_("Unable to read quant rules for raster map <%s>"), G_fully_qualified_name(name, mapset)); return -1; } if (Rast_quant_is_truncate(&quant) || Rast_quant_is_round(&quant)) { if (Rast_read_fp_range(name, mapset, &drange) >= 0) { Rast_get_fp_range_min_max(&drange, &dmin, &dmax); if (Rast_quant_is_truncate(&quant)) { x[0] = (CELL) dmin; x[1] = (CELL) dmax; } else { /* round */ if (dmin > 0) x[0] = (CELL) (dmin + .5); else x[0] = (CELL) (dmin - .5); if (dmax > 0) x[1] = (CELL) (dmax + .5); else x[1] = (CELL) (dmax - .5); } } else return -1; } else Rast_quant_get_limits(&quant, &dmin, &dmax, &x[0], &x[1]); Rast_update_range(x[0], range); Rast_update_range(x[1], range); return 3; } if (G_find_file2_misc("cell_misc", "range", name, mapset)) { fd = G_fopen_old_misc("cell_misc", "range", name, mapset); if (!fd) { G_warning(_("Unable to read range file for <%s>"), G_fully_qualified_name(name, mapset)); return -1; } /* if range file exists but empty */ if (!fgets(buf, sizeof buf, fd)) { if (fd) fclose(fd); return 2; } x[0] = x[1] = x[2] = x[3] = 0; count = sscanf(buf, "%d%d%d%d", &x[0], &x[1], &x[2], &x[3]); /* if wrong format */ if (count <= 0) { if (fd) fclose(fd); G_warning(_("Unable to read range file for <%s>"), G_fully_qualified_name(name, mapset)); return -1; } for (n = 0; n < count; n++) { /* if count==4, the range file is old (4.1) and 0's in it have to be ignored */ if (count < 4 || x[n]) Rast_update_range((CELL) x[n], range); } fclose(fd); } return 1; }
int main(int argc, char *argv[]) { struct History history; struct GModule *module; char *desc; struct Cell_head cellhd, orig_cellhd; void *inrast, *outrast; int infd, outfd; void *ptr; int nrows, ncols, row, col; RASTER_MAP_TYPE in_data_type; struct Option *input_prefix, *output_prefix, *metfn, *sensor, *adate, *pdate, *elev, *bgain, *metho, *perc, *dark, *atmo, *lsatmet, *oscale; char *inputname, *met, *outputname, *sensorname; struct Flag *frad, *print_meta, *named; lsat_data lsat; char band_in[GNAME_MAX], band_out[GNAME_MAX]; int i, j, q, method, pixel, dn_dark[MAX_BANDS], dn_mode[MAX_BANDS], dn_sat; int overwrite; double qcal, rad, ref, percent, ref_mode, rayleigh, scale; unsigned long hist[QCALMAX], h_max; struct Colors colors; struct FPRange range; double min, max; /* initialize GIS environment */ G_gisinit(argv[0]); /* initialize module */ module = G_define_module(); module->description = _("Calculates top-of-atmosphere radiance or reflectance and temperature for Landsat MSS/TM/ETM+/OLI"); G_add_keyword(_("imagery")); G_add_keyword(_("radiometric conversion")); G_add_keyword(_("radiance")); G_add_keyword(_("reflectance")); G_add_keyword(_("brightness temperature")); G_add_keyword(_("Landsat")); G_add_keyword(_("atmospheric correction")); module->overwrite = TRUE; /* It defines the different parameters */ input_prefix = G_define_standard_option(G_OPT_R_BASENAME_INPUT); input_prefix->label = _("Base name of input raster bands"); input_prefix->description = _("Example: 'B.' for B.1, B.2, ..."); output_prefix = G_define_standard_option(G_OPT_R_BASENAME_OUTPUT); output_prefix->label = _("Prefix for output raster maps"); output_prefix->description = _("Example: 'B.toar.' generates B.toar.1, B.toar.2, ..."); metfn = G_define_standard_option(G_OPT_F_INPUT); metfn->key = "metfile"; metfn->required = NO; metfn->description = _("Name of Landsat metadata file (.met or MTL.txt)"); metfn->guisection = _("Metadata"); sensor = G_define_option(); sensor->key = "sensor"; sensor->type = TYPE_STRING; sensor->label = _("Spacecraft sensor"); sensor->description = _("Required only if 'metfile' not given (recommended for sanity)"); sensor->options = "mss1,mss2,mss3,mss4,mss5,tm4,tm5,tm7,oli8"; desc = NULL; G_asprintf(&desc, "mss1;%s;mss2;%s;mss3;%s;mss4;%s;mss5;%s;tm4;%s;tm5;%s;tm7;%s;oli8;%s", _("Landsat-1 MSS"), _("Landsat-2 MSS"), _("Landsat-3 MSS"), _("Landsat-4 MSS"), _("Landsat-5 MSS"), _("Landsat-4 TM"), _("Landsat-5 TM"), _("Landsat-7 ETM+"), _("Landsat_8 OLI/TIRS")); sensor->descriptions = desc; sensor->required = NO; /* perhaps YES for clarity */ sensor->guisection = _("Metadata"); metho = G_define_option(); metho->key = "method"; metho->type = TYPE_STRING; metho->required = NO; metho->options = "uncorrected,dos1,dos2,dos2b,dos3,dos4"; metho->label = _("Atmospheric correction method"); metho->description = _("Atmospheric correction method"); metho->answer = "uncorrected"; metho->guisection = _("Metadata"); adate = G_define_option(); adate->key = "date"; adate->type = TYPE_STRING; adate->required = NO; adate->key_desc = "yyyy-mm-dd"; adate->label = _("Image acquisition date (yyyy-mm-dd)"); adate->description = _("Required only if 'metfile' not given"); adate->guisection = _("Metadata"); elev = G_define_option(); elev->key = "sun_elevation"; elev->type = TYPE_DOUBLE; elev->required = NO; elev->label = _("Sun elevation in degrees"); elev->description = _("Required only if 'metfile' not given"); elev->guisection = _("Metadata"); pdate = G_define_option(); pdate->key = "product_date"; pdate->type = TYPE_STRING; pdate->required = NO; pdate->key_desc = "yyyy-mm-dd"; pdate->label = _("Image creation date (yyyy-mm-dd)"); pdate->description = _("Required only if 'metfile' not given"); pdate->guisection = _("Metadata"); bgain = G_define_option(); bgain->key = "gain"; bgain->type = TYPE_STRING; bgain->required = NO; bgain->label = _("Gain (H/L) of all Landsat ETM+ bands (1-5,61,62,7,8)"); bgain->description = _("Required only if 'metfile' not given"); bgain->guisection = _("Settings"); perc = G_define_option(); perc->key = "percent"; perc->type = TYPE_DOUBLE; perc->required = NO; perc->label = _("Percent of solar radiance in path radiance"); perc->description = _("Required only if 'method' is any DOS"); perc->answer = "0.01"; perc->guisection = _("Settings"); dark = G_define_option(); dark->key = "pixel"; dark->type = TYPE_INTEGER; dark->required = NO; dark->label = _("Minimum pixels to consider digital number as dark object"); dark->description = _("Required only if 'method' is any DOS"); dark->answer = "1000"; dark->guisection = _("Settings"); atmo = G_define_option(); atmo->key = "rayleigh"; atmo->type = TYPE_DOUBLE; atmo->required = NO; atmo->label = _("Rayleigh atmosphere (diffuse sky irradiance)"); /* scattering coefficient? */ atmo->description = _("Required only if 'method' is DOS3"); atmo->answer = "0.0"; atmo->guisection = _("Settings"); lsatmet = G_define_option(); lsatmet->key = "lsatmet"; lsatmet->type = TYPE_STRING; lsatmet->required = NO; lsatmet->multiple = YES; lsatmet->label = _("return value stored for a given metadata"); lsatmet->description = _("Required only if 'metfile' and -p given"); lsatmet->options = "number,creation,date,sun_elev,sensor,bands,sunaz,time"; desc = NULL; G_asprintf(&desc, "number;%s;creation;%s;date;%s;sun_elev;%s;sensor;%s;bands;%s;sunaz;%s;time;%s", _("Landsat Number"), _("Creation timestamp"), _("Date"), _("Sun Elevation"), _("Sensor"), _("Bands count"), _("Sun Azimuth Angle"), _("Time")); lsatmet->descriptions = desc; lsatmet->guisection = _("Settings"); oscale = G_define_option(); oscale->key = "scale"; oscale->type = TYPE_DOUBLE; oscale->answer = "1.0"; oscale->required = NO; oscale->description = _("Scale factor for output"); /* define the different flags */ frad = G_define_flag(); frad->key = 'r'; frad->description = _("Output at-sensor radiance instead of reflectance for all bands"); named = G_define_flag(); named->key = 'n'; named->description = _("Input raster maps use as extension the number of the band instead the code"); print_meta = G_define_flag(); print_meta->key = 'p'; print_meta->description = _("Print output metadata info"); /* options and afters parser */ if (G_parser(argc, argv)) exit(EXIT_FAILURE); /***************************************** * ---------- START -------------------- * Stores options and flags to variables *****************************************/ met = metfn->answer; inputname = input_prefix->answer; outputname = output_prefix->answer; sensorname = sensor->answer ? sensor->answer : ""; overwrite = G_check_overwrite(argc, argv); Rast_get_window(&orig_cellhd); G_zero(&lsat, sizeof(lsat)); if (adate->answer != NULL) { strncpy(lsat.date, adate->answer, 11); lsat.date[10] = '\0'; if (strlen(lsat.date) != 10) G_fatal_error(_("Illegal date format: [%s] (yyyy-mm-dd)"), lsat.date); } if (pdate->answer != NULL) { strncpy(lsat.creation, pdate->answer, 11); lsat.creation[10] = '\0'; if (strlen(lsat.creation) != 10) G_fatal_error(_("Illegal date format: [%s] (yyyy-mm-dd)"), lsat.creation); } lsat.sun_elev = elev->answer == NULL ? 0. : atof(elev->answer); percent = atof(perc->answer); pixel = atoi(dark->answer); rayleigh = atof(atmo->answer); scale = atof(oscale->answer); /* * Data from metadata file */ lsat.flag = NOMETADATAFILE; /* Unnecessary because G_zero filled, but for sanity */ if (met != NULL) { lsat.flag = METADATAFILE; lsat_metadata(met, &lsat); if (print_meta->answer) { char *lsatmeta; if (lsatmet->answer == NULL) { G_fatal_error(_("Please use a metadata keyword with -p")); } for (i = 0; lsatmet->answers[i] != NULL; i++) { lsatmeta = lsatmet->answers[i]; if (strcmp(lsatmeta, "number") == 0) { fprintf(stdout, "number=%d\n", lsat.number); } if (strcmp(lsatmeta, "creation") == 0) { fprintf(stdout, "creation=%s\n", lsat.creation); } if (strcmp(lsatmeta, "date") == 0) { fprintf(stdout, "date=%s\n", lsat.date); } if (strcmp(lsatmeta, "sun_elev") == 0) { fprintf(stdout, "sun_elev=%f\n", lsat.sun_elev); } if (strcmp(lsatmeta, "sunaz") == 0) { fprintf(stdout, "sunaz=%f\n", lsat.sun_az); } if (strcmp(lsatmeta, "sensor") == 0) { fprintf(stdout, "sensor=%s\n", lsat.sensor); } if (strcmp(lsatmeta, "bands") == 0) { fprintf(stdout, "bands=%d\n", lsat.bands); } if (strcmp(lsatmet->answer, "time") == 0) { fprintf(stdout, "%f\n", lsat.time); } } exit(EXIT_SUCCESS); } G_debug(1, "lsat.number = %d, lsat.sensor = [%s]", lsat.number, lsat.sensor); if (!lsat.sensor || lsat.number > 8 || lsat.number < 1) G_fatal_error(_("Failed to identify satellite")); G_debug(1, "Landsat-%d %s with data set in metadata file [%s]", lsat.number, lsat.sensor, met); if (elev->answer != NULL) { lsat.sun_elev = atof(elev->answer); G_warning("Overwriting solar elevation of metadata file"); } } /* * Data from command line */ else if (adate->answer == NULL || elev->answer == NULL) { G_fatal_error(_("Lacking '%s' and/or '%s' for this satellite"), adate->key, elev->key); } else { if (strcmp(sensorname, "tm7") == 0) { if (bgain->answer == NULL || strlen(bgain->answer) != 9) G_fatal_error(_("Landsat-7 requires band gain with 9 (H/L) characters")); set_ETM(&lsat, bgain->answer); } else if (strcmp(sensorname, "oli8") == 0) set_OLI(&lsat); else if (strcmp(sensorname, "tm5") == 0) set_TM5(&lsat); else if (strcmp(sensorname, "tm4") == 0) set_TM4(&lsat); else if (strcmp(sensorname, "mss5") == 0) set_MSS5(&lsat); else if (strcmp(sensorname, "mss4") == 0) set_MSS4(&lsat); else if (strcmp(sensorname, "mss3") == 0) set_MSS3(&lsat); else if (strcmp(sensorname, "mss2") == 0) set_MSS2(&lsat); else if (strcmp(sensorname, "mss1") == 0) set_MSS1(&lsat); else G_fatal_error(_("Unknown satellite type (defined by '%s')"), sensorname); } /***************************************** * ------------ PREPARATION -------------- *****************************************/ if (strcasecmp(metho->answer, "corrected") == 0) /* deleted 2013 */ method = CORRECTED; else if (strcasecmp(metho->answer, "dos1") == 0) method = DOS1; else if (strcasecmp(metho->answer, "dos2") == 0) method = DOS2; else if (strcasecmp(metho->answer, "dos2b") == 0) method = DOS2b; else if (strcasecmp(metho->answer, "dos3") == 0) method = DOS3; else if (strcasecmp(metho->answer, "dos4") == 0) method = DOS4; else method = UNCORRECTED; /* if (metho->answer[3] == '2') method = (metho->answer[4] == '\0') ? DOS2 : DOS2b; else if (metho->answer[3] == '1') method = DOS1; else if (metho->answer[3] == '3') method = DOS3; else if (metho->answer[3] == '4') method = DOS4; else method = UNCORRECTED; */ for (i = 0; i < lsat.bands; i++) { dn_mode[i] = 0; dn_dark[i] = (int)lsat.band[i].qcalmin; dn_sat = (int)(0.90 * lsat.band[i].qcalmax); /* Begin: calculate dark pixel */ if (method > DOS && !lsat.band[i].thermal) { for (q = 0; q <= lsat.band[i].qcalmax; q++) hist[q] = 0L; sprintf(band_in, "%s%d", inputname, lsat.band[i].code); Rast_get_cellhd(band_in, "", &cellhd); Rast_set_window(&cellhd); if ((infd = Rast_open_old(band_in, "")) < 0) G_fatal_error(_("Unable to open raster map <%s>"), band_in); in_data_type = Rast_get_map_type(infd); if (in_data_type < 0) G_fatal_error(_("Unable to read data type of raster map <%s>"), band_in); inrast = Rast_allocate_buf(in_data_type); nrows = Rast_window_rows(); ncols = Rast_window_cols(); G_message("Calculating dark pixel of <%s>... ", band_in); for (row = 0; row < nrows; row++) { Rast_get_row(infd, inrast, row, in_data_type); for (col = 0; col < ncols; col++) { switch (in_data_type) { case CELL_TYPE: ptr = (void *)((CELL *) inrast + col); q = (int)*((CELL *) ptr); break; case FCELL_TYPE: ptr = (void *)((FCELL *) inrast + col); q = (int)*((FCELL *) ptr); break; case DCELL_TYPE: ptr = (void *)((DCELL *) inrast + col); q = (int)*((DCELL *) ptr); break; default: ptr = NULL; q = -1.; } if (!Rast_is_null_value(ptr, in_data_type) && q >= lsat.band[i].qcalmin && q <= lsat.band[i].qcalmax) hist[q]++; } } /* DN of dark object */ for (j = lsat.band[i].qcalmin; j <= lsat.band[i].qcalmax; j++) { if (hist[j] >= (unsigned int)pixel) { dn_dark[i] = j; break; } } /* Mode of DN (exclude potentially saturated) */ h_max = 0L; for (j = lsat.band[i].qcalmin; j < dn_sat; j++) { /* G_debug(5, "%d-%ld", j, hist[j]); */ if (hist[j] > h_max) { h_max = hist[j]; dn_mode[i] = j; } } G_verbose_message ("... DN = %.2d [%lu] : mode %.2d [%lu], excluding DN > %d", dn_dark[i], hist[dn_dark[i]], dn_mode[i], hist[dn_mode[i]], dn_sat); G_free(inrast); Rast_close(infd); } /* End: calculate dark pixel */ /* Calculate transformation constants */ lsat_bandctes(&lsat, i, method, percent, dn_dark[i], rayleigh); } /* * unnecessary or necessary with more checking as acquisition date,... * if (strlen(lsat.creation) == 0) * G_fatal_error(_("Unknown production date (defined by '%s')"), pdate->key); */ if (G_verbose() > G_verbose_std()) { fprintf(stderr, "\n LANDSAT: %d SENSOR: %s\n", lsat.number, lsat.sensor); fprintf(stderr, " ACQUISITION DATE %s [production date %s]\n", lsat.date, lsat.creation); fprintf(stderr, " Earth-sun distance = %.8lf\n", lsat.dist_es); fprintf(stderr, " Solar elevation angle = %.8lf\n", lsat.sun_elev); fprintf(stderr, " Atmospheric correction: %s\n", (method == UNCORRECTED ? "UNCORRECTED" : metho->answer)); if (method > DOS) { fprintf(stderr, " Percent of solar irradiance in path radiance = %.4lf\n", percent); } for (i = 0; i < lsat.bands; i++) { fprintf(stderr, "-------------------\n"); fprintf(stderr, " BAND %d %s(code %d)\n", lsat.band[i].number, (lsat.band[i].thermal ? "thermal " : ""), lsat.band[i].code); fprintf(stderr, " calibrated digital number (DN): %.1lf to %.1lf\n", lsat.band[i].qcalmin, lsat.band[i].qcalmax); fprintf(stderr, " calibration constants (L): %.5lf to %.5lf\n", lsat.band[i].lmin, lsat.band[i].lmax); fprintf(stderr, " at-%s radiance = %.8lf * DN + %.5lf\n", (method > DOS ? "surface" : "sensor"), lsat.band[i].gain, lsat.band[i].bias); if (lsat.band[i].thermal) { fprintf(stderr, " at-sensor temperature = %.5lf / log[(%.5lf / radiance) + 1.0]\n", lsat.band[i].K2, lsat.band[i].K1); } else { fprintf(stderr, " mean solar exoatmospheric irradiance (ESUN): %.5lf\n", lsat.band[i].esun); fprintf(stderr, " at-%s reflectance = radiance / %.5lf\n", (method > DOS ? "surface" : "sensor"), lsat.band[i].K1); if (method > DOS) { fprintf(stderr, " the darkness DN with a least %d pixels is %d\n", pixel, dn_dark[i]); fprintf(stderr, " the DN mode is %d\n", dn_mode[i]); } } } fprintf(stderr, "-------------------\n"); fflush(stderr); } /***************************************** * ------------ CALCULUS ----------------- *****************************************/ G_message(_("Calculating...")); for (i = 0; i < lsat.bands; i++) { sprintf(band_in, "%s%d", inputname, (named->answer ? lsat.band[i].number : lsat.band[i].code)); sprintf(band_out, "%s%d", outputname, lsat.band[i].code); /* set same size as original band raster */ Rast_get_cellhd(band_in, "", &cellhd); Rast_set_window(&cellhd); if ((infd = Rast_open_old(band_in, "")) < 0) G_fatal_error(_("Unable to open raster map <%s>"), band_in); if (G_find_raster2(band_out, "")) { if (overwrite) { G_warning(_("Raster map <%s> already exists and will be overwritten"), band_out); } else { G_warning(_("Raster map <%s> exists. Skipping."), band_out); continue; } } in_data_type = Rast_get_map_type(infd); if (in_data_type < 0) G_fatal_error(_("Unable to read data type of raster map <%s>"), band_in); /* controlling, if we can write the raster */ if (G_legal_filename(band_out) < 0) G_fatal_error(_("<%s> is an illegal file name"), band_out); if ((outfd = Rast_open_new(band_out, DCELL_TYPE)) < 0) G_fatal_error(_("Unable to create raster map <%s>"), band_out); /* allocate input and output buffer */ inrast = Rast_allocate_buf(in_data_type); outrast = Rast_allocate_buf(DCELL_TYPE); nrows = Rast_window_rows(); ncols = Rast_window_cols(); G_important_message(_("Writing %s of <%s> to <%s>..."), (frad-> answer ? _("radiance") : (lsat.band[i]. thermal) ? _("temperature") : _("reflectance")), band_in, band_out); for (row = 0; row < nrows; row++) { G_percent(row, nrows, 2); Rast_get_row(infd, inrast, row, in_data_type); for (col = 0; col < ncols; col++) { switch (in_data_type) { case CELL_TYPE: ptr = (void *)((CELL *) inrast + col); qcal = (double)((CELL *) inrast)[col]; break; case FCELL_TYPE: ptr = (void *)((FCELL *) inrast + col); qcal = (double)((FCELL *) inrast)[col]; break; case DCELL_TYPE: ptr = (void *)((DCELL *) inrast + col); qcal = (double)((DCELL *) inrast)[col]; break; default: ptr = NULL; qcal = -1.; } if (Rast_is_null_value(ptr, in_data_type) || qcal < lsat.band[i].qcalmin) { Rast_set_d_null_value((DCELL *) outrast + col, 1); } else { rad = lsat_qcal2rad(qcal, &lsat.band[i]); if (frad->answer) { ref = rad; } else { if (lsat.band[i].thermal) { ref = lsat_rad2temp(rad, &lsat.band[i]); } else { ref = lsat_rad2ref(rad, &lsat.band[i]) * scale; if (ref < 0. && method > DOS) ref = 0.; } } ((DCELL *) outrast)[col] = ref; } } Rast_put_row(outfd, outrast, DCELL_TYPE); } G_percent(1, 1, 1); ref_mode = 0.; if (method > DOS && !lsat.band[i].thermal) { ref_mode = lsat_qcal2rad(dn_mode[i], &lsat.band[i]); ref_mode = lsat_rad2ref(ref_mode, &lsat.band[i]); } G_free(inrast); Rast_close(infd); G_free(outrast); Rast_close(outfd); /* * needed? * if (out_type != CELL_TYPE) * G_quantize_fp_map_range(band_out, G_mapset(), 0., 360., 0, * 360); */ /* set grey255 colortable */ Rast_init_colors(&colors); Rast_read_fp_range(band_out, G_mapset(), &range); Rast_get_fp_range_min_max(&range, &min, &max); Rast_make_grey_scale_fp_colors(&colors, min, max); Rast_write_colors(band_out, G_mapset(), &colors); /* Initialize the 'history' structure with basic info */ Rast_short_history(band_out, "raster", &history); Rast_append_format_history(&history, " %s of Landsat-%d %s (method %s)", (frad-> answer ? "Radiance" : (lsat.band[i]. thermal ? "Temperature" : "Reflectance")), lsat.number, lsat.sensor, metho->answer); Rast_append_history(&history, "-----------------------------------------------------------------"); Rast_append_format_history(&history, " Acquisition date (and time) ........... %s (%.4lf h)", lsat.date, lsat.time); Rast_append_format_history(&history, " Production date ....................... %s\n", lsat.creation); Rast_append_format_history(&history, " Earth-sun distance (d) ................ %.7lf", lsat.dist_es); Rast_append_format_history(&history, " Sun elevation (and azimuth) ........... %.5lf (%.5lf)", lsat.sun_elev, lsat.sun_az); Rast_append_format_history(&history, " Digital number (DN) range ............. %.0lf to %.0lf", lsat.band[i].qcalmin, lsat.band[i].qcalmax); Rast_append_format_history(&history, " Calibration constants (Lmin to Lmax) .. %+.5lf to %+.5lf", lsat.band[i].lmin, lsat.band[i].lmax); Rast_append_format_history(&history, " DN to Radiance (gain and bias) ........ %+.5lf and %+.5lf", lsat.band[i].gain, lsat.band[i].bias); if (lsat.band[i].thermal) { Rast_append_format_history(&history, " Temperature (K1 and K2) ............... %.3lf and %.3lf", lsat.band[i].K1, lsat.band[i].K2); } else { Rast_append_format_history(&history, " Mean solar irradiance (ESUN) .......... %.3lf", lsat.band[i].esun); Rast_append_format_history(&history, " Radiance to Reflectance (divide by) ... %+.5lf", lsat.band[i].K1); if (method > DOS) { Rast_append_format_history(&history, " "); Rast_append_format_history(&history, " Dark object (%4d pixels) DN = ........ %d", pixel, dn_dark[i]); Rast_append_format_history(&history, " Mode in reflectance histogram ......... %.5lf", ref_mode); } } Rast_append_history(&history, "------------------------------------------------------------------"); Rast_command_history(&history); Rast_write_history(band_out, &history); if (lsat.band[i].thermal) Rast_write_units(band_out, "Kelvin"); else if (frad->answer) Rast_write_units(band_out, "W/(m^2 sr um)"); else Rast_write_units(band_out, "unitless"); /* set raster timestamp from acq date? (see r.timestamp module) */ } Rast_set_window(&orig_cellhd); exit(EXIT_SUCCESS); }
int main(int argc, char **argv) { char *map_name; int color; int lines; int cols; struct FPRange fp_range; struct Colors colors; double ratio; DCELL dmin, dmax, dval; int cats_num; int cur_dot_row, cur_dot_col; int dots_per_line, dots_per_col; int atcat; int white, black; int atcol, atline; int count, offset; double t, b, l, r; int fp, new_colr; double x_box[5], y_box[5]; struct GModule *module; struct Option *opt1, *opt2, *opt3, *opt4; struct Flag *skip_null; /* Initialize the GIS calls */ G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("display")); G_add_keyword(_("raster")); module->description = _("Displays the color table associated with a raster map layer."); opt1 = G_define_standard_option(G_OPT_R_MAP); opt1->description = _("Name of raster map whose color table is to be displayed"); opt2 = G_define_option(); opt2->key = "color"; opt2->type = TYPE_STRING; opt2->answer = DEFAULT_BG_COLOR; opt2->gisprompt = "old_color,color,color"; opt2->description = _("Color of lines separating the colors of the color table"); opt3 = G_define_option(); opt3->key = "lines"; opt3->type = TYPE_INTEGER; opt3->options = "1-1000"; opt3->description = _("Number of lines to appear in the color table"); opt4 = G_define_option(); opt4->key = "cols"; opt4->type = TYPE_INTEGER; opt4->options = "1-1000"; opt4->description = _("Number of columns to appear in the color table"); skip_null = G_define_flag(); skip_null->key = 'n'; skip_null->description = _("Don't draw a collar showing the NULL color in FP maps"); /* Check command line */ if (G_parser(argc, argv)) exit(EXIT_FAILURE); map_name = opt1->answer; fp = Rast_map_is_fp(map_name, ""); if (opt2->answer != NULL) { new_colr = D_translate_color(opt2->answer); color = new_colr; } if (fp) lines = 1; else lines = 0; if (opt3->answer != NULL) { if (fp) G_warning(_("<%s> is floating-point; " "ignoring [lines] and drawing continuous color ramp"), map_name); else sscanf(opt3->answer, "%d", &lines); } if (fp) cols = 1; else cols = 0; if (opt4->answer) { if (fp) G_warning(_("<%s> is floating-point; " "ignoring [cols] and drawing continuous color ramp"), map_name); else sscanf(opt4->answer, "%d", &cols); } /* Make sure map is available */ if (Rast_read_colors(map_name, "", &colors) == -1) G_fatal_error(_("Color file for <%s> not available"), map_name); if (Rast_read_fp_range(map_name, "", &fp_range) == -1) G_fatal_error(_("Range file for <%s> not available"), map_name); if (D_open_driver() != 0) G_fatal_error(_("No graphics device selected. " "Use d.mon to select graphics device.")); D_setup_unity(0); D_get_src(&t, &b, &l, &r); Rast_get_fp_range_min_max(&fp_range, &dmin, &dmax); if (Rast_is_d_null_value(&dmin) || Rast_is_d_null_value(&dmax)) G_fatal_error(_("Data range is empty")); cats_num = (int)dmax - (int)dmin + 1; if (lines <= 0 && cols <= 0) { double dx, dy; dy = (double)(b - t); dx = (double)(r - l); ratio = dy / dx; cols = 1 + sqrt((dmax - dmin + 1.) / ratio); lines = 1 + cats_num / cols; } else if (lines > 0 && cols <= 0) { cols = 1 + cats_num / lines; } else if (cols > 0 && lines <= 0) { lines = 1 + cats_num / cols; } /* otherwise, accept without complaint what the user requests * It is possible that the number of lines and cols is not * sufficient for the number of categories. */ dots_per_line = (b - t) / lines; dots_per_col = (r - l) / cols; x_box[0] = 0; y_box[0] = 0; x_box[1] = 0; y_box[1] = (6 - dots_per_line); x_box[2] = (dots_per_col - 6); y_box[2] = 0; x_box[3] = 0; y_box[3] = (dots_per_line - 6); x_box[4] = (6 - dots_per_col); y_box[4] = 0; white = D_translate_color("white"); black = D_translate_color("black"); Rast_set_c_null_value(&atcat, 1); if (!fp) { for (atcol = 0; atcol < cols; atcol++) { cur_dot_row = t; cur_dot_col = l + atcol * dots_per_col; count = 0; for (atline = 0; atline < lines; atline++) { cur_dot_row += dots_per_line; /* Draw outer border box */ D_use_color(color); D_begin(); D_move_abs(cur_dot_col + 2, (cur_dot_row - 1)); D_cont_rel(0, (2 - dots_per_line)); D_cont_rel((dots_per_col - 2), 0); D_cont_rel(0, (dots_per_line - 2)); D_cont_rel((2 - dots_per_col), 0); D_end(); D_stroke(); /* Draw black box */ D_use_color(black); D_begin(); D_move_abs(cur_dot_col + 3, (cur_dot_row - 2)); D_cont_rel(0, (4 - dots_per_line)); D_cont_rel((dots_per_col - 4), 0); D_cont_rel(0, (dots_per_line - 4)); D_cont_rel((4 - dots_per_col), 0); D_end(); D_stroke(); /* Color box */ D_color((CELL) atcat, &colors); D_pos_abs(cur_dot_col + 4, (cur_dot_row - 3)); D_polygon_rel(x_box, y_box, 5); count++; /* first cat number is null value */ if (count == 1) atcat = (int)dmin; else if (++atcat > (int)dmax) break; } if (atcat > (int)dmax) break; } /* col loop */ } /* int map */ else { /*** draw continuous color ramp for fp map ***/ cur_dot_row = t + dots_per_line; cur_dot_col = l; /* Draw outer border box */ D_use_color(color); D_begin(); D_move_abs(cur_dot_col + 1, (cur_dot_row - 1)); D_cont_rel(0, (2 - dots_per_line)); D_cont_rel((dots_per_col - 2), 0); D_cont_rel(0, (dots_per_line - 2)); D_cont_rel((2 - dots_per_col), 0); D_end(); D_stroke(); /* Draw black box */ D_use_color(black); D_begin(); D_move_abs(cur_dot_col + 2, (cur_dot_row - 2)); D_cont_rel(0, (4 - dots_per_line)); D_cont_rel((dots_per_col - 4), 0); D_cont_rel(0, (dots_per_line - 4)); D_cont_rel((4 - dots_per_col), 0); D_end(); D_stroke(); /* Color ramp box */ /* get separate color for each pixel */ /* fisrt 5 pixels draw null color */ y_box[1] = -1; y_box[3] = 1; x_box[2] = (dots_per_col - 6); x_box[4] = (6 - dots_per_col); G_debug(1, "dots_per_line: %d dmin=%.2f dmax=%.2f", dots_per_line, dmin, dmax); if (skip_null->answer) offset = 1; else offset = 4; for (r = 0; r < dots_per_line - 6; r++) { if ((r <= 4) && !skip_null->answer) Rast_set_d_null_value(&dval, 1); else dval = dmin + r*(dmax - dmin) / (dots_per_line - 6 - offset); D_d_color(dval, &colors); D_pos_abs(cur_dot_col + 3, (cur_dot_row - 3) - r); D_polygon_rel(x_box, y_box, 5); } } D_save_command(G_recreate_command()); D_close_driver(); exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { extern struct Cell_head window; union RASTER_PTR elevbuf, tmpbuf, outbuf; CELL min, max; DCELL dvalue, dvalue2, dmin, dmax; struct History hist; RASTER_MAP_TYPE data_type; struct Range range; struct FPRange fprange; double drow, dcol; int elev_fd, output_fd, zeros; struct { struct Option *opt1, *opt2, *opt3, *opt4, *north, *east, *year, *month, *day, *hour, *minutes, *seconds, *timezone; } parm; struct Flag *flag1, *flag3, *flag4; struct GModule *module; char *name, *outname; double dazi, dalti; double azi, alti; double nstep, estep; double maxh; double east, east1, north, north1; int row1, col1; char OK; double timezone; int year, month, day, hour, minutes, seconds; long retval; int solparms, locparms, use_solpos; double sunrise, sunset, current_time; int sretr = 0, ssetr = 0, sretr_sec = 0, ssetr_sec = 0; double dsretr, dssetr; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("raster")); G_add_keyword(_("sun position")); module->label = _("Calculates cast shadow areas from sun position and elevation raster map."); module->description = _("Either exact sun position (A) is specified, or date/time to calculate " "the sun position (B) by r.sunmask itself."); parm.opt1 = G_define_standard_option(G_OPT_R_ELEV); parm.opt2 = G_define_standard_option(G_OPT_R_OUTPUT); parm.opt2->required = NO; parm.opt3 = G_define_option(); parm.opt3->key = "altitude"; parm.opt3->type = TYPE_DOUBLE; parm.opt3->required = NO; parm.opt3->options = "0-89.999"; parm.opt3->description = _("Altitude of the sun above horizon, degrees (A)"); parm.opt3->guisection = _("Position"); parm.opt4 = G_define_option(); parm.opt4->key = "azimuth"; parm.opt4->type = TYPE_DOUBLE; parm.opt4->required = NO; parm.opt4->options = "0-360"; parm.opt4->description = _("Azimuth of the sun from the north, degrees (A)"); parm.opt4->guisection = _("Position"); parm.year = G_define_option(); parm.year->key = "year"; parm.year->type = TYPE_INTEGER; parm.year->required = NO; parm.year->description = _("Year (B)"); parm.year->options = "1950-2050"; parm.year->guisection = _("Time"); parm.month = G_define_option(); parm.month->key = "month"; parm.month->type = TYPE_INTEGER; parm.month->required = NO; parm.month->description = _("Month (B)"); parm.month->options = "0-12"; parm.month->guisection = _("Time"); parm.day = G_define_option(); parm.day->key = "day"; parm.day->type = TYPE_INTEGER; parm.day->required = NO; parm.day->description = _("Day (B)"); parm.day->options = "0-31"; parm.day->guisection = _("Time"); parm.hour = G_define_option(); parm.hour->key = "hour"; parm.hour->type = TYPE_INTEGER; parm.hour->required = NO; parm.hour->description = _("Hour (B)"); parm.hour->options = "0-24"; parm.hour->guisection = _("Time"); parm.minutes = G_define_option(); parm.minutes->key = "minute"; parm.minutes->type = TYPE_INTEGER; parm.minutes->required = NO; parm.minutes->description = _("Minutes (B)"); parm.minutes->options = "0-60"; parm.minutes->guisection = _("Time"); parm.seconds = G_define_option(); parm.seconds->key = "second"; parm.seconds->type = TYPE_INTEGER; parm.seconds->required = NO; parm.seconds->description = _("Seconds (B)"); parm.seconds->options = "0-60"; parm.seconds->guisection = _("Time"); parm.timezone = G_define_option(); parm.timezone->key = "timezone"; parm.timezone->type = TYPE_INTEGER; parm.timezone->required = NO; parm.timezone->label = _("Timezone"); parm.timezone->description = _("East positive, offset from GMT, also use to adjust daylight savings"); parm.timezone->guisection = _("Time"); parm.east = G_define_option(); parm.east->key = "east"; parm.east->key_desc = "value"; parm.east->type = TYPE_STRING; parm.east->required = NO; parm.east->label = _("Easting coordinate (point of interest)"); parm.east->description = _("Default: map center"); parm.east->guisection = _("Position"); parm.north = G_define_option(); parm.north->key = "north"; parm.north->key_desc = "value"; parm.north->type = TYPE_STRING; parm.north->required = NO; parm.north->label = _("Northing coordinate (point of interest)"); parm.north->description = _("Default: map center"); parm.north->guisection = _("Position"); flag1 = G_define_flag(); flag1->key = 'z'; flag1->description = _("Don't ignore zero elevation"); flag3 = G_define_flag(); flag3->key = 's'; flag3->description = _("Calculate sun position only and exit"); flag3->guisection = _("Print"); flag4 = G_define_flag(); flag4->key = 'g'; flag4->description = _("Print the sun position output in shell script style"); flag4->guisection = _("Print"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); zeros = flag1->answer; G_get_window(&window); /* if not given, get east and north: XX */ if (!parm.north->answer || !parm.east->answer) { north = (window.north - window.south) / 2. + window.south; east = (window.west - window.east) / 2. + window.east; G_verbose_message(_("Using map center coordinates: %f %f"), east, north); } else { /* user defined east, north: */ sscanf(parm.north->answer, "%lf", &north); sscanf(parm.east->answer, "%lf", &east); if (strlen(parm.east->answer) == 0) G_fatal_error(_("Empty east coordinate specified")); if (strlen(parm.north->answer) == 0) G_fatal_error(_("Empty north coordinate specified")); } /* check which method to use for sun position: either user defines directly sun position or it is calculated */ if (parm.opt3->answer && parm.opt4->answer) solparms = 1; /* opt3 & opt4 complete */ else solparms = 0; /* calculate sun position */ if (parm.year->answer && parm.month->answer && parm.day->answer && parm.hour->answer && parm.minutes->answer && parm.seconds->answer && parm.timezone->answer) locparms = 1; /* complete */ else locparms = 0; if (solparms && locparms) /* both defined */ G_fatal_error(_("Either define sun position or location/date/time parameters")); if (!solparms && !locparms) /* nothing defined */ G_fatal_error(_("Neither sun position nor east/north, date/time/timezone definition are complete")); /* if here, one definition was complete */ if (locparms) { G_message(_("Calculating sun position... (using solpos (V. %s) from NREL)"), SOLPOSVERSION); use_solpos = 1; } else { G_message(_("Using user defined sun azimuth, altitude settings (ignoring eventual other values)")); use_solpos = 0; } name = parm.opt1->answer; outname = parm.opt2->answer; if (!use_solpos) { sscanf(parm.opt3->answer, "%lf", &dalti); sscanf(parm.opt4->answer, "%lf", &dazi); } else { sscanf(parm.year->answer, "%i", &year); sscanf(parm.month->answer, "%i", &month); sscanf(parm.day->answer, "%i", &day); sscanf(parm.hour->answer, "%i", &hour); sscanf(parm.minutes->answer, "%i", &minutes); sscanf(parm.seconds->answer, "%i", &seconds); sscanf(parm.timezone->answer, "%lf", &timezone); } /* NOTES: G_calc_solar_position () - the algorithm will compensate for leap year. - longitude, latitude: decimal degree - timezone: DO NOT ADJUST FOR DAYLIGHT SAVINGS TIME. - timezone: negative for zones west of Greenwich - lat/long: east and north positive - the atmospheric refraction is calculated for 1013hPa, 15�C - time: local time from your watch Order of parameters: long, lat, timezone, year, month, day, hour, minutes, seconds */ if (use_solpos) { G_debug(3, "\nlat:%f long:%f", north, east); retval = calc_solar_position(east, north, timezone, year, month, day, hour, minutes, seconds); /* Remove +0.5 above if you want round-down instead of round-to-nearest */ sretr = (int)floor(pdat->sretr); /* sunrise */ dsretr = pdat->sretr; sretr_sec = (int) floor(((dsretr - floor(dsretr)) * 60 - floor((dsretr - floor(dsretr)) * 60)) * 60); ssetr = (int)floor(pdat->ssetr); /* sunset */ dssetr = pdat->ssetr; ssetr_sec = (int) floor(((dssetr - floor(dssetr)) * 60 - floor((dssetr - floor(dssetr)) * 60)) * 60); /* print the results */ if (retval == 0) { /* error check */ if (flag3->answer) { if (flag4->answer) { fprintf(stdout, "date=%d/%02d/%02d\n", pdat->year, pdat->month, pdat->day); fprintf(stdout, "daynum=%d\n", pdat->daynum); fprintf(stdout, "time=%02i:%02i:%02i\n", pdat->hour, pdat->minute, pdat->second); fprintf(stdout, "decimaltime=%f\n", pdat->hour + (pdat->minute * 100.0 / 60.0 + pdat->second * 100.0 / 3600.0) / 100.); fprintf(stdout, "longitudine=%f\n", pdat->longitude); fprintf(stdout, "latitude=%f\n", pdat->latitude); fprintf(stdout, "timezone=%f\n", pdat->timezone); fprintf(stdout, "sunazimuth=%f\n", pdat->azim); fprintf(stdout, "sunangleabovehorizon=%f\n", pdat->elevref); if (sretr / 60 <= 24.0) { fprintf(stdout, "sunrise=%02d:%02d:%02d\n", sretr / 60, sretr % 60, sretr_sec); fprintf(stdout, "sunset=%02d:%02d:%02d\n", ssetr / 60, ssetr % 60, ssetr_sec); } } else { fprintf(stdout, "%d/%02d/%02d, daynum: %d, time: %02i:%02i:%02i (decimal time: %f)\n", pdat->year, pdat->month, pdat->day, pdat->daynum, pdat->hour, pdat->minute, pdat->second, pdat->hour + (pdat->minute * 100.0 / 60.0 + pdat->second * 100.0 / 3600.0) / 100.); fprintf(stdout, "long: %f, lat: %f, timezone: %f\n", pdat->longitude, pdat->latitude, pdat->timezone); fprintf(stdout, "Solar position: sun azimuth: %f, sun angle above horz. (refraction corrected): %f\n", pdat->azim, pdat->elevref); if (sretr / 60 <= 24.0) { fprintf(stdout, "Sunrise time (without refraction): %02d:%02d:%02d\n", sretr / 60, sretr % 60, sretr_sec); fprintf(stdout, "Sunset time (without refraction): %02d:%02d:%02d\n", ssetr / 60, ssetr % 60, ssetr_sec); } } } sunrise = pdat->sretr / 60.; /* decimal minutes */ sunset = pdat->ssetr / 60.; current_time = pdat->hour + (pdat->minute / 60.) + (pdat->second / 3600.); } else /* fatal error in G_calc_solar_position() */ G_fatal_error(_("Please correct settings")); } if (use_solpos) { dalti = pdat->elevref; dazi = pdat->azim; } /* otherwise already defined */ /* check sunrise */ if (use_solpos) { G_debug(3, "current_time:%f sunrise:%f", current_time, sunrise); if ((current_time < sunrise)) { if (sretr / 60 <= 24.0) G_message(_("Time (%02i:%02i:%02i) is before sunrise (%02d:%02d:%02d)"), pdat->hour, pdat->minute, pdat->second, sretr / 60, sretr % 60, sretr_sec); else G_message(_("Time (%02i:%02i:%02i) is before sunrise"), pdat->hour, pdat->minute, pdat->second); G_warning(_("Nothing to calculate. Please verify settings.")); } if ((current_time > sunset)) { if (sretr / 60 <= 24.0) G_message(_("Time (%02i:%02i:%02i) is after sunset (%02d:%02d:%02d)"), pdat->hour, pdat->minute, pdat->second, ssetr / 60, ssetr % 60, ssetr_sec); else G_message(_("Time (%02i:%02i:%02i) is after sunset"), pdat->hour, pdat->minute, pdat->second); G_warning(_("Nothing to calculate. Please verify settings.")); } } if (flag3->answer && (use_solpos == 1)) { /* we only want the sun position */ exit(EXIT_SUCCESS); } else if (flag3->answer && (use_solpos == 0)) { /* are you joking ? */ G_message(_("You already know the sun position")); exit(EXIT_SUCCESS); } if (!outname) G_fatal_error(_("Option <%s> required"), parm.opt2->key); elev_fd = Rast_open_old(name, ""); output_fd = Rast_open_c_new(outname); data_type = Rast_get_map_type(elev_fd); elevbuf.v = Rast_allocate_buf(data_type); tmpbuf.v = Rast_allocate_buf(data_type); outbuf.v = Rast_allocate_buf(CELL_TYPE); /* binary map */ if (data_type == CELL_TYPE) { if ((Rast_read_range(name, "", &range)) < 0) G_fatal_error(_("Unable to open range file for raster map <%s>"), name); Rast_get_range_min_max(&range, &min, &max); dmin = (double)min; dmax = (double)max; } else { Rast_read_fp_range(name, "", &fprange); Rast_get_fp_range_min_max(&fprange, &dmin, &dmax); } azi = 2 * M_PI * dazi / 360; alti = 2 * M_PI * dalti / 360; nstep = cos(azi) * window.ns_res; estep = sin(azi) * window.ew_res; row1 = 0; G_message(_("Calculating shadows from DEM...")); while (row1 < window.rows) { G_percent(row1, window.rows, 2); col1 = 0; drow = -1; Rast_get_row(elev_fd, elevbuf.v, row1, data_type); while (col1 < window.cols) { dvalue = raster_value(elevbuf, data_type, col1); /* outbuf.c[col1]=1; */ Rast_set_null_value(&outbuf.c[col1], 1, CELL_TYPE); OK = 1; east = Rast_col_to_easting(col1 + 0.5, &window); north = Rast_row_to_northing(row1 + 0.5, &window); east1 = east; north1 = north; if (dvalue == 0.0 && !zeros) OK = 0; while (OK == 1) { east += estep; north += nstep; if (north > window.north || north < window.south || east > window.east || east < window.west) OK = 0; else { maxh = tan(alti) * sqrt((north1 - north) * (north1 - north) + (east1 - east) * (east1 - east)); if ((maxh) > (dmax - dvalue)) OK = 0; else { dcol = Rast_easting_to_col(east, &window); if (drow != Rast_northing_to_row(north, &window)) { drow = Rast_northing_to_row(north, &window); Rast_get_row(elev_fd, tmpbuf.v, (int)drow, data_type); } dvalue2 = raster_value(tmpbuf, data_type, (int)dcol); if ((dvalue2 - dvalue) > (maxh)) { OK = 0; outbuf.c[col1] = 1; } } } } G_debug(3, "Analysing col %i", col1); col1 += 1; } G_debug(3, "Writing result row %i of %i", row1, window.rows); Rast_put_row(output_fd, outbuf.c, CELL_TYPE); row1 += 1; } G_percent(1, 1, 1); Rast_close(output_fd); Rast_close(elev_fd); /* writing history file */ Rast_short_history(outname, "raster", &hist); Rast_format_history(&hist, HIST_DATSRC_1, "raster elevation map %s", name); Rast_command_history(&hist); Rast_write_history(outname, &hist); exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { struct Categories cats; struct FPRange range; DCELL min, max; RASTER_MAP_TYPE map_type; char buf[1024]; RULE *rules, *tail; int any; const char *old_mapset; FILE *srcfp; int tty; struct GModule *module; struct { struct Option *input, *output, *title, *rules; } parm; /* any interaction must run in a term window */ G_putenv("GRASS_UI_TERM", "1"); G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("raster")); G_add_keyword(_("reclassification")); module->label = _("Reclassify raster map based on category values."); module->description = _("Creates a new raster map whose category values are based " "upon a reclassification of the categories in an existing " "raster map."); parm.input = G_define_standard_option(G_OPT_R_INPUT); parm.input->description = _("Name of raster map to be reclassified"); parm.output = G_define_standard_option(G_OPT_R_OUTPUT); parm.rules = G_define_standard_option(G_OPT_F_INPUT); parm.rules->key = "rules"; parm.rules->label = _("File containing reclass rules"); parm.rules->description = _("'-' for standard input"); parm.title = G_define_option(); parm.title->key = "title"; parm.title->required = NO; parm.title->type = TYPE_STRING; parm.title->description = _("Title for output raster map"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); old_mapset = G_find_raster2(parm.input->answer, ""); if (old_mapset == NULL) G_fatal_error(_("Raster map <%s> not found"), parm.input->answer); if (strcmp(parm.input->answer, parm.output->answer) == 0 && strcmp(old_mapset, G_mapset()) == 0) G_fatal_error(_("Input map can NOT be the same as output map")); srcfp = stdin; if (strcmp(parm.rules->answer, "-") != 0) { srcfp = fopen(parm.rules->answer, "r"); if (!srcfp) G_fatal_error(_("Cannot open rules file <%s>"), parm.rules->answer); } tty = isatty(fileno(srcfp)); Rast_init_cats("", &cats); map_type = Rast_map_type(parm.input->answer, old_mapset); Rast_read_fp_range(parm.input->answer, old_mapset, &range); Rast_get_fp_range_min_max(&range, &min, &max); rules = tail = NULL; any = 0; if (tty) { fprintf(stderr, _("Enter rule(s), \"end\" when done, \"help\" if you need it\n")); if (map_type == FCELL_TYPE) fprintf(stderr, _("FCELL: Data range is %.7g to %.7g\n"), (double)min, (double)max); else if (map_type == DCELL_TYPE) fprintf(stderr, _("DCELL: Data range is %.15g to %.15g\n"), (double)min, (double)max); else fprintf(stderr, _("CELL: Data range is %ld to %ld\n"), (long)min, (long)max); } while (input(srcfp, tty, buf)) { switch (parse(buf, &rules, &tail, &cats)) { case -1: if (tty) { fprintf(stderr, _("Illegal reclass rule -")); fprintf(stderr, _(" ignored\n")); } else { strcat(buf, _(" - invalid reclass rule")); G_fatal_error("%s", buf); } break; case 0: break; default: any = 1; break; } } if (!any) { if (tty) G_fatal_error(_("No rules specified. Raster map <%s> not created"), parm.output->answer); else G_fatal_error(_("No rules specified")); } reclass(parm.input->answer, old_mapset, parm.output->answer, rules, &cats, parm.title->answer); exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { struct Cell_head cellhd; char *name, *result; char **mapname; FCELL **fbuf; int n_measures, n_outputs, *measure_idx; int nrows, ncols; int row, col, first_row, last_row, first_col, last_col; int i, j; CELL **data; /* Data structure containing image */ DCELL *dcell_row; struct FPRange range; DCELL min, max, inscale; FCELL measure; /* Containing measure done */ int dist, size; /* dist = value of distance, size = s. of moving window */ int offset; int have_px, have_py, have_sentr, have_pxpys, have_pxpyd; int infd, *outfd; RASTER_MAP_TYPE data_type, out_data_type; struct GModule *module; struct Option *opt_input, *opt_output, *opt_size, *opt_dist, *opt_measure; struct Flag *flag_ind, *flag_all; struct History history; char p[1024]; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("raster")); G_add_keyword(_("algebra")); G_add_keyword(_("statistics")); G_add_keyword(_("texture")); module->description = _("Generate images with textural features from a raster map."); module->overwrite = 1; /* Define the different options */ opt_input = G_define_standard_option(G_OPT_R_INPUT); opt_output = G_define_standard_option(G_OPT_R_BASENAME_OUTPUT); opt_size = G_define_option(); opt_size->key = "size"; opt_size->key_desc = "value"; opt_size->type = TYPE_INTEGER; opt_size->required = NO; opt_size->description = _("The size of moving window (odd and >= 3)"); opt_size->answer = "3"; /* Textural character is in direct relation of the spatial size of the texture primitives. */ opt_dist = G_define_option(); opt_dist->key = "distance"; opt_dist->key_desc = "value"; opt_dist->type = TYPE_INTEGER; opt_dist->required = NO; opt_dist->description = _("The distance between two samples (>= 1)"); opt_dist->answer = "1"; for (i = 0; menu[i].name; i++) { if (i) strcat(p, ","); else *p = 0; strcat(p, menu[i].name); } opt_measure = G_define_option(); opt_measure->key = "method"; opt_measure->type = TYPE_STRING; opt_measure->required = NO; opt_measure->multiple = YES; opt_measure->options = p; opt_measure->description = _("Textural measurement method"); flag_ind = G_define_flag(); flag_ind->key = 's'; flag_ind->description = _("Separate output for each angle (0, 45, 90, 135)"); flag_all = G_define_flag(); flag_all->key = 'a'; flag_all->description = _("Calculate all textural measurements"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); name = opt_input->answer; result = opt_output->answer; size = atoi(opt_size->answer); if (size <= 0) G_fatal_error(_("Size of the moving window must be > 0")); if (size % 2 != 1) G_fatal_error(_("Size of the moving window must be odd")); dist = atoi(opt_dist->answer); if (dist <= 0) G_fatal_error(_("The distance between two samples must be > 0")); n_measures = 0; if (flag_all->answer) { for (i = 0; menu[i].name; i++) { menu[i].useme = 1; } n_measures = i; } else { for (i = 0; opt_measure->answers[i]; i++) { if (opt_measure->answers[i]) { const char *measure_name = opt_measure->answers[i]; int n = find_measure(measure_name); menu[n].useme = 1; n_measures++; } } } if (!n_measures) G_fatal_error(_("Nothing to compute. Use at least one textural measure.")); measure_idx = G_malloc(n_measures * sizeof(int)); j = 0; for (i = 0; menu[i].name; i++) { if (menu[i].useme == 1) { measure_idx[j] = menu[i].idx; j++; } } /* variables needed */ if (menu[2].useme || menu[11].useme || menu[12].useme) have_px = 1; else have_px = 0; if (menu[11].useme || menu[12].useme) have_py = 1; else have_py = 0; if (menu[6].useme || menu[7].useme) have_sentr = 1; else have_sentr = 0; if (menu[5].useme || menu[6].useme || menu[7].useme) have_pxpys = 1; else have_pxpys = 0; if (menu[9].useme || menu[10].useme) have_pxpyd = 1; else have_pxpyd = 0; infd = Rast_open_old(name, ""); /* determine the inputmap type (CELL/FCELL/DCELL) */ data_type = Rast_get_map_type(infd); Rast_get_cellhd(name, "", &cellhd); out_data_type = FCELL_TYPE; /* Allocate output buffers, use FCELL data_type */ n_outputs = n_measures; if (flag_ind->answer) { n_outputs = n_measures * 4; } fbuf = G_malloc(n_outputs * sizeof(FCELL *)); mapname = G_malloc(n_outputs * sizeof(char *)); for (i = 0; i < n_outputs; i++) { mapname[i] = G_malloc(GNAME_MAX * sizeof(char)); fbuf[i] = Rast_allocate_buf(out_data_type); } /* open output maps */ outfd = G_malloc(n_outputs * sizeof(int)); for (i = 0; i < n_measures; i++) { if (flag_ind->answer) { for (j = 0; j < 4; j++) { sprintf(mapname[i * 4 + j], "%s%s_%d", result, menu[measure_idx[i]].suffix, j * 45); outfd[i * 4 + j] = Rast_open_new(mapname[i * 4 + j], out_data_type); } } else { sprintf(mapname[i], "%s%s", result, menu[measure_idx[i]].suffix); outfd[i] = Rast_open_new(mapname[i], out_data_type); } } nrows = Rast_window_rows(); ncols = Rast_window_cols(); /* Load raster map. */ /* allocate the space for one row of cell map data *A* */ dcell_row = Rast_allocate_d_buf(); /* Allocate appropriate memory for the structure containing the image */ data = (int **)G_malloc(nrows * sizeof(int *)); for (i = 0; i < nrows; i++) { data[i] = (int *)G_malloc(ncols * sizeof(int)); } /* read input range */ Rast_init_fp_range(&range); Rast_read_fp_range(name, "", &range); Rast_get_fp_range_min_max(&range, &min, &max); inscale = 0; if (min < 0 || max > 255) { inscale = 255. / (max - min); } /* input has 0 - 1 range */ else if (max <= 1.) { inscale = 255. / (max - min); } /* Read in cell map values */ /* TODO: use r.proj cache */ G_important_message(_("Reading raster map...")); for (j = 0; j < nrows; j++) { Rast_get_row(infd, dcell_row, j, DCELL_TYPE); for (i = 0; i < ncols; i++) { if (Rast_is_d_null_value(&(dcell_row[i]))) data[j][i] = -1; else if (inscale) { data[j][i] = (CELL)((dcell_row[i] - min) * inscale); } else data[j][i] = (CELL)dcell_row[i]; } } /* close input cell map and release the row buffer */ Rast_close(infd); G_free(dcell_row); /* Now raster map is loaded to memory. */ /* ************************************************************************************************* * * Compute of the matrix S.G.L.D. (Spatial Gray-Level Dependence Matrices) or co-occurrence matrix. * The image is analized for piece, every piece is naming moving window (s.w.). The s.w. must be * square with number of size's samples odd, that because we want the sample at the center of matrix. * ***************************************************************************************************/ offset = size / 2; first_row = first_col = offset; last_row = nrows - offset; last_col = ncols - offset; Rast_set_f_null_value(fbuf[0], ncols); for (row = 0; row < first_row; row++) { for (i = 0; i < n_outputs; i++) { Rast_put_row(outfd[i], fbuf[0], out_data_type); } } if (n_measures > 1) G_message(n_("Calculating %d texture measure", "Calculating %d texture measures", n_measures), n_measures); else G_message(_("Calculating %s"), menu[measure_idx[0]].desc); alloc_vars(size, dist); for (row = first_row; row < last_row; row++) { G_percent(row, nrows, 2); for (i = 0; i < n_outputs; i++) Rast_set_f_null_value(fbuf[i], ncols); /*process the data */ for (col = first_col; col < last_col; col++) { if (!set_vars(data, row, col, size, offset, dist)) { for (i = 0; i < n_outputs; i++) Rast_set_f_null_value(&(fbuf[i][col]), 1); continue; } /* for all angles (0, 45, 90, 135) */ for (i = 0; i < 4; i++) { set_angle_vars(i, have_px, have_py, have_sentr, have_pxpys, have_pxpyd); /* for all requested textural measures */ for (j = 0; j < n_measures; j++) { measure = (FCELL) h_measure(measure_idx[j]); if (flag_ind->answer) { /* output for each angle separately */ fbuf[j * 4 + i][col] = measure; } else { /* use average over all angles for each measure */ if (i == 0) fbuf[j][col] = measure; else if (i < 3) fbuf[j][col] += measure; else fbuf[j][col] = (fbuf[j][col] + measure) / 4.0; } } } } for (i = 0; i < n_outputs; i++) { Rast_put_row(outfd[i], fbuf[i], out_data_type); } } Rast_set_f_null_value(fbuf[0], ncols); for (row = last_row; row < nrows; row++) { for (i = 0; i < n_outputs; i++) { Rast_put_row(outfd[i], fbuf[0], out_data_type); } } G_percent(nrows, nrows, 1); for (i = 0; i < n_outputs; i++) { Rast_close(outfd[i]); Rast_short_history(mapname[i], "raster", &history); Rast_command_history(&history); Rast_write_history(mapname[i], &history); G_free(fbuf[i]); } G_free(fbuf); G_free(data); exit(EXIT_SUCCESS); }
/* exact check for each band * returns 0 on success * -1 if given nodata value was present in data * -2 if selected GDAL datatype could not hold all values * */ int exact_checks(GDALDataType export_datatype, const char *name, const char *mapset, struct Cell_head *cellhead, RASTER_MAP_TYPE maptype, double nodataval, const char *nodatakey, int default_nodataval) { int bHaveMinMax; double dfCellMin; double dfCellMax; struct FPRange sRange; int fd; int cols = cellhead->cols; int rows = cellhead->rows; int ret = 0; /* Open GRASS raster */ fd = Rast_open_old(name, mapset); /* Get min/max values. */ if (Rast_read_fp_range(name, mapset, &sRange) == -1) { bHaveMinMax = FALSE; } else { bHaveMinMax = TRUE; Rast_get_fp_range_min_max(&sRange, &dfCellMin, &dfCellMax); } /* Create GRASS raster buffer */ void *bufer = Rast_allocate_buf(maptype); if (bufer == NULL) { G_warning(_("Unable to allocate buffer for reading raster map")); return -1; } /* the following routine must be kept identical to export_band */ /* Copy data form GRASS raster to GDAL raster */ int row, col; int n_nulls = 0, nodatavalmatch = 0; dfCellMin = TYPE_FLOAT64_MAX; dfCellMax = TYPE_FLOAT64_MIN; /* Better use selected GDAL datatype instead of * the best match with GRASS raster map types ? */ if (maptype == FCELL_TYPE) { FCELL fnullval = (FCELL) nodataval; G_debug(1, "FCELL nodata val: %f", fnullval); for (row = 0; row < rows; row++) { Rast_get_row(fd, bufer, row, maptype); for (col = 0; col < cols; col++) { if (Rast_is_f_null_value(&((FCELL *) bufer)[col])) { n_nulls++; } else { if (((FCELL *) bufer)[col] == fnullval) { nodatavalmatch = 1; } if (dfCellMin > ((FCELL *) bufer)[col]) dfCellMin = ((FCELL *) bufer)[col]; if (dfCellMax < ((FCELL *) bufer)[col]) dfCellMax = ((FCELL *) bufer)[col]; } } G_percent(row + 1, rows, 2); } } else if (maptype == DCELL_TYPE) { DCELL dnullval = (DCELL) nodataval; G_debug(1, "DCELL nodata val: %f", dnullval); for (row = 0; row < rows; row++) { Rast_get_row(fd, bufer, row, maptype); for (col = 0; col < cols; col++) { if (Rast_is_d_null_value(&((DCELL *) bufer)[col])) { ((DCELL *) bufer)[col] = dnullval; n_nulls++; } else { if (((DCELL *) bufer)[col] == dnullval) { nodatavalmatch = 1; } if (dfCellMin > ((DCELL *) bufer)[col]) dfCellMin = ((DCELL *) bufer)[col]; if (dfCellMax < ((DCELL *) bufer)[col]) dfCellMax = ((DCELL *) bufer)[col]; } } G_percent(row + 1, rows, 2); } } else { CELL inullval = (CELL) nodataval; G_debug(1, "CELL nodata val: %d", inullval); for (row = 0; row < rows; row++) { Rast_get_row(fd, bufer, row, maptype); for (col = 0; col < cols; col++) { if (Rast_is_c_null_value(&((CELL *) bufer)[col])) { ((CELL *) bufer)[col] = inullval; n_nulls++; } else { if (((CELL *) bufer)[col] == inullval) { nodatavalmatch = 1; } if (dfCellMin > ((CELL *) bufer)[col]) dfCellMin = ((CELL *) bufer)[col]; if (dfCellMax < ((CELL *) bufer)[col]) dfCellMax = ((CELL *) bufer)[col]; } } G_percent(row + 1, rows, 2); } } G_debug(1, "min %g max %g", dfCellMin, dfCellMax); /* can the GDAL datatype hold the data range to be exported ? */ /* f-flag does not override */ if (exact_range_check(dfCellMin, dfCellMax, export_datatype, name)) { G_warning("Raster export results in data loss."); ret = -2; } /* a default nodata value was used and NULL cells were present */ if (n_nulls && default_nodataval) { if (maptype == CELL_TYPE) G_important_message(_("Input raster map contains cells with NULL-value (no-data). " "The value %d will be used to represent no-data values in the input map. " "You can specify a nodata value with the %s option."), (int)nodataval, nodatakey); else G_important_message(_("Input raster map contains cells with NULL-value (no-data). " "The value %g will be used to represent no-data values in the input map. " "You can specify a nodata value with the %s option."), nodataval, nodatakey); } /* the nodata value was present in the exported data */ if (nodatavalmatch && n_nulls) { /* default nodataval didn't work */ if (default_nodataval) { G_warning(_("The default nodata value is present in raster" "band <%s> and would lead to data loss. Please specify a " "custom nodata value with the %s parameter."), name, nodatakey); } /* user-specified nodataval didn't work */ else { G_warning(_("The user given nodata value %g is present in raster" "band <%s> and would lead to data loss. Please specify a " "different nodata value with the %s parameter."), nodataval, name, nodatakey); } ret = -1; } G_free(bufer); return ret; }
int main(int argc, char *argv[]) { struct GModule *module; struct { struct Option *quant, *perc, *slots, *basemap, *covermap, *output; } opt; struct { struct Flag *r, *p; } flag; const char *basemap, *covermap; char **outputs; int reclass, print; int cover_fd, base_fd; struct Range range; struct FPRange fprange; int i; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("raster")); G_add_keyword(_("statistics")); module->description = _("Compute category quantiles using two passes."); opt.basemap = G_define_standard_option(G_OPT_R_BASE); opt.covermap = G_define_standard_option(G_OPT_R_COVER); opt.quant = G_define_option(); opt.quant->key = "quantiles"; opt.quant->type = TYPE_INTEGER; opt.quant->required = NO; opt.quant->description = _("Number of quantiles"); opt.perc = G_define_option(); opt.perc->key = "percentiles"; opt.perc->type = TYPE_DOUBLE; opt.perc->multiple = YES; opt.perc->description = _("List of percentiles"); opt.perc->answer = "50"; opt.slots = G_define_option(); opt.slots->key = "bins"; opt.slots->type = TYPE_INTEGER; opt.slots->required = NO; opt.slots->description = _("Number of bins to use"); opt.slots->answer = "1000"; opt.output = G_define_standard_option(G_OPT_R_OUTPUT); opt.output->description = _("Resultant raster map(s)"); opt.output->required = NO; opt.output->multiple = YES; flag.r = G_define_flag(); flag.r->key = 'r'; flag.r->description = _("Create reclass map with statistics as category labels"); flag.p = G_define_flag(); flag.p->key = 'p'; flag.p->description = _("Do not create output maps; just print statistics"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); basemap = opt.basemap->answer; covermap = opt.covermap->answer; outputs = opt.output->answers; reclass = flag.r->answer; print = flag.p->answer; if (!print && !opt.output->answers) G_fatal_error(_("Either -%c or %s= must be given"), flag.p->key, opt.output->key); if (print && opt.output->answers) G_fatal_error(_("-%c and %s= are mutually exclusive"), flag.p->key, opt.output->key); num_slots = atoi(opt.slots->answer); if (opt.quant->answer) { num_quants = atoi(opt.quant->answer) - 1; quants = G_calloc(num_quants, sizeof(DCELL)); for (i = 0; i < num_quants; i++) quants[i] = 1.0 * (i + 1) / (num_quants + 1); } else { for (i = 0; opt.perc->answers[i]; i++) ; num_quants = i; quants = G_calloc(num_quants, sizeof(DCELL)); for (i = 0; i < num_quants; i++) quants[i] = atof(opt.perc->answers[i]) / 100; qsort(quants, num_quants, sizeof(DCELL), compare_dcell); } if (opt.output->answer) { for (i = 0; opt.output->answers[i]; i++) ; if (i != num_quants) G_fatal_error(_("Number of quantiles (%d) does not match number of output maps (%d)"), num_quants, i); } base_fd = Rast_open_old(basemap, ""); cover_fd = Rast_open_old(covermap, ""); if (Rast_map_is_fp(basemap, "") != 0) G_fatal_error(_("The base map must be an integer (CELL) map")); if (Rast_read_range(basemap, "", &range) < 0) G_fatal_error(_("Unable to read range of base map <%s>"), basemap); Rast_get_range_min_max(&range, &min, &max); num_cats = max - min + 1; if (num_cats > MAX_CATS) G_fatal_error(_("Base map <%s> has too many categories (max: %d)"), basemap, MAX_CATS); Rast_read_fp_range(covermap, "", &fprange); Rast_get_fp_range_min_max(&fprange, &f_min, &f_max); slot_size = (f_max - f_min) / num_slots; basecats = G_calloc(num_cats, sizeof(struct basecat)); for (i = 0; i < num_cats; i++) basecats[i].slots = G_calloc(num_slots, sizeof(unsigned int)); rows = Rast_window_rows(); cols = Rast_window_cols(); get_slot_counts(base_fd, cover_fd); initialize_bins(); fill_bins(base_fd, cover_fd); sort_bins(); compute_quantiles(); if (print) print_quantiles(); else if (reclass) do_reclass(basemap, outputs); else do_output(base_fd, outputs, covermap); Rast_close(cover_fd); Rast_close(base_fd); return (EXIT_SUCCESS); }
int main(int argc, char **argv) { struct Cell_head window; RASTER_MAP_TYPE raster_type, mag_raster_type = -1; int layer_fd; void *raster_row, *ptr; int nrows, ncols; int aspect_c = -1; float aspect_f = -1.0; double scale; int skip, no_arrow; char *mag_map = NULL; void *mag_raster_row = NULL, *mag_ptr = NULL; double length = -1; int mag_fd = -1; struct FPRange range; double mag_min, mag_max; struct GModule *module; struct Option *opt1, *opt2, *opt3, *opt4, *opt5, *opt6, *opt7, *opt8, *opt9; struct Flag *align; double t, b, l, r; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("display")); G_add_keyword(_("raster")); module->description = _("Draws arrows representing cell aspect direction " "for a raster map containing aspect data."); opt1 = G_define_standard_option(G_OPT_R_MAP); opt1->description = _("Name of raster aspect map to be displayed"); opt2 = G_define_option(); opt2->key = "type"; opt2->type = TYPE_STRING; opt2->required = NO; opt2->answer = "grass"; opt2->options = "grass,compass,agnps,answers"; opt2->description = _("Type of existing raster aspect map"); opt3 = G_define_option(); opt3->key = "arrow_color"; opt3->type = TYPE_STRING; opt3->required = NO; opt3->answer = "green"; opt3->gisprompt = "old_color,color,color"; opt3->description = _("Color for drawing arrows"); opt3->guisection = _("Colors"); opt4 = G_define_option(); opt4->key = "grid_color"; opt4->type = TYPE_STRING; opt4->required = NO; opt4->answer = "gray"; opt4->gisprompt = "old_color,color,color_none"; opt4->description = _("Color for drawing grid or \"none\""); opt4->guisection = _("Colors"); opt5 = G_define_option(); opt5->key = "x_color"; opt5->type = TYPE_STRING; opt5->required = NO; opt5->answer = DEFAULT_FG_COLOR; opt5->gisprompt = "old_color,color,color_none"; opt5->description = _("Color for drawing X's (null values)"); opt5->guisection = _("Colors"); opt6 = G_define_option(); opt6->key = "unknown_color"; opt6->type = TYPE_STRING; opt6->required = NO; opt6->answer = "red"; opt6->gisprompt = "old_color,color,color_none"; opt6->description = _("Color for showing unknown information"); opt6->guisection = _("Colors"); opt9 = G_define_option(); opt9->key = "skip"; opt9->type = TYPE_INTEGER; opt9->required = NO; opt9->answer = "1"; opt9->description = _("Draw arrow every Nth grid cell"); opt7 = G_define_option(); opt7->key = "magnitude_map"; opt7->type = TYPE_STRING; opt7->required = NO; opt7->multiple = NO; opt7->gisprompt = "old,cell,raster"; opt7->description = _("Raster map containing values used for arrow length"); opt8 = G_define_option(); opt8->key = "scale"; opt8->type = TYPE_DOUBLE; opt8->required = NO; opt8->answer = "1.0"; opt8->description = _("Scale factor for arrows (magnitude map)"); align = G_define_flag(); align->key = 'a'; align->description = _("Align grids with raster cells"); /* Check command line */ if (G_parser(argc, argv)) exit(EXIT_FAILURE); layer_name = opt1->answer; arrow_color = D_translate_color(opt3->answer); x_color = D_translate_color(opt5->answer); unknown_color = D_translate_color(opt6->answer); if (strcmp("none", opt4->answer) == 0) grid_color = -1; else grid_color = D_translate_color(opt4->answer); if (strcmp("grass", opt2->answer) == 0) map_type = 1; else if (strcmp("agnps", opt2->answer) == 0) map_type = 2; else if (strcmp("answers", opt2->answer) == 0) map_type = 3; else if (strcmp("compass", opt2->answer) == 0) map_type = 4; scale = atof(opt8->answer); if (scale <= 0.0) G_fatal_error(_("Illegal value for scale factor")); skip = atoi(opt9->answer); if (skip <= 0) G_fatal_error(_("Illegal value for skip factor")); if (opt7->answer) { if (map_type != 1 && map_type != 4) G_fatal_error(_("Magnitude is only supported for GRASS and compass aspect maps.")); mag_map = opt7->answer; } else if (scale != 1.0) G_warning(_("Scale option requires magnitude_map")); /* Setup driver and check important information */ if (D_open_driver() != 0) G_fatal_error(_("No graphics device selected. " "Use d.mon to select graphics device.")); D_setup(0); /* Read in the map window associated with window */ G_get_window(&window); if (align->answer) { struct Cell_head wind; Rast_get_cellhd(layer_name, "", &wind); /* expand window extent by one wind resolution */ wind.west += wind.ew_res * ((int)((window.west - wind.west) / wind.ew_res) - (window.west < wind.west)); wind.east += wind.ew_res * ((int)((window.east - wind.east) / wind.ew_res) + (window.east > wind.east)); wind.south += wind.ns_res * ((int)((window.south - wind.south) / wind.ns_res) - (window.south < wind.south)); wind.north += wind.ns_res * ((int)((window.north - wind.north) / wind.ns_res) + (window.north > wind.north)); wind.rows = (wind.north - wind.south) / wind.ns_res; wind.cols = (wind.east - wind.west) / wind.ew_res; Rast_set_window(&wind); nrows = wind.rows; ncols = wind.cols; t = (wind.north - window.north) * nrows / (wind.north - wind.south); b = t + (window.north - window.south) * nrows / (wind.north - wind.south); l = (window.west - wind.west) * ncols / (wind.east - wind.west); r = l + (window.east - window.west) * ncols / (wind.east - wind.west); } else { nrows = window.rows; ncols = window.cols; t = 0; b = nrows; l = 0; r = ncols; } D_set_src(t, b, l, r); D_update_conversions(); /* figure out arrow scaling if using a magnitude map */ if (opt7->answer) { Rast_init_fp_range(&range); /* really needed? */ if (Rast_read_fp_range(mag_map, "", &range) != 1) G_fatal_error(_("Problem reading range file")); Rast_get_fp_range_min_max(&range, &mag_min, &mag_max); scale *= 1.5 / fabs(mag_max); G_debug(3, "scaling=%.2f rast_max=%.2f", scale, mag_max); } if (grid_color > 0) { /* ie not "none" */ /* Set color */ D_use_color(grid_color); /* Draw vertical grids */ for (col = 0; col < ncols; col++) D_line_abs(col, 0, col, nrows); /* Draw horizontal grids */ for (row = 0; row < nrows; row++) D_line_abs(0, row, ncols, row); } /* open the raster map */ layer_fd = Rast_open_old(layer_name, ""); raster_type = Rast_get_map_type(layer_fd); /* allocate the cell array */ raster_row = Rast_allocate_buf(raster_type); if (opt7->answer) { /* open the magnitude raster map */ mag_fd = Rast_open_old(mag_map, ""); mag_raster_type = Rast_get_map_type(mag_fd); /* allocate the cell array */ mag_raster_row = Rast_allocate_buf(mag_raster_type); } /* loop through cells, find value, determine direction (n,s,e,w,ne,se,sw,nw), and call appropriate function to draw an arrow on the cell */ for (row = 0; row < nrows; row++) { Rast_get_row(layer_fd, raster_row, row, raster_type); ptr = raster_row; if (opt7->answer) { Rast_get_row(mag_fd, mag_raster_row, row, mag_raster_type); mag_ptr = mag_raster_row; } for (col = 0; col < ncols; col++) { if (row % skip != 0) no_arrow = TRUE; else no_arrow = FALSE; if (col % skip != 0) no_arrow = TRUE; /* find aspect direction based on cell value */ if (raster_type == CELL_TYPE) aspect_f = *((CELL *) ptr); else if (raster_type == FCELL_TYPE) aspect_f = *((FCELL *) ptr); else if (raster_type == DCELL_TYPE) aspect_f = *((DCELL *) ptr); if (opt7->answer) { if (mag_raster_type == CELL_TYPE) length = *((CELL *) mag_ptr); else if (mag_raster_type == FCELL_TYPE) length = *((FCELL *) mag_ptr); else if (mag_raster_type == DCELL_TYPE) length = *((DCELL *) mag_ptr); length *= scale; if (Rast_is_null_value(mag_ptr, mag_raster_type)) { G_debug(5, "Invalid arrow length [NULL]. Skipping."); no_arrow = TRUE; } else if (length <= 0.0) { /* use fabs() or theta+=180? */ G_debug(5, "Illegal arrow length [%.3f]. Skipping.", length); no_arrow = TRUE; } } if (no_arrow) { ptr = G_incr_void_ptr(ptr, Rast_cell_size(raster_type)); if (opt7->answer) mag_ptr = G_incr_void_ptr(mag_ptr, Rast_cell_size(mag_raster_type)); no_arrow = FALSE; continue; } /* treat AGNPS and ANSWERS data like old zero-as-null CELL */ /* TODO: update models */ if (map_type == 2 || map_type == 3) { if (Rast_is_null_value(ptr, raster_type)) aspect_c = 0; else aspect_c = (int)(aspect_f + 0.5); } /** Now draw the arrows **/ /* case switch for standard GRASS aspect map measured in degrees counter-clockwise from east */ if (map_type == 1) { D_use_color(arrow_color); if (Rast_is_null_value(ptr, raster_type)) { D_use_color(x_color); draw_x(); D_use_color(arrow_color); } else if (aspect_f >= 0.0 && aspect_f <= 360.0) { if (opt7->answer) arrow_mag(aspect_f, length); else arrow_360(aspect_f); } else { D_use_color(unknown_color); unknown_(); D_use_color(arrow_color); } } /* case switch for AGNPS type aspect map */ else if (map_type == 2) { D_use_color(arrow_color); switch (aspect_c) { case 0: D_use_color(x_color); draw_x(); D_use_color(arrow_color); break; case 1: arrow_n(); break; case 2: arrow_ne(); break; case 3: arrow_e(); break; case 4: arrow_se(); break; case 5: arrow_s(); break; case 6: arrow_sw(); break; case 7: arrow_w(); break; case 8: arrow_nw(); break; default: D_use_color(unknown_color); unknown_(); D_use_color(arrow_color); break; } } /* case switch for ANSWERS type aspect map */ else if (map_type == 3) { D_use_color(arrow_color); if (aspect_c >= 15 && aspect_c <= 360) /* start at zero? */ arrow_360((double)aspect_c); else if (aspect_c == 400) { D_use_color(unknown_color); unknown_(); D_use_color(arrow_color); } else { D_use_color(x_color); draw_x(); D_use_color(arrow_color); } } /* case switch for compass type aspect map measured in degrees clockwise from north */ else if (map_type == 4) { D_use_color(arrow_color); if (Rast_is_null_value(ptr, raster_type)) { D_use_color(x_color); draw_x(); D_use_color(arrow_color); } else if (aspect_f >= 0.0 && aspect_f <= 360.0) { if (opt7->answer) arrow_mag(90 - aspect_f, length); else arrow_360(90 - aspect_f); } else { D_use_color(unknown_color); unknown_(); D_use_color(arrow_color); } } ptr = G_incr_void_ptr(ptr, Rast_cell_size(raster_type)); if (opt7->answer) mag_ptr = G_incr_void_ptr(mag_ptr, Rast_cell_size(mag_raster_type)); } } Rast_close(layer_fd); if (opt7->answer) Rast_close(mag_fd); D_save_command(G_recreate_command()); D_close_driver(); exit(EXIT_SUCCESS); }
void draw_histogram(const char *map_name, int x0, int y0, int width, int height, int color, int flip, int horiz, int map_type, int is_fp, struct FPRange render_range) { int i, nsteps, ystep; long cell_count = 0; double max_width, width_mult, dx; double dy, y0_adjust; /* only needed for CELL maps */ struct stat_list dist_stats; struct stat_node *ptr; struct Range range; struct FPRange fprange; CELL c_map_min, c_map_max; DCELL d_map_min, d_map_max; double map_min, map_max, map_range, user_range; double crop_min_perc = 0.0, crop_max_perc = 1.0, pad_min_perc = 0.0; if (horiz) { max_width = height * 1.75; nsteps = width - 3; } else { max_width = width * 1.75; nsteps = height - 3; } if (render_range.first_time) { /* user specified range, can be either larger or smaller than actual map's range */ if (is_fp) { Rast_read_fp_range(map_name, "", &fprange); Rast_get_fp_range_min_max(&fprange, &d_map_min, &d_map_max); map_min = (double)d_map_min; map_max = (double)d_map_max; } else { Rast_read_range(map_name, "", &range); Rast_get_range_min_max(&range, &c_map_min, &c_map_max); map_min = (double)c_map_min; map_max = (double)c_map_max; } map_range = map_max - map_min; user_range = render_range.max - render_range.min; if (horiz) nsteps = (int)(0.5 + (map_range * (width - 3) / user_range)); else nsteps = (int)(0.5 + (map_range * (height - 3) / user_range)); G_debug(1, "number of steps for r.stats = %d, height-3=%d width-3=%d", nsteps, height - 3, width - 3); /* need to know the % of the MAP range where user range starts and stops. * note that MAP range can be fully inside user range, in which case * keep 0-100% aka 0,nsteps, i.e. the step number in the nsteps range */ if (render_range.min > map_min) { crop_min_perc = (render_range.min - map_min) / map_range; G_debug(3, "min: %.02f vs. %.02f (%.02f) ... %.02f%%", render_range.min, map_min, map_range, 100 * crop_min_perc); } if (render_range.max > map_max) { crop_max_perc = 1.0 - ((render_range.max - map_max) / user_range); G_debug(3, "max: %.02f vs. %.02f (%.02f) ... %.02f%%", map_max, render_range.max, map_range, 100 * crop_max_perc); } if (render_range.min < map_min) { pad_min_perc = (map_min - render_range.min) / user_range; G_debug(3, "Min: %.02f vs. %.02f (%.02f) ... %.02f%%", map_min, render_range.min, user_range, 100 * pad_min_perc); } #ifdef amplify_gain /* proportion of nsteps to width, use as mult factor to boost the 1.75x when spread out over more nsteps than we are displaying */ G_debug(0, "max_width was: %.2f (nsteps=%d)", max_width, nsteps); if (nsteps > ((horiz ? width : height) - 3.0)) max_width *= nsteps / ((horiz ? width : height) - 3.0); G_debug(0, "max_width now: %.2f", max_width); #endif } /* TODO */ if (!is_fp && render_range.first_time) { G_warning(_("Histogram constrained by range not yet implemented for " "categorical rasters")); return; } /* get the distribution statistics */ get_stats(map_name, &dist_stats, nsteps, map_type); width_mult = max_width / dist_stats.maxstat; D_use_color(color); D_begin(); ptr = dist_stats.ptr; if (!is_fp) { dy = (nsteps + 3.0) / (1 + dist_stats.maxcat - dist_stats.mincat); if (flip) dy *= -1; if (dist_stats.mincat == 0) y0_adjust = dy; else y0_adjust = 0; if (!flip) /* mmph */ y0_adjust += 0.5; } G_debug(3, "mincat=%ld maxcat=%ld", dist_stats.mincat, dist_stats.maxcat); for (i = dist_stats.mincat, ystep = 0; i <= dist_stats.maxcat; i++) { if (!ptr) break; /* jump out if user range cuts things shorter than the map's native range */ if ((horiz && ystep > width - 4) || (!horiz && ystep > height - 4)) break; /* jump out if user range goes beyond max of map data */ if (((double)ystep / ((horiz ? width : height) - 3.0)) > crop_max_perc) break; /* TODO if (!is_fp && i > render_range.max) break; */ /* haven't made it to the min of the user range yet */ if (((double)i / nsteps) < crop_min_perc) { continue; } /* now it's ok advance the plotter position */ ystep++; /* if user range is below the minimum real map value, we need to pad out the space */ if (render_range.first_time && render_range.min < map_min) { if ( ((double)ystep / ((horiz ? width : height) - 3.0)) < pad_min_perc) { i--; continue; } } if (ptr->cat == i) { /* AH-HA!! found the stat */ cell_count = ptr->stat; if (ptr->next != NULL) ptr = ptr->next; } else { /* we have to look for the stat */ /* loop until we find it, or pass where it should be */ while (ptr->cat < i && ptr->next != NULL) ptr = ptr->next; if (ptr->cat == i) { /* AH-HA!! found the stat */ cell_count = ptr->stat; if (ptr->next != NULL) ptr = ptr->next; } else /* stat cannot be found */ G_debug(5, "No matching stat found, i=%d", i); } G_debug(5, "i=%d ptr->cat=%ld cell_count=%ld", i, ptr->cat, cell_count); if (!cell_count) continue; dx = cell_count * width_mult; if (is_fp) { if (horiz) { if (flip) D_move_abs(x0 + width - ystep - 1, y0 - 1); else D_move_abs(x0 + ystep + 1, y0 - 1); D_cont_rel(0, -dx); } else { /* vertical */ if (flip) D_move_abs(x0 - 1, y0 - 1 + height - ystep); else D_move_abs(x0 - 1, y0 + 1 + ystep); D_cont_rel(-dx, 0); } } else { /* categorical */ if (horiz) { if (flip) D_box_abs(x0 + width + y0_adjust + ((i - 1) * dy), y0 - 1, x0 + width + y0_adjust + 1 + (i * dy), y0 - 1 - dx); else D_box_abs(x0 + y0_adjust + ((i - 1) * dy), y0 - 1, x0 - 1 + y0_adjust + (i * dy), y0 - 1 - dx); } else { /* vertical */ if (flip) /* GRASS_EPSILON fudge around D_box_abs() weirdness + PNG driver */ D_box_abs(x0 - 1 - GRASS_EPSILON * 10, y0 + height + y0_adjust + ((i - 1) * dy), x0 - 1 - dx, y0 + height + y0_adjust + 1 + (i * dy)); else D_box_abs(x0 - 1 - GRASS_EPSILON * 10, y0 + y0_adjust + ((i - 1) * dy), x0 - 1 - dx, y0 + y0_adjust - 1 + (i * dy)); } } } D_close(); D_end(); D_stroke(); }