• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

OSGeo / gdal / 15885686134

25 Jun 2025 07:44PM UTC coverage: 71.084%. Remained the same
15885686134

push

github

rouault
gdal_priv.h: fix C++11 compatibility

573814 of 807237 relevant lines covered (71.08%)

250621.56 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.15
/frmts/hdf5/hdf5eosparser.cpp
1
/******************************************************************************
2
 *
3
 * Project:  Hierarchical Data Format Release 5 (HDF5)
4
 * Purpose:  Implementation of HDF5 HDFEOS parser
5
 * Author:   Even Rouault
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 2023, Even Rouault <even dot rouault at spatialys.com>
9
 *
10
 * SPDX-License-Identifier: MIT
11
 ****************************************************************************/
12

13
#include "cpl_error.h"
14
#include "nasakeywordhandler.h"
15

16
#include "hdf5eosparser.h"
17

18
#include <cstring>
19
#include <utility>
20

21
/************************************************************************/
22
/*                             HasHDFEOS()                              */
23
/************************************************************************/
24

25
bool HDF5EOSParser::HasHDFEOS(hid_t hRoot)
258✔
26
{
27
    hsize_t numObjs = 0;
258✔
28
    H5Gget_num_objs(hRoot, &numObjs);
258✔
29
    bool bFound = false;
258✔
30
    for (hsize_t i = 0; i < numObjs; ++i)
866✔
31
    {
32
        char szName[128];
33
        ssize_t nLen =
34
            H5Gget_objname_by_idx(hRoot, i, szName, sizeof(szName) - 1);
634✔
35
        if (nLen > 0)
634✔
36
        {
37
            szName[nLen] = 0;
634✔
38
            if (strcmp(szName, "HDFEOS INFORMATION") == 0)
634✔
39
            {
40
                bFound = true;
26✔
41
                break;
26✔
42
            }
43
        }
44
    }
45
    if (!bFound)
258✔
46
        return false;
232✔
47

48
    H5G_stat_t oStatbuf;
49
    if (H5Gget_objinfo(hRoot, "HDFEOS INFORMATION", false, &oStatbuf) < 0)
26✔
50
        return false;
×
51

52
    auto hHDFEOSInformation = H5Gopen(hRoot, "HDFEOS INFORMATION");
26✔
53
    if (hHDFEOSInformation < 0)
26✔
54
    {
55
        return false;
×
56
    }
57
    H5Gclose(hHDFEOSInformation);
26✔
58
    return true;
26✔
59
}
60

61
/************************************************************************/
62
/*                               Parse()                                */
63
/************************************************************************/
64

