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 : class Progress;
31 :
32 : /// Executes a viewshed computation on a source band, placing the result
33 : /// in the destination band.
34 : class ViewshedExecutor
35 : {
36 : public:
37 : ViewshedExecutor(GDALRasterBand &srcBand, GDALRasterBand &dstBand, int nX,
38 : int nY, const Window &oOutExtent, const Window &oCurExtent,
39 : const Options &opts, Progress &oProgress,
40 : bool emitWarningIfNoData);
41 : bool run();
42 :
43 : /** Return whether an input pixel is at the nodata value. */
44 196 : bool hasFoundNoData() const
45 : {
46 196 : return m_hasFoundNoData;
47 : }
48 :
49 : private:
50 : CPLWorkerThreadPool m_pool;
51 : GDALRasterBand &m_srcBand;
52 : GDALRasterBand &m_dstBand;
53 : double m_noDataValue = 0;
54 : bool m_hasNoData = false;
55 : bool m_emitWarningIfNoData = false;
56 : bool m_hasFoundNoData = false;
57 : const Window oOutExtent;
58 : const Window oCurExtent;
59 : const int m_nX;
60 : const int m_nY;
61 : const Options oOpts;
62 : Progress &oProgress;
63 : double m_dfHeightAdjFactor{0};
64 : double m_dfMinDistance2;
65 : double m_dfMaxDistance2;
66 : double m_dfZObserver{0};
67 : std::mutex iMutex{};
68 : std::mutex oMutex{};
69 : std::array<double, 6> m_adfTransform{0, 1, 0, 0, 0, 1};
70 : std::array<double, 5> m_testAngle{};
71 : double m_lowTanPitch{std::numeric_limits<double>::quiet_NaN()};
72 : double m_highTanPitch{std::numeric_limits<double>::quiet_NaN()};
73 : double (*oZcalc)(int, int, double, double, double){};
74 :
75 : double calcHeightAdjFactor();
76 : void setOutput(double &dfResult, double &dfCellVal, double dfZ);
77 : bool readLine(int nLine, double *data);
78 : bool writeLine(int nLine, std::vector<double> &vResult);
79 : bool processLine(int nLine, std::vector<double> &vLastLineVal);
80 : bool processFirstLine(std::vector<double> &vLastLineVal);
81 : void processFirstLineLeft(const LineLimits &ll,
82 : std::vector<double> &vResult,
83 : std::vector<double> &vThisLineVal);
84 : void processFirstLineRight(const LineLimits &ll,
85 : std::vector<double> &vResult,
86 : std::vector<double> &vThisLineVal);
87 : void processFirstLineTopOrBottom(const LineLimits &ll,
88 : std::vector<double> &vResult,
89 : std::vector<double> &vThisLineVal);
90 : void processLineLeft(int nYOffset, LineLimits &ll,
91 : std::vector<double> &vResult,
92 : std::vector<double> &vThisLineVal,
93 : std::vector<double> &vLastLineVal);
94 : void processLineRight(int nYOffset, LineLimits &ll,
95 : std::vector<double> &vResult,
96 : std::vector<double> &vThisLineVal,
97 : std::vector<double> &vLastLineVal);
98 : LineLimits adjustHeight(int iLine, std::vector<double> &thisLineVal);
99 : void maskInitial(std::vector<double> &vResult, int nLine);
100 : bool maskAngleLeft(std::vector<double> &vResult, int nLine);
101 : bool maskAngleRight(std::vector<double> &vResult, int nLine);
102 : void maskLineLeft(std::vector<double> &vResult, const LineLimits &ll,
103 : int nLine);
104 : void maskLineRight(std::vector<double> &vResult, const LineLimits &ll,
105 : int nLine);
106 : void maskLowPitch(double &dfZ, int nXOffset, int nYOffset);
107 : void maskHighPitch(double &dfResult, double dfZ, int nXOffset,
108 : int nYOffset);
109 : void calcTestAngles();
110 : };
111 :
112 : } // namespace viewshed
113 : } // namespace gdal
|