Esempio n. 1
0
File: main.c Progetto: caomw/grass
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);
    }
}
Esempio n. 2
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;
}
Esempio n. 3
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);
}
Esempio n. 4
0
File: main.c Progetto: caomw/grass
int main(int argc, char **argv)
{
    static DCELL *count, *sum, *mean, *sumu, *sum2, *sum3, *sum4, *min, *max;
    DCELL *result;
    struct GModule *module;
    struct {
	struct Option *method, *basemap, *covermap, *output;
    } opt;
    struct {
	struct Flag *c, *r;
    } flag;
    char methods[2048];
    const char *basemap, *covermap, *output;
    int usecats;
    int reclass;
    int base_fd, cover_fd;
    struct Categories cats;
    CELL *base_buf;
    DCELL *cover_buf;
    struct Range range;
    CELL mincat, ncats;
    int method;
    int rows, cols;
    int row, col, i;

    G_gisinit(argv[0]);

    module = G_define_module();
    G_add_keyword(_("raster"));
    G_add_keyword(_("statistics"));
    module->description =
	_("Calculates category or object oriented statistics (accumulator-based statistics).");

    opt.basemap = G_define_standard_option(G_OPT_R_BASE);

    opt.covermap = G_define_standard_option(G_OPT_R_COVER);

    opt.method = G_define_option();
    opt.method->key = "method";
    opt.method->type = TYPE_STRING;
    opt.method->required = YES;
    opt.method->description = _("Method of object-based statistic");

    for (i = 0; menu[i].name; i++) {
	if (i)
	    strcat(methods, ",");
	else
	    *(methods) = 0;
	strcat(methods, menu[i].name);
    }
    opt.method->options = G_store(methods);

    for (i = 0; menu[i].name; i++) {
	if (i)
	    strcat(methods, ";");
	else
	    *(methods) = 0;
	strcat(methods, menu[i].name);
	strcat(methods, ";");
	strcat(methods, menu[i].text);
    }
    opt.method->descriptions = G_store(methods);

    opt.output = G_define_standard_option(G_OPT_R_OUTPUT);
    opt.output->description = _("Resultant raster map");
    opt.output->required = YES;

    flag.c = G_define_flag();
    flag.c->key = 'c';
    flag.c->description =
	_("Cover values extracted from the category labels of the cover map");

    flag.r = G_define_flag();
    flag.r->key = 'r';
    flag.r->description =
	_("Create reclass map with statistics as category labels");

    if (G_parser(argc, argv))
	exit(EXIT_FAILURE);

    basemap = opt.basemap->answer;
    covermap = opt.covermap->answer;
    output = opt.output->answer;
    usecats = flag.c->answer;
    reclass = flag.r->answer;

    for (i = 0; menu[i].name; i++)
	if (strcmp(menu[i].name, opt.method->answer) == 0)
	    break;

    if (!menu[i].name) {
	G_warning(_("<%s=%s> unknown %s"), opt.method->key, opt.method->answer,
		  opt.method->key);
	G_usage();
	exit(EXIT_FAILURE);
    }

    method = menu[i].val;

    base_fd = Rast_open_old(basemap, "");

    cover_fd = Rast_open_old(covermap, "");

    if (usecats && Rast_read_cats(covermap, "", &cats) < 0)
	G_fatal_error(_("Unable to read category file of cover map <%s>"), 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);

    mincat = range.min;
    ncats = range.max - range.min + 1;

    rows = Rast_window_rows();
    cols = Rast_window_cols();

    switch (method) {
    case COUNT:
	count = G_calloc(ncats, sizeof(DCELL));
	break;
    case SUM:
	sum = G_calloc(ncats, sizeof(DCELL));
	break;
    case MIN:
	min = G_malloc(ncats * sizeof(DCELL));
	break;
    case MAX:
	max = G_malloc(ncats * sizeof(DCELL));
	break;
    case RANGE:
	min = G_malloc(ncats * sizeof(DCELL));
	max = G_malloc(ncats * sizeof(DCELL));
	break;
    case AVERAGE:
    case ADEV:
    case VARIANCE2:
    case STDDEV2:
    case SKEWNESS2:
    case KURTOSIS2:
	count = G_calloc(ncats, sizeof(DCELL));
	sum = G_calloc(ncats, sizeof(DCELL));
	break;
    case VARIANCE1:
    case STDDEV1:
	count = G_calloc(ncats, sizeof(DCELL));
	sum = G_calloc(ncats, sizeof(DCELL));
	sum2 = G_calloc(ncats, sizeof(DCELL));
	break;
    case SKEWNESS1:
	count = G_calloc(ncats, sizeof(DCELL));
	sum = G_calloc(ncats, sizeof(DCELL));
	sum2 = G_calloc(ncats, sizeof(DCELL));
	sum3 = G_calloc(ncats, sizeof(DCELL));
	break;
    case KURTOSIS1:
	count = G_calloc(ncats, sizeof(DCELL));
	sum = G_calloc(ncats, sizeof(DCELL));
	sum2 = G_calloc(ncats, sizeof(DCELL));
	sum4 = G_calloc(ncats, sizeof(DCELL));
	break;
    }

    if (min)
	for (i = 0; i < ncats; i++)
	    min[i] = 1e300;
    if (max)
	for (i = 0; i < ncats; i++)
	    max[i] = -1e300;

    base_buf = Rast_allocate_c_buf();
    cover_buf = Rast_allocate_d_buf();

    G_message(_("First pass"));

    for (row = 0; row < rows; row++) {
	Rast_get_c_row(base_fd, base_buf, row);
	Rast_get_d_row(cover_fd, cover_buf, row);

	for (col = 0; col < cols; col++) {
	    int n;
	    DCELL v;

	    if (Rast_is_c_null_value(&base_buf[col]))
		continue;
	    if (Rast_is_d_null_value(&cover_buf[col]))
		continue;

	    n = base_buf[col] - mincat;

	    if (n < 0 || n >= ncats)
		continue;

	    v = cover_buf[col];
	    if (usecats)
		sscanf(Rast_get_c_cat((CELL *) &v, &cats), "%lf", &v);

	    if (count)
		count[n]++;
	    if (sum)
		sum[n] += v;
	    if (sum2)
		sum2[n] += v * v;
	    if (sum3)
		sum3[n] += v * v * v;
	    if (sum4)
		sum4[n] += v * v * v * v;
	    if (min && min[n] > v)
		min[n] = v;
	    if (max && max[n] < v)
		max[n] = v;
	}

	G_percent(row, rows, 2);
    }

    G_percent(row, rows, 2);

    result = G_calloc(ncats, sizeof(DCELL));

    switch (method) {
    case ADEV:
    case VARIANCE2:
    case STDDEV2:
    case SKEWNESS2:
    case KURTOSIS2:
	mean = G_calloc(ncats, sizeof(DCELL));
	for (i = 0; i < ncats; i++)
	    mean[i] = sum[i] / count[i];
	G_free(sum);
	break;
    }

    switch (method) {
    case ADEV:
	sumu = G_calloc(ncats, sizeof(DCELL));
	break;
    case VARIANCE2:
    case STDDEV2:
	sum2 = G_calloc(ncats, sizeof(DCELL));
	break;
    case SKEWNESS2:
	sum2 = G_calloc(ncats, sizeof(DCELL));
	sum3 = G_calloc(ncats, sizeof(DCELL));
	break;
    case KURTOSIS2:
	sum2 = G_calloc(ncats, sizeof(DCELL));
	sum4 = G_calloc(ncats, sizeof(DCELL));
	break;
    }

    if (mean) {
	G_message(_("Second pass"));

	for (row = 0; row < rows; row++) {
	    Rast_get_c_row(base_fd, base_buf, row);
	    Rast_get_d_row(cover_fd, cover_buf, row);

	    for (col = 0; col < cols; col++) {
		int n;
		DCELL v, d;

		if (Rast_is_c_null_value(&base_buf[col]))
		    continue;
		if (Rast_is_d_null_value(&cover_buf[col]))
		    continue;

		n = base_buf[col] - mincat;

		if (n < 0 || n >= ncats)
		    continue;

		v = cover_buf[col];
		if (usecats)
		    sscanf(Rast_get_c_cat((CELL *) &v, &cats), "%lf", &v);
		d = v - mean[n];

		if (sumu)
		    sumu[n] += fabs(d);
		if (sum2)
		    sum2[n] += d * d;
		if (sum3)
		    sum3[n] += d * d * d;
		if (sum4)
		    sum4[n] += d * d * d * d;
	    }

	    G_percent(row, rows, 2);
	}

	G_percent(row, rows, 2);
	G_free(mean);
	G_free(cover_buf);
    }

    switch (method) {
    case COUNT:
	for (i = 0; i < ncats; i++)
	    result[i] = count[i];
	break;
    case SUM:
	for (i = 0; i < ncats; i++)
	    result[i] = sum[i];
	break;
    case AVERAGE:
	for (i = 0; i < ncats; i++)
	    result[i] = sum[i] / count[i];
	break;
    case MIN:
	for (i = 0; i < ncats; i++)
	    result[i] = min[i];
	break;
    case MAX:
	for (i = 0; i < ncats; i++)
	    result[i] = max[i];
	break;
    case RANGE:
	for (i = 0; i < ncats; i++)
	    result[i] = max[i] - min[i];
	break;
    case VARIANCE1:
	for (i = 0; i < ncats; i++) {
	    double n = count[i];
	    double var = (sum2[i] - sum[i] * sum[i] / n) / (n - 1);
	    result[i] = var;
	}
	break;
    case STDDEV1:
	for (i = 0; i < ncats; i++) {
	    double n = count[i];
	    double var = (sum2[i] - sum[i] * sum[i] / n) / (n - 1);
	    result[i] = sqrt(var);
	}
	break;
    case SKEWNESS1:
	for (i = 0; i < ncats; i++) {
	    double n = count[i];
	    double var = (sum2[i] - sum[i] * sum[i] / n) / (n - 1);
	    double skew = (sum3[i] / n
			   - 3 * sum[i] * sum2[i] / (n * n)
			   + 2 * sum[i] * sum[i] * sum[i] / (n * n * n))
		/ (pow(var, 1.5));
	    result[i] = skew;
	}
	break;
    case KURTOSIS1:
	for (i = 0; i < ncats; i++) {
	    double n = count[i];
	    double var = (sum2[i] - sum[i] * sum[i] / n) / (n - 1);
	    double kurt = (sum4[i] / n
			   - 4 * sum[i] * sum3[i] / (n * n)
			   + 6 * sum[i] * sum[i] * sum2[i] / (n * n * n)
			   - 3 * sum[i] * sum[i] * sum[i] * sum[i] / (n * n * n * n))
		/ (var * var) - 3;
	    result[i] = kurt;
	}
	break;
    case ADEV:
	for (i = 0; i < ncats; i++)
	    result[i] = sumu[i] / count[i];
	break;
    case VARIANCE2:
	for (i = 0; i < ncats; i++)
	    result[i] = sum2[i] / (count[i] - 1);
	break;
    case STDDEV2:
	for (i = 0; i < ncats; i++)
	    result[i] = sqrt(sum2[i] / (count[i] - 1));
	break;
    case SKEWNESS2:
	for (i = 0; i < ncats; i++) {
	    double n = count[i];
	    double var = sum2[i] / (n - 1);
	    double sdev = sqrt(var);
	    result[i] = sum3[i] / (sdev * sdev * sdev) / n;
	}
	G_free(count);
	G_free(sum2);
	G_free(sum3);
	break;
    case KURTOSIS2:
	for (i = 0; i < ncats; i++) {
	    double n = count[i];
	    double var = sum2[i] / (n - 1);
	    result[i] = sum4[i] / (var * var) / n - 3;
	}
	G_free(count);
	G_free(sum2);
	G_free(sum4);
	break;
    }

    if (reclass) {
	const char *tempfile = G_tempfile();
	char *input_arg = G_malloc(strlen(basemap) + 7);
	char *output_arg = G_malloc(strlen(output) + 8);
	char *rules_arg = G_malloc(strlen(tempfile) + 7);
	FILE *fp;

	G_message(_("Generating reclass map"));

	sprintf(input_arg, "input=%s", basemap);
	sprintf(output_arg, "output=%s", output);
	sprintf(rules_arg, "rules=%s", tempfile);

	fp = fopen(tempfile, "w");
	if (!fp)
	    G_fatal_error(_("Unable to open temporary file"));

	for (i = 0; i < ncats; i++)
	    fprintf(fp, "%d = %d %f\n", mincat + i, mincat + i, result[i]);

	fclose(fp);

	G_spawn("r.reclass", "r.reclass", input_arg, output_arg, rules_arg, NULL);
    }
    else {
	int out_fd;
	DCELL *out_buf;
	struct Colors colors;

	G_message(_("Writing output map"));

	out_fd = Rast_open_fp_new(output);

	out_buf = Rast_allocate_d_buf();

	for (row = 0; row < rows; row++) {
	    Rast_get_c_row(base_fd, base_buf, row);

	    for (col = 0; col < cols; col++)
		if (Rast_is_c_null_value(&base_buf[col]))
		    Rast_set_d_null_value(&out_buf[col], 1);
		else
		    out_buf[col] = result[base_buf[col] - mincat];

	    Rast_put_d_row(out_fd, out_buf);

	    G_percent(row, rows, 2);
	}

	G_percent(row, rows, 2);

	Rast_close(out_fd);

	if (Rast_read_colors(covermap, "", &colors) > 0)
	    Rast_write_colors(output, G_mapset(), &colors);
    }

    return 0;
}
Esempio n. 5
0
int main(int argc, char **argv)
{
    int text_height;
    int text_width;
    struct Categories cats;
    struct Range range;
    struct Colors pcolors;
    char title[GNAME_MAX];
    double tt, tb, tl, tr;
    double t, b, l, r;
    struct GModule *module;
    struct Option *opt1;
    struct Option *opt2, *bg_opt;
    struct Option *opt4;
    struct Option *opt5;
    struct Flag *flag1;
    struct Flag *flag2;
    struct Flag *flag3;


    /* Initialize the GIS calls */
    G_gisinit(argv[0]);

    module = G_define_module();
    G_add_keyword(_("display"));
    G_add_keyword(_("histogram"));
    G_add_keyword(_("statistics"));
    module->description =
	_("Displays a histogram in the form of a pie or bar chart "
	  "for a user-specified raster map.");

    opt1 = G_define_standard_option(G_OPT_R_MAP);
    opt1->description = _("Raster map for which histogram will be displayed");

    opt4 = G_define_option();
    opt4->key = "style";
    opt4->description = _("Indicate if a pie or bar chart is desired");
    opt4->type = TYPE_STRING;
    opt4->required = NO;
    opt4->options = "pie,bar";
    opt4->answer = "bar";

    /* The color option specifies the color for the labels, tic-marks,
     * and borders of the chart. */
    opt2 = G_define_standard_option(G_OPT_C);
    opt2->label = _("Color for text and axes");

    bg_opt = G_define_standard_option(G_OPT_CN);
    bg_opt->key = "bgcolor";
    bg_opt->label = _("Background color");
    bg_opt->answer = DEFAULT_BG_COLOR;

#ifdef CAN_DO_AREAS
    opt3 = G_define_option();
    opt3->key = "type";
    opt3->description =
	_("Indicate if cell counts or map areas should be displayed");
    opt3->type = TYPE_STRING;
    opt3->required = NO;
    opt3->answer = "count";
    opt3->options = "count,area";
#endif

    opt5 = G_define_option();
    opt5->key = "nsteps";
    opt5->description =
	_("Number of steps to divide the data range into (fp maps only)");
    opt5->type = TYPE_INTEGER;
    opt5->required = NO;
    opt5->answer = "255";

    flag1 = G_define_flag();
    flag1->key = 'n';
    flag1->description = _("Display information for null cells");

    flag3 = G_define_flag();
    flag3->key = 'c';
    flag3->description =
	_("Report for ranges defined in cats file (fp maps only)");

    if (G_parser(argc, argv))
	exit(EXIT_FAILURE);


    map_name = opt1->answer;

    color = D_parse_color(opt2->answer, FALSE);

    type = COUNT;
#ifdef CAN_DO_AREAS
    if (strcmp(opt3->answer, "count") == 0)
	type = COUNT;
    else
	type = AREA;
#endif

    if (strcmp(opt4->answer, "bar") == 0)
	style = BAR;
    else
	style = PIE;

    if (sscanf(opt5->answer, "%d", &nsteps) != 1)
	G_fatal_error(_("Invalid number of steps: %s"), opt5->answer);

    cat_ranges = flag3->answer;

    if (cat_ranges && nsteps != 255)
	G_warning(_("When -C flag is set, the nsteps argument is ignored"));

    nodata = flag1->answer;

    if (Rast_read_colors(map_name, "", &pcolors) == -1)
	G_fatal_error(_("Color file for <%s> not available"), map_name);

    if (Rast_read_cats(map_name, "", &cats) == -1)
	G_fatal_error(_("Category file for <%s> not available"), map_name);

    if (Rast_read_range(map_name, "", &range) == -1)
	G_fatal_error(_("Range information for <%s> not available"),
		      map_name);

    /* get the distribution statistics */

    get_stats(map_name, &dist_stats);

    /* set up the graphics driver and initialize its color-table */

    D_open_driver();
    
    D_setup_unity(0);			/* 0 = don't clear frame */
    D_get_src(&t, &b, &l, &r);

    /* clear the frame, if requested to do so */
    if (strcmp(bg_opt->answer, "none") != 0)
	D_erase(bg_opt->answer);

    /* draw a title for */
    sprintf(title, "%s", map_name);
    text_height = (b - t) * 0.05;
    text_width = (r - l) * 0.05 * 0.50;
    D_text_size(text_width, text_height);
    D_get_text_box(title, &tt, &tb, &tl, &tr);
    D_pos_abs(l + (r - l) / 2 - (tr - tl) / 2,
	      t + (b - t) * 0.07);
    D_use_color(color);
    D_text(title);

    /* plot the distributrion statistics */
    if (style == PIE)
	pie(&dist_stats, &pcolors);
    else
	bar(&dist_stats, &pcolors);

    D_save_command(G_recreate_command());
    D_close_driver();

    exit(EXIT_SUCCESS);
}
Esempio n. 6
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);
}
Esempio n. 7
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;
}
Esempio n. 8
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();
}
Esempio n. 9
0
File: Gs3.c Progetto: caomw/grass
/*!
   \brief Get map data type

   \param filename raster map name
   \param negflag

   \return -1 if map is integer and Rast_read_range() fails
   \return data type (ARRY_*)
 */
