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

Generated by: LCOV version 1.14