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