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