65
bool HDF5EOSParser::Parse(hid_t hRoot)
26✔
66
{
67
    auto hHDFEOSInformation = H5Gopen(hRoot, "HDFEOS INFORMATION");
26✔
68
    if (hHDFEOSInformation < 0)
26✔
69
    {
70
        return false;
×
71
    }
72

73
    const hid_t hArrayId = H5Dopen(hHDFEOSInformation, "StructMetadata.0");
26✔
74
    if (hArrayId < 0)
26✔
75
    {
76
        CPLError(CE_Failure, CPLE_AppDefined, "Cannot find StructMetadata.0");
×
77
        H5Gclose(hHDFEOSInformation);
×
78
        return false;
×
79
    }
80

81
    const hid_t hAttrSpace = H5Dget_space(hArrayId);
26✔
82
    const hid_t hAttrTypeID = H5Dget_type(hArrayId);
26✔
83
    const hid_t hAttrNativeType =
84
        H5Tget_native_type(hAttrTypeID, H5T_DIR_DEFAULT);
26✔
85

86
    // Fetch StructMetadata.0 content in a std::string
87
    std::string osResult;
52✔
88
    if (H5Tget_class(hAttrNativeType) == H5T_STRING &&
26✔
89
        !H5Tis_variable_str(hAttrNativeType) &&
52✔
90
        H5Sget_simple_extent_ndims(hAttrSpace) == 0)
26✔
91
    {
92
        const auto nSize = H5Tget_size(hAttrNativeType);
26✔
93
        if (nSize > 10 * 1024 * 1024)
26✔
94
        {
95
            CPLError(CE_Failure, CPLE_AppDefined,
×
96
                     "Too large HDFEOS INFORMATION.StructMetadata.0");
97
        }
98
        else
99
        {
100
            osResult.resize(nSize);
26✔
101
            H5Dread(hArrayId, hAttrNativeType, H5S_ALL, hAttrSpace, H5P_DEFAULT,
26✔
102
                    &osResult[0]);
26✔
103
        }
104
    }
105
    else
106
    {
107
        CPLError(CE_Failure, CPLE_AppDefined,
×
108
                 "HDFEOS INFORMATION.StructMetadata.0 not of type string");
109
    }
110
    H5Sclose(hAttrSpace);
26✔
111
    H5Tclose(hAttrNativeType);
26✔
112
    H5Tclose(hAttrTypeID);
26✔
113

114
    H5Dclose(hArrayId);
26✔
115
    H5Gclose(hHDFEOSInformation);
26✔
116

117
    if (osResult.empty())
26✔
118
        return false;
×
119

120
    // Parse StructMetadata.0 with NASAKeywordHandler
121
    NASAKeywordHandler oKWHandler;
52✔
122
#ifdef DEBUG
123
    CPLDebug("HDF5EOS", "%s", osResult.c_str());
26✔
124
#endif
125
    if (!oKWHandler.Parse(osResult.c_str()))
26✔
126
    {
127
        CPLError(CE_Failure, CPLE_AppDefined,
×
128
                 "Cannot parse HDFEOS INFORMATION.StructMetadata.0 with "
129
                 "NASAKeywordHandler");
130
        return false;
×
131
    }
132

133
    auto oJsonRoot = oKWHandler.GetJsonObject();
52✔
134
    auto oGridStructure = oJsonRoot.GetObj("GridStructure");
78✔
135
    auto oSwathStructure = oJsonRoot.GetObj("SwathStructure");
52✔
136
    bool bOK = false;
26✔
137
    // An empty
138
    // GROUP=GridStructure
139
    // END_GROUP=GridStructure
140
    // will generate 2 keys (_type and END_GROUP)
141
    if (oGridStructure.IsValid() && oGridStructure.GetChildren().size() > 2)
26✔
142
    {
143
        bOK = true;
12✔
144
        m_eDataModel = DataModel::GRID;
12✔
145
        ParseGridStructure(oGridStructure);
12✔
146
    }
147
    else if (oSwathStructure.IsValid() &&
28✔
148
             oSwathStructure.GetChildren().size() > 2)
28✔
149
    {
150
        bOK = true;
14✔
151
        m_eDataModel = DataModel::SWATH;
14✔
152
        ParseSwathStructure(oSwathStructure);
14✔
153
    }
154

155
    return bOK;
26✔
156
}
157

158
/************************************************************************/
159
/*                     GetGTCPProjectionCode()                          */
160
/************************************************************************/
161

162
static int GetGTCPProjectionCode(const std::string &osProjection)
12✔
163
{
164
    const char *const apszGCTPProjections[] = {
12✔
165
        "HE5_GCTP_GEO",    "HE5_GCTP_UTM",    "HE5_GCTP_SPCS",
166
        "HE5_GCTP_ALBERS", "HE5_GCTP_LAMCC",  "HE5_GCTP_MERCAT",
167
        "HE5_GCTP_PS",     "HE5_GCTP_POLYC",  "HE5_GCTP_EQUIDC",
168
        "HE5_GCTP_TM",     "HE5_GCTP_STEREO", "HE5_GCTP_LAMAZ",
169
        "HE5_GCTP_AZMEQD", "HE5_GCTP_GNOMON", "HE5_GCTP_ORTHO",
170
        "HE5_GCTP_GVNSP",  "HE5_GCTP_SNSOID", "HE5_GCTP_EQRECT",
171
        "HE5_GCTP_MILLER", "HE5_GCTP_VGRINT", "HE5_GCTP_HOM",
172
        "HE5_GCTP_ROBIN",  "HE5_GCTP_SOM",    "HE5_GCTP_ALASKA",
173
        "HE5_GCTP_GOOD",   "HE5_GCTP_MOLL",   "HE5_GCTP_IMOLL",
174
        "HE5_GCTP_HAMMER", "HE5_GCTP_WAGIV",  "HE5_GCTP_WAGVII",
175
        "HE5_GCTP_OBLEQA"};
176
    // HE5_GCTP_CEA, HE5_GCTP_BCEA, HE5_GCTP_ISINUS not taken
177
    // into account.
178
    for (int i = 0; i < static_cast<int>(CPL_ARRAYSIZE(apszGCTPProjections));
81✔
179
         ++i)
180
    {
181
        if (osProjection == apszGCTPProjections[i])
81✔
182
        {
183
            return i;
12✔
184
        }
185
    }
186
    return -1;
×
187
}
188

