Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: GDAL
4 : * Purpose: Generic support for GML Coverage descriptions.
5 : * Author: Frank Warmerdam, warmerdam@pobox.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2006, Frank Warmerdam <warmerdam@pobox.com>
9 : *
10 : * Permission is hereby granted, free of charge, to any person obtaining a
11 : * copy of this software and associated documentation files (the "Software"),
12 : * to deal in the Software without restriction, including without limitation
13 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 : * and/or sell copies of the Software, and to permit persons to whom the
15 : * Software is furnished to do so, subject to the following conditions:
16 : *
17 : * The above copyright notice and this permission notice shall be included
18 : * in all copies or substantial portions of the Software.
19 : *
20 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 : * DEALINGS IN THE SOFTWARE.
27 : ****************************************************************************/
28 :
29 : #include "cpl_port.h"
30 : #include "gdal_priv.h"
31 :
32 : #include <cstdlib>
33 : #include <cstring>
34 :
35 : #include "cpl_conv.h"
36 : #include "cpl_error.h"
37 : #include "cpl_minixml.h"
38 : #include "cpl_string.h"
39 : #include "ogr_api.h"
40 : #include "ogr_core.h"
41 : #include "ogr_geometry.h"
42 : #include "ogr_spatialref.h"
43 : #include "gmlcoverage.h"
44 :
45 : /************************************************************************/
46 : /* ParseGMLCoverageDesc() */
47 : /************************************************************************/
48 :
49 15 : CPLErr WCSParseGMLCoverage(CPLXMLNode *psXML, int *pnXSize, int *pnYSize,
50 : double *padfGeoTransform, char **ppszProjection)
51 :
52 : {
53 15 : CPLStripXMLNamespace(psXML, nullptr, TRUE);
54 :
55 : /* -------------------------------------------------------------------- */
56 : /* Isolate RectifiedGrid. Eventually we will need to support */
57 : /* other georeferencing objects. */
58 : /* -------------------------------------------------------------------- */
59 15 : CPLXMLNode *psRG = CPLSearchXMLNode(psXML, "=RectifiedGrid");
60 15 : CPLXMLNode *psOriginPoint = nullptr;
61 15 : const char *pszOffset1 = nullptr;
62 15 : const char *pszOffset2 = nullptr;
63 :
64 15 : if (psRG != nullptr)
65 : {
66 15 : psOriginPoint = CPLGetXMLNode(psRG, "origin.Point");
67 15 : if (psOriginPoint == nullptr)
68 15 : psOriginPoint = CPLGetXMLNode(psRG, "origin");
69 :
70 15 : CPLXMLNode *psOffset1 = CPLGetXMLNode(psRG, "offsetVector");
71 15 : if (psOffset1 != nullptr)
72 : {
73 15 : pszOffset1 = CPLGetXMLValue(psOffset1, "", nullptr);
74 : pszOffset2 =
75 15 : CPLGetXMLValue(psOffset1->psNext, "=offsetVector", nullptr);
76 : }
77 : }
78 :
79 : /* -------------------------------------------------------------------- */
80 : /* If we are missing any of the origin or 2 offsets then give up. */
81 : /* -------------------------------------------------------------------- */
82 15 : if (psRG == nullptr || psOriginPoint == nullptr || pszOffset1 == nullptr ||
83 : pszOffset2 == nullptr)
84 : {
85 0 : CPLError(CE_Failure, CPLE_AppDefined,
86 : "Unable to find GML RectifiedGrid, origin or offset vectors");
87 0 : return CE_Failure;
88 : }
89 :
90 : /* -------------------------------------------------------------------- */
91 : /* Search for the GridEnvelope and derive the raster size. */
92 : /* -------------------------------------------------------------------- */
93 : char **papszLow =
94 15 : CSLTokenizeString(CPLGetXMLValue(psRG, "limits.GridEnvelope.low", ""));
95 : char **papszHigh =
96 15 : CSLTokenizeString(CPLGetXMLValue(psRG, "limits.GridEnvelope.high", ""));
97 :
98 15 : if (CSLCount(papszLow) < 2 || CSLCount(papszHigh) < 2)
99 : {
100 0 : CPLError(CE_Failure, CPLE_AppDefined,
101 : "Unable to find or parse GridEnvelope.low/high.");
102 0 : CSLDestroy(papszLow);
103 0 : CSLDestroy(papszHigh);
104 0 : return CE_Failure;
105 : }
106 :
107 15 : if (pnXSize != nullptr)
108 15 : *pnXSize = atoi(papszHigh[0]) - atoi(papszLow[0]) + 1;
109 15 : if (pnYSize != nullptr)
110 15 : *pnYSize = atoi(papszHigh[1]) - atoi(papszLow[1]) + 1;
111 :
112 15 : CSLDestroy(papszLow);
113 15 : CSLDestroy(papszHigh);
114 :
115 : /* -------------------------------------------------------------------- */
116 : /* Extract origin location. */
117 : /* -------------------------------------------------------------------- */
118 15 : OGRPoint *poOriginGeometry = nullptr;
119 0 : std::unique_ptr<OGRGeometry> poGeom;
120 15 : const char *pszSRSName = nullptr;
121 :
122 : {
123 15 : bool bOldWrap = false;
124 :
125 : // Old coverages (i.e. WCS) just have <pos> under <origin>, so we
126 : // may need to temporarily force <origin> to <Point>.
127 15 : if (psOriginPoint->eType == CXT_Element &&
128 15 : EQUAL(psOriginPoint->pszValue, "origin"))
129 : {
130 15 : strcpy(psOriginPoint->pszValue, "Point");
131 15 : bOldWrap = true;
132 : }
133 15 : poGeom.reset(
134 : OGRGeometry::FromHandle(OGR_G_CreateFromGMLTree(psOriginPoint)));
135 :
136 30 : if (poGeom != nullptr &&
137 15 : wkbFlatten(poGeom->getGeometryType()) == wkbPoint)
138 : {
139 15 : poOriginGeometry = poGeom->toPoint();
140 : }
141 :
142 15 : if (bOldWrap)
143 15 : strcpy(psOriginPoint->pszValue, "origin");
144 :
145 : // SRS?
146 15 : pszSRSName = CPLGetXMLValue(psOriginPoint, "srsName", nullptr);
147 : }
148 :
149 : /* -------------------------------------------------------------------- */
150 : /* Extract offset(s) */
151 : /* -------------------------------------------------------------------- */
152 15 : bool bSuccess = false;
153 :
154 : char **papszOffset1Tokens =
155 15 : CSLTokenizeStringComplex(pszOffset1, " ,", FALSE, FALSE);
156 : char **papszOffset2Tokens =
157 15 : CSLTokenizeStringComplex(pszOffset2, " ,", FALSE, FALSE);
158 :
159 15 : if (CSLCount(papszOffset1Tokens) >= 2 &&
160 15 : CSLCount(papszOffset2Tokens) >= 2 && poOriginGeometry != nullptr)
161 : {
162 15 : padfGeoTransform[0] = poOriginGeometry->getX();
163 15 : padfGeoTransform[1] = CPLAtof(papszOffset1Tokens[0]);
164 15 : padfGeoTransform[2] = CPLAtof(papszOffset1Tokens[1]);
165 15 : padfGeoTransform[3] = poOriginGeometry->getY();
166 15 : padfGeoTransform[4] = CPLAtof(papszOffset2Tokens[0]);
167 15 : padfGeoTransform[5] = CPLAtof(papszOffset2Tokens[1]);
168 :
169 : // offset from center of pixel.
170 15 : padfGeoTransform[0] -= padfGeoTransform[1] * 0.5;
171 15 : padfGeoTransform[0] -= padfGeoTransform[2] * 0.5;
172 15 : padfGeoTransform[3] -= padfGeoTransform[4] * 0.5;
173 15 : padfGeoTransform[3] -= padfGeoTransform[5] * 0.5;
174 :
175 15 : bSuccess = true;
176 : }
177 :
178 15 : CSLDestroy(papszOffset1Tokens);
179 15 : CSLDestroy(papszOffset2Tokens);
180 :
181 : /* -------------------------------------------------------------------- */
182 : /* If we have gotten a geotransform, then try to interpret the */
183 : /* srsName. */
184 : /* -------------------------------------------------------------------- */
185 15 : if (bSuccess && pszSRSName != nullptr &&
186 0 : (*ppszProjection == nullptr || strlen(*ppszProjection) == 0))
187 : {
188 0 : if (STARTS_WITH_CI(pszSRSName, "epsg:"))
189 : {
190 0 : OGRSpatialReference oSRS;
191 0 : if (oSRS.SetFromUserInput(pszSRSName) == OGRERR_NONE)
192 0 : oSRS.exportToWkt(ppszProjection);
193 : }
194 0 : else if (STARTS_WITH_CI(pszSRSName, "urn:ogc:def:crs:"))
195 : {
196 0 : OGRSpatialReference oSRS;
197 0 : if (oSRS.importFromURN(pszSRSName) == OGRERR_NONE)
198 0 : oSRS.exportToWkt(ppszProjection);
199 : }
200 : else
201 0 : *ppszProjection = CPLStrdup(pszSRSName);
202 : }
203 :
204 15 : if (*ppszProjection)
205 0 : CPLDebug("GDALJP2Metadata", "Got projection from GML box: %s",
206 : *ppszProjection);
207 :
208 15 : return CE_None;
209 : }
|