Esempio n. 1
0
int G_math_srand_auto(void)
{
    return (int) G_srand48_auto();
}
Esempio n. 2
0
File: main.c Progetto: caomw/grass
int main(int argc, char *argv[])
{
    char *output, buf[DB_SQL_MAX];
    double (*rng)(void) = G_drand48;
    double zmin, zmax;
    int seed;
    int i, j, k, n, type, usefloat;
    int area, nareas, field;
    struct boxlist *List = NULL;
    BOX_SIZE *size_list = NULL;
    int alloc_size_list = 0;
    struct Map_info In, Out;
    struct line_pnts *Points;
    struct line_cats *Cats;
    struct cat_list *cat_list;
    struct bound_box box;
    struct Cell_head window;
    struct GModule *module;
    struct
    {
	struct Option *input, *field, *cats, *where, *output, *nsites,
		      *zmin, *zmax, *zcol, *ztype, *seed;
    } parm;
    struct
    {
	struct Flag *z, *notopo, *a;
    } flag;
    struct field_info *Fi;
    dbDriver *driver;
    dbTable *table;
    dbString sql;

    G_gisinit(argv[0]);

    module = G_define_module();
    G_add_keyword(_("vector"));
    G_add_keyword(_("sampling"));
    G_add_keyword(_("statistics"));
    G_add_keyword(_("random"));
    module->description = _("Generates random 2D/3D vector points.");

    parm.output = G_define_standard_option(G_OPT_V_OUTPUT);

    parm.nsites = G_define_option();
    parm.nsites->key = "n";
    parm.nsites->type = TYPE_INTEGER;
    parm.nsites->required = YES;
    parm.nsites->description = _("Number of points to be created");

    parm.input = G_define_standard_option(G_OPT_V_INPUT);
    parm.input->required = NO;
    parm.input->description = _("Restrict points to areas in input vector");
    parm.input->guisection = _("Selection");

    parm.field = G_define_standard_option(G_OPT_V_FIELD_ALL);
    parm.field->guisection = _("Selection");

    parm.cats = G_define_standard_option(G_OPT_V_CATS);
    parm.cats->guisection = _("Selection");
    
    parm.where = G_define_standard_option(G_OPT_DB_WHERE);
    parm.where->guisection = _("Selection");

    parm.zmin = G_define_option();
    parm.zmin->key = "zmin";
    parm.zmin->type = TYPE_DOUBLE;
    parm.zmin->required = NO;
    parm.zmin->description =
	_("Minimum z height (needs -z flag or column name)");
    parm.zmin->answer = "0.0";
    parm.zmin->guisection = _("3D output");

    parm.zmax = G_define_option();
    parm.zmax->key = "zmax";
    parm.zmax->type = TYPE_DOUBLE;
    parm.zmax->required = NO;
    parm.zmax->description =
	_("Maximum z height (needs -z flag or column name)");
    parm.zmax->answer = "0.0";
    parm.zmax->guisection = _("3D output");

    parm.seed = G_define_option();
    parm.seed->key = "seed";
    parm.seed->type = TYPE_INTEGER;
    parm.seed->required = NO;
    parm.seed->description =
	_("The seed to initialize the random generator. If not set the process ID is used");

    parm.zcol = G_define_standard_option(G_OPT_DB_COLUMN);
    parm.zcol->label = _("Name of column for z values");
    parm.zcol->description =
	_("Writes z values to column");
    parm.zcol->guisection = _("3D output");

    parm.ztype = G_define_option();
    parm.ztype->key = "column_type";
    parm.ztype->type = TYPE_STRING;
    parm.ztype->required = NO;
    parm.ztype->multiple = NO;
    parm.ztype->description = _("Type of column for z values");
    parm.ztype->options = "integer,double precision";
    parm.ztype->answer = "double precision";
    parm.ztype->guisection = _("3D output");

    flag.z = G_define_flag();
    flag.z->key = 'z';
    flag.z->description = _("Create 3D output");
    flag.z->guisection = _("3D output");

    flag.a = G_define_flag();
    flag.a->key = 'a';
    flag.a->description = _("Generate n points for each individual area");

    flag.notopo = G_define_standard_flag(G_FLG_V_TOPO);

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

    output = parm.output->answer;
    n = atoi(parm.nsites->answer);
    
    if(parm.seed->answer)
        seed = atoi(parm.seed->answer);

    if (n <= 0) {
	G_fatal_error(_("Number of points must be > 0 (%d given)"), n);
    }

    nareas = 0;
    cat_list = NULL;
    field = -1;
    if (parm.input->answer) {
	Vect_set_open_level(2); /* topology required */
	if (2 > Vect_open_old2(&In, parm.input->answer, "", parm.field->answer))
	    G_fatal_error(_("Unable to open vector map <%s>"),
			  parm.input->answer);

	if (parm.field->answer)
	    field = Vect_get_field_number(&In, parm.field->answer);

	if ((parm.cats->answer || parm.where->answer) && field == -1) {
	    G_warning(_("Invalid layer number (%d). Parameter '%s' or '%s' specified, assuming layer '1'."),
		      field, parm.cats->key, parm.where->key);
	    field = 1;
	}
	if (field > 0)
	    cat_list = Vect_cats_set_constraint(&In, field, parm.where->answer,
						parm.cats->answer);
	nareas = Vect_get_num_areas(&In);
	if (nareas == 0) {
	    Vect_close(&In);
	    G_fatal_error(_("No areas in vector map <%s>"), parm.input->answer);
	}
    }
    else {
	if (flag.a->answer)
	    G_fatal_error(_("The <-%c> flag requires an input vector with areas"),
	                  flag.a->key);
    }

    /* create new vector map */
    if (-1 == Vect_open_new(&Out, output, flag.z->answer ? WITH_Z : WITHOUT_Z))
        G_fatal_error(_("Unable to create vector map <%s>"), output);
    Vect_set_error_handler_io(NULL, &Out);

    /* Do we need to write random values into attribute table? */
    usefloat = -1;
    if (parm.zcol->answer) {
	Fi = Vect_default_field_info(&Out, 1, NULL, GV_1TABLE);
	driver =
	    db_start_driver_open_database(Fi->driver,
					  Vect_subst_var(Fi->database, &Out));
	if (driver == NULL) {
	    G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
			  Vect_subst_var(Fi->database, &Out), Fi->driver);
	}
        db_set_error_handler_driver(driver);
        
	db_begin_transaction(driver);

	db_init_string(&sql);
	sprintf(buf, "create table %s (%s integer, %s %s)", Fi->table, GV_KEY_COLUMN,
		parm.zcol->answer, parm.ztype->answer);
	db_set_string(&sql, buf);
	Vect_map_add_dblink(&Out, 1, NULL, Fi->table, GV_KEY_COLUMN, Fi->database,
			    Fi->driver);

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

	/* Create index */
	if (db_create_index2(driver, Fi->table, Fi->key) != DB_OK)
	    G_warning(_("Unable to create index"));

	/* Grant */
	if (db_grant_on_table
	    (driver, Fi->table, DB_PRIV_SELECT,
	     DB_GROUP | DB_PUBLIC) != DB_OK) {
	    G_fatal_error(_("Unable to grant privileges on table <%s>"),
			  Fi->table);
	}

	/* OK. Let's check what type of column user has created */
	db_set_string(&sql, Fi->table);
	if (db_describe_table(driver, &sql, &table) != DB_OK) {
	    G_fatal_error(_("Unable to describe table <%s>"), Fi->table);
	}

	if (db_get_table_number_of_columns(table) != 2) {
	    G_fatal_error(_("Table should contain only two columns"));
	}

	type = db_get_column_sqltype(db_get_table_column(table, 1));
	if (type == DB_SQL_TYPE_SMALLINT || type == DB_SQL_TYPE_INTEGER)
	    usefloat = 0;
	if (type == DB_SQL_TYPE_REAL || type == DB_SQL_TYPE_DOUBLE_PRECISION)
	    usefloat = 1;
	if (usefloat < 0) {
	    G_fatal_error(_("You have created unsupported column type. This module supports only INTEGER"
			   " and DOUBLE PRECISION column types."));
	}
    }

    Vect_hist_command(&Out);

    /* Init the random seed */
    if(parm.seed->answer)
	G_srand48(seed);
    else
	G_srand48_auto();

    G_get_window(&window);

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

    if (nareas > 0) {
	int first = 1, count;
	struct bound_box abox, bbox;

	box.W = window.west;
	box.E = window.east;
	box.S = window.south;
	box.N = window.north;
	box.B = -PORT_DOUBLE_MAX;
	box.T = PORT_DOUBLE_MAX;

	count = 0;

	for (i = 1; i <= nareas; i++) {
	    
	    if (!Vect_get_area_centroid(&In, i))
		continue;

	    if (field > 0) {
		if (Vect_get_area_cats(&In, i, Cats))
		    continue;

		if (!Vect_cats_in_constraint(Cats, field, cat_list))
		    continue;
	    }

	    Vect_get_area_box(&In, i, &abox);
	    if (!Vect_box_overlap(&abox, &box))
		continue;

	    if (first) {
		Vect_box_copy(&bbox, &abox);
		first = 0;
	    }
	    else
		Vect_box_extend(&bbox, &abox);
	    count++;
	}
	if (count == 0) {
	    Vect_close(&In);
	    Vect_close(&Out);
	    Vect_delete(output);
	    G_fatal_error(_("Selected areas in input vector <%s> do not overlap with the current region"),
			  parm.input->answer);
	}
	Vect_box_copy(&box, &bbox);

	/* does the vector overlap with the current region ? */
	if (box.W >= window.east || box.E <= window.west ||
	    box.S >= window.north || box.N <= window.south) {

	    Vect_close(&In);
	    Vect_close(&Out);
	    Vect_delete(output);
	    G_fatal_error(_("Input vector <%s> does not overlap with the current region"),
	                  parm.input->answer);
	}

	/* try to reduce the current region */
	if (window.east > box.E)
	    window.east = box.E;
	if (window.west < box.W)
	    window.west = box.W;
	if (window.north > box.N)
	    window.north = box.N;
	if (window.south < box.S)
	    window.south = box.S;

	List = Vect_new_boxlist(1);
	alloc_size_list = 10;
	size_list = G_malloc(alloc_size_list * sizeof(BOX_SIZE));
    }

    zmin = zmax = 0;
    if (flag.z->answer || parm.zcol->answer) {
	zmax = atof(parm.zmax->answer);
	zmin = atof(parm.zmin->answer);
    }

    G_message(_("Generating points..."));
    if (flag.a->answer && nareas > 0) {
	struct bound_box abox, bbox;
	int cat = 1;

	/* n points for each area */
	nareas = Vect_get_num_areas(&In);
	
	G_percent(0, nareas, 1);
	for (area = 1; area <= nareas; area++) {

	    G_percent(area, nareas, 1);

	    if (!Vect_get_area_centroid(&In, area))
		continue;

	    if (field > 0) {
		if (Vect_get_area_cats(&In, area, Cats))
		    continue;

		if (!Vect_cats_in_constraint(Cats, field, cat_list)) {
		    continue;
		}
	    }

	    box.W = window.west;
	    box.E = window.east;
	    box.S = window.south;
	    box.N = window.north;
	    box.B = -PORT_DOUBLE_MAX;
	    box.T = PORT_DOUBLE_MAX;
	    
	    Vect_get_area_box(&In, area, &abox);
	    if (!Vect_box_overlap(&box, &abox))
		continue;
		
	    bbox = abox;
	    if (bbox.W < box.W)
		bbox.W = box.W;
	    if (bbox.E > box.E)
		bbox.E = box.E;
	    if (bbox.S < box.S)
		bbox.S = box.S;
	    if (bbox.N > box.N)
		bbox.N = box.N;

	    for (i = 0; i < n; ++i) {
		double x, y, z;
		int outside = 1;
		int ret;

		Vect_reset_line(Points);
		Vect_reset_cats(Cats);

		while (outside) {
		    x = rng() * (bbox.W - bbox.E) + bbox.E;
		    y = rng() * (bbox.N - bbox.S) + bbox.S;
		    z = rng() * (zmax - zmin) + zmin;

		    ret = Vect_point_in_area(x, y, &In, area, &abox);

		    G_debug(3, "    area = %d Vect_point_in_area() = %d", area, ret);

		    if (ret >= 1) {
			outside = 0;
		    }
		}

		if (flag.z->answer)
		    Vect_append_point(Points, x, y, z);
		else
		    Vect_append_point(Points, x, y, 0.0);

		if (parm.zcol->answer) {
		    sprintf(buf, "insert into %s values ( %d, ", Fi->table, i + 1);
		    db_set_string(&sql, buf);
		    /* Round random value if column is integer type */
		    if (usefloat)
			sprintf(buf, "%f )", z);
		    else
			sprintf(buf, "%.0f )", z);
		    db_append_string(&sql, buf);

		    G_debug(3, db_get_string(&sql));
		    if (db_execute_immediate(driver, &sql) != DB_OK) {
			G_fatal_error(_("Cannot insert new row: %s"),
				      db_get_string(&sql));
		    }
		}

		Vect_cat_set(Cats, 1, cat++);
		Vect_write_line(&Out, GV_POINT, Points, Cats);
	    }
	}
    }
    else {
	/* n points in total */
	for (i = 0; i < n; ++i) {
	    double x, y, z;

	    G_percent(i, n, 4);

	    Vect_reset_line(Points);
	    Vect_reset_cats(Cats);

	    x = rng() * (window.west - window.east) + window.east;
	    y = rng() * (window.north - window.south) + window.south;
	    z = rng() * (zmax - zmin) + zmin;
	    
	    if (nareas) {
		int outside = 1;

		do {
		    /* select areas by box */
		    box.E = x;
		    box.W = x;
		    box.N = y;
		    box.S = y;
		    box.T = PORT_DOUBLE_MAX;
		    box.B = -PORT_DOUBLE_MAX;
		    Vect_select_areas_by_box(&In, &box, List);
		    G_debug(3, "  %d areas selected by box", List->n_values);

		    /* sort areas by size, the smallest is likely to be the nearest */
		    if (alloc_size_list < List->n_values) {
			alloc_size_list = List->n_values;
			size_list = G_realloc(size_list, alloc_size_list * sizeof(BOX_SIZE));
		    }

		    k = 0;
		    for (j = 0; j < List->n_values; j++) {
			area = List->id[j];

			if (!Vect_get_area_centroid(&In, area))
			    continue;

			if (field > 0) {
			    if (Vect_get_area_cats(&In, area, Cats))
				continue;

			    if (!Vect_cats_in_constraint(Cats, field, cat_list)) {
				continue;
			    }
			}

			List->id[k] = List->id[j];
			List->box[k] = List->box[j];
			size_list[k].i = List->id[k];
			box = List->box[k];
			size_list[k].box = List->box[k];
			size_list[k].size = (box.N - box.S) * (box.E - box.W);
			k++;
		    }
		    List->n_values = k;
		    
		    if (List->n_values == 2) {
			/* simple swap */
			if (size_list[1].size < size_list[0].size) {
			    size_list[0].i = List->id[1];
			    size_list[1].i = List->id[0];
			    size_list[0].box = List->box[1];
			    size_list[1].box = List->box[0];
			}
		    }
		    else if (List->n_values > 2)
			qsort(size_list, List->n_values, sizeof(BOX_SIZE), sort_by_size);

		    for (j = 0; j < List->n_values; j++) {
			int ret;

			area = size_list[j].i;
			ret = Vect_point_in_area(x, y, &In, area, &size_list[j].box);

			G_debug(3, "    area = %d Vect_point_in_area() = %d", area, ret);

			if (ret >= 1) {
			    outside = 0;
			    break;
			}
		    }
		    if (outside) {
			x = rng() * (window.west - window.east) + window.east;
			y = rng() * (window.north - window.south) + window.south;
			z = rng() * (zmax - zmin) + zmin;
		    }
		} while (outside);
	    }

	    if (flag.z->answer)
		Vect_append_point(Points, x, y, z);
	    else
		Vect_append_point(Points, x, y, 0.0);

	    if (parm.zcol->answer) {
		sprintf(buf, "insert into %s values ( %d, ", Fi->table, i + 1);
		db_set_string(&sql, buf);
		/* Round random value if column is integer type */
		if (usefloat)
		    sprintf(buf, "%f )", z);
		else
		    sprintf(buf, "%.0f )", z);
		db_append_string(&sql, buf);

		G_debug(3, db_get_string(&sql));
		if (db_execute_immediate(driver, &sql) != DB_OK) {
		    G_fatal_error(_("Cannot insert new row: %s"),
				  db_get_string(&sql));
		}
	    }

	    Vect_cat_set(Cats, 1, i + 1);
	    Vect_write_line(&Out, GV_POINT, Points, Cats);
	}
	G_percent(1, 1, 1);
    }
    
    if (parm.zcol->answer) {
	db_commit_transaction(driver);
	db_close_database_shutdown_driver(driver);
    }

    if (!flag.notopo->answer) {
	Vect_build(&Out);
    }
    Vect_close(&Out);

    exit(EXIT_SUCCESS);
}
Esempio n. 3
0
int main(int argc, char *argv[])
{
    int ii;
    int ret_val;
    struct Cell_head cellhd;
    struct WaterParams wp;
    struct options parm;
    struct flags flag;
    long seed_value;

    G_gisinit(argv[0]);

    module = G_define_module();
    G_add_keyword(_("raster"));
    G_add_keyword(_("hydrology"));
    G_add_keyword(_("soil"));
    G_add_keyword(_("sediment flow"));
    G_add_keyword(_("erosion"));
    G_add_keyword(_("deposition"));
    G_add_keyword(_("model"));
    module->description =
	_("Sediment transport and erosion/deposition simulation "
	  "using path sampling method (SIMWE).");

    parm.elevin = G_define_standard_option(G_OPT_R_ELEV);
    
    parm.wdepth = G_define_standard_option(G_OPT_R_INPUT);
    parm.wdepth->key = "water_depth";
    parm.wdepth->description = _("Name of water depth raster map [m]");

    parm.dxin = G_define_standard_option(G_OPT_R_INPUT);
    parm.dxin->key = "dx";
    parm.dxin->description = _("Name of x-derivatives raster map [m/m]");

    parm.dyin = G_define_standard_option(G_OPT_R_INPUT);
    parm.dyin->key = "dy";
    parm.dyin->description = _("Name of y-derivatives raster map [m/m]");
    
    parm.detin = G_define_standard_option(G_OPT_R_INPUT);
    parm.detin->key = "detachment_coeff";
    parm.detin->description =
	_("Name of detachment capacity coefficient raster map [s/m]");

    parm.tranin = G_define_standard_option(G_OPT_R_INPUT);
    parm.tranin->key = "transport_coeff";
    parm.tranin->description =
	_("Name of transport capacity coefficient raster map [s]");
    
    parm.tauin = G_define_standard_option(G_OPT_R_INPUT);
    parm.tauin->key = "shear_stress";
    parm.tauin->description =
	_("Name of critical shear stress raster map [Pa]");

    parm.manin = G_define_standard_option(G_OPT_R_INPUT);
    parm.manin->key = "man";
    parm.manin->required = NO;
    parm.manin->description = _("Name of Manning's n raster map");
    parm.manin->guisection = _("Input");

    parm.maninval = G_define_option();
    parm.maninval->key = "man_value";
    parm.maninval->type = TYPE_DOUBLE;
    parm.maninval->answer = MANINVAL;
    parm.maninval->required = NO;
    parm.maninval->description = _("Manning's n unique value");
    parm.maninval->guisection = _("Input");

    parm.observation = G_define_standard_option(G_OPT_V_INPUT);
    parm.observation->key = "observation";
    parm.observation->required = NO;
    parm.observation->label =
	_("Name of sampling locations vector points map");
    parm.observation->guisection = _("Input");

    parm.tc = G_define_standard_option(G_OPT_R_OUTPUT);
    parm.tc->key = "transport_capacity";
    parm.tc->required = NO;
    parm.tc->description = _("Name for output transport capacity raster map [kg/ms]");
    parm.tc->guisection = _("Output");

    parm.et = G_define_standard_option(G_OPT_R_OUTPUT);
    parm.et->key = "tlimit_erosion_deposition";
    parm.et->required = NO;
    parm.et->description =
	_("Name for output transport limited erosion-deposition raster map [kg/m2s]");
    parm.et->guisection = _("Output");

    parm.conc = G_define_standard_option(G_OPT_R_OUTPUT);
    parm.conc->key = "sediment_concentration";
    parm.conc->required = NO;
    parm.conc->description =
	_("Name for output sediment concentration raster map [particle/m3]");
    parm.conc->guisection = _("Output");

    parm.flux = G_define_standard_option(G_OPT_R_OUTPUT);
    parm.flux->key = "sediment_flux";
    parm.flux->required = NO;
    parm.flux->description = _("Name for output sediment flux raster map [kg/ms]");
    parm.flux->guisection = _("Output");

    parm.erdep = G_define_standard_option(G_OPT_R_OUTPUT);
    parm.erdep->key = "erosion_deposition";
    parm.erdep->required = NO;
    parm.erdep->description =
	_("Name for output erosion-deposition raster map [kg/m2s]");
    parm.erdep->guisection = _("Output");

    parm.logfile = G_define_standard_option(G_OPT_F_OUTPUT);
    parm.logfile->key = "logfile";
    parm.logfile->required = NO;
    parm.logfile->description =
	_("Name for sampling points output text file. For each observation vector point the time series of sediment transport is stored.");
    parm.logfile->guisection = _("Output");

    parm.outwalk = G_define_standard_option(G_OPT_V_OUTPUT);
    parm.outwalk->key = "walkers_output";
    parm.outwalk->required = NO;
    parm.outwalk->description =
	_("Base name of the output walkers vector points map");
    parm.outwalk->guisection = _("Output");

    parm.nwalk = G_define_option();
    parm.nwalk->key = "nwalkers";
    parm.nwalk->type = TYPE_INTEGER;
    parm.nwalk->required = NO;
    parm.nwalk->description = _("Number of walkers");
    parm.nwalk->guisection = _("Parameters");

    parm.niter = G_define_option();
    parm.niter->key = "niterations";
    parm.niter->type = TYPE_INTEGER;
    parm.niter->answer = NITER;
    parm.niter->required = NO;
    parm.niter->description = _("Time used for iterations [minutes]");
    parm.niter->guisection = _("Parameters");

    parm.outiter = G_define_option();
    parm.outiter->key = "output_step";
    parm.outiter->type = TYPE_INTEGER;
    parm.outiter->answer = ITEROUT;
    parm.outiter->required = NO;
    parm.outiter->description =
	_("Time interval for creating output maps [minutes]");
    parm.outiter->guisection = _("Parameters");

/*
    parm.density = G_define_option();
    parm.density->key = "density";
    parm.density->type = TYPE_INTEGER;
    parm.density->answer = DENSITY;
    parm.density->required = NO;
    parm.density->description = _("Density of output walkers");
    parm.density->guisection = _("Parameters");
*/

    parm.diffc = G_define_option();
    parm.diffc->key = "diffusion_coeff";
    parm.diffc->type = TYPE_DOUBLE;
    parm.diffc->answer = DIFFC;
    parm.diffc->required = NO;
    parm.diffc->description = _("Water diffusion constant");
    parm.diffc->guisection = _("Parameters");

    
    parm.seed = G_define_option();
    parm.seed->key = "random_seed";
    parm.seed->type = TYPE_INTEGER;
    parm.seed->required = NO;
    parm.seed->label = _("Seed for random number generator");
    parm.seed->description =
        _("The same seed can be used to obtain same results"
          " or random seed can be generated by other means.");

    flag.generateSeed = G_define_flag();
    flag.generateSeed->key = 's';
    flag.generateSeed->label =
        _("Generate random seed");
    flag.generateSeed->description =
        _("Automatically generates random seed for random number"
          " generator (use when you don't want to provide the seed option)");

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

    if (flag.generateSeed->answer) {
        seed_value = G_srand48_auto();
        G_verbose_message(_("Generated random seed (-s): %ld"), seed_value);
    }
    else if (parm.seed->answer) {
        seed_value = atol(parm.seed->answer);
        G_srand48(seed_value);
        G_verbose_message(_("Read random seed from %s option: %ld"),
                          parm.seed->key, seed_value);
    }
    else {
        /* default as it used to be */
        G_srand48(12345);
    }

    G_get_set_window(&cellhd);

    WaterParams_init(&wp);

    wp.conv = G_database_units_to_meters_factor();

    wp.mixx = cellhd.west * wp.conv;
    wp.maxx = cellhd.east * wp.conv;
    wp.miyy = cellhd.south * wp.conv;
    wp.mayy = cellhd.north * wp.conv;

    wp.stepx = cellhd.ew_res * wp.conv;
    wp.stepy = cellhd.ns_res * wp.conv;
    /*  wp.step = amin1(wp.stepx,wp.stepy); */
    wp.step = (wp.stepx + wp.stepy) / 2.;
    wp.mx = cellhd.cols;
    wp.my = cellhd.rows;
    wp.xmin = 0.;
    wp.ymin = 0.;
    wp.xp0 = wp.xmin + wp.stepx / 2.;
    wp.yp0 = wp.ymin + wp.stepy / 2.;
    wp.xmax = wp.xmin + wp.stepx * (float)wp.mx;
    wp.ymax = wp.ymin + wp.stepy * (float)wp.my;
    wp.hhc = wp.hhmax = 0.;

#if 0
    wp.bxmi = 2093113. * wp.conv;
    wp.bymi = 731331. * wp.conv;
    wp.bxma = 2093461. * wp.conv;
    wp.byma = 731529. * wp.conv;
    wp.bresx = 2. * wp.conv;
    wp.bresy = 2. * wp.conv;
    wp.maxwab = 100000;

    wp.mx2o = (int)((wp.bxma - wp.bxmi) / wp.bresx);
    wp.my2o = (int)((wp.byma - wp.bymi) / wp.bresy);

    /* relative small box coordinates: leave 1 grid layer for overlap */

    wp.bxmi = wp.bxmi - wp.mixx + wp.stepx;
    wp.bymi = wp.bymi - wp.miyy + wp.stepy;
    wp.bxma = wp.bxma - wp.mixx - wp.stepx;
    wp.byma = wp.byma - wp.miyy - wp.stepy;
    wp.mx2 = wp.mx2o - 2 * ((int)(wp.stepx / wp.bresx));
    wp.my2 = wp.my2o - 2 * ((int)(wp.stepy / wp.bresy));
#endif

    wp.elevin = parm.elevin->answer;
    wp.wdepth = parm.wdepth->answer;
    wp.dxin = parm.dxin->answer;
    wp.dyin = parm.dyin->answer;
    wp.detin = parm.detin->answer;
    wp.tranin = parm.tranin->answer;
    wp.tauin = parm.tauin->answer;
    wp.manin = parm.manin->answer;
    wp.tc = parm.tc->answer;
    wp.et = parm.et->answer;
    wp.conc = parm.conc->answer;
    wp.flux = parm.flux->answer;
    wp.erdep = parm.erdep->answer;
    wp.outwalk = parm.outwalk->answer; 

    /*      sscanf(parm.nwalk->answer, "%d", &wp.maxwa); */
    sscanf(parm.niter->answer, "%d", &wp.timesec);
    sscanf(parm.outiter->answer, "%d", &wp.iterout);
/*    sscanf(parm.density->answer, "%d", &wp.ldemo); */
    sscanf(parm.diffc->answer, "%lf", &wp.frac);
    sscanf(parm.maninval->answer, "%lf", &wp.manin_val);

    /* Recompute timesec from user input in minutes
     * to real timesec in seconds */
    wp.timesec = wp.timesec * 60;
    wp.iterout = wp.iterout * 60;
    if ((wp.timesec / wp.iterout) > 100)
	G_message(_("More than 100 files are going to be created !!!!!"));

    /* compute how big the raster is and set this to appr 2 walkers per cell */
    if (parm.nwalk->answer == NULL) {
	wp.maxwa = wp.mx * wp.my * 2;
	wp.rwalk = (double)(wp.mx * wp.my * 2.);
	G_message(_("default nwalk=%d, rwalk=%f"), wp.maxwa, wp.rwalk);
    }
    else {
	sscanf(parm.nwalk->answer, "%d", &wp.maxwa);
	wp.rwalk = (double)wp.maxwa;
    }
    /*rwalk = (double) maxwa; */

    if (wp.conv != 1.0)
	G_message(_("Using metric conversion factor %f, step=%f"), wp.conv,
		  wp.step);

    init_library_globals(&wp);

    if ((wp.tc == NULL) && (wp.et == NULL) && (wp.conc == NULL) && (wp.flux == NULL) &&
	(wp.erdep == NULL))
	G_warning(_("You are not outputting any raster or site files"));
    ret_val = input_data();
    if (ret_val != 1)
	G_fatal_error(_("Input failed"));

    alloc_grids_sediment();

    grad_check();
    init_grids_sediment();
    /* treba dat output pre topoerdep */
    main_loop();

    /* always true for sediment? */
    if (wp.tserie == NULL) {
	ii = output_data(0, 1.);
	if (ii != 1)
	    G_fatal_error(_("Cannot write raster maps"));
    }

    /* Exit with Success */
    exit(EXIT_SUCCESS);
}
Esempio n. 4
0
File: main.c Progetto: caomw/grass
int main(int argc, char *argv[])
{
    int col, row;

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

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

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

    G_gisinit(argv[0]);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

    /*  Get database window parameters  */

    G_get_window(&window);

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

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

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

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

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

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

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

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

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

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

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

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

    /*  Open input cell layers for reading  */

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

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

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

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

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

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

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

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


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

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

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


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

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

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

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

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

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


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


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

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

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

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

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

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

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

    exit(EXIT_SUCCESS);
}