Line data Source code
1 : /******************************************************************************
2 : *
3 : * Name: gdalc_omputedrasterband.h
4 : * Project: GDAL Core
5 : * Purpose: Declaration of GDALComputedRasterBand and related gdal:: methods
6 : * Author: Even Rouault, <even.rouault@spatialys.com>
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2025, Even Rouault, <even.rouault@spatialys.com>
10 : *
11 : * SPDX-License-Identifier: MIT
12 : ****************************************************************************/
13 :
14 : #ifndef GDALCOMPUTEDRASTERBAND_H_INCLUDED
15 : #define GDALCOMPUTEDRASTERBAND_H_INCLUDED
16 :
17 : #include "cpl_port.h"
18 : #include "gdal_dataset.h" // GDALDatasetUniquePtrReleaser
19 : #include "gdal_rasterband.h"
20 :
21 : #include <algorithm>
22 : #include <cmath>
23 : #include <limits>
24 : #include <memory>
25 : #include <vector>
26 :
27 : /* ******************************************************************** */
28 : /* GDALComputedRasterBand */
29 : /* ******************************************************************** */
30 :
31 : /** Class represented the result of an operation on one or two input bands.
32 : *
33 : * Such class is instantiated only by operators on GDALRasterBand.
34 : * The resulting band is lazy evaluated.
35 : *
36 : * @since 3.12
37 : */
38 : class CPL_DLL GDALComputedRasterBand final : public GDALRasterBand
39 : {
40 : public:
41 : /** Destructor */
42 : ~GDALComputedRasterBand() override;
43 :
44 : //! @cond Doxygen_Suppress
45 : enum class Operation
46 : {
47 : OP_ADD,
48 : OP_SUBTRACT,
49 : OP_MULTIPLY,
50 : OP_DIVIDE,
51 : OP_MIN,
52 : OP_MAX,
53 : OP_MEAN,
54 : OP_GT,
55 : OP_GE,
56 : OP_LT,
57 : OP_LE,
58 : OP_EQ,
59 : OP_NE,
60 : OP_LOGICAL_AND,
61 : OP_LOGICAL_OR,
62 : OP_CAST,
63 : OP_TERNARY,
64 : OP_ABS,
65 : OP_SQRT,
66 : OP_LOG,
67 : OP_LOG10,
68 : OP_POW,
69 : };
70 :
71 : GDALComputedRasterBand(
72 : Operation op, const std::vector<const GDALRasterBand *> &bands,
73 : double constant = std::numeric_limits<double>::quiet_NaN());
74 : GDALComputedRasterBand(Operation op, const GDALRasterBand &band);
75 : GDALComputedRasterBand(Operation op, double constant,
76 : const GDALRasterBand &band);
77 : GDALComputedRasterBand(Operation op, const GDALRasterBand &band,
78 : double constant);
79 : GDALComputedRasterBand(Operation op, const GDALRasterBand &band,
80 : GDALDataType dt);
81 :
82 : // Semi-public for gdal::min(), gdal::max()
83 : GDALComputedRasterBand(Operation op, const GDALRasterBand &firstBand,
84 : const GDALRasterBand &secondBand);
85 :
86 : GDALComputedRasterBand(GDALComputedRasterBand &&) = default;
87 :
88 : //! @endcond
89 :
90 : double GetNoDataValue(int *pbSuccess = nullptr) override;
91 :
92 : /** Convert a GDALComputedRasterBand* to a GDALComputedRasterBandH.
93 : */
94 : static inline GDALComputedRasterBandH
95 : ToHandle(GDALComputedRasterBand *poBand)
96 : {
97 : return static_cast<GDALComputedRasterBandH>(poBand);
98 : }
99 :
100 : /** Convert a GDALComputedRasterBandH to a GDALComputedRasterBand*.
101 : */
102 : static inline GDALComputedRasterBand *
103 163 : FromHandle(GDALComputedRasterBandH hBand)
104 : {
105 163 : return static_cast<GDALComputedRasterBand *>(hBand);
106 : }
107 :
108 : protected:
109 : friend class GDALRasterBand;
110 :
111 : CPLErr IReadBlock(int, int, void *) override;
112 :
113 : CPLErr IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize,
114 : int nYSize, void *pData, int nBufXSize, int nBufYSize,
115 : GDALDataType eBufType, GSpacing nPixelSpace,
116 : GSpacing nLineSpace,
117 : GDALRasterIOExtraArg *psExtraArg) override;
118 :
119 : private:
120 : friend class GDALComputedDataset;
121 : std::unique_ptr<GDALDataset, GDALDatasetUniquePtrReleaser> m_poOwningDS{};
122 : bool m_bHasNoData{false};
123 : double m_dfNoDataValue{0};
124 :
125 : GDALComputedRasterBand(const GDALComputedRasterBand &, bool);
126 : GDALComputedRasterBand(const GDALComputedRasterBand &) = delete;
127 : GDALComputedRasterBand &operator=(const GDALComputedRasterBand &) = delete;
128 : GDALComputedRasterBand &operator=(GDALComputedRasterBand &&) = delete;
129 : };
130 :
131 : namespace gdal
132 : {
133 : using std::abs;
134 : GDALComputedRasterBand CPL_DLL abs(const GDALRasterBand &band);
135 :
136 : using std::fabs;
137 : GDALComputedRasterBand CPL_DLL fabs(const GDALRasterBand &band);
138 :
139 : using std::sqrt;
140 : GDALComputedRasterBand CPL_DLL sqrt(const GDALRasterBand &band);
141 :
142 : using std::log;
143 : GDALComputedRasterBand CPL_DLL log(const GDALRasterBand &band);
144 :
145 : using std::log10;
146 : GDALComputedRasterBand CPL_DLL log10(const GDALRasterBand &band);
147 :
148 : using std::pow;
149 : GDALComputedRasterBand CPL_DLL pow(const GDALRasterBand &band, double constant);
150 : #ifndef DOXYGEN_SKIP
151 : GDALComputedRasterBand CPL_DLL pow(double constant, const GDALRasterBand &band);
152 : GDALComputedRasterBand CPL_DLL pow(const GDALRasterBand &band1,
153 : const GDALRasterBand &band2);
154 : #endif
155 :
156 : GDALComputedRasterBand CPL_DLL IfThenElse(const GDALRasterBand &condBand,
157 : const GDALRasterBand &thenBand,
158 : const GDALRasterBand &elseBand);
159 :
160 : //! @cond Doxygen_Suppress
161 :
162 : GDALComputedRasterBand CPL_DLL IfThenElse(const GDALRasterBand &condBand,
163 : double thenValue,
164 : const GDALRasterBand &elseBand);
165 :
166 : GDALComputedRasterBand CPL_DLL IfThenElse(const GDALRasterBand &condBand,
167 : const GDALRasterBand &thenBand,
168 : double elseValue);
169 :
170 : GDALComputedRasterBand CPL_DLL IfThenElse(const GDALRasterBand &condBand,
171 : double thenValue, double elseValue);
172 :
173 : //! @endcond
174 :
175 : using std::max;
176 : using std::min;
177 :
178 : GDALComputedRasterBand CPL_DLL min(const GDALRasterBand &first,
179 : const GDALRasterBand &second);
180 :
181 : //! @cond Doxygen_Suppress
182 :
183 : namespace detail
184 : {
185 :
186 : template <typename U, typename Enable> struct minDealFirstArg;
187 :
188 : template <typename U>
189 : struct minDealFirstArg<
190 : U, typename std::enable_if<std::is_arithmetic<U>::value>::type>
191 : {
192 2 : inline static void process(std::vector<const GDALRasterBand *> &,
193 : double &constant, const U &first)
194 : {
195 2 : if (std::isnan(constant) || static_cast<double>(first) < constant)
196 2 : constant = static_cast<double>(first);
197 2 : }
198 : };
199 :
200 : template <typename U>
201 : struct minDealFirstArg<
202 : U, typename std::enable_if<!std::is_arithmetic<U>::value>::type>
203 : {
204 16 : inline static void process(std::vector<const GDALRasterBand *> &bands,
205 : double &, const U &first)
206 : {
207 16 : if (!bands.empty())
208 10 : GDALRasterBand::ThrowIfNotSameDimensions(first, *(bands.front()));
209 14 : bands.push_back(&first);
210 14 : }
211 : };
212 :
213 : inline static GDALComputedRasterBand
214 4 : minInternal(std::vector<const GDALRasterBand *> &bands, double constant)
215 : {
216 : return GDALComputedRasterBand(GDALComputedRasterBand::Operation::OP_MIN,
217 4 : bands, constant);
218 : }
219 :
220 : template <typename U, typename... V>
221 18 : GDALComputedRasterBand minInternal(std::vector<const GDALRasterBand *> &bands,
222 : double constant, const U &first, V &&...rest)
223 : {
224 18 : minDealFirstArg<U, void>::process(bands, constant, first);
225 16 : return minInternal(bands, constant, std::forward<V>(rest)...);
226 : }
227 :
228 : } // namespace detail
229 :
230 : template <typename U, typename... V>
231 6 : inline GDALComputedRasterBand min(const U &first, V &&...rest)
232 : {
233 12 : std::vector<const GDALRasterBand *> bands;
234 : return detail::minInternal(bands, std::numeric_limits<double>::quiet_NaN(),
235 10 : first, std::forward<V>(rest)...);
236 : }
237 :
238 : //! @endcond
239 :
240 : GDALComputedRasterBand CPL_DLL max(const GDALRasterBand &first,
241 : const GDALRasterBand &second);
242 :
243 : //! @cond Doxygen_Suppress
244 :
245 : namespace detail
246 : {
247 :
248 : template <typename U, typename Enable> struct maxDealFirstArg;
249 :
250 : template <typename U>
251 : struct maxDealFirstArg<
252 : U, typename std::enable_if<std::is_arithmetic<U>::value>::type>
253 : {
254 2 : inline static void process(std::vector<const GDALRasterBand *> &,
255 : double &constant, const U &first)
256 : {
257 2 : if (std::isnan(constant) || static_cast<double>(first) > constant)
258 2 : constant = static_cast<double>(first);
259 2 : }
260 : };
261 :
262 : template <typename U>
263 : struct maxDealFirstArg<
264 : U, typename std::enable_if<!std::is_arithmetic<U>::value>::type>
265 : {
266 14 : inline static void process(std::vector<const GDALRasterBand *> &bands,
267 : double &, const U &first)
268 : {
269 14 : if (!bands.empty())
270 9 : GDALRasterBand::ThrowIfNotSameDimensions(first, *(bands.front()));
271 12 : bands.push_back(&first);
272 12 : }
273 : };
274 :
275 : inline static GDALComputedRasterBand
276 3 : maxInternal(std::vector<const GDALRasterBand *> &bands, double constant)
277 : {
278 : return GDALComputedRasterBand(GDALComputedRasterBand::Operation::OP_MAX,
279 3 : bands, constant);
280 : }
281 :
282 : template <typename U, typename... V>
283 16 : GDALComputedRasterBand maxInternal(std::vector<const GDALRasterBand *> &bands,
284 : double constant, const U &first, V &&...rest)
285 : {
286 16 : maxDealFirstArg<U, void>::process(bands, constant, first);
287 14 : return maxInternal(bands, constant, std::forward<V>(rest)...);
288 : }
289 :
290 : } // namespace detail
291 :
292 : template <typename U, typename... V>
293 5 : inline GDALComputedRasterBand max(const U &first, V &&...rest)
294 : {
295 10 : std::vector<const GDALRasterBand *> bands;
296 : return detail::maxInternal(bands, std::numeric_limits<double>::quiet_NaN(),
297 8 : first, std::forward<V>(rest)...);
298 : }
299 :
300 : //! @endcond
301 :
302 : GDALComputedRasterBand CPL_DLL mean(const GDALRasterBand &first,
303 : const GDALRasterBand &second);
304 :
305 : //! @cond Doxygen_Suppress
306 : inline GDALComputedRasterBand
307 1 : meanInternal(std::vector<const GDALRasterBand *> &bands)
308 : {
309 : return GDALComputedRasterBand(GDALComputedRasterBand::Operation::OP_MEAN,
310 1 : bands);
311 : }
312 :
313 : template <typename U, typename... V>
314 : inline GDALComputedRasterBand
315 8 : meanInternal(std::vector<const GDALRasterBand *> &bands, const U &first,
316 : V &&...rest)
317 : {
318 8 : if (!bands.empty())
319 5 : GDALRasterBand::ThrowIfNotSameDimensions(first, *(bands.front()));
320 6 : bands.push_back(&first);
321 6 : return meanInternal(bands, std::forward<V>(rest)...);
322 : }
323 :
324 3 : template <typename... Args> inline GDALComputedRasterBand mean(Args &&...args)
325 : {
326 6 : std::vector<const GDALRasterBand *> bands;
327 4 : return meanInternal(bands, std::forward<Args>(args)...);
328 : }
329 :
330 : //! @endcond
331 :
332 : } // namespace gdal
333 :
334 : #endif
|