main.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  1. /****************************************************************************
  2. *
  3. * MODULE: r.spread
  4. * AUTHOR(S): Jianping Xu, 1995 (original contributor)
  5. * Center for Remote Sensing and Spatial Analysis (CRSSA)
  6. * Rutgers University.
  7. * Andreas.Lange <andreas.lange rhein-main.de>, Eric G. Miller <egm2 jps.net>,
  8. * Markus Neteler <neteler itc.it>, Roberto Flor <flor itc.it>,
  9. * Brad Douglas <rez touchofmadness.com>,
  10. * Glynn Clements <glynn gclements.plus.com>, Jachym Cepicky <jachym les-ejk.cz>
  11. * PURPOSE:
  12. * This is the main program for simulating elliptical spread.
  13. *
  14. * It
  15. * 1) determines the earliest time a phenomenon REACHES to a
  16. * map cell, NOT the time that cell is EXHAUSTED.
  17. * 3) If a cell is spread barrier, a no-data value is assigned
  18. * to it.
  19. * COPYRIGHT: (C) 2000-2006 by the GRASS Development Team
  20. *
  21. * This program is free software under the GNU General Public
  22. * License (>=v2). Read the file COPYING that comes with GRASS
  23. * for details.
  24. *
  25. *****************************************************************************/
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <math.h>
  29. #include <sys/types.h>
  30. #include <unistd.h>
  31. #include <grass/gis.h>
  32. #include <grass/raster.h>
  33. #include <grass/glocale.h>
  34. #include "cmd_line.h"
  35. #include "costHa.h"
  36. #include "cell_ptrHa.h"
  37. #include "local_proto.h"
  38. #define DATA(map, r, c) (map)[(r) * ncols + (c)]
  39. CELL range_min, range_max;
  40. CELL *cell;
  41. CELL *x_cell;
  42. CELL *y_cell;
  43. CELL *map_max;
  44. CELL *map_dir;
  45. CELL *map_base;
  46. CELL *map_spotdist;
  47. CELL *map_velocity;
  48. CELL *map_mois;
  49. float *map_out;
  50. CELL *map_x_out;
  51. CELL *map_y_out;
  52. CELL *map_visit;
  53. char buf[400];
  54. float zero = 0.0;
  55. float neg = -2.0;
  56. int BARRIER = 0;
  57. int max_fd, dir_fd, base_fd, start_fd;
  58. int spotdist_fd, velocity_fd, mois_fd;
  59. int cum_fd, x_fd, y_fd;
  60. int nrows, ncols;
  61. long heap_len;
  62. struct Cell_head window;
  63. struct Range range;
  64. struct costHa *heap;
  65. int main(int argc, char *argv[])
  66. {
  67. int col, row;
  68. struct
  69. {
  70. struct Option *max, *dir, *base, *start,
  71. *spotdist, *velocity, *mois,
  72. *least, *comp_dens, *init_time,
  73. *time_lag, *backdrop, *out, *x_out, *y_out;
  74. } parm;
  75. struct
  76. {
  77. /* please, remove before GRASS 7 released */
  78. struct Flag *display, *spotting;
  79. } flag;
  80. struct GModule *module;
  81. /* initialize access to database and create temporary files */
  82. G_gisinit(argv[0]);
  83. /* Set description */
  84. module = G_define_module();
  85. G_add_keyword(_("raster"));
  86. G_add_keyword(_("fire"));
  87. module->label =
  88. _("Simulates elliptically anisotropic spread on a graphics window and "
  89. "generates a raster map of the cumulative time of spread, "
  90. "given raster maps containing the rates of spread (ROS), the ROS "
  91. "directions and the spread origins.");
  92. module->description =
  93. _("It optionally produces raster maps to contain backlink UTM "
  94. "coordinates for tracing spread paths.");
  95. parm.max = G_define_option();
  96. parm.max->key = "max";
  97. parm.max->type = TYPE_STRING;
  98. parm.max->required = YES;
  99. parm.max->gisprompt = "old,cell,raster";
  100. parm.max->guisection = _("Input maps");
  101. parm.max->description =
  102. _("Name of raster map containing MAX rate of spread (ROS) (cm/min)");
  103. parm.dir = G_define_option();
  104. parm.dir->key = "dir";
  105. parm.dir->type = TYPE_STRING;
  106. parm.dir->required = YES;
  107. parm.dir->gisprompt = "old,cell,raster";
  108. parm.dir->guisection = _("Input maps");
  109. parm.dir->description =
  110. _("Name of raster map containing DIRections of max ROS (degree)");
  111. parm.base = G_define_option();
  112. parm.base->key = "base";
  113. parm.base->type = TYPE_STRING;
  114. parm.base->required = YES;
  115. parm.base->gisprompt = "old,cell,raster";
  116. parm.base->guisection = _("Input maps");
  117. parm.base->description =
  118. _("Name of raster map containing BASE ROS (cm/min)");
  119. parm.start = G_define_option();
  120. parm.start->key = "start";
  121. parm.start->type = TYPE_STRING;
  122. parm.start->required = YES;
  123. parm.start->gisprompt = "old,cell,raster";
  124. parm.start->guisection = _("Input maps");
  125. parm.start->description =
  126. _("Name of raster map containing STARTing sources");
  127. parm.spotdist = G_define_option();
  128. parm.spotdist->key = "spot_dist";
  129. parm.spotdist->type = TYPE_STRING;
  130. parm.spotdist->gisprompt = "old,cell,raster";
  131. parm.spotdist->guisection = _("Input maps");
  132. parm.spotdist->description =
  133. _("Name of raster map containing max SPOTting DISTance (m) (required w/ -s)");
  134. parm.velocity = G_define_option();
  135. parm.velocity->key = "w_speed";
  136. parm.velocity->type = TYPE_STRING;
  137. parm.velocity->gisprompt = "old,cell,raster";
  138. parm.velocity->guisection = _("Input maps");
  139. parm.velocity->description =
  140. _("Name of raster map containing midflame Wind SPEED (ft/min) (required w/ -s)");
  141. parm.mois = G_define_option();
  142. parm.mois->key = "f_mois";
  143. parm.mois->type = TYPE_STRING;
  144. parm.mois->gisprompt = "old,cell,raster";
  145. parm.mois->guisection = _("Input maps");
  146. parm.mois->description =
  147. _("Name of raster map containing fine Fuel MOISture of the cell receiving a spotting firebrand (%) (required w/ -s)");
  148. parm.least = G_define_option();
  149. parm.least->key = "least_size";
  150. parm.least->type = TYPE_STRING;
  151. parm.least->key_desc = "odd int";
  152. parm.least->options = "3,5,7,9,11,13,15";
  153. parm.least->description =
  154. _("Basic sampling window SIZE needed to meet certain accuracy (3)");
  155. parm.comp_dens = G_define_option();
  156. parm.comp_dens->key = "comp_dens";
  157. parm.comp_dens->type = TYPE_STRING;
  158. parm.comp_dens->key_desc = "decimal";
  159. parm.comp_dens->description =
  160. _("Sampling DENSity for additional COMPutin (range: 0.0 - 1.0 (0.5))");
  161. parm.init_time = G_define_option();
  162. parm.init_time->key = "init_time";
  163. parm.init_time->type = TYPE_STRING;
  164. parm.init_time->key_desc = "int (>= 0)";
  165. parm.init_time->description =
  166. _("INITial TIME for current simulation (0) (min)");
  167. parm.time_lag = G_define_option();
  168. parm.time_lag->key = "lag";
  169. parm.time_lag->type = TYPE_STRING;
  170. parm.time_lag->key_desc = "int (>= 0)";
  171. parm.time_lag->description =
  172. _("Simulating time duration LAG (fill the region) (min)");
  173. parm.backdrop = G_define_option();
  174. parm.backdrop->key = "backdrop";
  175. parm.backdrop->type = TYPE_STRING;
  176. parm.backdrop->gisprompt = "old,cell,raster";
  177. parm.backdrop->description =
  178. _("Name of raster map as a display backdrop");
  179. parm.out = G_define_option();
  180. parm.out->key = "output";
  181. parm.out->type = TYPE_STRING;
  182. parm.out->required = YES;
  183. parm.out->gisprompt = "new,cell,raster";
  184. parm.out->guisection = _("Output maps");
  185. parm.out->description =
  186. _("Name of raster map to contain OUTPUT spread time (min)");
  187. parm.x_out = G_define_option();
  188. parm.x_out->key = "x_output";
  189. parm.x_out->type = TYPE_STRING;
  190. parm.x_out->gisprompt = "new,cell,raster";
  191. parm.x_out->guisection = _("Output maps");
  192. parm.x_out->description =
  193. _("Name of raster map to contain X_BACK coordinates");
  194. parm.y_out = G_define_option();
  195. parm.y_out->key = "y_output";
  196. parm.y_out->type = TYPE_STRING;
  197. parm.y_out->gisprompt = "new,cell,raster";
  198. parm.y_out->guisection = _("Output maps");
  199. parm.y_out->description =
  200. _("Name of raster map to contain Y_BACK coordinates");
  201. flag.display = G_define_flag();
  202. flag.display->key = 'd';
  203. #if 0
  204. flag.display->description = _("DISPLAY 'live' spread process on screen");
  205. #else
  206. flag.display->description = _("Live display - currently DISABLED");
  207. #endif
  208. flag.spotting = G_define_flag();
  209. flag.spotting->key = 's';
  210. flag.spotting->description = _("For wildfires: consider SPOTTING effect");
  211. /* Parse command line */
  212. if (G_parser(argc, argv))
  213. exit(EXIT_FAILURE);
  214. srand(getpid());
  215. display = flag.display->answer;
  216. #if 1
  217. if (display)
  218. G_fatal_error(_("The display feature is disabled"));
  219. #endif
  220. spotting = flag.spotting->answer;
  221. max_layer = parm.max->answer;
  222. dir_layer = parm.dir->answer;
  223. base_layer = parm.base->answer;
  224. start_layer = parm.start->answer;
  225. backdrop_layer = parm.backdrop->answer;
  226. out_layer = parm.out->answer;
  227. if (parm.x_out->answer) {
  228. x_out = 1;
  229. x_out_layer = parm.x_out->answer;
  230. }
  231. if (parm.y_out->answer) {
  232. y_out = 1;
  233. y_out_layer = parm.y_out->answer;
  234. }
  235. if (spotting) {
  236. if (!
  237. (parm.spotdist->answer && parm.velocity->answer &&
  238. parm.mois->answer)) {
  239. G_warning
  240. ("SPOTTING DISTANCE, fuel MOISTURE, or wind VELOCITY map not given w/ -s");
  241. G_usage();
  242. exit(EXIT_FAILURE);
  243. }
  244. else {
  245. spotdist_layer = parm.spotdist->answer;
  246. velocity_layer = parm.velocity->answer;
  247. mois_layer = parm.mois->answer;
  248. }
  249. }
  250. /*Check the given the least sampling size, assign the default if needed */
  251. if (parm.least->answer)
  252. least = atoi(parm.least->answer);
  253. else
  254. least = 3;
  255. /*Check the given computing density, assign the default if needed */
  256. if (parm.comp_dens->answer) {
  257. comp_dens = atof(parm.comp_dens->answer);
  258. if (comp_dens < 0.0 || comp_dens > 1.0) {
  259. G_warning("Illegal computing density <%s>",
  260. parm.comp_dens->answer);
  261. G_usage();
  262. exit(EXIT_FAILURE);
  263. }
  264. }
  265. else {
  266. comp_dens = 0.5;
  267. }
  268. /*Check the given initial time and simulation time lag, assign the default if needed */
  269. if (parm.init_time->answer) {
  270. init_time = atoi(parm.init_time->answer);
  271. if (init_time < 0) {
  272. G_warning("Illegal initial time <%s>", parm.init_time->answer);
  273. G_usage();
  274. exit(EXIT_FAILURE);
  275. }
  276. }
  277. else {
  278. time_lag = 0;
  279. }
  280. if (parm.time_lag->answer) {
  281. time_lag = atoi(parm.time_lag->answer);
  282. if (time_lag < 0) {
  283. G_warning("Illegal simulating time lag <%s>",
  284. parm.time_lag->answer);
  285. G_usage();
  286. exit(EXIT_FAILURE);
  287. }
  288. }
  289. else {
  290. time_lag = 99999;
  291. }
  292. /* Get database window parameters */
  293. G_get_window(&window);
  294. /* find number of rows and columns in window */
  295. nrows = Rast_window_rows();
  296. ncols = Rast_window_cols();
  297. /*transfor measurement unit from meters to centimeters due to ROS unit
  298. *if the input ROSs are in m/min units, cancell the following*/
  299. window.ns_res = 100 * window.ns_res;
  300. window.ew_res = 100 * window.ew_res;
  301. /* Initialize display screens */
  302. #if 0
  303. if (display)
  304. display_init();
  305. #endif
  306. /* Check if input layers exists in data base */
  307. if (G_find_raster2(max_layer, "") == NULL)
  308. G_fatal_error("Raster map <%s> not found", max_layer);
  309. if (G_find_raster2(dir_layer, "") == NULL)
  310. G_fatal_error(_("Raster map <%s> not found"), dir_layer);
  311. if (G_find_raster2(base_layer, "") == NULL)
  312. G_fatal_error(_("Raster map <%s> not found"), base_layer);
  313. if (G_find_raster2(start_layer, "") == NULL)
  314. G_fatal_error(_("Raster map <%s> not found"), start_layer);
  315. if (spotting) {
  316. if (G_find_raster2(spotdist_layer, "") == NULL)
  317. G_fatal_error(_("Raster map <%s> not found"), spotdist_layer);
  318. if (G_find_raster2(velocity_layer, "") == NULL)
  319. G_fatal_error(_("Raster map <%s> not found"), velocity_layer);
  320. if (G_find_raster2(mois_layer, "") == NULL)
  321. G_fatal_error(_("Raster map <%s> not found"), mois_layer);
  322. }
  323. /* Open input cell layers for reading */
  324. max_fd = Rast_open_old(max_layer, G_find_raster2(max_layer, ""));
  325. dir_fd = Rast_open_old(dir_layer, G_find_raster2(dir_layer, ""));
  326. base_fd = Rast_open_old(base_layer, G_find_raster2(base_layer, ""));
  327. if (spotting) {
  328. spotdist_fd =
  329. Rast_open_old(spotdist_layer, G_find_raster2(spotdist_layer, ""));
  330. velocity_fd =
  331. Rast_open_old(velocity_layer, G_find_raster2(velocity_layer, ""));
  332. mois_fd = Rast_open_old(mois_layer, G_find_raster2(mois_layer, ""));
  333. }
  334. /* Allocate memories for a row */
  335. cell = Rast_allocate_c_buf();
  336. if (x_out)
  337. x_cell = Rast_allocate_c_buf();
  338. if (y_out)
  339. y_cell = Rast_allocate_c_buf();
  340. /* Allocate memories for a map */
  341. map_max = (CELL *) G_calloc(nrows * ncols + 1, sizeof(CELL));
  342. map_dir = (CELL *) G_calloc(nrows * ncols + 1, sizeof(CELL));
  343. map_base = (CELL *) G_calloc(nrows * ncols + 1, sizeof(CELL));
  344. map_visit = (CELL *) G_calloc(nrows * ncols + 1, sizeof(CELL));
  345. map_out = (float *)G_calloc(nrows * ncols + 1, sizeof(float));
  346. if (spotting) {
  347. map_spotdist = (CELL *) G_calloc(nrows * ncols + 1, sizeof(CELL));
  348. map_velocity = (CELL *) G_calloc(nrows * ncols + 1, sizeof(CELL));
  349. map_mois = (CELL *) G_calloc(nrows * ncols + 1, sizeof(CELL));
  350. }
  351. if (x_out)
  352. map_x_out = (CELL *) G_calloc(nrows * ncols + 1, sizeof(CELL));
  353. if (y_out)
  354. map_y_out = (CELL *) G_calloc(nrows * ncols + 1, sizeof(CELL));
  355. /* Write the input layers in the map "arrays" */
  356. G_message(_("Reading inputs..."));
  357. for (row = 0; row < nrows; row++) {
  358. G_percent(row, nrows, 2);
  359. Rast_get_c_row(max_fd, cell, row);
  360. for (col = 0; col < ncols; col++)
  361. DATA(map_max, row, col) = cell[col];
  362. Rast_get_c_row(dir_fd, cell, row);
  363. for (col = 0; col < ncols; col++)
  364. DATA(map_dir, row, col) = cell[col];
  365. Rast_get_c_row(base_fd, cell, row);
  366. for (col = 0; col < ncols; col++)
  367. DATA(map_base, row, col) = cell[col];
  368. if (spotting) {
  369. Rast_get_c_row(spotdist_fd, cell, row);
  370. for (col = 0; col < ncols; col++)
  371. DATA(map_spotdist, row, col) = cell[col];
  372. Rast_get_c_row(velocity_fd, cell, row);
  373. for (col = 0; col < ncols; col++)
  374. DATA(map_velocity, row, col) = cell[col];
  375. Rast_get_c_row(mois_fd, cell, row);
  376. for (col = 0; col < ncols; col++)
  377. DATA(map_mois, row, col) = cell[col];
  378. }
  379. }
  380. G_percent(row, nrows, 2);
  381. /* Scan the START layer searching for starting points.
  382. * Create an array of starting points (min_heap) ordered by costs.
  383. */
  384. start_fd = Rast_open_old(start_layer, G_find_raster2(start_layer, ""));
  385. Rast_read_range(start_layer, G_find_file("cell", start_layer, ""), &range);
  386. Rast_get_range_min_max(&range, &range_min, &range_max);
  387. /* Initialize the heap */
  388. heap =
  389. (struct costHa *)G_calloc(nrows * ncols + 1, sizeof(struct costHa));
  390. heap_len = 0;
  391. G_message(_("Reading %s..."), start_layer);
  392. G_debug(1, "Collecting origins...");
  393. collect_ori(start_fd);
  394. G_debug(1, "Done");
  395. /* Major computation of spread time */
  396. G_debug(1, "Spreading...");
  397. spread();
  398. G_debug(1, "Done");
  399. /* Open cumulative cost layer (and x, y direction layers) for writing */
  400. cum_fd = Rast_open_c_new(out_layer);
  401. if (x_out)
  402. x_fd = Rast_open_c_new(x_out_layer);
  403. if (y_out)
  404. y_fd = Rast_open_c_new(y_out_layer);
  405. /* prepare output -- adjust from cm to m */
  406. window.ew_res = window.ew_res / 100;
  407. window.ns_res = window.ns_res / 100;
  408. /* copy maps in ram to output maps */
  409. ram2out();
  410. G_free(map_max);
  411. G_free(map_dir);
  412. G_free(map_base);
  413. G_free(map_out);
  414. G_free(map_visit);
  415. if (x_out)
  416. G_free(map_x_out);
  417. if (y_out)
  418. G_free(map_y_out);
  419. if (spotting) {
  420. G_free(map_spotdist);
  421. G_free(map_mois);
  422. G_free(map_velocity);
  423. }
  424. Rast_close(max_fd);
  425. Rast_close(dir_fd);
  426. Rast_close(base_fd);
  427. Rast_close(start_fd);
  428. Rast_close(cum_fd);
  429. if (x_out)
  430. Rast_close(x_fd);
  431. if (y_out)
  432. Rast_close(y_fd);
  433. if (spotting) {
  434. Rast_close(spotdist_fd);
  435. Rast_close(velocity_fd);
  436. Rast_close(mois_fd);
  437. }
  438. /* close graphics */
  439. #if 0
  440. if (display)
  441. display_close();
  442. #endif
  443. exit(EXIT_SUCCESS);
  444. }