visibility.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. /****************************************************************************
  2. *
  3. * MODULE: r.viewshed
  4. *
  5. * AUTHOR(S): Laura Toma, Bowdoin College - ltoma@bowdoin.edu
  6. * Yi Zhuang - yzhuang@bowdoin.edu
  7. * Ported to GRASS by William Richard -
  8. * wkrichar@bowdoin.edu or willster3021@gmail.com
  9. * Markus Metz: surface interpolation
  10. *
  11. * Date: april 2011
  12. *
  13. * PURPOSE: To calculate the viewshed (the visible cells in the
  14. * raster) for the given viewpoint (observer) location. The
  15. * visibility model is the following: Two points in the raster are
  16. * considered visible to each other if the cells where they belong are
  17. * visible to each other. Two cells are visible to each other if the
  18. * line-of-sight that connects their centers does not intersect the
  19. * terrain. The terrain is NOT viewed as a tesselation of flat cells,
  20. * i.e. if the line-of-sight does not pass through the cell center,
  21. * elevation is determined using bilinear interpolation.
  22. * The viewshed algorithm is efficient both in
  23. * terms of CPU operations and I/O operations. It has worst-case
  24. * complexity O(n lg n) in the RAM model and O(sort(n)) in the
  25. * I/O-model. For the algorithm and all the other details see the
  26. * paper: "Computing Visibility on * Terrains in External Memory" by
  27. * Herman Haverkort, Laura Toma and Yi Zhuang.
  28. *
  29. * COPYRIGHT: (C) 2008 by the GRASS Development Team
  30. *
  31. * This program is free software under the GNU General Public License
  32. * (>=v2). Read the file COPYING that comes with GRASS for details.
  33. *
  34. *****************************************************************************/
  35. #include <stdio.h>
  36. extern "C"
  37. {
  38. #include <grass/gis.h>
  39. #include <grass/glocale.h>
  40. }
  41. #include "grid.h"
  42. #include "visibility.h"
  43. #include "grass.h"
  44. /* ------------------------------------------------------------ */
  45. /* viewpoint functions */
  46. void print_viewpoint(Viewpoint vp)
  47. {
  48. G_debug(3, "vp=(%d, %d, %.1f) ", vp.row, vp.col, vp.elev);
  49. return;
  50. }
  51. /* ------------------------------------------------------------ */
  52. void set_viewpoint_coord(Viewpoint * vp, dimensionType row, dimensionType col)
  53. {
  54. assert(vp);
  55. vp->row = row;
  56. vp->col = col;
  57. return;
  58. }
  59. /* ------------------------------------------------------------ */
  60. void set_viewpoint_elev(Viewpoint * vp, float elev)
  61. {
  62. assert(vp);
  63. vp->elev = elev;
  64. return;
  65. }
  66. /* ------------------------------------------------------------ */
  67. /*copy from b to a */
  68. void copy_viewpoint(Viewpoint * a, Viewpoint b)
  69. {
  70. assert(a);
  71. a->row = b.row;
  72. a->col = b.col;
  73. a->elev = b.elev;
  74. return;
  75. }
  76. /* ------------------------------------------------------------ */
  77. /* MemoryVisibilityGrid functions */
  78. /* create and return a grid of the sizes specified in the header */
  79. MemoryVisibilityGrid *create_inmem_visibilitygrid(GridHeader hd, Viewpoint vp)
  80. {
  81. MemoryVisibilityGrid *visgrid;
  82. visgrid = (MemoryVisibilityGrid *) G_malloc(sizeof(MemoryVisibilityGrid));
  83. assert(visgrid);
  84. /* create the grid */
  85. visgrid->grid = create_empty_grid();
  86. assert(visgrid->grid);
  87. /* create the header */
  88. visgrid->grid->hd = (GridHeader *) G_malloc(sizeof(GridHeader));
  89. assert(visgrid->grid->hd);
  90. /* set the header */
  91. copy_header(visgrid->grid->hd, hd);
  92. /* allocate the Grid data */
  93. alloc_grid_data(visgrid->grid);
  94. /*allocate viewpoint */
  95. visgrid->vp = (Viewpoint *) G_malloc(sizeof(Viewpoint));
  96. assert(visgrid->vp);
  97. copy_viewpoint(visgrid->vp, vp);
  98. return visgrid;
  99. }
  100. /* ------------------------------------------------------------ */
  101. void free_inmem_visibilitygrid(MemoryVisibilityGrid * visgrid)
  102. {
  103. assert(visgrid);
  104. if (visgrid->grid) {
  105. destroy_grid(visgrid->grid);
  106. }
  107. if (visgrid->vp) {
  108. G_free(visgrid->vp);
  109. }
  110. G_free(visgrid);
  111. return;
  112. }
  113. /* ------------------------------------------------------------ */
  114. /*set all values of visgrid's Grid to the given value */
  115. void set_inmem_visibilitygrid(MemoryVisibilityGrid * visgrid, float val)
  116. {
  117. assert(visgrid && visgrid->grid && visgrid->grid->hd &&
  118. visgrid->grid->grid_data);
  119. dimensionType i, j;
  120. for (i = 0; i < visgrid->grid->hd->nrows; i++) {
  121. assert(visgrid->grid->grid_data[i]);
  122. for (j = 0; j < visgrid->grid->hd->ncols; j++) {
  123. visgrid->grid->grid_data[i][j] = val;
  124. }
  125. }
  126. return;
  127. }
  128. /* ------------------------------------------------------------ */
  129. /*set the (i,j) value of visgrid's Grid to the given value */
  130. void add_result_to_inmem_visibilitygrid(MemoryVisibilityGrid * visgrid,
  131. dimensionType i, dimensionType j,
  132. float val)
  133. {
  134. assert(visgrid && visgrid->grid && visgrid->grid->hd &&
  135. visgrid->grid->grid_data);
  136. assert(i < visgrid->grid->hd->nrows);
  137. assert(j < visgrid->grid->hd->ncols);
  138. assert(visgrid->grid->grid_data[i]);
  139. visgrid->grid->grid_data[i][j] = val;
  140. return;
  141. }
  142. /* ------------------------------------------------------------ */
  143. /* The following functions are used to convert the visibility results
  144. recorded during the viewshed computation into the output grid into
  145. tehe output required by the user.
  146. x is assumed to be the visibility value computed for a cell during the
  147. viewshed computation.
  148. The value computed during the viewshed is the following:
  149. x is NODATA if the cell is NODATA;
  150. x is INVISIBLE if the cell is invisible;
  151. x is the vertical angle of the cell wrt the viewpoint if the cell is
  152. visible---the angle is a value in (0,180).
  153. */
  154. int is_visible(float x)
  155. {
  156. /* if GRASS is on, we cannot guarantee that NODATA is negative; so
  157. we need to check */
  158. int isnull = Rast_is_null_value(&x, G_SURFACE_TYPE);
  159. if (isnull)
  160. return 0;
  161. else
  162. return (x >= 0);
  163. }
  164. int is_invisible_not_nodata(float x)
  165. {
  166. return ((int)x == (int)INVISIBLE);
  167. }
  168. int is_invisible_nodata(float x)
  169. {
  170. return (!is_visible(x)) && (!is_invisible_not_nodata(x));
  171. }
  172. /* ------------------------------------------------------------ */
  173. /* This function is called when the program runs in
  174. viewOptions.outputMode == OUTPUT_BOOL. */
  175. float booleanVisibilityOutput(float x)
  176. {
  177. /* NODATA and INVISIBLE are both negative values */
  178. if (is_visible(x))
  179. return BOOL_VISIBLE;
  180. else
  181. return BOOL_INVISIBLE;
  182. }
  183. /* ------------------------------------------------------------ */
  184. /* This function is called when the program runs in
  185. viewOptions.outputMode == OUTPUT_ANGLE. In this case x represents
  186. the right value. */
  187. float angleVisibilityOutput(float x)
  188. {
  189. return x;
  190. }
  191. /* ------------------------------------------------------------ */
  192. /* visgrid is the structure that records the visibility information
  193. after the sweep is done. Use it to write the visibility output
  194. grid and then distroy it.
  195. */
  196. void save_inmem_visibilitygrid(MemoryVisibilityGrid * visgrid,
  197. ViewOptions viewOptions, Viewpoint vp)
  198. {
  199. if (viewOptions.outputMode == OUTPUT_BOOL)
  200. save_grid_to_GRASS(visgrid->grid, viewOptions.outputfname, CELL_TYPE,
  201. booleanVisibilityOutput);
  202. else if (viewOptions.outputMode == OUTPUT_ANGLE)
  203. save_grid_to_GRASS(visgrid->grid, viewOptions.outputfname, FCELL_TYPE,
  204. angleVisibilityOutput);
  205. else
  206. /* elevation output */
  207. save_vis_elev_to_GRASS(visgrid->grid, viewOptions.inputfname,
  208. viewOptions.outputfname,
  209. vp.elev + viewOptions.obsElev);
  210. free_inmem_visibilitygrid(visgrid);
  211. return;
  212. }
  213. /* ------------------------------------------------------------ */
  214. /* IOVisibilityGrid functions */
  215. /* ------------------------------------------------------------ */
  216. /* ------------------------------------------------------------ */
  217. /*create grid from given header and viewpoint */
  218. IOVisibilityGrid *init_io_visibilitygrid(GridHeader hd, Viewpoint vp)
  219. {
  220. IOVisibilityGrid *visgrid;
  221. visgrid = (IOVisibilityGrid *) G_malloc(sizeof(IOVisibilityGrid));
  222. assert(visgrid);
  223. /*header */
  224. visgrid->hd = (GridHeader *) G_malloc(sizeof(GridHeader));
  225. assert(visgrid->hd);
  226. copy_header(visgrid->hd, hd);
  227. /*viewpoint */
  228. visgrid->vp = (Viewpoint *) G_malloc(sizeof(Viewpoint));
  229. assert(visgrid->vp);
  230. copy_viewpoint(visgrid->vp, vp);
  231. /*stream */
  232. visgrid->visStr = new AMI_STREAM < VisCell > ();
  233. assert(visgrid->visStr);
  234. return visgrid;
  235. }
  236. /* ------------------------------------------------------------ */
  237. /*free the grid */
  238. void free_io_visibilitygrid(IOVisibilityGrid * grid)
  239. {
  240. assert(grid);
  241. if (grid->hd)
  242. G_free(grid->hd);
  243. if (grid->vp)
  244. G_free(grid->vp);
  245. if (grid->visStr)
  246. delete grid->visStr;
  247. G_free(grid);
  248. return;
  249. }
  250. /* ------------------------------------------------------------ */
  251. /*write cell to stream */
  252. void add_result_to_io_visibilitygrid(IOVisibilityGrid * visgrid,
  253. VisCell * cell)
  254. {
  255. assert(visgrid && cell);
  256. AMI_err ae;
  257. assert(visgrid->visStr);
  258. ae = visgrid->visStr->write_item(*cell);
  259. assert(ae == AMI_ERROR_NO_ERROR);
  260. return;
  261. }
  262. /* ------------------------------------------------------------ */
  263. /*compare function, (i,j) grid order */
  264. int IJCompare::compare(const VisCell & a, const VisCell & b)
  265. {
  266. if (a.row > b.row)
  267. return 1;
  268. if (a.row < b.row)
  269. return -1;
  270. /*a.row==b.row */
  271. if (a.col > b.col)
  272. return 1;
  273. if (a.col < b.col)
  274. return -1;
  275. /*all equal */
  276. return 0;
  277. }
  278. /* ------------------------------------------------------------ */
  279. /*sort stream in grid order */
  280. void sort_io_visibilitygrid(IOVisibilityGrid * visGrid)
  281. {
  282. assert(visGrid);
  283. assert(visGrid->visStr);
  284. if (visGrid->visStr->stream_len() == 0)
  285. return;
  286. AMI_STREAM < VisCell > *sortedStr;
  287. AMI_err ae;
  288. IJCompare cmpObj;
  289. ae = AMI_sort(visGrid->visStr, &sortedStr, &cmpObj, 1);
  290. assert(ae == AMI_ERROR_NO_ERROR);
  291. assert(sortedStr);
  292. sortedStr->seek(0);
  293. visGrid->visStr = sortedStr;
  294. return;
  295. }
  296. /* ------------------------------------------------------------ */
  297. void
  298. save_io_visibilitygrid(IOVisibilityGrid * visgrid,
  299. ViewOptions viewOptions, Viewpoint vp)
  300. {
  301. if (viewOptions.outputMode == OUTPUT_BOOL)
  302. save_io_visibilitygrid_to_GRASS(visgrid, viewOptions.outputfname,
  303. CELL_TYPE, booleanVisibilityOutput);
  304. else if (viewOptions.outputMode == OUTPUT_ANGLE)
  305. save_io_visibilitygrid_to_GRASS(visgrid, viewOptions.outputfname,
  306. FCELL_TYPE, angleVisibilityOutput);
  307. else
  308. /* elevation output */
  309. save_io_vis_and_elev_to_GRASS(visgrid, viewOptions.inputfname,
  310. viewOptions.outputfname,
  311. vp.elev + viewOptions.obsElev);
  312. /*free visibiliyty grid */
  313. free_io_visibilitygrid(visgrid);
  314. return;
  315. }