Exemple #1
0
int main(int argc, char *argv[])
{

    FILE *in_fp;
    int out_fd;
    char *infile, *outmap;
    int xcol, ycol, zcol, max_col, percent;
    int do_zfilter;
    int method = -1;
    int bin_n, bin_min, bin_max, bin_sum, bin_sumsq, bin_index;
    double zrange_min, zrange_max, d_tmp;
    char *fs;			/* field delim */
    off_t filesize;
    int linesize;
    long estimated_lines;
    int from_stdin;
    int can_seek;

    RASTER_MAP_TYPE rtype;
    struct History history;
    char title[64];
    void *n_array, *min_array, *max_array, *sum_array, *sumsq_array,
	*index_array;
    void *raster_row, *ptr;
    struct Cell_head region;
    int rows, cols;		/* scan box size */
    int row, col;		/* counters */

    int pass, npasses;
    unsigned long line;
    char buff[BUFFSIZE];
    double x, y, z;
    char **tokens;
    int ntokens;		/* number of tokens */
    double pass_north, pass_south;
    int arr_row, arr_col;
    unsigned long count, count_total;

    double min = 0.0 / 0.0;	/* init as nan */
    double max = 0.0 / 0.0;	/* init as nan */
    double zscale = 1.0;
    size_t offset, n_offset;
    int n = 0;
    double sum = 0.;
    double sumsq = 0.;
    double variance, mean, skew, sumdev;
    int pth = 0;
    double trim = 0.0;

    int j, k;
    int head_id, node_id;
    int r_low, r_up;

    struct GModule *module;
    struct Option *input_opt, *output_opt, *delim_opt, *percent_opt,
	*type_opt;
    struct Option *method_opt, *xcol_opt, *ycol_opt, *zcol_opt, *zrange_opt,
	*zscale_opt;
    struct Option *trim_opt, *pth_opt;
    struct Flag *scan_flag, *shell_style, *skipline;


    G_gisinit(argv[0]);

    module = G_define_module();
    module->keywords = _("raster, import, LIDAR");
    module->description =
	_("Create a raster map from an assemblage of many coordinates using univariate statistics.");

    input_opt = G_define_standard_option(G_OPT_F_INPUT);
    input_opt->description =
	_("ASCII file containing input data (or \"-\" to read from stdin)");

    output_opt = G_define_standard_option(G_OPT_R_OUTPUT);

    method_opt = G_define_option();
    method_opt->key = "method";
    method_opt->type = TYPE_STRING;
    method_opt->required = NO;
    method_opt->description = _("Statistic to use for raster values");
    method_opt->options =
	"n,min,max,range,sum,mean,stddev,variance,coeff_var,median,percentile,skewness,trimmean";
    method_opt->answer = "mean";
    method_opt->guisection = _("Statistic");

    type_opt = G_define_option();
    type_opt->key = "type";
    type_opt->type = TYPE_STRING;
    type_opt->required = NO;
    type_opt->options = "CELL,FCELL,DCELL";
    type_opt->answer = "FCELL";
    type_opt->description = _("Storage type for resultant raster map");

    delim_opt = G_define_standard_option(G_OPT_F_SEP);
    delim_opt->guisection = _("Input");

    xcol_opt = G_define_option();
    xcol_opt->key = "x";
    xcol_opt->type = TYPE_INTEGER;
    xcol_opt->required = NO;
    xcol_opt->answer = "1";
    xcol_opt->description =
	_("Column number of x coordinates in input file (first column is 1)");
    xcol_opt->guisection = _("Input");

    ycol_opt = G_define_option();
    ycol_opt->key = "y";
    ycol_opt->type = TYPE_INTEGER;
    ycol_opt->required = NO;
    ycol_opt->answer = "2";
    ycol_opt->description = _("Column number of y coordinates in input file");
    ycol_opt->guisection = _("Input");

    zcol_opt = G_define_option();
    zcol_opt->key = "z";
    zcol_opt->type = TYPE_INTEGER;
    zcol_opt->required = NO;
    zcol_opt->answer = "3";
    zcol_opt->description = _("Column number of data values in input file");
    zcol_opt->guisection = _("Input");

    zrange_opt = G_define_option();
    zrange_opt->key = "zrange";
    zrange_opt->type = TYPE_DOUBLE;
    zrange_opt->required = NO;
    zrange_opt->key_desc = "min,max";
    zrange_opt->description = _("Filter range for z data (min,max)");

    zscale_opt = G_define_option();
    zscale_opt->key = "zscale";
    zscale_opt->type = TYPE_DOUBLE;
    zscale_opt->required = NO;
    zscale_opt->answer = "1.0";
    zscale_opt->description = _("Scale to apply to z data");

    percent_opt = G_define_option();
    percent_opt->key = "percent";
    percent_opt->type = TYPE_INTEGER;
    percent_opt->required = NO;
    percent_opt->answer = "100";
    percent_opt->options = "1-100";
    percent_opt->description = _("Percent of map to keep in memory");

    pth_opt = G_define_option();
    pth_opt->key = "pth";
    pth_opt->type = TYPE_INTEGER;
    pth_opt->required = NO;
    pth_opt->options = "1-100";
    pth_opt->description = _("pth percentile of the values");
    pth_opt->guisection = _("Statistic");

    trim_opt = G_define_option();
    trim_opt->key = "trim";
    trim_opt->type = TYPE_DOUBLE;
    trim_opt->required = NO;
    trim_opt->options = "0-50";
    trim_opt->description =
	_("Discard <trim> percent of the smallest and <trim> percent of the largest observations");
    trim_opt->guisection = _("Statistic");

    scan_flag = G_define_flag();
    scan_flag->key = 's';
    scan_flag->description = _("Scan data file for extent then exit");

    shell_style = G_define_flag();
    shell_style->key = 'g';
    shell_style->description =
	_("In scan mode, print using shell script style");

    skipline = G_define_flag();
    skipline->key = 'i';
    skipline->description = _("Ignore broken lines");

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


    /* parse input values */
    infile = input_opt->answer;
    outmap = output_opt->answer;

    if (shell_style->answer && !scan_flag->answer) {
	scan_flag->answer = 1;
    }

    fs = delim_opt->answer;
    if (strcmp(fs, "\\t") == 0)
	fs = "\t";
    if (strcmp(fs, "tab") == 0)
	fs = "\t";
    if (strcmp(fs, "space") == 0)
	fs = " ";

    xcol = atoi(xcol_opt->answer);
    ycol = atoi(ycol_opt->answer);
    zcol = atoi(zcol_opt->answer);
    if ((xcol < 0) || (ycol < 0) || (zcol < 0))
	G_fatal_error(_("Please specify a reasonable column number."));
    max_col = (xcol > ycol) ? xcol : ycol;
    max_col = (zcol > max_col) ? zcol : max_col;

    percent = atoi(percent_opt->answer);
    zscale = atof(zscale_opt->answer);

    /* parse zrange */
    do_zfilter = FALSE;
    if (zrange_opt->answer != NULL) {
	if (zrange_opt->answers[0] == NULL)
	    G_fatal_error(_("Invalid zrange"));

	sscanf(zrange_opt->answers[0], "%lf", &zrange_min);
	sscanf(zrange_opt->answers[1], "%lf", &zrange_max);
	do_zfilter = TRUE;

	if (zrange_min > zrange_max) {
	    d_tmp = zrange_max;
	    zrange_max = zrange_min;
	    zrange_min = d_tmp;
	}
    }

    /* figure out what maps we need in memory */
    /*  n               n
       min              min
       max              max
       range            min max         max - min
       sum              sum
       mean             sum n           sum/n
       stddev           sum sumsq n     sqrt((sumsq - sum*sum/n)/n)
       variance         sum sumsq n     (sumsq - sum*sum/n)/n
       coeff_var        sum sumsq n     sqrt((sumsq - sum*sum/n)/n) / (sum/n)
       median           n               array index to linked list
       percentile       n               array index to linked list
       skewness         n               array index to linked list
       trimmean         n               array index to linked list
     */
    bin_n = FALSE;
    bin_min = FALSE;
    bin_max = FALSE;
    bin_sum = FALSE;
    bin_sumsq = FALSE;
    bin_index = FALSE;

    if (strcmp(method_opt->answer, "n") == 0) {
	method = METHOD_N;
	bin_n = TRUE;
    }
    if (strcmp(method_opt->answer, "min") == 0) {
	method = METHOD_MIN;
	bin_min = TRUE;
    }
    if (strcmp(method_opt->answer, "max") == 0) {
	method = METHOD_MAX;
	bin_max = TRUE;
    }
    if (strcmp(method_opt->answer, "range") == 0) {
	method = METHOD_RANGE;
	bin_min = TRUE;
	bin_max = TRUE;
    }
    if (strcmp(method_opt->answer, "sum") == 0) {
	method = METHOD_SUM;
	bin_sum = TRUE;
    }
    if (strcmp(method_opt->answer, "mean") == 0) {
	method = METHOD_MEAN;
	bin_sum = TRUE;
	bin_n = TRUE;
    }
    if (strcmp(method_opt->answer, "stddev") == 0) {
	method = METHOD_STDDEV;
	bin_sum = TRUE;
	bin_sumsq = TRUE;
	bin_n = TRUE;
    }
    if (strcmp(method_opt->answer, "variance") == 0) {
	method = METHOD_VARIANCE;
	bin_sum = TRUE;
	bin_sumsq = TRUE;
	bin_n = TRUE;
    }
    if (strcmp(method_opt->answer, "coeff_var") == 0) {
	method = METHOD_COEFF_VAR;
	bin_sum = TRUE;
	bin_sumsq = TRUE;
	bin_n = TRUE;
    }
    if (strcmp(method_opt->answer, "median") == 0) {
	method = METHOD_MEDIAN;
	bin_index = TRUE;
    }
    if (strcmp(method_opt->answer, "percentile") == 0) {
	if (pth_opt->answer != NULL)
	    pth = atoi(pth_opt->answer);
	else
	    G_fatal_error(_("Unable to calculate percentile without the pth option specified!"));
	method = METHOD_PERCENTILE;
	bin_index = TRUE;
    }
    if (strcmp(method_opt->answer, "skewness") == 0) {
	method = METHOD_SKEWNESS;
	bin_index = TRUE;
    }
    if (strcmp(method_opt->answer, "trimmean") == 0) {
	if (trim_opt->answer != NULL)
	    trim = atof(trim_opt->answer) / 100.0;
	else
	    G_fatal_error(_("Unable to calculate trimmed mean without the trim option specified!"));
	method = METHOD_TRIMMEAN;
	bin_index = TRUE;
    }

    if (strcmp("CELL", type_opt->answer) == 0)
	rtype = CELL_TYPE;
    else if (strcmp("DCELL", type_opt->answer) == 0)
	rtype = DCELL_TYPE;
    else
	rtype = FCELL_TYPE;

    if (method == METHOD_N)
	rtype = CELL_TYPE;


    G_get_window(&region);
    rows = (int)(region.rows * (percent / 100.0));
    cols = region.cols;

    G_debug(2, "region.n=%f  region.s=%f  region.ns_res=%f", region.north,
	    region.south, region.ns_res);
    G_debug(2, "region.rows=%d  [box_rows=%d]  region.cols=%d", region.rows,
	    rows, region.cols);

    npasses = (int)ceil(1.0 * region.rows / rows);

    if (!scan_flag->answer) {
	/* allocate memory (test for enough before we start) */
	if (bin_n)
	    n_array = G_calloc(rows * (cols + 1), G_raster_size(CELL_TYPE));
	if (bin_min)
	    min_array = G_calloc(rows * (cols + 1), G_raster_size(rtype));
	if (bin_max)
	    max_array = G_calloc(rows * (cols + 1), G_raster_size(rtype));
	if (bin_sum)
	    sum_array = G_calloc(rows * (cols + 1), G_raster_size(rtype));
	if (bin_sumsq)
	    sumsq_array = G_calloc(rows * (cols + 1), G_raster_size(rtype));
	if (bin_index)
	    index_array =
		G_calloc(rows * (cols + 1), G_raster_size(CELL_TYPE));

	/* and then free it again */
	if (bin_n)
	    G_free(n_array);
	if (bin_min)
	    G_free(min_array);
	if (bin_max)
	    G_free(max_array);
	if (bin_sum)
	    G_free(sum_array);
	if (bin_sumsq)
	    G_free(sumsq_array);
	if (bin_index)
	    G_free(index_array);

	/** end memory test **/
    }


    /* open input file */
    if (strcmp("-", infile) == 0) {
	from_stdin = TRUE;
	in_fp = stdin;
	infile = G_store("stdin");	/* filename for history metadata */
    }
    else {
	if ((in_fp = fopen(infile, "r")) == NULL)
	    G_fatal_error(_("Unable to open input file <%s>"), infile);
    }

    can_seek = fseek(in_fp, 0, SEEK_SET) == 0;

    /* can't rewind() non-files */
    if (!can_seek && npasses != 1) {
	G_warning(_("If input is not from a file it is only possible to perform a single pass."));
	npasses = 1;
    }

    if (scan_flag->answer) {
	if (zrange_opt->answer)
	    G_warning(_("zrange will not be taken into account during scan"));

	scan_bounds(in_fp, xcol, ycol, zcol, fs, shell_style->answer,
		    skipline->answer, zscale);

	if (!from_stdin)
	    fclose(in_fp);

	exit(EXIT_SUCCESS);
    }


    /* open output map */
    out_fd = G_open_raster_new(outmap, rtype);
    if (out_fd < 0)
	G_fatal_error(_("Unable to create raster map <%s>"), outmap);

    if (can_seek) {
	/* guess at number of lines in the file without actually reading it all in */
	for (line = 0; line < 10; line++) {	/* arbitrarily use 10th line for guess */
	    if (0 == G_getl2(buff, BUFFSIZE - 1, in_fp))
		break;
	    linesize = strlen(buff) + 1;
	}
	fseek(in_fp, 0L, SEEK_END);
	filesize = ftell(in_fp);
	rewind(in_fp);
	if (linesize < 6)	/* min possible: "0,0,0\n" */
	    linesize = 6;
	estimated_lines = filesize / linesize;
	G_debug(2, "estimated number of lines in file: %ld", estimated_lines);
    }
    else
	estimated_lines = -1;

    /* allocate memory for a single row of output data */
    raster_row = G_allocate_raster_buf(rtype);

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

    count_total = 0;

    /* main binning loop(s) */
    for (pass = 1; pass <= npasses; pass++) {
	if (npasses > 1)
	    G_message(_("Pass #%d (of %d) ..."), pass, npasses);

	if (can_seek)
	    rewind(in_fp);

	/* figure out segmentation */
	pass_north = region.north - (pass - 1) * rows * region.ns_res;
	if (pass == npasses)
	    rows = region.rows - (pass - 1) * rows;
	pass_south = pass_north - rows * region.ns_res;

	G_debug(2, "pass=%d/%d  pass_n=%f  pass_s=%f  rows=%d",
		pass, npasses, pass_north, pass_south, rows);


	if (bin_n) {
	    G_debug(2, "allocating n_array");
	    n_array = G_calloc(rows * (cols + 1), G_raster_size(CELL_TYPE));
	    blank_array(n_array, rows, cols, CELL_TYPE, 0);
	}
	if (bin_min) {
	    G_debug(2, "allocating min_array");
	    min_array = G_calloc(rows * (cols + 1), G_raster_size(rtype));
	    blank_array(min_array, rows, cols, rtype, -1);	/* fill with NULLs */
	}
	if (bin_max) {
	    G_debug(2, "allocating max_array");
	    max_array = G_calloc(rows * (cols + 1), G_raster_size(rtype));
	    blank_array(max_array, rows, cols, rtype, -1);	/* fill with NULLs */
	}
	if (bin_sum) {
	    G_debug(2, "allocating sum_array");
	    sum_array = G_calloc(rows * (cols + 1), G_raster_size(rtype));
	    blank_array(sum_array, rows, cols, rtype, 0);
	}
	if (bin_sumsq) {
	    G_debug(2, "allocating sumsq_array");
	    sumsq_array = G_calloc(rows * (cols + 1), G_raster_size(rtype));
	    blank_array(sumsq_array, rows, cols, rtype, 0);
	}
	if (bin_index) {
	    G_debug(2, "allocating index_array");
	    index_array =
		G_calloc(rows * (cols + 1), G_raster_size(CELL_TYPE));
	    blank_array(index_array, rows, cols, CELL_TYPE, -1);	/* fill with NULLs */
	}

	line = 0;
	count = 0;
	G_percent_reset();

	while (0 != G_getl2(buff, BUFFSIZE - 1, in_fp)) {
	    line++;

	    if (line % 10000 == 0) {	/* mod for speed */
		if (!can_seek)
		    G_clicker();
		else if (line < estimated_lines)
		    G_percent(line, estimated_lines, 3);
	    }

	    if ((buff[0] == '#') || (buff[0] == '\0')) {
		continue;	/* line is a comment or blank */
	    }

	    G_chop(buff);	/* remove leading and trailing whitespace from the string.  unneded?? */
	    tokens = G_tokenize(buff, fs);
	    ntokens = G_number_of_tokens(tokens);

	    if ((ntokens < 3) || (max_col > ntokens)) {
		if (skipline->answer) {
		    G_warning(_("Not enough data columns. "
				"Incorrect delimiter or column number? "
				"Found the following character(s) in row %lu:\n[%s]"),
			      line, buff);
		    G_warning(_("Line ignored as requested"));
		    continue;	/* line is garbage */
		}
		else {
		    G_fatal_error(_("Not enough data columns. "
				    "Incorrect delimiter or column number? "
				    "Found the following character(s) in row %lu:\n[%s]"),
				  line, buff);
		}
	    }

	    /* too slow?
	       if ( G_projection() == PROJECTION_LL ) {
	       G_scan_easting( tokens[xcol-1], &x, region.proj);
	       G_scan_northing( tokens[ycol-1], &y, region.proj);
	       }
	       else {
	     */
	    if (1 != sscanf(tokens[ycol - 1], "%lf", &y))
		G_fatal_error(_("Bad y-coordinate line %lu column %d. <%s>"),
			      line, ycol, tokens[ycol - 1]);
	    if (y <= pass_south || y > pass_north) {
		G_free_tokens(tokens);
		continue;
	    }
	    if (1 != sscanf(tokens[xcol - 1], "%lf", &x))
		G_fatal_error(_("Bad x-coordinate line %lu column %d. <%s>"),
			      line, xcol, tokens[xcol - 1]);
	    if (x < region.west || x > region.east) {
		G_free_tokens(tokens);
		continue;
	    }
	    if (1 != sscanf(tokens[zcol - 1], "%lf", &z))
		G_fatal_error(_("Bad z-coordinate line %lu column %d. <%s>"),
			      line, zcol, tokens[zcol - 1]);

	    z = z * zscale;

	    if (zrange_opt->answer) {
		if (z < zrange_min || z > zrange_max) {
		    G_free_tokens(tokens);
		    continue;
		}
	    }

	    count++;
	    /*          G_debug(5, "x: %f, y: %f, z: %f", x, y, z); */
	    G_free_tokens(tokens);

	    /* find the bin in the current array box */
	    arr_row = (int)((pass_north - y) / region.ns_res);
	    arr_col = (int)((x - region.west) / region.ew_res);

	    /*          G_debug(5, "arr_row: %d   arr_col: %d", arr_row, arr_col); */

	    /* The range should be [0,cols-1]. We use (int) to round down,
	       but if the point exactly on eastern edge arr_col will be /just/
	       on the max edge .0000000 and end up on the next row.
	       We could make above bounds check "if(x>=region.east) continue;"
	       But instead we go to all sorts of trouble so that not one single
	       data point is lost. GE is too small to catch them all.
	       We don't try to make y happy as percent segmenting will make some
	       points happen twice that way; so instead we use the y<= test above.
	     */
	    if (arr_col >= cols) {
		if (((x - region.west) / region.ew_res) - cols <
		    10 * GRASS_EPSILON)
		    arr_col--;
		else {		/* oh well, we tried. */
		    G_debug(3,
			    "skipping extraneous data point [%.3f], column %d of %d",
			    x, arr_col, cols);
		    continue;
		}
	    }

	    if (bin_n)
		update_n(n_array, cols, arr_row, arr_col);
	    if (bin_min)
		update_min(min_array, cols, arr_row, arr_col, rtype, z);
	    if (bin_max)
		update_max(max_array, cols, arr_row, arr_col, rtype, z);
	    if (bin_sum)
		update_sum(sum_array, cols, arr_row, arr_col, rtype, z);
	    if (bin_sumsq)
		update_sumsq(sumsq_array, cols, arr_row, arr_col, rtype, z);
	    if (bin_index) {
		ptr = index_array;
		ptr =
		    G_incr_void_ptr(ptr,
				    ((arr_row * cols) +
				     arr_col) * G_raster_size(CELL_TYPE));

		if (G_is_null_value(ptr, CELL_TYPE)) {	/* first node */
		    head_id = new_node();
		    nodes[head_id].next = -1;
		    nodes[head_id].z = z;
		    G_set_raster_value_c(ptr, head_id, CELL_TYPE);	/* store index to head */
		}
		else {		/* head is already there */

		    head_id = G_get_raster_value_c(ptr, CELL_TYPE);	/* get index to head */
		    head_id = add_node(head_id, z);
		    if (head_id != -1)
			G_set_raster_value_c(ptr, head_id, CELL_TYPE);	/* store index to head */
		}
	    }
	}			/* while !EOF */

	G_percent(1, 1, 1);	/* flush */
	G_debug(2, "pass %d finished, %lu coordinates in box", pass, count);
	count_total += count;


	/* calc stats and output */
	G_message(_("Writing to map ..."));
	for (row = 0; row < rows; row++) {

	    switch (method) {
	    case METHOD_N:	/* n is a straight copy */
		G_raster_cpy(raster_row,
			     n_array +
			     (row * cols * G_raster_size(CELL_TYPE)), cols,
			     CELL_TYPE);
		break;

	    case METHOD_MIN:
		G_raster_cpy(raster_row,
			     min_array + (row * cols * G_raster_size(rtype)),
			     cols, rtype);
		break;

	    case METHOD_MAX:
		G_raster_cpy(raster_row,
			     max_array + (row * cols * G_raster_size(rtype)),
			     cols, rtype);
		break;

	    case METHOD_SUM:
		G_raster_cpy(raster_row,
			     sum_array + (row * cols * G_raster_size(rtype)),
			     cols, rtype);
		break;

	    case METHOD_RANGE:	/* (max-min) */
		ptr = raster_row;
		for (col = 0; col < cols; col++) {
		    offset = (row * cols + col) * G_raster_size(rtype);
		    min = G_get_raster_value_d(min_array + offset, rtype);
		    max = G_get_raster_value_d(max_array + offset, rtype);
		    G_set_raster_value_d(ptr, max - min, rtype);
		    ptr = G_incr_void_ptr(ptr, G_raster_size(rtype));
		}
		break;

	    case METHOD_MEAN:	/* (sum / n) */
		ptr = raster_row;
		for (col = 0; col < cols; col++) {
		    offset = (row * cols + col) * G_raster_size(rtype);
		    n_offset = (row * cols + col) * G_raster_size(CELL_TYPE);
		    n = G_get_raster_value_c(n_array + n_offset, CELL_TYPE);
		    sum = G_get_raster_value_d(sum_array + offset, rtype);

		    if (n == 0)
			G_set_null_value(ptr, 1, rtype);
		    else
			G_set_raster_value_d(ptr, (sum / n), rtype);

		    ptr = G_incr_void_ptr(ptr, G_raster_size(rtype));
		}
		break;

	    case METHOD_STDDEV:	/*  sqrt(variance)        */
	    case METHOD_VARIANCE:	/*  (sumsq - sum*sum/n)/n */
	    case METHOD_COEFF_VAR:	/*  100 * stdev / mean    */
		ptr = raster_row;
		for (col = 0; col < cols; col++) {
		    offset = (row * cols + col) * G_raster_size(rtype);
		    n_offset = (row * cols + col) * G_raster_size(CELL_TYPE);
		    n = G_get_raster_value_c(n_array + n_offset, CELL_TYPE);
		    sum = G_get_raster_value_d(sum_array + offset, rtype);
		    sumsq = G_get_raster_value_d(sumsq_array + offset, rtype);

		    if (n == 0)
			G_set_null_value(ptr, 1, rtype);
		    else {
			variance = (sumsq - sum * sum / n) / n;
			if (variance < GRASS_EPSILON)
			    variance = 0.0;

			if (method == METHOD_STDDEV)
			    G_set_raster_value_d(ptr, sqrt(variance), rtype);

			else if (method == METHOD_VARIANCE)
			    G_set_raster_value_d(ptr, variance, rtype);

			else if (method == METHOD_COEFF_VAR)
			    G_set_raster_value_d(ptr,
						 100 * sqrt(variance) / (sum /
									 n),
						 rtype);

		    }
		    ptr = G_incr_void_ptr(ptr, G_raster_size(rtype));
		}
		break;
	    case METHOD_MEDIAN:	/* median, if only one point in cell we will use that */
		ptr = raster_row;
		for (col = 0; col < cols; col++) {
		    n_offset = (row * cols + col) * G_raster_size(CELL_TYPE);
		    if (G_is_null_value(index_array + n_offset, CELL_TYPE))	/* no points in cell */
			G_set_null_value(ptr, 1, rtype);
		    else {	/* one or more points in cell */

			head_id =
			    G_get_raster_value_c(index_array + n_offset,
						 CELL_TYPE);
			node_id = head_id;

			n = 0;

			while (node_id != -1) {	/* count number of points in cell */
			    n++;
			    node_id = nodes[node_id].next;
			}

			if (n == 1)	/* only one point, use that */
			    G_set_raster_value_d(ptr, nodes[head_id].z,
						 rtype);
			else if (n % 2 != 0) {	/* odd number of points: median_i = (n + 1) / 2 */
			    n = (n + 1) / 2;
			    node_id = head_id;
			    for (j = 1; j < n; j++)	/* get "median element" */
				node_id = nodes[node_id].next;

			    G_set_raster_value_d(ptr, nodes[node_id].z,
						 rtype);
			}
			else {	/* even number of points: median = (val_below + val_above) / 2 */

			    z = (n + 1) / 2.0;
			    n = floor(z);
			    node_id = head_id;
			    for (j = 1; j < n; j++)	/* get element "below" */
				node_id = nodes[node_id].next;

			    z = (nodes[node_id].z +
				 nodes[nodes[node_id].next].z) / 2;
			    G_set_raster_value_d(ptr, z, rtype);
			}
		    }
		    ptr = G_incr_void_ptr(ptr, G_raster_size(rtype));
		}
		break;
	    case METHOD_PERCENTILE:	/* rank = (pth*(n+1))/100; interpolate linearly */
		ptr = raster_row;
		for (col = 0; col < cols; col++) {
		    n_offset = (row * cols + col) * G_raster_size(CELL_TYPE);
		    if (G_is_null_value(index_array + n_offset, CELL_TYPE))	/* no points in cell */
			G_set_null_value(ptr, 1, rtype);
		    else {
			head_id =
			    G_get_raster_value_c(index_array + n_offset,
						 CELL_TYPE);
			node_id = head_id;
			n = 0;

			while (node_id != -1) {	/* count number of points in cell */
			    n++;
			    node_id = nodes[node_id].next;
			}

			z = (pth * (n + 1)) / 100.0;
			r_low = floor(z);	/* lower rank */
			if (r_low < 1)
			    r_low = 1;
			else if (r_low > n)
			    r_low = n;

			r_up = ceil(z);	/* upper rank */
			if (r_up > n)
			    r_up = n;

			node_id = head_id;
			for (j = 1; j < r_low; j++)	/* search lower value */
			    node_id = nodes[node_id].next;

			z = nodes[node_id].z;	/* save lower value */
			node_id = head_id;
			for (j = 1; j < r_up; j++)	/* search upper value */
			    node_id = nodes[node_id].next;

			z = (z + nodes[node_id].z) / 2;
			G_set_raster_value_d(ptr, z, rtype);
		    }
		    ptr = G_incr_void_ptr(ptr, G_raster_size(rtype));
		}
		break;
	    case METHOD_SKEWNESS:	/* skewness = sum(xi-mean)^3/(N-1)*s^3 */
		ptr = raster_row;
		for (col = 0; col < cols; col++) {
		    n_offset = (row * cols + col) * G_raster_size(CELL_TYPE);
		    if (G_is_null_value(index_array + n_offset, CELL_TYPE))	/* no points in cell */
			G_set_null_value(ptr, 1, rtype);
		    else {
			head_id =
			    G_get_raster_value_c(index_array + n_offset,
						 CELL_TYPE);
			node_id = head_id;

			n = 0;	/* count */
			sum = 0.0;	/* sum */
			sumsq = 0.0;	/* sum of squares */
			sumdev = 0.0;	/* sum of (xi - mean)^3 */
			skew = 0.0;	/* skewness */

			while (node_id != -1) {
			    z = nodes[node_id].z;
			    n++;
			    sum += z;
			    sumsq += (z * z);
			    node_id = nodes[node_id].next;
			}

			if (n > 1) {	/* if n == 1, skew is "0.0" */
			    mean = sum / n;
			    node_id = head_id;
			    while (node_id != -1) {
				z = nodes[node_id].z;
				sumdev += pow((z - mean), 3);
				node_id = nodes[node_id].next;
			    }

			    variance = (sumsq - sum * sum / n) / n;
			    if (variance < GRASS_EPSILON)
				skew = 0.0;
			    else
				skew =
				    sumdev / ((n - 1) *
					      pow(sqrt(variance), 3));
			}
			G_set_raster_value_d(ptr, skew, rtype);
		    }
		    ptr = G_incr_void_ptr(ptr, G_raster_size(rtype));
		}
		break;
	    case METHOD_TRIMMEAN:
		ptr = raster_row;
		for (col = 0; col < cols; col++) {
		    n_offset = (row * cols + col) * G_raster_size(CELL_TYPE);
		    if (G_is_null_value(index_array + n_offset, CELL_TYPE))	/* no points in cell */
			G_set_null_value(ptr, 1, rtype);
		    else {
			head_id =
			    G_get_raster_value_c(index_array + n_offset,
						 CELL_TYPE);

			node_id = head_id;
			n = 0;
			while (node_id != -1) {	/* count number of points in cell */
			    n++;
			    node_id = nodes[node_id].next;
			}

			if (1 == n)
			    mean = nodes[head_id].z;
			else {
			    k = floor(trim * n + 0.5);	/* number of ranks to discard on each tail */

			    if (k > 0 && (n - 2 * k) > 0) {	/* enough elements to discard */
				node_id = head_id;
				for (j = 0; j < k; j++)	/* move to first rank to consider */
				    node_id = nodes[node_id].next;

				j = k + 1;
				k = n - k;
				n = 0;
				sum = 0.0;

				while (j <= k) {	/* get values in interval */
				    n++;
				    sum += nodes[node_id].z;
				    node_id = nodes[node_id].next;
				    j++;
				}
			    }
			    else {
				node_id = head_id;
				n = 0;
				sum = 0.0;
				while (node_id != -1) {
				    n++;
				    sum += nodes[node_id].z;
				    node_id = nodes[node_id].next;
				}
			    }
			    mean = sum / n;
			}
			G_set_raster_value_d(ptr, mean, rtype);
		    }
		    ptr = G_incr_void_ptr(ptr, G_raster_size(rtype));
		}
		break;

	    default:
		G_fatal_error("?");
	    }

	    /* write out line of raster data */
	    if (1 != G_put_raster_row(out_fd, raster_row, rtype)) {
		G_close_cell(out_fd);
		G_fatal_error(_("Writing map, row %d"),
			      ((pass - 1) * rows) + row);
	    }
	}

	/* free memory */
	if (bin_n)
	    G_free(n_array);
	if (bin_min)
	    G_free(min_array);
	if (bin_max)
	    G_free(max_array);
	if (bin_sum)
	    G_free(sum_array);
	if (bin_sumsq)
	    G_free(sumsq_array);
	if (bin_index) {
	    G_free(index_array);
	    G_free(nodes);
	    num_nodes = 0;
	    max_nodes = 0;
	    nodes = NULL;
	}

    }				/* passes loop */

    G_percent(1, 1, 1);		/* flush */
    G_free(raster_row);

    /* close input file */
    if (!from_stdin)
	fclose(in_fp);

    /* close raster file & write history */
    G_close_cell(out_fd);

    sprintf(title, "Raw x,y,z data binned into a raster grid by cell %s",
	    method_opt->answer);
    G_put_cell_title(outmap, title);

    G_short_history(outmap, "raster", &history);
    G_command_history(&history);
    strncpy(history.datsrc_1, infile, RECORD_LEN);
    history.datsrc_1[RECORD_LEN - 1] = '\0';	/* strncpy() doesn't null terminate if maxfill */
    G_write_history(outmap, &history);


    sprintf(buff, _("%lu points found in region."), count_total);
    G_done_msg(buff);
    G_debug(1, "Processed %lu lines.", line);

    exit(EXIT_SUCCESS);

}
Exemple #2
0
int transform_digit_file(struct Map_info *Old, struct Map_info *New,
                         double ztozero, int swap_xy, int swap_xz,
                         int swap_yz, int swap_after,
                         double *trans_params_def, char **columns, int field)
{
    int i, type, cat, line, ret;
    int verbose, format;
    unsigned int j;
    double *trans_params;
    double ang, x, y, tmp;
    static struct line_pnts *Points;
    static struct line_cats *Cats;

    /* db */
    struct field_info *fi;
    int ctype;
    dbDriver *driver;
    dbValue val;

    cat = -1;			/* dummy value for debugging */

    Points = Vect_new_line_struct();
    Cats = Vect_new_cats_struct();

    driver = NULL;
    fi = NULL;
    if (field > 0) {
	fi = Vect_get_field(Old, field);

	driver = db_start_driver_open_database(fi->driver, fi->database);
	if (!driver)
	    G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
			  fi->database, fi->driver);

	trans_params = (double *)G_calloc(IDX_ZROT + 1, sizeof(double));
    }
    else {
	trans_params = trans_params_def;
	ang = PI * trans_params[IDX_ZROT] / 180;
    }

    line = 0;
    ret = 1;
    format = G_info_format();
    verbose = G_verbose() > G_verbose_min();
    while (TRUE) {
	type = Vect_read_next_line(Old, Points, Cats);

	if (type == -1)	{	/* error */
	    ret = 0;
	    break;
	}

	if (type == -2) {	/* EOF */
	    ret = 1;
	    break;
	}

	if (field != -1 && !Vect_cat_get(Cats, field, NULL))
	    continue;
	
	if (verbose && line % 1000 == 0) {
	    if (format == G_INFO_FORMAT_PLAIN)
		fprintf(stderr, "%d..", line);
	    else
		fprintf(stderr, "%11d\b\b\b\b\b\b\b\b\b\b\b", line);
	}

        if (swap_xy && !swap_after) {
            for (i = 0; i < Points->n_points; i++) {
                x = Points->x[i];
                Points->x[i] = Points->y[i];
                Points->y[i] = x;
            }
        }
        if (swap_xz && !swap_after) {
            for (i = 0; i < Points->n_points; i++) {
                tmp = Points->z[i];
                Points->z[i] = Points->x[i];
                Points->x[i] = tmp;
            }
        }
        if (swap_yz && !swap_after) {
            for (i = 0; i < Points->n_points; i++) {
                tmp = Points->z[i];
                Points->z[i] = Points->y[i];
                Points->y[i] = tmp;
            }
        }

	/* get transformation parameters */
	if (field > 0) {
	    Vect_cat_get(Cats, field, &cat);	/* get first category */
	    if (cat > -1) {
		for (j = 0; j <= IDX_ZROT; j++) {
		    if (columns[j] == NULL) {
			trans_params[j] = trans_params_def[j];
			continue;
		    }
		    ctype = db_column_Ctype(driver, fi->table, columns[j]);
		    switch (ctype) {
		    case DB_C_TYPE_INT:
		    case DB_C_TYPE_DOUBLE:
		    case DB_C_TYPE_STRING:
			break;
		    case -1:
			G_fatal_error(_("Column <%s> not found in table <%s>"),
				      columns[j], fi->table);
		    default:
			G_fatal_error(_("Unsupported column type of <%s>"),
				      columns[j]);
		    }
		    if (db_select_value
			(driver, fi->table, fi->key, cat, columns[j], &val) != 1
			|| db_test_value_isnull(&val)) {
			trans_params[j] = trans_params_def[j];

			G_warning(_("Unable to select value for category %d from table <%s>, column <%s>. "
				   "For category %d using default transformation parameter %.3f."),
				  cat, fi->table, columns[j], cat,
				  trans_params[j]);
		    }
		    else {
			trans_params[j] = db_get_value_as_double(&val, ctype);
		    }
		}
	    }
	    else {
		G_warning(_("No category number defined. Using default transformation parameters."));

		for (j = 0; j <= IDX_ZROT; j++) {
		    trans_params[j] = trans_params_def[j];
		}
	    }
	    ang = PI * trans_params[IDX_ZROT] / 180;
	}

	/* transform points */
	for (i = 0; i < Points->n_points; i++) {
	    G_debug(3, "idx=%d, cat=%d, xshift=%g, yshift=%g, zshift=%g, "
		    "xscale=%g, yscale=%g, zscale=%g, zrot=%g",
		    i, cat, trans_params[IDX_XSHIFT],
		    trans_params[IDX_YSHIFT], trans_params[IDX_ZSHIFT],
		    trans_params[IDX_XSCALE], trans_params[IDX_YSCALE],
		    trans_params[IDX_ZSCALE], trans_params[IDX_ZROT]);

	    /* transform point */
	    x = trans_params[IDX_XSHIFT] +
		trans_params[IDX_XSCALE] * Points->x[i] * cos(ang)
		- trans_params[IDX_YSCALE] * Points->y[i] * sin(ang);
	    y = trans_params[IDX_YSHIFT] +
		trans_params[IDX_XSCALE] * Points->x[i] * sin(ang)
		+ trans_params[IDX_YSCALE] * Points->y[i] * cos(ang);
	    Points->x[i] = x;
	    Points->y[i] = y;

	    /* ztozero shifts oldmap z to zero, zshift shifts rescaled object
	     * to target elevation: */
	    Points->z[i] =
		((Points->z[i] + ztozero) * trans_params[IDX_ZSCALE]) +
		trans_params[IDX_ZSHIFT];

            if (swap_after) {
                if (swap_xy) {
                    tmp = Points->x[i];
                    Points->x[i] = Points->y[i];
                    Points->y[i] = tmp;
                }
                if (swap_xz) {
                    tmp = Points->z[i];
                    Points->z[i] = Points->x[i];
                    Points->x[i] = tmp;
                }
                if (swap_yz) {
                    tmp = Points->z[i];
                    Points->z[i] = Points->y[i];
                    Points->y[i] = tmp;
                }
            }
	}

	Vect_write_line(New, type, Points, Cats);
	line++;
    }

    if (verbose && format != G_INFO_FORMAT_PLAIN)
	fprintf(stderr, "\r");
    
    if (field > 0) {
	db_close_database_shutdown_driver(driver);
	G_free((void *)trans_params);
    }
    
    return ret;
}
Exemple #3
0
int main(int argc, char *argv[])
{
    struct GModule *module;
    struct GParams *params;

    int i, ret;
    int red, grn, blu;
    float size;
    double vp_height, z_exag;	/* calculated viewpoint height, z-exag */
    int width, height;		/* output image size */
    char *output_name;

    nv_data data;
    struct render_window *offscreen;

    /* initialize GRASS */
    G_gisinit(argv[0]);

    module = G_define_module();
    G_add_keyword(_("visualization"));
    G_add_keyword(_("graphics"));
    G_add_keyword(_("raster"));
    G_add_keyword(_("vector"));
    G_add_keyword(_("raster3d"));
    module->label = _("Creates a 3D rendering of GIS data.");
    module->description = _("Renders surfaces (raster data), "
			    "2D/3D vector data, and "
			    "volumes (3D raster data) in 3D.");

    params = (struct GParams *)G_malloc(sizeof(struct GParams));

    /* define options, call G_parser() */
    parse_command(argc, argv, params);

    /* check parameters consistency */
    check_parameters(params);

    width = atoi(params->size->answers[0]);
    height = atoi(params->size->answers[1]);
    G_asprintf(&output_name, "%s.%s", params->output->answer,
	       params->format->answer);

    GS_libinit();
    GVL_libinit();

    GS_set_swap_func(swap_gl);

    /* define render window */
    offscreen = Nviz_new_render_window();
    Nviz_init_render_window(offscreen);
    if (Nviz_create_render_window(offscreen, NULL, width, height) == -1)
	G_fatal_error(_("Unable to render data"));
    Nviz_make_current_render_window(offscreen);

    /* initialize nviz data */
    Nviz_init_data(&data);

    /* define default attributes for map objects */
    Nviz_set_surface_attr_default();

    /* set background color */
    Nviz_set_bgcolor(&data, Nviz_color_from_str(params->bgcolor->answer));

    /* init view, lights */
    Nviz_init_view(&data);

    /* load raster maps (surface topography) & set attributes (map/constant) */
    load_rasters(params, &data);

    /* set draw mode of loaded surfaces */
    surface_set_draw_mode(params);

    /* load line vector maps */
    if (params->vlines->answer) {
	load_vlines(params, &data);
	/* set attributes of 2d lines */
	vlines_set_attrb(params);
    }

    /* load point vector maps */
    if (params->vpoints->answer) {
	load_vpoints(params, &data);
	/* set attributes for points */
	vpoints_set_attrb(params);
    }

    /* load volumes */
    if (params->volume->answer) {
	load_rasters3d(params, &data);
    }

    /* define isosurfaces for displaying volumes */
    if (params->isosurf_level->answer) {
	add_isosurfs(params, &data);
    }

    /* define slices for displaying volumes */
    if (params->slice->answer) {
	add_slices(params, &data);
    }

    /* focus on loaded data */
    Nviz_set_focus_map(MAP_OBJ_UNDEFINED, -1);

    /* define view point */
    if (params->exag->answer) {
	z_exag = atof(params->exag->answer);
    }
    else {
	z_exag = Nviz_get_exag();
	G_verbose_message(_("Vertical exaggeration not given, using calculated "
			   "value %.0f"), z_exag);
    }
    Nviz_change_exag(&data, z_exag);

    if (params->height->answer) {
	vp_height = atof(params->height->answer);
    }
    else {
	double min, max;

	Nviz_get_exag_height(&vp_height, &min, &max);
	G_verbose_message(_("Viewpoint height not given, using calculated "
			    "value %.0f"), vp_height);
    }
    Nviz_set_viewpoint_height(vp_height);

    Nviz_set_viewpoint_position(atof(params->pos->answers[0]),
				atof(params->pos->answers[1]));
    Nviz_set_viewpoint_twist(atoi(params->twist->answer));
    Nviz_set_viewpoint_persp(atoi(params->persp->answer));

    if (params->focus->answer) {
	Nviz_set_focus(&data, atof(params->focus->answers[0]),
		       atof(params->focus->answers[1]),
		       atof(params->focus->answers[2]));
    }

    /* set lights */
    Nviz_set_light_position(&data, 1,
			    atof(params->light_pos->answers[0]),
			    atof(params->light_pos->answers[1]),
			    atof(params->light_pos->answers[2]), 0.0);
    Nviz_set_light_bright(&data, 1,
			  atoi(params->light_bright->answer) / 100.0);
    if (G_str_to_color(params->light_color->answer, &red, &grn, &blu) != 1) {
	red = grn = blu = 255;
    }
    Nviz_set_light_color(&data, 1, red, grn, blu);
    Nviz_set_light_ambient(&data, 1,
			   atof(params->light_ambient->answer) / 100.0);

    /* define fringes */
    if (params->fringe->answer) {
	int nw, ne, sw, se;

	i = 0;
	nw = ne = sw = se = 0;
	while (params->fringe->answers[i]) {
	    const char *edge = params->fringe->answers[i++];

	    if (strcmp(edge, "nw") == 0)
		nw = 1;
	    else if (strcmp(edge, "ne") == 0)
		ne = 1;
	    else if (strcmp(edge, "sw") == 0)
		sw = 1;
	    else if (strcmp(edge, "se") == 0)
		se = 1;
	}
	Nviz_new_fringe(&data, -1,
			Nviz_color_from_str(params->fringe_color->answer),
			atof(params->fringe_elev->answer), nw, ne, sw, se);
    }

    /* draw north arrow */
    if (params->north_arrow->answer) {

	if (!params->north_arrow_size->answer)
	    size = Nviz_get_longdim(&data) / 8.;
	else
	    size = atof(params->north_arrow_size->answer);

	Nviz_set_arrow(&data, atoi(params->north_arrow->answers[0]),
		       atoi(params->north_arrow->answers[1]),
		       size,
		       Nviz_color_from_str(params->north_arrow_color->
					   answer));
	Nviz_draw_arrow(&data);
    }

    GS_clear(data.bgcolor);

    /* cutting planes */
    if (params->cplane->answer)
	draw_cplane(params, &data);

    /* draw */
    Nviz_draw_all(&data);

    /* write to image */
    ret = 0;
    if (strcmp(params->format->answer, "ppm") == 0)
	ret = write_img(output_name, FORMAT_PPM);
    if (strcmp(params->format->answer, "tif") == 0)
	ret = write_img(output_name, FORMAT_TIF);

    if (!ret)
	G_fatal_error(_("Unsupported output format"));

    G_done_msg(_("File <%s> created."), output_name);

    Nviz_destroy_data(&data);
    Nviz_destroy_render_window(offscreen);

    G_free((void *)output_name);
    G_free((void *)params);

    exit(EXIT_SUCCESS);
}
Exemple #4
0
/*!
   \brief Free allocated memory

   \param fv pointer to geovect struct
 */
