Esempio n. 1
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);
} 
Esempio n. 2
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() */