LCOV - code coverage report
Current view: top level - gcore - gdalmultidim_rat.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 171 186 91.9 %
Date: 2025-07-09 17:50:03 Functions: 23 23 100.0 %

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

Generated by: LCOV version 1.14