Coverage Report

Created: 2025-06-13 06:29

/src/gdal/alg/gdal_interpolateatpoint.cpp
Line
Count
Source (jump to first uncovered line)
1
/******************************************************************************
2
 * $Id$
3
 *
4
 * Project:  GDAL DEM Interpolation
5
 * Purpose:  Interpolation algorithms with cache
6
 * Author:   Frank Warmerdam, warmerdam@pobox.com
7
 *
8
 ******************************************************************************
9
 * Copyright (c) 2001, Frank Warmerdam
10
 * Copyright (c) 2008-2012, Even Rouault <even dot rouault at spatialys.com>
11
 * Copyright (c) 2024, Javier Jimenez Shaw
12
 *
13
 * SPDX-License-Identifier: MIT
14
 ****************************************************************************/
15
16
#include "gdal_interpolateatpoint.h"
17
18
#include "gdalresamplingkernels.h"
19
20
#include "gdal_vectorx.h"
21
22
#include <algorithm>
23
#include <complex>
24
25
template <typename T> bool areEqualReal(double dfNoDataValue, T dfOut);
26
27
template <> bool areEqualReal(double dfNoDataValue, double dfOut)
28
0
{
29
0
    return ARE_REAL_EQUAL(dfNoDataValue, dfOut);
30
0
}
31
32
template <> bool areEqualReal(double dfNoDataValue, std::complex<double> dfOut)
33
0
{
34
0
    return ARE_REAL_EQUAL(dfNoDataValue, dfOut.real());
35
0
}
36
37
// Only valid for T = double or std::complex<double>
38
template <typename T>
39
bool GDALInterpExtractValuesWindow(GDALRasterBand *pBand,
40
                                   std::unique_ptr<DoublePointsCache> &cache,
41
                                   gdal::Vector2i point,
42
                                   gdal::Vector2i dimensions, T *padfOut)
43
0
{
44
0
    constexpr int BLOCK_SIZE = 64;
45
46
0
    const int nX = point.x();
47
0
    const int nY = point.y();
48
0
    const int nWidth = dimensions.x();
49
0
    const int nHeight = dimensions.y();
50
51
    // Request the DEM by blocks of BLOCK_SIZE * BLOCK_SIZE and put them
52
    // in cache
53
0
    if (!cache)
54
0
        cache.reset(new DoublePointsCache{});
55
56
0
    const int nXIters = (nX + nWidth - 1) / BLOCK_SIZE - nX / BLOCK_SIZE + 1;
57
0
    const int nYIters = (nY + nHeight - 1) / BLOCK_SIZE - nY / BLOCK_SIZE + 1;
58
0
    const int nRasterXSize = pBand->GetXSize();
59
0
    const int nRasterYSize = pBand->GetYSize();
60
0
    const bool bIsComplex =
61
0
        CPL_TO_BOOL(GDALDataTypeIsComplex(pBand->GetRasterDataType()));
62
63
0
    for (int iY = 0; iY < nYIters; iY++)
64
0
    {
65
0
        const int nBlockY = nY / BLOCK_SIZE + iY;
66
0
        const int nReqYSize =
67
0
            std::min(nRasterYSize - nBlockY * BLOCK_SIZE, BLOCK_SIZE);
68
0
        const int nFirstLineInCachedBlock = (iY == 0) ? nY % BLOCK_SIZE : 0;
69
0
        const int nFirstLineInOutput =
70
0
            (iY == 0) ? 0
71
0
                      : BLOCK_SIZE - (nY % BLOCK_SIZE) + (iY - 1) * BLOCK_SIZE;
72
0
        const int nLinesToCopy = (nYIters == 1) ? nHeight
73
0
                                 : (iY == 0)    ? BLOCK_SIZE - (nY % BLOCK_SIZE)
74
0
                                 : (iY == nYIters - 1)
75
0
                                     ? 1 + (nY + nHeight - 1) % BLOCK_SIZE
76
0
                                     : BLOCK_SIZE;
77
0
        for (int iX = 0; iX < nXIters; iX++)
78
0
        {
79
0
            const int nBlockX = nX / BLOCK_SIZE + iX;
80
0
            const int nReqXSize =
81
0
                std::min(nRasterXSize - nBlockX * BLOCK_SIZE, BLOCK_SIZE);
82
0
            const uint64_t nKey =
83
0
                (static_cast<uint64_t>(nBlockY) << 32) | nBlockX;
84
0
            const int nFirstColInCachedBlock = (iX == 0) ? nX % BLOCK_SIZE : 0;
85
0
            const int nFirstColInOutput =
86
0
                (iX == 0)
87
0
                    ? 0
88
0
                    : BLOCK_SIZE - (nX % BLOCK_SIZE) + (iX - 1) * BLOCK_SIZE;
89
0
            const int nColsToCopy = (nXIters == 1) ? nWidth
90
0
                                    : (iX == 0) ? BLOCK_SIZE - (nX % BLOCK_SIZE)
91
0
                                    : (iX == nXIters - 1)
92
0
                                        ? 1 + (nX + nWidth - 1) % BLOCK_SIZE
93
0
                                        : BLOCK_SIZE;
94
95
#if 0
96
            CPLDebug("RPC", "nY=%d nX=%d nBlockY=%d nBlockX=%d "
97
                     "nFirstLineInCachedBlock=%d nFirstLineInOutput=%d nLinesToCopy=%d "
98
                     "nFirstColInCachedBlock=%d nFirstColInOutput=%d nColsToCopy=%d",
99
                     nY, nX, nBlockY, nBlockX, nFirstLineInCachedBlock, nFirstLineInOutput, nLinesToCopy,
100
                     nFirstColInCachedBlock, nFirstColInOutput, nColsToCopy);
101
#endif
102
103
0
            constexpr int nTypeFactor = sizeof(T) / sizeof(double);
104
0
            std::shared_ptr<std::vector<double>> poValue;
105
0
            if (!cache->tryGet(nKey, poValue))
106
0
            {
107
0
                const GDALDataType eDataType =
108
0
                    bIsComplex ? GDT_CFloat64 : GDT_Float64;
109
0
                const size_t nVectorSize =
110
0
                    size_t(nReqXSize) * nReqYSize * nTypeFactor;
111
0
                poValue = std::make_shared<std::vector<double>>(nVectorSize);
112
0
                CPLErr eErr = pBand->RasterIO(
113
0
                    GF_Read, nBlockX * BLOCK_SIZE, nBlockY * BLOCK_SIZE,
114
0
                    nReqXSize, nReqYSize, poValue->data(), nReqXSize, nReqYSize,
115
0
                    eDataType, 0, 0, nullptr);
116
0
                if (eErr != CE_None)
117
0
                {
118
0
                    return false;
119
0
                }
120
0
                cache->insert(nKey, poValue);
121
0
            }
122
123
0
            double *padfAsDouble = reinterpret_cast<double *>(padfOut);
124
            // Compose the cached block to the final buffer
125
0
            for (int j = 0; j < nLinesToCopy; j++)
126
0
            {
127
0
                const size_t dstOffset =
128
0
                    (static_cast<size_t>(nFirstLineInOutput + j) * nWidth +
129
0
                     nFirstColInOutput) *
130
0
                    nTypeFactor;
131
0
                const size_t srcOffset =
132
0
                    (static_cast<size_t>(nFirstLineInCachedBlock + j) *
133
0
                         nReqXSize +
134
0
                     nFirstColInCachedBlock) *
135
0
                    nTypeFactor;
136
0
                if (srcOffset + nColsToCopy * nTypeFactor > poValue->size())
137
0
                {
138
0
                    return false;
139
0
                }
140
0
                memcpy(padfAsDouble + dstOffset, poValue->data() + srcOffset,
141
0
                       nColsToCopy * sizeof(T));
142
0
            }
143
0
        }
144
0
    }
145
146
#if 0
147
    CPLDebug("RPC_DEM", "DEM for %d,%d,%d,%d", nX, nY, nWidth, nHeight);
148
    for(int j = 0; j < nHeight; j++)
149
    {
150
        std::string osLine;
151
        for(int i = 0; i < nWidth; ++i )
152
        {
153
            if( !osLine.empty() )
154
                osLine += ", ";
155
            osLine += std::to_string(padfOut[j * nWidth + i]);
156
        }
157
        CPLDebug("RPC_DEM", "%s", osLine.c_str());
158
    }
159
#endif
160
161
0
    return true;
162
0
}
Unexecuted instantiation: bool GDALInterpExtractValuesWindow<std::__1::complex<double> >(GDALRasterBand*, std::__1::unique_ptr<lru11::Cache<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > >, lru11::NullLock, std::__1::unordered_map<unsigned long, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*>, std::__1::hash<unsigned long>, std::__1::equal_to<unsigned long>, std::__1::allocator<std::__1::pair<unsigned long const, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*> > > > >, std::__1::default_delete<lru11::Cache<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > >, lru11::NullLock, std::__1::unordered_map<unsigned long, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*>, std::__1::hash<unsigned long>, std::__1::equal_to<unsigned long>, std::__1::allocator<std::__1::pair<unsigned long const, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*> > > > > > >&, gdal::VectorX<int, 2ul>, gdal::VectorX<int, 2ul>, std::__1::complex<double>*)
Unexecuted instantiation: bool GDALInterpExtractValuesWindow<double>(GDALRasterBand*, std::__1::unique_ptr<lru11::Cache<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > >, lru11::NullLock, std::__1::unordered_map<unsigned long, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*>, std::__1::hash<unsigned long>, std::__1::equal_to<unsigned long>, std::__1::allocator<std::__1::pair<unsigned long const, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*> > > > >, std::__1::default_delete<lru11::Cache<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > >, lru11::NullLock, std::__1::unordered_map<unsigned long, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*>, std::__1::hash<unsigned long>, std::__1::equal_to<unsigned long>, std::__1::allocator<std::__1::pair<unsigned long const, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*> > > > > > >&, gdal::VectorX<int, 2ul>, gdal::VectorX<int, 2ul>, double*)
163
164
template <typename T>
165
bool GDALInterpolateAtPointImpl(GDALRasterBand *pBand,
166
                                GDALRIOResampleAlg eResampleAlg,
167
                                std::unique_ptr<DoublePointsCache> &cache,
168
                                double dfXIn, double dfYIn, T &out)
