Coverage Report

Created: 2026-02-14 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/alg/viewshed/viewshed_executor.h
Line
Count
Source
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
    std::vector<double> prevTmp;  //!< Saved prev values when in SD mode.
41
    std::vector<double> sd;       //!< SD mask.
42
43
    /// Constructor
44
    Lines() : cur(), result(), prev(), pitchMask(), prevTmp(), sd()
45
0
    {
46
0
    }
47
48
    /// Constructor that initializes to line length
49
    /// \param lineLen  Line length.
50
    explicit Lines(size_t lineLen)
51
0
        : cur(lineLen), result(lineLen), prev(), pitchMask(), prevTmp(), sd()
52
0
    {
53
0
    }
54
};
55
56
/// Dummy raster band.
57
//! @cond Doxygen_Suppress
58
class DummyBand : public GDALRasterBand
59
{
60
    CPLErr IReadBlock(int, int, void *) override;
61
};
62
//! @endcond
63
64
class Progress;
65
66
/// Executes a viewshed computation on a source band, placing the result
67
/// in the destination band.
68
class ViewshedExecutor
69
{
70
  public:
71
    ViewshedExecutor(GDALRasterBand &srcBand, GDALRasterBand &sdBand,
72
                     GDALRasterBand &dstBand, int nX, int nY,
73
                     const Window &oOutExtent, const Window &oCurExtent,
74
                     const Options &opts, Progress &oProgress,
75
                     bool emitWarningIfNoData);
76
77
    ViewshedExecutor(GDALRasterBand &srcBand, GDALRasterBand &dstBand, int nX,
78
                     int nY, const Window &oOutExtent, const Window &oCurExtent,
79
                     const Options &opts, Progress &oProgress,
80
                     bool emitWarningIfNoData);
81
    bool run();
82
83
    /** Return whether an input pixel is at the nodata value. */
84
    bool hasFoundNoData() const
85
0
    {
86
0
        return m_hasFoundNoData;
87
0
    }
88
89
  private:
90
    CPLWorkerThreadPool m_pool;
91
    DummyBand m_dummyBand;
92
    GDALRasterBand &m_srcBand;
93
    GDALRasterBand &m_sdBand;
94
    GDALRasterBand &m_dstBand;
95
    const bool m_hasSdBand;
96
    double m_noDataValue = 0;
97
    bool m_hasNoData = false;
98
    bool m_emitWarningIfNoData = false;
99
    bool m_hasFoundNoData = false;
100
    const Window oOutExtent;
101
    const Window oCurExtent;
102
    const int m_nX;
103
    const int m_nY;
104
    const Options oOpts;
105
    Progress &oProgress;
106
    double m_dfHeightAdjFactor{0};
107
    double m_dfMinDistance2;
108
    double m_dfMaxDistance2;
109
    double m_dfZObserver{0};
110
    std::mutex iMutex{};
111
    std::mutex oMutex{};
112
    GDALGeoTransform m_gt{};
113
    std::array<double, 5> m_testAngle{};
114
    double m_lowTanPitch{std::numeric_limits<double>::quiet_NaN()};
115
    double m_highTanPitch{std::numeric_limits<double>::quiet_NaN()};
116
    double (*oZcalc)(int, int, double, double, double){};
117
118
    double calcHeightAdjFactor();
119
120
    void setOutputNormal(Lines &lines, int pos, double dfZ);
121
    void setOutputSd(Lines &lines, int pos, double dfZ);
122
123
    bool readLine(int nLine, Lines &lines);
124
    bool writeLine(int nLine, std::vector<double> &vResult);
125
    bool processLine(int nLine, Lines &lines);
126
    bool processFirstLine(Lines &lines);
127
    void processFirstLineLeft(const LineLimits &ll, Lines &lines, bool sdCalc);
128
    void processFirstLineRight(const LineLimits &ll, Lines &lines, bool sdCalc);
129
    void processFirstLineTopOrBottom(const LineLimits &ll, Lines &lines);
130
    void processLineLeft(int nYOffset, LineLimits &ll, Lines &lines,
131
                         bool sdCalc);
132
    void processLineRight(int nYOffset, LineLimits &ll, Lines &lines,
133
                          bool sdCalc);
134
    LineLimits adjustHeight(int iLine, Lines &lines);
135
    bool maskInitial(std::vector<double> &vResult, const LineLimits &ll,
136
                     int nLine);
137
    bool maskAngleLeft(std::vector<double> &vResult, int nLine);
138
    bool maskAngleRight(std::vector<double> &vResult, int nLine);
139
    void maskLineLeft(std::vector<double> &vResult, const LineLimits &ll,
140
                      int nLine);
141
    void maskLineRight(std::vector<double> &vResult, const LineLimits &ll,
142
                       int nLine);
143
    void calcPitchMask(double dfZ, double dfDist, double dfResult,
144
                       double &maskVal);
145
    void applyPitchMask(std::vector<double> &vResult,
146
                        const std::vector<double> &vPitchMaskVal);
147
    void calcTestAngles();
148
149
    inline bool sdMode() const
150
0
    {
151
0
        return m_hasSdBand;
152
0
    }
153
};
154
155
}  // namespace viewshed
156
}  // namespace gdal