189
/************************************************************************/
190
/*                        ParseGridStructure()                          */
191
/************************************************************************/
192

193
void HDF5EOSParser::ParseGridStructure(const CPLJSONObject &oGridStructure)
12✔
194
{
195
    for (const auto &oGrid : oGridStructure.GetChildren())
48✔
196
    {
197
        if (oGrid.GetType() == CPLJSONObject::Type::Object)
36✔
198
        {
199
            const auto osGridName = oGrid.GetString("GridName");
36✔
200
            const auto oDataFields = oGrid.GetObj("DataField");
36✔
201
            const auto oDimensions = oGrid.GetObj("Dimension");
36✔
202
            std::map<std::string, int> oMapDimensionNameToSize;
24✔
203
            auto poGridMetadata = std::make_unique<GridMetadata>();
24✔
204
            poGridMetadata->osGridName = osGridName;
12✔
205
            for (const auto &oDimension : oDimensions.GetChildren())
60✔
206
            {
207
                if (oDimension.GetType() == CPLJSONObject::Type::Object)
48✔
208
                {
209
                    std::string osDimensionName =
210
                        oDimension.GetString("DimensionName");
72✔
211
                    int nSize = oDimension.GetInteger("Size");
24✔
212
                    oMapDimensionNameToSize[osDimensionName] = nSize;
24✔
213
                    Dimension oDim;
48✔
214
                    oDim.osName = std::move(osDimensionName);
24✔
215
                    oDim.nSize = nSize;
24✔
216
                    poGridMetadata->aoDimensions.push_back(std::move(oDim));
24✔
217
                }
218
            }
219

220
            // Happens for example for products following
221
            // AMSR-E/AMSR2 Unified L3 Daily 12.5 km Brightness Temperatures,
222
            // Sea Ice Concentration, Motion & Snow Depth Polar Grids
223
            // (https://nsidc.org/sites/default/files/au_si12-v001-userguide_1.pdf)
224
            // such as
225
            // https://n5eil01u.ecs.nsidc.org/AMSA/AU_SI12.001/2012.07.02/AMSR_U2_L3_SeaIce12km_B04_20120702.he5
226
            const int nXDim = oGrid.GetInteger("XDim", 0);
12✔
227
            const int nYDim = oGrid.GetInteger("YDim", 0);
12✔
228
            if (poGridMetadata->aoDimensions.empty() && nXDim > 0 && nYDim > 0)
12✔
229
            {
230
                // Check that all data fields have a DimList=(YDim,XDim)
231
                // property. This may be unneeded, but at least if we meet
232
                // this condition, that should be a strong hint that the first
233
                // dimension is Y, and the second X.
234
                bool bDimListIsYDimXDim = true;
2✔
235
                for (const auto &oDataField : oDataFields.GetChildren())
8✔
236
                {
237
                    if (oDataField.GetType() == CPLJSONObject::Type::Object)
6✔
238
                    {
239
                        const auto oDimList = oDataField.GetArray("DimList");
4✔
240
                        if (!(oDimList.Size() == 2 &&
4✔
241
                              oDimList[0].ToString() == "YDim" &&
4✔
242
                              oDimList[1].ToString() == "XDim"))
4✔
243
                        {
244
                            bDimListIsYDimXDim = false;
×
245
                            break;
×
246
                        }
247
                    }
248
                }
249
                if (bDimListIsYDimXDim)
2✔
250
                {
251
                    {
252
                        std::string osDimensionName("YDim");
4✔
253
                        oMapDimensionNameToSize[osDimensionName] = nYDim;
2✔
254
                        Dimension oDim;
4✔
255
                        oDim.osName = std::move(osDimensionName);
2✔
256
                        oDim.nSize = nYDim;
2✔
257
                        poGridMetadata->aoDimensions.push_back(std::move(oDim));
2✔
258
                    }
259
                    {
260
                        std::string osDimensionName("XDim");
4✔
261
                        oMapDimensionNameToSize[osDimensionName] = nXDim;
2✔
262
                        Dimension oDim;
4✔
263
                        oDim.osName = std::move(osDimensionName);
2✔
264
                        oDim.nSize = nXDim;
2✔
265
                        poGridMetadata->aoDimensions.push_back(std::move(oDim));
2✔
266
                    }
267
                }
268
            }
269

270
            poGridMetadata->osProjection = oGrid.GetString("Projection");
12✔
271
            poGridMetadata->nProjCode =
24✔
272
                GetGTCPProjectionCode(poGridMetadata->osProjection);
12✔
273
            poGridMetadata->osGridOrigin = oGrid.GetString("GridOrigin");
12✔
274
            poGridMetadata->nZone = oGrid.GetInteger("ZoneCode", -1);
12✔
275
            poGridMetadata->nSphereCode = oGrid.GetInteger("SphereCode", -1);
12✔
276

277
            const auto oProjParams = oGrid.GetArray("ProjParams");
36✔
278
            for (int j = 0; j < oProjParams.Size(); ++j)
64✔
279
                poGridMetadata->adfProjParams.push_back(
52✔
280
                    oProjParams[j].ToDouble());
52✔
281

282
            const auto oUpperLeftPointMtrs =
283
                oGrid.GetArray("UpperLeftPointMtrs");
36✔
284
            for (int j = 0; j < oUpperLeftPointMtrs.Size(); ++j)
36✔
285
                poGridMetadata->adfUpperLeftPointMeters.push_back(
24✔
286
                    oUpperLeftPointMtrs[j].ToDouble());
24✔
287

288
            const auto oLowerRightMtrs = oGrid.GetArray("LowerRightMtrs");
36✔
289
            for (int j = 0; j < oLowerRightMtrs.Size(); ++j)
36✔
290
                poGridMetadata->adfLowerRightPointMeters.push_back(
24✔
291
                    oLowerRightMtrs[j].ToDouble());
24✔
292

293
            m_oMapGridNameToGridMetadata[osGridName] =
12✔
294
                std::move(poGridMetadata);
24✔
295
            const auto poGridMetadataRef =
296
                m_oMapGridNameToGridMetadata[osGridName].get();
12✔
297

298
            for (const auto &oDataField : oDataFields.GetChildren())
48✔
299
            {
300
                if (oDataField.GetType() == CPLJSONObject::Type::Object)
36✔
301
                {
302
                    const auto osDataFieldName =
303
                        oDataField.GetString("DataFieldName");
36✔
304
                    const auto oDimList = oDataField.GetArray("DimList");
36✔
305
                    GridDataFieldMetadata oDataFieldMetadata;
24✔
306
                    bool bValid = oDimList.Size() > 0;
12✔
307
                    for (int j = 0; j < oDimList.Size(); ++j)
40✔
308
                    {
309
                        std::string osDimensionName = oDimList[j].ToString();
56✔
310
                        const auto oIter = oMapDimensionNameToSize.find(
311
                            osDimensionName.c_str());
28✔
312
                        if (oIter == oMapDimensionNameToSize.end())
28✔
313
                        {
314
                            bValid = false;
×
315
                            break;
×
316
                        }
317
                        Dimension oDim;
56✔
318
                        oDim.osName = std::move(osDimensionName);
28✔
319
                        oDim.nSize = oIter->second;
28✔
320
                        oDataFieldMetadata.aoDimensions.push_back(
28✔
321
                            std::move(oDim));
28✔
322
                    }
323
                    if (bValid)
12✔
324
                    {
325
                        oDataFieldMetadata.poGridMetadata = poGridMetadataRef;
12✔
326
                        m_oMapSubdatasetNameToGridDataFieldMetadata
327
                            ["//HDFEOS/GRIDS/" + osGridName + "/Data_Fields/" +
24✔
328
                             osDataFieldName] = std::move(oDataFieldMetadata);
24✔
329
                    }
330
                }
331
            }
332
        }
333
    }
334
}
12✔
335

