Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: Viewshed Generation
4 : * Purpose: Core algorithm implementation for viewshed generation.
5 : * Author: Tamas Szekeres, szekerest@gmail.com
6 : *
7 : * (c) 2024 info@hobu.co
8 : *
9 : ******************************************************************************
10 : *
11 : * SPDX-License-Identifier: MIT
12 : ****************************************************************************/
13 :
14 : #pragma once
15 :
16 : #include <array>
17 : #include <limits>
18 : #include <mutex>
19 :
20 : #include "gdal_priv.h"
21 : #include "cpl_worker_thread_pool.h"
22 :
23 : #include "viewshed_types.h"
24 :
25 : namespace gdal
26 : {
27 : namespace viewshed
28 : {
29 :
30 : /**
31 : * Container for lines necessary for processing.
32 : */
33 : struct Lines
34 : {
35 : std::vector<double> cur; //!< Current line being processed
36 : std::vector<double> result; //!< Result values for current line
37 : std::vector<double> prev; //!< Height values for previous line
38 : std::vector<double>
39 : pitchMask; //!< Height/indicator values for pitch masking.
40 :
41 : /// Constructor
42 : Lines() : cur(), result(), prev(), pitchMask()
43 : {
44 : }
45 :
46 : /// Constructor that initializes to line length
47 : /// \param lineLen Line length.
48 705 : explicit Lines(size_t lineLen)
49 705 : : cur(lineLen), result(lineLen), prev(), pitchMask()
50 : {
51 705 : }
52 : };
53 :
54 : class Progress;
55 :
56 : /// Executes a viewshed computation on a source band, placing the result
57 : /// in the destination band.
58 : class ViewshedExecutor
59 : {
60 : public:
61 : ViewshedExecutor(GDALRasterBand &srcBand, GDALRasterBand &dstBand, int nX,
62 : int nY, const Window &oOutExtent, const Window &oCurExtent,
63 : const Options &opts, Progress &oProgress,
64 : bool emitWarningIfNoData);
65 : bool run();
66 :
67 : /** Return whether an input pixel is at the nodata value. */
68 196 : bool hasFoundNoData() const
69 : {
70 196 : return m_hasFoundNoData;
71 : }
72 :
73 : private:
74 : CPLWorkerThreadPool m_pool;
75 : GDALRasterBand &m_srcBand;
76 : GDALRasterBand &m_dstBand;
77 : double m_noDataValue = 0;
78 : bool m_hasNoData = false;
79 : bool m_emitWarningIfNoData = false;
80 : bool m_hasFoundNoData = false;
81 : const Window oOutExtent;
82 : const Window oCurExtent;
83 : const int m_nX;
84 : const int m_nY;
85 : const Options oOpts;
86 : Progress &oProgress;
87 : double m_dfHeightAdjFactor{0};
88 : double m_dfMinDistance2;
89 : double m_dfMaxDistance2;
90 : double m_dfZObserver{0};
91 : std::mutex iMutex{};
92 : std::mutex oMutex{};
93 : GDALGeoTransform m_gt{};
94 : std::array<double, 5> m_testAngle{};
95 : double m_lowTanPitch{std::numeric_limits<double>::quiet_NaN()};
96 : double m_highTanPitch{std::numeric_limits<double>::quiet_NaN()};
97 : double (*oZcalc)(int, int, double, double, double){};
98 :
99 : double calcHeightAdjFactor();
100 : void setOutput(double &dfResult, double &dfCellVal, double dfZ);
101 : bool readLine(int nLine, std::vector<double> &line);
102 : bool writeLine(int nLine, std::vector<double> &vResult);
103 : bool processLine(int nLine, Lines &lines);
104 : bool processFirstLine(Lines &lines);
105 : void processFirstLineLeft(const LineLimits &ll, Lines &lines);
106 : void processFirstLineRight(const LineLimits &ll, Lines &lines);
107 : void processFirstLineTopOrBottom(const LineLimits &ll, Lines &lines);
108 : void processLineLeft(int nYOffset, LineLimits &ll, Lines &lines);
109 : void processLineRight(int nYOffset, LineLimits &ll, Lines &lines);
110 : LineLimits adjustHeight(int iLine, Lines &lines);
111 : void maskInitial(std::vector<double> &vResult, int nLine);
112 : bool maskAngleLeft(std::vector<double> &vResult, int nLine);
113 : bool maskAngleRight(std::vector<double> &vResult, int nLine);
114 : void maskLineLeft(std::vector<double> &vResult, const LineLimits &ll,
115 : int nLine);
116 : void maskLineRight(std::vector<double> &vResult, const LineLimits &ll,
117 : int nLine);
118 : void calcPitchMask(double dfZ, double dfDist, double dfResult,
119 : double &maskVal);
120 : void applyPitchMask(std::vector<double> &vResult,
121 : const std::vector<double> &vPitchMaskVal);
122 : void calcTestAngles();
123 : };
124 :
125 : } // namespace viewshed
126 : } // namespace gdal
|