Line data Source code
1 : /******************************************************************************
2 : *
3 : * Name: gdalmultidim_c_api_array.cpp
4 : * Project: GDAL Core
5 : * Purpose: C API for GDALMDArray
6 : * Author: Even Rouault <even.rouault at spatialys.com>
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2019, Even Rouault <even.rouault at spatialys.com>
10 : *
11 : * SPDX-License-Identifier: MIT
12 : ****************************************************************************/
13 :
14 : #include "gdal_multidim.h"
15 : #include "gdalmultidim_priv.h"
16 : #include "gdal_fwd.h"
17 :
18 : /************************************************************************/
19 : /* GDALMDArrayRelease() */
20 : /************************************************************************/
21 :
22 : /** Release the GDAL in-memory object associated with a GDALMDArray.
23 : *
24 : * Note: when applied on a object coming from a driver, this does not
25 : * destroy the object in the file, database, etc...
26 : */
27 3087 : void GDALMDArrayRelease(GDALMDArrayH hMDArray)
28 : {
29 3087 : delete hMDArray;
30 3087 : }
31 :
32 : /************************************************************************/
33 : /* GDALMDArrayGetName() */
34 : /************************************************************************/
35 :
36 : /** Return array name.
37 : *
38 : * This is the same as the C++ method GDALMDArray::GetName()
39 : */
40 84 : const char *GDALMDArrayGetName(GDALMDArrayH hArray)
41 : {
42 84 : VALIDATE_POINTER1(hArray, __func__, nullptr);
43 84 : return hArray->m_poImpl->GetName().c_str();
44 : }
45 :
46 : /************************************************************************/
47 : /* GDALMDArrayGetFullName() */
48 : /************************************************************************/
49 :
50 : /** Return array full name.
51 : *
52 : * This is the same as the C++ method GDALMDArray::GetFullName()
53 : */
54 71 : const char *GDALMDArrayGetFullName(GDALMDArrayH hArray)
55 : {
56 71 : VALIDATE_POINTER1(hArray, __func__, nullptr);
57 71 : return hArray->m_poImpl->GetFullName().c_str();
58 : }
59 :
60 : /************************************************************************/
61 : /* GDALMDArrayGetName() */
62 : /************************************************************************/
63 :
64 : /** Return the total number of values in the array.
65 : *
66 : * This is the same as the C++ method
67 : * GDALAbstractMDArray::GetTotalElementsCount()
68 : */
69 6 : GUInt64 GDALMDArrayGetTotalElementsCount(GDALMDArrayH hArray)
70 : {
71 6 : VALIDATE_POINTER1(hArray, __func__, 0);
72 6 : return hArray->m_poImpl->GetTotalElementsCount();
73 : }
74 :
75 : /************************************************************************/
76 : /* GDALMDArrayGetDimensionCount() */
77 : /************************************************************************/
78 :
79 : /** Return the number of dimensions.
80 : *
81 : * This is the same as the C++ method GDALAbstractMDArray::GetDimensionCount()
82 : */
83 16476 : size_t GDALMDArrayGetDimensionCount(GDALMDArrayH hArray)
84 : {
85 16476 : VALIDATE_POINTER1(hArray, __func__, 0);
86 16476 : return hArray->m_poImpl->GetDimensionCount();
87 : }
88 :
89 : /************************************************************************/
90 : /* GDALMDArrayGetDimensions() */
91 : /************************************************************************/
92 :
93 : /** Return the dimensions of the array
94 : *
95 : * The returned array must be freed with GDALReleaseDimensions(). If only the
96 : * array itself needs to be freed, CPLFree() should be called (and
97 : * GDALDimensionRelease() on individual array members).
98 : *
99 : * This is the same as the C++ method GDALAbstractMDArray::GetDimensions()
100 : *
101 : * @param hArray Array.
102 : * @param pnCount Pointer to the number of values returned. Must NOT be NULL.
103 : *
104 : * @return an array of *pnCount dimensions.
105 : */
106 3530 : GDALDimensionH *GDALMDArrayGetDimensions(GDALMDArrayH hArray, size_t *pnCount)
107 : {
108 3530 : VALIDATE_POINTER1(hArray, __func__, nullptr);
109 3530 : VALIDATE_POINTER1(pnCount, __func__, nullptr);
110 3530 : const auto &dims(hArray->m_poImpl->GetDimensions());
111 : auto ret = static_cast<GDALDimensionH *>(
112 3530 : CPLMalloc(sizeof(GDALDimensionH) * dims.size()));
113 10126 : for (size_t i = 0; i < dims.size(); i++)
114 : {
115 6596 : ret[i] = new GDALDimensionHS(dims[i]);
116 : }
117 3530 : *pnCount = dims.size();
118 3530 : return ret;
119 : }
120 :
121 : /************************************************************************/
122 : /* GDALMDArrayGetDataType() */
123 : /************************************************************************/
124 :
125 : /** Return the data type
126 : *
127 : * The return must be freed with GDALExtendedDataTypeRelease().
128 : */
129 6240 : GDALExtendedDataTypeH GDALMDArrayGetDataType(GDALMDArrayH hArray)
130 : {
131 6240 : VALIDATE_POINTER1(hArray, __func__, nullptr);
132 : return new GDALExtendedDataTypeHS(
133 6240 : new GDALExtendedDataType(hArray->m_poImpl->GetDataType()));
134 : }
135 :
136 : /************************************************************************/
137 : /* GDALMDArrayRead() */
138 : /************************************************************************/
139 :
140 : /** Read part or totality of a multidimensional array.
141 : *
142 : * This is the same as the C++ method GDALAbstractMDArray::Read()
143 : *
144 : * @return TRUE in case of success.
145 : */
146 3036 : int GDALMDArrayRead(GDALMDArrayH hArray, const GUInt64 *arrayStartIdx,
147 : const size_t *count, const GInt64 *arrayStep,
148 : const GPtrDiff_t *bufferStride,
149 : GDALExtendedDataTypeH bufferDataType, void *pDstBuffer,
150 : const void *pDstBufferAllocStart,
151 : size_t nDstBufferAllocSize)
152 : {
153 3036 : VALIDATE_POINTER1(hArray, __func__, FALSE);
154 3036 : if ((arrayStartIdx == nullptr || count == nullptr) &&
155 0 : hArray->m_poImpl->GetDimensionCount() > 0)
156 : {
157 0 : VALIDATE_POINTER1(arrayStartIdx, __func__, FALSE);
158 0 : VALIDATE_POINTER1(count, __func__, FALSE);
159 : }
160 3036 : VALIDATE_POINTER1(bufferDataType, __func__, FALSE);
161 3036 : VALIDATE_POINTER1(pDstBuffer, __func__, FALSE);
162 6072 : return hArray->m_poImpl->Read(arrayStartIdx, count, arrayStep, bufferStride,
163 3036 : *(bufferDataType->m_poImpl), pDstBuffer,
164 3036 : pDstBufferAllocStart, nDstBufferAllocSize);
165 : }
166 :
167 : /************************************************************************/
168 : /* GDALMDArrayWrite() */
169 : /************************************************************************/
170 :
171 : /** Write part or totality of a multidimensional array.
172 : *
173 : * This is the same as the C++ method GDALAbstractMDArray::Write()
174 : *
175 : * @return TRUE in case of success.
176 : */
177 897 : int GDALMDArrayWrite(GDALMDArrayH hArray, const GUInt64 *arrayStartIdx,
178 : const size_t *count, const GInt64 *arrayStep,
179 : const GPtrDiff_t *bufferStride,
180 : GDALExtendedDataTypeH bufferDataType,
181 : const void *pSrcBuffer, const void *pSrcBufferAllocStart,
182 : size_t nSrcBufferAllocSize)
183 : {
184 897 : VALIDATE_POINTER1(hArray, __func__, FALSE);
185 897 : if ((arrayStartIdx == nullptr || count == nullptr) &&
186 0 : hArray->m_poImpl->GetDimensionCount() > 0)
187 : {
188 0 : VALIDATE_POINTER1(arrayStartIdx, __func__, FALSE);
189 0 : VALIDATE_POINTER1(count, __func__, FALSE);
190 : }
191 897 : VALIDATE_POINTER1(bufferDataType, __func__, FALSE);
192 897 : VALIDATE_POINTER1(pSrcBuffer, __func__, FALSE);
193 1794 : return hArray->m_poImpl->Write(arrayStartIdx, count, arrayStep,
194 897 : bufferStride, *(bufferDataType->m_poImpl),
195 : pSrcBuffer, pSrcBufferAllocStart,
196 897 : nSrcBufferAllocSize);
197 : }
198 :
199 : /************************************************************************/
200 : /* GDALMDArrayAdviseRead() */
201 : /************************************************************************/
202 :
203 : /** Advise driver of upcoming read requests.
204 : *
205 : * This is the same as the C++ method GDALMDArray::AdviseRead()
206 : *
207 : * @return TRUE in case of success.
208 : *
209 : * @since GDAL 3.2
210 : */
211 0 : int GDALMDArrayAdviseRead(GDALMDArrayH hArray, const GUInt64 *arrayStartIdx,
212 : const size_t *count)
213 : {
214 0 : return GDALMDArrayAdviseReadEx(hArray, arrayStartIdx, count, nullptr);
215 : }
216 :
217 : /************************************************************************/
218 : /* GDALMDArrayAdviseReadEx() */
219 : /************************************************************************/
220 :
221 : /** Advise driver of upcoming read requests.
222 : *
223 : * This is the same as the C++ method GDALMDArray::AdviseRead()
224 : *
225 : * @return TRUE in case of success.
226 : *
227 : * @since GDAL 3.4
228 : */
229 19 : int GDALMDArrayAdviseReadEx(GDALMDArrayH hArray, const GUInt64 *arrayStartIdx,
230 : const size_t *count, CSLConstList papszOptions)
231 : {
232 19 : VALIDATE_POINTER1(hArray, __func__, FALSE);
233 19 : return hArray->m_poImpl->AdviseRead(arrayStartIdx, count, papszOptions);
234 : }
235 :
236 : /************************************************************************/
237 : /* GDALMDArrayGetAttribute() */
238 : /************************************************************************/
239 :
240 : /** Return an attribute by its name.
241 : *
242 : * This is the same as the C++ method GDALIHasAttribute::GetAttribute()
243 : *
244 : * The returned attribute must be freed with GDALAttributeRelease().
245 : */
246 120 : GDALAttributeH GDALMDArrayGetAttribute(GDALMDArrayH hArray, const char *pszName)
247 : {
248 120 : VALIDATE_POINTER1(hArray, __func__, nullptr);
249 120 : VALIDATE_POINTER1(pszName, __func__, nullptr);
250 360 : auto attr = hArray->m_poImpl->GetAttribute(std::string(pszName));
251 120 : if (attr)
252 111 : return new GDALAttributeHS(attr);
253 9 : return nullptr;
254 : }
255 :
256 : /************************************************************************/
257 : /* GDALMDArrayGetAttributes() */
258 : /************************************************************************/
259 :
260 : /** Return the list of attributes contained in this array.
261 : *
262 : * The returned array must be freed with GDALReleaseAttributes(). If only the
263 : * array itself needs to be freed, CPLFree() should be called (and
264 : * GDALAttributeRelease() on individual array members).
265 : *
266 : * This is the same as the C++ method GDALMDArray::GetAttributes().
267 : *
268 : * @param hArray Array.
269 : * @param pnCount Pointer to the number of values returned. Must NOT be NULL.
270 : * @param papszOptions Driver specific options determining how attributes
271 : * should be retrieved. Pass nullptr for default behavior.
272 : *
273 : * @return an array of *pnCount attributes.
274 : */
275 59 : GDALAttributeH *GDALMDArrayGetAttributes(GDALMDArrayH hArray, size_t *pnCount,
276 : CSLConstList papszOptions)
277 : {
278 59 : VALIDATE_POINTER1(hArray, __func__, nullptr);
279 59 : VALIDATE_POINTER1(pnCount, __func__, nullptr);
280 59 : auto attrs = hArray->m_poImpl->GetAttributes(papszOptions);
281 : auto ret = static_cast<GDALAttributeH *>(
282 59 : CPLMalloc(sizeof(GDALAttributeH) * attrs.size()));
283 189 : for (size_t i = 0; i < attrs.size(); i++)
284 : {
285 130 : ret[i] = new GDALAttributeHS(attrs[i]);
286 : }
287 59 : *pnCount = attrs.size();
288 59 : return ret;
289 : }
290 :
291 : /************************************************************************/
292 : /* GDALMDArrayCreateAttribute() */
293 : /************************************************************************/
294 :
295 : /** Create a attribute within an array.
296 : *
297 : * This is the same as the C++ method GDALMDArray::CreateAttribute().
298 : *
299 : * @return the attribute, to be freed with GDALAttributeRelease(), or nullptr.
300 : */
301 188 : GDALAttributeH GDALMDArrayCreateAttribute(GDALMDArrayH hArray,
302 : const char *pszName,
303 : size_t nDimensions,
304 : const GUInt64 *panDimensions,
305 : GDALExtendedDataTypeH hEDT,
306 : CSLConstList papszOptions)
307 : {
308 188 : VALIDATE_POINTER1(hArray, __func__, nullptr);
309 188 : VALIDATE_POINTER1(pszName, __func__, nullptr);
310 188 : VALIDATE_POINTER1(hEDT, __func__, nullptr);
311 376 : std::vector<GUInt64> dims;
312 188 : dims.reserve(nDimensions);
313 249 : for (size_t i = 0; i < nDimensions; i++)
314 61 : dims.push_back(panDimensions[i]);
315 188 : auto ret = hArray->m_poImpl->CreateAttribute(
316 564 : std::string(pszName), dims, *(hEDT->m_poImpl), papszOptions);
317 188 : if (!ret)
318 9 : return nullptr;
319 179 : return new GDALAttributeHS(ret);
320 : }
321 :
322 : /************************************************************************/
323 : /* GDALMDArrayDeleteAttribute() */
324 : /************************************************************************/
325 :
326 : /** Delete an attribute from an array.
327 : *
328 : * After this call, if a previously obtained instance of the deleted object
329 : * is still alive, no method other than for freeing it should be invoked.
330 : *
331 : * This is the same as the C++ method GDALMDArray::DeleteAttribute().
332 : *
333 : * @return true in case of success.
334 : * @since GDAL 3.8
335 : */
336 24 : bool GDALMDArrayDeleteAttribute(GDALMDArrayH hArray, const char *pszName,
337 : CSLConstList papszOptions)
338 : {
339 24 : VALIDATE_POINTER1(hArray, __func__, false);
340 24 : VALIDATE_POINTER1(pszName, __func__, false);
341 48 : return hArray->m_poImpl->DeleteAttribute(std::string(pszName),
342 24 : papszOptions);
343 : }
344 :
345 : /************************************************************************/
346 : /* GDALMDArrayGetRawNoDataValue() */
347 : /************************************************************************/
348 :
349 : /** Return the nodata value as a "raw" value.
350 : *
351 : * The value returned might be nullptr in case of no nodata value. When
352 : * a nodata value is registered, a non-nullptr will be returned whose size in
353 : * bytes is GetDataType().GetSize().
354 : *
355 : * The returned value should not be modified or freed.
356 : *
357 : * This is the same as the ++ method GDALMDArray::GetRawNoDataValue().
358 : *
359 : * @return nullptr or a pointer to GetDataType().GetSize() bytes.
360 : */
361 79 : const void *GDALMDArrayGetRawNoDataValue(GDALMDArrayH hArray)
362 : {
363 79 : VALIDATE_POINTER1(hArray, __func__, nullptr);
364 79 : return hArray->m_poImpl->GetRawNoDataValue();
365 : }
366 :
367 : /************************************************************************/
368 : /* GDALMDArrayGetNoDataValueAsDouble() */
369 : /************************************************************************/
370 :
371 : /** Return the nodata value as a double.
372 : *
373 : * The value returned might be nullptr in case of no nodata value. When
374 : * a nodata value is registered, a non-nullptr will be returned whose size in
375 : * bytes is GetDataType().GetSize().
376 : *
377 : * This is the same as the C++ method GDALMDArray::GetNoDataValueAsDouble().
378 : *
379 : * @param hArray Array handle.
380 : * @param pbHasNoDataValue Pointer to a output boolean that will be set to true
381 : * if a nodata value exists and can be converted to double. Might be nullptr.
382 : *
383 : * @return the nodata value as a double. A 0.0 value might also indicate the
384 : * absence of a nodata value or an error in the conversion (*pbHasNoDataValue
385 : * will be set to false then).
386 : */
387 124 : double GDALMDArrayGetNoDataValueAsDouble(GDALMDArrayH hArray,
388 : int *pbHasNoDataValue)
389 : {
390 124 : VALIDATE_POINTER1(hArray, __func__, 0);
391 124 : bool bHasNodataValue = false;
392 124 : double ret = hArray->m_poImpl->GetNoDataValueAsDouble(&bHasNodataValue);
393 124 : if (pbHasNoDataValue)
394 124 : *pbHasNoDataValue = bHasNodataValue;
395 124 : return ret;
396 : }
397 :
398 : /************************************************************************/
399 : /* GDALMDArrayGetNoDataValueAsInt64() */
400 : /************************************************************************/
401 :
402 : /** Return the nodata value as a Int64.
403 : *
404 : * This is the same as the C++ method GDALMDArray::GetNoDataValueAsInt64().
405 : *
406 : * @param hArray Array handle.
407 : * @param pbHasNoDataValue Pointer to a output boolean that will be set to true
408 : * if a nodata value exists and can be converted to Int64. Might be nullptr.
409 : *
410 : * @return the nodata value as a Int64.
411 : * @since GDAL 3.5
412 : */
413 13 : int64_t GDALMDArrayGetNoDataValueAsInt64(GDALMDArrayH hArray,
414 : int *pbHasNoDataValue)
415 : {
416 13 : VALIDATE_POINTER1(hArray, __func__, 0);
417 13 : bool bHasNodataValue = false;
418 13 : const auto ret = hArray->m_poImpl->GetNoDataValueAsInt64(&bHasNodataValue);
419 13 : if (pbHasNoDataValue)
420 13 : *pbHasNoDataValue = bHasNodataValue;
421 13 : return ret;
422 : }
423 :
424 : /************************************************************************/
425 : /* GDALMDArrayGetNoDataValueAsUInt64() */
426 : /************************************************************************/
427 :
428 : /** Return the nodata value as a UInt64.
429 : *
430 : * This is the same as the C++ method GDALMDArray::GetNoDataValueAsInt64().
431 : *
432 : * @param hArray Array handle.
433 : * @param pbHasNoDataValue Pointer to a output boolean that will be set to true
434 : * if a nodata value exists and can be converted to UInt64. Might be nullptr.
435 : *
436 : * @return the nodata value as a UInt64.
437 : * @since GDAL 3.5
438 : */
439 7 : uint64_t GDALMDArrayGetNoDataValueAsUInt64(GDALMDArrayH hArray,
440 : int *pbHasNoDataValue)
441 : {
442 7 : VALIDATE_POINTER1(hArray, __func__, 0);
443 7 : bool bHasNodataValue = false;
444 7 : const auto ret = hArray->m_poImpl->GetNoDataValueAsUInt64(&bHasNodataValue);
445 7 : if (pbHasNoDataValue)
446 7 : *pbHasNoDataValue = bHasNodataValue;
447 7 : return ret;
448 : }
449 :
450 : /************************************************************************/
451 : /* GDALMDArraySetRawNoDataValue() */
452 : /************************************************************************/
453 :
454 : /** Set the nodata value as a "raw" value.
455 : *
456 : * This is the same as the C++ method GDALMDArray::SetRawNoDataValue(const
457 : * void*).
458 : *
459 : * @return TRUE in case of success.
460 : */
461 15 : int GDALMDArraySetRawNoDataValue(GDALMDArrayH hArray, const void *pNoData)
462 : {
463 15 : VALIDATE_POINTER1(hArray, __func__, FALSE);
464 15 : return hArray->m_poImpl->SetRawNoDataValue(pNoData);
465 : }
466 :
467 : /************************************************************************/
468 : /* GDALMDArraySetNoDataValueAsDouble() */
469 : /************************************************************************/
470 :
471 : /** Set the nodata value as a double.
472 : *
473 : * If the natural data type of the attribute/array is not double, type
474 : * conversion will occur to the type returned by GetDataType().
475 : *
476 : * This is the same as the C++ method GDALMDArray::SetNoDataValue(double).
477 : *
478 : * @return TRUE in case of success.
479 : */
480 58 : int GDALMDArraySetNoDataValueAsDouble(GDALMDArrayH hArray, double dfNoDataValue)
481 : {
482 58 : VALIDATE_POINTER1(hArray, __func__, FALSE);
483 58 : return hArray->m_poImpl->SetNoDataValue(dfNoDataValue);
484 : }
485 :
486 : /************************************************************************/
487 : /* GDALMDArraySetNoDataValueAsInt64() */
488 : /************************************************************************/
489 :
490 : /** Set the nodata value as a Int64.
491 : *
492 : * If the natural data type of the attribute/array is not Int64, type conversion
493 : * will occur to the type returned by GetDataType().
494 : *
495 : * This is the same as the C++ method GDALMDArray::SetNoDataValue(int64_t).
496 : *
497 : * @return TRUE in case of success.
498 : * @since GDAL 3.5
499 : */
500 1 : int GDALMDArraySetNoDataValueAsInt64(GDALMDArrayH hArray, int64_t nNoDataValue)
501 : {
502 1 : VALIDATE_POINTER1(hArray, __func__, FALSE);
503 1 : return hArray->m_poImpl->SetNoDataValue(nNoDataValue);
504 : }
505 :
506 : /************************************************************************/
507 : /* GDALMDArraySetNoDataValueAsUInt64() */
508 : /************************************************************************/
509 :
510 : /** Set the nodata value as a UInt64.
511 : *
512 : * If the natural data type of the attribute/array is not UInt64, type
513 : * conversion will occur to the type returned by GetDataType().
514 : *
515 : * This is the same as the C++ method GDALMDArray::SetNoDataValue(uint64_t).
516 : *
517 : * @return TRUE in case of success.
518 : * @since GDAL 3.5
519 : */
520 1 : int GDALMDArraySetNoDataValueAsUInt64(GDALMDArrayH hArray,
521 : uint64_t nNoDataValue)
522 : {
523 1 : VALIDATE_POINTER1(hArray, __func__, FALSE);
524 1 : return hArray->m_poImpl->SetNoDataValue(nNoDataValue);
525 : }
526 :
527 : /************************************************************************/
528 : /* GDALMDArrayResize() */
529 : /************************************************************************/
530 :
531 : /** Resize an array to new dimensions.
532 : *
533 : * Not all drivers may allow this operation, and with restrictions (e.g.
534 : * for netCDF, this is limited to growing of "unlimited" dimensions)
535 : *
536 : * Resizing a dimension used in other arrays will cause those other arrays
537 : * to be resized.
538 : *
539 : * This is the same as the C++ method GDALMDArray::Resize().
540 : *
541 : * @param hArray Array.
542 : * @param panNewDimSizes Array of GetDimensionCount() values containing the
543 : * new size of each indexing dimension.
544 : * @param papszOptions Options. (Driver specific)
545 : * @return true in case of success.
546 : * @since GDAL 3.7
547 : */
548 42 : bool GDALMDArrayResize(GDALMDArrayH hArray, const GUInt64 *panNewDimSizes,
549 : CSLConstList papszOptions)
550 : {
551 42 : VALIDATE_POINTER1(hArray, __func__, false);
552 42 : VALIDATE_POINTER1(panNewDimSizes, __func__, false);
553 84 : std::vector<GUInt64> anNewDimSizes(hArray->m_poImpl->GetDimensionCount());
554 125 : for (size_t i = 0; i < anNewDimSizes.size(); ++i)
555 : {
556 83 : anNewDimSizes[i] = panNewDimSizes[i];
557 : }
558 42 : return hArray->m_poImpl->Resize(anNewDimSizes, papszOptions);
559 : }
560 :
561 : /************************************************************************/
562 : /* GDALMDArraySetScale() */
563 : /************************************************************************/
564 :
565 : /** Set the scale value to apply to raw values.
566 : *
567 : * unscaled_value = raw_value * GetScale() + GetOffset()
568 : *
569 : * This is the same as the C++ method GDALMDArray::SetScale().
570 : *
571 : * @return TRUE in case of success.
572 : */
573 0 : int GDALMDArraySetScale(GDALMDArrayH hArray, double dfScale)
574 : {
575 0 : VALIDATE_POINTER1(hArray, __func__, FALSE);
576 0 : return hArray->m_poImpl->SetScale(dfScale);
577 : }
578 :
579 : /************************************************************************/
580 : /* GDALMDArraySetScaleEx() */
581 : /************************************************************************/
582 :
583 : /** Set the scale value to apply to raw values.
584 : *
585 : * unscaled_value = raw_value * GetScale() + GetOffset()
586 : *
587 : * This is the same as the C++ method GDALMDArray::SetScale().
588 : *
589 : * @return TRUE in case of success.
590 : * @since GDAL 3.3
591 : */
592 21 : int GDALMDArraySetScaleEx(GDALMDArrayH hArray, double dfScale,
593 : GDALDataType eStorageType)
594 : {
595 21 : VALIDATE_POINTER1(hArray, __func__, FALSE);
596 21 : return hArray->m_poImpl->SetScale(dfScale, eStorageType);
597 : }
598 :
599 : /************************************************************************/
600 : /* GDALMDArraySetOffset() */
601 : /************************************************************************/
602 :
603 : /** Set the scale value to apply to raw values.
604 : *
605 : * unscaled_value = raw_value * GetScale() + GetOffset()
606 : *
607 : * This is the same as the C++ method GDALMDArray::SetOffset().
608 : *
609 : * @return TRUE in case of success.
610 : */
611 0 : int GDALMDArraySetOffset(GDALMDArrayH hArray, double dfOffset)
612 : {
613 0 : VALIDATE_POINTER1(hArray, __func__, FALSE);
614 0 : return hArray->m_poImpl->SetOffset(dfOffset);
615 : }
616 :
617 : /************************************************************************/
618 : /* GDALMDArraySetOffsetEx() */
619 : /************************************************************************/
620 :
621 : /** Set the scale value to apply to raw values.
622 : *
623 : * unscaled_value = raw_value * GetOffset() + GetOffset()
624 : *
625 : * This is the same as the C++ method GDALMDArray::SetOffset().
626 : *
627 : * @return TRUE in case of success.
628 : * @since GDAL 3.3
629 : */
630 21 : int GDALMDArraySetOffsetEx(GDALMDArrayH hArray, double dfOffset,
631 : GDALDataType eStorageType)
632 : {
633 21 : VALIDATE_POINTER1(hArray, __func__, FALSE);
634 21 : return hArray->m_poImpl->SetOffset(dfOffset, eStorageType);
635 : }
636 :
637 : /************************************************************************/
638 : /* GDALMDArrayGetScale() */
639 : /************************************************************************/
640 :
641 : /** Get the scale value to apply to raw values.
642 : *
643 : * unscaled_value = raw_value * GetScale() + GetOffset()
644 : *
645 : * This is the same as the C++ method GDALMDArray::GetScale().
646 : *
647 : * @return the scale value
648 : */
649 105 : double GDALMDArrayGetScale(GDALMDArrayH hArray, int *pbHasValue)
650 : {
651 105 : VALIDATE_POINTER1(hArray, __func__, 0.0);
652 105 : bool bHasValue = false;
653 105 : double dfRet = hArray->m_poImpl->GetScale(&bHasValue);
654 105 : if (pbHasValue)
655 105 : *pbHasValue = bHasValue;
656 105 : return dfRet;
657 : }
658 :
659 : /************************************************************************/
660 : /* GDALMDArrayGetScaleEx() */
661 : /************************************************************************/
662 :
663 : /** Get the scale value to apply to raw values.
664 : *
665 : * unscaled_value = raw_value * GetScale() + GetScale()
666 : *
667 : * This is the same as the C++ method GDALMDArray::GetScale().
668 : *
669 : * @return the scale value
670 : * @since GDAL 3.3
671 : */
672 5 : double GDALMDArrayGetScaleEx(GDALMDArrayH hArray, int *pbHasValue,
673 : GDALDataType *peStorageType)
674 : {
675 5 : VALIDATE_POINTER1(hArray, __func__, 0.0);
676 5 : bool bHasValue = false;
677 5 : double dfRet = hArray->m_poImpl->GetScale(&bHasValue, peStorageType);
678 5 : if (pbHasValue)
679 5 : *pbHasValue = bHasValue;
680 5 : return dfRet;
681 : }
682 :
683 : /************************************************************************/
684 : /* GDALMDArrayGetOffset() */
685 : /************************************************************************/
686 :
687 : /** Get the scale value to apply to raw values.
688 : *
689 : * unscaled_value = raw_value * GetScale() + GetOffset()
690 : *
691 : * This is the same as the C++ method GDALMDArray::GetOffset().
692 : *
693 : * @return the scale value
694 : */
695 102 : double GDALMDArrayGetOffset(GDALMDArrayH hArray, int *pbHasValue)
696 : {
697 102 : VALIDATE_POINTER1(hArray, __func__, 0.0);
698 102 : bool bHasValue = false;
699 102 : double dfRet = hArray->m_poImpl->GetOffset(&bHasValue);
700 102 : if (pbHasValue)
701 102 : *pbHasValue = bHasValue;
702 102 : return dfRet;
703 : }
704 :
705 : /************************************************************************/
706 : /* GDALMDArrayGetOffsetEx() */
707 : /************************************************************************/
708 :
709 : /** Get the scale value to apply to raw values.
710 : *
711 : * unscaled_value = raw_value * GetScale() + GetOffset()
712 : *
713 : * This is the same as the C++ method GDALMDArray::GetOffset().
714 : *
715 : * @return the scale value
716 : * @since GDAL 3.3
717 : */
718 5 : double GDALMDArrayGetOffsetEx(GDALMDArrayH hArray, int *pbHasValue,
719 : GDALDataType *peStorageType)
720 : {
721 5 : VALIDATE_POINTER1(hArray, __func__, 0.0);
722 5 : bool bHasValue = false;
723 5 : double dfRet = hArray->m_poImpl->GetOffset(&bHasValue, peStorageType);
724 5 : if (pbHasValue)
725 5 : *pbHasValue = bHasValue;
726 5 : return dfRet;
727 : }
728 :
729 : /************************************************************************/
730 : /* GDALMDArrayGetBlockSize() */
731 : /************************************************************************/
732 :
733 : /** Return the "natural" block size of the array along all dimensions.
734 : *
735 : * Some drivers might organize the array in tiles/blocks and reading/writing
736 : * aligned on those tile/block boundaries will be more efficient.
737 : *
738 : * The returned number of elements in the vector is the same as
739 : * GetDimensionCount(). A value of 0 should be interpreted as no hint regarding
740 : * the natural block size along the considered dimension.
741 : * "Flat" arrays will typically return a vector of values set to 0.
742 : *
743 : * The default implementation will return a vector of values set to 0.
744 : *
745 : * This method is used by GetProcessingChunkSize().
746 : *
747 : * Pedantic note: the returned type is GUInt64, so in the highly unlikely
748 : * theoretical case of a 32-bit platform, this might exceed its size_t
749 : * allocation capabilities.
750 : *
751 : * This is the same as the C++ method GDALAbstractMDArray::GetBlockSize().
752 : *
753 : * @return the block size, in number of elements along each dimension.
754 : */
755 110 : GUInt64 *GDALMDArrayGetBlockSize(GDALMDArrayH hArray, size_t *pnCount)
756 : {
757 110 : VALIDATE_POINTER1(hArray, __func__, nullptr);
758 110 : VALIDATE_POINTER1(pnCount, __func__, nullptr);
759 110 : auto res = hArray->m_poImpl->GetBlockSize();
760 110 : auto ret = static_cast<GUInt64 *>(CPLMalloc(sizeof(GUInt64) * res.size()));
761 339 : for (size_t i = 0; i < res.size(); i++)
762 : {
763 229 : ret[i] = res[i];
764 : }
765 110 : *pnCount = res.size();
766 110 : return ret;
767 : }
768 :
769 : /************************************************************************/
770 : /* GDALMDArrayGetProcessingChunkSize() */
771 : /************************************************************************/
772 :
773 : /** \brief Return an optimal chunk size for read/write operations, given the
774 : * natural block size and memory constraints specified.
775 : *
776 : * This method will use GetBlockSize() to define a chunk whose dimensions are
777 : * multiple of those returned by GetBlockSize() (unless the block define by
778 : * GetBlockSize() is larger than nMaxChunkMemory, in which case it will be
779 : * returned by this method).
780 : *
781 : * This is the same as the C++ method
782 : * GDALAbstractMDArray::GetProcessingChunkSize().
783 : *
784 : * @param hArray Array.
785 : * @param pnCount Pointer to the number of values returned. Must NOT be NULL.
786 : * @param nMaxChunkMemory Maximum amount of memory, in bytes, to use for the
787 : * chunk.
788 : *
789 : * @return the chunk size, in number of elements along each dimension.
790 : */
791 :
792 1 : size_t *GDALMDArrayGetProcessingChunkSize(GDALMDArrayH hArray, size_t *pnCount,
793 : size_t nMaxChunkMemory)
794 : {
795 1 : VALIDATE_POINTER1(hArray, __func__, nullptr);
796 1 : VALIDATE_POINTER1(pnCount, __func__, nullptr);
797 1 : auto res = hArray->m_poImpl->GetProcessingChunkSize(nMaxChunkMemory);
798 1 : auto ret = static_cast<size_t *>(CPLMalloc(sizeof(size_t) * res.size()));
799 3 : for (size_t i = 0; i < res.size(); i++)
800 : {
801 2 : ret[i] = res[i];
802 : }
803 1 : *pnCount = res.size();
804 1 : return ret;
805 : }
806 :
807 : /************************************************************************/
808 : /* GDALMDArrayGetStructuralInfo() */
809 : /************************************************************************/
810 :
811 : /** Return structural information on the array.
812 : *
813 : * This may be the compression, etc..
814 : *
815 : * The return value should not be freed and is valid until GDALMDArray is
816 : * released or this function called again.
817 : *
818 : * This is the same as the C++ method GDALMDArray::GetStructuralInfo().
819 : */
820 17 : CSLConstList GDALMDArrayGetStructuralInfo(GDALMDArrayH hArray)
821 : {
822 17 : VALIDATE_POINTER1(hArray, __func__, nullptr);
823 17 : return hArray->m_poImpl->GetStructuralInfo();
824 : }
825 :
826 : /************************************************************************/
827 : /* GDALMDArrayGetView() */
828 : /************************************************************************/
829 :
830 : /** Return a view of the array using slicing or field access.
831 : *
832 : * The returned object should be released with GDALMDArrayRelease().
833 : *
834 : * This is the same as the C++ method GDALMDArray::GetView().
835 : */
836 438 : GDALMDArrayH GDALMDArrayGetView(GDALMDArrayH hArray, const char *pszViewExpr)
837 : {
838 438 : VALIDATE_POINTER1(hArray, __func__, nullptr);
839 438 : VALIDATE_POINTER1(pszViewExpr, __func__, nullptr);
840 1314 : auto sliced = hArray->m_poImpl->GetView(std::string(pszViewExpr));
841 438 : if (!sliced)
842 23 : return nullptr;
843 415 : return new GDALMDArrayHS(sliced);
844 : }
845 :
846 : /************************************************************************/
847 : /* GDALMDArrayTranspose() */
848 : /************************************************************************/
849 :
850 : /** Return a view of the array whose axis have been reordered.
851 : *
852 : * The returned object should be released with GDALMDArrayRelease().
853 : *
854 : * This is the same as the C++ method GDALMDArray::Transpose().
855 : */
856 46 : GDALMDArrayH GDALMDArrayTranspose(GDALMDArrayH hArray, size_t nNewAxisCount,
857 : const int *panMapNewAxisToOldAxis)
858 : {
859 46 : VALIDATE_POINTER1(hArray, __func__, nullptr);
860 92 : std::vector<int> anMapNewAxisToOldAxis(nNewAxisCount);
861 46 : if (nNewAxisCount)
862 : {
863 45 : memcpy(&anMapNewAxisToOldAxis[0], panMapNewAxisToOldAxis,
864 : nNewAxisCount * sizeof(int));
865 : }
866 92 : auto reordered = hArray->m_poImpl->Transpose(anMapNewAxisToOldAxis);
867 46 : if (!reordered)
868 7 : return nullptr;
869 39 : return new GDALMDArrayHS(reordered);
870 : }
871 :
872 : /************************************************************************/
873 : /* GDALMDArrayGetUnscaled() */
874 : /************************************************************************/
875 :
876 : /** Return an array that is the unscaled version of the current one.
877 : *
878 : * That is each value of the unscaled array will be
879 : * unscaled_value = raw_value * GetScale() + GetOffset()
880 : *
881 : * Starting with GDAL 3.3, the Write() method is implemented and will convert
882 : * from unscaled values to raw values.
883 : *
884 : * The returned object should be released with GDALMDArrayRelease().
885 : *
886 : * This is the same as the C++ method GDALMDArray::GetUnscaled().
887 : */
888 13 : GDALMDArrayH GDALMDArrayGetUnscaled(GDALMDArrayH hArray)
889 : {
890 13 : VALIDATE_POINTER1(hArray, __func__, nullptr);
891 26 : auto unscaled = hArray->m_poImpl->GetUnscaled();
892 13 : if (!unscaled)
893 0 : return nullptr;
894 13 : return new GDALMDArrayHS(unscaled);
895 : }
896 :
897 : /************************************************************************/
898 : /* GDALMDArrayGetMask() */
899 : /************************************************************************/
900 :
901 : /** Return an array that is a mask for the current array
902 : *
903 : * This array will be of type Byte, with values set to 0 to indicate invalid
904 : * pixels of the current array, and values set to 1 to indicate valid pixels.
905 : *
906 : * The returned object should be released with GDALMDArrayRelease().
907 : *
908 : * This is the same as the C++ method GDALMDArray::GetMask().
909 : */
910 35 : GDALMDArrayH GDALMDArrayGetMask(GDALMDArrayH hArray, CSLConstList papszOptions)
911 : {
912 35 : VALIDATE_POINTER1(hArray, __func__, nullptr);
913 70 : auto unscaled = hArray->m_poImpl->GetMask(papszOptions);
914 35 : if (!unscaled)
915 7 : return nullptr;
916 28 : return new GDALMDArrayHS(unscaled);
917 : }
918 :
919 : /************************************************************************/
920 : /* GDALMDArrayGetResampled() */
921 : /************************************************************************/
922 :
923 : /** Return an array that is a resampled / reprojected view of the current array
924 : *
925 : * This is the same as the C++ method GDALMDArray::GetResampled().
926 : *
927 : * Currently this method can only resample along the last 2 dimensions, unless
928 : * orthorectifying a NASA EMIT dataset.
929 : *
930 : * The returned object should be released with GDALMDArrayRelease().
931 : *
932 : * @since 3.4
933 : */
934 34 : GDALMDArrayH GDALMDArrayGetResampled(GDALMDArrayH hArray, size_t nNewDimCount,
935 : const GDALDimensionH *pahNewDims,
936 : GDALRIOResampleAlg resampleAlg,
937 : OGRSpatialReferenceH hTargetSRS,
938 : CSLConstList papszOptions)
939 : {
940 34 : VALIDATE_POINTER1(hArray, __func__, nullptr);
941 34 : VALIDATE_POINTER1(pahNewDims, __func__, nullptr);
942 68 : std::vector<std::shared_ptr<GDALDimension>> apoNewDims(nNewDimCount);
943 112 : for (size_t i = 0; i < nNewDimCount; ++i)
944 : {
945 78 : if (pahNewDims[i])
946 8 : apoNewDims[i] = pahNewDims[i]->m_poImpl;
947 : }
948 34 : auto poNewArray = hArray->m_poImpl->GetResampled(
949 34 : apoNewDims, resampleAlg, OGRSpatialReference::FromHandle(hTargetSRS),
950 68 : papszOptions);
951 34 : if (!poNewArray)
952 8 : return nullptr;
953 26 : return new GDALMDArrayHS(poNewArray);
954 : }
955 :
956 : /************************************************************************/
957 : /* GDALMDArraySetUnit() */
958 : /************************************************************************/
959 :
960 : /** Set the variable unit.
961 : *
962 : * Values should conform as much as possible with those allowed by
963 : * the NetCDF CF conventions:
964 : * http://cfconventions.org/Data/cf-conventions/cf-conventions-1.7/cf-conventions.html#units
965 : * but others might be returned.
966 : *
967 : * Few examples are "meter", "degrees", "second", ...
968 : * Empty value means unknown.
969 : *
970 : * This is the same as the C function GDALMDArraySetUnit()
971 : *
972 : * @param hArray array.
973 : * @param pszUnit unit name.
974 : * @return TRUE in case of success.
975 : */
976 15 : int GDALMDArraySetUnit(GDALMDArrayH hArray, const char *pszUnit)
977 : {
978 15 : VALIDATE_POINTER1(hArray, __func__, FALSE);
979 15 : return hArray->m_poImpl->SetUnit(pszUnit ? pszUnit : "");
980 : }
981 :
982 : /************************************************************************/
983 : /* GDALMDArrayGetUnit() */
984 : /************************************************************************/
985 :
986 : /** Return the array unit.
987 : *
988 : * Values should conform as much as possible with those allowed by
989 : * the NetCDF CF conventions:
990 : * http://cfconventions.org/Data/cf-conventions/cf-conventions-1.7/cf-conventions.html#units
991 : * but others might be returned.
992 : *
993 : * Few examples are "meter", "degrees", "second", ...
994 : * Empty value means unknown.
995 : *
996 : * The return value should not be freed and is valid until GDALMDArray is
997 : * released or this function called again.
998 : *
999 : * This is the same as the C++ method GDALMDArray::GetUnit().
1000 : */
1001 113 : const char *GDALMDArrayGetUnit(GDALMDArrayH hArray)
1002 : {
1003 113 : VALIDATE_POINTER1(hArray, __func__, nullptr);
1004 113 : return hArray->m_poImpl->GetUnit().c_str();
1005 : }
1006 :
1007 : /************************************************************************/
1008 : /* GDALMDArrayGetSpatialRef() */
1009 : /************************************************************************/
1010 :
1011 : /** Assign a spatial reference system object to the array.
1012 : *
1013 : * This is the same as the C++ method GDALMDArray::SetSpatialRef().
1014 : * @return TRUE in case of success.
1015 : */
1016 30 : int GDALMDArraySetSpatialRef(GDALMDArrayH hArray, OGRSpatialReferenceH hSRS)
1017 : {
1018 30 : VALIDATE_POINTER1(hArray, __func__, FALSE);
1019 60 : return hArray->m_poImpl->SetSpatialRef(
1020 60 : OGRSpatialReference::FromHandle(hSRS));
1021 : }
1022 :
1023 : /************************************************************************/
1024 : /* GDALMDArrayGetSpatialRef() */
1025 : /************************************************************************/
1026 :
1027 : /** Return the spatial reference system object associated with the array.
1028 : *
1029 : * This is the same as the C++ method GDALMDArray::GetSpatialRef().
1030 : *
1031 : * The returned object must be freed with OSRDestroySpatialReference().
1032 : */
1033 82 : OGRSpatialReferenceH GDALMDArrayGetSpatialRef(GDALMDArrayH hArray)
1034 : {
1035 82 : VALIDATE_POINTER1(hArray, __func__, nullptr);
1036 82 : auto poSRS = hArray->m_poImpl->GetSpatialRef();
1037 82 : return poSRS ? OGRSpatialReference::ToHandle(poSRS->Clone()) : nullptr;
1038 : }
1039 :
1040 : /************************************************************************/
1041 : /* GDALMDArrayGetStatistics() */
1042 : /************************************************************************/
1043 :
1044 : /**
1045 : * \brief Fetch statistics.
1046 : *
1047 : * This is the same as the C++ method GDALMDArray::GetStatistics().
1048 : *
1049 : * @since GDAL 3.2
1050 : */
1051 :
1052 15 : CPLErr GDALMDArrayGetStatistics(GDALMDArrayH hArray, GDALDatasetH /*hDS*/,
1053 : int bApproxOK, int bForce, double *pdfMin,
1054 : double *pdfMax, double *pdfMean,
1055 : double *pdfStdDev, GUInt64 *pnValidCount,
1056 : GDALProgressFunc pfnProgress,
1057 : void *pProgressData)
1058 : {
1059 15 : VALIDATE_POINTER1(hArray, __func__, CE_Failure);
1060 30 : return hArray->m_poImpl->GetStatistics(
1061 15 : CPL_TO_BOOL(bApproxOK), CPL_TO_BOOL(bForce), pdfMin, pdfMax, pdfMean,
1062 15 : pdfStdDev, pnValidCount, pfnProgress, pProgressData);
1063 : }
1064 :
1065 : /************************************************************************/
1066 : /* GDALMDArrayComputeStatistics() */
1067 : /************************************************************************/
1068 :
1069 : /**
1070 : * \brief Compute statistics.
1071 : *
1072 : * This is the same as the C++ method GDALMDArray::ComputeStatistics().
1073 : *
1074 : * @since GDAL 3.2
1075 : * @see GDALMDArrayComputeStatisticsEx()
1076 : */
1077 :
1078 0 : int GDALMDArrayComputeStatistics(GDALMDArrayH hArray, GDALDatasetH /* hDS */,
1079 : int bApproxOK, double *pdfMin, double *pdfMax,
1080 : double *pdfMean, double *pdfStdDev,
1081 : GUInt64 *pnValidCount,
1082 : GDALProgressFunc pfnProgress,
1083 : void *pProgressData)
1084 : {
1085 0 : VALIDATE_POINTER1(hArray, __func__, FALSE);
1086 0 : return hArray->m_poImpl->ComputeStatistics(
1087 0 : CPL_TO_BOOL(bApproxOK), pdfMin, pdfMax, pdfMean, pdfStdDev,
1088 0 : pnValidCount, pfnProgress, pProgressData, nullptr);
1089 : }
1090 :
1091 : /************************************************************************/
1092 : /* GDALMDArrayComputeStatisticsEx() */
1093 : /************************************************************************/
1094 :
1095 : /**
1096 : * \brief Compute statistics.
1097 : *
1098 : * Same as GDALMDArrayComputeStatistics() with extra papszOptions argument.
1099 : *
1100 : * This is the same as the C++ method GDALMDArray::ComputeStatistics().
1101 : *
1102 : * @since GDAL 3.8
1103 : */
1104 :
1105 4 : int GDALMDArrayComputeStatisticsEx(GDALMDArrayH hArray, GDALDatasetH /* hDS */,
1106 : int bApproxOK, double *pdfMin,
1107 : double *pdfMax, double *pdfMean,
1108 : double *pdfStdDev, GUInt64 *pnValidCount,
1109 : GDALProgressFunc pfnProgress,
1110 : void *pProgressData,
1111 : CSLConstList papszOptions)
1112 : {
1113 4 : VALIDATE_POINTER1(hArray, __func__, FALSE);
1114 8 : return hArray->m_poImpl->ComputeStatistics(
1115 4 : CPL_TO_BOOL(bApproxOK), pdfMin, pdfMax, pdfMean, pdfStdDev,
1116 8 : pnValidCount, pfnProgress, pProgressData, papszOptions);
1117 : }
1118 :
1119 : /************************************************************************/
1120 : /* GDALMDArrayGetCoordinateVariables() */
1121 : /************************************************************************/
1122 :
1123 : /** Return coordinate variables.
1124 : *
1125 : * The returned array must be freed with GDALReleaseArrays(). If only the array
1126 : * itself needs to be freed, CPLFree() should be called (and
1127 : * GDALMDArrayRelease() on individual array members).
1128 : *
1129 : * This is the same as the C++ method GDALMDArray::GetCoordinateVariables()
1130 : *
1131 : * @param hArray Array.
1132 : * @param pnCount Pointer to the number of values returned. Must NOT be NULL.
1133 : *
1134 : * @return an array of *pnCount arrays.
1135 : * @since 3.4
1136 : */
1137 13 : GDALMDArrayH *GDALMDArrayGetCoordinateVariables(GDALMDArrayH hArray,
1138 : size_t *pnCount)
1139 : {
1140 13 : VALIDATE_POINTER1(hArray, __func__, nullptr);
1141 13 : VALIDATE_POINTER1(pnCount, __func__, nullptr);
1142 13 : const auto coordinates(hArray->m_poImpl->GetCoordinateVariables());
1143 : auto ret = static_cast<GDALMDArrayH *>(
1144 13 : CPLMalloc(sizeof(GDALMDArrayH) * coordinates.size()));
1145 29 : for (size_t i = 0; i < coordinates.size(); i++)
1146 : {
1147 16 : ret[i] = new GDALMDArrayHS(coordinates[i]);
1148 : }
1149 13 : *pnCount = coordinates.size();
1150 13 : return ret;
1151 : }
1152 :
1153 : /************************************************************************/
1154 : /* GDALMDArrayGetGridded() */
1155 : /************************************************************************/
1156 :
1157 : /** Return a gridded array from scattered point data, that is from an array
1158 : * whose last dimension is the indexing variable of X and Y arrays.
1159 : *
1160 : * The returned object should be released with GDALMDArrayRelease().
1161 : *
1162 : * This is the same as the C++ method GDALMDArray::GetGridded().
1163 : *
1164 : * @since GDAL 3.7
1165 : */
1166 22 : GDALMDArrayH GDALMDArrayGetGridded(GDALMDArrayH hArray,
1167 : const char *pszGridOptions,
1168 : GDALMDArrayH hXArray, GDALMDArrayH hYArray,
1169 : CSLConstList papszOptions)
1170 : {
1171 22 : VALIDATE_POINTER1(hArray, __func__, nullptr);
1172 22 : VALIDATE_POINTER1(pszGridOptions, __func__, nullptr);
1173 22 : auto gridded = hArray->m_poImpl->GetGridded(
1174 44 : pszGridOptions, hXArray ? hXArray->m_poImpl : nullptr,
1175 88 : hYArray ? hYArray->m_poImpl : nullptr, papszOptions);
1176 22 : if (!gridded)
1177 19 : return nullptr;
1178 3 : return new GDALMDArrayHS(gridded);
1179 : }
1180 :
1181 : /************************************************************************/
1182 : /* GDALMDArrayGetMeshGrid() */
1183 : /************************************************************************/
1184 :
1185 : /** Return a list of multidimensional arrays from a list of one-dimensional
1186 : * arrays.
1187 : *
1188 : * This is typically used to transform one-dimensional longitude, latitude
1189 : * arrays into 2D ones.
1190 : *
1191 : * More formally, for one-dimensional arrays x1, x2,..., xn with lengths
1192 : * Ni=len(xi), returns (N1, N2, ..., Nn) shaped arrays if indexing="ij" or
1193 : * (N2, N1, ..., Nn) shaped arrays if indexing="xy" with the elements of xi
1194 : * repeated to fill the matrix along the first dimension for x1, the second
1195 : * for x2 and so on.
1196 : *
1197 : * For example, if x = [1, 2], and y = [3, 4, 5],
1198 : * GetMeshGrid([x, y], ["INDEXING=xy"]) will return [xm, ym] such that
1199 : * xm=[[1, 2],[1, 2],[1, 2]] and ym=[[3, 3],[4, 4],[5, 5]],
1200 : * or more generally xm[any index][i] = x[i] and ym[i][any index]=y[i]
1201 : *
1202 : * and
1203 : * GetMeshGrid([x, y], ["INDEXING=ij"]) will return [xm, ym] such that
1204 : * xm=[[1, 1, 1],[2, 2, 2]] and ym=[[3, 4, 5],[3, 4, 5]],
1205 : * or more generally xm[i][any index] = x[i] and ym[any index][i]=y[i]
1206 : *
1207 : * The currently supported options are:
1208 : * <ul>
1209 : * <li>INDEXING=xy/ij: Cartesian ("xy", default) or matrix ("ij") indexing of
1210 : * output.
1211 : * </li>
1212 : * </ul>
1213 : *
1214 : * This is the same as
1215 : * <a href="https://numpy.org/doc/stable/reference/generated/numpy.meshgrid.html">numpy.meshgrid()</a>
1216 : * function.
1217 : *
1218 : * The returned array (of arrays) must be freed with GDALReleaseArrays().
1219 : * If only the array itself needs to be freed, CPLFree() should be called
1220 : * (and GDALMDArrayRelease() on individual array members).
1221 : *
1222 : * This is the same as the C++ method GDALMDArray::GetMeshGrid()
1223 : *
1224 : * @param pahInputArrays Input arrays
1225 : * @param nCountInputArrays Number of input arrays
1226 : * @param pnCountOutputArrays Pointer to the number of values returned. Must NOT be NULL.
1227 : * @param papszOptions NULL, or NULL terminated list of options.
1228 : *
1229 : * @return an array of *pnCountOutputArrays arrays.
1230 : * @since 3.10
1231 : */
1232 7 : GDALMDArrayH *GDALMDArrayGetMeshGrid(const GDALMDArrayH *pahInputArrays,
1233 : size_t nCountInputArrays,
1234 : size_t *pnCountOutputArrays,
1235 : CSLConstList papszOptions)
1236 : {
1237 7 : VALIDATE_POINTER1(pahInputArrays, __func__, nullptr);
1238 7 : VALIDATE_POINTER1(pnCountOutputArrays, __func__, nullptr);
1239 :
1240 14 : std::vector<std::shared_ptr<GDALMDArray>> apoInputArrays;
1241 20 : for (size_t i = 0; i < nCountInputArrays; ++i)
1242 13 : apoInputArrays.push_back(pahInputArrays[i]->m_poImpl);
1243 :
1244 : const auto apoOutputArrays =
1245 7 : GDALMDArray::GetMeshGrid(apoInputArrays, papszOptions);
1246 : auto ret = static_cast<GDALMDArrayH *>(
1247 7 : CPLMalloc(sizeof(GDALMDArrayH) * apoOutputArrays.size()));
1248 17 : for (size_t i = 0; i < apoOutputArrays.size(); i++)
1249 : {
1250 10 : ret[i] = new GDALMDArrayHS(apoOutputArrays[i]);
1251 : }
1252 7 : *pnCountOutputArrays = apoOutputArrays.size();
1253 7 : return ret;
1254 : }
1255 :
1256 : /************************************************************************/
1257 : /* GDALReleaseArrays() */
1258 : /************************************************************************/
1259 :
1260 : /** Free the return of GDALMDArrayGetCoordinateVariables()
1261 : *
1262 : * @param arrays return pointer of above methods
1263 : * @param nCount *pnCount value returned by above methods
1264 : */
1265 20 : void GDALReleaseArrays(GDALMDArrayH *arrays, size_t nCount)
1266 : {
1267 46 : for (size_t i = 0; i < nCount; i++)
1268 : {
1269 26 : delete arrays[i];
1270 : }
1271 20 : CPLFree(arrays);
1272 20 : }
1273 :
1274 : /************************************************************************/
1275 : /* GDALMDArrayCache() */
1276 : /************************************************************************/
1277 :
1278 : /**
1279 : * \brief Cache the content of the array into an auxiliary filename.
1280 : *
1281 : * This is the same as the C++ method GDALMDArray::Cache().
1282 : *
1283 : * @since GDAL 3.4
1284 : */
1285 :
1286 7 : int GDALMDArrayCache(GDALMDArrayH hArray, CSLConstList papszOptions)
1287 : {
1288 7 : VALIDATE_POINTER1(hArray, __func__, FALSE);
1289 7 : return hArray->m_poImpl->Cache(papszOptions);
1290 : }
1291 :
1292 : /************************************************************************/
1293 : /* GDALMDArrayRename() */
1294 : /************************************************************************/
1295 :
1296 : /** Rename the array.
1297 : *
1298 : * This is not implemented by all drivers.
1299 : *
1300 : * Drivers known to implement it: MEM, netCDF, Zarr.
1301 : *
1302 : * This is the same as the C++ method GDALAbstractMDArray::Rename()
1303 : *
1304 : * @return true in case of success
1305 : * @since GDAL 3.8
1306 : */
1307 28 : bool GDALMDArrayRename(GDALMDArrayH hArray, const char *pszNewName)
1308 : {
1309 28 : VALIDATE_POINTER1(hArray, __func__, false);
1310 28 : VALIDATE_POINTER1(pszNewName, __func__, false);
1311 28 : return hArray->m_poImpl->Rename(pszNewName);
1312 : }
1313 :
1314 : /************************************************************************/
1315 : /* GDALMDArrayAsClassicDataset() */
1316 : /************************************************************************/
1317 :
1318 : /** Return a view of this array as a "classic" GDALDataset (ie 2D)
1319 : *
1320 : * Only 2D or more arrays are supported.
1321 : *
1322 : * In the case of > 2D arrays, additional dimensions will be represented as
1323 : * raster bands.
1324 : *
1325 : * The "reverse" methods are GDALRasterBand::AsMDArray() and
1326 : * GDALDataset::AsMDArray()
1327 : *
1328 : * This is the same as the C++ method GDALMDArray::AsClassicDataset().
1329 : *
1330 : * @param hArray Array.
1331 : * @param iXDim Index of the dimension that will be used as the X/width axis.
1332 : * @param iYDim Index of the dimension that will be used as the Y/height axis.
1333 : * @return a new GDALDataset that must be freed with GDALClose(), or nullptr
1334 : */
1335 0 : GDALDatasetH GDALMDArrayAsClassicDataset(GDALMDArrayH hArray, size_t iXDim,
1336 : size_t iYDim)
1337 : {
1338 0 : VALIDATE_POINTER1(hArray, __func__, nullptr);
1339 0 : return GDALDataset::ToHandle(
1340 0 : hArray->m_poImpl->AsClassicDataset(iXDim, iYDim));
1341 : }
1342 :
1343 : /************************************************************************/
1344 : /* GDALMDArrayAsClassicDatasetEx() */
1345 : /************************************************************************/
1346 :
1347 : /** Return a view of this array as a "classic" GDALDataset (ie 2D)
1348 : *
1349 : * Only 2D or more arrays are supported.
1350 : *
1351 : * In the case of > 2D arrays, additional dimensions will be represented as
1352 : * raster bands.
1353 : *
1354 : * The "reverse" method is GDALRasterBand::AsMDArray().
1355 : *
1356 : * This is the same as the C++ method GDALMDArray::AsClassicDataset().
1357 : * @param hArray Array.
1358 : * @param iXDim Index of the dimension that will be used as the X/width axis.
1359 : * @param iYDim Index of the dimension that will be used as the Y/height axis.
1360 : * Ignored if the dimension count is 1.
1361 : * @param hRootGroup Root group, or NULL. Used with the BAND_METADATA and
1362 : * BAND_IMAGERY_METADATA option.
1363 : * @param papszOptions Cf GDALMDArray::AsClassicDataset()
1364 : * @return a new GDALDataset that must be freed with GDALClose(), or nullptr
1365 : * @since GDAL 3.8
1366 : */
1367 112 : GDALDatasetH GDALMDArrayAsClassicDatasetEx(GDALMDArrayH hArray, size_t iXDim,
1368 : size_t iYDim, GDALGroupH hRootGroup,
1369 : CSLConstList papszOptions)
1370 : {
1371 112 : VALIDATE_POINTER1(hArray, __func__, nullptr);
1372 224 : return GDALDataset::ToHandle(hArray->m_poImpl->AsClassicDataset(
1373 224 : iXDim, iYDim, hRootGroup ? hRootGroup->m_poImpl : nullptr,
1374 224 : papszOptions));
1375 : }
1376 :
1377 : /************************************************************************/
1378 : /* GDALMDArray::GetRawBlockInfo() */
1379 : /************************************************************************/
1380 :
1381 : /** Return information on a raw block.
1382 : *
1383 : * The block coordinates must be between 0 and
1384 : * (GetDimensions()[i]->GetSize() / GetBlockSize()[i]) - 1, for all i between
1385 : * 0 and GetDimensionCount()-1.
1386 : *
1387 : * If the queried block has valid coordinates but is missing in the dataset,
1388 : * all fields of info will be set to 0/nullptr, but the function will return
1389 : * true.
1390 : *
1391 : * This method is only implemented by a subset of drivers. The base
1392 : * implementation just returns false and empty info.
1393 : *
1394 : * The values returned in psBlockInfo->papszInfo are driver dependent.
1395 : *
1396 : * For multi-byte data types, drivers should return a "ENDIANNESS" key whose
1397 : * value is "LITTLE" or "BIG".
1398 : *
1399 : * For HDF5 and netCDF 4, the potential keys are "COMPRESSION" (possible values
1400 : * "DEFLATE" or "SZIP") and "FILTER" (if several filters, names are
1401 : * comma-separated)
1402 : *
1403 : * For ZARR, the potential keys are "COMPRESSOR" (value is the JSON encoded
1404 : * content from the array definition), "FILTERS" (for Zarr V2, value is JSON
1405 : * encoded content) and "TRANSPOSE_ORDER" (value is a string like
1406 : * "[idx0,...,idxN]" with the permutation).
1407 : *
1408 : * For VRT, the potential keys are the ones of the underlying source(s). Note
1409 : * that GetRawBlockInfo() on VRT only works when the VRT declares a block size,
1410 : * that for each queried VRT block, there is one and only one source that
1411 : * is used to fill the VRT block and that the block size of this source is
1412 : * exactly the one of the VRT block.
1413 : *
1414 : * This is the same as C function GDALMDArrayGetRawBlockInfo().
1415 : *
1416 : * @param panBlockCoordinates array of GetDimensionCount() values with the block
1417 : * coordinates.
1418 : * @param[out] info structure to fill with block information.
1419 : * @return true in case of success, or false if an error occurs.
1420 : * @since 3.12
1421 : */
1422 0 : bool GDALMDArray::GetRawBlockInfo(const uint64_t *panBlockCoordinates,
1423 : GDALMDArrayRawBlockInfo &info) const
1424 : {
1425 : (void)panBlockCoordinates;
1426 0 : info.clear();
1427 0 : return false;
1428 : }
1429 :
1430 : /************************************************************************/
1431 : /* GDALMDArrayGetRawBlockInfo() */
1432 : /************************************************************************/
1433 :
1434 : /** Return information on a raw block.
1435 : *
1436 : * The block coordinates must be between 0 and
1437 : * (GetDimensions()[i]->GetSize() / GetBlockSize()[i]) - 1, for all i between
1438 : * 0 and GetDimensionCount()-1.
1439 : *
1440 : * If the queried block has valid coordinates but is missing in the dataset,
1441 : * all fields of info will be set to 0/nullptr, but the function will return
1442 : * true.
1443 : *
1444 : * This method is only implemented by a subset of drivers. The base
1445 : * implementation just returns false and empty info.
1446 : *
1447 : * The values returned in psBlockInfo->papszInfo are driver dependent.
1448 : *
1449 : * For multi-byte data types, drivers should return a "ENDIANNESS" key whose
1450 : * value is "LITTLE" or "BIG".
1451 : *
1452 : * For HDF5 and netCDF 4, the potential keys are "COMPRESSION" (possible values
1453 : * "DEFLATE" or "SZIP") and "FILTER" (if several filters, names are
1454 : * comma-separated)
1455 : *
1456 : * For ZARR, the potential keys are "COMPRESSOR" (value is the JSON encoded
1457 : * content from the array definition), "FILTERS" (for Zarr V2, value is JSON
1458 : * encoded content) and "TRANSPOSE_ORDER" (value is a string like
1459 : * "[idx0,...,idxN]" with the permutation).
1460 : *
1461 : * For VRT, the potential keys are the ones of the underlying source(s). Note
1462 : * that GetRawBlockInfo() on VRT only works when the VRT declares a block size,
1463 : * that for each queried VRT block, there is one and only one source that
1464 : * is used to fill the VRT block and that the block size of this source is
1465 : * exactly the one of the VRT block.
1466 : *
1467 : * This is the same as C++ method GDALMDArray::GetRawBlockInfo().
1468 : *
1469 : * @param hArray handle to array.
1470 : * @param panBlockCoordinates array of GetDimensionCount() values with the block
1471 : * coordinates.
1472 : * @param[out] psBlockInfo structure to fill with block information.
1473 : * Must be allocated with GDALMDArrayRawBlockInfoCreate(),
1474 : * and freed with GDALMDArrayRawBlockInfoRelease().
1475 : * @return true in case of success, or false if an error occurs.
1476 : * @since 3.12
1477 : */
1478 21 : bool GDALMDArrayGetRawBlockInfo(GDALMDArrayH hArray,
1479 : const uint64_t *panBlockCoordinates,
1480 : GDALMDArrayRawBlockInfo *psBlockInfo)
1481 : {
1482 21 : VALIDATE_POINTER1(hArray, __func__, false);
1483 21 : VALIDATE_POINTER1(panBlockCoordinates, __func__, false);
1484 21 : VALIDATE_POINTER1(psBlockInfo, __func__, false);
1485 21 : return hArray->m_poImpl->GetRawBlockInfo(panBlockCoordinates, *psBlockInfo);
1486 : }
1487 :
1488 : /************************************************************************/
1489 : /* GDALMDArrayRawBlockInfoCreate() */
1490 : /************************************************************************/
1491 :
1492 : /** Allocate a new instance of GDALMDArrayRawBlockInfo.
1493 : *
1494 : * Returned pointer must be freed with GDALMDArrayRawBlockInfoRelease().
1495 : *
1496 : * @since 3.12
1497 : */
1498 21 : GDALMDArrayRawBlockInfo *GDALMDArrayRawBlockInfoCreate(void)
1499 : {
1500 21 : return new GDALMDArrayRawBlockInfo();
1501 : }
1502 :
1503 : /************************************************************************/
1504 : /* GDALMDArrayRawBlockInfoRelease() */
1505 : /************************************************************************/
1506 :
1507 : /** Free an instance of GDALMDArrayRawBlockInfo.
1508 : *
1509 : * @since 3.12
1510 : */
1511 21 : void GDALMDArrayRawBlockInfoRelease(GDALMDArrayRawBlockInfo *psBlockInfo)
1512 : {
1513 21 : delete psBlockInfo;
1514 21 : }
1515 :
1516 : /************************************************************************/
1517 : /* GDALMDArray::GetOverviewCount() */
1518 : /************************************************************************/
1519 :
1520 : /**
1521 : * \brief Return the number of overview arrays available.
1522 : *
1523 : * This method is the same as the C function GDALMDArrayGetOverviewCount().
1524 : *
1525 : * @return overview count, zero if none.
1526 : *
1527 : * @since 3.13
1528 : */
1529 :
1530 118 : int GDALMDArray::GetOverviewCount() const
1531 : {
1532 118 : return 0;
1533 : }
1534 :
1535 : /************************************************************************/
1536 : /* GDALMDArrayGetOverviewCount() */
1537 : /************************************************************************/
1538 : /**
1539 : * \brief Return the number of overview arrays available.
1540 : *
1541 : * This method is the same as the C++ method GDALMDArray::GetOverviewCount().
1542 : *
1543 : * @param hArray Array.
1544 : * @return overview count, zero if none.
1545 : *
1546 : * @since 3.13
1547 : */
1548 :
1549 113 : int GDALMDArrayGetOverviewCount(GDALMDArrayH hArray)
1550 : {
1551 113 : VALIDATE_POINTER1(hArray, __func__, 0);
1552 113 : return hArray->m_poImpl->GetOverviewCount();
1553 : }
1554 :
1555 : /************************************************************************/
1556 : /* GDALMDArray::GetOverview() */
1557 : /************************************************************************/
1558 :
1559 : /**
1560 : * \brief Get overview array object.
1561 : *
1562 : * This method is the same as the C function GDALMDArrayGetOverview().
1563 : *
1564 : * @param nIdx overview index between 0 and GetOverviewCount()-1.
1565 : *
1566 : * @return overview GDALMDArray, or nullptr
1567 : *
1568 : * @since 3.13
1569 : */
1570 :
1571 70 : std::shared_ptr<GDALMDArray> GDALMDArray::GetOverview(int nIdx) const
1572 : {
1573 : (void)nIdx;
1574 70 : return nullptr;
1575 : }
1576 :
1577 : /************************************************************************/
1578 : /* GDALMDArrayGetOverview() */
1579 : /************************************************************************/
1580 :
1581 : /**
1582 : * \brief Get overview array object.
1583 : *
1584 : * This method is the same as the C++ method GDALMDArray::GetOverview().
1585 : *
1586 : * @param hArray Array.
1587 : * @param nIdx overview index between 0 and GDALMDArrayGetOverviewCount()-1.
1588 : *
1589 : * @return overview GDALMDArray, or nullptr.
1590 : * Must be released with GDALMDArrayRelease()
1591 : *
1592 : * @since 3.13
1593 : */
1594 :
1595 124 : GDALMDArrayH GDALMDArrayGetOverview(GDALMDArrayH hArray, int nIdx)
1596 : {
1597 124 : VALIDATE_POINTER1(hArray, __func__, nullptr);
1598 248 : auto poOverview = hArray->m_poImpl->GetOverview(nIdx);
1599 124 : if (!poOverview)
1600 89 : return nullptr;
1601 35 : return new GDALMDArrayHS(poOverview);
1602 : }
1603 :
1604 : /************************************************************************/
1605 : /* GDALMDArray::BuildOverviews() */
1606 : /************************************************************************/
1607 :
1608 : /** Build overviews for this array.
1609 : *
1610 : * Creates reduced resolution copies of this array using the specified
1611 : * resampling method. The driver is responsible for storing the overview
1612 : * arrays and any associated metadata (e.g., multiscales convention for Zarr).
1613 : *
1614 : * For arrays with more than 2 dimensions, only the spatial dimensions
1615 : * (last two by default, or as specified by the spatial:dimensions
1616 : * attribute) are downsampled. Non-spatial dimensions are preserved.
1617 : *
1618 : * Overview factors need not be sorted; the implementation will sort and
1619 : * deduplicate them. Each level is resampled sequentially from the
1620 : * previous level (e.g., 4x is built from 2x, not from the base).
1621 : *
1622 : * This method can also be invoked via GDALDataset::BuildOverviews()
1623 : * when the dataset was obtained through GDALMDArray::AsClassicDataset().
1624 : *
1625 : * @note The Zarr v3 implementation replaces all existing overviews on each
1626 : * call, unlike GDALDataset::BuildOverviews() which may add new levels.
1627 : *
1628 : * @note Currently only implemented by the Zarr v3 driver.
1629 : *
1630 : * @param pszResampling Resampling method name (e.g., "NEAREST", "AVERAGE").
1631 : * If nullptr or empty, defaults to "NEAREST".
1632 : * @param nOverviews Number of overview levels to build. Pass 0 to remove
1633 : * all existing overviews.
1634 : * @param panOverviewList Array of overview decimation factors (e.g., 2, 4, 8).
1635 : * Each factor must be >= 2. May be nullptr when
1636 : * nOverviews is 0.
1637 : * @param pfnProgress Progress callback, or nullptr.
1638 : * @param pProgressData Progress callback user data.
1639 : * @param papszOptions Driver-specific options, or nullptr.
1640 : * @return CE_None on success, CE_Failure otherwise.
1641 : * @since GDAL 3.13
1642 : */
1643 2 : CPLErr GDALMDArray::BuildOverviews(CPL_UNUSED const char *pszResampling,
1644 : CPL_UNUSED int nOverviews,
1645 : CPL_UNUSED const int *panOverviewList,
1646 : CPL_UNUSED GDALProgressFunc pfnProgress,
1647 : CPL_UNUSED void *pProgressData,
1648 : CPL_UNUSED CSLConstList papszOptions)
1649 : {
1650 2 : CPLError(CE_Failure, CPLE_NotSupported,
1651 : "BuildOverviews() not supported by this driver");
1652 2 : return CE_Failure;
1653 : }
1654 :
1655 : /************************************************************************/
1656 : /* GDALMDArrayBuildOverviews() */
1657 : /************************************************************************/
1658 :
1659 : /** \brief Build overviews for a multidimensional array.
1660 : *
1661 : * This is the same as the C++ method GDALMDArray::BuildOverviews().
1662 : *
1663 : * @since GDAL 3.13
1664 : */
1665 13 : CPLErr GDALMDArrayBuildOverviews(GDALMDArrayH hArray, const char *pszResampling,
1666 : int nOverviews, const int *panOverviewList,
1667 : GDALProgressFunc pfnProgress,
1668 : void *pProgressData, CSLConstList papszOptions)
1669 : {
1670 13 : VALIDATE_POINTER1(hArray, __func__, CE_Failure);
1671 26 : return hArray->m_poImpl->BuildOverviews(pszResampling, nOverviews,
1672 : panOverviewList, pfnProgress,
1673 13 : pProgressData, papszOptions);
1674 : }
|