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 11 : HDF5CreateRAT(const std::shared_ptr<GDALMDArray> &poValues, 24 : bool bFirstColIsMinMax) 25 : { 26 22 : auto poRAT = std::make_unique<GDALDefaultRasterAttributeTable>(); 27 11 : const auto &poComponents = poValues->GetDataType().GetComponents(); 28 42 : for (const auto &poComponent : poComponents) 29 : { 30 : GDALRATFieldType eType; 31 31 : if (poComponent->GetType().GetClass() == GEDTC_NUMERIC) 32 : { 33 21 : if (GDALDataTypeIsInteger( 34 42 : poComponent->GetType().GetNumericDataType())) 35 : { 36 : // S102 featureAttributeTable 37 11 : if (poComponent->GetName() == 38 : "featuresDetected." 39 11 : "leastDepthOfDetectedFeaturesMeasured" || 40 11 : poComponent->GetName() == 41 11 : "featuresDetected.significantFeaturesDetected" || 42 33 : poComponent->GetName() == "fullSeafloorCoverageAchieved" || 43 11 : poComponent->GetName() == "bathyCoverage") 44 : { 45 0 : eType = GFT_Boolean; 46 : } 47 : else 48 : { 49 11 : eType = GFT_Integer; 50 : } 51 : } 52 : else 53 10 : eType = GFT_Real; 54 : } 55 : else 56 : { 57 : // S102 featureAttributeTable 58 20 : if (poComponent->GetName() == "surveyDateRange.dateStart" || 59 10 : poComponent->GetName() == "surveyDateRange.dateEnd") 60 0 : eType = GFT_DateTime; 61 : else 62 10 : eType = GFT_String; 63 : } 64 62 : poRAT->CreateColumn(poComponent->GetName().c_str(), eType, 65 13 : bFirstColIsMinMax && poRAT->GetColumnCount() == 0 66 : ? GFU_MinMax 67 31 : : GFU_Generic); 68 : } 69 : 70 11 : const auto &oValuesDT = poValues->GetDataType(); 71 22 : std::vector<GByte> abyRow(oValuesDT.GetSize()); 72 11 : const int nRows = static_cast<int>(poValues->GetDimensions()[0]->GetSize()); 73 63 : for (int iRow = 0; iRow < nRows; iRow++) 74 : { 75 52 : const GUInt64 arrayStartIdx = static_cast<GUInt64>(iRow); 76 52 : const size_t count = 1; 77 52 : const GInt64 arrayStep = 0; 78 52 : const GPtrDiff_t bufferStride = 0; 79 104 : poValues->Read(&arrayStartIdx, &count, &arrayStep, &bufferStride, 80 52 : oValuesDT, &abyRow[0]); 81 52 : int iCol = 0; 82 192 : for (const auto &poComponent : poComponents) 83 : { 84 140 : const auto eRATType = poRAT->GetTypeOfCol(iCol); 85 140 : if (eRATType == GFT_Integer || eRATType == GFT_Boolean) 86 : { 87 52 : int nValue = 0; 88 52 : GDALCopyWords(&abyRow[poComponent->GetOffset()], 89 52 : poComponent->GetType().GetNumericDataType(), 0, 90 : &nValue, GDT_Int32, 0, 1); 91 52 : poRAT->SetValue(iRow, iCol, nValue); 92 : } 93 88 : else if (eRATType == GFT_Real) 94 : { 95 44 : double dfValue = 0; 96 44 : GDALCopyWords(&abyRow[poComponent->GetOffset()], 97 44 : poComponent->GetType().GetNumericDataType(), 0, 98 : &dfValue, GDT_Float64, 0, 1); 99 44 : poRAT->SetValue(iRow, iCol, dfValue); 100 : } 101 : else 102 : { 103 44 : char *pszStr = nullptr; 104 88 : GDALExtendedDataType::CopyValue( 105 44 : &abyRow[poComponent->GetOffset()], poComponent->GetType(), 106 88 : &pszStr, GDALExtendedDataType::CreateString()); 107 44 : if (pszStr) 108 : { 109 44 : if (eRATType == GFT_DateTime) 110 : { 111 0 : GDALRATDateTime sDateTime; 112 0 : if (strlen(pszStr) == 8 && 113 0 : sscanf(pszStr, "%04d%02d%02d", &(sDateTime.nYear), 114 : &(sDateTime.nMonth), &(sDateTime.nDay)) == 3) 115 : { 116 0 : sDateTime.bPositiveTimeZone = true; 117 0 : 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 0 : poRAT->SetValue(iRow, iCol, sDateTime); 146 : } 147 : else 148 : { 149 44 : poRAT->SetValue(iRow, iCol, pszStr); 150 : } 151 : } 152 44 : CPLFree(pszStr); 153 : } 154 140 : iCol++; 155 : } 156 52 : oValuesDT.FreeDynamicMemory(&abyRow[0]); 157 : } 158 22 : return poRAT; 159 : }