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 : * Permission is hereby granted, free of charge, to any person obtaining a
14 : * copy of this software and associated documentation files (the "Software"),
15 : * to deal in the Software without restriction, including without limitation
16 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 : * and/or sell copies of the Software, and to permit persons to whom the
18 : * Software is furnished to do so, subject to the following conditions:
19 : *
20 : * The above copyright notice and this permission notice shall be included
21 : * in all copies or substantial portions of the Software.
22 : *
23 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 : * DEALINGS IN THE SOFTWARE.
30 : ****************************************************************************/
31 :
32 : #include "cpl_port.h"
33 :
34 : #include <cstdlib>
35 : #include <cstring>
36 :
37 : #include "cpl_error.h"
38 : #include "cpl_minixml.h"
39 : #include "iso19115_srs.h"
40 : #include "ogr_core.h"
41 : #include "ogr_spatialref.h"
42 :
43 : /************************************************************************/
44 : /* OGR_SRS_ImportFromISO19115() */
45 : /************************************************************************/
46 :
47 80 : OGRErr OGR_SRS_ImportFromISO19115(OGRSpatialReference *poThis,
48 : const char *pszISOXML)
49 :
50 : {
51 : // Parse the XML into tree form.
52 80 : CPLXMLNode *psRoot = CPLParseXMLString(pszISOXML);
53 :
54 80 : if (psRoot == nullptr)
55 0 : return OGRERR_FAILURE;
56 :
57 80 : CPLStripXMLNamespace(psRoot, nullptr, TRUE);
58 :
59 : // For now we look for projection codes recognised in the BAG
60 : // format (see ons_fsd.pdf: Metadata Dataset Character String
61 : // Constants).
62 80 : CPLXMLNode *psRSI = CPLSearchXMLNode(psRoot, "=referenceSystemInfo");
63 80 : if (psRSI == nullptr)
64 : {
65 0 : CPLError(CE_Failure, CPLE_AppDefined,
66 : "Unable to find <referenceSystemInfo> in metadata.");
67 0 : CPLDestroyXMLNode(psRoot);
68 0 : return OGRERR_FAILURE;
69 : }
70 :
71 80 : poThis->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
72 80 : poThis->Clear();
73 :
74 : // First, set the datum.
75 : const char *pszDatum =
76 80 : CPLGetXMLValue(psRSI, "MD_CRS.datum.RS_Identifier.code", "");
77 :
78 84 : if (strlen(pszDatum) > 0 &&
79 4 : poThis->SetWellKnownGeogCS(pszDatum) != OGRERR_NONE)
80 : {
81 2 : CPLDestroyXMLNode(psRoot);
82 2 : return OGRERR_FAILURE;
83 : }
84 :
85 : // Then try to extract the projection.
86 : const char *pszProjection =
87 78 : CPLGetXMLValue(psRSI, "MD_CRS.projection.RS_Identifier.code", "");
88 :
89 78 : if (EQUAL(pszProjection, "UTM"))
90 : {
91 2 : int nZone = atoi(CPLGetXMLValue(
92 : psRSI, "MD_CRS.projectionParameters.MD_ProjectionParameters.zone",
93 : "0"));
94 :
95 : // We have encountered files (#5152) that identify the southern
96 : // hemisphere with a false northing of 10000000 value. The existing
97 : // code checked for negative zones, but it isn't clear if any actual
98 : // files use that.
99 2 : int bNorth = nZone > 0;
100 2 : if (bNorth)
101 : {
102 : const char *pszFalseNorthing =
103 2 : CPLGetXMLValue(psRSI,
104 : "MD_CRS.projectionParameters.MD_"
105 : "ProjectionParameters.falseNorthing",
106 : "");
107 2 : if (strlen(pszFalseNorthing) > 0)
108 : {
109 2 : if (CPLAtof(pszFalseNorthing) == 0.0)
110 : {
111 0 : bNorth = TRUE;
112 : }
113 2 : else if (CPLAtof(pszFalseNorthing) == 10000000.0)
114 : {
115 2 : bNorth = FALSE;
116 : }
117 : else
118 : {
119 0 : CPLError(CE_Failure, CPLE_AppDefined,
120 : "falseNorthing value not recognized: %s",
121 : pszFalseNorthing);
122 : }
123 : }
124 : }
125 2 : poThis->SetUTM(std::abs(nZone), bNorth);
126 : }
127 76 : else if (EQUAL(pszProjection, "Geodetic"))
128 : {
129 : const char *pszEllipsoid =
130 0 : CPLGetXMLValue(psRSI, "MD_CRS.ellipsoid.RS_Identifier.code", "");
131 :
132 0 : if (!EQUAL(pszDatum, "WGS84") || !EQUAL(pszEllipsoid, "WGS84"))
133 : {
134 0 : CPLError(CE_Failure, CPLE_AppDefined,
135 : "ISO 19115 parser does not support custom GCS.");
136 0 : CPLDestroyXMLNode(psRoot);
137 0 : return OGRERR_FAILURE;
138 : }
139 : }
140 : else
141 : {
142 76 : if (!EQUAL(pszProjection, ""))
143 : {
144 0 : CPLError(CE_Failure, CPLE_AppDefined,
145 : "projection = %s not recognised by ISO 19115 parser.",
146 : pszProjection);
147 : }
148 76 : CPLDestroyXMLNode(psRoot);
149 76 : return OGRERR_FAILURE;
150 : }
151 :
152 2 : CPLDestroyXMLNode(psRoot);
153 :
154 2 : return OGRERR_NONE;
155 : }
|