Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: Hierarchical Data Format Release 5 (HDF5) 4 : * Purpose: RAT utility 5 : * Author: Even Rouault <even dot rouault at spatialys dot com> 6 : * 7 : ****************************************************************************** 8 : * Copyright (c) 2023, Even Rouault <even dot rouault at spatialys dot com> 9 : * 10 : * SPDX-License-Identifier: MIT 11 : ****************************************************************************/ 12 : 13 : #include "rat.h" 14 : #include "ogr_p.h" 15 : 16 : #include <cmath> 17 : 18 : /************************************************************************/ 19 : /* CreateRAT() */ 20 : /************************************************************************/ 21 : 22 : std::unique_ptr<GDALRasterAttributeTable> 23 13 : HDF5CreateRAT(const std::shared_ptr<GDALMDArray> &poValues, 24 : bool bFirstColIsMinMax) 25 : { 26 26 : auto poRAT = std::make_unique<GDALDefaultRasterAttributeTable>(); 27 13 : const auto &poComponents = poValues->GetDataType().GetComponents(); 28 56 : for (const auto &poComponent : poComponents) 29 : { 30 : GDALRATFieldType eType; 31 43 : if (poComponent->GetType().GetClass() == GEDTC_NUMERIC) 32 : { 33 30 : if (GDALDataTypeIsInteger( 34 60 : poComponent->GetType().GetNumericDataType())) 35 : { 36 : // S102 featureAttributeTable 37 18 : if (poComponent->GetName() == 38 : "featuresDetected." 39 18 : "leastDepthOfDetectedFeaturesMeasured" || 40 18 : poComponent->GetName() == 41 18 : "featuresDetected.significantFeaturesDetected" || 42 54 : poComponent->GetName() == "fullSeafloorCoverageAchieved" || 43 18 : poComponent->GetName() == "bathyCoverage") 44 : { 45 1 : eType = GFT_Boolean; 46 : } 47 : else 48 : { 49 17 : eType = GFT_Integer; 50 : } 51 : } 52 : else 53 12 : eType = GFT_Real; 54 : } 55 : else 56 : { 57 : // S102 featureAttributeTable 58 25 : if (poComponent->GetName() == "surveyDateRange.dateStart" || 59 12 : poComponent->GetName() == "surveyDateRange.dateEnd") 60 1 : eType = GFT_DateTime; 61 : else 62 12 : eType = GFT_String; 63 : } 64 86 : poRAT->CreateColumn(poComponent->GetName().c_str(), eType, 65 25 : bFirstColIsMinMax && poRAT->GetColumnCount() == 0 66 : ? GFU_MinMax 67 43 : : GFU_Generic); 68 : } 69 : 70 13 : const auto &oValuesDT = poValues->GetDataType(); 71 26 : std::vector<GByte> abyRow(oValuesDT.GetSize()); 72 13 : const int nRows = static_cast<int>(poValues->GetDimensions()[0]->GetSize()); 73 68 : for (int iRow = 0; iRow < nRows; iRow++) 74 : { 75 55 : const GUInt64 arrayStartIdx = static_cast<GUInt64>(iRow); 76 55 : const size_t count = 1; 77 55 : const GInt64 arrayStep = 0; 78 55 : const GPtrDiff_t bufferStride = 0; 79 110 : poValues->Read(&arrayStartIdx, &count, &arrayStep, &bufferStride, 80 55 : oValuesDT, &abyRow[0]); 81 55 : int iCol = 0; 82 214 : for (const auto &poComponent : poComponents) 83 : { 84 159 : const auto eRATType = poRAT->GetTypeOfCol(iCol); 85 159 : if (eRATType == GFT_Integer || eRATType == GFT_Boolean) 86 : { 87 63 : int nValue = 0; 88 63 : GDALCopyWords(&abyRow[poComponent->GetOffset()], 89 63 : poComponent->GetType().GetNumericDataType(), 0, 90 : &nValue, GDT_Int32, 0, 1); 91 63 : poRAT->SetValue(iRow, iCol, nValue); 92 : } 93 96 : else if (eRATType == GFT_Real) 94 : { 95 47 : double dfValue = 0; 96 47 : GDALCopyWords(&abyRow[poComponent->GetOffset()], 97 47 : poComponent->GetType().GetNumericDataType(), 0, 98 : &dfValue, GDT_Float64, 0, 1); 99 47 : poRAT->SetValue(iRow, iCol, dfValue); 100 : } 101 : else 102 : { 103 49 : char *pszStr = nullptr; 104 98 : GDALExtendedDataType::CopyValue( 105 49 : &abyRow[poComponent->GetOffset()], poComponent->GetType(), 106 98 : &pszStr, GDALExtendedDataType::CreateString()); 107 49 : if (pszStr) 108 : { 109 49 : if (eRATType == GFT_DateTime) 110 : { 111 2 : GDALRATDateTime sDateTime; 112 4 : if (strlen(pszStr) == 8 && 113 2 : sscanf(pszStr, "%04d%02d%02d", &(sDateTime.nYear), 114 : &(sDateTime.nMonth), &(sDateTime.nDay)) == 3) 115 : { 116 2 : sDateTime.bPositiveTimeZone = true; 117 2 : sDateTime.bIsValid = true; 118 : } 119 : else 120 : { 121 : OGRField sField; 122 0 : if (OGRParseDate(pszStr, &sField, 0)) 123 : { 124 0 : sDateTime.nYear = sField.Date.Year; 125 0 : sDateTime.nMonth = sField.Date.Month; 126 0 : sDateTime.nDay = sField.Date.Day; 127 0 : sDateTime.nHour = sField.Date.Hour; 128 0 : sDateTime.nMinute = sField.Date.Minute; 129 0 : sDateTime.fSecond = sField.Date.Second; 130 0 : sDateTime.bPositiveTimeZone = 131 0 : sField.Date.TZFlag >= 100 || 132 0 : sField.Date.TZFlag <= 2; 133 0 : if (sField.Date.TZFlag > 2) 134 : { 135 0 : sDateTime.nTimeZoneHour = 136 0 : std::abs(sField.Date.TZFlag - 100) / 4; 137 0 : sDateTime.nTimeZoneMinute = 138 0 : (std::abs(sField.Date.TZFlag - 100) % 139 0 : 4) * 140 : 15; 141 : } 142 0 : sDateTime.bIsValid = true; 143 : } 144 : } 145 2 : poRAT->SetValue(iRow, iCol, sDateTime); 146 : } 147 : else 148 : { 149 47 : poRAT->SetValue(iRow, iCol, pszStr); 150 : } 151 : } 152 49 : CPLFree(pszStr); 153 : } 154 159 : iCol++; 155 : } 156 55 : oValuesDT.FreeDynamicMemory(&abyRow[0]); 157 : } 158 26 : return poRAT; 159 : }