int G_math_srand_auto(void) { return (int) G_srand48_auto(); }
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); }
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); }
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); }