336
/************************************************************************/
337
/*                        GetGridMetadata()                             */
338
/************************************************************************/
339

340
bool HDF5EOSParser::GetGridMetadata(const std::string &osGridName,
7✔
341
                                    GridMetadata &gridMetadataOut) const
342
{
343
    const auto oIter = m_oMapGridNameToGridMetadata.find(osGridName);
7✔
344
    if (oIter == m_oMapGridNameToGridMetadata.end())
7✔
345
        return false;
5✔
346
    gridMetadataOut = *(oIter->second);
2✔
347
    return true;
2✔
348
}
349

350
/************************************************************************/
351
/*                     GetGridDataFieldMetadata()                       */
352
/************************************************************************/
353

354
bool HDF5EOSParser::GetGridDataFieldMetadata(
10✔
355
    const char *pszSubdatasetName,
356
    GridDataFieldMetadata &gridDataFieldMetadataOut) const
357
{
358
    const auto oIter =
359
        m_oMapSubdatasetNameToGridDataFieldMetadata.find(pszSubdatasetName);
10✔
360
    if (oIter == m_oMapSubdatasetNameToGridDataFieldMetadata.end())
10✔
361
        return false;
3✔
362
    gridDataFieldMetadataOut = oIter->second;
7✔
363
    return true;
7✔
364
}
365

