Line data Source code
1 : /**************************************************************************** 2 : * (c) 2024 info@hobu.co 3 : * 4 : * SPDX-License-Identifier: MIT 5 : ****************************************************************************/ 6 : #ifndef VIEWSHED_TYPES_H_INCLUDED 7 : #define VIEWSHED_TYPES_H_INCLUDED 8 : 9 : #include <algorithm> 10 : #include <limits> 11 : #include <string> 12 : 13 : #include "gdal_priv.h" 14 : 15 : namespace gdal 16 : { 17 : namespace viewshed 18 : { 19 : 20 : /// Unique pointer to GDAL dataset. 21 : using DatasetPtr = std::unique_ptr<GDALDataset>; 22 : 23 : /** 24 : * Raster output mode. 25 : */ 26 : enum class OutputMode 27 : { 28 : Normal, //!< Normal output mode (visibility only) 29 : DEM, //!< Output height from DEM 30 : Ground, //!< Output height from ground 31 : Cumulative //!< Output observability heat map 32 : }; 33 : 34 : /** 35 : * Cell height calculation mode. 36 : */ 37 : enum class CellMode 38 : { 39 : Diagonal, //!< Diagonal Mode 40 : Edge, //!< Edge Mode 41 : Max, //!< Maximum value produced by Diagonal and Edge mode 42 : Min //!< Minimum value produced by Diagonal and Edge mode 43 : }; 44 : 45 : /** 46 : * A point. 47 : */ 48 : struct Point 49 : { 50 : double x; //!< X value 51 : double y; //!< Y value 52 : double z; //!< Z value 53 : }; 54 : 55 : /** 56 : * Options for viewshed generation. 57 : */ 58 : struct Options 59 : { 60 : Point observer{0, 0, 0}; //!< x, y, and z of the observer 61 : double visibleVal{255}; //!< raster output value for visible pixels. 62 : double invisibleVal{0}; //!< raster output value for non-visible pixels. 63 : double outOfRangeVal{ 64 : 0}; //!< raster output value for pixels outside of max distance. 65 : double nodataVal{-1}; //!< raster output value for pixels with no data 66 : double targetHeight{0.0}; //!< target height above the DEM surface 67 : double maxDistance{ 68 : 0.0}; //!< maximum distance from observer to compute value 69 : double minDistance{ 70 : 0.0}; //!< minimum distance from observer to compute value. 71 : double startAngle{0.0}; //!< start angle of observable range 72 : double endAngle{0.0}; //!< end angle of observable range 73 : double lowPitch{ 74 : -90.0}; //!< minimum pitch (vertical angle) of observable points 75 : double highPitch{ 76 : 90.0}; //!< maximum pitch (vertical angle) of observable points 77 : double curveCoeff{.85714}; //!< coefficient for atmospheric refraction 78 : OutputMode outputMode{OutputMode::Normal}; //!< Output information. 79 : //!< Normal, Height from DEM or Height from ground 80 : std::string outputFormat{}; //!< output raster format 81 : std::string outputFilename{}; //!< output raster filename 82 : CPLStringList creationOpts{}; //!< options for output raster creation 83 : CellMode cellMode{CellMode::Edge}; //!< Mode of cell height calculation. 84 : int observerSpacing{10}; //!< Observer spacing in cumulative mode. 85 : uint8_t numJobs{3}; //!< Relative number of jobs in cumulative mode. 86 : 87 : /// True if angle masking will occur. 88 54619 : bool angleMasking() const 89 : { 90 54619 : return startAngle != endAngle; 91 : } 92 : 93 : /// True if low pitch masking will occur. 94 2976680 : bool lowPitchMasking() const 95 : { 96 2976680 : return lowPitch > -90.0; 97 : } 98 : 99 : /// True if high pitch masking will occur. 100 2975370 : bool highPitchMasking() const 101 : { 102 2975370 : return highPitch < 90.0; 103 : } 104 : 105 : /// True if pitch masking will occur. 106 2973960 : bool pitchMasking() const 107 : { 108 2973960 : return lowPitchMasking() || highPitchMasking(); 109 : } 110 : }; 111 : 112 : /** 113 : * A window in a raster including pixels in [xStart, xStop) and [yStart, yStop). 114 : */ 115 : struct Window 116 : { 117 : int xStart{}; //!< X start position 118 : int xStop{}; //!< X end position 119 : int yStart{}; //!< Y start position 120 : int yStop{}; //!< Y end position 121 : 122 : /// Returns true when one window is equal to the other. 123 13 : bool operator==(const Window &w2) const 124 : { 125 13 : return xStart == w2.xStart && xStop == w2.xStop && 126 26 : yStart == w2.yStart && yStop == w2.yStop; 127 : } 128 : 129 : /// \brief Window size in the X direction. 130 1857690 : int xSize() const 131 : { 132 1857690 : return xStop - xStart; 133 : } 134 : 135 : /// \brief Window size in the Y direction. 136 87319 : int ySize() const 137 : { 138 87319 : return yStop - yStart; 139 : } 140 : 141 : /// \brief Number of cells. 142 86528 : size_t size() const 143 : { 144 86528 : return static_cast<size_t>(xSize()) * ySize(); 145 : } 146 : 147 : /// \brief Determine if the X window contains the index. 148 : /// \param nX Index to check 149 : /// \return True if the index is contained, false otherwise. 150 29203 : bool containsX(int nX) const 151 : { 152 29203 : return nX >= xStart && nX < xStop; 153 : } 154 : 155 : /// \brief Determine if the Y window contains the index. 156 : /// \param nY Index to check 157 : /// \return True if the index is contained, false otherwise. 158 268 : bool containsY(int nY) const 159 : { 160 268 : return nY >= xStart && nY < yStop; 161 : } 162 : 163 : /// \brief Determine if the window contains the index. 164 : /// \param nX X coordinate of the index to check 165 : /// \param nY Y coordinate of the index to check 166 : /// \return True if the index is contained, false otherwise. 167 39 : bool contains(int nX, int nY) const 168 : { 169 39 : return containsX(nX) && containsY(nY); 170 : } 171 : 172 : /// \brief Clamp the argument to be in the window in the X dimension. 173 : /// \param nX Value to clamp. 174 : /// \return Clamped value. 175 83481 : int clampX(int nX) const 176 : { 177 83481 : return xSize() ? std::clamp(nX, xStart, xStop - 1) : xStart; 178 : } 179 : 180 : /// \brief Clamp the argument to be in the window in the Y dimension. 181 : /// \param nY Value to clamp. 182 : /// \return Clamped value. 183 470 : int clampY(int nY) const 184 : { 185 470 : return ySize() ? std::clamp(nY, yStart, yStop - 1) : yStart; 186 : } 187 : 188 : /// \brief Shift the X dimension by nShift. 189 : /// \param nShift Amount to shift 190 39 : void shiftX(int nShift) 191 : { 192 39 : xStart += nShift; 193 39 : xStop += nShift; 194 39 : } 195 : }; 196 : 197 0 : inline std::ostream &operator<<(std::ostream &out, const Window &w) 198 : { 199 0 : out << "Xstart/stop Ystart/stop = " << w.xStart << "/" << w.xStop << " " 200 0 : << w.yStart << "/" << w.yStop; 201 0 : return out; 202 : } 203 : 204 : /// Processing limits based on min/max distance restrictions. 205 : /// The left side processing range is [left, leftMin). 206 : /// The right side processing range is [rightMin, right). 207 : struct LineLimits 208 : { 209 : /// Constructor that takes the members in order. 210 28780 : LineLimits(int leftArg, int leftMinArg, int rightMinArg, int rightArg) 211 28780 : : left(leftArg), leftMin(leftMinArg), rightMin(rightMinArg), 212 28780 : right(rightArg) 213 : { 214 28780 : } 215 : 216 : int left; //!< Starting (leftmost) cell on the left side. 217 : int leftMin; //!< One past the rightmost cell on the left side. 218 : int rightMin; //!< Starting (leftmost) cell on the right side. 219 : int right; //!< One past the rightmost cell on the right side. 220 : }; 221 : 222 : inline std::ostream &operator<<(std::ostream &out, const LineLimits &ll) 223 : { 224 : out << "Left/LeftMin RightMin/Right = " << ll.left << "/" << ll.leftMin 225 : << " " << ll.rightMin << "/" << ll.right; 226 : return out; 227 : } 228 : 229 : constexpr int INVALID_ISECT = std::numeric_limits<int>::max(); 230 : 231 : } // namespace viewshed 232 : } // namespace gdal 233 : 234 : #endif