Beispiel #1
0
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;
}
Beispiel #2
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 &region3D) {
    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;
    }
}
Beispiel #4
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);
}
Beispiel #5
0
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);
    }
}
Beispiel #6
0
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;
}
Beispiel #7
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;
}
Beispiel #8
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(&params, 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(&params, 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(&params);
    /* 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(&params, 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(&params, 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);
}
Beispiel #9
0
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;
}
Beispiel #10
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;
}
Beispiel #11
0
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);
}
Beispiel #12
0
int open_files(struct globals *globals)
{
    struct Ref Ref;		/* group reference list */
    int *in_fd, bounds_fd, is_null;
    int n, row, col, srows, scols, inlen, outlen, nseg;
    DCELL **inbuf;		/* buffers to store lines from each of the imagery group rasters */
    CELL *boundsbuf, bounds_val;
    int have_bounds = 0;
    CELL s, id;
    struct Range range;	/* min/max values of bounds map */
    struct FPRange *fp_range;	/* min/max values of each input raster */
    DCELL *min, *max;
    struct ngbr_stats Ri, Rk;

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

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

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

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

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

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

    /* Read Imagery Group */

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

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

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

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

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

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

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

    /* size of each element to be stored */

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

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

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

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

    nseg = manage_memory(srows, scols, globals);

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

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

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

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

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

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

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

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

    /* bounds/constraints */

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

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

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

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

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

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

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

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

    /* Free memory */

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

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

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

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

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

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

    return TRUE;
}
Beispiel #13
0
/*!
 * \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;
}
Beispiel #14
0
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);
}
Beispiel #15
0
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);
}
Beispiel #16
0
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);
}
Beispiel #17
0
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);
}
Beispiel #18
0
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);
}
Beispiel #19
0
/* 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;
}
Beispiel #20
0
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);
}
Beispiel #21
0
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);
}
Beispiel #22
0
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();
}