GDAL
viewshed.h
1 /******************************************************************************
2  *
3  * Project: Viewshed Generation
4  * Purpose: Core algorithm implementation for viewshed generation.
5  * Author: Tamas Szekeres, szekerest@gmail.com
6  *
7  ******************************************************************************
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining a
10  * copy of this software and associated documentation files (the "Software"),
11  * to deal in the Software without restriction, including without limitation
12  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13  * and/or sell copies of the Software, and to permit persons to whom the
14  * Software is furnished to do so, subject to the following conditions:
15  *
16  * The above copyright notice and this permission notice shall be included
17  * in all copies or substantial portions of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25  * DEALINGS IN THE SOFTWARE.
26  ****************************************************************************/
27 
28 #include <algorithm>
29 #include <array>
30 #include <cstdint>
31 #include <functional>
32 #include <limits>
33 #include <memory>
34 #include <mutex>
35 #include <string>
36 
37 #include "cpl_progress.h"
38 #include "gdal_priv.h"
39 
40 namespace gdal
41 {
42 
46 class Viewshed
47 {
48  public:
52  enum class OutputMode
53  {
54  Normal,
55  DEM,
56  Ground
57  };
58 
62  enum class CellMode
63  {
64  Diagonal,
65  Edge,
66  Max,
67  Min
68  };
69 
73  struct Point
74  {
75  double x;
76  double y;
77  double z;
78  };
79 
83  struct Window
84  {
85  int xStart{};
86  int xStop{};
87  int yStart{};
88  int yStop{};
89 
91  int xSize() const
92  {
93  return xStop - xStart;
94  }
95 
97  int ySize() const
98  {
99  return yStop - yStart;
100  }
101 
105  bool containsX(int nX) const
106  {
107  return nX >= xStart && nX < xStop;
108  }
109 
113  bool containsY(int nY) const
114  {
115  return nY >= xStart && nY < yStop;
116  }
117 
122  bool contains(int nX, int nY) const
123  {
124  return containsX(nX) && containsY(nY);
125  }
126 
130  int clampX(int nX) const
131  {
132  return xSize() ? std::clamp(nX, xStart, xStop - 1) : xStart;
133  }
134 
138  int clampY(int nY) const
139  {
140  return ySize() ? std::clamp(nY, yStart, yStop - 1) : yStart;
141  }
142 
145  void shiftX(int nShift)
146  {
147  xStart += nShift;
148  xStop += nShift;
149  }
150  };
151 
155  struct Options
156  {
157  Point observer{0, 0, 0};
158  double visibleVal{255};
159  double invisibleVal{
160  0};
162  0};
163  double nodataVal{-1};
164  double targetHeight{0.0};
165  double maxDistance{
166  0.0};
167  double curveCoeff{.85714};
170  std::string outputFormat{};
171  std::string outputFilename{};
174  CellMode::Edge};
175  };
176 
182  CPL_DLL explicit Viewshed(const Options &opts)
183  : oOpts{opts}, oOutExtent{}, oCurExtent{},
184  dfMaxDistance2{opts.maxDistance * opts.maxDistance},
185  dfZObserver{0}, poDstDS{}, pSrcBand{}, pDstBand{},
186  dfHeightAdjFactor{0}, nLineCount{0}, adfTransform{0, 1, 0, 0, 0, 1},
187  adfInvTransform{}, oProgress{}, oZcalc{}, oMutex{}, iMutex{}
188  {
189  if (dfMaxDistance2 == 0)
190  dfMaxDistance2 = std::numeric_limits<double>::max();
191  }
192 
193  Viewshed(const Viewshed &) = delete;
194  Viewshed &operator=(const Viewshed &) = delete;
195 
196  CPL_DLL bool run(GDALRasterBandH hBand,
197  GDALProgressFunc pfnProgress = GDALDummyProgress,
198  void *pProgressArg = nullptr);
199 
205  CPL_DLL std::unique_ptr<GDALDataset> output()
206  {
207  return std::move(poDstDS);
208  }
209 
210  private:
211  Options oOpts;
212  Window oOutExtent;
213  Window oCurExtent;
214  double dfMaxDistance2;
215  double dfZObserver;
216  std::unique_ptr<GDALDataset> poDstDS;
217  GDALRasterBand *pSrcBand;
218  GDALRasterBand *pDstBand;
219  double dfHeightAdjFactor;
220  int nLineCount;
221  std::array<double, 6> adfTransform;
222  std::array<double, 6> adfInvTransform;
223  using ProgressFunc = std::function<bool(double frac, const char *msg)>;
224  ProgressFunc oProgress;
225  using ZCalc = std::function<double(int, int, double, double, double)>;
226  ZCalc oZcalc;
227  std::mutex oMutex;
228  std::mutex iMutex;
229 
230  void setOutput(double &dfResult, double &dfCellVal, double dfZ);
231  double calcHeight(double dfZ, double dfZ2);
232  bool readLine(int nLine, double *data);
233  bool writeLine(int nLine, std::vector<double> &vResult);
234  bool processLine(int nX, int nY, int nLine,
235  std::vector<double> &vLastLineVal);
236  bool processFirstLine(int nX, int nY, std::vector<double> &vLastLineVal);
237  void processFirstLineLeft(int nX, int iStart, int iEnd,
238  std::vector<double> &vResult,
239  std::vector<double> &vThisLineVal);
240  void processFirstLineRight(int nX, int iStart, int iEnd,
241  std::vector<double> &vResult,
242  std::vector<double> &vThisLineVal);
243  void processFirstLineTopOrBottom(int iLeft, int iRight,
244  std::vector<double> &vResult,
245  std::vector<double> &vThisLineVal);
246  void processLineLeft(int nX, int nYOffset, int iStart, int iEnd,
247  std::vector<double> &vResult,
248  std::vector<double> &vThisLineVal,
249  std::vector<double> &vLastLineVal);
250  void processLineRight(int nX, int nYOffset, int iStart, int iEnd,
251  std::vector<double> &vResult,
252  std::vector<double> &vThisLineVal,
253  std::vector<double> &vLastLineVal);
254  std::pair<int, int> adjustHeight(int iLine, int nX,
255  std::vector<double> &thisLineVal);
256  bool calcOutputExtent(int nX, int nY);
257  bool createOutputDataset();
258  bool lineProgress();
259  bool emitProgress(double fraction);
260 };
261 
262 } // namespace gdal
String list class designed around our use of C "char**" string lists.
Definition: cpl_string.h:449
A single raster band (or channel).
Definition: gdal_priv.h:1504
Class to support viewshed raster generation.
Definition: viewshed.h:47
std::unique_ptr< GDALDataset > output()
Fetch a pointer to the created raster band.
Definition: viewshed.h:205
bool run(GDALRasterBandH hBand, GDALProgressFunc pfnProgress=GDALDummyProgress, void *pProgressArg=nullptr)
Compute the viewshed of a raster band.
Definition: viewshed.cpp:959
Viewshed(const Options &opts)
Constructor.
Definition: viewshed.h:182
CellMode
Cell height calculation mode.
Definition: viewshed.h:63
@ Max
Maximum value produced by Diagonal and Edge mode.
@ Min
Minimum value produced by Diagonal and Edge mode.
@ Diagonal
Diagonal Mode.
OutputMode
Raster output mode.
Definition: viewshed.h:53
@ Ground
Output height from ground.
@ DEM
Output height from DEM.
@ Normal
Normal output mode (visibility only)
void * GDALRasterBandH
Opaque type used for the C bindings of the C++ GDALRasterBand class.
Definition: gdal.h:294
C++ GDAL entry points.
Options for viewshed generation.
Definition: viewshed.h:156
double maxDistance
maximum distance from observer to compute value
Definition: viewshed.h:165
double nodataVal
raster output value for pixels with no data
Definition: viewshed.h:163
double curveCoeff
coefficient for atmospheric refraction
Definition: viewshed.h:167
CellMode cellMode
Mode of cell height calculation.
Definition: viewshed.h:173
CPLStringList creationOpts
options for output raster creation
Definition: viewshed.h:172
OutputMode outputMode
Output information.
Definition: viewshed.h:168
std::string outputFormat
output raster format
Definition: viewshed.h:170
double outOfRangeVal
raster output value for pixels outside of max distance.
Definition: viewshed.h:161
double visibleVal
raster output value for visible pixels.
Definition: viewshed.h:158
double invisibleVal
raster output value for non-visible pixels.
Definition: viewshed.h:159
double targetHeight
target height above the DEM surface
Definition: viewshed.h:164
std::string outputFilename
output raster filename
Definition: viewshed.h:171
Point observer
x, y, and z of the observer
Definition: viewshed.h:157
A point.
Definition: viewshed.h:74
double y
Y value.
Definition: viewshed.h:76
double x
X value.
Definition: viewshed.h:75
double z
Z value.
Definition: viewshed.h:77
A window in a raster including pixels in [xStart, xStop) and [yStart, yStop).
Definition: viewshed.h:84
int clampY(int nY) const
Clamp the argument to be in the window in the Y dimension.
Definition: viewshed.h:138
bool contains(int nX, int nY) const
Determine if the window contains the index.
Definition: viewshed.h:122
bool containsX(int nX) const
Determine if the X window contains the index.
Definition: viewshed.h:105
int clampX(int nX) const
Clamp the argument to be in the window in the X dimension.
Definition: viewshed.h:130
bool containsY(int nY) const
Determine if the Y window contains the index.
Definition: viewshed.h:113
int xStart
X start position.
Definition: viewshed.h:85
int xSize() const
Window size in the X direction.
Definition: viewshed.h:91
int xStop
X end position.
Definition: viewshed.h:86
int yStop
Y end position.
Definition: viewshed.h:88
void shiftX(int nShift)
Shift the X dimension by nShift.
Definition: viewshed.h:145
int yStart
Y start position.
Definition: viewshed.h:87
int ySize() const
Window size in the Y direction.
Definition: viewshed.h:97