366
/************************************************************************/
367
/*                        ParseSwathStructure()                         */
368
/************************************************************************/
369

370
void HDF5EOSParser::ParseSwathStructure(const CPLJSONObject &oSwathStructure)
14✔
371
{
372
    for (const auto &oSwath : oSwathStructure.GetChildren())
56✔
373
    {
374
        if (oSwath.GetType() == CPLJSONObject::Type::Object)
42✔
375
        {
376
            const auto osSwathName = oSwath.GetString("SwathName");
42✔
377

378
            const auto oDimensions = oSwath.GetObj("Dimension");
42✔
379
            std::map<std::string, int> oMapDimensionNameToSize;
28✔
380
            auto poSwathMetadata = std::make_unique<SwathMetadata>();
28✔
381
            poSwathMetadata->osSwathName = osSwathName;
14✔
382
            for (const auto &oDimension : oDimensions.GetChildren())
120✔
383
            {
384
                if (oDimension.GetType() == CPLJSONObject::Type::Object)
106✔
385
                {
386
                    auto osDimensionName =
387
                        oDimension.GetString("DimensionName");
234✔
388
                    int nSize = oDimension.GetInteger("Size");
78✔
389
                    oMapDimensionNameToSize[osDimensionName] = nSize;
78✔
390
                    Dimension oDim;
156✔
391
                    oDim.osName = std::move(osDimensionName);
78✔
392
                    oDim.nSize = nSize;
78✔
393
                    poSwathMetadata->aoDimensions.emplace_back(std::move(oDim));
78✔
394
                }
395
            }
396

397
            m_oMapSwathNameToSwathMetadata[osSwathName] =
14✔
398
                std::move(poSwathMetadata);
28✔
399
            const auto poSwathMetadataRef =
400
                m_oMapSwathNameToSwathMetadata[osSwathName].get();
14✔
401

402
            struct DimensionMap
403
            {
404
                std::string osGeoDimName{};
405
                std::string osDataDimName{};
406
                int nOffset = 0;
407
                int nIncrement = 1;
408
            };
409

410
            std::vector<DimensionMap> aoDimensionMaps;
28✔
411
            std::map<std::string, std::string> oMapDataDimensionToGeoDimension;
28✔
412

413
            const auto jsonDimensionMaps = oSwath.GetObj("DimensionMap");
42✔
414
            for (const auto &jsonDimensionMap : jsonDimensionMaps.GetChildren())
54✔
415
            {
416
                if (jsonDimensionMap.GetType() == CPLJSONObject::Type::Object)
40✔
417
                {
418
                    DimensionMap oDimensionMap;
24✔
419
                    oDimensionMap.osGeoDimName =
420
                        jsonDimensionMap.GetString("GeoDimension");
12✔
421
                    oDimensionMap.osDataDimName =
422
                        jsonDimensionMap.GetString("DataDimension");
12✔
423
                    oDimensionMap.nOffset =
12✔
424
                        jsonDimensionMap.GetInteger("Offset", 0);
12✔
425
                    oDimensionMap.nIncrement =
12✔
426
                        jsonDimensionMap.GetInteger("Increment", 1);
12✔
427
                    oMapDataDimensionToGeoDimension[oDimensionMap
428
                                                        .osDataDimName] =
12✔
429
                        oDimensionMap.osGeoDimName;
12✔
430
                    aoDimensionMaps.emplace_back(oDimensionMap);
12✔
431
                }
432
            }
433

434
            const auto oGeoFields = oSwath.GetObj("GeoField");
42✔
435
            std::vector<Dimension> aoLongitudeDimensions;
28✔
436
            std::vector<Dimension> aoLatitudeDimensions;
28✔
437
            for (const auto &oGeoField : oGeoFields.GetChildren())
84✔
438
            {
439
                if (oGeoField.GetType() == CPLJSONObject::Type::Object)
70✔
440
                {
441
                    auto osGeoFieldName = oGeoField.GetString("GeoFieldName");
126✔
442
                    auto oDimList = oGeoField.GetArray("DimList");
126✔
443
                    bool bValid = true;
42✔
444
                    std::vector<Dimension> aoDimensions;
84✔
445
                    for (int j = 0; j < oDimList.Size(); ++j)
112✔
446
                    {
447
                        const auto osDimensionName = oDimList[j].ToString();
140✔
448
                        const auto oIter = oMapDimensionNameToSize.find(
449
                            osDimensionName.c_str());
70✔
450
                        if (oIter == oMapDimensionNameToSize.end())
70✔
451
                        {
452
                            bValid = false;
×
453
                            break;
×
454
                        }
455
                        Dimension oDim;
140✔
456
                        oDim.osName = osDimensionName;
70✔
457
                        oDim.nSize = oIter->second;
70✔
458
                        aoDimensions.push_back(std::move(oDim));
70✔
459
                        if (oMapDataDimensionToGeoDimension.find(
70✔
460
                                osDimensionName) ==
70✔
461
                            oMapDataDimensionToGeoDimension.end())
140✔
462
                        {
463
                            // Create a fake dimension map for this dim
464
                            DimensionMap oDimensionMap;
56✔
465
                            oDimensionMap.osGeoDimName = osDimensionName;
28✔
466
                            oDimensionMap.osDataDimName = osDimensionName;
28✔
467
                            oDimensionMap.nOffset = 0;
28✔
468
                            oDimensionMap.nIncrement = 1;
28✔
469
                            oMapDataDimensionToGeoDimension[osDimensionName] =
28✔
470
                                osDimensionName;
28✔
471
                            aoDimensionMaps.emplace_back(oDimensionMap);
28✔
472
                        }
473
                    }
474
                    if (bValid)
42✔
475
                    {
476
                        SwathGeolocationFieldMetadata oMetadata;
84✔
477
                        oMetadata.poSwathMetadata = poSwathMetadataRef;
42✔
478

479
                        if (osGeoFieldName == "Longitude")
42✔
480
                            aoLongitudeDimensions = aoDimensions;
14✔
481
                        else if (osGeoFieldName == "Latitude")
28✔
482
                            aoLatitudeDimensions = aoDimensions;
14✔
483

484
                        oMetadata.aoDimensions = std::move(aoDimensions);
42✔
485

486
                        const std::string osSubdatasetName =
487
                            "//HDFEOS/SWATHS/" + osSwathName +
84✔
488
                            "/Geolocation_Fields/" + osGeoFieldName;
84✔
489
                        m_oMapSubdatasetNameToSwathGeolocationFieldMetadata
490
                            [osSubdatasetName] = std::move(oMetadata);
42✔
491
                    }
492
                }
493
            }
494

495
            const auto oDataFields = oSwath.GetObj("DataField");
42✔
496
            for (const auto &oDataField : oDataFields.GetChildren())
86✔
497
            {
498
                if (oDataField.GetType() == CPLJSONObject::Type::Object)
72✔
499
                {
500
                    const auto osDataFieldName =
501
                        oDataField.GetString("DataFieldName");
132✔
502
                    const auto oDimList = oDataField.GetArray("DimList");
132✔
503
                    SwathDataFieldMetadata oMetadata;
88✔
504
                    oMetadata.poSwathMetadata = poSwathMetadataRef;
44✔
505
                    bool bValid = oDimList.Size() > 0;
44✔
506
                    for (int j = 0; j < oDimList.Size(); ++j)
122✔
507
                    {
508
                        std::string osDimensionName = oDimList[j].ToString();
156✔
509
                        const auto oIter = oMapDimensionNameToSize.find(
510
                            osDimensionName.c_str());
78✔
511
                        if (oIter == oMapDimensionNameToSize.end())
78✔
512
                        {
513
                            bValid = false;
×
514
                            break;
×
515
                        }
516
                        Dimension oDim;
156✔
517
                        oDim.osName = std::move(osDimensionName);
78✔
518
                        oDim.nSize = oIter->second;
78✔
519
                        oMetadata.aoDimensions.push_back(std::move(oDim));
78✔
520
                    }
521
                    if (bValid)
44✔
522
                    {
523
                        if (oMetadata.aoDimensions.size() >= 2 &&
64✔
524
                            aoLongitudeDimensions.size() == 2 &&
64✔
525
                            aoLongitudeDimensions == aoLatitudeDimensions)
20✔
526
                        {
527
                            int i = 0;
20✔
528
                            std::string osDataXDimName;
40✔
529
                            std::string osDataYDimName;
40✔
530
                            for (const auto &oDimSwath : oMetadata.aoDimensions)
74✔
531
                            {
532
                                auto oIter =
533
                                    oMapDataDimensionToGeoDimension.find(
534
                                        oDimSwath.osName);
54✔
535
                                if (oIter !=
54✔
536
                                    oMapDataDimensionToGeoDimension.end())
108✔
537
                                {
538
                                    const auto &osGeoDimName = oIter->second;
40✔
539
                                    if (osGeoDimName ==
40✔
540
                                        aoLongitudeDimensions[0].osName)
40✔
541
                                    {
542
                                        osDataYDimName = oDimSwath.osName;
20✔
543
                                        oMetadata.iYDim = i;
20✔
544
                                    }
545
                                    else if (osGeoDimName ==
20✔
546
                                             aoLongitudeDimensions[1].osName)
20✔
547
                                    {
548
                                        osDataXDimName = oDimSwath.osName;
20✔
549
                                        oMetadata.iXDim = i;
20✔
550
                                    }
551
                                }
552
                                else
553
                                {
554
                                    oMetadata.iOtherDim = i;
14✔
555
                                }
556
                                ++i;
54✔
557
                            }
558
                            if (oMetadata.iXDim >= 0 && oMetadata.iYDim >= 0)
20✔
559
                            {
560
                                oMetadata.osLongitudeSubdataset =
561
                                    "//HDFEOS/SWATHS/" + osSwathName +
40✔
562
                                    "/Geolocation_Fields/Longitude";
20✔
563
                                oMetadata.osLatitudeSubdataset =
564
                                    "//HDFEOS/SWATHS/" + osSwathName +
40✔
565
                                    "/Geolocation_Fields/Latitude";
20✔
566

567
                                for (const auto &oDimMap : aoDimensionMaps)
84✔
568
                                {
569
                                    if (oDimMap.osDataDimName == osDataYDimName)
64✔
570
                                    {
571
                                        oMetadata.nLineOffset = oDimMap.nOffset;
20✔
572
                                        oMetadata.nLineStep =
20✔
573
                                            oDimMap.nIncrement;
20✔
574
                                    }
575
                                    else if (oDimMap.osDataDimName ==
44✔
576
                                             osDataXDimName)
577
                                    {
578
                                        oMetadata.nPixelOffset =
20✔
579
                                            oDimMap.nOffset;
20✔
580
                                        oMetadata.nPixelStep =
20✔
581
                                            oDimMap.nIncrement;
20✔
582
                                    }
583
                                }
584
                            }
585
                        }
586

587
                        m_oMapSubdatasetNameToSwathDataFieldMetadata
588
                            ["//HDFEOS/SWATHS/" + osSwathName +
88✔
589
                             "/Data_Fields/" + osDataFieldName] =
132✔
590
                                std::move(oMetadata);
88✔
591
                    }
592
                }
593
            }
594
        }
595
    }
596
}
14✔
597

