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 : }