int Gs_numtype(const char *filename, int *negflag)
{
    CELL max = 0, min = 0;
    struct Range range;
    const char *mapset;
    int shortbits, charbits, bitplace;
    static int max_short, max_char;
    static int first = 1;

    if (first) {
	max_short = max_char = 1;
	shortbits = 8 * sizeof(short);

	for (bitplace = 1; bitplace < shortbits; ++bitplace) {
	    /*1 bit for sign */
	    max_short *= 2;
	}

	max_short -= 1;

	/* NO bits for sign, using unsigned char */
	charbits = 8 * sizeof(unsigned char);

	for (bitplace = 0; bitplace < charbits; ++bitplace) {
	    max_char *= 2;
	}

	max_char -= 1;

	first = 0;
    }

    mapset = G_find_raster2(filename, "");
    if (!mapset) {
	G_warning(_("Raster map <%s> not found"), filename);
	return -1;
    }

    if (Rast_map_is_fp(filename, mapset)) {
	G_debug(3, "Gs_numtype(): fp map detected");

	return (ATTY_FLOAT);
    }

    if (-1 == Rast_read_range(filename, mapset, &range)) {
	return (-1);
    }

    Rast_get_range_min_max(&range, &min, &max);
    *negflag = (min < 0);

    if (max < max_char && min > 0) {
	return (ATTY_CHAR);
    }

    if (max < max_short && min > -max_short) {
	return (ATTY_SHORT);
    }

    return (ATTY_INT);
}
Esempio n. 10
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);
}
Esempio n. 11
0
int main(int argc, char *argv[])
{
    int fd[NFILES];
    int outfd;
    int i;
    const char *name;
    const char *output;
    const char *mapset;
    int non_zero;
    struct Range range;
    CELL ncats, max_cats;
    int primary;
    struct Categories pcats;
    struct Colors pcolr;
    char buf[1024];
    CELL result;
    struct GModule *module;
    struct
    {
	struct Option *input, *output;
    } parm;
    struct
    {
	struct Flag *z;
    } flag;

    G_gisinit(argv[0]);

    /* Define the different options */

    module = G_define_module();
    G_add_keyword(_("raster"));
    G_add_keyword(_("statistics"));
    module->description =
	_("Creates a cross product of the category values from "
	  "multiple raster map layers.");

    parm.input = G_define_option();
    parm.input->key = "input";
    parm.input->type = TYPE_STRING;
    parm.input->required = YES;
    parm.input->multiple = YES;
    parm.input->gisprompt = "old,cell,raster";
    sprintf(buf, _("Names of 2-%d input raster maps"), NFILES);
    parm.input->description = G_store(buf);

    parm.output = G_define_standard_option(G_OPT_R_OUTPUT);

    /* Define the different flags */

    flag.z = G_define_flag();
    flag.z->key = 'z';
    flag.z->description = _("Non-zero data only");

    if (G_parser(argc, argv))
	exit(EXIT_FAILURE);

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

    nfiles = 0;
    non_zero = flag.z->answer;

    for (nfiles = 0; (name = parm.input->answers[nfiles]); nfiles++) {
	if (nfiles >= NFILES)
	    G_fatal_error(_("More than %d files not allowed"), NFILES);
	mapset = G_find_raster2(name, "");
	if (!mapset)
	    G_fatal_error(_("Raster map <%s> not found"), name);
	names[nfiles] = name;
	fd[nfiles] = Rast_open_old(name, mapset);
	Rast_read_range(name, mapset, &range);
	ncats = range.max - range.min;

	if (nfiles == 0 || ncats > max_cats) {
	    primary = nfiles;
	    max_cats = ncats;
	}
    }

    if (nfiles <= 1)
	G_fatal_error(_("Must specify 2 or more input maps"));
    output = parm.output->answer;
    outfd = Rast_open_c_new(output);

    sprintf(buf, "Cross of %s", names[0]);
    for (i = 1; i < nfiles - 1; i++) {
	strcat(buf, ", ");
	strcat(buf, names[i]);
    }
    strcat(buf, " and ");
    strcat(buf, names[i]);
    Rast_init_cats(buf, &pcats);

    /* first step is cross product, but un-ordered */
    result = cross(fd, non_zero, primary, outfd);

    /* print message STEP mesage */
    G_message(_("%s: STEP 2 ..."), G_program_name());

    /* now close all files */
    for (i = 0; i < nfiles; i++)
	Rast_close(fd[i]);
    Rast_close(outfd);

    if (result <= 0)
	exit(0);


    /* build the renumbering/reclass and the new cats file */
    qsort(reclass, result + 1, sizeof(RECLASS), cmp);
    table = (CELL *) G_calloc(result + 1, sizeof(CELL));
    for (i = 0; i < nfiles; i++) {
	mapset = G_find_raster2(names[i], "");
	Rast_read_cats(names[i], mapset, &labels[i]);
    }

    for (ncats = 0; ncats <= result; ncats++) {
	table[reclass[ncats].result] = ncats;
	set_cat(ncats, reclass[ncats].cat, &pcats);
    }

    for (i = 0; i < nfiles; i++)
	Rast_free_cats(&labels[i]);

    /* reopen the output cell for reading and for writing */
    fd[0] = Rast_open_old(output, G_mapset());
    outfd = Rast_open_c_new(output);

    renumber(fd[0], outfd);

    G_message(_("Creating support files for <%s>..."), output);
    Rast_close(fd[0]);
    Rast_close(outfd);
    Rast_write_cats(output, &pcats);
    Rast_free_cats(&pcats);
    if (result > 0) {
	Rast_make_random_colors(&pcolr, (CELL) 1, result);
	Rast_write_colors(output, G_mapset(), &pcolr);
    }

    G_message(_("%ld categories"), (long)result);
    exit(EXIT_SUCCESS);
}
Esempio n. 12
0
File: main.c Progetto: caomw/grass
int main(int argc, char *argv[])
{
    int col, row;

    /* to menage start (source) raster map */
    struct Range start_range;
    CELL start_range_min, start_range_max;
    int start_is_time;  /* 0 or 1 */

    struct
    {
	struct Option *max, *dir, *base, *start,
	    *spotdist, *velocity, *mois,
	    *least, *comp_dens, *init_time,
	    *time_lag, *backdrop, *out, *x_out, *y_out;
    } parm;
    struct
    {
	/* please, remove display before GRASS 7 released */
	struct Flag *display, *spotting, *start_is_time;
    } flag;
    struct GModule *module;

    /* initialize access to database and create temporary files */

    G_gisinit(argv[0]);

    /* Set description */
    module = G_define_module();
    G_add_keyword(_("raster"));
    G_add_keyword(_("fire"));
    G_add_keyword(_("spread"));
    G_add_keyword(_("hazard"));
    module->label =
	_("Simulates elliptically anisotropic spread.");
    module->description =
	_("Generates a raster map of the cumulative time of spread, "
	  "given raster maps containing the rates of spread (ROS), "
	  "the ROS directions and the spread origins. "
	  "It optionally produces raster maps to contain backlink UTM "
	  "coordinates for tracing spread paths. "
	  "Usable for fire spread simulations.");

    parm.max = G_define_option();
    parm.max->key = "max";
    parm.max->type = TYPE_STRING;
    parm.max->required = YES;
    parm.max->gisprompt = "old,cell,raster";
    parm.max->guisection = _("Input maps");
    parm.max->label =
	_("Raster map containing maximal ROS (cm/min)");
	parm.max->description =
	_("Name of an existing raster map layer in the user's current "
	  "mapset search path containing the maximum ROS values (cm/minute).");

    parm.dir = G_define_option();
    parm.dir->key = "dir";
    parm.dir->type = TYPE_STRING;
    parm.dir->required = YES;
    parm.dir->gisprompt = "old,cell,raster";
    parm.dir->guisection = _("Input maps");
    parm.dir->label =
	_("Raster map containing directions of maximal ROS (degree)");
    parm.dir->description =
	_("Name of an existing raster map layer in the user's "
	  "current mapset search path containing directions of the maximum ROSes, "
	  "clockwise from north (degree)."); /* TODO: clockwise from north? see r.ros */

    parm.base = G_define_option();
    parm.base->key = "base";
    parm.base->type = TYPE_STRING;
    parm.base->required = YES;
    parm.base->gisprompt = "old,cell,raster";
    parm.base->guisection = _("Input maps");
    parm.base->label =
	_("Raster map containing base ROS (cm/min)");
    parm.base->description =
	_("Name of an existing raster map layer in the user's "
	  "current mapset search path containing the ROS values in the directions "
	  "perpendicular to maximum ROSes' (cm/minute). These ROSes are also the ones "
	  "without the effect of directional factors.");

    parm.start = G_define_option();
    parm.start->key = "start";
    parm.start->type = TYPE_STRING;
    parm.start->required = YES;
    parm.start->gisprompt = "old,cell,raster";
    parm.start->guisection = _("Input maps");
    parm.start->description =
	_("Raster map containing starting sources");
    parm.start->description =
	_("Name of an existing raster map layer in the "
	  "user's current mapset search path containing starting locations of the "
	  "spread phenomenon. Any positive integers in this map are recognized as "
	  "starting sources (seeds).");

    parm.spotdist = G_define_option();
    parm.spotdist->key = "spot_dist";
    parm.spotdist->type = TYPE_STRING;
    parm.spotdist->gisprompt = "old,cell,raster";
    parm.spotdist->guisection = _("Input maps");
    parm.spotdist->label =
	_("Raster map containing maximal spotting distance (m, required with -s)");
    parm.spotdist->description =
	_("Name of an existing raster map layer in "
	  "the user's current mapset search path containing the maximum potential "
	  "spotting distances (meters).");

    parm.velocity = G_define_option();
    parm.velocity->key = "w_speed";
    parm.velocity->type = TYPE_STRING;
    parm.velocity->gisprompt = "old,cell,raster";
    parm.velocity->guisection = _("Input maps");
    parm.velocity->label =
	_("Raster map containing midflame wind speed (ft/min, required with -s)");
    parm.velocity->description =
	_("Name of an existing raster map layer in the "
	  "user's current mapset search path containing wind velocities at half of "
	  "the average flame height (feet/minute).");

    parm.mois = G_define_option();
    parm.mois->key = "f_mois";
    parm.mois->type = TYPE_STRING;
    parm.mois->gisprompt = "old,cell,raster";
    parm.mois->guisection = _("Input maps");
    parm.mois->label =
	_("Raster map containing fine fuel moisture of the cell receiving a spotting firebrand (%, required with -s)");
    parm.mois->description =
	_("Name of an existing raster map layer in the "
	  "user's current mapset search path containing the 1-hour (<.25\") fuel "
	  "moisture (percentage content multiplied by 100).");

    parm.least = G_define_option();
    parm.least->key = "least_size";
    parm.least->type = TYPE_STRING;
    parm.least->key_desc = "odd int";
    parm.least->options = "3,5,7,9,11,13,15";
    parm.least->description =
	_("Basic sampling window size needed to meet certain accuracy (3)"); /* TODO: what is 3 here? default? */
    parm.least->description =
	_("An odd integer ranging 3 - 15 indicating "
	  "the basic sampling window size within which all cells will be considered "
	  "to see whether they will be reached by the current spread cell. The default "
	  "number is 3 which means a 3x3 window.");

    parm.comp_dens = G_define_option();
    parm.comp_dens->key = "comp_dens";
    parm.comp_dens->type = TYPE_STRING;
    parm.comp_dens->key_desc = "decimal";
    parm.comp_dens->label =
	_("Sampling density for additional computing (range: 0.0 - 1.0 (0.5))"); /* TODO: again, what is 0.5?, TODO: range not set */
    parm.comp_dens->description =
	_("A decimal number ranging 0.0 - 1.0 indicating "
	  "additional sampling cells will be considered to see whether they will be "
	  "reached by the current spread cell. The closer to 1.0 the decimal number "
	  "is, the longer the program will run and the higher the simulation accuracy "
	  "will be. The default number is 0.5.");

    parm.init_time = G_define_option();
    parm.init_time->key = "init_time";
    parm.init_time->type = TYPE_STRING;
    parm.init_time->key_desc = "int (>= 0)"; /* TODO: move to ->options */
    parm.init_time->answer = "0";
    parm.init_time->label =
	_("Initial time for current simulation (0) (min)");
    parm.init_time->description =
	_("A non-negative number specifying the initial "
	  "time for the current spread simulation (minutes). This is useful when multiple "
	  "phase simulation is conducted. The default time is 0.");

    parm.time_lag = G_define_option();
    parm.time_lag->key = "lag";
    parm.time_lag->type = TYPE_STRING;
    parm.time_lag->key_desc = "int (>= 0)"; /* TODO: move to ->options */
    parm.time_lag->description =
	_("Simulating time duration LAG (fill the region) (min)"); /* TODO: what does this mean? */
    parm.time_lag->description =
	_("A non-negative integer specifying the simulating "
	  "duration time lag (minutes). The default is infinite, but the program will "
	  "terminate when the current geographic region/mask has been filled. It also "
	  "controls the computational time, the shorter the time lag, the faster the "
	  "program will run.");

    /* TODO: what's this? probably display, so remove */
    parm.backdrop = G_define_option();
    parm.backdrop->key = "backdrop";
    parm.backdrop->type = TYPE_STRING;
    parm.backdrop->gisprompt = "old,cell,raster";
    parm.backdrop->label =
	_("Name of raster map as a display backdrop");
    parm.backdrop->description =
	_("Name of an existing raster map layer in the "
	  "user's current mapset search path to be used as the background on which "
	  "the \"live\" movement will be shown.");

    parm.out = G_define_option();
    parm.out->key = "output";
    parm.out->type = TYPE_STRING;
    parm.out->required = YES;
    parm.out->gisprompt = "new,cell,raster";
    parm.out->guisection = _("Output maps");
    parm.out->label =
	_("Raster map to contain output spread time (min)");
    parm.out->description =
	_("Name of the new raster map layer to contain "
	  "the results of the cumulative spread time needed for a phenomenon to reach "
	  "each cell from the starting sources (minutes).");

    parm.x_out = G_define_option();
    parm.x_out->key = "x_output";
    parm.x_out->type = TYPE_STRING;
    parm.x_out->gisprompt = "new,cell,raster";
    parm.x_out->guisection = _("Output maps");
    parm.x_out->label =
	_("Name of raster map to contain X back coordinates");
    parm.x_out->description =
	_("Name of the new raster map layer to contain "
	  "the results of backlink information in UTM easting coordinates for each "
	  "cell.");

    parm.y_out = G_define_option();
    parm.y_out->key = "y_output";
    parm.y_out->type = TYPE_STRING;
    parm.y_out->gisprompt = "new,cell,raster";
    parm.y_out->guisection = _("Output maps");
    parm.y_out->label =
	_("Name of raster map to contain Y back coordinates");
    parm.y_out->description =
	_("Name of the new raster map layer to contain "
	  "the results of backlink information in UTM northing coordinates for each "
	  "cell.");

    flag.display = G_define_flag();
    flag.display->key = 'd';
#if 0
    flag.display->label = _("DISPLAY 'live' spread process on screen");
    flag.display->description =
	_("Display the 'live' simulation on screen. A graphics window "
	  "must be opened and selected before using this option.");
#else
    flag.display->description = _("Live display - disabled and depreciated");
#endif

    flag.spotting = G_define_flag();
    flag.spotting->key = 's';
    flag.spotting->description = _("Consider spotting effect (for wildfires)");

    flag.start_is_time = G_define_flag();
    flag.start_is_time->key = 'i';
    flag.start_is_time->label = _("Use start raster map values in"
	" output spread time raster map");
    flag.start_is_time->description = _("Designed to be used with output"
	" of previous run of r.spread when computing spread iteratively."
	" The values in start raster map are considered as time."
	" Allowed values in raster map are from zero"
	" to the value of init_time option."
	" If not enabled, init_time is used in the area of start raster map");

    /*   Parse command line */
    if (G_parser(argc, argv))
	exit(EXIT_FAILURE);


    /* FIXME - allow seed to be specified for repeatability */
    G_srand48_auto();

    display = flag.display->answer;
#if 1
    if (display)
	G_fatal_error(_("The display feature is disabled"));
#endif
    spotting = flag.spotting->answer;

    max_layer = parm.max->answer;
    dir_layer = parm.dir->answer;
    base_layer = parm.base->answer;
    start_layer = parm.start->answer;
    backdrop_layer = parm.backdrop->answer;
    out_layer = parm.out->answer;
    if (parm.x_out->answer) {
	x_out = 1;
	x_out_layer = parm.x_out->answer;
    }
    if (parm.y_out->answer) {
	y_out = 1;
	y_out_layer = parm.y_out->answer;
    }
    if (spotting) {
	if (!
	    (parm.spotdist->answer && parm.velocity->answer &&
	     parm.mois->answer)) {
	    G_warning
		("SPOTTING DISTANCE, fuel MOISTURE, or wind VELOCITY map not given w/ -s");
	    G_usage();
	    exit(EXIT_FAILURE);
	}
	else {
	    spotdist_layer = parm.spotdist->answer;
	    velocity_layer = parm.velocity->answer;
	    mois_layer = parm.mois->answer;
	}
    }
    /*Check the given the least sampling size, assign the default if needed */
    if (parm.least->answer)
	least = atoi(parm.least->answer);
    else
	least = 3;
    /*Check the given computing density, assign the default if needed */
    if (parm.comp_dens->answer) {
	comp_dens = atof(parm.comp_dens->answer);
	if (comp_dens < 0.0 || comp_dens > 1.0) {
	    G_warning("Illegal computing density <%s>",
		      parm.comp_dens->answer);
	    G_usage();
	    exit(EXIT_FAILURE);
	}
    }
    else {
	comp_dens = 0.5;
    }
    /*Check the given initial time and simulation time lag, assign the default if needed */
    init_time = atoi(parm.init_time->answer);
    if (init_time < 0) {
	G_warning("Illegal initial time <%s>", parm.init_time->answer);
	G_usage();
	exit(EXIT_FAILURE);
    }

    if (parm.time_lag->answer) {
	time_lag = atoi(parm.time_lag->answer);
	if (time_lag < 0) {
	    G_warning("Illegal simulating time lag <%s>",
		      parm.time_lag->answer);
	    G_usage();
	    exit(EXIT_FAILURE);
	}
    }
    else {
	time_lag = 99999;
    }

    /*  Get database window parameters  */

    G_get_window(&window);

    /*  find number of rows and columns in window    */

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

    /*transfor measurement unit from meters to centimeters due to ROS unit
     *if the input ROSs are in m/min units, cancell the following*/
    window.ns_res = 100 * window.ns_res;
    window.ew_res = 100 * window.ew_res;

    /* Initialize display screens */
#if 0
    if (display)
	display_init();
#endif

    /*  Check if input layers exists in data base  */

    if (G_find_raster2(max_layer, "") == NULL)
	G_fatal_error("Raster map <%s> not found", max_layer);

    if (G_find_raster2(dir_layer, "") == NULL)
	G_fatal_error(_("Raster map <%s> not found"), dir_layer);

    if (G_find_raster2(base_layer, "") == NULL)
	G_fatal_error(_("Raster map <%s> not found"), base_layer);

    if (G_find_raster2(start_layer, "") == NULL)
	G_fatal_error(_("Raster map <%s> not found"), start_layer);

    if (spotting) {
	if (G_find_raster2(spotdist_layer, "") == NULL)
	    G_fatal_error(_("Raster map <%s> not found"), spotdist_layer);

	if (G_find_raster2(velocity_layer, "") == NULL)
	    G_fatal_error(_("Raster map <%s> not found"), velocity_layer);

	if (G_find_raster2(mois_layer, "") == NULL)
	    G_fatal_error(_("Raster map <%s> not found"), mois_layer);
    }

    /*  Open input cell layers for reading  */

    max_fd = Rast_open_old(max_layer, G_find_raster2(max_layer, ""));

    dir_fd = Rast_open_old(dir_layer, G_find_raster2(dir_layer, ""));

    base_fd = Rast_open_old(base_layer, G_find_raster2(base_layer, ""));

    if (spotting) {
	spotdist_fd =
	    Rast_open_old(spotdist_layer, G_find_raster2(spotdist_layer, ""));

	velocity_fd =
	    Rast_open_old(velocity_layer, G_find_raster2(velocity_layer, ""));

	mois_fd = Rast_open_old(mois_layer, G_find_raster2(mois_layer, ""));
    }

    /*  Allocate memories for a row  */
    cell = Rast_allocate_c_buf();
    if (x_out)
	x_cell = Rast_allocate_c_buf();
    if (y_out)
	y_cell = Rast_allocate_c_buf();

    /*  Allocate memories for a map  */
    map_max = (CELL *) G_calloc(nrows * ncols + 1, sizeof(CELL));
    map_dir = (CELL *) G_calloc(nrows * ncols + 1, sizeof(CELL));
    map_base = (CELL *) G_calloc(nrows * ncols + 1, sizeof(CELL));
    map_visit = (CELL *) G_calloc(nrows * ncols + 1, sizeof(CELL));
    map_out = (float *)G_calloc(nrows * ncols + 1, sizeof(float));
    if (spotting) {
	map_spotdist = (CELL *) G_calloc(nrows * ncols + 1, sizeof(CELL));
	map_velocity = (CELL *) G_calloc(nrows * ncols + 1, sizeof(CELL));
	map_mois = (CELL *) G_calloc(nrows * ncols + 1, sizeof(CELL));
    }
    if (x_out)
	map_x_out = (CELL *) G_calloc(nrows * ncols + 1, sizeof(CELL));
    if (y_out)
	map_y_out = (CELL *) G_calloc(nrows * ncols + 1, sizeof(CELL));


    /*   Write the input layers in the map "arrays"  */

    G_message(_("Reading inputs..."));

    for (row = 0; row < nrows; row++) {
	G_percent(row, nrows, 2);
	Rast_get_c_row(max_fd, cell, row);
	for (col = 0; col < ncols; col++)
	    DATA(map_max, row, col) = cell[col];
	Rast_get_c_row(dir_fd, cell, row);
	for (col = 0; col < ncols; col++)
	    DATA(map_dir, row, col) = cell[col];
	Rast_get_c_row(base_fd, cell, row);
	for (col = 0; col < ncols; col++)
	    DATA(map_base, row, col) = cell[col];
	if (spotting) {
	    Rast_get_c_row(spotdist_fd, cell, row);
	    for (col = 0; col < ncols; col++)
		DATA(map_spotdist, row, col) = cell[col];
	    Rast_get_c_row(velocity_fd, cell, row);
	    for (col = 0; col < ncols; col++)
		DATA(map_velocity, row, col) = cell[col];
	    Rast_get_c_row(mois_fd, cell, row);
	    for (col = 0; col < ncols; col++)
		DATA(map_mois, row, col) = cell[col];
	}
    }
    G_percent(row, nrows, 2);


    /*   Scan the START layer searching for starting points.
     *   Create an array of starting points (min_heap) ordered by costs.
     */

    start_fd = Rast_open_old(start_layer, G_find_raster2(start_layer, ""));

    Rast_read_range(start_layer, G_find_file("cell", start_layer, ""),
		    &start_range);
    Rast_get_range_min_max(&start_range, &start_range_min, &start_range_max);

    start_is_time = flag.start_is_time->answer;
    /* values higher than init_time are unexpected and may cause segfaults */
    if (start_is_time && start_range_max > init_time)
	G_fatal_error(_("Maximum of start raster map is grater than init_time"
			" (%d > %d)"), start_range_max, init_time);
    /* values lower then zero does not make sense for time */
    if (start_is_time && start_range_min < 0)
	G_fatal_error(_("Minimum of start raster map is less than zero"
			" (%d < 0)"), start_range_min, init_time);

    /*  Initialize the heap  */
    heap =
	(struct costHa *)G_calloc(nrows * ncols + 1, sizeof(struct costHa));
    heap_len = 0;

    G_message(_("Reading %s..."), start_layer);
    G_debug(1, "Collecting origins...");
    collect_ori(start_fd, start_is_time);
    G_debug(1, "Done");


    /* Major computation of spread time */
    G_debug(1, "Spreading...");
    spread();
    G_debug(1, "Done");


    /*  Open cumulative cost layer (and x, y direction layers) for writing */

    cum_fd = Rast_open_c_new(out_layer);
    if (x_out)
	x_fd = Rast_open_c_new(x_out_layer);
    if (y_out)
	y_fd = Rast_open_c_new(y_out_layer);

    /* prepare output -- adjust from cm to m */
    window.ew_res = window.ew_res / 100;
    window.ns_res = window.ns_res / 100;

    /* copy maps in ram to output maps */
    ram2out();

    G_free(map_max);
    G_free(map_dir);
    G_free(map_base);
    G_free(map_out);
    G_free(map_visit);
    if (x_out)
	G_free(map_x_out);
    if (y_out)
	G_free(map_y_out);
    if (spotting) {
	G_free(map_spotdist);
	G_free(map_mois);
	G_free(map_velocity);
    }

    Rast_close(max_fd);
    Rast_close(dir_fd);
    Rast_close(base_fd);
    Rast_close(start_fd);
    Rast_close(cum_fd);
    if (x_out)
	Rast_close(x_fd);
    if (y_out)
	Rast_close(y_fd);
    if (spotting) {
	Rast_close(spotdist_fd);
	Rast_close(velocity_fd);
	Rast_close(mois_fd);
    }

    /* close graphics */
#if 0
    if (display)
	display_close();
#endif

    exit(EXIT_SUCCESS);
}