598
/************************************************************************/
599
/*                        GetSwathMetadata()                            */
600
/************************************************************************/
601

602
bool HDF5EOSParser::GetSwathMetadata(const std::string &osSwathName,
3✔
603
                                     SwathMetadata &swathMetadataOut) const
604
{
605
    const auto oIter = m_oMapSwathNameToSwathMetadata.find(osSwathName);
3✔
606
    if (oIter == m_oMapSwathNameToSwathMetadata.end())
3✔
607
        return false;
×
608
    swathMetadataOut = *(oIter->second.get());
3✔
609
    return true;
3✔
610
}
611

612
/************************************************************************/
613
/*                      GetSwathDataFieldMetadata()                     */
614
/************************************************************************/
615

616
bool HDF5EOSParser::GetSwathDataFieldMetadata(
21✔
617
    const char *pszSubdatasetName,
618
    SwathDataFieldMetadata &swathDataFieldMetadataOut) const
619
{
620
    const auto oIter =
621
        m_oMapSubdatasetNameToSwathDataFieldMetadata.find(pszSubdatasetName);
21✔
622
    if (oIter == m_oMapSubdatasetNameToSwathDataFieldMetadata.end())
21✔
623
        return false;
12✔
624
    swathDataFieldMetadataOut = oIter->second;
9✔
625
    return true;
9✔
626
}
627