void gv_free_vectmem(geovect * fv)
{
    geoline *gln, *tmpln;
    
    G_free((void *)fv->filename);
    fv->filename = NULL;
    if (fv->style)
	G_free(fv->style);
    if (fv->hstyle)
	G_free(fv->hstyle);

    if (fv->lines) {
	for (gln = fv->lines; gln;) {
	    if (gln->dims == 2) {
		sub_Vectmem(gln->npts * sizeof(Point2));
		G_free(gln->p2);
	    }

	    if (gln->dims == 3) {
		G_free(gln->p3);
	    }

	    G_free(gln->cats);
	    
	    tmpln = gln;
	    gln = gln->next;
	    sub_Vectmem(sizeof(geoline));
	    G_free(tmpln);
	}

	fv->n_lines = 0;
	fv->lines = NULL;
    }

    if (fv->tstyle) {
	G_free(fv->tstyle->color_column);
	G_free(fv->tstyle->symbol_column);
	G_free(fv->tstyle->size_column);
	G_free(fv->tstyle->width_column);
    }

    return;
}
int douglas_peucker(struct line_pnts *Points, double thresh, int with_z)
{
    int *stack = G_malloc(sizeof(int) * Points->n_points * 2);

    if (!stack) {
	G_fatal_error(_("Out of memory"));
	return Points->n_points;
    }

    int *index = G_malloc(sizeof(int) * Points->n_points);	/* Indices of points in output line */

    if (!index) {
	G_fatal_error(_("Out of memory"));
	G_free(stack);
	return Points->n_points;
    }

    int top = 2;		/* first free slot in the stack */
    int icount = 1;		/* number of indices stored */
    int i;

    thresh *= thresh;

    index[0] = 0;		/* first point is always in output line */

    /* stack contains pairs of elements: (beginning, end) */

    stack[0] = 0;
    stack[1] = Points->n_points - 1;

    while (top > 0) {		/*there are still segments to consider */
	/*Pop indices of the segment from the stack */
	int last = stack[--top];
	int first = stack[--top];

	double x1 = Points->x[first];
	double y1 = Points->y[first];
	double z1 = Points->z[first];

	double x2 = Points->x[last];
	double y2 = Points->y[last];
	double z2 = Points->z[last];

	int maxindex = -1;
	double maxdist = -1;
	int i;

	for (i = first + 1; i <= last - 1; i++) {	/* Find the furthermost point between first, last */
	    double px, py, pz, pdist;
	    int status;
	    double dist =
		dig_distance2_point_to_line(Points->x[i], Points->y[i],
					    Points->z[i],
					    x1, y1, z1, x2, y2, z2, with_z,
					    &px, &py, &pz, &pdist, &status);

	    if (maxindex == -1 || dist > maxdist) {	/* update the furthermost point so far seen */
		maxindex = i;
		maxdist = dist;
	    }
	}


	if (maxindex == -1 || maxdist <= thresh) {	/* no points between or all point are inside the threshold */
	    index[icount++] = last;
	}
	else {
	    /* break line into two parts, the order of pushing is crucial! It gurantees, that we are going to the left */
	    stack[top++] = maxindex;
	    stack[top++] = last;
	    stack[top++] = first;
	    stack[top++] = maxindex;
	}


    }


    Points->n_points = icount;

    /* finally, select only points marked in the algorithm */
    for (i = 0; i < icount; i++) {
	Points->x[i] = Points->x[index[i]];
	Points->y[i] = Points->y[index[i]];
	Points->z[i] = Points->z[index[i]];
    }

    G_free(stack);
    G_free(index);
    return (Points->n_points);
}
Exemple #6
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)
{
    double dfCellMin;
    double dfCellMax;
    int fd;
    int cols = cellhead->cols;
    int rows = cellhead->rows;
    int ret = 0;

    /* Open GRASS raster */
    fd = Rast_open_old(name, mapset);

    /* 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;
    }
    G_message(_("Using GDAL data type <%s>"), GDALGetDataTypeName(export_datatype));

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

    Rast_close(fd);

    G_free(bufer);

    return ret;
}
Exemple #7
0
/*!
 *  \brief Extract a cell value from raster map (bilinear interpolation).
 *
 *  Extract a cell value from raster map at given northing and easting
 *  with a sampled 3x3 window using a bilinear interpolation.
 *
 *  \param fd file descriptor
 *  \param window region settings
 *  \param cats categories
 *  \param north northing position
 *  \param east easting position
 *  \param usedesc flag to scan category label
 *
 *  \return cell value at given position
 */
DCELL Rast_get_sample_bilinear(int fd,
			       const struct Cell_head * window,
			       struct Categories * cats,
			       double north, double east, int usedesc)
{
    int row, col;
    double grid[2][2];
    DCELL *arow = Rast_allocate_d_buf();
    DCELL *brow = Rast_allocate_d_buf();
    double frow, fcol, trow, tcol;
    DCELL result;

    frow = Rast_northing_to_row(north, window);
    fcol = Rast_easting_to_col(east, window);

    /* convert northing and easting to row and col, resp */
    row = (int)floor(frow - 0.5);
    col = (int)floor(fcol - 0.5);

    trow = frow - row - 0.5;
    tcol = fcol - col - 0.5;

    if (row < 0 || row + 1 >= Rast_window_rows() ||
	col < 0 || col + 1 >= Rast_window_cols()) {
	Rast_set_d_null_value(&result, 1);
	goto done;
    }

    Rast_get_d_row(fd, arow, row);
    Rast_get_d_row(fd, brow, row + 1);

    if (Rast_is_d_null_value(&arow[col]) ||
	Rast_is_d_null_value(&arow[col + 1]) ||
	Rast_is_d_null_value(&brow[col]) ||
	Rast_is_d_null_value(&brow[col + 1])) {
	Rast_set_d_null_value(&result, 1);
	goto done;
    }

    /*-
     * now were ready to do bilinear interpolation over
     * arow[col], arow[col+1],
     * brow[col], brow[col+1]
     */

    if (usedesc) {
	char *buf;

	G_squeeze(buf = Rast_get_c_cat((int *)&(arow[col]), cats));
	grid[0][0] = scancatlabel(buf);
	G_squeeze(buf = Rast_get_c_cat((CELL *) & (arow[col + 1]), cats));
	grid[0][1] = scancatlabel(buf);
	G_squeeze(buf = Rast_get_c_cat((CELL *) & (brow[col]), cats));
	grid[1][0] = scancatlabel(buf);
	G_squeeze(buf = Rast_get_c_cat((CELL *) & (brow[col + 1]), cats));
	grid[1][1] = scancatlabel(buf);
    }
    else {
	grid[0][0] = arow[col];
	grid[0][1] = arow[col + 1];
	grid[1][0] = brow[col];
	grid[1][1] = brow[col + 1];
    }

    result = Rast_interp_bilinear(tcol, trow,
				  grid[0][0], grid[0][1], grid[1][0],
				  grid[1][1]);

  done:
    G_free(arow);
    G_free(brow);

    return result;
}
Exemple #8
0
int main(int argc, char *argv[])
{
    /* variables   */
    CELL *data_buf, *clump_buf;
    CELL i, max;
    int row, col, rows, cols;
    int out_mode, use_MASK, *n, *e;
    long int *count;
    int fd_data, fd_clump;
    const char *datamap, *clumpmap, *site_list;
    const char *clump_mapset;
    double avg, vol, total_vol, east, north, *sum;
    struct Cell_head window;
    struct Map_info *fd_sites = NULL;
    Site *mysite;
    Site_head site_info;
    struct GModule *module;
    struct Option *opt1, *opt2, *opt3;
    struct Flag *flag1;

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

    module = G_define_module();
    G_add_keyword(_("raster"));
    G_add_keyword(_("volume"));
    module->description =
	_("Calculates the volume of data \"clumps\", "
	  "and (optionally) produces a GRASS vector points map "
	  "containing the calculated centroids of these clumps.");

    opt1 = G_define_standard_option(G_OPT_R_INPUT);
    opt1->description =
	_("Existing raster map representing data that will be summed within clumps");

    opt2 = G_define_standard_option(G_OPT_R_INPUT);
    opt2->key = "clump";
    opt2->required = NO;
    opt2->description =
	_("Existing raster map, preferably the output of r.clump");

    opt3 = G_define_standard_option(G_OPT_V_OUTPUT);
    opt3->key = "centroids";
    opt3->required = NO;
    opt3->description = _("Vector points map to contain clump centroids");

    flag1 = G_define_flag();
    flag1->key = 'f';
    flag1->description = _("Generate unformatted report");

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

    /* get current window */
    G_get_window(&window);

    /* initialize */
    out_mode = 1;		/* assume full output text */
    mysite = G_site_new_struct(CELL_TYPE, 2, 0, 4);

    /* get arguments */
    datamap = opt1->answer;

    if (opt2->answer)
	clumpmap = opt2->answer;
    else
	clumpmap = "";

    if (opt3->answer)
	site_list = opt3->answer;
    else
	site_list = "";

    out_mode = (!flag1->answer);

    if (*datamap == 0)
	G_fatal_error(_("No data map specified"));

    /*
     * See if MASK or a separate "clumpmap" layer is to be used-- it must(!)
     * be one of those two choices.
     */
    use_MASK = 0;
    if (*clumpmap == '\0') {
	clumpmap = "MASK";
	use_MASK = 1;
    }
    fd_data = Rast_open_old(datamap, "");
    if (use_MASK)
	clump_mapset = G_mapset();
    else
	clump_mapset = "";

    fd_clump = Rast_open_old(clumpmap, clump_mapset);

    /* initialize sites file (for centroids) if needed */
    if (*site_list) {
	fd_sites = G_fopen_sites_new(site_list);
	if (fd_sites == NULL)
	    G_fatal_error(_("Unable to open centroids vector points map"));
    }

    /* initialize data accumulation arrays */
    max = Rast_get_max_c_cat(clumpmap, clump_mapset);

    sum = (double *)G_malloc((max + 1) * sizeof(double));
    count = (long int *)G_malloc((max + 1) * sizeof(long int));

    for (i = 0; i <= max; i++) {
	sum[i] = 0;
	count[i] = 0;
    }

    data_buf = Rast_allocate_c_buf();
    clump_buf = Rast_allocate_c_buf();

    /* get window size */
    rows = window.rows;
    cols = window.cols;

    /* now get the data -- first pass */
    G_message("Complete ...");
    for (row = 0; row < rows; row++) {
	G_percent(row, rows, 2);
	Rast_get_c_row(fd_data, data_buf, row);
	Rast_get_c_row(fd_clump, clump_buf, row);
	for (col = 0; col < cols; col++) {
	    i = clump_buf[col];
	    if (i > max)
		G_fatal_error(
		    "Row=%d Col=%d Cat=%d in clump map [%s]; max=%d.\n"
		    "Cat value > max returned by Rast_get_max_c_cat.",
		    row, col, i, clumpmap, max);
	    if (i < 1)
		continue;	/* ignore zeros and negs */
	    count[i]++;
	    sum[i] += data_buf[col];
	}
    }
    G_percent(row, rows, 2);
    /* free some buffer space */
    G_free(data_buf);
    G_free(clump_buf);

    /* data lists for centroids of clumps */
    e = (int *)G_malloc((max + 1) * sizeof(int));
    n = (int *)G_malloc((max + 1) * sizeof(int));

    i = centroids(fd_clump, e, n, 1, max);

    /* got everything, now do output */
    if (*site_list) {
	char desc[GNAME_MAX * 2 + 40];

	site_info.form = NULL;
	site_info.time = NULL;
	site_info.stime = NULL;
	sprintf(desc, "from %s on map %s using clumps from %s",
		argv[0], datamap, clumpmap);
	site_info.desc = G_store(desc);
	site_info.name = G_store(site_list);
	site_info.labels =
	    G_store("centroid east|centroid north|#cat vol avg t n");
	G_site_put_head(fd_sites, &site_info);
    }
    if (out_mode) {
	fprintf(stdout, "Volume report on data from %s", datamap);
	fprintf(stdout, " using clumps on %s map\n\n", clumpmap);
	fprintf(stdout,
		" Cat    Average   Data   # Cells        Centroid             Total\n");
	fprintf(stdout,
		"Number  in clump  Total  in clump   Easting   Northing       Volume\n\n");
    }
    total_vol = 0.0;

    for (i = 1; i <= max; i++) {
	if (count[i]) {
	    avg = sum[i] / (double)count[i];
	    vol = sum[i] * window.ew_res * window.ns_res;
	    total_vol += vol;
	    east = window.west + (e[i] + 0.5) * window.ew_res;
	    north = window.north - (n[i] + 0.5) * window.ns_res;
	    if (*site_list) {
		mysite->east = east;
		mysite->north = north;
		mysite->ccat = i;
		mysite->dbl_att[0] = vol;
		mysite->dbl_att[1] = avg;
		mysite->dbl_att[2] = sum[i];
		mysite->dbl_att[3] = (double)count[i];
		/*       "%-1.2f|%-1.2f|#%5d v=%-1.2f a=%-1.2f t=%-1.0f n=%ld\n", */
		/* east, north, i, vol, avg, sum[i], count[i]); */
		G_site_put(fd_sites, mysite);
	    }
	    if (out_mode)
		fprintf(stdout,
			"%5d%10.2f%10.0f %7ld  %10.2f  %10.2f %16.2f\n", i,
			avg, sum[i], count[i], east, north, vol);
	    else
		fprintf(stdout, "%d:%.2f:%.0f:%ld:%.2f:%.2f:%.2f\n",
			i, avg, sum[i], count[i], east, north, vol);
	}
    }
    if (total_vol > 0.0 && out_mode)
	fprintf(stdout, "%58s %14.2f", "Total Volume =", total_vol);
    fprintf(stdout, "\n");
    exit(EXIT_SUCCESS);
}				/* end of main() */
Exemple #9
0
int main(int argc, char *argv[]) 
{
    int nrows, ncols;
    int row, col;
    char *nameflag;		/*Switch for particular method */
    struct GModule *module;
    struct Option *input1, *input2, *output;
    struct History history;	/*metadata */

    /************************************/ 
    char *result;		/*output raster name */
    int infd_annual_pmm;
    int outfd;
    char *annual_pmm;

    void *inrast_annual_pmm;
    DCELL * outrast;

    /************************************/ 
    G_gisinit(argv[0]);

    module = G_define_module();
    G_add_keyword(_("raster"));
    G_add_keyword(_("hydrology"));
    G_add_keyword(_("rainfall"));
    G_add_keyword(_("erosion"));
    module->description = _("Computes USLE R factor, Rainfall erosivity index.");
    
    input2 = G_define_standard_option(G_OPT_R_INPUT);
    input2->description = _("Name of annual precipitation raster map [mm/year]");

    output = G_define_standard_option(G_OPT_R_OUTPUT);
    output->description = _("Name for output USLE R raster map [MJ.mm/ha.hr.year]");

    /* Define the different options */ 
    input1 = G_define_option();
    input1->key = "method";
    input1->type = TYPE_STRING;
    input1->required = YES;
    input1->description = _("Name of USLE R equation");
    input1->options = "roose, morgan, foster, elswaify";
    input1->descriptions = _("roose;Roosle (1975);"
			     "morgan;Morgan (1974);"
			     "foster;Foster (1981);"
			     "elswaify;El-Swaify (1985)");
    input1->answer = "morgan";

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

    nameflag = input1->answer;
    annual_pmm = input2->answer;
    result = output->answer;
    
    /***************************************************/ 
    infd_annual_pmm = Rast_open_old(annual_pmm, "");
    inrast_annual_pmm = Rast_allocate_d_buf();
    
    /***************************************************/ 
    nrows = Rast_window_rows();
    ncols = Rast_window_cols();
    outrast = Rast_allocate_d_buf();
    
    /* Create New raster files */ 
    outfd = Rast_open_new(result, DCELL_TYPE);
    
    /* Process pixels */ 
    for (row = 0; row < nrows; row++)
    {
        DCELL d;
	DCELL d_annual_pmm;
	G_percent(row, nrows, 2);
	
	/* read input map */ 
	Rast_get_d_row(infd_annual_pmm, inrast_annual_pmm, row);
	
	/*process the data */ 
	for (col = 0; col < ncols; col++)
	{
	    d_annual_pmm = ((DCELL *) inrast_annual_pmm)[col];
	    if (Rast_is_d_null_value(&d_annual_pmm)) 
		Rast_set_d_null_value(&outrast[col], 1);
	    else 
            {
                /*calculate morgan       */ 
                if (!strcmp(nameflag, "morgan"))
                    d = morgan_1974(d_annual_pmm);
		/*calculate roose        */ 
		if (!strcmp(nameflag, "roose")) 
		    d = roose_1975(d_annual_pmm);
		/*calculate foster       */ 
		if (!strcmp(nameflag, "foster"))
		    d = foster_1981(d_annual_pmm);
		/*calculate elswaify     */ 
		if (!strcmp(nameflag, "elswaify")) 
		    d = elswaify_1985(d_annual_pmm);
		outrast[col] = d ;
	    }
	}
	Rast_put_d_row(outfd, outrast);
    }
    G_free(inrast_annual_pmm);
    Rast_close(infd_annual_pmm);
    G_free(outrast);
    Rast_close(outfd);

    Rast_short_history(result, "raster", &history);
    Rast_command_history(&history);
    Rast_write_history(result, &history);

    exit(EXIT_SUCCESS);
}
Exemple #10
0
/* create the actual report */
void do_report_CELL ( char *map, char *mapset, char *sites,
					int precision, int null_flag, int uncat_flag,
					int all_flag, int quiet_flag, int skip_flag,
				  	char *logfile, int background, int gain, int show_progress) {
    	CELL *cellbuf;
	struct Cell_head region;
	GT_Row_cache_t *cache;
	unsigned long row_idx, col_idx;	
	int fd;
	unsigned long i,j,k;
	unsigned long no_sites;
	FILE *lp;	
	unsigned long nrows, ncols;
	unsigned long *share_smp = NULL; /* array that keeps percentage of sites */
	double total = 0;
	double map_total = 0;
	double kvamme_gain;
	long null_count = 0; /* keeps count of sites on NULL cells */
	long nocat_count = 0;
	/* category counts and descriptions */
	int cats;
	char **cats_description; /* category labels */
	long *cat_count; /* category counts */
	long null_count_map; /* number of NULL cells in input map */
	long nocat_count_map; /* number of cells that do not fall into the category range [0 .. n] */		
	int debug_mode = 0;		/* 1 to enable writing additional output to logfile */
	time_t systime;

	char errmsg [200];
	struct Map_info in_vect_map;
  	struct line_pnts *vect_points;
	double x,y,z;
	int n_points = 1;
	int cur_type;
	

	/* get current region */
	G_get_window (&region);
	nrows = G_window_rows ();
	ncols = G_window_cols ();	
	
	/* check logfile */
	if (logfile != NULL) {
		debug_mode = 1;	
		if ( !G_legal_filename (logfile) ) {
			delete_tmpfile (map);
			G_fatal_error ("Please specify a legal filename for the logfile.\n");
		}
		/* attempt to write to logfile */
		if ( (lp = fopen ( logfile, "w+" ) ) == NULL )	{
			delete_tmpfile (map);
			G_fatal_error ("Could not create logfile.\n");
		}
		/* we want unbuffered output for the logfile */
		setvbuf (lp,NULL,_IONBF,0);	
		fprintf (lp,"This is %s, version %.2f\n",PROGNAME, PROGVERSION);
		systime = time (NULL);
		fprintf (lp,"Started on %s",ctime(&systime));
		fprintf (lp,"\tlocation    = %s\n",G_location());
		fprintf (lp,"\tmapset      = %s\n",G_mapset());
		fprintf (lp,"\tinput map   = %s\n",map);
		fprintf (lp,"\tsample file = %s\n",sites);
	} else {		
		/* log output to stderr by default */
		lp = stderr;
	}

  	if (1 > Vect_open_old (&in_vect_map, sites, "")) {
		delete_tmpfile (map);
    		sprintf (errmsg, "Could not open input map %s.\n", sites);
    		G_fatal_error (errmsg);
  	}

	vect_points = Vect_new_line_struct ();

	if (all_flag != 1) {
		Vect_set_constraint_region (&in_vect_map, region.north, region.south, 
			region.east, region.west, 0.0, 0.0);
	}
		
	/* get total number of sampling points */
	i = 0;	
	while ((cur_type = Vect_read_next_line (&in_vect_map, vect_points, NULL) > 0)) {
		i ++;
	}

	no_sites = i; /* store this for later use */
			
	/* open raster map */
	fd = G_open_cell_old (map, G_find_cell (map, ""));
	if (fd < 0)
	{
		delete_tmpfile (map);
		G_fatal_error ("Could not open raster map for reading!\n");
	}
	/* allocate a cache and a raster buffer */
	cache = (GT_Row_cache_t *) G_malloc (sizeof (GT_Row_cache_t));
	GT_RC_open (cache, CACHESIZE, fd, CELL_TYPE);
	cellbuf = G_allocate_raster_buf (CELL_TYPE);			
	
	cats = GT_get_stats (map,mapset,&null_count_map, &nocat_count_map, show_progress);
	if ( cats < 2 ) {
		delete_tmpfile (map);
		G_fatal_error ("Input map must have at least two categories.");
	}
	
	/* get category labels and counts */
	cats_description = GT_get_labels (map,mapset);
	if (cats_description == NULL) {
		delete_tmpfile (map);
		G_fatal_error ("Could not read category labels from input map.");
	}
	cat_count = GT_get_c_counts (map,mapset, show_progress);
	if (cat_count == NULL) {
		delete_tmpfile (map);
		G_fatal_error ("Could not count categories in input map.");
	}		
	
	/* allocate a double array to hold statistics */
	share_smp = (unsigned long *) G_malloc ((signed)(cats * sizeof (unsigned long)));
	for (i = 0; i < cats; i++)
	{
		share_smp[i] = 0;
		
	}	
	
	/* count raster values under sampling points */
	i = 0;
	k = 0; /* progress counter for status display */
	
	Vect_rewind (&in_vect_map);	
	
	if ( !quiet_flag ) {
		fprintf (stdout, "Counting sample: \n");
		fflush (stdout);	
	}
	
	/* we MUST not set constraints so that no raster values outside the current region are
	   accessed, which would give an "illegal cache request" error */
	Vect_set_constraint_region (&in_vect_map, region.north, region.south, 
				     region.east, region.west, 0.0, 0.0);
	
	while ((cur_type = Vect_read_next_line (&in_vect_map, vect_points, NULL) > 0)) {	
		Vect_copy_pnts_to_xyz (vect_points, &x, &y, &z, &n_points);		
		k ++;
		if ( !quiet_flag ) {
			G_percent ((signed) k, (signed) no_sites, 1);
		}
		/* get raster row with same northing as sample and perform
		   quantification */
		row_idx = (long) G_northing_to_row (y, &region);
		col_idx = (long) G_easting_to_col (x, &region);				
				
		cellbuf = GT_RC_get (cache, (signed) row_idx);
		/* now read the raster value under the current site */
		if (G_is_c_null_value (&cellbuf[col_idx]) == 0) {
			/* site on cell within category range [0..cats] ? */
			if ( (cellbuf[col_idx] > -1) && (cellbuf[col_idx] <= cats) ) {
				share_smp [cellbuf[col_idx] ] ++;
				/* i keeps track of samples on non-null coverage only */
				/* inside the current region */
				i ++;
			} else {
				if ( uncat_flag ) {
					/* also keep count of sites on uncategorised cells? */
					i ++;
					nocat_count++;
				}
			}				
		}
		if (G_is_c_null_value (&cellbuf[col_idx]) == 1) { 
			/* got a NULL value under this site */
			if (null_flag) { /* only count this, if null flag is set */
				null_count ++;
				i ++;
			}
		}
	}
	
	Vect_close (&in_vect_map);		
	
	fprintf (lp,"\n");
	if ( background ) {
		fprintf (lp,"Distribution of categories under %lu points (%lu in region) and in input map:\n",i,no_sites);	
	} else {
		fprintf (lp,"Distribution of categories under %lu points (%lu in region):\n",i,no_sites);	
	}
	/* determine starting value for total of sites analysed */
	total = 0;
	for ( j=0; j < cats; j ++) {
		total = total + share_smp[j];
		map_total = map_total + cat_count[j];
	}
	if (null_flag) { /* add NULL values to total */	
		total = total + null_count;
		map_total = map_total + null_count_map;
	}
	if (uncat_flag) { /* add uncategorised cells to total */
		total = total + nocat_count;
		map_total = map_total + nocat_count_map;
		
	}
	
	/* Now display those values which the user has chosen */
	if ( (background) && (gain) ) {	
		fprintf (lp,"Cat.\tPts.\t(%%)\tMap\t(%%)\tGain\tDescription\n");				
	}
	if ( (background) && (!gain) ) {	
		fprintf (lp,"Cat.\tPts.\t(%%)\tMap\t(%%)\tDescription\n");		
	}
	if ( (!background) && (gain) ) {	
		fprintf (lp,"Cat.\tPts.\t(%%)\tGain\tDescription\n");
	}
	if ( (!background) && (!gain) ) {	
		fprintf (lp,"Cat.\tPts.\t(%%)\tDescription\n");
	}	
	for ( j = 0; j < cats; j ++) {
		/* if skip_flag is not set: only show categories that have count > 0 */
		if ((skip_flag == 1) || ((skip_flag == 0) && (share_smp[j] > 0))) {
			if ( (background) && (gain) ) {
				/* Kvamme's Gain = 1 - (%area/%sites) */
				kvamme_gain = gstats_gain_K(((double) share_smp[j]*(100/total)),
							    ((double) cat_count[j]*(100/map_total)));							    				
				fprintf (lp, "%lu\t%6lu\t%6.2f\t%8lu %6.2f\t%6.2f\t%s\n", j, share_smp[j], (float) share_smp[j]*(100/total),
						cat_count[j], (float) cat_count[j]*(100/map_total),
						kvamme_gain, cats_description[j]);
			} 
			if ( (background) && (!gain) ) {
				fprintf (lp, "%lu\t%6lu\t%6.2f\t%8lu %6.2f\t%s\n", j, share_smp[j], (float) share_smp[j]*(100/total),
						cat_count[j], (float) cat_count[j]*(100/map_total),
						cats_description[j]);
				
			} 			
			if ( (!background) && (gain) ) {
				kvamme_gain = 1-( (float) cat_count[j]*(100/map_total) / (float) share_smp[j]*(100/total) );
				fprintf (lp, "%lu\t%6lu\t%6.2f\t%6.2f\t%s\n", j, share_smp[j], (float) share_smp[j]*(100/total),						
						kvamme_gain, cats_description[j]);				
			} 			
			if ( (!background) && (!gain) ) {
				fprintf (lp, "%lu\t%6lu\t%6.2f\t%s\n", j, share_smp[j], (float) share_smp[j]*(100/total),
						cats_description[j]);
			} 									
		}
	}
	if (null_flag) {		
		if ( background ) {
			fprintf (lp,"NULL\t%6lu\t%6.2f\t%8lu %6.2f\n",null_count, (float) null_count * 100 / total
						,null_count_map, (float) null_count_map * 100 / map_total);
		} else {
			fprintf (lp,"NULL\t%6lu\t%6.2f\n",null_count, (float) null_count * 100 / total);
		}
	}
	if (uncat_flag) {
		if ( background ) {
			fprintf (lp,"NOCAT\t%6lu\t%6.2f\t%8lu %6.2f\n",nocat_count, (float) nocat_count * 100 / total
						,nocat_count_map, (float) nocat_count_map * 100 / map_total);
		} else {
			fprintf (lp,"NOCAT\t%6lu\t%6.2f\n",nocat_count, (float) nocat_count * 100 / total);
		}		
	}	
	if ( background) {
		fprintf (lp,"TOTAL\t%6lu\t%6.2f\t%8lu %6.2f\n",(long) total, (float) 100, (long) map_total, (float) 100);
	} else {
		fprintf (lp,"TOTAL\t%6lu\t%6.2f\n",(long) total, (float) 100);
	}
	
	/* close cache and sites file; free buffers. */
	GT_RC_close (cache);
	G_free (cellbuf);
	G_free (cache);	
}
Exemple #11
0
int
main (int argc, char *argv[]) {
	struct GModule *module;
	struct Option *map; /* raster map to work on */
	struct Option *sites; /* output map to write */
	struct Option *mode; /* Categorisation mode */
	struct Option *min; /* range of values to categorise ... */
	struct Option *max; /*   .. anything outside will be NULL in output */
	struct Option *logfile; /* log output to this file instead of stdout */
	struct Option *precision; /* decimal digits precision for log file */
	struct Option *cachesize;
	struct Flag *null; /* also count NULL values? */
	struct Flag *all; /* disregard region when reporting total percentages */			
	struct Flag *zeroskip;	/* also show categories with 0 count? */
	struct Flag *uncat; /* also show cells outside category range? */	
	struct Flag *background; /* show background distribution? */
	struct Flag *gain; /* calculate Kvamme's gain for each category? */
	struct Flag *quiet; /* no status display on screen */				
	
	char *mapset;
	int show_progress = 1; /* enable progress display by default */
	/* these vars are used to store information about the input map */
	int cats; /* number of categories in input map */
	long null_count; /* number of NULL cells */
	long nocat_count; /* number of cells that do not fall into the category range [0 .. n] */	
	/* use to create command line for r.categorize call */
	char *sysstr, *tmpfile, *input_map;	
	int error;
	
	sysstr = NULL;
	tmpfile = NULL;
	
	/* setup some basic GIS stuff */
	G_gisinit (argv[0]);
	module = G_define_module ();
	module->description = "Analyses distribution of vector sample over a raster map";
	/* do not pause after a warning message was displayed */
	G_sleep_on_error (0);
		
	/* DEFINE OPTIONS AND FLAGS */
	/* raster map to sample */
	map = G_define_standard_option (G_OPT_R_INPUT);
	map->key = "raster";
	map->type = TYPE_STRING;
	map->required = YES;
	map->description = "Raster map to sample";

	/* site map for sampling positions */
	sites = G_define_standard_option (G_OPT_V_INPUT);
	sites->key = "positions";
	sites->type = TYPE_STRING;
	sites->required = YES;
	sites->description = "Vector map with sampling positions";
		
	/* Categorisation mode */
	mode = G_define_option ();
	mode->key = "mode";
	mode->type = TYPE_STRING;
	mode->required = NO;
	mode->description = "Categorisation mode (see manual)";

	/* min raster value to categorise */
	min = G_define_option ();
	min->key = "min";
	min->type = TYPE_DOUBLE;
	min->required = NO;
	min->description = "Minimum value to include in categorisation";

	/* max raster value to categorise */
	max = G_define_option ();
	max->key = "max";
	max->type = TYPE_DOUBLE;
	max->required = NO;
	max->description = "Maximum value to include in categorisation.";

	/* optional name of logfile */
	logfile = G_define_option ();
	logfile->key = "logfile";
	logfile->type = TYPE_DOUBLE;
	logfile->required = NO;
	logfile->description = "Name of ASCII logfile, if desired.";
	
	/* optional number of decimal digitis to store in logfile/show on screen */
	precision = G_define_option ();
	precision->key = "precision";
	precision->type = TYPE_DOUBLE;
	precision->required = NO;
	precision->answer = "2";
	precision->description = "Number of decimal digits for statistics/logfile";		
	
	/* number of lines to store in cache */
	cachesize = G_define_option ();
	cachesize->key = "cachesize";
	cachesize->type = TYPE_INTEGER;
	cachesize->answer = "-1";
	cachesize->required = NO;
	cachesize->description = "Number of raster rows to store in cache (-1 for auto)";	
		
	null = G_define_flag ();
	null->key = 'n';
	null->description = "Include NULL cells in report.";
	
	uncat = G_define_flag ();
	uncat->key = 'u';
	uncat->description = "Include uncategorised cells in statistics.";
	
	all = G_define_flag ();
	all->key = 'a';
	all->description = "Disregard region setting for counts.";	
	
	zeroskip = G_define_flag ();
	zeroskip->key = 'z';
	zeroskip->description = "Also show categories with zero count/percentage.";

	background = G_define_flag ();
	background->key = 'b';
	background->description = "Show background distribution of categories in raster input map.";

	gain = G_define_flag ();
	gain->key = 'g';
	gain->description = "Calculate Kvamme's Gain Factor for each category.";

	quiet = G_define_flag ();
	quiet->key = 'q';
	quiet->description = "Quiet operation: do not show progress display.";	

	
	/* parse command line */
	if (G_parser (argc, argv))
	{
		exit (-1);
	}

	/* check for 'quiet' flag */
	if ( quiet->answer ) {
		show_progress = 0;
	}
	
	PROGNAME = argv[0];		

	/* copy the 'map' option string to another buffer and use that */
	/* from now on. We do this because we might want to manipulate */
	/* that string and that is dangerous with GRASS Option->answer strings! */
	input_map = G_calloc (255, sizeof (char));
	G_strcpy (input_map, map->answer);
	
	mapset = G_calloc (255, sizeof (char));
	/* check if input map is a fully categorised raster map */
	mapset = G_find_cell (input_map,"");
	if ( mapset == NULL) {
		G_fatal_error ("The input map does not exist in the current database.");
	}

	if ( mode->answer == NULL ) {		
		cats = GT_get_stats (input_map,mapset,&null_count, &nocat_count, show_progress);
		if ( cats < 0 ) {
			G_fatal_error ("Could not stat input map. Do you have read access?");
		}
		if ( ((cats == 0) && (mode->answer==NULL)) ) {
			G_fatal_error ("No categories defined in input map.\nPlease specify a mode to create a fully classified map.");
		}
	}

	/* a classification mode was given: call r.categorize and save output
	   in a tmp file */
	if ( mode->answer != NULL ) {
		srand ((unsigned long) time(NULL));
		tmpfile = G_calloc (255, sizeof(char));
		sysstr = G_calloc (255, sizeof(char));
		/* create tmp file name from current PID and system time */		
		sprintf (tmpfile,"tmp.%i.%i", getpid(),(rand())/10000);
		if ( getenv("GISBASE") == NULL ) {
			G_fatal_error ("GISBASE not set. Unable to call GRASS module 'r.categorise'.");
		}		
		if ( quiet->answer ) {
			sprintf (sysstr,"%s/bin/r.categorize input=%s@%s output=%s mode=%s min=%s max=%s -q", getenv("GISBASE"), map->answer, 
					mapset, tmpfile, mode->answer, min->answer, max->answer);
		} else {
			sprintf (sysstr,"%s/bin/r.categorize input=%s@%s output=%s mode=%s min=%s max=%s", getenv("GISBASE"), map->answer, 
					mapset, tmpfile, mode->answer, min->answer, max->answer);
		}
		/* now create fully classified map using r.categorize and store */
		/* it in a temporary raster map */
		error = system (sysstr);
		if ( error < 0 ) {
			G_fatal_error ("Calling r.categorize has failed. Check your installation.");
		}
				
		/* store name of temporary file as new input map */
		G_strcpy (input_map, tmpfile);
		
		/* check categories of tmpfile */
		cats = GT_get_stats (input_map,mapset,&null_count, &nocat_count, show_progress);
		if (cats < 1) {
			G_fatal_error ("Could not create a fully categorised temporary file.\nTry another categorisation mode.");
		}
	}
	
	/* initialise cache structure */
	if ( input_map != NULL ) {
		/* set cachesize */
		CACHESIZE = atoi (cachesize->answer);
		if ( (CACHESIZE<-1) || (CACHESIZE > G_window_rows ()) ) {
			/* if cache size is invalid, just set to auto-mode (-1) */
			G_warning ("Invalid cache size requested (must be between 0 and %i or -1).\n", G_window_rows());
			CACHESIZE = -1;
		}
	}			
	
	if ( G_raster_map_is_fp (input_map, mapset))  {
		do_report_DCELL (input_map, mapset, sites->answer,
				atoi (precision->answer),null->answer, uncat->answer,
	           	all->answer, quiet->answer, zeroskip->answer,
			   	logfile->answer, background->answer, gain->answer, show_progress);
	} else {
		do_report_CELL (input_map, mapset, sites->answer,
				atoi (precision->answer),null->answer, uncat->answer,
	           	all->answer, quiet->answer, zeroskip->answer,
			   	logfile->answer, background->answer, gain->answer, show_progress);		
	}

		
	/* delete temporary file, if needed */
	if ( mode->answer != NULL ) {
		delete_tmpfile (tmpfile);
		G_free (tmpfile);
	}
	
	if ( sysstr != NULL ) {
		G_free (sysstr);
	}
	G_free (input_map);

	return (EXIT_SUCCESS);
}
Exemple #12
0
/*!
 * \brief Create window mapping.
 *
 * Creates mapping from cell header into window. The boundaries and 
 * resolution of the two spaces do not have to be the same or aligned in 
 * any way.
 *
 * \param fd file descriptor
 */
void Rast__create_window_mapping(int fd)
{
    struct fileinfo *fcb = &R__.fileinfo[fd];
    COLUMN_MAPPING *col;
    int i;
    int x;
    double C1, C2;
    double west;

    if (fcb->open_mode >= 0 && fcb->open_mode != OPEN_OLD)	/* open for write? */
	return;
    if (fcb->open_mode == OPEN_OLD)	/* already open ? */
	G_free(fcb->col_map);

    col = fcb->col_map = alloc_index(R__.rd_window.cols);

    /*
     * for each column in the window, go to center of the cell,
     * compute nearest column in the data file
     * if column is not in data file, set column to 0
     *
     * for lat/lon move window so that west is bigger than
     * cellhd west.
     */
    west = R__.rd_window.west;
    if (R__.rd_window.proj == PROJECTION_LL) {
	while (west > fcb->cellhd.west + 360.0)
	    west -= 360.0;
	while (west < fcb->cellhd.west)
	    west += 360.0;
    }

    C1 = R__.rd_window.ew_res / fcb->cellhd.ew_res;
    C2 = (west - fcb->cellhd.west +
	  R__.rd_window.ew_res / 2.0) / fcb->cellhd.ew_res;
    for (i = 0; i < R__.rd_window.cols; i++) {
	x = C2;
	if (C2 < x)		/* adjust for rounding of negatives */
	    x--;
	if (x < 0 || x >= fcb->cellhd.cols)	/* not in data file */
	    x = -1;
	*col++ = x + 1;
	C2 += C1;
    }

    /* do wrap around for lat/lon */
    if (R__.rd_window.proj == PROJECTION_LL) {
	col = fcb->col_map;
	C2 = (west - 360.0 - fcb->cellhd.west +
	      R__.rd_window.ew_res / 2.0) / fcb->cellhd.ew_res;
	for (i = 0; i < R__.rd_window.cols; i++) {
	    x = C2;
	    if (C2 < x)		/* adjust for rounding of negatives */
		x--;
	    if (x < 0 || x >= fcb->cellhd.cols)	/* not in data file */
		x = -1;
	    if (*col == 0)	/* only change those not already set */
		*col = x + 1;
	    col++;
	    C2 += C1;
	}
    }

    G_debug(3, "create window mapping (%d columns)", R__.rd_window.cols);
    /*  for (i = 0; i < R__.rd_window.cols; i++)
       fprintf(stderr, "%s%ld", i % 15 ? " " : "\n", (long)fcb->col_map[i]);
       fprintf(stderr, "\n");
     */

    /* compute C1,C2 for row window mapping */
    fcb->C1 = R__.rd_window.ns_res / fcb->cellhd.ns_res;
    fcb->C2 =
	(fcb->cellhd.north - R__.rd_window.north +
	 R__.rd_window.ns_res / 2.0) / fcb->cellhd.ns_res;
}
Exemple #13
0
static int load_seeds(struct globals *globals, int srows, int scols, int nseg)
{
    int row, col;
    SEGMENT seeds_seg;
    CELL *seeds_buf, seeds_val;
    int seeds_fd;
    int spos, sneg, have_seeds;
    struct rc Ri;

    G_debug(1, "load_seeds()");
    
    G_message(_("Loading seeds from raster map <%s>..."), globals->seeds);

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

    seeds_fd = Rast_open_old(globals->seeds, "");
    seeds_buf = Rast_allocate_c_buf();
    
    have_seeds = 0;

    /* load seeds map to segment structure */
    for (row = 0; row < globals->nrows; row++) {
	Rast_get_c_row(seeds_fd, seeds_buf, row);
	for (col = 0; col < globals->ncols; col++) {
	    if (FLAG_GET(globals->null_flag, row, col)) {
		Rast_set_c_null_value(&seeds_val, 1);
	    }
	    else {
		seeds_val = seeds_buf[col];
		if (!Rast_is_c_null_value(&seeds_val))
		    have_seeds = 1;
	    }
	    if (Segment_put(&seeds_seg, &seeds_val, row, col) != 1)
		G_fatal_error(_("Unable to write to temporary file"));
	}
    }

    if (!have_seeds) {
	G_warning(_("No seeds found in '%s'!"), globals->seeds);
	G_free(seeds_buf);
	Rast_close(seeds_fd);
	Segment_close(&seeds_seg);
	return 0;
    }

    spos = 1;
    sneg = -1;

    /* convert seeds to regions */
    G_debug(1, "convert seeds to regions");
    Rast_set_c_null_value(&seeds_val, 1);
    for (row = 0; row < globals->nrows; row++) {
	Rast_get_c_row(seeds_fd, seeds_buf, row);
	for (col = 0; col < globals->ncols; col++) {
	    if (!(FLAG_GET(globals->null_flag, row, col)) && 
	        !(FLAG_GET(globals->candidate_flag, row, col))) {

		if (Rast_is_c_null_value(&(seeds_buf[col]))) {
		    if (Segment_put(&globals->rid_seg, &sneg, row, col) != 1)
			G_fatal_error(_("Unable to write to temporary file"));
		    sneg--;
		    globals->n_regions--;
		}
		else {
		    Ri.row = row;
		    Ri.col = col;
		    read_seed(globals, &seeds_seg, &Ri, spos);
		    spos++;
		}
	    }
	}
    }

    G_free(seeds_buf);
    Rast_close(seeds_fd);
    Segment_close(&seeds_seg);

    globals->n_regions = spos - 1;
    
    flag_clear_all(globals->candidate_flag);
    
    return 1;
}
Exemple #14
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;
}
Exemple #15
0
int main(int argc, char *argv[])
{
    /* variables */
    DCELL *data_buf;
    CELL *clump_buf;
    CELL i, max;

    int row, col, rows, cols;
    int out_mode, use_MASK, *n, *e;
    long int *count;
    int fd_data, fd_clump;

    const char *datamap, *clumpmap, *centroidsmap;
    
    double avg, vol, total_vol, east, north, *sum;

    struct Cell_head window;

    struct Map_info *fd_centroids;
    struct line_pnts *Points;
    struct line_cats *Cats;
    struct field_info *Fi;

    char buf[DB_SQL_MAX];
    dbString sql;
    dbDriver *driver;

    struct GModule *module;
    struct {
        struct Option *input, *clump, *centroids, *output;
    } opt;
    struct {
        struct Flag *report;
    } flag;

    /* define parameters and flags */
    G_gisinit(argv[0]);

    module = G_define_module();
    G_add_keyword(_("raster"));
    G_add_keyword(_("volume"));
    G_add_keyword(_("clumps"));
    module->label =
	_("Calculates the volume of data \"clumps\".");
    module->description = _("Optionally produces a GRASS vector points map "
                            "containing the calculated centroids of these clumps.");

    opt.input = G_define_standard_option(G_OPT_R_INPUT);
    opt.input->description =
	_("Name of input raster map representing data that will be summed within clumps");

    opt.clump = G_define_standard_option(G_OPT_R_INPUT);
    opt.clump->key = "clump";
    opt.clump->required = NO;
    opt.clump->label =
        _("Name of input clump raster map");
    opt.clump->description = _("Preferably the output of r.clump. "
                               "If no clump map is given than MASK is used.");

    opt.centroids = G_define_standard_option(G_OPT_V_OUTPUT);
    opt.centroids->key = "centroids";
    opt.centroids->required = NO;
    opt.centroids->description = _("Name for output vector points map to contain clump centroids");

    opt.output = G_define_standard_option(G_OPT_F_OUTPUT);
    opt.output->required = NO;
    opt.output->label =
	_("Name for output file to hold the report");
    opt.output->description =
	_("If no output file given report is printed to standard output");

    flag.report = G_define_flag();
    flag.report->key = 'f';
    flag.report->description = _("Generate unformatted report (items separated by colon)");

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

    /* get arguments */
    datamap = opt.input->answer;
    
    clumpmap = NULL;
    if (opt.clump->answer)
	clumpmap = opt.clump->answer;
    
    centroidsmap = NULL;
    fd_centroids = NULL;
    Points = NULL;
    Cats = NULL;
    driver = NULL;
    if (opt.centroids->answer) {
	centroidsmap = opt.centroids->answer;
        fd_centroids = G_malloc(sizeof(struct Map_info));
    }
    
    out_mode = (!flag.report->answer);

    /*
     * see if MASK or a separate "clumpmap" raster map is to be used
     * -- it must(!) be one of those two choices.
     */
    use_MASK = 0;
    if (!clumpmap) {
	clumpmap = "MASK";
	use_MASK = 1;
        if (!G_find_raster2(clumpmap, G_mapset()))
            G_fatal_error(_("No MASK found. If no clump map is given than the MASK is required. "
                            "You need to define a clump raster map or create a MASK by r.mask command."));
        G_important_message(_("No clump map given, using MASK"));
    }
    
    /* open input and clump raster maps */
    fd_data = Rast_open_old(datamap, "");
    fd_clump = Rast_open_old(clumpmap, use_MASK ? G_mapset() : "");
    
    /* initialize vector map (for centroids) if needed */
    if (centroidsmap) {
	if (Vect_open_new(fd_centroids, centroidsmap, WITHOUT_Z) < 0)
	    G_fatal_error(_("Unable to create vector map <%s>"), centroidsmap);
        
        Points = Vect_new_line_struct();
        Cats = Vect_new_cats_struct();
        
        /* initialize data structures */
        Vect_append_point(Points, 0., 0., 0.);
        Vect_cat_set(Cats, 1, 1);
    }
    
    /* initialize output file */
    if (opt.output->answer && strcmp(opt.output->answer, "-") != 0) {
	if (freopen(opt.output->answer, "w", stdout) == NULL) {
	    perror(opt.output->answer);
	    exit(EXIT_FAILURE);
	}
    }

    /* initialize data accumulation arrays */
    max = Rast_get_max_c_cat(clumpmap, use_MASK ? G_mapset() : "");

    sum = (double *)G_malloc((max + 1) * sizeof(double));
    count = (long int *)G_malloc((max + 1) * sizeof(long int));

    G_zero(sum, (max + 1) * sizeof(double));
    G_zero(count, (max + 1) * sizeof(long int));
    
    data_buf = Rast_allocate_d_buf();
    clump_buf = Rast_allocate_c_buf();
    
    /* get window size */
    G_get_window(&window);
    rows = window.rows;
    cols = window.cols;

    /* now get the data -- first pass */
    for (row = 0; row < rows; row++) {
	G_percent(row, rows, 2);
	Rast_get_d_row(fd_data, data_buf, row);
	Rast_get_c_row(fd_clump, clump_buf, row);
	for (col = 0; col < cols; col++) {
	    i = clump_buf[col];
	    if (i > max)
		G_fatal_error(_("Invalid category value %d (max=%d): row=%d col=%d"),
                              i, max, row, col);
	    if (i < 1) {
                G_debug(3, "row=%d col=%d: zero or negs ignored", row, col);
		continue;	/* ignore zeros and negs */
            }
	    if (Rast_is_d_null_value(&data_buf[col])) {
                G_debug(3, "row=%d col=%d: NULL ignored", row, col);
		continue;
            }
            
	    sum[i] += data_buf[col];
	    count[i]++;
	}
    }
    G_percent(1, 1, 1);
    
    /* free some buffer space */
    G_free(data_buf);
    G_free(clump_buf);

    /* data lists for centroids of clumps */
    e = (int *)G_malloc((max + 1) * sizeof(int));
    n = (int *)G_malloc((max + 1) * sizeof(int));

    i = centroids(fd_clump, e, n, 1, max);

    /* close raster maps */
    Rast_close(fd_data);
    Rast_close(fd_clump);
    
    /* got everything, now do output */
    if (centroidsmap) {
        G_message(_("Creating vector point map <%s>..."), centroidsmap);
        /* set comment */
	sprintf(buf, _("From '%s' on raster map <%s> using clumps from <%s>"),
                argv[0], datamap, clumpmap);
        Vect_set_comment(fd_centroids, buf);

        /* create attribute table */        
        Fi = Vect_default_field_info(fd_centroids, 1, NULL, GV_1TABLE);
        
        driver = db_start_driver_open_database(Fi->driver,
                                               Vect_subst_var(Fi->database, fd_centroids));
	if (driver == NULL) {
	    G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
			  Vect_subst_var(Fi->database, fd_centroids), Fi->driver);
	}
        db_set_error_handler_driver(driver);
        
	db_begin_transaction(driver);
        
        db_init_string(&sql);
	sprintf(buf, "create table %s (cat integer, volume double precision, "
                "average double precision, sum double precision, count integer)",
                Fi->table);
	db_set_string(&sql, buf);
	Vect_map_add_dblink(fd_centroids, 1, NULL, Fi->table, GV_KEY_COLUMN, Fi->database,
			    Fi->driver);

	G_debug(3, "%s", db_get_string(&sql));
	if (db_execute_immediate(driver, &sql) != DB_OK) {
	    G_fatal_error(_("Unable to create table: %s"), db_get_string(&sql));
	}
    }

    /* print header */
    if (out_mode) {
	fprintf(stdout, _("\nVolume report on data from <%s> using clumps on <%s> raster map"),
                datamap, clumpmap);
        fprintf(stdout, "\n\n");
	fprintf(stdout,
		_("Category   Average   Data   # Cells        Centroid             Total\n"));
	fprintf(stdout,
		_("Number     in clump  Total  in clump   Easting     Northing     Volume"));
        fprintf(stdout, "\n%s\n", SEP);
    }
    total_vol = 0.0;

    /* print output, write centroids */
    for (i = 1; i <= max; i++) {
	if (count[i]) {
	    avg = sum[i] / (double)count[i];
	    vol = sum[i] * window.ew_res * window.ns_res;
	    total_vol += vol;
	    east = window.west + (e[i] + 0.5) * window.ew_res;
	    north = window.north - (n[i] + 0.5) * window.ns_res;
	    if (fd_centroids) { /* write centroids if requested */
                Points->x[0] = east;
                Points->y[0] = north;
                Cats->cat[0] = i;
                Vect_write_line(fd_centroids, GV_POINT, Points, Cats);
	
                sprintf(buf, "insert into %s values (%d, %f, %f, %f, %ld)",
                        Fi->table, i, vol, avg, sum[i], count[i]);
                db_set_string(&sql, buf);

                if (db_execute_immediate(driver, &sql) != DB_OK)
                    G_fatal_error(_("Cannot insert new row: %s"),
                                  db_get_string(&sql));
	    }
	    if (out_mode)
		fprintf(stdout,
			"%8d%10.2f%10.0f %7ld  %10.2f  %10.2f %16.2f\n", i,
			avg, sum[i], count[i], east, north, vol);
	    else
		fprintf(stdout, "%d:%.2f:%.0f:%ld:%.2f:%.2f:%.2f\n",
			i, avg, sum[i], count[i], east, north, vol);
	}
    }

    /* write centroid attributes and close the map*/
    if (fd_centroids) {
        db_commit_transaction(driver);
        Vect_close(fd_centroids);
    }
    
    /* print total value */
    if (total_vol > 0.0 && out_mode) {
        fprintf(stdout, "%s\n", SEP);
	fprintf(stdout, "%60s = %14.2f", _("Total Volume"), total_vol);
        fprintf(stdout, "\n");
    }

    exit(EXIT_SUCCESS);
} 
Exemple #16
0
int main(int argc, char *argv[])
{
    /* buffer for input-output rasters */
    void *inrast_TEMPKA, *inrast_PATM, *inrast_RNET, *inrast_G0;
    DCELL *outrast;

    /* pointers to input-output raster files */
    int infd_TEMPKA, infd_PATM, infd_RNET, infd_G0;
    int outfd;

    /* names of input-output raster files */
    char *RNET, *TEMPKA, *PATM, *G0;
    char *ETa;

    /* input-output cell values */
    DCELL d_tempka, d_pt_patm, d_rnet, d_g0;
    DCELL d_pt_alpha, d_pt_delta, d_pt_ghamma, d_daily_et;

    /* region information and handler */
    struct Cell_head cellhd;
    int nrows, ncols;
    int row, col;

    /* parser stuctures definition */
    struct GModule *module;
    struct Option *input_RNET, *input_TEMPKA, *input_PATM, *input_G0,
	*input_PT;
    struct Option *output;
    struct Flag *zero;
    struct Colors color;
    struct History history;

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

    module = G_define_module();
    G_add_keyword(_("imagery"));
    G_add_keyword(_("evapotranspiration"));
    module->description =
	_("Computes evapotranspiration calculation "
	  "Priestley and Taylor formulation, 1972.");
    
    /* Define different options */
    input_RNET = G_define_standard_option(G_OPT_R_INPUT);
    input_RNET->key = "net_radiation";
    input_RNET->description = _("Name of input net radiation raster map [W/m2]");

    input_G0 = G_define_standard_option(G_OPT_R_INPUT);
    input_G0->key = "soil_heatflux";
    input_G0->description = _("Name of input soil heat flux raster map [W/m2]");

    input_TEMPKA = G_define_standard_option(G_OPT_R_INPUT);
    input_TEMPKA->key = "air_temperature";
    input_TEMPKA->description = _("Name of input air temperature raster map [K]");

    input_PATM = G_define_standard_option(G_OPT_R_INPUT);
    input_PATM->key = "atmospheric_pressure";
    input_PATM->description = _("Name of input atmospheric pressure raster map [millibars]");

    input_PT = G_define_option();
    input_PT->key = "priestley_taylor_coeff";
    input_PT->type = TYPE_DOUBLE;
    input_PT->required = YES;
    input_PT->description = _("Priestley-Taylor coefficient");
    input_PT->answer = "1.26";

    output = G_define_standard_option(G_OPT_R_OUTPUT);
    output->description = _("Name of output evapotranspiration raster map [mm/d]");

    /* Define the different flags */
    zero = G_define_flag();
    zero->key = 'z';
    zero->description = _("Set negative ETa to zero");

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

    /* get entered parameters */
    RNET = input_RNET->answer;
    TEMPKA = input_TEMPKA->answer;
    PATM = input_PATM->answer;
    G0 = input_G0->answer;
    d_pt_alpha = atof(input_PT->answer);

    ETa = output->answer;

    /* open pointers to input raster files */
    infd_RNET = Rast_open_old(RNET, "");
    infd_TEMPKA = Rast_open_old(TEMPKA, "");
    infd_PATM = Rast_open_old(PATM, "");
    infd_G0 = Rast_open_old(G0, "");

    /* read headers of raster files */
    Rast_get_cellhd(RNET, "", &cellhd);
    Rast_get_cellhd(TEMPKA, "", &cellhd);
    Rast_get_cellhd(PATM, "", &cellhd);
    Rast_get_cellhd(G0, "", &cellhd);

    /* Allocate input buffer */
    inrast_RNET = Rast_allocate_d_buf();
    inrast_TEMPKA = Rast_allocate_d_buf();
    inrast_PATM = Rast_allocate_d_buf();
    inrast_G0 = Rast_allocate_d_buf();

    /* get rows and columns number of the current region */
    nrows = Rast_window_rows();
    ncols = Rast_window_cols();

    /* allocate output buffer */
    outrast = Rast_allocate_d_buf();

    /* open pointers to output raster files */
    outfd = Rast_open_new(ETa, DCELL_TYPE);

    /* start the loop through cells */
    for (row = 0; row < nrows; row++) {

	G_percent(row, nrows, 2);
	/* read input raster row into line buffer */
	Rast_get_d_row(infd_RNET, inrast_RNET, row);
	Rast_get_d_row(infd_TEMPKA, inrast_TEMPKA, row);
	Rast_get_d_row(infd_PATM, inrast_PATM, row);
	Rast_get_d_row(infd_G0, inrast_G0, row);

	for (col = 0; col < ncols; col++) {
	    /* read current cell from line buffer */
            d_rnet = ((DCELL *) inrast_RNET)[col];
            d_tempka = ((DCELL *) inrast_TEMPKA)[col];
            d_pt_patm = ((DCELL *) inrast_PATM)[col];
            d_g0 = ((DCELL *) inrast_G0)[col];

	    /*Delta_pt and Ghamma_pt */
	    d_pt_delta = pt_delta(d_tempka);
	    d_pt_ghamma = pt_ghamma(d_tempka, d_pt_patm);

	    /*Calculate ET */
	    d_daily_et =
		pt_daily_et(d_pt_alpha, d_pt_delta, d_pt_ghamma, d_rnet, d_g0,
			    d_tempka);
	    if (zero->answer && d_daily_et < 0)
		d_daily_et = 0.0;

	    /* write calculated ETP to output line buffer */
	    outrast[col] = d_daily_et;
	}

	/* write output line buffer to output raster file */
	Rast_put_d_row(outfd, outrast);
    }
    /* free buffers and close input maps */

    G_free(inrast_RNET);
    G_free(inrast_TEMPKA);
    G_free(inrast_PATM);
    G_free(inrast_G0);
    Rast_close(infd_RNET);
    Rast_close(infd_TEMPKA);
    Rast_close(infd_PATM);
    Rast_close(infd_G0);

    /* generate color table between -20 and 20 */
    Rast_make_rainbow_colors(&color, -20, 20);
    Rast_write_colors(ETa, G_mapset(), &color);

    Rast_short_history(ETa, "raster", &history);
    Rast_command_history(&history);
    Rast_write_history(ETa, &history);

    /* free buffers and close output map */
    G_free(outrast);
    Rast_close(outfd);

    return (EXIT_SUCCESS);
}
Exemple #17
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;
}
Exemple #18
0
int db__copy_table(const char *from_drvname, const char *from_dbname,
		   const char *from_tblname, const char *to_drvname,
		   const char *to_dbname, const char *to_tblname,
		   const char *where, const char *select, const char *selcol,
		   int *ivals, int nvals)
{
    int col, ncols, sqltype, ctype, more, selcol_found;
    char buf[1000];
    int *ivalues;
    dbHandle from_handle, to_handle;
    dbString tblname, sql;
    dbString value_string;
    dbString *tblnames;
    dbTable *table, *out_table;
    dbCursor cursor;
    dbColumn *column;
    dbValue *value;
    const char *colname;
    dbDriver *from_driver, *to_driver;
    int count, i;

    G_debug(3, "db_copy_table():\n  from driver = %s, db = %s, table = %s\n"
	    "  to driver = %s, db = %s, table = %s, where = %s, select = %s",
	    from_drvname, from_dbname, from_tblname, to_drvname, to_dbname,
	    to_tblname, where, select);

    db_init_handle(&from_handle);
    db_init_handle(&to_handle);
    db_init_string(&tblname);
    db_init_string(&sql);
    db_init_string(&value_string);

    /* Make a copy of input values and sort it */
    if (ivals) {
	ivalues = (int *)G_malloc(nvals * sizeof(int));
	memcpy(ivalues, ivals, nvals * sizeof(int));
	qsort((void *)ivalues, nvals, sizeof(int), cmp);
    }

    /* Open input driver and database */
    from_driver = db_start_driver(from_drvname);
    if (from_driver == NULL) {
	G_warning(_("Unable to start driver <%s>"), from_drvname);
	return DB_FAILED;
    }
    db_set_handle(&from_handle, from_dbname, NULL);
    if (db_open_database(from_driver, &from_handle) != DB_OK) {
	G_warning(_("Unable to open database <%s> by driver <%s>"),
		  from_dbname, from_drvname);
	db_close_database_shutdown_driver(from_driver);
	return DB_FAILED;
    }

    /* Open output driver and database */
    if (strcmp(from_drvname, to_drvname) == 0
	&& strcmp(from_dbname, to_dbname) == 0) {
	G_debug(3, "Use the same driver");
	to_driver = from_driver;
    }
    else {
	to_driver = db_start_driver(to_drvname);
	if (to_driver == NULL) {
	    G_warning(_("Unable to start driver <%s>"), to_drvname);
	    db_close_database_shutdown_driver(from_driver);
	    return DB_FAILED;
	}
	db_set_handle(&to_handle, to_dbname, NULL);
	if (db_open_database(to_driver, &to_handle) != DB_OK) {
	    G_warning(_("Unable to open database <%s> by driver <%s>"),
		      to_dbname, to_drvname);
	    db_close_database_shutdown_driver(to_driver);
	    if (from_driver != to_driver) {
		db_close_database_shutdown_driver(from_driver);
	    }
	    return DB_FAILED;
	}
    }

    db_begin_transaction(to_driver);

    /* Because in SQLite3 an opened cursor is no more valid
       if 'schema' is modified (create table), we have to open
       cursor twice */

    /* test if the table exists */
    if (db_list_tables(to_driver, &tblnames, &count, 0) != DB_OK) {
	G_warning(_("Unable to get list tables in database <%s>"),
		  to_dbname);
	db_close_database_shutdown_driver(to_driver);
	if (from_driver != to_driver)
	    db_close_database_shutdown_driver(from_driver);

	return DB_FAILED;
    }

    for (i = 0; i < count; i++) {
	const char *tblname = db_get_string(&tblnames[i]);

	if (strcmp(to_tblname, tblname) == 0) {
	    G_warning(_("Table <%s> already exists in database <%s>"),
		      to_tblname, to_dbname);
	    db_close_database_shutdown_driver(to_driver);
	    if (from_driver != to_driver)
		db_close_database_shutdown_driver(from_driver);

	    return DB_FAILED;
	}
    }

    /* Create new table */
    /* Open cursor for data structure */
    if (select) {
	db_set_string(&sql, select);

	/* TODO!: cannot use this because it will not work if a query 
	 *         ends with 'group by' for example */
	/*
	   tmp = strdup ( select );
	   G_tolcase ( tmp );

	   if ( !strstr( tmp,"where") )
	   {
	   db_append_string ( &sql, " where 0 = 1");
	   }
	   else
	   {
	   db_append_string ( &sql, " and 0 = 1");
	   }

	   free (tmp);
	 */
    }
    else {
	db_set_string(&sql, "select * from ");
	db_append_string(&sql, from_tblname);
	db_append_string(&sql, " where 0 = 1");	/* to get no data */
    }

    G_debug(3, db_get_string(&sql));
    if (db_open_select_cursor(from_driver, &sql, &cursor, DB_SEQUENTIAL) !=
	DB_OK) {
	G_warning(_("Unable to open select cursor: '%s'"),
		  db_get_string(&sql));
	db_close_database_shutdown_driver(to_driver);
	if (from_driver != to_driver) {
	    db_close_database_shutdown_driver(from_driver);
	}
	return DB_FAILED;
    }
    G_debug(3, "Select cursor opened");

    table = db_get_cursor_table(&cursor);
    ncols = db_get_table_number_of_columns(table);
    G_debug(3, "ncols = %d", ncols);

    out_table = db_alloc_table(ncols);
    db_set_table_name(out_table, to_tblname);

    selcol_found = 0;
    for (col = 0; col < ncols; col++) {
	dbColumn *out_column;

	column = db_get_table_column(table, col);
	colname = db_get_column_name(column);
	sqltype = db_get_column_sqltype(column);
	ctype = db_sqltype_to_Ctype(sqltype);

	G_debug(3, "%s (%s)", colname, db_sqltype_name(sqltype));

	out_column = db_get_table_column(out_table, col);

	if (selcol && G_strcasecmp(colname, selcol) == 0) {
	    if (ctype != DB_C_TYPE_INT)
		G_fatal_error(_("Column <%s> is not integer"),
			      colname);
	    selcol_found = 1;
	}

	db_set_column_name(out_column, db_get_column_name(column));
	db_set_column_description(out_column,
				  db_get_column_description(column));
	db_set_column_sqltype(out_column, db_get_column_sqltype(column));
	db_set_column_length(out_column, db_get_column_length(column));
	db_set_column_precision(out_column, db_get_column_precision(column));
	db_set_column_scale(out_column, db_get_column_scale(column));
    }

    db_close_cursor(&cursor);

    if (selcol && !selcol_found)
	G_fatal_error(_("Column <%s> not found"), selcol);

    if (db_create_table(to_driver, out_table) != DB_OK) {
	G_warning(_("Unable to create table <%s>"),
		  to_tblname);
	db_close_database_shutdown_driver(to_driver);
	if (from_driver != to_driver) {
	    db_close_database_shutdown_driver(from_driver);
	}
	return DB_FAILED;
    }

    /* Open cursor with data */
    if (select) {
	db_set_string(&sql, select);
    }
    else {
	db_set_string(&sql, "select * from ");
	db_append_string(&sql, from_tblname);
	if (where) {
	    db_append_string(&sql, " where ");
	    db_append_string(&sql, where);
	}
    }

    G_debug(3, db_get_string(&sql));
    if (db_open_select_cursor(from_driver, &sql, &cursor, DB_SEQUENTIAL) !=
	DB_OK) {
	G_warning(_("Unable to open select cursor: '%s'"),
		  db_get_string(&sql));
	db_close_database_shutdown_driver(to_driver);
	if (from_driver != to_driver) {
	    db_close_database_shutdown_driver(from_driver);
	}
	return DB_FAILED;
    }
    G_debug(3, "Select cursor opened");

    table = db_get_cursor_table(&cursor);
    ncols = db_get_table_number_of_columns(table);
    G_debug(3, "ncols = %d", ncols);

    /* Copy all rows */
    while (1) {
	int select;

	if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK) {
	    G_warning(_("Unable to fetch data from table <%s>"),
		      from_tblname);
	    db_close_cursor(&cursor);
	    db_close_database_shutdown_driver(to_driver);
	    if (from_driver != to_driver) {
		db_close_database_shutdown_driver(from_driver);
	    }
	    return DB_FAILED;
	}
	if (!more)
	    break;

	sprintf(buf, "insert into %s values ( ", to_tblname);
	db_set_string(&sql, buf);
	select = 1;
	for (col = 0; col < ncols; col++) {
	    column = db_get_table_column(table, col);
	    colname = db_get_column_name(column);
	    sqltype = db_get_column_sqltype(column);
	    ctype = db_sqltype_to_Ctype(sqltype);
	    value = db_get_column_value(column);

	    if (selcol && G_strcasecmp(colname, selcol) == 0) {
		if (db_test_value_isnull(value))
		    continue;
		if (!bsearch(&(value->i), ivalues, nvals, sizeof(int), cmp)) {
		    select = 0;
		    break;
		}
	    }
	    if (col > 0)
		db_append_string(&sql, ", ");
	    db_convert_value_to_string(value, sqltype, &value_string);
	    switch (ctype) {
	    case DB_C_TYPE_STRING:
	    case DB_C_TYPE_DATETIME:
		if (db_test_value_isnull(value)) {
		    db_append_string(&sql, "null");
		}
		else {
		    db_double_quote_string(&value_string);
		    db_append_string(&sql, "'");
		    db_append_string(&sql, db_get_string(&value_string));
		    db_append_string(&sql, "'");
		}
		break;
	    case DB_C_TYPE_INT:
	    case DB_C_TYPE_DOUBLE:
		if (db_test_value_isnull(value)) {
		    db_append_string(&sql, "null");
		}
		else {
		    db_append_string(&sql, db_get_string(&value_string));
		}
		break;
	    default:
		G_warning(_("Unknown column type (column <%s>)"),
			  colname);
		db_close_cursor(&cursor);
		db_close_database_shutdown_driver(to_driver);
		if (from_driver != to_driver) {
		    db_close_database_shutdown_driver(from_driver);
		}
		return DB_FAILED;
	    }
	}
	if (!select)
	    continue;
	db_append_string(&sql, ")");
	G_debug(3, db_get_string(&sql));
	if (db_execute_immediate(to_driver, &sql) != DB_OK) {
	    G_warning("Unable to insert new record: '%s'",
		      db_get_string(&sql));
	    db_close_cursor(&cursor);
	    db_close_database_shutdown_driver(to_driver);
	    if (from_driver != to_driver) {
		db_close_database_shutdown_driver(from_driver);
	    }
	    return DB_FAILED;
	}
    }
    if (selcol)
	G_free(ivalues);
    G_debug(3, "Table copy OK");

    db_close_cursor(&cursor);
    db_commit_transaction(to_driver);
    db_close_database_shutdown_driver(to_driver);
    if (from_driver != to_driver) {
	db_close_database_shutdown_driver(from_driver);
    }

    return DB_OK;
}
Exemple #19
0
int read_rgb(char *key, char *data)
{
    char names[3][100];
    char fullname[100];
    int i;

    if (sscanf(data, "%s %s %s", names[0], names[1], names[2]) != 3) {
	error(key, data, "illegal request (rgb)");
	return 0;
    }

    PS.do_raster = 0;
    PS.do_colortable = 0;
    if (PS.cell_fd >= 0) {
	G_close_cell(PS.cell_fd);
	G_free(PS.cell_name);
	G_free(PS.cell_mapset);
	G_free_colors(&PS.colors);
	PS.cell_fd = -1;
    }

    /* initialize group structure (for compatibility with PS_raster_plot()) */
    I_init_group_ref(&grp.ref);

    /*
     * not relevant here
     *
     if (I_get_group_ref(grp.group_name, &grp.ref) == 0)
     G_fatal_error(_("Can't get group information"));
     */

    grp.group_name = "RGB Group";

    /* get file names for R, G, & B */

    for (i = 0; i < 3; i++) {
	char *mapset, *name, *p;

	name = names[i];

	p = strchr(name, '@');
	if (p) {
	    *p = '\0';
	    mapset = p + 1;
	}
	else {
	    mapset = G_find_file2("cell", name, "");
	    if (!mapset) {
		error(name, "", "not found");
		return 0;
	    }
	}

	grp.name[i] = G_store(name);
	grp.mapset[i] = G_store(mapset);

	/* read in colors */
	if (G_read_colors(grp.name[i], grp.mapset[i], &(grp.colors[i])) == -1) {
	    sprintf(fullname, "%s in %s", grp.name[i], grp.mapset[i]);
	    error(fullname, "", "can't read color table");
	    return 0;
	}

	/* open raster maps for reading */
	if ((grp.fd[i] = G_open_cell_old(grp.name[i], grp.mapset[i])) < 0) {
	    sprintf(fullname, "%s in %s", grp.name[i], grp.mapset[i]);
	    error(fullname, "", "can't open raster map");
	    G_free_colors(&(grp.colors[i]));
	    return 0;
	}
    }

    strcpy(PS.celltitle, grp.group_name);
    G_strip(PS.celltitle);
    return 1;
}
Exemple #20
0
int main(int argc, char *argv[])
{
    unsigned int r, c, rows, cols;	/*  totals  */
    int map1_fd, map2_fd;
    double sumX, sumY, sumsqX, sumsqY, sumXY;
    double meanX, meanY, varX, varY, sdX, sdY;
    double A, B, R, F;
    long count = 0;
    DCELL *map1_buf, *map2_buf, map1_val, map2_val;
    char *name;
    struct Option *input_map1, *input_map2, *output_opt;
    struct Flag *shell_style;
    struct Cell_head region;
    struct GModule *module;

    G_gisinit(argv[0]);

    module = G_define_module();
    G_add_keyword(_("raster"));
    G_add_keyword(_("statistics"));
    module->description =
	_("Calculates linear regression from two raster maps: y = a + b*x.");

    /* Define the different options */
    input_map1 = G_define_standard_option(G_OPT_R_MAP);
    input_map1->key = "map1";
    input_map1->description = (_("Map for x coefficient"));

    input_map2 = G_define_standard_option(G_OPT_R_MAP);
    input_map2->key = "map2";
    input_map2->description = (_("Map for y coefficient"));

    output_opt = G_define_standard_option(G_OPT_F_OUTPUT);
    output_opt->key = "output";
    output_opt->required = NO;
    output_opt->description =
	(_("ASCII file for storing regression coefficients (output to screen if file not specified)."));

    shell_style = G_define_flag();
    shell_style->key = 'g';
    shell_style->description = _("Print in shell script style");

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

    name = output_opt->answer;
    if (name != NULL && strcmp(name, "-") != 0) {
	if (NULL == freopen(name, "w", stdout)) {
	    G_fatal_error(_("Unable to open file <%s> for writing"), name);
	}
    }

    G_get_window(&region);
    rows = region.rows;
    cols = region.cols;

    /* open maps */
    map1_fd = Rast_open_old(input_map1->answer, "");
    map2_fd = Rast_open_old(input_map2->answer, "");

    map1_buf = Rast_allocate_d_buf();
    map2_buf = Rast_allocate_d_buf();

    sumX = sumY = sumsqX = sumsqY = sumXY = 0.0;
    meanX = meanY = varX = varY = sdX = sdY = 0.0;
    for (r = 0; r < rows; r++) {
	G_percent(r, rows, 2);
	Rast_get_d_row(map1_fd, map1_buf, r);
	Rast_get_d_row(map2_fd, map2_buf, r);
	for (c = 0; c < cols; c++) {
	    map1_val = map1_buf[c];
	    map2_val = map2_buf[c];
	    if (Rast_is_d_null_value(&map1_val) ||
		Rast_is_d_null_value(&map2_val))
		continue;

	    sumX += map1_val;
	    sumY += map2_val;
	    sumsqX += map1_val * map1_val;
	    sumsqY += map2_val * map2_val;
	    sumXY += map1_val * map2_val;
	    count++;
	}
    }
    Rast_close(map1_fd);
    Rast_close(map2_fd);
    G_free(map1_buf);
    G_free(map2_buf);

    B = (sumXY - sumX * sumY / count) / (sumsqX - sumX * sumX / count);
    R = (sumXY - sumX * sumY / count) /
	sqrt((sumsqX - sumX * sumX / count) * (sumsqY - sumY * sumY / count));

    meanX = sumX / count;
    sumsqX = sumsqX / count;
    varX = sumsqX - (meanX * meanX);
    sdX = sqrt(varX);

    meanY = sumY / count;
    sumsqY = sumsqY / count;
    varY = sumsqY - (meanY * meanY);
    sdY = sqrt(varY);

    A = meanY - B * meanX;
    F = R * R / (1 - R * R / count - 2);

    if (shell_style->answer) {
	fprintf(stdout, "a=%f\n", A);
	fprintf(stdout, "b=%f\n", B);
	fprintf(stdout, "R=%f\n", R);
	fprintf(stdout, "N=%ld\n", count);
	fprintf(stdout, "F=%f\n", F);
	fprintf(stdout, "meanX=%f\n", meanX);
	fprintf(stdout, "sdX=%f\n", sdX);
	fprintf(stdout, "meanY=%f\n", meanY);
	fprintf(stdout, "sdY=%f\n", sdY);
    }
    else {
	fprintf(stdout, "y = a + b*x\n");
	fprintf(stdout, "   a (Offset): %f\n", A);
	fprintf(stdout, "   b (Gain): %f\n", B);
	fprintf(stdout, "   R (sumXY - sumX*sumY/N): %f\n", R);
	fprintf(stdout, "   N (Number of elements): %ld\n", count);
	fprintf(stdout, "   F (F-test significance): %f\n", F);
	fprintf(stdout, "   meanX (Mean of map1): %f\n", meanX);
	fprintf(stdout, "   sdX (Standard deviation of map1): %f\n", sdX);
	fprintf(stdout, "   meanY (Mean of map2): %f\n", meanY);
	fprintf(stdout, "   sdY (Standard deviation of map2): %f\n", sdY);
    }

    exit(EXIT_SUCCESS);
}
Exemple #21
0
/*!
 *  \brief Extract a cell value from raster map (cubic interpolation).
 *
 *  Extract a cell value from raster map at given northing and easting
 *  with a sampled 3x3 window using a cubic interpolation.
 *
 *  \param fd file descriptor
 *  \param window region settings
 *  \param cats categories
 *  \param north northing position
 *  \param east easting position
 *  \param usedesc flag to scan category label
 *
 *  \return cell value at given position
 */
