main.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703
  1. /****************************************************************************
  2. *
  3. * MODULE: r.viewshed
  4. *
  5. * AUTHOR(S): Laura Toma, Bowdoin College - ltoma@bowdoin.edu
  6. * Yi Zhuang - yzhuang@bowdoin.edu
  7. *
  8. * Ported to GRASS by William Richard -
  9. * wkrichar@bowdoin.edu or willster3021@gmail.com
  10. * Markus Metz: surface interpolation
  11. *
  12. * Date: July 2008; April 2011
  13. *
  14. * PURPOSE: To calculate the viewshed (the visible cells in the
  15. * raster) for the given viewpoint (observer) location. The
  16. * visibility model is the following: Two points in the raster are
  17. * considered visible to each other if the cells where they belong are
  18. * visible to each other. Two cells are visible to each other if the
  19. * line-of-sight that connects their centers does not intersect the
  20. * terrain. The terrain is NOT viewed as a tesselation of flat cells,
  21. * i.e. if the line-of-sight does not pass through the cell center,
  22. * elevation is determined using bilinear interpolation.
  23. * The viewshed algorithm is efficient both in
  24. * terms of CPU operations and I/O operations. It has worst-case
  25. * complexity O(n lg n) in the RAM model and O(sort(n)) in the
  26. * I/O-model. For the algorithm and all the other details see the
  27. * paper: "Computing Visibility on * Terrains in External Memory" by
  28. * Herman Haverkort, Laura Toma and Yi Zhuang.
  29. *
  30. * COPYRIGHT: (C) 2008-2011 by the GRASS Development Team
  31. *
  32. * This program is free software under the GNU General Public License
  33. * (>=v2). Read the file COPYING that comes with GRASS for details.
  34. *
  35. *****************************************************************************/
  36. #include <stdlib.h>
  37. #include <stdio.h>
  38. #include <string.h>
  39. #include <ctype.h>
  40. #include <unistd.h>
  41. extern "C"
  42. {
  43. #include <grass/config.h>
  44. #include <grass/gis.h>
  45. #include <grass/glocale.h>
  46. }
  47. #include "grass.h"
  48. #include <grass/iostream/ami.h>
  49. #include "viewshed.h"
  50. #include "visibility.h"
  51. #include "grid.h"
  52. #include "rbbst.h"
  53. #include "statusstructure.h"
  54. #include "distribute.h"
  55. /* if the user does not specify how much memory is available for the
  56. program, this is the default value used (in bytes) */
  57. #define DEFAULT_MEMORY 500<<20
  58. /* observer elevation above the terrain */
  59. #define DEFAULT_OBS_ELEVATION 0
  60. /* All these flags are used for debugging */
  61. /* if this flag is set, it always runs in memory */
  62. //#define FORCE_INTERNAL
  63. /* if this is set, it runs in external memory, even if the problem is
  64. small enough to fit in memory. In external memory it first tries
  65. to run the base-case, then recursion. */
  66. //#define FORCE_EXTERNAL
  67. /* if this flag is set it runs in external memory, and starts
  68. recursion without checking the base-case. */
  69. //#define FORCE_DISTRIBUTION
  70. /* ------------------------------------------------------------ */
  71. /* forward declarations */
  72. /* ------------------------------------------------------------ */
  73. void print_timings_internal(Rtimer sweepTime, Rtimer outputTime,
  74. Rtimer totalTime);
  75. void print_timings_external_memory(Rtimer totalTime, Rtimer viewshedTime,
  76. Rtimer outputTime, Rtimer sortOutputTime);
  77. void parse_args(int argc, char *argv[], int *vpRow, int *vpCol,
  78. ViewOptions * viewOptions, long long *memSizeBytes,
  79. Cell_head * window);
  80. /* ------------------------------------------------------------ */
  81. int main(int argc, char *argv[])
  82. {
  83. /* GRASS initialization stuff */
  84. struct GModule *module;
  85. /*initialize GIS environment */
  86. G_gisinit(argv[0]);
  87. /*initialize module */
  88. module = G_define_module();
  89. G_add_keyword(_("raster"));
  90. G_add_keyword(_("viewshed"));
  91. G_add_keyword(_("line of sight"));
  92. G_add_keyword(_("LOS"));
  93. module->label = _("Computes the viewshed of a point on an elevation raster map.");
  94. module->description = _("Default format: NULL (invisible), vertical angle wrt viewpoint (visible).");
  95. struct Cell_head region;
  96. Rast_get_window(&region);
  97. /* ************************************************************ */
  98. /* parameters set up */
  99. long long memSizeBytes = DEFAULT_MEMORY;
  100. /* the maximum size of main memory that the program ca use. The
  101. user can specify it, otherwise the default value of 500MB is
  102. used. The program uses this value to decied in which mode to
  103. run --- in internal memory, or external memory. */
  104. int vpRow, vpCol;
  105. /* the coordinates of the viewpoint in the raster; right now the
  106. algorithm assumes that the viewpoint is inside the grid, though
  107. this is not necessary; some changes will be needed to make it
  108. work with a viewpoint outside the terrain */
  109. ViewOptions viewOptions;
  110. //viewOptions.inputfname = (char*)malloc(500);
  111. //viewOptions.outputfname = (char*)malloc(500);
  112. //assert(inputfname && outputfname);
  113. viewOptions.obsElev = DEFAULT_OBS_ELEVATION;
  114. viewOptions.maxDist = INFINITY_DISTANCE;
  115. viewOptions.outputMode = OUTPUT_ANGLE;
  116. viewOptions.doCurv = FALSE;
  117. viewOptions.doRefr = FALSE;
  118. viewOptions.refr_coef = 1.0/7.0;
  119. parse_args(argc, argv, &vpRow, &vpCol, &viewOptions, &memSizeBytes,
  120. &region);
  121. /* set viewpoint with the coordinates specified by user. The
  122. height of the viewpoint is not known at this point---it will be
  123. set during the execution of the algorithm */
  124. Viewpoint vp;
  125. set_viewpoint_coord(&vp, vpRow, vpCol);
  126. /* ************************************************************ */
  127. /* set up the header of the raster with all raster info and make
  128. sure the requested viewpoint is on the map */
  129. GridHeader *hd;
  130. hd = read_header(viewOptions.inputfname, &region);
  131. assert(hd);
  132. G_get_set_window(&(hd->window));
  133. /* LT: there is no need to exit if viewpoint is outside grid,
  134. the algorithm will work correctly in theory. But this
  135. requires some changes. To do. */
  136. if (!(vp.row < hd->nrows && vp.col < hd->ncols)) {
  137. /* unfortunately, we don't know the point coordinates now */
  138. G_warning(_("Region extent: north=%d, south=%d, east=%d, west=%d"),
  139. hd->window.north, hd->window.south, hd->window.east, hd->window.west);
  140. G_warning(_("Region extent: rows=%d, cols=%d"), hd->nrows, hd->ncols);
  141. G_warning(_("Viewpoint: row=%d, col=%d"), vp.row, vp.col);
  142. G_fatal_error(_("Viewpoint outside of computational region"));
  143. }
  144. /* set curvature params */
  145. viewOptions.cellsize = region.ew_res;
  146. double e2;
  147. G_get_ellipsoid_parameters(&viewOptions.ellps_a, &e2);
  148. if (viewOptions.ellps_a == 0) {
  149. /*according to r.los, this can be
  150. problematic, so we'll have a backup, hardcoded radius :-( */
  151. G_warning(_("Problems obtaining current ellipsoid parameters, using sphere (6370997.0)"));
  152. viewOptions.ellps_a = 6370997.00;
  153. }
  154. G_begin_distance_calculations();
  155. /* ************************************************************ */
  156. /* decide whether the computation of the viewshed will take place
  157. in-memory or in external memory */
  158. int IN_MEMORY;
  159. long long inmemSizeBytes = get_viewshed_memory_usage(hd);
  160. G_verbose_message(_("In-memory memory usage is %lld B (%d MB), \
  161. max mem allowed=%lld B(%dMB)"), inmemSizeBytes,
  162. (int)(inmemSizeBytes >> 20), memSizeBytes,
  163. (int)(memSizeBytes >> 20));
  164. if (inmemSizeBytes < memSizeBytes) {
  165. IN_MEMORY = 1;
  166. G_verbose_message("***** IN_MEMORY MODE *****");
  167. }
  168. else {
  169. G_verbose_message("***** EXTERNAL_MEMORY MODE *****");
  170. IN_MEMORY = 0;
  171. }
  172. /* the mode can be forced to in memory or external if the user
  173. wants to test or debug a specific mode */
  174. #ifdef FORCE_EXTERNAL
  175. IN_MEMORY = 0;
  176. G_debug(1, "FORCED EXTERNAL");
  177. #endif
  178. #ifdef FORCE_INTERNAL
  179. IN_MEMORY = 1;
  180. G_debug(1, "FORCED INTERNAL");
  181. #endif
  182. /* ************************************************************ */
  183. /* compute viewshed in memory */
  184. /* ************************************************************ */
  185. if (IN_MEMORY) {
  186. /*//////////////////////////////////////////////////// */
  187. /*/viewshed in internal memory */
  188. /*//////////////////////////////////////////////////// */
  189. Rtimer totalTime, outputTime, sweepTime;
  190. MemoryVisibilityGrid *visgrid;
  191. rt_start(totalTime);
  192. /*compute the viewshed and store it in visgrid */
  193. rt_start(sweepTime);
  194. visgrid =
  195. viewshed_in_memory(viewOptions.inputfname, hd, &vp, viewOptions);
  196. rt_stop(sweepTime);
  197. /* write the output */
  198. rt_start(outputTime);
  199. save_inmem_visibilitygrid(visgrid, viewOptions, vp);
  200. rt_stop(outputTime);
  201. rt_stop(totalTime);
  202. print_timings_internal(sweepTime, outputTime, totalTime);
  203. }
  204. /* ************************************************************ */
  205. /* compute viewshed in external memory */
  206. /* ************************************************************ */
  207. else {
  208. /* ************************************************************ */
  209. /* set up external memory mode */
  210. /* setup STREAM_DIR if not already set */
  211. char buf[1000];
  212. if (getenv(STREAM_TMPDIR) != NULL) {
  213. /*if already set */
  214. G_debug(1, "%s=%s", STREAM_TMPDIR, getenv(STREAM_TMPDIR));
  215. G_debug(1, "Intermediate stream location: %s",
  216. getenv(STREAM_TMPDIR));
  217. }
  218. else {
  219. /*set it */
  220. sprintf(buf, "%s=%s", STREAM_TMPDIR, viewOptions.streamdir);
  221. G_debug(1, "setting %s ", buf);
  222. putenv(buf);
  223. if (getenv(STREAM_TMPDIR) == NULL) {
  224. G_fatal_error(_("%s not set"), "STREAM_TMPDIR");
  225. exit(1);
  226. }
  227. else {
  228. G_debug(1, "are ok.");
  229. }
  230. }
  231. G_important_message(_("Intermediate files will not be deleted \
  232. in case of abnormal termination."));
  233. G_important_message(_("Intermediate location: %s"), viewOptions.streamdir);
  234. G_important_message(_("To save space delete these files manually!"));
  235. /* initialize IOSTREAM memory manager */
  236. MM_manager.set_memory_limit(memSizeBytes);
  237. MM_manager.ignore_memory_limit();
  238. MM_manager.print_limit_mode();
  239. /* ************************************************************ */
  240. /* BASE CASE OR DISTRIBUTION */
  241. /* determine whether base-case of external algorithm is enough,
  242. or recursion is necessary */
  243. int BASE_CASE = 0;
  244. if (get_active_str_size_bytes(hd) < memSizeBytes)
  245. BASE_CASE = 1;
  246. /*if the user set the FORCE_DISTRIBUTION flag, then the
  247. algorithm runs in the fuly recursive mode (even if this is
  248. not necessary). This is used solely for debugging purpses */
  249. #ifdef FORCE_DISTRIBUTION
  250. BASE_CASE = 0;
  251. #endif
  252. /* ************************************************************ */
  253. /* external memory, base case */
  254. /* ************************************************************ */
  255. if (BASE_CASE) {
  256. G_debug
  257. (1, "---Active structure small, starting base case---");
  258. Rtimer totalTime, viewshedTime, outputTime, sortOutputTime;
  259. rt_start(totalTime);
  260. /*run viewshed's algorithm */
  261. IOVisibilityGrid *visgrid;
  262. rt_start(viewshedTime);
  263. visgrid =
  264. viewshed_external(viewOptions.inputfname, hd, &vp,
  265. viewOptions);
  266. rt_stop(viewshedTime);
  267. /*sort output */
  268. rt_start(sortOutputTime);
  269. sort_io_visibilitygrid(visgrid);
  270. rt_stop(sortOutputTime);
  271. /*save output stream to file. */
  272. rt_start(outputTime);
  273. save_io_visibilitygrid(visgrid, viewOptions, vp);
  274. rt_stop(outputTime);
  275. rt_stop(totalTime);
  276. print_timings_external_memory(totalTime, viewshedTime,
  277. outputTime, sortOutputTime);
  278. }
  279. /************************************************************/
  280. /* external memory, recursive distribution sweeping recursion */
  281. /************************************************************ */
  282. else { /* if not BASE_CASE */
  283. #ifndef FORCE_DISTRIBUTION
  284. G_debug(1, "---Active structure does not fit in memory,");
  285. #else
  286. G_debug(1, "FORCED DISTRIBUTION");
  287. #endif
  288. Rtimer totalTime, sweepTime, outputTime, sortOutputTime;
  289. rt_start(totalTime);
  290. /*get the viewshed solution by distribution */
  291. IOVisibilityGrid *visgrid;
  292. rt_start(sweepTime);
  293. visgrid =
  294. distribute_and_sweep(viewOptions.inputfname, hd, &vp,
  295. viewOptions);
  296. rt_stop(sweepTime);
  297. /*sort the visibility grid so that it is in order when it is
  298. outputted */
  299. rt_start(sortOutputTime);
  300. sort_io_visibilitygrid(visgrid);
  301. rt_stop(sortOutputTime);
  302. rt_start(outputTime);
  303. save_io_visibilitygrid(visgrid, viewOptions, vp);
  304. rt_stop(outputTime);
  305. rt_stop(totalTime);
  306. print_timings_external_memory(totalTime, sweepTime,
  307. outputTime, sortOutputTime);
  308. }
  309. }
  310. /*end external memory, distribution sweep */
  311. /**************************************/
  312. /* FINISH UP, ALL CASES */
  313. /**************************************/
  314. /*close input file and free grid header */
  315. G_free(hd);
  316. /*following GRASS's coding standards for history and exiting */
  317. struct History history;
  318. Rast_short_history(viewOptions.outputfname, "raster", &history);
  319. Rast_command_history(&history);
  320. Rast_write_history(viewOptions.outputfname, &history);
  321. exit(EXIT_SUCCESS);
  322. }
  323. /* ------------------------------------------------------------ */
  324. /* parse arguments */
  325. void
  326. parse_args(int argc, char *argv[], int *vpRow, int *vpCol,
  327. ViewOptions * viewOptions, long long *memSizeBytes,
  328. Cell_head * window)
  329. {
  330. assert(vpRow && vpCol && memSizeBytes && window);
  331. /* the input */
  332. struct Option *inputOpt;
  333. inputOpt = G_define_standard_option(G_OPT_R_ELEV);
  334. inputOpt->key = "input";
  335. /* the output */
  336. struct Option *outputOpt;
  337. outputOpt = G_define_standard_option(G_OPT_R_OUTPUT);
  338. /* curvature flag */
  339. struct Flag *curvature;
  340. curvature = G_define_flag();
  341. curvature->key = 'c';
  342. curvature->description =
  343. _("Consider the curvature of the earth (current ellipsoid)");
  344. /* atmospheric refraction flag */
  345. struct Flag *refractionFlag;
  346. refractionFlag = G_define_flag();
  347. refractionFlag->key = 'r';
  348. refractionFlag->description =
  349. _("Consider the effect of atmospheric refraction");
  350. refractionFlag->guisection = _("Refraction");
  351. /* boolean output flag */
  352. struct Flag *booleanOutput;
  353. booleanOutput = G_define_flag();
  354. booleanOutput->key = 'b';
  355. booleanOutput->description =
  356. _("Output format is invisible = 0, visible = 1");
  357. booleanOutput->guisection = _("Output format");
  358. /* output mode = elevation flag */
  359. struct Flag *elevationFlag;
  360. elevationFlag = G_define_flag();
  361. elevationFlag->key = 'e';
  362. elevationFlag->description =
  363. _("Output format is invisible = NULL, else current elev - viewpoint_elev");
  364. elevationFlag->guisection = _("Output format");
  365. /* viewpoint coordinates */
  366. struct Option *viewLocOpt;
  367. viewLocOpt = G_define_standard_option(G_OPT_M_COORDS);
  368. viewLocOpt->required = YES;
  369. viewLocOpt->description = _("Coordinates of viewing position");
  370. /* observer elevation */
  371. struct Option *obsElevOpt;
  372. obsElevOpt = G_define_option();
  373. obsElevOpt->key = "observer_elevation";
  374. obsElevOpt->type = TYPE_DOUBLE;
  375. obsElevOpt->required = NO;
  376. obsElevOpt->key_desc = "value";
  377. obsElevOpt->description = _("Viewing elevation above the ground");
  378. obsElevOpt->answer = "1.75";
  379. obsElevOpt->guisection = _("Settings");
  380. /* target elevation offset */
  381. struct Option *tgtElevOpt;
  382. tgtElevOpt = G_define_option();
  383. tgtElevOpt->key = "target_elevation";
  384. tgtElevOpt->type = TYPE_DOUBLE;
  385. tgtElevOpt->required = NO;
  386. tgtElevOpt->key_desc = "value";
  387. tgtElevOpt->description = _("Offset for target elevation above the ground");
  388. tgtElevOpt->answer = "0.0";
  389. tgtElevOpt->guisection = _("Settings");
  390. /* max distance */
  391. struct Option *maxDistOpt;
  392. maxDistOpt = G_define_option();
  393. maxDistOpt->key = "max_distance";
  394. maxDistOpt->type = TYPE_DOUBLE;
  395. maxDistOpt->required = NO;
  396. maxDistOpt->key_desc = "value";
  397. maxDistOpt->description =
  398. _("Maximum visibility radius. By default infinity (-1)");
  399. char infdist[10];
  400. sprintf(infdist, "%d", INFINITY_DISTANCE);
  401. maxDistOpt->answer = infdist;
  402. maxDistOpt->guisection = _("Settings");
  403. /* atmospheric refraction coeff. 1/7 for visual, 0.325 for radio waves, ... */
  404. /* in future we might calculate this based on the physics, for now we
  405. just fudge by the 1/7th approximation.
  406. ?? See ??
  407. @article{yoeli1985making,
  408. title={The making of intervisibility maps with computer and plotter},
  409. author={Yoeli, Pinhas},
  410. journal={Cartographica: The International Journal for Geographic Information and Geovisualization},
  411. volume={22},
  412. number={3},
  413. pages={88--103},
  414. year={1985},
  415. publisher={UT Press}
  416. }
  417. */
  418. struct Option *refrCoeffOpt;
  419. refrCoeffOpt = G_define_option();
  420. refrCoeffOpt->key = "refraction_coeff";
  421. refrCoeffOpt->description = _("Refraction coefficient");
  422. refrCoeffOpt->type = TYPE_DOUBLE;
  423. refrCoeffOpt->required = NO;
  424. refrCoeffOpt->answer = "0.14286";
  425. refrCoeffOpt->options = "0.0-1.0";
  426. refrCoeffOpt->guisection = _("Refraction");
  427. /* memory size */
  428. struct Option *memAmountOpt;
  429. memAmountOpt = G_define_option();
  430. memAmountOpt->key = "memory";
  431. memAmountOpt->type = TYPE_INTEGER;
  432. memAmountOpt->required = NO;
  433. memAmountOpt->key_desc = "value";
  434. memAmountOpt->description =
  435. _("Amount of memory to use in MB");
  436. memAmountOpt->answer = "500";
  437. /* temporary STREAM path */
  438. struct Option *streamdirOpt;
  439. streamdirOpt = G_define_option() ;
  440. streamdirOpt->key = "directory";
  441. streamdirOpt->type = TYPE_STRING;
  442. streamdirOpt->required = NO;
  443. //streamdirOpt->answer = "";
  444. streamdirOpt->description=
  445. _("Directory to hold temporary files (they can be large)");
  446. /*fill the options and flags with G_parser */
  447. if (G_parser(argc, argv))
  448. exit(EXIT_FAILURE);
  449. /* store the parameters into a structure to be used along the way */
  450. strcpy(viewOptions->inputfname, inputOpt->answer);
  451. strcpy(viewOptions->outputfname, outputOpt->answer);
  452. if (!streamdirOpt->answer) {
  453. const char *tmpdir = G_tempfile();
  454. if (G_mkdir(tmpdir) == -1)
  455. G_fatal_error(_("Unable to create temp dir"));
  456. strcpy(viewOptions->streamdir, tmpdir);
  457. }
  458. else
  459. strcpy(viewOptions->streamdir,streamdirOpt->answer);
  460. viewOptions->obsElev = atof(obsElevOpt->answer);
  461. if(tgtElevOpt->answer)
  462. viewOptions->tgtElev = atof(tgtElevOpt->answer);
  463. viewOptions->maxDist = atof(maxDistOpt->answer);
  464. if (viewOptions->maxDist < 0 && viewOptions->maxDist != INFINITY_DISTANCE) {
  465. G_fatal_error(_("A negative max distance value is not allowed"));
  466. }
  467. viewOptions->doCurv = curvature->answer;
  468. viewOptions->doRefr = refractionFlag->answer;
  469. if (refractionFlag->answer && !curvature->answer)
  470. G_fatal_error(_("Atmospheric refraction is only calculated with "
  471. "respect to the curvature of the Earth. "
  472. "Enable the -c flag as well."));
  473. viewOptions->refr_coef = atof(refrCoeffOpt->answer);
  474. if (booleanOutput->answer)
  475. viewOptions->outputMode = OUTPUT_BOOL;
  476. else if (elevationFlag->answer)
  477. viewOptions->outputMode = OUTPUT_ELEV;
  478. else
  479. viewOptions->outputMode = OUTPUT_ANGLE;
  480. int memSizeMB = atoi(memAmountOpt->answer);
  481. if (memSizeMB < 0) {
  482. G_warning(_("Amount of memory cannot be negative."));
  483. G_warning(_(" Converting %d to %d MB"), memSizeMB, -memSizeMB);
  484. memSizeMB = -memSizeMB;
  485. }
  486. *memSizeBytes = (long long)memSizeMB;
  487. *memSizeBytes = (*memSizeBytes) << 20;
  488. G_get_set_window(window);
  489. /*The algorithm runs with the viewpoint row and col, so we need to
  490. convert the lat-lon coordinates to row and column format */
  491. *vpRow = (int)Rast_northing_to_row(atof(viewLocOpt->answers[1]), window);
  492. *vpCol = (int)Rast_easting_to_col(atof(viewLocOpt->answers[0]), window);
  493. G_debug(3, "viewpoint converted from current projection: (%.3f, %.3f) to col, row (%d, %d)",
  494. atof(viewLocOpt->answers[0]), atof(viewLocOpt->answers[1]), *vpCol, *vpRow);
  495. return;
  496. }
  497. /* ------------------------------------------------------------ */
  498. /*print the timings for the internal memory method of computing the
  499. viewshed */
  500. void
  501. print_timings_internal(Rtimer sweepTime, Rtimer outputTime, Rtimer totalTime)
  502. {
  503. char timeused[100];
  504. G_verbose_message("TOTAL TIMING:");
  505. rt_sprint_safe(timeused, sweepTime);
  506. G_verbose_message("Sweep: %s", timeused);
  507. G_verbose_message("\n");
  508. rt_sprint_safe(timeused, outputTime);
  509. G_verbose_message("Output: %s", timeused);
  510. G_verbose_message("\n");
  511. rt_sprint_safe(timeused, totalTime);
  512. G_verbose_message("Total: %s", timeused);
  513. G_verbose_message("\n");
  514. }
  515. /* ------------------------------------------------------------ */
  516. /*print the timings for the external memory method of solving the viewshed */
  517. void
  518. print_timings_external_memory(Rtimer totalTime, Rtimer viewshedTime,
  519. Rtimer outputTime, Rtimer sortOutputTime)
  520. {
  521. /*print timings */
  522. char timeused[100];
  523. G_verbose_message("\n\nTOTAL TIMING:");
  524. rt_sprint_safe(timeused, viewshedTime);
  525. G_verbose_message("Total sweep: %s", timeused);
  526. rt_sprint_safe(timeused, sortOutputTime);
  527. G_verbose_message("Sort output: %s", timeused);
  528. rt_sprint_safe(timeused, outputTime);
  529. G_verbose_message("Write result grid: %s", timeused);
  530. rt_sprint_safe(timeused, totalTime);
  531. G_verbose_message("Total Time: %s", timeused);
  532. G_verbose_message("\n\n");
  533. return;
  534. }