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