DCELL Rast_get_sample_cubic(int fd,
			    const struct Cell_head * window,
			    struct Categories * cats,
			    double north, double east, int usedesc)
{
    int i, j, row, col;
    double grid[4][4];
    DCELL *rows[4];
    double frow, fcol, trow, tcol;
    DCELL result;

    for (i = 0; i < 4; i++)
	rows[i] = Rast_allocate_d_buf();

    frow = Rast_northing_to_row(north, window);
    fcol = Rast_easting_to_col(east, window);

    /* convert northing and easting to row and col, resp */
    row = (int)floor(frow - 1.5);
    col = (int)floor(fcol - 1.5);

    trow = frow - row - 1.5;
    tcol = fcol - col - 1.5;

    if (row < 0 || row + 3 >= Rast_window_rows() ||
	col < 0 || col + 3 >= Rast_window_cols()) {
	Rast_set_d_null_value(&result, 1);
	goto done;
    }

    for (i = 0; i < 4; i++)
	Rast_get_d_row(fd, rows[i], row + i);

    for (i = 0; i < 4; i++)
	for (j = 0; j < 4; j++)
	    if (Rast_is_d_null_value(&rows[i][col + j])) {
		Rast_set_d_null_value(&result, 1);
		goto done;
	    }

    /*
     * now were ready to do cubic interpolation over
     * arow[col], arow[col+1], arow[col+2], arow[col+3],
     * brow[col], brow[col+1], brow[col+2], brow[col+3],
     * crow[col], crow[col+1], crow[col+2], crow[col+3],
     * drow[col], drow[col+1], drow[col+2], drow[col+3],
     */

    if (usedesc) {
	char *buf;

	for (i = 0; i < 4; i++) {
	    for (j = 0; j < 4; j++) {
		G_squeeze(buf =
			  Rast_get_c_cat((CELL *) & (rows[i][col + j]),
					 cats));
		grid[i][j] = scancatlabel(buf);
	    }
	}
    }
    else {
	for (i = 0; i < 4; i++)
	    for (j = 0; j < 4; j++)
		grid[i][j] = rows[i][col + j];
    }

    result = Rast_interp_bicubic(tcol, trow,
				 grid[0][0], grid[0][1], grid[0][2],
				 grid[0][3], grid[1][0], grid[1][1],
				 grid[1][2], grid[1][3], grid[2][0],
				 grid[2][1], grid[2][2], grid[2][3],
				 grid[3][0], grid[3][1], grid[3][2],
				 grid[3][3]);

  done:
    for (i = 0; i < 4; i++)
	G_free(rows[i]);

    return result;
}
Exemple #22
0
int avl_add(avl_tree * root, const generic_cell k, const long n)
{

    avl_node *p = NULL;
    avl_node *node_temp = NULL;
    avl_node *critical = NULL;

    int d = 0;
    int pos1 = 0, pos2 = 0;
    int rotation = 0;



    if ((root == NULL) || (*root == NULL)) {
	G_fatal_error("\navl.c: avl_add: param NULL");
	return AVL_ERR;
    }


    /* search position where insert the new node */
    node_temp = avl_individua(*root, k, &p, &d);

    if (node_temp != NULL) {
	node_temp->counter = node_temp->counter + n;
	return AVL_PRES;
    }

    node_temp = avl_make(k, n);
    if (node_temp == NULL) {
	G_fatal_error("\navl.c:  avl_add: create node error");
	return AVL_ERR;
    }


    /* link the new node */
    node_temp->father = p;

    if (d == -1) {
	p->left_child = node_temp;
    }
    else {
	if (d == 1) {
	    p->right_child = node_temp;
	}
	else {
	    G_free(node_temp);
	    G_fatal_error("avl.c: avl_add: new node position unknown");
	    return AVL_ERR;
	}
    }

    /* if it's necessary balance the tree */
    critical = critical_node(node_temp, &pos1, &pos2, NULL);
    if (critical == NULL)
	return AVL_ADD;
    rotation = (pos1 * 10) + pos2;

    switch (rotation) {
    case AVL_SS:
	avl_rotation_ll(critical);
	break;
    case AVL_SD:
	avl_rotation_lr(critical);
	break;
    case AVL_DS:
	avl_rotation_rl(critical);
	break;
    case AVL_DD:
	avl_rotation_rr(critical);
	break;
    default:
	G_fatal_error("avl, avl_add: balancing error\n");
	return AVL_ERR;
    }

    /* if after rotation the root is changed modufy the pointer to the root */
    while ((*root)->father != NULL)
	*root = (*root)->father;

    return AVL_ADD;
}
Exemple #23
0
int init_vars(int argc, char *argv[])
{
    int r, c;
    int ele_fd, wat_fd, fd = -1;
    int seg_rows, seg_cols, num_cseg_total, num_open_segs, num_open_array_segs;
    double memory_divisor, heap_mem, seg_factor, disk_space;

    /* int page_block, num_cseg; */
    int max_bytes;
    CELL *buf, alt_value, *alt_value_buf, block_value;
    char asp_value;
    DCELL wat_value;
    DCELL dvalue;
    WAT_ALT wa, *wabuf;
    ASP_FLAG af, af_nbr, *afbuf;
    char MASK_flag;
    void *elebuf, *ptr, *watbuf, *watptr;
    int ele_map_type, wat_map_type;
    size_t ele_size, wat_size;
    int ct_dir, r_nbr, c_nbr;

    G_gisinit(argv[0]);
    /* input */
    ele_flag = pit_flag = run_flag = ril_flag = 0;
    /* output */
    wat_flag = asp_flag = bas_flag = seg_flag = haf_flag = tci_flag = 0;
    bas_thres = 0;
    /* shed, unused */
    arm_flag = dis_flag = 0;
    /* RUSLE */
    ob_flag = st_flag = sl_flag = sg_flag = ls_flag = er_flag = 0;
    nxt_avail_pt = 0;
    /* dep_flag = 0; */
    max_length = d_zero = 0.0;
    d_one = 1.0;
    ril_value = -1.0;
    /* dep_slope = 0.0; */
    max_bytes = 0;
    sides = 8;
    mfd = 1;
    c_fac = 5;
    abs_acc = 0;
    ele_scale = 1;
    segs_mb = 300;
    /* scan options */
    for (r = 1; r < argc; r++) {
	if (sscanf(argv[r], "elevation=%s", ele_name) == 1)
	    ele_flag++;
	else if (sscanf(argv[r], "accumulation=%s", wat_name) == 1)
	    wat_flag++;
	else if (sscanf(argv[r], "tci=%s", tci_name) == 1)
	    tci_flag++;
	else if (sscanf(argv[r], "drainage=%s", asp_name) == 1)
	    asp_flag++;
	else if (sscanf(argv[r], "depression=%s", pit_name) == 1)
	    pit_flag++;
	else if (sscanf(argv[r], "threshold=%d", &bas_thres) == 1) ;
	else if (sscanf(argv[r], "max_slope_length=%lf", &max_length) == 1) ;
	else if (sscanf(argv[r], "basin=%s", bas_name) == 1)
	    bas_flag++;
	else if (sscanf(argv[r], "stream=%s", seg_name) == 1)
	    seg_flag++;
	else if (sscanf(argv[r], "half_basin=%s", haf_name) == 1)
	    haf_flag++;
	else if (sscanf(argv[r], "flow=%s", run_name) == 1)
	    run_flag++;
	else if (sscanf(argv[r], "ar=%s", arm_name) == 1)
	    arm_flag++;
	/* slope length
	else if (sscanf(argv[r], "slope_length=%s", sl_name) == 1)
	    sl_flag++; */
	else if (sscanf(argv[r], "slope_steepness=%s", sg_name) == 1)
	    sg_flag++;
	else if (sscanf(argv[r], "length_slope=%s", ls_name) == 1)
	    ls_flag++;
	else if (sscanf(argv[r], "blocking=%s", ob_name) == 1)
	    ob_flag++;
	else if (sscanf(argv[r], "memory=%lf", &segs_mb) == 1) ;
	else if (sscanf(argv[r], "disturbed_land=%s", ril_name) == 1) {
	    if (sscanf(ril_name, "%lf", &ril_value) == 0) {
		ril_value = -1.0;
		ril_flag++;
	    }
	}
	/* slope deposition
	else if (sscanf (argv[r], "sd=%[^\n]", dep_name) == 1) dep_flag++; */
	else if (sscanf(argv[r], "-%d", &sides) == 1) {
	    if (sides != 4)
		usage(argv[0]);
	}
	else if (sscanf(argv[r], "convergence=%d", &c_fac) == 1) ;
	else if (strcmp(argv[r], "-s") == 0)
	    mfd = 0;
	else if (strcmp(argv[r], "-a") == 0)
	    abs_acc = 1;
	else
	    usage(argv[0]);
    }
    /* check options */
    if (mfd == 1 && (c_fac < 1 || c_fac > 10)) {
	G_fatal_error("Convergence factor must be between 1 and 10.");
    }
    if ((ele_flag != 1)
	||
	((arm_flag == 1) &&
	 ((bas_thres <= 0) || ((haf_flag != 1) && (bas_flag != 1))))
	||
	((bas_thres <= 0) &&
	 ((bas_flag == 1) || (seg_flag == 1) || (haf_flag == 1) ||
	  (sl_flag == 1) || (sg_flag == 1) || (ls_flag == 1)))
	)
	usage(argv[0]);
    tot_parts = 4;
    if (sl_flag || sg_flag || ls_flag)
	er_flag = 1;
    /* do RUSLE */
    if (er_flag)
	tot_parts++;
    /* define basins */
    if (seg_flag || bas_flag || haf_flag)
	tot_parts++;

    G_message(_n("SECTION 1 beginning: Initiating Variables. %d section total.", 
        "SECTION 1 beginning: Initiating Variables. %d sections total.", 
        tot_parts),
	      tot_parts);

    this_mapset = G_mapset();
    /* for sd factor
       if (dep_flag)        {
       if (sscanf (dep_name, "%lf", &dep_slope) != 1)       {
       dep_flag = -1;
       }
       }
     */
    G_get_set_window(&window);
    nrows = Rast_window_rows();
    ncols = Rast_window_cols();
    if (max_length <= d_zero)
	max_length = 10 * nrows * window.ns_res + 10 * ncols * window.ew_res;
    if (window.ew_res < window.ns_res)
	half_res = .5 * window.ew_res;
    else
	half_res = .5 * window.ns_res;
    diag = sqrt(window.ew_res * window.ew_res +
		window.ns_res * window.ns_res);
    if (sides == 4)
	diag *= 0.5;

    /* Segment rows and cols: 64 */

    seg_rows = SROW;
    seg_cols = SCOL;
    /* seg_factor * <size in bytes> = segment size in KB */
    seg_factor = seg_rows * seg_rows / 1024.;

    if (segs_mb < 3.0) {
	segs_mb = 3;
	G_warning(_("Maximum memory to be used was smaller than 3 MB,"
	            " set to 3 MB."));
    }

    /* balance segment files */
    /* elevation + accumulation: * 2 */
    memory_divisor = sizeof(WAT_ALT) * 2;
    disk_space = sizeof(WAT_ALT);
    /* aspect and flags: * 4 */
    memory_divisor += sizeof(ASP_FLAG) * 4;
    disk_space += sizeof(ASP_FLAG);
    /* astar_points: / 16 */
    /* ideally only a few but large segments */
    memory_divisor += sizeof(POINT) / 16.;
    disk_space += sizeof(POINT);
    /* heap points: / 4 */
    memory_divisor += sizeof(HEAP_PNT) / 4.;
    disk_space += sizeof(HEAP_PNT);
    /* TCI: as is */
    if (tci_flag) {
	memory_divisor += sizeof(double);
	disk_space += sizeof(double);
    }
    /* RUSLE */
    if (er_flag) {
	/* r_h */
	memory_divisor += 4;
	disk_space += 4;
	/* s_l */
	memory_divisor += 8;
	disk_space += 8;
	/* s_g */
	if (sg_flag) {
	    memory_divisor += 8;
	    disk_space += 8;
	}
	/* l_s */
	if (ls_flag) {
	    memory_divisor += 8;
	    disk_space += 8;
	}
	/* ril */
	if (ril_flag) {
	    memory_divisor += 8;
	    disk_space += 8;
	}
    }
    
    /* KB -> MB */
    memory_divisor = memory_divisor * seg_factor / 1024.;
    disk_space = disk_space * seg_factor / 1024.;
    num_open_segs = segs_mb / memory_divisor;
    heap_mem = num_open_segs * seg_factor * sizeof(HEAP_PNT) / (4. * 1024.);

    G_debug(1, "segs MB: %.0f", segs_mb);
    G_debug(1, "region rows: %d", nrows);
    G_debug(1, "seg rows: %d", seg_rows);
    G_debug(1, "region cols: %d", ncols);
    G_debug(1, "seg cols: %d", seg_cols);

    num_cseg_total = nrows / SROW + 1;
    G_debug(1, "   row segments:\t%d", num_cseg_total);

    num_cseg_total = ncols / SCOL + 1;
    G_debug(1, "column segments:\t%d", num_cseg_total);

    num_cseg_total = (ncols / seg_cols + 1) * (nrows / seg_rows + 1);
    G_debug(1, " total segments:\t%d", num_cseg_total);
    G_debug(1, "  open segments:\t%d", num_open_segs);

    /* nonsense to have more segments open than exist */
    if (num_open_segs > num_cseg_total)
	num_open_segs = num_cseg_total;
    G_debug(1, "  open segments after adjusting:\t%d", num_open_segs);

    disk_space *= num_cseg_total;
    if (disk_space < 1024.0)
	G_verbose_message(_("Will need up to %.2f MB of disk space"), disk_space);
    else
	G_verbose_message(_("Will need up to %.2f GB (%.0f MB) of disk space"),
	           disk_space / 1024.0, disk_space);

    if (er_flag) {
	cseg_open(&r_h, seg_rows, seg_cols, num_open_segs);
	cseg_read_cell(&r_h, ele_name, "");
    }
    
    /* read elevation input and mark NULL/masked cells */

    /* scattered access: alt, watalt, bitflags, asp */
    seg_open(&watalt, nrows, ncols, seg_rows, seg_cols, num_open_segs * 2, sizeof(WAT_ALT));
    seg_open(&aspflag, nrows, ncols, seg_rows, seg_cols, num_open_segs * 4, sizeof(ASP_FLAG));

    if (tci_flag)
	dseg_open(&tci, seg_rows, seg_cols, num_open_segs);

    /* open elevation input */
    ele_fd = Rast_open_old(ele_name, "");

    ele_map_type = Rast_get_map_type(ele_fd);
    ele_size = Rast_cell_size(ele_map_type);
    elebuf = Rast_allocate_buf(ele_map_type);
    afbuf = G_malloc(ncols * sizeof(ASP_FLAG));

    if (ele_map_type == FCELL_TYPE || ele_map_type == DCELL_TYPE)
	ele_scale = 1000; 	/* should be enough to do the trick */

    /* initial flow accumulation */
    if (run_flag) {
	wat_fd = Rast_open_old(run_name, "");

	wat_map_type = Rast_get_map_type(ele_fd);
	wat_size = Rast_cell_size(ele_map_type);
	watbuf = Rast_allocate_buf(ele_map_type);
    }
    else {
	watbuf = watptr = NULL;
	wat_fd = wat_size = wat_map_type = -1;
    }
    wabuf = G_malloc(ncols * sizeof(WAT_ALT));
    alt_value_buf = Rast_allocate_buf(CELL_TYPE);

    /* read elevation input and mark NULL/masked cells */
    G_message("SECTION 1a: Mark masked and NULL cells");
    MASK_flag = 0;
    do_points = (GW_LARGE_INT) nrows * ncols;
    for (r = 0; r < nrows; r++) {
	G_percent(r, nrows, 1);
	Rast_get_row(ele_fd, elebuf, r, ele_map_type);
	ptr = elebuf;

	if (run_flag) {
	    Rast_get_row(wat_fd, watbuf, r, wat_map_type);
	    watptr = watbuf;
	}
	
	for (c = 0; c < ncols; c++) {

	    afbuf[c].flag = 0;
	    afbuf[c].asp = 0;

	    /* check for masked and NULL cells */
	    if (Rast_is_null_value(ptr, ele_map_type)) {
		FLAG_SET(afbuf[c].flag, NULLFLAG);
		FLAG_SET(afbuf[c].flag, INLISTFLAG);
		FLAG_SET(afbuf[c].flag, WORKEDFLAG);
		Rast_set_c_null_value(&alt_value, 1);
		/* flow accumulation */
		Rast_set_d_null_value(&wat_value, 1);
		do_points--;
	    }
	    else {
		if (ele_map_type == CELL_TYPE) {
		    alt_value = *((CELL *)ptr);
		}
		else if (ele_map_type == FCELL_TYPE) {
		    dvalue = *((FCELL *)ptr);
		    dvalue *= ele_scale;
		    alt_value = ele_round(dvalue);
		}
		else if (ele_map_type == DCELL_TYPE) {
		    dvalue = *((DCELL *)ptr);
		    dvalue *= ele_scale;
		    alt_value = ele_round(dvalue);
		}

		/* flow accumulation */
		if (run_flag) {
		    if (Rast_is_null_value(watptr, wat_map_type)) {
			wat_value = 0;    /* ok ? */
		    }
		    else {
			if (wat_map_type == CELL_TYPE) {
			    wat_value = *((CELL *)watptr);
			}
			else if (wat_map_type == FCELL_TYPE) {
			    wat_value = *((FCELL *)watptr);
			}
			else if (wat_map_type == DCELL_TYPE) {
			    wat_value = *((DCELL *)watptr);
			}
		    }
		}
		else {
		    wat_value = 1;
		}
	    }
	    wabuf[c].wat = wat_value;
	    wabuf[c].ele = alt_value;
	    alt_value_buf[c] = alt_value;
	    ptr = G_incr_void_ptr(ptr, ele_size);
	    if (run_flag) {
		watptr = G_incr_void_ptr(watptr, wat_size);
	    }
	}
	seg_put_row(&watalt, (char *) wabuf, r);
	seg_put_row(&aspflag, (char *)afbuf, r);
	
	if (er_flag) {
	    cseg_put_row(&r_h, alt_value_buf, r);
	}
    }
    G_percent(nrows, nrows, 1);    /* finish it */
    Rast_close(ele_fd);
    G_free(wabuf);
    G_free(afbuf);
    
    if (run_flag) {
	Rast_close(wat_fd);
	G_free(watbuf);
    }

    MASK_flag = (do_points < nrows * ncols);
    
    /* do RUSLE */
    if (er_flag) {
	if (ob_flag) {
	    fd = Rast_open_old(ob_name, "");
	    buf = Rast_allocate_c_buf();
	    for (r = 0; r < nrows; r++) {
		G_percent(r, nrows, 1);
		Rast_get_c_row(fd, buf, r);
		for (c = 0; c < ncols; c++) {
		    block_value = buf[c];
		    if (!Rast_is_c_null_value(&block_value) && block_value) {
			seg_get(&aspflag, (char *)&af, r, c);
			FLAG_SET(af.flag, RUSLEBLOCKFLAG);
			seg_put(&aspflag, (char *)&af, r, c);
		    }
		}
	    }
	    G_percent(nrows, nrows, 1);    /* finish it */
	    Rast_close(fd);
	    G_free(buf);
	}

	if (ril_flag) {
	    dseg_open(&ril, seg_rows, seg_cols, num_open_segs);
	    dseg_read_cell(&ril, ril_name, "");
	}
	
	/* dseg_open(&slp, SROW, SCOL, num_open_segs); */

	dseg_open(&s_l, seg_rows, seg_cols, num_open_segs);
	if (sg_flag)
	    dseg_open(&s_g, seg_rows, seg_cols, num_open_segs);
	if (ls_flag)
	    dseg_open(&l_s, seg_rows, seg_cols, num_open_segs);
    }

    G_debug(1, "open segments for A* points");
    /* columns per segment */
    seg_cols = seg_rows * seg_rows;
    num_cseg_total = do_points / seg_cols;
    if (do_points % seg_cols > 0)
	num_cseg_total++;
    /* no need to have more segments open than exist */
    num_open_array_segs = num_open_segs / 16.;
    if (num_open_array_segs > num_cseg_total)
	num_open_array_segs = num_cseg_total;
    if (num_open_array_segs < 1)
	num_open_array_segs = 1;
    
    seg_open(&astar_pts, 1, do_points, 1, seg_cols, num_open_array_segs,
	     sizeof(POINT));

    /* one-based d-ary search_heap with astar_pts */
    G_debug(1, "open segments for A* search heap");
    G_debug(1, "heap memory %.2f MB", heap_mem);
    /* columns per segment */
    /* larger is faster */
    seg_cols = seg_rows * seg_rows;
    num_cseg_total = do_points / seg_cols;
    if (do_points % seg_cols > 0)
	num_cseg_total++;
    /* no need to have more segments open than exist */
    num_open_array_segs = (1 << 20) * heap_mem / (seg_cols * sizeof(HEAP_PNT));
    if (num_open_array_segs > num_cseg_total)
	num_open_array_segs = num_cseg_total;
    if (num_open_array_segs < 2)
	num_open_array_segs = 2;

    G_debug(1, "A* search heap open segments %d, total %d",
            num_open_array_segs, num_cseg_total);
    /* the search heap will not hold more than 5% of all points at any given time ? */
    /* chances are good that the heap will fit into one large segment */
    seg_open(&search_heap, 1, do_points + 1, 1, seg_cols,
	     num_open_array_segs, sizeof(HEAP_PNT));

    G_message(_("SECTION 1b: Determining Offmap Flow."));

    /* heap is empty */
    heap_size = 0;

    if (pit_flag) {
	buf = Rast_allocate_c_buf();
	fd = Rast_open_old(pit_name, "");
    }
    else
	buf = NULL;
    first_astar = first_cum = -1;

    for (r = 0; r < nrows; r++) {
	G_percent(r, nrows, 1);
	if (pit_flag)
	    Rast_get_c_row(fd, buf, r);
	for (c = 0; c < ncols; c++) {
	    seg_get(&aspflag, (char *)&af, r, c);
	    if (!FLAG_GET(af.flag, NULLFLAG)) {
		if (er_flag)
		    dseg_put(&s_l, &half_res, r, c);
		asp_value = af.asp;
		if (r == 0 || c == 0 || r == nrows - 1 ||
		    c == ncols - 1) {
		    /* dseg_get(&wat, &wat_value, r, c); */
		    seg_get(&watalt, (char *)&wa, r, c);
		    wat_value = wa.wat;
		    if (wat_value > 0) {
			wat_value = -wat_value;
			/* dseg_put(&wat, &wat_value, r, c); */
			wa.wat = wat_value;
			seg_put(&watalt, (char *)&wa, r, c);
		    }
		    if (r == 0)
			asp_value = -2;
		    else if (c == 0)
			asp_value = -4;
		    else if (r == nrows - 1)
			asp_value = -6;
		    else if (c == ncols - 1)
			asp_value = -8;
		    /* cseg_get(&alt, &alt_value, r, c); */
		    alt_value = wa.ele;
		    add_pt(r, c, alt_value);
		    FLAG_SET(af.flag, INLISTFLAG);
		    FLAG_SET(af.flag, EDGEFLAG);
		    af.asp = asp_value;
		    seg_put(&aspflag, (char *)&af, r, c);
		}
		else {
		    seg_get(&watalt, (char *)&wa, r, c);
		    for (ct_dir = 0; ct_dir < sides; ct_dir++) {
			/* get r, c (r_nbr, c_nbr) for neighbours */
			r_nbr = r + nextdr[ct_dir];
			c_nbr = c + nextdc[ct_dir];

			seg_get(&aspflag, (char *)&af_nbr, r_nbr, c_nbr);
			if (FLAG_GET(af_nbr.flag, NULLFLAG)) {
			    af.asp = -1 * drain[r - r_nbr + 1][c - c_nbr + 1];
			    add_pt(r, c, wa.ele);
			    FLAG_SET(af.flag, INLISTFLAG);
			    FLAG_SET(af.flag, EDGEFLAG);
			    seg_put(&aspflag, (char *)&af, r, c);
			    wat_value = wa.wat;
			    if (wat_value > 0) {
				wa.wat = -wat_value;
				seg_put(&watalt, (char *)&wa, r, c);
			    }
			    break;
			}
		    }
		}
		/* real depression ? */
		if (pit_flag && asp_value == 0) {
		    if (!Rast_is_c_null_value(&buf[c]) && buf[c] != 0) {

			seg_get(&watalt, (char *)&wa, r, c);
			add_pt(r, c, wa.ele);

			FLAG_SET(af.flag, INLISTFLAG);
			FLAG_SET(af.flag, EDGEFLAG);
			seg_put(&aspflag, (char *)&af, r, c);
			wat_value = wa.wat;
			if (wat_value > 0) {
			    wa.wat = -wat_value;
			    seg_put(&watalt, (char *)&wa, r, c);
			}
		    }
		}

	    }  /* end non-NULL cell */
	}  /* end column */
    }
    G_percent(r, nrows, 1);	/* finish it */

    return 0;
}
Exemple #24
0
/* ************************************************************************* */
int main(int argc, char *argv[])
{
    struct GModule *module = NULL;
    N_solute_transport_data2d *data = NULL;
    N_geom_data *geom = NULL;
    N_les *les = NULL;
    N_les_callback_2d *call = NULL;
    struct Cell_head region;
    double error, sor;
    char *solver;
    int x, y, stat, i, maxit = 1;
    double loops = 1;
    N_array_2d *xcomp = NULL;
    N_array_2d *ycomp = NULL;
    N_array_2d *hc_x = NULL;
    N_array_2d *hc_y = NULL;
    N_array_2d *phead = NULL;

    double time_step, cfl, length, time_loops, time_sum;

    /* Initialize GRASS */
    G_gisinit(argv[0]);

    module = G_define_module();
    G_add_keyword(_("raster"));
    G_add_keyword(_("hydrology"));
    G_add_keyword(_("solute transport"));
    module->description =
	_("Numerical calculation program for transient, confined and unconfined "
            "solute transport in two dimensions");

    /* Get parameters from user */
    set_params();

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

    /* Make sure that the current projection is not lat/long */
    if ((G_projection() == PROJECTION_LL))
	G_fatal_error(_("Lat/Long location is not supported by %s. Please reproject map first."),
		      G_program_name());
    
    /*Set the maximum iterations */
    sscanf(param.maxit->answer, "%i", &(maxit));
    /*Set the calculation error break criteria */
    sscanf(param.error->answer, "%lf", &(error));
    sscanf(param.sor->answer, "%lf", &(sor));
    /*number of loops*/
    sscanf(param.loops->answer, "%lf", &(loops));    
    /*Set the solver */
    solver = param.solver->answer;

    if (strcmp(solver, G_MATH_SOLVER_DIRECT_LU) == 0 && !param.full_les->answer)
	G_fatal_error(_("The direct LU solver do not work with sparse matrices"));
    if (strcmp(solver, G_MATH_SOLVER_DIRECT_GAUSS) == 0 && !param.full_les->answer)
	G_fatal_error(_("The direct Gauss solver do not work with sparse matrices"));


    /*get the current region */
    G_get_set_window(&region);

    /*allocate the geometry structure for geometry and area calculation */
    geom = N_init_geom_data_2d(&region, geom);

    /*Set the function callback to the groundwater flow function */
    call = N_alloc_les_callback_2d();
    N_set_les_callback_2d_func(call, (*N_callback_solute_transport_2d));	/*solute_transport 2d */

    /*Allocate the groundwater flow data structure */
    data = N_alloc_solute_transport_data2d(geom->cols, geom->rows);

    /*Set the stabilizing scheme*/
    if (strncmp("full", param.stab->answer, 4) == 0) {
        data->stab = N_UPWIND_FULL;
    }
    if (strncmp("exp", param.stab->answer, 3) == 0) {
        data->stab = N_UPWIND_EXP;
    }
 
    /*the dispersivity lengths*/
    sscanf(param.al->answer, "%lf", &(data->al));
    sscanf(param.at->answer, "%lf", &(data->at));

    /*Set the calculation time */
    sscanf(param.dt->answer, "%lf", &(data->dt));

    /*read all input maps into the memory and take care of the
     * null values.*/
    N_read_rast_to_array_2d(param.c->answer, data->c);
    N_convert_array_2d_null_to_zero(data->c);
    N_read_rast_to_array_2d(param.c->answer, data->c_start);
    N_convert_array_2d_null_to_zero(data->c_start);
    N_read_rast_to_array_2d(param.status->answer, data->status);
    N_convert_array_2d_null_to_zero(data->status);
    N_read_rast_to_array_2d(param.diff_x->answer, data->diff_x);
    N_convert_array_2d_null_to_zero(data->diff_x);
    N_read_rast_to_array_2d(param.diff_y->answer, data->diff_y);
    N_convert_array_2d_null_to_zero(data->diff_y);
    N_read_rast_to_array_2d(param.q->answer, data->q);
    N_convert_array_2d_null_to_zero(data->q);
    N_read_rast_to_array_2d(param.nf->answer, data->nf);
    N_convert_array_2d_null_to_zero(data->nf);
    N_read_rast_to_array_2d(param.cs->answer, data->cs);
    N_convert_array_2d_null_to_zero(data->cs);
    N_read_rast_to_array_2d(param.top->answer, data->top);
    N_convert_array_2d_null_to_zero(data->top);
    N_read_rast_to_array_2d(param.bottom->answer, data->bottom);
    N_convert_array_2d_null_to_zero(data->bottom);
    N_read_rast_to_array_2d(param.r->answer, data->R);
    N_convert_array_2d_null_to_zero(data->R);

    if(param.cin->answer) {
      N_read_rast_to_array_2d(param.cin->answer, data->cin);
      N_convert_array_2d_null_to_zero(data->cin);
    }

    /*initiate the values for velocity calculation*/
    hc_x = N_alloc_array_2d(geom->cols, geom->rows, 1, DCELL_TYPE);
    hc_x = N_read_rast_to_array_2d(param.hc_x->answer, hc_x);
    N_convert_array_2d_null_to_zero(hc_x);
    hc_y = N_alloc_array_2d(geom->cols, geom->rows, 1, DCELL_TYPE);
    hc_y = N_read_rast_to_array_2d(param.hc_y->answer, hc_y);
    N_convert_array_2d_null_to_zero(hc_y);
    phead = N_alloc_array_2d(geom->cols, geom->rows, 1, DCELL_TYPE);
    phead = N_read_rast_to_array_2d(param.phead->answer, phead);
    N_convert_array_2d_null_to_zero(phead);

    /* Set the inactive values to zero, to assure a no flow boundary */
    for (y = 0; y < geom->rows; y++) {
	for (x = 0; x < geom->cols; x++) {
	    stat = (int)N_get_array_2d_d_value(data->status, x, y);
	    if (stat == N_CELL_INACTIVE) {	/*only inactive cells */
		N_put_array_2d_d_value(data->diff_x, x, y, 0);
		N_put_array_2d_d_value(data->diff_y, x, y, 0);
		N_put_array_2d_d_value(data->cs, x, y, 0);
		N_put_array_2d_d_value(data->q, x, y, 0);
	    }
	}
    }

    /*compute the velocities */
    N_math_array_2d(hc_x, data->nf, hc_x, N_ARRAY_DIV);
    N_math_array_2d(hc_y, data->nf, hc_y, N_ARRAY_DIV);
    N_compute_gradient_field_2d(phead, hc_x, hc_y, geom, data->grad);

    /*Now compute the dispersivity tensor*/
    N_calc_solute_transport_disptensor_2d(data);

    /***************************************/
    /*the Courant-Friedrichs-Lewy criteria */
    /*Compute the correct time step */
    if (geom->dx > geom->dy)
	length = geom->dx;
    else
	length = geom->dy;

    if (fabs(data->grad->max) > fabs(data->grad->min)) {
	cfl = (double)data->dt * fabs(data->grad->max) / length;
	time_step = 1*length / fabs(data->grad->max);
    }
    else {
	cfl = (double)data->dt * fabs(data->grad->min) / length;
	time_step = 1*length / fabs(data->grad->min);
    }

    G_message(_("The Courant-Friedrichs-Lewy criteria is %g it should be within [0:1]"), cfl);
    G_message(_("The largest stable time step is %g"), time_step);

    /*Set the number of inner loops and the time step*/
    if (data->dt > time_step && param.cfl->answer) {
	/*safe the user time step */
	time_sum = data->dt;
	time_loops = data->dt / time_step;
	time_loops = floor(time_loops) + 1;
	data->dt = data->dt / time_loops;
	G_message(_("Number of inner loops is %g"), time_loops);
	G_message(_("Time step for each loop %g"), data->dt);
    }
    else {
        if(data->dt > time_step)
	    G_warning(_("The time step is to large: %gs. The largest time step should be of size %gs."), data->dt, time_step);

	time_loops = loops;
	data->dt = data->dt / loops;
    }

    N_free_array_2d(phead);
    N_free_array_2d(hc_x);
    N_free_array_2d(hc_y);

     /*Compute for each time step*/
     for (i = 0; i < time_loops; i++) {
	 G_message(_("Time step %i with time sum %g"), i + 1, (i + 1)*data->dt);

	/*assemble the linear equation system  and solve it */
	les = create_solve_les(geom, data, call, solver, maxit, error, sor);

	/* copy the result into the c array for output */
	copy_result(data->status, data->c_start, les->x, &region, data->c, 1);
	N_convert_array_2d_null_to_zero(data->c_start);

        if (les)
	    N_free_les(les);

	/*Set the start array*/
	N_copy_array_2d(data->c, data->c_start);
	/*Set the transmission boundary*/
	N_calc_solute_transport_transmission_2d(data);

    }

    /*write the result to the output file */
    N_write_array_2d_to_rast(data->c, param.output->answer);

    /*Compute the the velocity field if required and write the result into three rast maps */
    if (param.vector_x->answer || param.vector_y->answer) {
	xcomp = N_alloc_array_2d(geom->cols, geom->rows, 1, DCELL_TYPE);
	ycomp = N_alloc_array_2d(geom->cols, geom->rows, 1, DCELL_TYPE);

	N_compute_gradient_field_components_2d(data->grad, xcomp, ycomp);

        if (param.vector_x->answer)
            N_write_array_2d_to_rast(xcomp, param.vector_x->answer);
        if (param.vector_y->answer)
            N_write_array_2d_to_rast(ycomp, param.vector_y->answer);

	if (xcomp)
	    N_free_array_2d(xcomp);
	if (ycomp)
	    N_free_array_2d(ycomp);
    }


    if (data)
	N_free_solute_transport_data2d(data);
    if (geom)
	N_free_geom_data(geom);
    if (call)
	G_free(call);

    return (EXIT_SUCCESS);
}
/* douglas-peucker algorithm which simplifies a line to a line with
 * at most reduction% of points.
 * returns the number of points in the output line. It is approx 
 * reduction/100 * Points->n_points.
 */
