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

Generated by: LCOV version 1.14