Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: OpenGIS Simple Features Reference Implementation
4 : * Purpose: Implement ERMapper projection conversions.
5 : * Author: Frank Warmerdam, warmerdam@pobox.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2007, Frank Warmerdam <warmerdam@pobox.com>
9 : * Copyright (c) 2008-2011, Even Rouault <even dot rouault at spatialys.com>
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "cpl_port.h"
31 : #include "ogr_srs_api.h"
32 :
33 : #include <cmath>
34 : #include <cstdio>
35 : #include <cstdlib>
36 : #include <cstring>
37 :
38 : #include "cpl_conv.h"
39 : #include "cpl_error.h"
40 : #include "ogr_core.h"
41 : #include "ogr_spatialref.h"
42 :
43 : /************************************************************************/
44 : /* OSRImportFromERM() */
45 : /************************************************************************/
46 :
47 : /**
48 : * \brief Create OGR WKT from ERMapper projection definitions.
49 : *
50 : * This function is the same as OGRSpatialReference::importFromERM().
51 : */
52 :
53 7 : OGRErr OSRImportFromERM(OGRSpatialReferenceH hSRS, const char *pszProj,
54 : const char *pszDatum, const char *pszUnits)
55 :
56 : {
57 7 : VALIDATE_POINTER1(hSRS, "OSRImportFromERM", OGRERR_FAILURE);
58 :
59 7 : return reinterpret_cast<OGRSpatialReference *>(hSRS)->importFromERM(
60 7 : pszProj, pszDatum, pszUnits);
61 : }
62 :
63 : /************************************************************************/
64 : /* importFromERM() */
65 : /************************************************************************/
66 :
67 : /**
68 : * Create OGR WKT from ERMapper projection definitions.
69 : *
70 : * Generates an OGRSpatialReference definition from an ERMapper datum
71 : * and projection name. Based on the ecw_cs.wkt dictionary file from
72 : * gdal/data.
73 : *
74 : * @param pszProj the projection name, such as "NUTM11" or "GEOGRAPHIC".
75 : * @param pszDatum the datum name, such as "NAD83".
76 : * @param pszUnits the linear units "FEET" or "METERS".
77 : *
78 : * @return OGRERR_NONE on success or OGRERR_UNSUPPORTED_SRS if not found.
79 : */
80 :
81 82 : OGRErr OGRSpatialReference::importFromERM(const char *pszProj,
82 : const char *pszDatum,
83 : const char *pszUnits)
84 :
85 : {
86 82 : Clear();
87 :
88 : /* -------------------------------------------------------------------- */
89 : /* do we have projection and datum? */
90 : /* -------------------------------------------------------------------- */
91 82 : if (EQUAL(pszProj, "RAW"))
92 45 : return OGRERR_NONE;
93 :
94 : /* -------------------------------------------------------------------- */
95 : /* Do we have an EPSG coordinate system? */
96 : /* -------------------------------------------------------------------- */
97 :
98 37 : if (STARTS_WITH_CI(pszProj, "EPSG:"))
99 3 : return importFromEPSG(atoi(pszProj + 5));
100 :
101 34 : if (STARTS_WITH_CI(pszDatum, "EPSG:"))
102 0 : return importFromEPSG(atoi(pszDatum + 5));
103 :
104 68 : CPLString osGEOGCS = lookupInDict("ecw_cs.wkt", pszDatum);
105 34 : if (osGEOGCS.empty())
106 2 : return OGRERR_UNSUPPORTED_SRS;
107 :
108 : /* -------------------------------------------------------------------- */
109 : /* Set projection if we have it. */
110 : /* -------------------------------------------------------------------- */
111 32 : if (!EQUAL(pszProj, "GEODETIC"))
112 : {
113 50 : CPLString osProjWKT = lookupInDict("ecw_cs.wkt", pszProj);
114 25 : if (osProjWKT.empty() || osProjWKT.back() != ']')
115 0 : return OGRERR_UNSUPPORTED_SRS;
116 :
117 25 : if (osProjWKT.find("LOCAL_CS[") == 0)
118 : {
119 0 : return importFromWkt(osProjWKT);
120 : }
121 :
122 : // Remove trailing ]
123 25 : osProjWKT.resize(osProjWKT.size() - 1);
124 :
125 : // Remove any UNIT
126 25 : auto nPos = osProjWKT.find(",UNIT");
127 25 : if (nPos != std::string::npos)
128 : {
129 18 : osProjWKT.resize(nPos);
130 : }
131 :
132 : // Insert GEOGCS
133 25 : nPos = osProjWKT.find(",PROJECTION");
134 25 : if (nPos == std::string::npos)
135 0 : return OGRERR_UNSUPPORTED_SRS;
136 :
137 : osProjWKT =
138 25 : osProjWKT.substr(0, nPos) + ',' + osGEOGCS + osProjWKT.substr(nPos);
139 :
140 25 : if (EQUAL(pszUnits, "FEET"))
141 5 : osProjWKT += ",UNIT[\"Foot_US\",0.3048006096012192]]";
142 : else
143 20 : osProjWKT += ",UNIT[\"Metre\",1.0]]";
144 :
145 25 : return importFromWkt(osProjWKT);
146 : }
147 : else
148 : {
149 7 : return importFromWkt(osGEOGCS);
150 : }
151 : }
152 :
153 : /************************************************************************/
154 : /* OSRExportToERM() */
155 : /************************************************************************/
156 : /**
157 : * \brief Convert coordinate system to ERMapper format.
158 : *
159 : * This function is the same as OGRSpatialReference::exportToERM().
160 : */
161 1 : OGRErr OSRExportToERM(OGRSpatialReferenceH hSRS, char *pszProj, char *pszDatum,
162 : char *pszUnits)
163 :
164 : {
165 1 : VALIDATE_POINTER1(hSRS, "OSRExportToERM", OGRERR_FAILURE);
166 :
167 1 : return reinterpret_cast<OGRSpatialReference *>(hSRS)->exportToERM(
168 1 : pszProj, pszDatum, pszUnits);
169 : }
170 :
171 : /************************************************************************/
172 : /* exportToERM() */
173 : /************************************************************************/
174 :
175 : /**
176 : * Convert coordinate system to ERMapper format.
177 : *
178 : * @param pszProj 32 character buffer to receive projection name.
179 : * @param pszDatum 32 character buffer to receive datum name.
180 : * @param pszUnits 32 character buffer to receive units name.
181 : *
182 : * @return OGRERR_NONE on success, OGRERR_SRS_UNSUPPORTED if not translation is
183 : * found, or OGRERR_FAILURE on other failures.
184 : */
185 :
186 52 : OGRErr OGRSpatialReference::exportToERM(char *pszProj, char *pszDatum,
187 : char *pszUnits)
188 :
189 : {
190 52 : const int BUFFER_SIZE = 32;
191 52 : strcpy(pszProj, "RAW");
192 52 : strcpy(pszDatum, "RAW");
193 52 : strcpy(pszUnits, "METERS");
194 :
195 52 : if (!IsProjected() && !IsGeographic())
196 0 : return OGRERR_UNSUPPORTED_SRS;
197 :
198 : /* -------------------------------------------------------------------- */
199 : /* Try to find the EPSG code. */
200 : /* -------------------------------------------------------------------- */
201 52 : int nEPSGCode = 0;
202 :
203 52 : if (IsProjected())
204 : {
205 6 : const char *pszAuthName = GetAuthorityName("PROJCS");
206 :
207 6 : if (pszAuthName != nullptr && EQUAL(pszAuthName, "epsg"))
208 : {
209 2 : nEPSGCode = atoi(GetAuthorityCode("PROJCS"));
210 : }
211 : }
212 46 : else if (IsGeographic())
213 : {
214 46 : const char *pszAuthName = GetAuthorityName("GEOGCS");
215 :
216 46 : if (pszAuthName != nullptr && EQUAL(pszAuthName, "epsg"))
217 : {
218 2 : nEPSGCode = atoi(GetAuthorityCode("GEOGCS"));
219 : }
220 : }
221 :
222 : /* -------------------------------------------------------------------- */
223 : /* Is our GEOGCS name already defined in ecw_cs.wkt? */
224 : /* -------------------------------------------------------------------- */
225 52 : const char *pszWKTDatum = GetAttrValue("DATUM");
226 :
227 104 : if (pszWKTDatum != nullptr &&
228 104 : !lookupInDict("ecw_cs.wkt", pszWKTDatum).empty())
229 : {
230 0 : strncpy(pszDatum, pszWKTDatum, BUFFER_SIZE);
231 0 : pszDatum[BUFFER_SIZE - 1] = '\0';
232 : }
233 :
234 : /* -------------------------------------------------------------------- */
235 : /* Is this a "well known" geographic coordinate system? */
236 : /* -------------------------------------------------------------------- */
237 52 : if (EQUAL(pszDatum, "RAW"))
238 : {
239 52 : int nEPSGGCSCode = GetEPSGGeogCS();
240 :
241 52 : if (nEPSGGCSCode == 4326)
242 4 : strcpy(pszDatum, "WGS84");
243 :
244 48 : else if (nEPSGGCSCode == 4322)
245 0 : strcpy(pszDatum, "WGS72DOD");
246 :
247 48 : else if (nEPSGGCSCode == 4267)
248 2 : strcpy(pszDatum, "NAD27");
249 :
250 46 : else if (nEPSGGCSCode == 4269)
251 0 : strcpy(pszDatum, "NAD83");
252 :
253 46 : else if (nEPSGGCSCode == 4277)
254 0 : strcpy(pszDatum, "OSGB36");
255 :
256 46 : else if (nEPSGGCSCode == 4278)
257 0 : strcpy(pszDatum, "OSGB78");
258 :
259 46 : else if (nEPSGGCSCode == 4201)
260 0 : strcpy(pszDatum, "ADINDAN");
261 :
262 46 : else if (nEPSGGCSCode == 4202)
263 0 : strcpy(pszDatum, "AGD66");
264 :
265 46 : else if (nEPSGGCSCode == 4203)
266 0 : strcpy(pszDatum, "AGD84");
267 :
268 46 : else if (nEPSGGCSCode == 4209)
269 0 : strcpy(pszDatum, "ARC1950");
270 :
271 46 : else if (nEPSGGCSCode == 4210)
272 0 : strcpy(pszDatum, "ARC1960");
273 :
274 46 : else if (nEPSGGCSCode == 4275)
275 0 : strcpy(pszDatum, "NTF");
276 :
277 46 : else if (nEPSGGCSCode == 4283)
278 0 : strcpy(pszDatum, "GDA94");
279 :
280 46 : else if (nEPSGGCSCode == 4284)
281 0 : strcpy(pszDatum, "PULKOVO");
282 :
283 46 : else if (nEPSGGCSCode == 7844)
284 1 : strcpy(pszDatum, "GDA2020");
285 : }
286 :
287 : /* -------------------------------------------------------------------- */
288 : /* Are we working with a geographic (geodetic) coordinate system? */
289 : /* -------------------------------------------------------------------- */
290 :
291 52 : if (IsGeographic())
292 : {
293 46 : if (EQUAL(pszDatum, "RAW"))
294 44 : return OGRERR_UNSUPPORTED_SRS;
295 : else
296 : {
297 2 : strcpy(pszProj, "GEODETIC");
298 2 : return OGRERR_NONE;
299 : }
300 : }
301 :
302 : /* -------------------------------------------------------------------- */
303 : /* Is this a UTM projection? */
304 : /* -------------------------------------------------------------------- */
305 6 : int bNorth = FALSE;
306 6 : int nZone = 0;
307 :
308 6 : nZone = GetUTMZone(&bNorth);
309 6 : if (nZone > 0)
310 : {
311 4 : if ((EQUAL(pszDatum, "GDA94") || EQUAL(pszDatum, "GDA2020")) &&
312 1 : !bNorth && nZone >= 48 && nZone <= 58)
313 : {
314 1 : snprintf(pszProj, BUFFER_SIZE, "MGA%02d", nZone);
315 : }
316 : else
317 : {
318 3 : if (bNorth)
319 3 : snprintf(pszProj, BUFFER_SIZE, "NUTM%02d", nZone);
320 : else
321 0 : snprintf(pszProj, BUFFER_SIZE, "SUTM%02d", nZone);
322 : }
323 : }
324 :
325 : /* -------------------------------------------------------------------- */
326 : /* Is our PROJCS name already defined in ecw_cs.wkt? */
327 : /* -------------------------------------------------------------------- */
328 : else
329 : {
330 2 : const char *pszPROJCS = GetAttrValue("PROJCS");
331 :
332 4 : if (pszPROJCS != nullptr &&
333 4 : lookupInDict("ecw_cs.wkt", pszPROJCS).find("PROJCS") == 0)
334 : {
335 1 : strncpy(pszProj, pszPROJCS, BUFFER_SIZE);
336 1 : pszProj[BUFFER_SIZE - 1] = '\0';
337 : }
338 : }
339 :
340 : /* -------------------------------------------------------------------- */
341 : /* If we have not translated it yet, but we have an EPSG code */
342 : /* then use EPSG:n notation. */
343 : /* -------------------------------------------------------------------- */
344 6 : if ((EQUAL(pszDatum, "RAW") || EQUAL(pszProj, "RAW")) && nEPSGCode != 0)
345 : {
346 0 : snprintf(pszProj, BUFFER_SIZE, "EPSG:%d", nEPSGCode);
347 0 : snprintf(pszDatum, BUFFER_SIZE, "EPSG:%d", nEPSGCode);
348 : }
349 :
350 : /* -------------------------------------------------------------------- */
351 : /* Handle the units. */
352 : /* -------------------------------------------------------------------- */
353 6 : const double dfUnits = GetLinearUnits();
354 :
355 6 : if (fabs(dfUnits - 0.3048) < 0.0001)
356 1 : strcpy(pszUnits, "FEET");
357 : else
358 5 : strcpy(pszUnits, "METERS");
359 :
360 6 : if (EQUAL(pszProj, "RAW"))
361 1 : return OGRERR_UNSUPPORTED_SRS;
362 :
363 5 : return OGRERR_NONE;
364 : }
|