int douglas_peucker_reduction(struct line_pnts *Points, double thresh,
			      double reduction, int with_z)
{

    int i;
    int n = Points->n_points;

    /* the maximum number of points  which may be 
     * included in the output */
    int nexp = n * (reduction / (double)100.0);

    /* line too short */
    if (n < 3)
	return n;

    /* indicates which point were selected by the algorithm */
    int *sel;
    sel = G_calloc(sizeof(int), n);
    if (sel == NULL) {
	G_fatal_error(_("Out of memory"));
	return n;
    }

    /* array used for storing the indices of line segments+furthest point */
    int *index;
    index = G_malloc(sizeof(int) * 3 * n);
    if (index == NULL) {
	G_fatal_error(_("Out of memory"));
	G_free(sel);
	return n;
    }

    int indices;

    indices = 0;

    /* preserve first and last point */
    sel[0] = sel[n - 1] = 1;
    nexp -= 2;

    thresh *= thresh;

    double d;
    int mid = get_furthest(Points, 0, n - 1, with_z, &d);
    int em;

    /* priority queue of line segments,
     * key is the distance of the furthest point */
    binary_heap pq;

    if (!binary_heap_init(n, &pq)) {
	G_fatal_error(_("Out of memory"));
	G_free(sel);
	G_free(index);
	return n;
    }


    if (d > thresh) {
	index[0] = 0;
	index[1] = n - 1;
	index[2] = mid;
	binary_heap_push(d, 0, &pq);
	indices = 3;
    }

    /* while we can add new points and queue is non-empty */
    while (nexp > 0) {
	/* empty heap */
	if (!binary_heap_extract_max(&pq, &em))
	    break;
	int left = index[em];
	int right = index[em + 1];
	int furt = index[em + 2];

	/*mark the furthest point */
	sel[furt] = 1;
	nexp--;

	/* consider left and right segment */
	mid = get_furthest(Points, left, furt, with_z, &d);
	if (d > thresh) {
	    binary_heap_push(d, indices, &pq);
	    index[indices++] = left;
	    index[indices++] = furt;
	    index[indices++] = mid;
	}

	mid = get_furthest(Points, furt, right, with_z, &d);
	if (d > thresh) {
	    binary_heap_push(d, indices, &pq);
	    index[indices++] = furt;
	    index[indices++] = right;
	    index[indices++] = mid;
	}

    }

    /* copy selected points */
    int selected = 0;

    for (i = 0; i < n; i++) {
	if (sel[i]) {
	    Points->x[selected] = Points->x[i];
	    Points->y[selected] = Points->y[i];
	    Points->z[selected] = Points->z[i];
	    selected++;
	}
    }

    G_free(sel);
    G_free(index);
    binary_heap_free(&pq);
    Points->n_points = selected;
    return Points->n_points;
}
Exemple #26
0
void cell_clip(DCELL ** buf, DCELL ** null_buf, int row0, int col0, int nrows,
	       int ncols, int index, float radius)
{
    CELL *tmp, *tmp1;
    FCELL *ftmp;
    DCELL *dtmp;
    char *tmpname, *nulltmp;
    int fr;
    register int i, j;
    double center_row = 0.0, center_col = 0.0;
    double dist;
    RASTER_MAP_TYPE data_type;

    /*
       Variables:
       IN:
       buf        = pointer to array containing only the pixels inside the area 
       that was specified to be clipped, so a smaller array than the
       original raster map
       null_buf   = pointer to array containing the corresponding null values
       row0       = starting row for the area to be clipped out of the raster map
       col0       = starting col for the area to be clipped out of the raster map
       nrows      = total number of rows in the area to be clipped
       ncols      = total number of cols in the area to be clipped
       index      = number of the region to be clipped, if there's a region map
       INTERNAL:
       tmp        = pointer to a temporary array to store a row of the raster map
       tmp1       = pointer to a temporary array to store a row of the region map
       fr         = return value from attempting to open the region map
       i, j       = indices to rows and cols of the arrays
     */

    data_type = G_raster_map_type(choice->fn, G_mapset());

    /* if sampling by region was chosen, check
       for the region map and make sure it is
       an integer (CELL_TYPE) map */

    if (choice->wrum == 'r') {
	if (0 > (fr = G_open_cell_old(choice->reg, G_mapset()))) {
	    fprintf(stderr, "\n");
	    fprintf(stderr,
		    "   *******************************************************\n");
	    fprintf(stderr,
		    "    You specified sam=r to request sampling by region,    \n");
	    fprintf(stderr,
		    "    but the region map specified with the 'reg=' parameter\n");
	    fprintf(stderr,
		    "    cannot be found in the current mapset.                \n");
	    fprintf(stderr,
		    "   *******************************************************\n");
	    exit(1);
	}
	if (G_raster_map_type(choice->reg, G_mapset()) > 0) {
	    fprintf(stderr, "\n");
	    fprintf(stderr,
		    "   *******************************************************\n");
	    fprintf(stderr,
		    "    You specified sam=r to request sampling by region,    \n");
	    fprintf(stderr,
		    "    but the region map specified with the 'reg=' parameter\n");
	    fprintf(stderr,
		    "    must be an integer map, and it is floating point or   \n");
	    fprintf(stderr,
		    "    double instead.                                       \n");
	    fprintf(stderr,
		    "   *******************************************************\n");
	    exit(1);
	}
	tmp1 = G_allocate_raster_buf(CELL_TYPE);
	G_zero_raster_buf(tmp1, CELL_TYPE);
	fprintf(stderr, "Analyzing region number %d...\n", index);
    }

    /* allocate memory to store a row of the
       raster map, depending on the type of
       input raster map; keep track of the
       name of the buffer for each raster type */

    switch (data_type) {
    case CELL_TYPE:
	tmp = G_allocate_raster_buf(CELL_TYPE);
	tmpname = "tmp";
	break;
    case FCELL_TYPE:
	ftmp = G_allocate_raster_buf(FCELL_TYPE);
	tmpname = "ftmp";
	break;
    case DCELL_TYPE:
	dtmp = G_allocate_raster_buf(DCELL_TYPE);
	tmpname = "dtmp";
	break;
    }

    /* allocate memory to store a row of the
       null values corresponding to the raster
       map */

    nulltmp = G_allocate_null_buf();

    /* if circles are used for sampling, then
       calculate the center of the area to be
       clipped, in pixels */

    if ((int)radius) {
	center_row = ((double)row0 + ((double)nrows - 1) / 2);
	center_col = ((double)col0 + ((double)ncols - 1) / 2);
    }

    /* for each row of the area to be clipped */

    for (i = row0; i < row0 + nrows; i++) {

	/* if region, read in the corresponding
	   map row in the region file */

	if (choice->wrum == 'r')
	    G_get_raster_row_nomask(fr, tmp1, i, CELL_TYPE);

	/* initialize each element of the
	   row buffer to 0; this row buffer
	   will hold one row of the clipped
	   raster map.  Then read row i of the
	   map and the corresponding null values
	   into tmp and nulltmp buffers */

	switch (data_type) {
	case CELL_TYPE:
	    G_zero_raster_buf(tmp, data_type);
	    G_get_raster_row(finput, tmp, i, CELL_TYPE);
	    break;
	case FCELL_TYPE:
	    G_zero_raster_buf(ftmp, data_type);
	    G_get_raster_row(finput, ftmp, i, FCELL_TYPE);
	    break;
	case DCELL_TYPE:
	    G_zero_raster_buf(dtmp, data_type);
	    G_get_raster_row(finput, dtmp, i, DCELL_TYPE);
	    break;
	}

	G_get_null_value_row(finput, nulltmp, i);

	/* for all the columns one by one */

	for (j = col0; j < col0 + ncols; j++) {

	    /* if circles are used for sampling */

	    if ((int)radius) {
		dist = sqrt(((double)i - center_row) *
			    ((double)i - center_row) +
			    ((double)j - center_col) *
			    ((double)j - center_col));

		/* copy the contents of tmp into the
		   appropriate cell in buf */

		if (dist < radius) {
		    switch (data_type) {
		    case CELL_TYPE:
			*(*(buf + i + 1 - row0) + j + 1 - col0) = *(tmp + j);
			break;
		    case FCELL_TYPE:
			*(*(buf + i + 1 - row0) + j + 1 - col0) = *(ftmp + j);
			break;
		    case DCELL_TYPE:
			*(*(buf + i + 1 - row0) + j + 1 - col0) = *(dtmp + j);
			break;
		    }
		    *(*(null_buf + i + 1 - row0) + j + 1 - col0) =
			*(nulltmp + j);
		}
	    }

	    /* if circles are not used and
	       if the choice is not "by region" or
	       if this column is in region "index" */

	    else if (choice->wrum != 'r' || *(tmp1 + j) == index) {

		/* copy the contents of the correct tmp
		   into the appropriate cell in the buf
		   and the corresponding null values into
		   the appropriate cell in null_buf */

		switch (data_type) {
		case CELL_TYPE:
		    *(*(buf + i + 1 - row0) + j + 1 - col0) = *(tmp + j);
		    break;
		case FCELL_TYPE:
		    *(*(buf + i + 1 - row0) + j + 1 - col0) = *(ftmp + j);
		    break;
		case DCELL_TYPE:
		    *(*(buf + i + 1 - row0) + j + 1 - col0) = *(dtmp + j);
		    break;
		}
		*(*(null_buf + i + 1 - row0) + j + 1 - col0) = *(nulltmp + j);
	    }
	}
    }

    switch (data_type) {
    case CELL_TYPE:
	G_free(tmp);
	break;
    case FCELL_TYPE:
	G_free(ftmp);
	break;
    case DCELL_TYPE:
	G_free(dtmp);
	break;
    }
    if (choice->wrum == 'r') {
	G_free(tmp1);
	G_close_cell(fr);
    }
    G_free(nulltmp);
    return;
}
Exemple #27
0
/*!
   \brief Get number of articulation points in the graph

   \param graph input graph
   \param[out] articulation_list list of articulation points

   \return number of points
   \return -1 on error
 */
