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 54671 : bool angleMasking() const 89 : { 90 54671 : return startAngle != endAngle; 91 : } 92 : }; 93 : 94 : /** 95 : * A window in a raster including pixels in [xStart, xStop) and [yStart, yStop). 96 : */ 97 : struct Window 98 : { 99 : int xStart{}; //!< X start position 100 : int xStop{}; //!< X end position 101 : int yStart{}; //!< Y start position 102 : int yStop{}; //!< Y end position 103 : 104 : /// Returns true when one window is equal to the other. 105 13 : bool operator==(const Window &w2) const 106 : { 107 13 : return xStart == w2.xStart && xStop == w2.xStop && 108 26 : yStart == w2.yStart && yStop == w2.yStop; 109 : } 110 : 111 : /// \brief Window size in the X direction. 112 1867340 : int xSize() const 113 : { 114 1867340 : return xStop - xStart; 115 : } 116 : 117 : /// \brief Window size in the Y direction. 118 87319 : int ySize() const 119 : { 120 87319 : return yStop - yStart; 121 : } 122 : 123 : /// \brief Number of cells. 124 86528 : size_t size() const 125 : { 126 86528 : return static_cast<size_t>(xSize()) * ySize(); 127 : } 128 : 129 : /// \brief Determine if the X window contains the index. 130 : /// \param nX Index to check 131 : /// \return True if the index is contained, false otherwise. 132 29215 : bool containsX(int nX) const 133 : { 134 29215 : return nX >= xStart && nX < xStop; 135 : } 136 : 137 : /// \brief Determine if the Y window contains the index. 138 : /// \param nY Index to check 139 : /// \return True if the index is contained, false otherwise. 140 268 : bool containsY(int nY) const 141 : { 142 268 : return nY >= xStart && nY < yStop; 143 : } 144 : 145 : /// \brief Determine if the window contains the index. 146 : /// \param nX X coordinate of the index to check 147 : /// \param nY Y coordinate of the index to check 148 : /// \return True if the index is contained, false otherwise. 149 39 : bool contains(int nX, int nY) const 150 : { 151 39 : return containsX(nX) && containsY(nY); 152 : } 153 : 154 : /// \brief Clamp the argument to be in the window in the X dimension. 155 : /// \param nX Value to clamp. 156 : /// \return Clamped value. 157 83563 : int clampX(int nX) const 158 : { 159 83563 : return xSize() ? std::clamp(nX, xStart, xStop - 1) : xStart; 160 : } 161 : 162 : /// \brief Clamp the argument to be in the window in the Y dimension. 163 : /// \param nY Value to clamp. 164 : /// \return Clamped value. 165 470 : int clampY(int nY) const 166 : { 167 470 : return ySize() ? std::clamp(nY, yStart, yStop - 1) : yStart; 168 : } 169 : 170 : /// \brief Shift the X dimension by nShift. 171 : /// \param nShift Amount to shift 172 39 : void shiftX(int nShift) 173 : { 174 39 : xStart += nShift; 175 39 : xStop += nShift; 176 39 : } 177 : }; 178 : 179 0 : inline std::ostream &operator<<(std::ostream &out, const Window &w) 180 : { 181 0 : out << "Xstart/stop Ystart/stop = " << w.xStart << "/" << w.xStop << " " 182 0 : << w.yStart << "/" << w.yStop; 183 0 : return out; 184 : } 185 : 186 : /// Processing limits based on min/max distance restrictions. 187 : /// The left side processing range is [left, leftMin). 188 : /// The right side processing range is [rightMin, right). 189 : struct LineLimits 190 : { 191 : /// Constructor that takes the members in order. 192 28820 : LineLimits(int leftArg, int leftMinArg, int rightMinArg, int rightArg) 193 28820 : : left(leftArg), leftMin(leftMinArg), rightMin(rightMinArg), 194 28820 : right(rightArg) 195 : { 196 28820 : } 197 : 198 : int left; //!< Starting (leftmost) cell on the left side. 199 : int leftMin; //!< One past the rightmost cell on the left side. 200 : int rightMin; //!< Starting (leftmost) cell on the right side. 201 : int right; //!< One past the rightmost cell on the right side. 202 : }; 203 : 204 : inline std::ostream &operator<<(std::ostream &out, const LineLimits &ll) 205 : { 206 : out << "Left/LeftMin RightMin/Right = " << ll.left << "/" << ll.leftMin 207 : << " " << ll.rightMin << "/" << ll.right; 208 : return out; 209 : } 210 : 211 : constexpr int INVALID_ISECT = std::numeric_limits<int>::max(); 212 : 213 : } // namespace viewshed 214 : } // namespace gdal 215 : 216 : #endif