LCOV - code coverage report
Current view: top level - frmts/hdf5 - iso19115_srs.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 30 42 71.4 %
Date: 2026-05-07 11:45:54 Functions: 1 1 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  BAG Driver
       4             :  * Purpose:  Implements code to parse ISO 19115 metadata to extract a
       5             :  *           spatial reference system.  Eventually intended to be made
       6             :  *           a method on OGRSpatialReference.
       7             :  * Author:   Frank Warmerdam <warmerdam@pobox.com>
       8             :  *
       9             :  ******************************************************************************
      10             :  * Copyright (c) 2009, Frank Warmerdam <warmerdam@pobox.com>
      11             :  * Copyright (c) 2009-2012, Even Rouault <even dot rouault at spatialys.com>
      12             :  *
      13             :  * SPDX-License-Identifier: MIT
      14             :  ****************************************************************************/
      15             : 
      16             : #ifdef _POSIX_C_SOURCE
      17             : #undef _POSIX_C_SOURCE
      18             : #endif
      19             : 
      20             : #include "cpl_port.h"
      21             : 
      22             : #include <cstdlib>
      23             : #include <cstring>
      24             : 
      25             : #include "cpl_error.h"
      26             : #include "cpl_minixml.h"
      27             : #include "iso19115_srs.h"
      28             : #include "ogr_core.h"
      29             : #include "ogr_spatialref.h"
      30             : 
      31             : /************************************************************************/
      32             : /*                     OGR_SRS_ImportFromISO19115()                     */
      33             : /************************************************************************/
      34             : 
      35          80 : OGRErr OGR_SRS_ImportFromISO19115(OGRSpatialReference *poThis,
      36             :                                   const char *pszISOXML)
      37             : 
      38             : {
      39             :     // Parse the XML into tree form.
      40          80 :     CPLXMLNode *psRoot = CPLParseXMLString(pszISOXML);
      41             : 
      42          80 :     if (psRoot == nullptr)
      43           0 :         return OGRERR_FAILURE;
      44             : 
      45          80 :     CPLStripXMLNamespace(psRoot, nullptr, TRUE);
      46             : 
      47             :     // For now we look for projection codes recognised in the BAG
      48             :     // format (see ons_fsd.pdf: Metadata Dataset Character String
      49             :     // Constants).
      50          80 :     CPLXMLNode *psRSI = CPLSearchXMLNode(psRoot, "=referenceSystemInfo");
      51          80 :     if (psRSI == nullptr)
      52             :     {
      53           0 :         CPLError(CE_Failure, CPLE_AppDefined,
      54             :                  "Unable to find <referenceSystemInfo> in metadata.");
      55           0 :         CPLDestroyXMLNode(psRoot);
      56           0 :         return OGRERR_FAILURE;
      57             :     }
      58             : 
      59          80 :     poThis->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
      60          80 :     poThis->Clear();
      61             : 
      62             :     // First, set the datum.
      63             :     const char *pszDatum =
      64          80 :         CPLGetXMLValue(psRSI, "MD_CRS.datum.RS_Identifier.code", "");
      65             : 
      66          84 :     if (strlen(pszDatum) > 0 &&
      67           4 :         poThis->SetWellKnownGeogCS(pszDatum) != OGRERR_NONE)
      68             :     {
      69           2 :         CPLDestroyXMLNode(psRoot);
      70           2 :         return OGRERR_FAILURE;
      71             :     }
      72             : 
      73             :     // Then try to extract the projection.
      74             :     const char *pszProjection =
      75          78 :         CPLGetXMLValue(psRSI, "MD_CRS.projection.RS_Identifier.code", "");
      76             : 
      77          78 :     if (EQUAL(pszProjection, "UTM"))
      78             :     {
      79           2 :         int nZone = atoi(CPLGetXMLValue(
      80             :             psRSI, "MD_CRS.projectionParameters.MD_ProjectionParameters.zone",
      81             :             "0"));
      82             : 
      83             :         // We have encountered files (#5152) that identify the southern
      84             :         // hemisphere with a false northing of 10000000 value.  The existing
      85             :         // code checked for negative zones, but it isn't clear if any actual
      86             :         // files use that.
      87           2 :         int bNorth = nZone > 0;
      88           2 :         if (bNorth)
      89             :         {
      90             :             const char *pszFalseNorthing =
      91           2 :                 CPLGetXMLValue(psRSI,
      92             :                                "MD_CRS.projectionParameters.MD_"
      93             :                                "ProjectionParameters.falseNorthing",
      94             :                                "");
      95           2 :             if (strlen(pszFalseNorthing) > 0)
      96             :             {
      97           2 :                 if (CPLAtof(pszFalseNorthing) == 0.0)
      98             :                 {
      99           0 :                     bNorth = TRUE;
     100             :                 }
     101           2 :                 else if (CPLAtof(pszFalseNorthing) == 10000000.0)
     102             :                 {
     103           2 :                     bNorth = FALSE;
     104             :                 }
     105             :                 else
     106             :                 {
     107           0 :                     CPLError(CE_Failure, CPLE_AppDefined,
     108             :                              "falseNorthing value not recognized: %s",
     109             :                              pszFalseNorthing);
     110             :                 }
     111             :             }
     112             :         }
     113           2 :         poThis->SetUTM(std::abs(nZone), bNorth);
     114             :     }
     115          76 :     else if (EQUAL(pszProjection, "Geodetic"))
     116             :     {
     117             :         const char *pszEllipsoid =
     118           0 :             CPLGetXMLValue(psRSI, "MD_CRS.ellipsoid.RS_Identifier.code", "");
     119             : 
     120           0 :         if (!EQUAL(pszDatum, "WGS84") || !EQUAL(pszEllipsoid, "WGS84"))
     121             :         {
     122           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     123             :                      "ISO 19115 parser does not support custom GCS.");
     124           0 :             CPLDestroyXMLNode(psRoot);
     125           0 :             return OGRERR_FAILURE;
     126             :         }
     127             :     }
     128             :     else
     129             :     {
     130          76 :         if (!EQUAL(pszProjection, ""))
     131             :         {
     132           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     133             :                      "projection = %s not recognised by ISO 19115 parser.",
     134             :                      pszProjection);
     135             :         }
     136          76 :         CPLDestroyXMLNode(psRoot);
     137          76 :         return OGRERR_FAILURE;
     138             :     }
     139             : 
     140           2 :     CPLDestroyXMLNode(psRoot);
     141             : 
     142           2 :     return OGRERR_NONE;
     143             : }

Generated by: LCOV version 1.14