int NetA_articulation_points(dglGraph_s * graph,
                             struct ilist *articulation_list)
{
    int nnodes;
    int points = 0;

    dglEdgesetTraverser_s *current;	/*edge to be processed when the node is visited */
    int *tin, *min_tin;		/*time in, and smallest tin over all successors. 0 if not yet visited */
    dglInt32_t **parent;	/*parents of the nodes */
    dglInt32_t **stack;		/*stack of nodes */
    dglInt32_t **current_edge;	/*current edge for each node */
    int *mark;			/*marked articulation points */
    dglNodeTraverser_s nt;
    dglInt32_t *current_node;
    int stack_size;
    int i, time;

    nnodes = dglGet_NodeCount(graph);
    current =
        (dglEdgesetTraverser_s *) G_calloc(nnodes + 1,
                                           sizeof(dglEdgesetTraverser_s));
    tin = (int *)G_calloc(nnodes + 1, sizeof(int));
    min_tin = (int *)G_calloc(nnodes + 1, sizeof(int));
    parent = (dglInt32_t **) G_calloc(nnodes + 1, sizeof(dglInt32_t *));
    stack = (dglInt32_t **) G_calloc(nnodes + 1, sizeof(dglInt32_t *));
    current_edge = (dglInt32_t **) G_calloc(nnodes + 1, sizeof(dglInt32_t *));
    mark = (int *)G_calloc(nnodes + 1, sizeof(int));
    if (!tin || !min_tin || !parent || !stack || !current || !mark) {
        G_fatal_error(_("Out of memory"));
        return -1;
    }

    for (i = 1; i <= nnodes; i++) {
        dglEdgeset_T_Initialize(&current[i], graph,
                                dglNodeGet_OutEdgeset(graph,
                                        dglGetNode(graph, i)));
        current_edge[i] = dglEdgeset_T_First(&current[i]);
        tin[i] = mark[i] = 0;
    }

    dglNode_T_Initialize(&nt, graph);

    time = 0;
    for (current_node = dglNode_T_First(&nt); current_node;
            current_node = dglNode_T_Next(&nt)) {
        dglInt32_t current_id = dglNodeGet_Id(graph, current_node);

        if (tin[current_id] == 0) {
            int children = 0;	/*number of subtrees rooted at the root/current_node */

            stack[0] = current_node;
            stack_size = 1;
            parent[current_id] = NULL;
            while (stack_size) {
                dglInt32_t *node = stack[stack_size - 1];
                dglInt32_t node_id = dglNodeGet_Id(graph, node);

                if (tin[node_id] == 0)	/*vertex visited for the first time */
                    min_tin[node_id] = tin[node_id] = ++time;
                else {		/*return from the recursion */
                    dglInt32_t to = dglNodeGet_Id(graph,
                                                  dglEdgeGet_Tail(graph,
                                                          current_edge
                                                          [node_id]));
                    if (min_tin[to] >= tin[node_id])	/*no path from the subtree above the current node */
                        mark[node_id] = 1;	/*so the current node must be an articulation point */

                    if (min_tin[to] < min_tin[node_id])
                        min_tin[node_id] = min_tin[to];
                    current_edge[node_id] = dglEdgeset_T_Next(&current[node_id]);	/*proceed to the next edge */
                }
                /*try next edges */
                for (; current_edge[node_id]; current_edge[node_id] = dglEdgeset_T_Next(&current[node_id])) {
                    dglInt32_t *to =
                        dglEdgeGet_Tail(graph, current_edge[node_id]);
                    if (to == parent[node_id])
                        continue;	/*skip parent */
                    int to_id = dglNodeGet_Id(graph, to);

                    if (tin[to_id]) {	/*back edge, cannot be a bridge/articualtion point */
                        if (tin[to_id] < min_tin[node_id])
                            min_tin[node_id] = tin[to_id];
                    }
                    else {	/*forward edge */
                        if (node_id == current_id)
                            children++;	/*if root, increase number of children */
                        parent[to_id] = node;
                        stack[stack_size++] = to;
                        break;
                    }
                }
                if (!current_edge[node_id])
                    stack_size--;	/*current node completely processed */
            }
            if (children > 1)
                mark[current_id] = 1;	/*if the root has more than 1 subtrees rooted at it, then it is an
					 * articulation point */
        }
    }