169
0
{
170
0
    const gdal::Vector2i rasterSize{pBand->GetXSize(), pBand->GetYSize()};
171
172
0
    if (eResampleAlg == GRIORA_NearestNeighbour)
173
0
    {
174
        // Allow input coordinates right at the bottom or right edge
175
        // with GRIORA_NearestNeighbour.
176
        // "introduce" them in the pixel of the image.
177
0
        if (dfXIn >= rasterSize.x() && dfXIn <= rasterSize.x() + 1e-5)
178
0
            dfXIn -= 0.25;
179
0
        if (dfYIn >= rasterSize.y() && dfYIn <= rasterSize.y() + 1e-5)
180
0
            dfYIn -= 0.25;
181
0
    }
182
0
    const gdal::Vector2d inLoc{dfXIn, dfYIn};
183
184
0
    int bGotNoDataValue = FALSE;
185
0
    const double dfNoDataValue = pBand->GetNoDataValue(&bGotNoDataValue);
186
187
0
    if (inLoc.x() < 0 || inLoc.x() > rasterSize.x() || inLoc.y() < 0 ||
188
0
        inLoc.y() > rasterSize.y())
189
0
    {
190
0
        return FALSE;
191
0
    }
192
193
    // Downgrade the interpolation algorithm if the image is too small
194
0
    if ((rasterSize.x() < 4 || rasterSize.y() < 4) &&
195
0
        (eResampleAlg == GRIORA_CubicSpline || eResampleAlg == GRIORA_Cubic))
196
0
    {
197
0
        eResampleAlg = GRIORA_Bilinear;
198
0
    }
199
0
    if ((rasterSize.x() < 2 || rasterSize.y() < 2) &&
200
0
        eResampleAlg == GRIORA_Bilinear)
201
0
    {
202
0
        eResampleAlg = GRIORA_NearestNeighbour;
203
0
    }
204
205
0
    auto outOfBorderCorrectionSimple =
206
0
        [](int dNew, int nRasterSize, int nKernelsize)
207
0
    {
208
0
        int dOutOfBorder = 0;
209
0
        if (dNew < 0)
210
0
        {
211
0
            dOutOfBorder = dNew;
212
0
        }
213
0
        if (dNew + nKernelsize >= nRasterSize)
214
0
        {
215
0
            dOutOfBorder = dNew + nKernelsize - nRasterSize;
216
0
        }
217
0
        return dOutOfBorder;
218
0
    };
Unexecuted instantiation: GDALInterpolateAtPointImpl<std::__1::complex<double> >(GDALRasterBand*, GDALRIOResampleAlg, std::__1::unique_ptr<lru11::Cache<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > >, lru11::NullLock, std::__1::unordered_map<unsigned long, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*>, std::__1::hash<unsigned long>, std::__1::equal_to<unsigned long>, std::__1::allocator<std::__1::pair<unsigned long const, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*> > > > >, std::__1::default_delete<lru11::Cache<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > >, lru11::NullLock, std::__1::unordered_map<unsigned long, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*>, std::__1::hash<unsigned long>, std::__1::equal_to<unsigned long>, std::__1::allocator<std::__1::pair<unsigned long const, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*> > > > > > >&, double, double, std::__1::complex<double>&)::{lambda(int, int, int)#1}::operator()(int, int, int) const
Unexecuted instantiation: GDALInterpolateAtPointImpl<double>(GDALRasterBand*, GDALRIOResampleAlg, std::__1::unique_ptr<lru11::Cache<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > >, lru11::NullLock, std::__1::unordered_map<unsigned long, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*>, std::__1::hash<unsigned long>, std::__1::equal_to<unsigned long>, std::__1::allocator<std::__1::pair<unsigned long const, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*> > > > >, std::__1::default_delete<lru11::Cache<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > >, lru11::NullLock, std::__1::unordered_map<unsigned long, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*>, std::__1::hash<unsigned long>, std::__1::equal_to<unsigned long>, std::__1::allocator<std::__1::pair<unsigned long const, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*> > > > > > >&, double, double, double&)::{lambda(int, int, int)#1}::operator()(int, int, int) const
219
220
0
    auto outOfBorderCorrection =
221
0
        [&outOfBorderCorrectionSimple,
222
0
         &rasterSize](gdal::Vector2i input, int nKernelsize) -> gdal::Vector2i
223
0
    {
224
0
        return {
225
0
            outOfBorderCorrectionSimple(input.x(), rasterSize.x(), nKernelsize),
226
0
            outOfBorderCorrectionSimple(input.y(), rasterSize.y(),
227
0
                                        nKernelsize)};
228
0
    };
Unexecuted instantiation: GDALInterpolateAtPointImpl<std::__1::complex<double> >(GDALRasterBand*, GDALRIOResampleAlg, std::__1::unique_ptr<lru11::Cache<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > >, lru11::NullLock, std::__1::unordered_map<unsigned long, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*>, std::__1::hash<unsigned long>, std::__1::equal_to<unsigned long>, std::__1::allocator<std::__1::pair<unsigned long const, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*> > > > >, std::__1::default_delete<lru11::Cache<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > >, lru11::NullLock, std::__1::unordered_map<unsigned long, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*>, std::__1::hash<unsigned long>, std::__1::equal_to<unsigned long>, std::__1::allocator<std::__1::pair<unsigned long const, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*> > > > > > >&, double, double, std::__1::complex<double>&)::{lambda(gdal::VectorX<int, 2ul>, int)#1}::operator()(gdal::VectorX<int, 2ul>, int) const
Unexecuted instantiation: GDALInterpolateAtPointImpl<double>(GDALRasterBand*, GDALRIOResampleAlg, std::__1::unique_ptr<lru11::Cache<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > >, lru11::NullLock, std::__1::unordered_map<unsigned long, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*>, std::__1::hash<unsigned long>, std::__1::equal_to<unsigned long>, std::__1::allocator<std::__1::pair<unsigned long const, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*> > > > >, std::__1::default_delete<lru11::Cache<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > >, lru11::NullLock, std::__1::unordered_map<unsigned long, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*>, std::__1::hash<unsigned long>, std::__1::equal_to<unsigned long>, std::__1::allocator<std::__1::pair<unsigned long const, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*> > > > > > >&, double, double, double&)::{lambda(gdal::VectorX<int, 2ul>, int)#1}::operator()(gdal::VectorX<int, 2ul>, int) const
229
230
0
    auto dragReadDataInBorderSimple =
231
0
        [](T *adfElevData, int dOutOfBorder, int nKernelSize, bool bIsX)
232
0
    {
233
0
        while (dOutOfBorder < 0)
234
0
        {
235
0
            for (int j = 0; j < nKernelSize; j++)
236
0
                for (int ii = 0; ii < nKernelSize - 1; ii++)
237
0
                {
238
0
                    const int i = nKernelSize - ii - 2;  // iterate in reverse
239
0
                    const int row_src = bIsX ? j : i;
240
0
                    const int row_dst = bIsX ? j : i + 1;
241
0
                    const int col_src = bIsX ? i : j;
242
0
                    const int col_dst = bIsX ? i + 1 : j;
243
0
                    adfElevData[nKernelSize * row_dst + col_dst] =
244
0
                        adfElevData[nKernelSize * row_src + col_src];
245
0
                }
246
0
            dOutOfBorder++;
247
0
        }
248
0
        while (dOutOfBorder > 0)
249
0
        {
250
0
            for (int j = 0; j < nKernelSize; j++)
251
0
                for (int i = 0; i < nKernelSize - 1; i++)
252
0
                {
253
0
                    const int row_src = bIsX ? j : i + 1;
254
0
                    const int row_dst = bIsX ? j : i;
255
0
                    const int col_src = bIsX ? i + 1 : j;
256
0
                    const int col_dst = bIsX ? i : j;
257
0
                    adfElevData[nKernelSize * row_dst + col_dst] =
258
0
                        adfElevData[nKernelSize * row_src + col_src];
259
0
                }
260
0
            dOutOfBorder--;
261
0
        }
262
0
    };
Unexecuted instantiation: GDALInterpolateAtPointImpl<std::__1::complex<double> >(GDALRasterBand*, GDALRIOResampleAlg, std::__1::unique_ptr<lru11::Cache<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > >, lru11::NullLock, std::__1::unordered_map<unsigned long, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*>, std::__1::hash<unsigned long>, std::__1::equal_to<unsigned long>, std::__1::allocator<std::__1::pair<unsigned long const, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*> > > > >, std::__1::default_delete<lru11::Cache<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > >, lru11::NullLock, std::__1::unordered_map<unsigned long, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*>, std::__1::hash<unsigned long>, std::__1::equal_to<unsigned long>, std::__1::allocator<std::__1::pair<unsigned long const, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*> > > > > > >&, double, double, std::__1::complex<double>&)::{lambda(std::__1::complex<double>*, int, int, bool)#1}::operator()(std::__1::complex<double>*, int, int, bool) const
Unexecuted instantiation: GDALInterpolateAtPointImpl<double>(GDALRasterBand*, GDALRIOResampleAlg, std::__1::unique_ptr<lru11::Cache<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > >, lru11::NullLock, std::__1::unordered_map<unsigned long, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*>, std::__1::hash<unsigned long>, std::__1::equal_to<unsigned long>, std::__1::allocator<std::__1::pair<unsigned long const, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*> > > > >, std::__1::default_delete<lru11::Cache<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > >, lru11::NullLock, std::__1::unordered_map<unsigned long, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*>, std::__1::hash<unsigned long>, std::__1::equal_to<unsigned long>, std::__1::allocator<std::__1::pair<unsigned long const, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*> > > > > > >&, double, double, double&)::{lambda(double*, int, int, bool)#1}::operator()(double*, int, int, bool) const
263
0
    auto dragReadDataInBorder = [&dragReadDataInBorderSimple](
264
0
                                    T *adfElevData, gdal::Vector2i dOutOfBorder,
265
0
                                    int nKernelSize) -> void
266
0
    {
267
0
        dragReadDataInBorderSimple(adfElevData, dOutOfBorder.x(), nKernelSize,
268
0
                                   true);
269
0
        dragReadDataInBorderSimple(adfElevData, dOutOfBorder.y(), nKernelSize,
270
0
                                   false);
271
0
    };
Unexecuted instantiation: GDALInterpolateAtPointImpl<std::__1::complex<double> >(GDALRasterBand*, GDALRIOResampleAlg, std::__1::unique_ptr<lru11::Cache<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > >, lru11::NullLock, std::__1::unordered_map<unsigned long, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*>, std::__1::hash<unsigned long>, std::__1::equal_to<unsigned long>, std::__1::allocator<std::__1::pair<unsigned long const, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*> > > > >, std::__1::default_delete<lru11::Cache<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > >, lru11::NullLock, std::__1::unordered_map<unsigned long, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*>, std::__1::hash<unsigned long>, std::__1::equal_to<unsigned long>, std::__1::allocator<std::__1::pair<unsigned long const, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*> > > > > > >&, double, double, std::__1::complex<double>&)::{lambda(std::__1::complex<double>*, gdal::VectorX<int, 2ul>, int)#1}::operator()(std::__1::complex<double>*, gdal::VectorX<int, 2ul>, int) const
Unexecuted instantiation: GDALInterpolateAtPointImpl<double>(GDALRasterBand*, GDALRIOResampleAlg, std::__1::unique_ptr<lru11::Cache<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > >, lru11::NullLock, std::__1::unordered_map<unsigned long, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*>, std::__1::hash<unsigned long>, std::__1::equal_to<unsigned long>, std::__1::allocator<std::__1::pair<unsigned long const, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*> > > > >, std::__1::default_delete<lru11::Cache<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > >, lru11::NullLock, std::__1::unordered_map<unsigned long, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*>, std::__1::hash<unsigned long>, std::__1::equal_to<unsigned long>, std::__1::allocator<std::__1::pair<unsigned long const, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*> > > > > > >&, double, double, double&)::{lambda(double*, gdal::VectorX<int, 2ul>, int)#1}::operator()(double*, gdal::VectorX<int, 2ul>, int) const
272
273
0
    auto applyBilinearKernel = [&](gdal::Vector2d dfDelta, T *adfValues,
274
0
                                   T &pdfRes) -> bool
275
0
    {
276
0
        if (bGotNoDataValue)
277
0
        {
278
            // TODO: We could perhaps use a valid sample if there's one.
279
0
            bool bFoundNoDataElev = false;
280
0
            for (int k_i = 0; k_i < 4; k_i++)
281
0
            {
282
0
                if (areEqualReal(dfNoDataValue, adfValues[k_i]))
283
0
                    bFoundNoDataElev = true;
284
0
            }
285
0
            if (bFoundNoDataElev)
286
0
            {
287
0
                return FALSE;
288
0
            }
289
0
        }
290
0
        const gdal::Vector2d dfDelta1 = 1.0 - dfDelta;
291
292
0
        const T dfXZ1 =
293
0
            adfValues[0] * dfDelta1.x() + adfValues[1] * dfDelta.x();
294
0
        const T dfXZ2 =
295
0
            adfValues[2] * dfDelta1.x() + adfValues[3] * dfDelta.x();
296
0
        const T dfYZ = dfXZ1 * dfDelta1.y() + dfXZ2 * dfDelta.y();
297
298
0
        pdfRes = dfYZ;
299
0
        return TRUE;
300
0
    };
Unexecuted instantiation: GDALInterpolateAtPointImpl<std::__1::complex<double> >(GDALRasterBand*, GDALRIOResampleAlg, std::__1::unique_ptr<lru11::Cache<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > >, lru11::NullLock, std::__1::unordered_map<unsigned long, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*>, std::__1::hash<unsigned long>, std::__1::equal_to<unsigned long>, std::__1::allocator<std::__1::pair<unsigned long const, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*> > > > >, std::__1::default_delete<lru11::Cache<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > >, lru11::NullLock, std::__1::unordered_map<unsigned long, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*>, std::__1::hash<unsigned long>, std::__1::equal_to<unsigned long>, std::__1::allocator<std::__1::pair<unsigned long const, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*> > > > > > >&, double, double, std::__1::complex<double>&)::{lambda(gdal::VectorX<double, 2ul>, std::__1::complex<double>*, std::__1::complex<double>&)#1}::operator()(gdal::VectorX<double, 2ul>, std::__1::complex<double>*, std::__1::complex<double>&) const
Unexecuted instantiation: GDALInterpolateAtPointImpl<double>(GDALRasterBand*, GDALRIOResampleAlg, std::__1::unique_ptr<lru11::Cache<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > >, lru11::NullLock, std::__1::unordered_map<unsigned long, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*>, std::__1::hash<unsigned long>, std::__1::equal_to<unsigned long>, std::__1::allocator<std::__1::pair<unsigned long const, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*> > > > >, std::__1::default_delete<lru11::Cache<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > >, lru11::NullLock, std::__1::unordered_map<unsigned long, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*>, std::__1::hash<unsigned long>, std::__1::equal_to<unsigned long>, std::__1::allocator<std::__1::pair<unsigned long const, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*> > > > > > >&, double, double, double&)::{lambda(gdal::VectorX<double, 2ul>, double*, double&)#1}::operator()(gdal::VectorX<double, 2ul>, double*, double&) const
301
302
0
    auto apply4x4Kernel = [&](gdal::Vector2d dfDelta, T *adfValues,
303
0
                              T &pdfRes) -> bool
304
0
    {
305
0
        T dfSumH = 0.0;
306
0
        T dfSumWeight = 0.0;
307
0
        for (int k_i = 0; k_i < 4; k_i++)
308
0
        {
309
            // Loop across the X axis.
310
0
            for (int k_j = 0; k_j < 4; k_j++)
311
0
            {
312
                // Calculate the weight for the specified pixel according
313
                // to the bicubic b-spline kernel we're using for
314
                // interpolation.
315
0
                const gdal::Vector2i dKernInd = {k_j - 1, k_i - 1};
316
0
                const gdal::Vector2d fPoint = dKernInd.cast<double>() - dfDelta;
317
0
                const double dfPixelWeight =
318
0
                    eResampleAlg == GDALRIOResampleAlg::GRIORA_CubicSpline
319
0
                        ? CubicSplineKernel(fPoint.x()) *
320
0
                              CubicSplineKernel(fPoint.y())
321
0
                        : CubicKernel(fPoint.x()) * CubicKernel(fPoint.y());
322
323
                // Create a sum of all values
324
                // adjusted for the pixel's calculated weight.
325
0
                const T dfElev = adfValues[k_j + k_i * 4];
326
0
                if (bGotNoDataValue && areEqualReal(dfNoDataValue, dfElev))
327
0
                    continue;
328
329
0
                dfSumH += dfElev * dfPixelWeight;
330
0
                dfSumWeight += dfPixelWeight;
331
0
            }
332
0
        }
333
0
        if (dfSumWeight == 0.0)
334
0
        {
335
0
            return FALSE;
336
0
        }
337
338
0
        pdfRes = dfSumH / dfSumWeight;
339
340
0
        return TRUE;
341
0
    };
Unexecuted instantiation: GDALInterpolateAtPointImpl<std::__1::complex<double> >(GDALRasterBand*, GDALRIOResampleAlg, std::__1::unique_ptr<lru11::Cache<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > >, lru11::NullLock, std::__1::unordered_map<unsigned long, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*>, std::__1::hash<unsigned long>, std::__1::equal_to<unsigned long>, std::__1::allocator<std::__1::pair<unsigned long const, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*> > > > >, std::__1::default_delete<lru11::Cache<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > >, lru11::NullLock, std::__1::unordered_map<unsigned long, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*>, std::__1::hash<unsigned long>, std::__1::equal_to<unsigned long>, std::__1::allocator<std::__1::pair<unsigned long const, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*> > > > > > >&, double, double, std::__1::complex<double>&)::{lambda(gdal::VectorX<double, 2ul>, std::__1::complex<double>*, std::__1::complex<double>&)#2}::operator()(gdal::VectorX<double, 2ul>, std::__1::complex<double>*, std::__1::complex<double>&) const
Unexecuted instantiation: GDALInterpolateAtPointImpl<double>(GDALRasterBand*, GDALRIOResampleAlg, std::__1::unique_ptr<lru11::Cache<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > >, lru11::NullLock, std::__1::unordered_map<unsigned long, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*>, std::__1::hash<unsigned long>, std::__1::equal_to<unsigned long>, std::__1::allocator<std::__1::pair<unsigned long const, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*> > > > >, std::__1::default_delete<lru11::Cache<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > >, lru11::NullLock, std::__1::unordered_map<unsigned long, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*>, std::__1::hash<unsigned long>, std::__1::equal_to<unsigned long>, std::__1::allocator<std::__1::pair<unsigned long const, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*> > > > > > >&, double, double, double&)::{lambda(gdal::VectorX<double, 2ul>, double*, double&)#2}::operator()(gdal::VectorX<double, 2ul>, double*, double&) const
342
343
0
    if (eResampleAlg == GDALRIOResampleAlg::GRIORA_CubicSpline ||
344
0
        eResampleAlg == GDALRIOResampleAlg::GRIORA_Cubic)
345
0
    {
346
        // Convert from upper left corner of pixel coordinates to center of
347
        // pixel coordinates:
348
0
        const gdal::Vector2d df = inLoc - 0.5;
349
0
        const gdal::Vector2i d = df.floor().template cast<int>();
350
0
        const gdal::Vector2d delta = df - d.cast<double>();
351
0
        const gdal::Vector2i dNew = d - 1;
352
0
        const int nKernelSize = 4;
353
0
        const gdal::Vector2i dOutOfBorder =
354
0
            outOfBorderCorrection(dNew, nKernelSize);
355
356
        // CubicSpline interpolation.
357
0
        T adfReadData[16] = {0.0};
358
0
        if (!GDALInterpExtractValuesWindow(pBand, cache, dNew - dOutOfBorder,
359
0
                                           {nKernelSize, nKernelSize},
360
0
                                           adfReadData))
361
0
        {
362
0
            return FALSE;
363
0
        }
364
0
        dragReadDataInBorder(adfReadData, dOutOfBorder, nKernelSize);
365
0
        if (!apply4x4Kernel(delta, adfReadData, out))
366
0
            return FALSE;
367
368
0
        return TRUE;
369
0
    }
370
0
    else if (eResampleAlg == GDALRIOResampleAlg::GRIORA_Bilinear)
371
0
    {
372
        // Convert from upper left corner of pixel coordinates to center of
373
        // pixel coordinates:
374
0
        const gdal::Vector2d df = inLoc - 0.5;
375
0
        const gdal::Vector2i d = df.floor().template cast<int>();
376
0
        const gdal::Vector2d delta = df - d.cast<double>();
377
0
        const int nKernelSize = 2;
378
0
        const gdal::Vector2i dOutOfBorder =
379
0
            outOfBorderCorrection(d, nKernelSize);
380
381
        // Bilinear interpolation.
382
0
        T adfReadData[4] = {0.0};
383
0
        if (!GDALInterpExtractValuesWindow(pBand, cache, d - dOutOfBorder,
384
0
                                           {nKernelSize, nKernelSize},
385
0
                                           adfReadData))
386
0
        {
387
0
            return FALSE;
388
0
        }
389
0
        dragReadDataInBorder(adfReadData, dOutOfBorder, nKernelSize);
390
0
        if (!applyBilinearKernel(delta, adfReadData, out))
391
0
            return FALSE;
392
393
0
        return TRUE;
394
0
    }
395
0
    else
396
0
    {
397
0
        const gdal::Vector2i d = inLoc.cast<int>();
398
0
        T adfOut[1] = {};
399
0
        if (!GDALInterpExtractValuesWindow(pBand, cache, d, {1, 1}, adfOut) ||
400
0
            (bGotNoDataValue && areEqualReal(dfNoDataValue, adfOut[0])))
401
0
        {
402
0
            return FALSE;
403
0
        }
404
405
0
        out = adfOut[0];
406
407
0
        return TRUE;
408
0
    }
409
0
}
Unexecuted instantiation: bool GDALInterpolateAtPointImpl<std::__1::complex<double> >(GDALRasterBand*, GDALRIOResampleAlg, std::__1::unique_ptr<lru11::Cache<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > >, lru11::NullLock, std::__1::unordered_map<unsigned long, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*>, std::__1::hash<unsigned long>, std::__1::equal_to<unsigned long>, std::__1::allocator<std::__1::pair<unsigned long const, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*> > > > >, std::__1::default_delete<lru11::Cache<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > >, lru11::NullLock, std::__1::unordered_map<unsigned long, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*>, std::__1::hash<unsigned long>, std::__1::equal_to<unsigned long>, std::__1::allocator<std::__1::pair<unsigned long const, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*> > > > > > >&, double, double, std::__1::complex<double>&)
Unexecuted instantiation: bool GDALInterpolateAtPointImpl<double>(GDALRasterBand*, GDALRIOResampleAlg, std::__1::unique_ptr<lru11::Cache<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > >, lru11::NullLock, std::__1::unordered_map<unsigned long, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*>, std::__1::hash<unsigned long>, std::__1::equal_to<unsigned long>, std::__1::allocator<std::__1::pair<unsigned long const, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*> > > > >, std::__1::default_delete<lru11::Cache<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > >, lru11::NullLock, std::__1::unordered_map<unsigned long, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*>, std::__1::hash<unsigned long>, std::__1::equal_to<unsigned long>, std::__1::allocator<std::__1::pair<unsigned long const, std::__1::__list_iterator<lru11::KeyValuePair<unsigned long, std::__1::shared_ptr<std::__1::vector<double, std::__1::allocator<double> > > >, void*> > > > > > >&, double, double, double&)
410
411
/************************************************************************/
412
/*                        GDALInterpolateAtPoint()                      */
413
/************************************************************************/
414
415
bool GDALInterpolateAtPoint(GDALRasterBand *pBand,
416
                            GDALRIOResampleAlg eResampleAlg,
417
                            std::unique_ptr<DoublePointsCache> &cache,
418
                            const double dfXIn, const double dfYIn,
419
                            double *pdfOutputReal, double *pdfOutputImag)
420
0
{
421
0
    const bool bIsComplex =
422
0
        CPL_TO_BOOL(GDALDataTypeIsComplex(pBand->GetRasterDataType()));
423
0
    bool res = TRUE;
424
0
    if (bIsComplex)
425
0
    {
426
0
        std::complex<double> out{};
427
0
        res = GDALInterpolateAtPointImpl(pBand, eResampleAlg, cache, dfXIn,
428
0
                                         dfYIn, out);
429
0
        *pdfOutputReal = out.real();
430
0
        if (pdfOutputImag)
431
0
            *pdfOutputImag = out.imag();
432
0
    }
433
0
    else
434
0
    {
435
0
        double out{};
436
0
        res = GDALInterpolateAtPointImpl(pBand, eResampleAlg, cache, dfXIn,
437
0
                                         dfYIn, out);
438
0
        *pdfOutputReal = out;
439
0
        if (pdfOutputImag)
440
0
            *pdfOutputImag = 0;
441
0
    }
442
0
    return res;
443
0
}