Line data Source code
1 : /******************************************************************************
2 : * Name: gdalmultidim_rat.cpp
3 : * Project: GDAL Core
4 : * Purpose: GDALCreateRasterAttributeTableFromMDArrays() implementation
5 : * Author: Even Rouault <even.rouault at spatialys.com>
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2023, Even Rouault <even.rouault at spatialys.com>
9 : *
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #include "gdal_priv.h"
14 : #include "gdal_rat.h"
15 : #include "gdalmultidim_priv.h"
16 :
17 : /************************************************************************/
18 : /* GDALRasterAttributeTableFromMDArrays() */
19 : /************************************************************************/
20 :
21 : class GDALRasterAttributeTableFromMDArrays final
22 : : public GDALRasterAttributeTable
23 : {
24 : const GDALRATTableType m_eTableType;
25 : const std::vector<std::shared_ptr<GDALMDArray>> m_apoArrays;
26 : const std::vector<GDALRATFieldUsage> m_aeUsages;
27 :
28 : mutable std::string m_osTmp{};
29 :
30 : public:
31 : GDALRasterAttributeTableFromMDArrays(
32 : GDALRATTableType eTableType,
33 : const std::vector<std::shared_ptr<GDALMDArray>> &apoArrays,
34 : const std::vector<GDALRATFieldUsage> &aeUsages);
35 :
36 : //
37 1 : GDALRasterAttributeTable *Clone() const override
38 : {
39 : return new GDALRasterAttributeTableFromMDArrays(
40 1 : m_eTableType, m_apoArrays, m_aeUsages);
41 : }
42 :
43 : //
44 36 : int GetColumnCount() const override
45 : {
46 36 : return static_cast<int>(m_apoArrays.size());
47 : }
48 :
49 3 : const char *GetNameOfCol(int iCol) const override
50 : {
51 3 : if (iCol < 0 || iCol >= GetColumnCount())
52 2 : return nullptr;
53 1 : return m_apoArrays[iCol]->GetName().c_str();
54 : }
55 :
56 : //
57 9 : GDALRATFieldUsage GetUsageOfCol(int iCol) const override
58 : {
59 9 : if (iCol < 0 || iCol >= GetColumnCount() || m_aeUsages.empty())
60 3 : return GFU_Generic;
61 6 : return m_aeUsages[iCol];
62 : }
63 :
64 : //
65 5 : GDALRATFieldType GetTypeOfCol(int iCol) const override
66 : {
67 5 : if (iCol < 0 || iCol >= GetColumnCount())
68 2 : return GFT_Integer;
69 3 : switch (m_apoArrays[iCol]->GetDataType().GetNumericDataType())
70 : {
71 1 : case GDT_Int8:
72 : case GDT_Byte:
73 : case GDT_UInt16:
74 : case GDT_Int16:
75 : case GDT_Int32:
76 1 : return GFT_Integer;
77 1 : case GDT_UInt32:
78 : case GDT_Int64:
79 : case GDT_UInt64:
80 : case GDT_Float16:
81 : case GDT_Float32:
82 : case GDT_Float64:
83 1 : return GFT_Real;
84 1 : default:
85 1 : break;
86 : }
87 1 : return GFT_String;
88 : }
89 :
90 : //
91 2 : int GetColOfUsage(GDALRATFieldUsage eUsage) const override
92 : {
93 2 : const int nColCount = GetColumnCount();
94 6 : for (int i = 0; i < nColCount; i++)
95 : {
96 5 : if (GetUsageOfCol(i) == eUsage)
97 1 : return i;
98 : }
99 :
100 1 : return -1;
101 : }
102 :
103 : //
104 25 : int GetRowCount() const override
105 : {
106 25 : return static_cast<int>(m_apoArrays[0]->GetDimensions()[0]->GetSize());
107 : }
108 :
109 : //
110 4 : const char *GetValueAsString(int iRow, int iField) const override
111 : {
112 6 : if (iRow < 0 || iRow >= GetRowCount() || iField < 0 ||
113 2 : iField >= GetColumnCount())
114 2 : return nullptr;
115 :
116 2 : const GUInt64 arrayStartIdx[1] = {static_cast<GUInt64>(iRow)};
117 2 : const size_t count[1] = {1};
118 2 : const GInt64 arrayStep[1] = {1};
119 2 : const GPtrDiff_t bufferStride[1] = {1};
120 2 : char *pszStr = nullptr;
121 2 : void *pDstBuffer = &pszStr;
122 4 : if (!m_apoArrays[iField]->Read(
123 : arrayStartIdx, count, arrayStep, bufferStride,
124 4 : GDALExtendedDataType::CreateString(), pDstBuffer))
125 0 : return nullptr;
126 2 : if (!pszStr)
127 0 : return nullptr;
128 2 : m_osTmp = pszStr;
129 2 : CPLFree(pszStr);
130 2 : return m_osTmp.c_str();
131 : }
132 :
133 : //
134 4 : int GetValueAsInt(int iRow, int iField) const override
135 : {
136 6 : if (iRow < 0 || iRow >= GetRowCount() || iField < 0 ||
137 2 : iField >= GetColumnCount())
138 2 : return 0;
139 :
140 2 : const GUInt64 arrayStartIdx[1] = {static_cast<GUInt64>(iRow)};
141 2 : const size_t count[1] = {1};
142 2 : const GInt64 arrayStep[1] = {1};
143 2 : const GPtrDiff_t bufferStride[1] = {1};
144 2 : int nVal = 0;
145 2 : void *pDstBuffer = &nVal;
146 4 : if (!m_apoArrays[iField]->Read(
147 : arrayStartIdx, count, arrayStep, bufferStride,
148 4 : GDALExtendedDataType::Create(GDT_Int32), pDstBuffer))
149 0 : return 0;
150 2 : return nVal;
151 : }
152 :
153 : //
154 4 : double GetValueAsDouble(int iRow, int iField) const override
155 : {
156 6 : if (iRow < 0 || iRow >= GetRowCount() || iField < 0 ||
157 2 : iField >= GetColumnCount())
158 2 : return 0;
159 :
160 2 : const GUInt64 arrayStartIdx[1] = {static_cast<GUInt64>(iRow)};
161 2 : const size_t count[1] = {1};
162 2 : const GInt64 arrayStep[1] = {1};
163 2 : const GPtrDiff_t bufferStride[1] = {1};
164 2 : double dfVal = 0;
165 2 : void *pDstBuffer = &dfVal;
166 4 : if (!m_apoArrays[iField]->Read(
167 : arrayStartIdx, count, arrayStep, bufferStride,
168 4 : GDALExtendedDataType::Create(GDT_Float64), pDstBuffer))
169 0 : return 0;
170 2 : return dfVal;
171 : }
172 :
173 : //
174 5 : CPLErr ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength,
175 : double *pdfData) override
176 : {
177 5 : if (eRWFlag != GF_Read)
178 : {
179 0 : CPLError(CE_Failure, CPLE_NotSupported,
180 : "GDALRasterAttributeTableFromMDArrays::ValuesIO(): "
181 : "eRWFlag != GF_Read not supported");
182 0 : return CE_Failure;
183 : }
184 9 : if (iStartRow < 0 || iLength <= 0 ||
185 4 : iStartRow > GetRowCount() - iLength)
186 : {
187 2 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid iStartRow/iLength");
188 2 : return CE_Failure;
189 : }
190 3 : if (iField < 0 || iField >= GetColumnCount())
191 : {
192 2 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid iField");
193 2 : return CE_Failure;
194 : }
195 1 : const GUInt64 arrayStartIdx[1] = {static_cast<GUInt64>(iStartRow)};
196 1 : const size_t count[1] = {static_cast<size_t>(iLength)};
197 1 : const GInt64 arrayStep[1] = {1};
198 1 : const GPtrDiff_t bufferStride[1] = {1};
199 2 : if (!m_apoArrays[iField]->Read(
200 : arrayStartIdx, count, arrayStep, bufferStride,
201 2 : GDALExtendedDataType::Create(GDT_Float64), pdfData))
202 0 : return CE_Failure;
203 1 : return CE_None;
204 : }
205 :
206 : //
207 5 : CPLErr ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength,
208 : int *pnData) override
209 : {
210 5 : if (eRWFlag != GF_Read)
211 : {
212 0 : CPLError(CE_Failure, CPLE_NotSupported,
213 : "GDALRasterAttributeTableFromMDArrays::ValuesIO(): "
214 : "eRWFlag != GF_Read not supported");
215 0 : return CE_Failure;
216 : }
217 9 : if (iStartRow < 0 || iLength <= 0 ||
218 4 : iStartRow > GetRowCount() - iLength)
219 : {
220 2 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid iStartRow/iLength");
221 2 : return CE_Failure;
222 : }
223 3 : if (iField < 0 || iField >= GetColumnCount())
224 : {
225 2 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid iField");
226 2 : return CE_Failure;
227 : }
228 1 : const GUInt64 arrayStartIdx[1] = {static_cast<GUInt64>(iStartRow)};
229 1 : const size_t count[1] = {static_cast<size_t>(iLength)};
230 1 : const GInt64 arrayStep[1] = {1};
231 1 : const GPtrDiff_t bufferStride[1] = {1};
232 2 : if (!m_apoArrays[iField]->Read(
233 : arrayStartIdx, count, arrayStep, bufferStride,
234 2 : GDALExtendedDataType::Create(GDT_Int32), pnData))
235 0 : return CE_Failure;
236 1 : return CE_None;
237 : }
238 :
239 : //
240 5 : CPLErr ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength,
241 : char **papszStrList) override
242 : {
243 5 : if (eRWFlag != GF_Read)
244 : {
245 0 : CPLError(CE_Failure, CPLE_NotSupported,
246 : "GDALRasterAttributeTableFromMDArrays::ValuesIO(): "
247 : "eRWFlag != GF_Read not supported");
248 0 : return CE_Failure;
249 : }
250 9 : if (iStartRow < 0 || iLength <= 0 ||
251 4 : iStartRow > GetRowCount() - iLength)
252 : {
253 2 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid iStartRow/iLength");
254 2 : return CE_Failure;
255 : }
256 3 : if (iField < 0 || iField >= GetColumnCount())
257 : {
258 2 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid iField");
259 2 : return CE_Failure;
260 : }
261 1 : const GUInt64 arrayStartIdx[1] = {static_cast<GUInt64>(iStartRow)};
262 1 : const size_t count[1] = {static_cast<size_t>(iLength)};
263 1 : const GInt64 arrayStep[1] = {1};
264 1 : const GPtrDiff_t bufferStride[1] = {1};
265 2 : if (!m_apoArrays[iField]->Read(
266 : arrayStartIdx, count, arrayStep, bufferStride,
267 2 : GDALExtendedDataType::CreateString(), papszStrList))
268 0 : return CE_Failure;
269 1 : return CE_None;
270 : }
271 :
272 : //
273 1 : void SetValue(int, int, const char *) override
274 : {
275 1 : CPLError(
276 : CE_Failure, CPLE_NotSupported,
277 : "GDALRasterAttributeTableFromMDArrays::SetValue(): not supported");
278 1 : }
279 :
280 : //
281 1 : void SetValue(int, int, int) override
282 : {
283 1 : CPLError(
284 : CE_Failure, CPLE_NotSupported,
285 : "GDALRasterAttributeTableFromMDArrays::SetValue(): not supported");
286 1 : }
287 :
288 : //
289 1 : void SetValue(int, int, double) override
290 : {
291 1 : CPLError(
292 : CE_Failure, CPLE_NotSupported,
293 : "GDALRasterAttributeTableFromMDArrays::SetValue(): not supported");
294 1 : }
295 :
296 : //
297 1 : int ChangesAreWrittenToFile() override
298 : {
299 1 : return false;
300 : }
301 :
302 : //
303 1 : CPLErr SetTableType(const GDALRATTableType) override
304 : {
305 1 : CPLError(CE_Failure, CPLE_NotSupported,
306 : "GDALRasterAttributeTableFromMDArrays::SetTableType(): not "
307 : "supported");
308 1 : return CE_Failure;
309 : }
310 :
311 : //
312 1 : void RemoveStatistics() override
313 : {
314 1 : }
315 :
316 : //
317 1 : GDALRATTableType GetTableType() const override
318 : {
319 1 : return m_eTableType;
320 : }
321 : };
322 :
323 : /************************************************************************/
324 : /* GDALRasterAttributeTableFromMDArrays() */
325 : /************************************************************************/
326 :
327 3 : GDALRasterAttributeTableFromMDArrays::GDALRasterAttributeTableFromMDArrays(
328 : GDALRATTableType eTableType,
329 : const std::vector<std::shared_ptr<GDALMDArray>> &apoArrays,
330 3 : const std::vector<GDALRATFieldUsage> &aeUsages)
331 3 : : m_eTableType(eTableType), m_apoArrays(apoArrays), m_aeUsages(aeUsages)
332 : {
333 3 : }
334 :
335 : /************************************************************************/
336 : /* GDALCreateRasterAttributeTableFromMDArrays() */
337 : /************************************************************************/
338 :
339 : /** Return a virtual Raster Attribute Table from several GDALMDArray's.
340 : *
341 : * All arrays must be single-dimensional and be indexed by the same dimension.
342 : *
343 : * This is the same as the C function GDALCreateRasterAttributeTableFromMDArrays().
344 : *
345 : * @param eTableType RAT table type
346 : * @param apoArrays Vector of GDALMDArray's (none of them should be nullptr)
347 : * @param aeUsages Vector of GDALRATFieldUsage (of the same size as apoArrays if non-empty), or empty vector to use defaults
348 : * @return a new Raster Attribute Table to free with delete, or nullptr in case of error
349 : * @since 3.9
350 : */
351 5 : GDALRasterAttributeTable *GDALCreateRasterAttributeTableFromMDArrays(
352 : GDALRATTableType eTableType,
353 : const std::vector<std::shared_ptr<GDALMDArray>> &apoArrays,
354 : const std::vector<GDALRATFieldUsage> &aeUsages)
355 : {
356 5 : if (apoArrays.empty())
357 : {
358 1 : CPLError(CE_Failure, CPLE_AppDefined,
359 : "GDALCreateRasterAttributeTableFromMDArrays(): apoArrays "
360 : "should not be empty");
361 1 : return nullptr;
362 : }
363 4 : if (!aeUsages.empty() && apoArrays.size() != aeUsages.size())
364 : {
365 0 : CPLError(CE_Failure, CPLE_AppDefined,
366 : "GDALCreateRasterAttributeTableFromMDArrays(): aeUsages "
367 : "should be empty or have the same size as apoArrays");
368 0 : return nullptr;
369 : }
370 11 : for (size_t i = 0; i < apoArrays.size(); ++i)
371 : {
372 9 : if (apoArrays[i]->GetDimensionCount() != 1)
373 : {
374 1 : CPLError(CE_Failure, CPLE_AppDefined,
375 : "GDALCreateRasterAttributeTableFromMDArrays(): "
376 : "apoArrays[%d] has a dimension count != 1",
377 : static_cast<int>(i));
378 1 : return nullptr;
379 : }
380 17 : if (i > 0 && (apoArrays[i]->GetDimensions()[0]->GetFullName() !=
381 9 : apoArrays[0]->GetDimensions()[0]->GetFullName() ||
382 4 : apoArrays[i]->GetDimensions()[0]->GetSize() !=
383 4 : apoArrays[0]->GetDimensions()[0]->GetSize()))
384 : {
385 1 : CPLError(
386 : CE_Failure, CPLE_AppDefined,
387 : "GDALCreateRasterAttributeTableFromMDArrays(): apoArrays[%d] "
388 : "does not have the same dimension has apoArrays[0]",
389 : static_cast<int>(i));
390 1 : return nullptr;
391 : }
392 : }
393 : return new GDALRasterAttributeTableFromMDArrays(eTableType, apoArrays,
394 2 : aeUsages);
395 : }
396 :
397 : /************************************************************************/
398 : /* GDALCreateRasterAttributeTableFromMDArrays() */
399 : /************************************************************************/
400 :
401 : /** Return a virtual Raster Attribute Table from several GDALMDArray's.
402 : *
403 : * All arrays must be single-dimensional and be indexed by the same dimension.
404 : *
405 : * This is the same as the C++ method GDALCreateRasterAttributeTableFromMDArrays().
406 : *
407 : * @param eTableType RAT table type
408 : * @param nArrays Number of elements in ahArrays parameter
409 : * @param ahArrays Array of nArrays GDALMDArray's (none of them should be nullptr)
410 : * @param paeUsages Array of nArray GDALRATFieldUsage, or nullptr to use defaults
411 : * @return a new Raster Attribute Table to free with GDALDestroyRasterAttributeTable(), or nullptr in case of error
412 : * @since 3.9
413 : */
414 5 : GDALRasterAttributeTableH GDALCreateRasterAttributeTableFromMDArrays(
415 : GDALRATTableType eTableType, int nArrays, const GDALMDArrayH *ahArrays,
416 : const GDALRATFieldUsage *paeUsages)
417 : {
418 5 : VALIDATE_POINTER1(ahArrays, __func__, nullptr);
419 10 : std::vector<std::shared_ptr<GDALMDArray>> apoArrays;
420 10 : std::vector<GDALRATFieldUsage> aeUsages;
421 14 : for (int i = 0; i < nArrays; ++i)
422 : {
423 9 : VALIDATE_POINTER1(ahArrays[i], __func__, nullptr);
424 9 : apoArrays.emplace_back(ahArrays[i]->m_poImpl);
425 9 : if (paeUsages)
426 3 : aeUsages.emplace_back(paeUsages[i]);
427 : }
428 5 : return GDALRasterAttributeTable::ToHandle(
429 : GDALCreateRasterAttributeTableFromMDArrays(eTableType, apoArrays,
430 5 : aeUsages));
431 : }
|