    for (i = 1; i <= nnodes; i++)
        if (mark[i]) {
            points++;
            Vect_list_append(articulation_list, i);
        }

    dglNode_T_Release(&nt);
    for (i = 1; i <= nnodes; i++)
        dglEdgeset_T_Release(&current[i]);

    G_free(current);
    G_free(tin);
    G_free(min_tin);
    G_free(parent);
    G_free(stack);
    G_free(current_edge);
    return points;
}
Exemple #28
0
void cell_clip_drv(int col0, int row0, int ncols, int nrows, double **value,
		   int index, int cntwhole, float radius)
{

    register int i, j;
    int cnt = 0, p;
    double *rich, *richtmp;
    char *name, *mapset;
    DCELL **buf;
    DCELL **null_buf;
    RASTER_MAP_TYPE data_type;

    /*
       col0 = starting column for area to be clipped
       row0 = starting row for area to be clipped
       ncols = number of columns in area to be clipped
       nrows = number of rows in area to be clipped
       value =
       index = number of the region to be clipped, if there's a region map
       buf = pointer to array containing the clipped area, a smaller area
       than the original raster map to be read from finput                            printf("h2\n");

       pat = pointer to array containing the map of patch numbers
       cor = pointer to array containing the map of interior area
     */

    name = choice->fn;
    mapset = G_mapset();
    data_type = G_raster_map_type(name, mapset);

    /* dynamically allocate storage for the
       buffer that will hold the contents of
       the window */

    buf = (DCELL **) G_calloc(nrows + 3, sizeof(DCELL *));
    for (i = 0; i < nrows + 3; i++) {
	buf[i] = (DCELL *) G_calloc(ncols + 3, sizeof(DCELL));
    }

    /* dynamically allocate storage for the
       buffer that will hold the null values for
       the clipped area */

    null_buf = (DCELL **) G_calloc(nrows + 3, sizeof(DCELL *));
    for (i = 0; i < nrows + 3; i++)
	null_buf[i] = (DCELL *) G_calloc(ncols + 3, sizeof(DCELL));

    /* call the cell_clip routine */

    cell_clip(buf, null_buf, row0, col0, nrows, ncols, index, radius);

    /* dynamically allocate memory for
       the richness array */

    richtmp = (double *)G_calloc(MAX, sizeof(double));

    /* go through the sampling area
       pixel by pixel */

    for (i = 1; i < nrows + 1; i++) {
	for (j = 1; j < ncols + 1; j++) {

	    /* if buf[i][j] is not a null value,
	       call get_rich to tally up the
	       number of different attributes
	       in the sampling area and fill
	       the richness array with those
	       attributes */

	    if ((buf[i][j] || buf[i][j] == 0.0) && null_buf[i][j] == 0.0) {
		/*printf("buf[%d][%d] = %f\n",i,j,buf[i][j]); */

		get_rich(buf[i][j], richtmp, &cnt);
	    }
	}
    }

    if (cnt) {

	rich = (double *)G_calloc(cnt, sizeof(double));
	for (i = 0; i < cnt; i++) {
	    rich[i] = richtmp[i];
	}
	G_free(richtmp);

	/* call ANSI C runtime library
	   function qsort to sort the 
	   richness array into ascending
	   order */

	qsort(rich, cnt, sizeof(double), compar);

	/* moving window */

	if (choice->wrum == 'm') {
	    if (is_not_empty_buffer(buf, null_buf, nrows + 1, ncols + 1)) {
		if (center_is_not_null(buf, null_buf, nrows, ncols))
		    mv_texture(nrows, ncols, buf, null_buf, value, index,
			       rich, cnt, cntwhole);
		else {
		    for (p = 0; p < 17; p++)
			*(*(value + index) + p) = -BIG;
		}
	    }
	}

	/* whole map, units, or regions */

	else if (is_not_empty_buffer(buf, null_buf, nrows + 1, ncols + 1))
	    df_texture(nrows, ncols, buf, null_buf, rich, cnt, cntwhole);

	for (i = 0; i < nrows + 3; i++)
	    G_free(*(buf + i));
	G_free(buf);

	/* free memory allocated for null buffer */

	for (i = 0; i < nrows + 3; i++)
	    G_free(null_buf[i]);
	G_free(null_buf);

	G_free(rich);
    }
    else
	G_free(richtmp);

    return;
}
Exemple #29
0
static int write_smooth_bnd(struct COOR *line_begin, struct COOR *line_end,	/* start and end point of line */
			    int n	/* number of points to write */
    )
{
    static struct line_pnts *points = NULL;
    double x, y;
    double dx, dy;
    int idx, idy;
    struct COOR *p, *last;
    int i, total;

    if (!points)
	points = Vect_new_line_struct();
    Vect_reset_line(points);

    n++;			/* %% 6.4.88 */

    p = line_begin;
    /* allocate the arrays and get the first point */

    y = cell_head.north - (double)p->row * cell_head.ns_res;
    x = cell_head.west + (double)p->col * cell_head.ew_res;
    Vect_append_point(points, x, y, 0.0);

    /* generate the list of smoothed points, may be duplicate points */
    total = 1;
    for (i = 1; i < n; i++) {
	if (i < 10)
	    G_debug(3, " row: %d col: %d\n", p->row, p->col);

	last = p;
	if ((p = move(p)) == NULPTR) {	/* this should NEVER happen */
	    G_debug(3, "write_line:  line terminated unexpectedly\n");
	    G_debug(3, "  previous (%d) point %p (%d,%d,%d) %p %p\n",
		    direction, last, last->row, last->col, last->node,
		    last->fptr, last->bptr);

	    exit(EXIT_FAILURE);
	}

	idy = (p->row - last->row);
	idx = (p->col - last->col);
	dy = (idy > 0) ? 0.5 : ((idy < 0) ? -0.5 : 0.0);	/* dy = 0.0, 0.5, or -0.5 */
	dx = (idx > 0) ? 0.5 : ((idx < 0) ? -0.5 : 0.0);	/* dx = 0.0, 0.5, or -0.5 */
	y = cell_head.north - (last->row + dy) * cell_head.ns_res;
	x = cell_head.west + (last->col + dx) * cell_head.ew_res;
	total++;
	Vect_append_point(points, x, y, 0.0);

	y = cell_head.north - (p->row - dy) * cell_head.ns_res;
	x = cell_head.west + (p->col - dx) * cell_head.ew_res;
	total++;
	Vect_append_point(points, x, y, 0.0);
    }				/* end of for i */

    y = cell_head.north - (double)p->row * cell_head.ns_res;
    x = cell_head.west + (double)p->col * cell_head.ew_res;
    total++;
    Vect_append_point(points, x, y, 0.0);

    /* strip out the duplicate points from the list */
    Vect_line_prune(points);
    G_debug(3, "removed duplicates: %d", total - points->n_points);

    /* write files */
    Vect_write_line(&Map, GV_BOUNDARY, points, Cats);

    /* now free all the pointers */
    p = line_begin;

    for (i = 1; i < n; i++) {
	if (i < 10)
	    G_debug(3, " row: %d col: %d\n", p->row, p->col);

	last = p;
	if ((p = move(p)) == NULPTR)
	    break;
	if (last == p)
	    break;
	if (last->fptr != NULPTR)
	    if (last->fptr->fptr == last)
		last->fptr->fptr = NULPTR;

	/* now it can already ne NULL */
	if (last->fptr != NULPTR)
	    if (last->fptr->bptr == last)
		last->fptr->bptr = NULPTR;
	if (last->bptr != NULPTR)
	    if (last->bptr->fptr == last)
		last->bptr->fptr = NULPTR;
	if (last->bptr != NULPTR)
	    if (last->bptr->bptr == last)
		last->bptr->bptr = NULPTR;

	G_free(last);
    }				/* end of for i */

    if (p != NULPTR)
	G_free(p);

    return 0;
}
Exemple #30
0
int main(int argc, char **argv)
{
    int i, j, ret, centre, line, centre1, centre2, tfield, tucfield;
    int nlines, nnodes, type, ltype, afield, nfield, geo, cat;
    int node, node1, node2;
    double cost, e1cost, e2cost, n1cost, n2cost, s1cost, s2cost, l, l1;
    struct Option *map, *output;
    struct Option *afield_opt, *nfield_opt, *afcol, *abcol, *ncol, *type_opt,
	*term_opt, *cost_opt, *tfield_opt, *tucfield_opt;
    struct Flag *geo_f, *turntable_f;
    struct GModule *module;
    struct Map_info Map, Out;
    struct cat_list *catlist;
    CENTER *Centers = NULL;
    int acentres = 0, ncentres = 0;
    NODE *Nodes;
    struct line_cats *Cats;
    struct line_pnts *Points, *SPoints;
    int niso, aiso;
    double *iso;
    int npnts1, apnts1 = 0, npnts2, apnts2 = 0;
    ISOPOINT *pnts1 = NULL, *pnts2 = NULL;
    int next_iso;

    G_gisinit(argv[0]);

    module = G_define_module();
    G_add_keyword(_("vector"));
    G_add_keyword(_("network"));
    G_add_keyword(_("isolines"));
    module->label = _("Splits net by cost isolines.");
    module->description =
	_
	("Splits net to bands between cost isolines (direction from center). "
	 "Center node must be opened (costs >= 0). "
	 "Costs of center node are used in calculation.");

    map = G_define_standard_option(G_OPT_V_INPUT);
    output = G_define_standard_option(G_OPT_V_OUTPUT);

    term_opt = G_define_standard_option(G_OPT_V_CATS);
    term_opt->key = "ccats";
    term_opt->required = YES;
    term_opt->description =
	_("Categories of centers (points on nodes) to which net "
	  "will be allocated, "
	  "layer for this categories is given by nlayer option");

    cost_opt = G_define_option();
    cost_opt->key = "costs";
    cost_opt->type = TYPE_INTEGER;
    cost_opt->multiple = YES;
    cost_opt->required = YES;
    cost_opt->description = _("Costs for isolines");

    afield_opt = G_define_standard_option(G_OPT_V_FIELD);
    afield_opt->key = "alayer";
    afield_opt->answer = "1";
    afield_opt->required = YES;
    afield_opt->label = _("Arc layer");

    type_opt = G_define_standard_option(G_OPT_V_TYPE);
    type_opt->options = "line,boundary";
    type_opt->answer = "line,boundary";
    type_opt->required = YES;
    type_opt->label = _("Arc type");

    nfield_opt = G_define_standard_option(G_OPT_V_FIELD);
    nfield_opt->key = "nlayer";
    nfield_opt->answer = "2";
    nfield_opt->required = YES;
    nfield_opt->label = _("Node layer");

    afcol = G_define_standard_option(G_OPT_DB_COLUMN);
    afcol->key = "afcolumn";
    afcol->description =
	_("Arc forward/both direction(s) cost column (number)");
    afcol->guisection = _("Cost");

    abcol = G_define_standard_option(G_OPT_DB_COLUMN);
    abcol->key = "abcolumn";
    abcol->description = _("Arc backward direction cost column (number)");
    abcol->guisection = _("Cost");

    ncol = G_define_standard_option(G_OPT_DB_COLUMN);
    ncol->key = "ncolumn";
    ncol->description = _("Node cost column (number)");
    ncol->guisection = _("Cost");

    turntable_f = G_define_flag();
    turntable_f->key = 't';
    turntable_f->description = _("Use turntable");
    turntable_f->guisection = _("Turntable");

    tfield_opt = G_define_standard_option(G_OPT_V_FIELD);
    tfield_opt->key = "tlayer";
    tfield_opt->answer = "3";
    tfield_opt->label = _("Layer with turntable");
    tfield_opt->description =
	_("Relevant only with -t flag");
    tfield_opt->guisection = _("Turntable");

    tucfield_opt = G_define_standard_option(G_OPT_V_FIELD);
    tucfield_opt->key = "tuclayer";
    tucfield_opt->answer = "4";
    tucfield_opt->label = _("Layer with unique categories used in turntable");
    tucfield_opt->description =
	_("Relevant only with -t flag");
    tucfield_opt->guisection = _("Turntable");

    geo_f = G_define_flag();
    geo_f->key = 'g';
    geo_f->description =
	_("Use geodesic calculation for longitude-latitude locations");

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

    Vect_check_input_output_name(map->answer, output->answer, G_FATAL_EXIT);

    Cats = Vect_new_cats_struct();
    Points = Vect_new_line_struct();
    SPoints = Vect_new_line_struct();

    type = Vect_option_to_types(type_opt);

    catlist = Vect_new_cat_list();
    Vect_str_to_cat_list(term_opt->answer, catlist);

    /* Iso costs */
    aiso = 1;
    iso = (double *)G_malloc(aiso * sizeof(double));
    /* Set first iso to 0 */
    iso[0] = 0;
    niso = 1;
    i = 0;
    while (cost_opt->answers[i]) {
	if (niso == aiso) {
	    aiso += 1;
	    iso = (double *)G_realloc(iso, aiso * sizeof(double));
	}
	iso[niso] = atof(cost_opt->answers[i]);
	if (iso[niso] <= 0)
	    G_fatal_error(_("Wrong iso cost: %f"), iso[niso]);

	if (iso[niso] <= iso[niso - 1])
	    G_fatal_error(_("Iso cost: %f less than previous"), iso[niso]);

	G_verbose_message(_("Iso cost %d: %f"), niso, iso[niso]);
	niso++;
	i++;
    }

    /* Should not happen: */
    if (niso < 2)
	G_warning(_
		  ("Not enough costs, everything reachable falls to first band"));

    if (geo_f->answer)
	geo = 1;
    else
	geo = 0;

    Vect_set_open_level(2);
    if (Vect_open_old(&Map, map->answer, "") < 0)
	G_fatal_error(_("Unable to open vector map <%s>"), map->answer);

    afield = Vect_get_field_number(&Map, afield_opt->answer);
    nfield = Vect_get_field_number(&Map, nfield_opt->answer);
    tfield = Vect_get_field_number(&Map, tfield_opt->answer);
    tucfield = Vect_get_field_number(&Map, tucfield_opt->answer);

    /* Build graph */
    if (turntable_f->answer)
	Vect_net_ttb_build_graph(&Map, type, afield, nfield, tfield, tucfield,
				 afcol->answer, abcol->answer, ncol->answer,
				 geo, 0);
    else
	Vect_net_build_graph(&Map, type, afield, nfield, afcol->answer,
			     abcol->answer, ncol->answer, geo, 0);

    nnodes = Vect_get_num_nodes(&Map);
    nlines = Vect_get_num_lines(&Map);

    /* Create list of centres based on list of categories */
    for (i = 1; i <= nlines; i++) {
	ltype = Vect_get_line_type(&Map, i);
	if (!(ltype & GV_POINT))
	    continue;

	Vect_read_line(&Map, Points, Cats, i);
	node =
	    Vect_find_node(&Map, Points->x[0], Points->y[0], Points->z[0], 0,
			   0);
	if (!node) {
	    G_warning(_("Point is not connected to the network"));
	    continue;
	}
	if (!(Vect_cat_get(Cats, nfield, &cat)))
	    continue;
	if (Vect_cat_in_cat_list(cat, catlist)) {
	    Vect_net_get_node_cost(&Map, node, &n1cost);
	    if (n1cost == -1) {	/* closed */
		G_warning(_("Centre at closed node (costs = -1) ignored"));
	    }
	    else {
		if (acentres == ncentres) {
		    acentres += 1;
		    Centers =
			(CENTER *) G_realloc(Centers,
					     acentres * sizeof(CENTER));
		}
		Centers[ncentres].cat = cat;
		Centers[ncentres].node = node;
		G_debug(2, "centre = %d node = %d cat = %d", ncentres,
			node, cat);
		ncentres++;
	    }
	}
    }

    G_message(_("Number of centres: %d (nlayer %d)"), ncentres, nfield);

    if (ncentres == 0)
	G_warning(_
		  ("Not enough centres for selected nlayer. Nothing will be allocated."));

    /* alloc and reset space for all nodes */
    if (turntable_f->answer) {
	/* if turntable is used we are looking for lines as destinations, instead of the intersections (nodes) */
	Nodes = (NODE *) G_calloc((nlines * 2 + 2), sizeof(NODE));
	for (i = 2; i <= (nlines * 2 + 2); i++) {
	    Nodes[i].centre = -1;/* NOTE: first two items of Nodes are not used */
	}

    }
    else {
	Nodes = (NODE *) G_calloc((nnodes + 1), sizeof(NODE));
	for (i = 1; i <= nnodes; i++) {
	    Nodes[i].centre = -1;
	}
    }

    apnts1 = 1;
    pnts1 = (ISOPOINT *) G_malloc(apnts1 * sizeof(ISOPOINT));

    apnts2 = 1;
    pnts2 = (ISOPOINT *) G_malloc(apnts2 * sizeof(ISOPOINT));

    /* Fill Nodes by neares centre and costs from that centre */
    for (centre = 0; centre < ncentres; centre++) {
	node1 = Centers[centre].node;
	Vect_net_get_node_cost(&Map, node1, &n1cost);
	G_debug(2, "centre = %d node = %d cat = %d", centre, node1,
		Centers[centre].cat);
	G_message(_("Calculating costs from centre %d..."), centre + 1);
	if (turntable_f->answer)
	    for (line = 1; line <= nlines; line++) {
		G_debug(5, "  node1 = %d line = %d", node1, line);
		Vect_net_get_node_cost(&Map, line, &n2cost);
		/* closed, left it as not attached */

		if (Vect_read_line(&Map, Points, Cats, line) < 0)
		    continue;
		if (Vect_get_line_type(&Map, line) != GV_LINE)
		    continue;
		if (!Vect_cat_get(Cats, tucfield, &cat))
		    continue;

		for (j = 0; j < 2; j++) {
		    if (j == 1)
			cat *= -1;

		    ret =
			Vect_net_ttb_shortest_path(&Map, node1, 0, cat, 1,
						   tucfield, NULL,
						   &cost);
		    if (ret == -1) {
			continue;
		    }		/* node unreachable */

		    /* We must add centre node costs (not calculated by Vect_net_shortest_path() ), but
	             *  only if centre and node are not identical, because at the end node cost is add later */
		    if (ret != 1)
			cost += n1cost;

		    G_debug(5,
			    "Arc nodes: %d %d cost: %f (x old cent: %d old cost %f",
			    node1, line, cost, Nodes[line * 2 + j].centre,
			    Nodes[line * 2 + j].cost);
		    if (Nodes[line * 2 + j].centre == -1 ||
			cost < Nodes[line * 2 + j].cost) {
			Nodes[line * 2 + j].cost = cost;
			Nodes[line * 2 + j].centre = centre;
		    }
		}
	    }
	else
	    for (node2 = 1; node2 <= nnodes; node2++) {
		G_percent(node2, nnodes, 1);
		G_debug(5, "  node1 = %d node2 = %d", node1, node2);
		Vect_net_get_node_cost(&Map, node2, &n2cost);
		if (n2cost == -1) {
		    continue;
		}		/* closed, left it as not attached */

		ret = Vect_net_shortest_path(&Map, node1, node2, NULL, &cost);
		if (ret == -1) {
		    continue;
		}		/* node unreachable */

		/* We must add centre node costs (not calculated by Vect_net_shortest_path() ), but
		 *  only if centre and node are not identical, because at the end node cost is add later */
		if (node1 != node2)
		    cost += n1cost;
		G_debug(5,
			"Arc nodes: %d %d cost: %f (x old cent: %d old cost %f",
			node1, node2, cost, Nodes[node2].centre,
			Nodes[node2].cost);
		if (Nodes[node2].centre == -1 || cost < Nodes[node2].cost) {
		    Nodes[node2].cost = cost;
		    Nodes[node2].centre = centre;
		}
	    }
    }

    /* Write arcs to new map */
    if (Vect_open_new(&Out, output->answer, Vect_is_3d(&Map)) < 0)
	G_fatal_error(_("Unable to create vector map <%s>"), output->answer);

    Vect_hist_command(&Out);

    G_message("Generating isolines...");
    nlines = Vect_get_num_lines(&Map);
    for (line = 1; line <= nlines; line++) {
	G_percent(line, nlines, 2);

	ltype = Vect_read_line(&Map, Points, NULL, line);
	if (!(ltype & type)) {
	    continue;
	}

	l = Vect_line_length(Points);
	if (l == 0)
	    continue;

	if (turntable_f->answer) {
	    centre1 = Nodes[line * 2].centre;
	    centre2 = Nodes[line * 2 + 1].centre;
	    s1cost = Nodes[line * 2].cost;
	    s2cost = Nodes[line * 2 + 1].cost;
	    n1cost = n2cost = 0;
	}
	else {
	    Vect_get_line_nodes(&Map, line, &node1, &node2);
	    centre1 = Nodes[node1].centre;
	    centre2 = Nodes[node2].centre;
	    s1cost = Nodes[node1].cost;
	    s2cost = Nodes[node2].cost;

	    Vect_net_get_node_cost(&Map, node1, &n1cost);
	    Vect_net_get_node_cost(&Map, node2, &n2cost);

	}

	Vect_net_get_line_cost(&Map, line, GV_FORWARD, &e1cost);
	Vect_net_get_line_cost(&Map, line, GV_BACKWARD, &e2cost);

	G_debug(3, "Line %d : length = %f", line, l);
	G_debug(3, "Arc centres: %d %d (nodes: %d %d)", centre1, centre2,
		node1, node2);

	G_debug(3, "  s1cost = %f n1cost = %f e1cost = %f", s1cost, n1cost,
		e1cost);
	G_debug(3, "  s2cost = %f n2cost = %f e2cost = %f", s2cost, n2cost,
		e2cost);


	/* First check if arc is reachable from at least one side */
	if ((centre1 != -1 && n1cost != -1 && e1cost != -1) ||
	    (centre2 != -1 && n2cost != -1 && e2cost != -1)) {
	    /* Line is reachable at least from one side */
	    G_debug(3, "  -> arc is reachable");

	    /* Add costs of node to starting costs */
	    s1cost += n1cost;
	    s2cost += n2cost;

	    e1cost /= l;
	    e2cost /= l;

	    /* Find points on isolines along the line in both directions, add them to array,
	     *  first point is placed at the beginning/end of line */
	    /* Forward */
	    npnts1 = 0;		/* in case this direction is closed */
	    if (centre1 != -1 && n1cost != -1 && e1cost != -1) {
		/* Find iso for beginning of the line */
		next_iso = 0;
		for (i = niso - 1; i >= 0; i--) {
		    if (iso[i] <= s1cost) {
			next_iso = i;
			break;
		    }
		}
		/* Add first */
		pnts1[0].iso = next_iso;
		pnts1[0].distance = 0;
		npnts1++;
		next_iso++;

		/* Calculate distances for points along line */
		while (next_iso < niso) {
		    if (e1cost == 0)
			break;	/* Outside line */
		    l1 = (iso[next_iso] - s1cost) / e1cost;
		    if (l1 >= l)
			break;	/* Outside line */

		    if (npnts1 == apnts1) {
			apnts1 += 1;
			pnts1 =
			    (ISOPOINT *) G_realloc(pnts1,
						   apnts1 * sizeof(ISOPOINT));
		    }
		    pnts1[npnts1].iso = next_iso;
		    pnts1[npnts1].distance = l1;
		    G_debug(3,
			    "  forward %d : iso %d : distance %f : cost %f",
			    npnts1, next_iso, l1, iso[next_iso]);
		    npnts1++;
		    next_iso++;
		}
	    }
	    G_debug(3, "  npnts1 = %d", npnts1);

	    /* Backward */
	    npnts2 = 0;
	    if (centre2 != -1 && n2cost != -1 && e2cost != -1) {
		/* Find iso for beginning of the line */
		next_iso = 0;
		for (i = niso - 1; i >= 0; i--) {
		    if (iso[i] <= s2cost) {
			next_iso = i;
			break;
		    }
		}
		/* Add first */
		pnts2[0].iso = next_iso;
		pnts2[0].distance = l;
		npnts2++;
		next_iso++;

		/* Calculate distances for points along line */
		while (next_iso < niso) {
		    if (e2cost == 0)
			break;	/* Outside line */
		    l1 = (iso[next_iso] - s2cost) / e2cost;
		    if (l1 >= l)
			break;	/* Outside line */

		    if (npnts2 == apnts2) {
			apnts2 += 1;
			pnts2 =
			    (ISOPOINT *) G_realloc(pnts2,
						   apnts2 * sizeof(ISOPOINT));
		    }
		    pnts2[npnts2].iso = next_iso;
		    pnts2[npnts2].distance = l - l1;
		    G_debug(3,
			    "  backward %d : iso %d : distance %f : cost %f",
			    npnts2, next_iso, l - l1, iso[next_iso]);
		    npnts2++;
		    next_iso++;
		}
	    }
	    G_debug(3, "  npnts2 = %d", npnts2);

	    /* Limit number of points by maximum costs in reverse direction, this may remove
	     *  also the first point in one direction, but not in both */
	    /* Forward */
	    if (npnts2 > 0) {
		for (i = 0; i < npnts1; i++) {
		    G_debug(3,
			    "  pnt1 = %d dist1 = %f iso1 = %d max iso2 = %d",
			    i, pnts1[i].distance, pnts1[i].iso,
			    pnts2[npnts2 - 1].iso);
		    if (pnts2[npnts2 - 1].iso < pnts1[i].iso) {
			G_debug(3, "    -> cut here");
			npnts1 = i;
			break;
		    }
		}
	    }
	    G_debug(3, "  npnts1 cut = %d", npnts1);

	    /* Backward */
	    if (npnts1 > 0) {
		for (i = 0; i < npnts2; i++) {
		    G_debug(3,
			    "  pnt2 = %d dist2 = %f iso2 = %d max iso1 = %d",
			    i, pnts2[i].distance, pnts2[i].iso,
			    pnts1[npnts1 - 1].iso);
		    if (pnts1[npnts1 - 1].iso < pnts2[i].iso) {
			G_debug(3, "    -> cut here");
			npnts2 = i;
			break;
		    }
		}
	    }
	    G_debug(3, "  npnts2 cut = %d", npnts2);

	    /* Biggest cost shoud be equal if exist (npnts > 0). Cut out overlapping segments,
	     *  this can cut only points on line but not first points */
	    if (npnts1 > 1 && npnts2 > 1) {
		while (npnts1 > 1 && npnts2 > 1) {
		    if (pnts1[npnts1 - 1].distance >= pnts2[npnts2 - 1].distance) {	/* overlap */
			npnts1--;
			npnts2--;
		    }
		    else {
			break;
		    }
		}
	    }
	    G_debug(3, "  npnts1 2. cut = %d", npnts1);
	    G_debug(3, "  npnts2 2. cut = %d", npnts2);

	    /* Now we have points in both directions which may not overlap, npoints in one
	     *  direction may be 0 but not both */

	    /* Join both arrays, iso of point is for next segment (point is at the beginning) */
	    /* In case npnts1 == 0 add point at distance 0 */
	    if (npnts1 == 0) {
		G_debug(3,
			"  npnts1 = 0 -> add first at distance 0, cat = %d",
			pnts2[npnts2 - 1].iso);
		pnts1[0].iso = pnts2[npnts2 - 1].iso;	/* use last point iso in reverse direction */
		pnts1[0].distance = 0;
		npnts1++;
	    }
	    for (i = npnts2 - 1; i >= 0; i--) {
		/* Check if identical */
		if (pnts1[npnts1 - 1].distance == pnts2[i].distance)
		    continue;

		if (npnts1 == apnts1) {
		    apnts1 += 1;
		    pnts1 =
			(ISOPOINT *) G_realloc(pnts1,
					       apnts1 * sizeof(ISOPOINT));
		}
		pnts1[npnts1].iso = pnts2[i].iso - 1;	/* last may be -1, but it is not used */
		pnts1[npnts1].distance = pnts2[i].distance;
		npnts1++;
	    }
	    /* In case npnts2 == 0 add point at the end */
	    if (npnts2 == 0) {
		pnts1[npnts1].iso = 0;	/* not used */
		pnts1[npnts1].distance = l;
		npnts1++;
	    }

	    /* Create line segments. */
	    for (i = 1; i < npnts1; i++) {
		cat = pnts1[i - 1].iso + 1;
		G_debug(3, "  segment %f - %f cat %d", pnts1[i - 1].distance,
			pnts1[i].distance, cat);
		ret =
		    Vect_line_segment(Points, pnts1[i - 1].distance,
				      pnts1[i].distance, SPoints);
		if (ret == 0) {
		    G_warning(_
			      ("Cannot get line segment, segment out of line"));
		}
		else {
		    Vect_reset_cats(Cats);
		    Vect_cat_set(Cats, 1, cat);
		    Vect_write_line(&Out, ltype, SPoints, Cats);
		}
	    }
	}
	else {
	    /* arc is not reachable */
	    G_debug(3, "  -> arc is not reachable");
	    Vect_reset_cats(Cats);
	    Vect_write_line(&Out, ltype, Points, Cats);
	}
    }

    Vect_build(&Out);

    /* Free, ... */
    G_free(Nodes);
    G_free(Centers);
    Vect_close(&Map);
    Vect_close(&Out);

    exit(EXIT_SUCCESS);
}