distribute.h 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  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. #ifndef __DISTRIBUTE_H
  36. #define __DISTRIBUTE_H
  37. #include "visibility.h"
  38. #include "grid.h"
  39. #include "eventlist.h"
  40. /* distribution sweep: write results to visgrid.
  41. */
  42. IOVisibilityGrid *distribute_and_sweep(char *inputfname,
  43. GridHeader * hd,
  44. Viewpoint * vp,
  45. ViewOptions viewOptions);
  46. /* distribute recursively the events and write results to
  47. visgrid. eventList is a list of events sorted by distance that fall
  48. within angle boundaries start_angle and end_angle; enterBndEvents
  49. is a stream that contains all the ENTER events that are not in this
  50. sector, but their corresponding Q or X events are in this sector.
  51. when problem is small enough, solve it in memory and write results
  52. to visgrid.
  53. invariant: distribute_sector deletes eventList and enterBndEvents
  54. returns the number of visible cells.
  55. */
  56. unsigned long distribute_sector(AMI_STREAM < AEvent > *eventList,
  57. AMI_STREAM < AEvent > *enterBndEvents,
  58. double start_angle, double end_angle,
  59. IOVisibilityGrid * visgrid, Viewpoint * vp,
  60. GridHeader *hd, ViewOptions viewOptions);
  61. /* bndEvents is a stream of events that cross into the sector's
  62. (first) boundary; they must be distributed to the boundary streams
  63. of the sub-sectors of this sector. Note: the boundary streams of
  64. the sub-sectors may not be empty; as a result, events get appended
  65. at the end, and they will not be sorted by distance from the
  66. vp.
  67. */
  68. void distribute_bnd_events(AMI_STREAM < AEvent > *bndEvents,
  69. AMI_STREAM < AEvent > *SectorBnd, int nsect,
  70. Viewpoint * vp, double start_angle,
  71. double end_angle, double *high, long *insert,
  72. long *drop);
  73. /* same as above, but does it inemory. it is called when sector fits
  74. in memory. eventList is the list of events in increasing order of
  75. distance from the viewpoint; enterBndEvents is the list of ENTER
  76. events that are outside the sector, whose corresponding EXIT events
  77. are inside the sector. start_angle and end_angle are the
  78. boundaries of the sector, and visgrid is the grid to which the
  79. visible/invisible cells must be written. The sector is solved by
  80. switching to radial sweep. Returns the number of visible cells. */
  81. unsigned long solve_in_memory(AMI_STREAM < AEvent > *eventList,
  82. AMI_STREAM < AEvent > *enterBndEvents,
  83. double start_angle, double end_angle,
  84. IOVisibilityGrid * visgrid, GridHeader *hd,
  85. Viewpoint * vp, ViewOptions viewOptions);
  86. /*returns 1 if enter angle is within epsilon from boundary angle */
  87. int is_almost_on_boundary(double angle, double boundary_angle);
  88. /* returns 1 if angle is within epsilon the boundaries of sector s */
  89. int is_almost_on_boundary(double angle, int s, double start_angle,
  90. double end_angle, int nsect);
  91. /* computes the number of sector for the distribution sweep;
  92. technically M/B */
  93. int compute_n_sectors();
  94. /* return 1 is s is inside sector; that is, if it is not -1 */
  95. int is_inside(int s, int nsect);
  96. /* compute the sector that contains this angle; there are nsect
  97. sectors that span the angle interval [sstartAngle, sendAngle] */
  98. int get_event_sector(double angle, double sstartAngle, double sendAngle,
  99. int nsect);
  100. /* insert event in this sector */
  101. void insert_event_in_sector(AMI_STREAM < AEvent > *str, AEvent * e);
  102. /* insert event e into sector if it is not occluded by high_s */
  103. void insert_event_in_sector(AEvent * e, int s, AMI_STREAM < AEvent > *str,
  104. double high_s, Viewpoint * vp, long *insert,
  105. long *drop);
  106. /**********************************************************************
  107. insert event e into sector, no occlusion check */
  108. void insert_event_in_sector_no_drop(AEvent * e, int s,
  109. AMI_STREAM < AEvent > *str, long *insert);
  110. /* returns 1 if the center of event is occluded by the gradient, which
  111. is assumed to be in line with the event */
  112. int is_center_gradient_occluded(AEvent * e, double gradient, Viewpoint * vp);
  113. /* called when dropping an event e, high is the highest gradiant value
  114. in its sector */
  115. void print_dropped(AEvent * e, Viewpoint * vp, double high);
  116. /* prints how many events were inserted and dropped in each sector */
  117. void print_sector_stats(off_t nevents, int nsect, double *high, long *total,
  118. long *insert, long *drop,
  119. AMI_STREAM < AEvent > *sector,
  120. AMI_STREAM < AEvent > *bndSector, long *bndInsert,
  121. long longEvents, double start_angle,
  122. double end_angle);
  123. /* the event e spans sectors from start_s to end_s; Action: update
  124. high[] for each spanned sector.
  125. */
  126. void process_long_cell(int start_s, int end_s, int nsect,
  127. Viewpoint * vp, AEvent * e, double *high);
  128. /* return the start angle of the i-th sector. Assuming that
  129. [start..end] is split into nsectors */
  130. double get_sector_start(int i, double start_angle, double end_angle,
  131. int nsect);
  132. /* return the start angle of the i-th sector. Assuming that
  133. [start..end] is split into nsectors */
  134. double get_sector_end(int i, double start_angle, double end_angle, int nsect);
  135. /* returns true if the event is inside the given sector */
  136. int is_inside(AEvent * e, double start_angle, double end_angle);
  137. /* returns true if this angle is inside the given sector */
  138. int is_inside(double angle, double start_angle, double end_angle);
  139. #endif