628
/************************************************************************/
629
/*                    GetSwathGeolocationFieldMetadata()                */
630
/************************************************************************/
631

632
bool HDF5EOSParser::GetSwathGeolocationFieldMetadata(
2✔
633
    const char *pszSubdatasetName,
634
    SwathGeolocationFieldMetadata &swathGeolocationFieldMetadataOut) const
635
{
636
    const auto oIter = m_oMapSubdatasetNameToSwathGeolocationFieldMetadata.find(
637
        pszSubdatasetName);
2✔
638
    if (oIter == m_oMapSubdatasetNameToSwathGeolocationFieldMetadata.end())
2✔
639
        return false;
×
640
    swathGeolocationFieldMetadataOut = oIter->second;
2✔
641
    return true;
2✔
642
}
643

644
/************************************************************************/
645
/*                        GetGeoTransform()                             */
646
/************************************************************************/
647

648
bool HDF5EOSParser::GridMetadata::GetGeoTransform(GDALGeoTransform &gt) const
7✔
649
{
650
    if (nProjCode >= 0 && osGridOrigin == "HE5_HDFE_GD_UL" &&
14✔
651
        adfUpperLeftPointMeters.size() == 2 &&
21✔
652
        adfLowerRightPointMeters.size() == 2)
7✔
653
    {
654
        int nRasterXSize = 0;
7✔
655
        int nRasterYSize = 0;
7✔
656

657
        for (const auto &oDim : aoDimensions)
23✔
658
        {
659
            if (oDim.osName == "XDim")
16✔
660
                nRasterXSize = oDim.nSize;
7✔
661
            else if (oDim.osName == "YDim")
9✔
662
                nRasterYSize = oDim.nSize;
7✔
663
        }
664
        if (nRasterXSize <= 0 || nRasterYSize <= 0)
7✔
665
            return false;
×
666
        if (nProjCode == 0)  // GEO
7✔
667
        {
668
            gt[0] = CPLPackedDMSToDec(adfUpperLeftPointMeters[0]);
2✔
669
            gt[1] = (CPLPackedDMSToDec(adfLowerRightPointMeters[0]) -
2✔
670
                     CPLPackedDMSToDec(adfUpperLeftPointMeters[0])) /
2✔
671
                    nRasterXSize;
672
            gt[2] = 0;
2✔
673
            gt[3] = CPLPackedDMSToDec(adfUpperLeftPointMeters[1]);
2✔
674
            gt[4] = 0;
2✔
675
            gt[5] = (CPLPackedDMSToDec(adfLowerRightPointMeters[1]) -
4✔
676
                     CPLPackedDMSToDec(adfUpperLeftPointMeters[1])) /
2✔
677
                    nRasterYSize;
678
        }
679
        else
680
        {
681
            gt[0] = adfUpperLeftPointMeters[0];
5✔
682
            gt[1] = (adfLowerRightPointMeters[0] - adfUpperLeftPointMeters[0]) /
5✔
683
                    nRasterXSize;
684
            gt[2] = 0;
5✔
685
            gt[3] = adfUpperLeftPointMeters[1];
5✔
686
            gt[4] = 0;
5✔
687
            gt[5] = (adfLowerRightPointMeters[1] - adfUpperLeftPointMeters[1]) /
5✔
688
                    nRasterYSize;
689
        }
690
        return true;
7✔
691
    }
692
    return false;
×
693
}
694

695
/************************************************************************/
696
/*                              GetSRS()                                */
697
/************************************************************************/
698

699
std::unique_ptr<OGRSpatialReference> HDF5EOSParser::GridMetadata::GetSRS() const
7✔
700
{
701
    std::vector<double> l_adfProjParams = adfProjParams;
14✔
702
    l_adfProjParams.resize(15);
7✔
703
    auto poSRS = std::make_unique<OGRSpatialReference>();
14✔
704
    poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
7✔
705
    if (poSRS->importFromUSGS(nProjCode, nZone, l_adfProjParams.data(),
14✔
706
                              nSphereCode) == OGRERR_NONE)
14✔
707
    {
708
        return poSRS;
7✔
709
    }
710
    return nullptr;
×
711
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc