1 : /******************************************************************************
2 : * $Id: ogr_srs_esri.cpp 23544 2011-12-12 00:34:54Z etourigny $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: OGRSpatialReference translation to/from ESRI .prj definitions.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2000, Frank Warmerdam
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 "ogr_spatialref.h"
31 : #include "ogr_p.h"
32 : #include "cpl_csv.h"
33 :
34 : #include "ogr_srs_esri_names.h"
35 :
36 : CPL_CVSID("$Id: ogr_srs_esri.cpp 23544 2011-12-12 00:34:54Z etourigny $");
37 :
38 : void SetNewName( OGRSpatialReference* pOgr, const char* keyName, const char* newName );
39 : int RemapImgWGSProjcsName(OGRSpatialReference* pOgr, const char* pszProjCSName,
40 : const char* pszProgCSName);
41 : int RemapImgUTMNames(OGRSpatialReference* pOgr, const char* pszProjCSName,
42 : const char* pszProgCSName, char **mappingTable);
43 : int RemapNameBasedOnKeyName(OGRSpatialReference* pOgr, const char* pszName,
44 : const char* pszkeyName, char **mappingTable);
45 : int RemapNamesBasedOnTwo(OGRSpatialReference* pOgr, const char* name1, const char* name2,
46 : char **mappingTable, long nTableStepSize,
47 : char** pszkeyNames, long nKeys);
48 : int RemapPValuesBasedOnProjCSAndPName(OGRSpatialReference* pOgr,
49 : const char* pszProgCSName, char **mappingTable);
50 : int RemapPNamesBasedOnProjCSAndPName(OGRSpatialReference* pOgr,
51 : const char* pszProgCSName, char **mappingTable);
52 : int DeleteParamBasedOnPrjName( OGRSpatialReference* pOgr,
53 : const char* pszProjectionName, char **mappingTable);
54 : int AddParamBasedOnPrjName( OGRSpatialReference* pOgr,
55 : const char* pszProjectionName, char **mappingTable);
56 : int RemapGeogCSName(OGRSpatialReference* pOgr, const char *pszGeogCSName);
57 :
58 : static int FindCodeFromDict( const char* pszDictFile, const char* CSName, char* code );
59 :
60 : static const char *apszProjMapping[] = {
61 : "Albers", SRS_PT_ALBERS_CONIC_EQUAL_AREA,
62 : "Cassini", SRS_PT_CASSINI_SOLDNER,
63 : "Equidistant_Cylindrical", SRS_PT_EQUIRECTANGULAR,
64 : "Plate_Carree", SRS_PT_EQUIRECTANGULAR,
65 : "Hotine_Oblique_Mercator_Azimuth_Natural_Origin",
66 : SRS_PT_HOTINE_OBLIQUE_MERCATOR,
67 : "Hotine_Oblique_Mercator_Azimuth_Center",
68 : SRS_PT_HOTINE_OBLIQUE_MERCATOR,
69 : "Lambert_Conformal_Conic", SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP,
70 : "Lambert_Conformal_Conic", SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP,
71 : "Van_der_Grinten_I", SRS_PT_VANDERGRINTEN,
72 : SRS_PT_TRANSVERSE_MERCATOR, SRS_PT_TRANSVERSE_MERCATOR,
73 : "Gauss_Kruger", SRS_PT_TRANSVERSE_MERCATOR,
74 : "Mercator", SRS_PT_MERCATOR_1SP,
75 : NULL, NULL };
76 :
77 : static const char *apszAlbersMapping[] = {
78 : SRS_PP_CENTRAL_MERIDIAN, SRS_PP_LONGITUDE_OF_CENTER,
79 : SRS_PP_LATITUDE_OF_ORIGIN, SRS_PP_LATITUDE_OF_CENTER,
80 : "Central_Parallel", SRS_PP_LATITUDE_OF_CENTER,
81 : NULL, NULL };
82 :
83 : static const char *apszECMapping[] = {
84 : SRS_PP_CENTRAL_MERIDIAN, SRS_PP_LONGITUDE_OF_CENTER,
85 : SRS_PP_LATITUDE_OF_ORIGIN, SRS_PP_LATITUDE_OF_CENTER,
86 : NULL, NULL };
87 :
88 : static const char *apszMercatorMapping[] = {
89 : SRS_PP_STANDARD_PARALLEL_1, SRS_PP_LATITUDE_OF_ORIGIN,
90 : NULL, NULL };
91 :
92 : static const char *apszPolarStereographicMapping[] = {
93 : SRS_PP_STANDARD_PARALLEL_1, SRS_PP_LATITUDE_OF_ORIGIN,
94 : NULL, NULL };
95 :
96 : static const char *apszOrthographicMapping[] = {
97 : "Longitude_Of_Center", SRS_PP_CENTRAL_MERIDIAN,
98 : "Latitude_Of_Center", SRS_PP_LATITUDE_OF_ORIGIN,
99 : NULL, NULL };
100 :
101 : static char **papszDatumMapping = NULL;
102 :
103 : static const char *apszDefaultDatumMapping[] = {
104 : "6267", "North_American_1927", SRS_DN_NAD27,
105 : "6269", "North_American_1983", SRS_DN_NAD83,
106 : NULL, NULL, NULL };
107 :
108 : static const char *apszSpheroidMapping[] = {
109 : "WGS_84", "WGS_1984",
110 : "WGS_72", "WGS_1972",
111 : "GRS_1967_Modified", "GRS_1967_Truncated",
112 : "Krassowsky_1940", "Krasovsky_1940",
113 : NULL, NULL };
114 :
115 : static const char *apszUnitMapping[] = {
116 : "Meter", "meter",
117 : "Meter", "metre",
118 : "Foot", "foot",
119 : "Foot", "feet",
120 : "Foot", "international_feet",
121 : "Foot_US", SRS_UL_US_FOOT,
122 : "Foot_Clarke", "clarke_feet",
123 : "Degree", "degree",
124 : "Degree", "degrees",
125 : "Degree", SRS_UA_DEGREE,
126 : "Radian", SRS_UA_RADIAN,
127 : NULL, NULL };
128 :
129 : /* -------------------------------------------------------------------- */
130 : /* Table relating USGS and ESRI state plane zones. */
131 : /* -------------------------------------------------------------------- */
132 : static const int anUsgsEsriZones[] =
133 : {
134 : 101, 3101,
135 : 102, 3126,
136 : 201, 3151,
137 : 202, 3176,
138 : 203, 3201,
139 : 301, 3226,
140 : 302, 3251,
141 : 401, 3276,
142 : 402, 3301,
143 : 403, 3326,
144 : 404, 3351,
145 : 405, 3376,
146 : 406, 3401,
147 : 407, 3426,
148 : 501, 3451,
149 : 502, 3476,
150 : 503, 3501,
151 : 600, 3526,
152 : 700, 3551,
153 : 901, 3601,
154 : 902, 3626,
155 : 903, 3576,
156 : 1001, 3651,
157 : 1002, 3676,
158 : 1101, 3701,
159 : 1102, 3726,
160 : 1103, 3751,
161 : 1201, 3776,
162 : 1202, 3801,
163 : 1301, 3826,
164 : 1302, 3851,
165 : 1401, 3876,
166 : 1402, 3901,
167 : 1501, 3926,
168 : 1502, 3951,
169 : 1601, 3976,
170 : 1602, 4001,
171 : 1701, 4026,
172 : 1702, 4051,
173 : 1703, 6426,
174 : 1801, 4076,
175 : 1802, 4101,
176 : 1900, 4126,
177 : 2001, 4151,
178 : 2002, 4176,
179 : 2101, 4201,
180 : 2102, 4226,
181 : 2103, 4251,
182 : 2111, 6351,
183 : 2112, 6376,
184 : 2113, 6401,
185 : 2201, 4276,
186 : 2202, 4301,
187 : 2203, 4326,
188 : 2301, 4351,
189 : 2302, 4376,
190 : 2401, 4401,
191 : 2402, 4426,
192 : 2403, 4451,
193 : 2500, 0,
194 : 2501, 4476,
195 : 2502, 4501,
196 : 2503, 4526,
197 : 2600, 0,
198 : 2601, 4551,
199 : 2602, 4576,
200 : 2701, 4601,
201 : 2702, 4626,
202 : 2703, 4651,
203 : 2800, 4676,
204 : 2900, 4701,
205 : 3001, 4726,
206 : 3002, 4751,
207 : 3003, 4776,
208 : 3101, 4801,
209 : 3102, 4826,
210 : 3103, 4851,
211 : 3104, 4876,
212 : 3200, 4901,
213 : 3301, 4926,
214 : 3302, 4951,
215 : 3401, 4976,
216 : 3402, 5001,
217 : 3501, 5026,
218 : 3502, 5051,
219 : 3601, 5076,
220 : 3602, 5101,
221 : 3701, 5126,
222 : 3702, 5151,
223 : 3800, 5176,
224 : 3900, 0,
225 : 3901, 5201,
226 : 3902, 5226,
227 : 4001, 5251,
228 : 4002, 5276,
229 : 4100, 5301,
230 : 4201, 5326,
231 : 4202, 5351,
232 : 4203, 5376,
233 : 4204, 5401,
234 : 4205, 5426,
235 : 4301, 5451,
236 : 4302, 5476,
237 : 4303, 5501,
238 : 4400, 5526,
239 : 4501, 5551,
240 : 4502, 5576,
241 : 4601, 5601,
242 : 4602, 5626,
243 : 4701, 5651,
244 : 4702, 5676,
245 : 4801, 5701,
246 : 4802, 5726,
247 : 4803, 5751,
248 : 4901, 5776,
249 : 4902, 5801,
250 : 4903, 5826,
251 : 4904, 5851,
252 : 5001, 6101,
253 : 5002, 6126,
254 : 5003, 6151,
255 : 5004, 6176,
256 : 5005, 6201,
257 : 5006, 6226,
258 : 5007, 6251,
259 : 5008, 6276,
260 : 5009, 6301,
261 : 5010, 6326,
262 : 5101, 5876,
263 : 5102, 5901,
264 : 5103, 5926,
265 : 5104, 5951,
266 : 5105, 5976,
267 : 5201, 6001,
268 : 5200, 6026,
269 : 5200, 6076,
270 : 5201, 6051,
271 : 5202, 6051,
272 : 5300, 0,
273 : 5400, 0
274 : };
275 :
276 : /* -------------------------------------------------------------------- */
277 : /* Datum Mapping functions and definitions */
278 : /* -------------------------------------------------------------------- */
279 : /* TODO adapt existing code and test */
280 : #define DM_IDX_EPSG_CODE 0
281 : #define DM_IDX_ESRI_NAME 1
282 : #define DM_IDX_EPSG_NAME 2
283 : #define DM_ELT_SIZE 3
284 :
285 : #define DM_GET_EPSG_CODE(map, i) map[(i)*DM_ELT_SIZE + DM_IDX_EPSG_CODE]
286 : #define DM_GET_ESRI_NAME(map, i) map[(i)*DM_ELT_SIZE + DM_IDX_ESRI_NAME]
287 : #define DM_GET_EPSG_NAME(map, i) map[(i)*DM_ELT_SIZE + DM_IDX_EPSG_NAME]
288 :
289 4219 : char *DMGetEPSGCode(int i) { return DM_GET_EPSG_CODE(papszDatumMapping, i); }
290 4139215 : char *DMGetESRIName(int i) { return DM_GET_ESRI_NAME(papszDatumMapping, i); }
291 0 : char *DMGetEPSGName(int i) { return DM_GET_EPSG_NAME(papszDatumMapping, i); }
292 :
293 :
294 : void OGREPSGDatumNameMassage( char ** ppszDatum );
295 :
296 : /************************************************************************/
297 : /* ESRIToUSGSZone() */
298 : /* */
299 : /* Convert ESRI style state plane zones to USGS style state */
300 : /* plane zones. */
301 : /************************************************************************/
302 :
303 0 : static int ESRIToUSGSZone( int nESRIZone )
304 :
305 : {
306 0 : int nPairs = sizeof(anUsgsEsriZones) / (2*sizeof(int));
307 : int i;
308 :
309 0 : for( i = 0; i < nPairs; i++ )
310 : {
311 0 : if( anUsgsEsriZones[i*2+1] == nESRIZone )
312 0 : return anUsgsEsriZones[i*2];
313 : }
314 :
315 0 : return 0;
316 : }
317 :
318 : /************************************************************************/
319 : /* MorphNameToESRI() */
320 : /* */
321 : /* Make name ESRI compatible. Convert spaces and special */
322 : /* characters to underscores and then strip down. */
323 : /************************************************************************/
324 :
325 29891 : static void MorphNameToESRI( char ** ppszName )
326 :
327 : {
328 : int i, j;
329 29891 : char *pszName = *ppszName;
330 :
331 29891 : if (pszName[0] == '\0')
332 0 : return;
333 :
334 : /* -------------------------------------------------------------------- */
335 : /* Translate non-alphanumeric values to underscores. */
336 : /* -------------------------------------------------------------------- */
337 606220 : for( i = 0; pszName[i] != '\0'; i++ )
338 : {
339 2568601 : if( pszName[i] != '+'
340 962493 : && !(pszName[i] >= 'A' && pszName[i] <= 'Z')
341 652321 : && !(pszName[i] >= 'a' && pszName[i] <= 'z')
342 377458 : && !(pszName[i] >= '0' && pszName[i] <= '9') )
343 : {
344 97170 : pszName[i] = '_';
345 : }
346 : }
347 :
348 : /* -------------------------------------------------------------------- */
349 : /* Remove repeated and trailing underscores. */
350 : /* -------------------------------------------------------------------- */
351 576329 : for( i = 1, j = 0; pszName[i] != '\0'; i++ )
352 : {
353 546438 : if( pszName[j] == '_' && pszName[i] == '_' )
354 18940 : continue;
355 :
356 527498 : pszName[++j] = pszName[i];
357 : }
358 29891 : if( pszName[j] == '_' )
359 2314 : pszName[j] = '\0';
360 : else
361 27577 : pszName[j+1] = '\0';
362 : }
363 :
364 : /************************************************************************/
365 : /* CleanESRIDatumMappingTable() */
366 : /************************************************************************/
367 :
368 : CPL_C_START
369 965 : void CleanupESRIDatumMappingTable()
370 :
371 : {
372 965 : if( papszDatumMapping == NULL )
373 886 : return;
374 :
375 79 : if( papszDatumMapping != (char **) apszDefaultDatumMapping )
376 : {
377 79 : CSLDestroy( papszDatumMapping );
378 79 : papszDatumMapping = NULL;
379 : }
380 : }
381 : CPL_C_END
382 :
383 : /************************************************************************/
384 : /* InitDatumMappingTable() */
385 : /************************************************************************/
386 :
387 44031 : static void InitDatumMappingTable()
388 :
389 : {
390 44031 : if( papszDatumMapping != NULL )
391 43952 : return;
392 :
393 : /* -------------------------------------------------------------------- */
394 : /* Try to open the datum.csv file. */
395 : /* -------------------------------------------------------------------- */
396 79 : const char *pszFilename = CSVFilename("gdal_datum.csv");
397 79 : FILE * fp = VSIFOpen( pszFilename, "rb" );
398 :
399 : /* -------------------------------------------------------------------- */
400 : /* Use simple default set if we can't find the file. */
401 : /* -------------------------------------------------------------------- */
402 79 : if( fp == NULL )
403 : {
404 0 : papszDatumMapping = (char **)apszDefaultDatumMapping;
405 0 : return;
406 : }
407 :
408 : /* -------------------------------------------------------------------- */
409 : /* Figure out what fields we are interested in. */
410 : /* -------------------------------------------------------------------- */
411 79 : char **papszFieldNames = CSVReadParseLine( fp );
412 79 : int nDatumCodeField = CSLFindString( papszFieldNames, "DATUM_CODE" );
413 79 : int nEPSGNameField = CSLFindString( papszFieldNames, "DATUM_NAME" );
414 79 : int nESRINameField = CSLFindString( papszFieldNames, "ESRI_DATUM_NAME" );
415 :
416 79 : CSLDestroy( papszFieldNames );
417 :
418 79 : if( nDatumCodeField == -1 || nEPSGNameField == -1 || nESRINameField == -1 )
419 : {
420 : CPLError( CE_Failure, CPLE_AppDefined,
421 0 : "Failed to find required field in gdal_datum.csv in InitDatumMappingTable(), using default table setup." );
422 :
423 0 : papszDatumMapping = (char **)apszDefaultDatumMapping;
424 0 : VSIFClose( fp );
425 0 : return;
426 : }
427 :
428 : /* -------------------------------------------------------------------- */
429 : /* Read each line, adding a detail line for each. */
430 : /* -------------------------------------------------------------------- */
431 79 : int nMappingCount = 0;
432 79 : const int nMaxDatumMappings = 1000;
433 : char **papszFields;
434 79 : papszDatumMapping = (char **)CPLCalloc(sizeof(char*),nMaxDatumMappings*3);
435 :
436 48427 : for( papszFields = CSVReadParseLine( fp );
437 : papszFields != NULL;
438 : papszFields = CSVReadParseLine( fp ) )
439 : {
440 48348 : int nFieldCount = CSLCount(papszFields);
441 :
442 48348 : CPLAssert( nMappingCount+1 < nMaxDatumMappings );
443 :
444 48348 : if( MAX(nEPSGNameField,MAX(nDatumCodeField,nESRINameField))
445 : < nFieldCount
446 : && nMaxDatumMappings > nMappingCount+1 )
447 : {
448 48348 : papszDatumMapping[nMappingCount*3+0] =
449 48348 : CPLStrdup( papszFields[nDatumCodeField] );
450 48348 : papszDatumMapping[nMappingCount*3+1] =
451 48348 : CPLStrdup( papszFields[nESRINameField] );
452 48348 : papszDatumMapping[nMappingCount*3+2] =
453 48348 : CPLStrdup( papszFields[nEPSGNameField] );
454 48348 : OGREPSGDatumNameMassage( &(papszDatumMapping[nMappingCount*3+2]) );
455 :
456 48348 : nMappingCount++;
457 : }
458 48348 : CSLDestroy( papszFields );
459 : }
460 :
461 79 : VSIFClose( fp );
462 :
463 79 : papszDatumMapping[nMappingCount*3+0] = NULL;
464 79 : papszDatumMapping[nMappingCount*3+1] = NULL;
465 79 : papszDatumMapping[nMappingCount*3+2] = NULL;
466 : }
467 :
468 :
469 : /************************************************************************/
470 : /* OSRImportFromESRI() */
471 : /************************************************************************/
472 :
473 : /**
474 : * \brief Import coordinate system from ESRI .prj format(s).
475 : *
476 : * This function is the same as the C++ method OGRSpatialReference::importFromESRI()
477 : */
478 5 : OGRErr OSRImportFromESRI( OGRSpatialReferenceH hSRS, char **papszPrj )
479 :
480 : {
481 5 : VALIDATE_POINTER1( hSRS, "OSRImportFromESRI", CE_Failure );
482 :
483 5 : return ((OGRSpatialReference *) hSRS)->importFromESRI( papszPrj );
484 : }
485 :
486 : /************************************************************************/
487 : /* OSR_GDV() */
488 : /* */
489 : /* Fetch a particular parameter out of the parameter list, or */
490 : /* the indicated default if it isn't available. This is a */
491 : /* helper function for importFromESRI(). */
492 : /************************************************************************/
493 :
494 67 : static double OSR_GDV( char **papszNV, const char * pszField,
495 : double dfDefaultValue )
496 :
497 : {
498 : int iLine;
499 :
500 67 : if( papszNV == NULL || papszNV[0] == NULL )
501 0 : return dfDefaultValue;
502 :
503 67 : if( EQUALN(pszField,"PARAM_",6) )
504 : {
505 : int nOffset;
506 :
507 493 : for( iLine = 0;
508 464 : papszNV[iLine] != NULL && !EQUALN(papszNV[iLine],"Paramet",7);
509 : iLine++ ) {}
510 :
511 256 : for( nOffset=atoi(pszField+6);
512 128 : papszNV[iLine] != NULL && nOffset > 0;
513 : iLine++ )
514 : {
515 99 : if( strlen(papszNV[iLine]) > 0 )
516 99 : nOffset--;
517 : }
518 :
519 58 : while( papszNV[iLine] != NULL && strlen(papszNV[iLine]) == 0 )
520 0 : iLine++;
521 :
522 29 : if( papszNV[iLine] != NULL )
523 : {
524 29 : char **papszTokens, *pszLine = papszNV[iLine];
525 : double dfValue;
526 :
527 : int i;
528 :
529 : // Trim comments.
530 2060 : for( i=0; pszLine[i] != '\0'; i++ )
531 : {
532 2031 : if( pszLine[i] == '/' && pszLine[i+1] == '*' )
533 29 : pszLine[i] = '\0';
534 : }
535 :
536 29 : papszTokens = CSLTokenizeString(papszNV[iLine]);
537 29 : if( CSLCount(papszTokens) == 3 )
538 : {
539 : /* http://agdcftp1.wr.usgs.gov/pub/projects/lcc/akcan_lcc/akcan.tar.gz contains */
540 : /* weird values for the second. Ignore it and the result looks correct */
541 18 : double dfSecond = atof(papszTokens[2]);
542 18 : if (dfSecond < 0.0 || dfSecond >= 60.0)
543 0 : dfSecond = 0.0;
544 :
545 36 : dfValue = ABS(atof(papszTokens[0]))
546 18 : + atof(papszTokens[1]) / 60.0
547 54 : + dfSecond / 3600.0;
548 :
549 18 : if( atof(papszTokens[0]) < 0.0 )
550 5 : dfValue *= -1;
551 : }
552 11 : else if( CSLCount(papszTokens) > 0 )
553 11 : dfValue = atof(papszTokens[0]);
554 : else
555 0 : dfValue = dfDefaultValue;
556 :
557 29 : CSLDestroy( papszTokens );
558 :
559 29 : return dfValue;
560 : }
561 : else
562 0 : return dfDefaultValue;
563 : }
564 : else
565 : {
566 424 : for( iLine = 0;
567 195 : papszNV[iLine] != NULL &&
568 191 : !EQUALN(papszNV[iLine],pszField,strlen(pszField));
569 : iLine++ ) {}
570 :
571 38 : if( papszNV[iLine] == NULL )
572 4 : return dfDefaultValue;
573 : else
574 34 : return atof( papszNV[iLine] + strlen(pszField) );
575 : }
576 : }
577 :
578 : /************************************************************************/
579 : /* OSR_GDS() */
580 : /************************************************************************/
581 :
582 60 : static CPLString OSR_GDS( char **papszNV, const char * pszField,
583 : const char *pszDefaultValue )
584 :
585 : {
586 : int iLine;
587 :
588 60 : if( papszNV == NULL || papszNV[0] == NULL )
589 0 : return pszDefaultValue;
590 :
591 507 : for( iLine = 0;
592 224 : papszNV[iLine] != NULL &&
593 223 : !EQUALN(papszNV[iLine],pszField,strlen(pszField));
594 : iLine++ ) {}
595 :
596 60 : if( papszNV[iLine] == NULL )
597 1 : return pszDefaultValue;
598 : else
599 : {
600 59 : CPLString osResult;
601 : char **papszTokens;
602 :
603 59 : papszTokens = CSLTokenizeString(papszNV[iLine]);
604 :
605 59 : if( CSLCount(papszTokens) > 1 )
606 59 : osResult = papszTokens[1];
607 : else
608 0 : osResult = pszDefaultValue;
609 :
610 59 : CSLDestroy( papszTokens );
611 59 : return osResult;
612 : }
613 : }
614 :
615 : /************************************************************************/
616 : /* importFromESRI() */
617 : /************************************************************************/
618 :
619 : /**
620 : * \brief Import coordinate system from ESRI .prj format(s).
621 : *
622 : * This function will read the text loaded from an ESRI .prj file, and
623 : * translate it into an OGRSpatialReference definition. This should support
624 : * many (but by no means all) old style (Arc/Info 7.x) .prj files, as well
625 : * as the newer pseudo-OGC WKT .prj files. Note that new style .prj files
626 : * are in OGC WKT format, but require some manipulation to correct datum
627 : * names, and units on some projection parameters. This is addressed within
628 : * importFromESRI() by an automatical call to morphFromESRI().
629 : *
630 : * Currently only GEOGRAPHIC, UTM, STATEPLANE, GREATBRITIAN_GRID, ALBERS,
631 : * EQUIDISTANT_CONIC, TRANSVERSE (mercator), POLAR, MERCATOR and POLYCONIC
632 : * projections are supported from old style files.
633 : *
634 : * At this time there is no equivelent exportToESRI() method. Writing old
635 : * style .prj files is not supported by OGRSpatialReference. However the
636 : * morphToESRI() and exportToWkt() methods can be used to generate output
637 : * suitable to write to new style (Arc 8) .prj files.
638 : *
639 : * This function is the equilvelent of the C function OSRImportFromESRI().
640 : *
641 : * @param papszPrj NULL terminated list of strings containing the definition.
642 : *
643 : * @return OGRERR_NONE on success or an error code in case of failure.
644 : */
645 :
646 307 : OGRErr OGRSpatialReference::importFromESRI( char **papszPrj )
647 :
648 : {
649 307 : if( papszPrj == NULL || papszPrj[0] == NULL )
650 15 : return OGRERR_CORRUPT_DATA;
651 :
652 : /* -------------------------------------------------------------------- */
653 : /* ArcGIS and related products now use a varient of Well Known */
654 : /* Text. Try to recognise this and ingest it. WKT is usually */
655 : /* all on one line, but we will accept multi-line formats and */
656 : /* concatenate. */
657 : /* -------------------------------------------------------------------- */
658 525 : if( EQUALN(papszPrj[0],"GEOGCS",6)
659 212 : || EQUALN(papszPrj[0],"PROJCS",6)
660 21 : || EQUALN(papszPrj[0],"LOCAL_CS",8) )
661 : {
662 : char *pszWKT, *pszWKT2;
663 : OGRErr eErr;
664 : int i;
665 :
666 271 : pszWKT = CPLStrdup(papszPrj[0]);
667 271 : for( i = 1; papszPrj[i] != NULL; i++ )
668 : {
669 : pszWKT = (char *)
670 0 : CPLRealloc(pszWKT,strlen(pszWKT)+strlen(papszPrj[i])+1);
671 0 : strcat( pszWKT, papszPrj[i] );
672 : }
673 271 : pszWKT2 = pszWKT;
674 271 : eErr = importFromWkt( &pszWKT2 );
675 271 : CPLFree( pszWKT );
676 :
677 271 : if( eErr == OGRERR_NONE )
678 271 : eErr = morphFromESRI();
679 271 : return eErr;
680 : }
681 :
682 : /* -------------------------------------------------------------------- */
683 : /* Operate on the basis of the projection name. */
684 : /* -------------------------------------------------------------------- */
685 21 : CPLString osProj = OSR_GDS( papszPrj, "Projection", "" );
686 :
687 21 : if( EQUAL(osProj,"") )
688 : {
689 1 : CPLDebug( "OGR_ESRI", "Can't find Projection\n" );
690 1 : return OGRERR_CORRUPT_DATA;
691 : }
692 :
693 20 : else if( EQUAL(osProj,"GEOGRAPHIC") )
694 : {
695 : }
696 :
697 19 : else if( EQUAL(osProj,"utm") )
698 : {
699 10 : if( (int) OSR_GDV( papszPrj, "zone", 0.0 ) != 0 )
700 : {
701 10 : double dfYShift = OSR_GDV( papszPrj, "Yshift", 0.0 );
702 :
703 : SetUTM( (int) OSR_GDV( papszPrj, "zone", 0.0 ),
704 10 : dfYShift == 0.0 );
705 : }
706 : else
707 : {
708 : double dfCentralMeridian, dfRefLat;
709 : int nZone;
710 :
711 0 : dfCentralMeridian = OSR_GDV( papszPrj, "PARAM_1", 0.0 );
712 0 : dfRefLat = OSR_GDV( papszPrj, "PARAM_2", 0.0 );
713 :
714 0 : nZone = (int) ((dfCentralMeridian+183) / 6.0 + 0.0000001);
715 0 : SetUTM( nZone, dfRefLat >= 0.0 );
716 : }
717 : }
718 :
719 9 : else if( EQUAL(osProj,"STATEPLANE") )
720 : {
721 4 : int nZone = (int) OSR_GDV( papszPrj, "zone", 0.0 );
722 4 : if( nZone != 0 )
723 0 : nZone = ESRIToUSGSZone( nZone );
724 : else
725 4 : nZone = (int) OSR_GDV( papszPrj, "fipszone", 0.0 );
726 :
727 4 : if( nZone != 0 )
728 : {
729 4 : if( EQUAL(OSR_GDS( papszPrj, "Datum", "NAD83"),"NAD27") )
730 0 : SetStatePlane( nZone, FALSE );
731 : else
732 4 : SetStatePlane( nZone, TRUE );
733 : }
734 : }
735 :
736 5 : else if( EQUAL(osProj,"GREATBRITIAN_GRID")
737 : || EQUAL(osProj,"GREATBRITAIN_GRID") )
738 : {
739 : const char *pszWkt =
740 0 : "PROJCS[\"OSGB 1936 / British National Grid\",GEOGCS[\"OSGB 1936\",DATUM[\"OSGB_1936\",SPHEROID[\"Airy 1830\",6377563.396,299.3249646]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",49],PARAMETER[\"central_meridian\",-2],PARAMETER[\"scale_factor\",0.999601272],PARAMETER[\"false_easting\",400000],PARAMETER[\"false_northing\",-100000],UNIT[\"metre\",1]]";
741 :
742 0 : importFromWkt( (char **) &pszWkt );
743 : }
744 :
745 5 : else if( EQUAL(osProj,"ALBERS") )
746 : {
747 : SetACEA( OSR_GDV( papszPrj, "PARAM_1", 0.0 ),
748 : OSR_GDV( papszPrj, "PARAM_2", 0.0 ),
749 : OSR_GDV( papszPrj, "PARAM_4", 0.0 ),
750 : OSR_GDV( papszPrj, "PARAM_3", 0.0 ),
751 : OSR_GDV( papszPrj, "PARAM_5", 0.0 ),
752 4 : OSR_GDV( papszPrj, "PARAM_6", 0.0 ) );
753 : }
754 :
755 1 : else if( EQUAL(osProj,"LAMBERT") )
756 : {
757 : SetLCC( OSR_GDV( papszPrj, "PARAM_1", 0.0 ),
758 : OSR_GDV( papszPrj, "PARAM_2", 0.0 ),
759 : OSR_GDV( papszPrj, "PARAM_4", 0.0 ),
760 : OSR_GDV( papszPrj, "PARAM_3", 0.0 ),
761 : OSR_GDV( papszPrj, "PARAM_5", 0.0 ),
762 0 : OSR_GDV( papszPrj, "PARAM_6", 0.0 ) );
763 : }
764 :
765 1 : else if( EQUAL(osProj,"LAMBERT_AZIMUTHAL") )
766 : {
767 : SetLAEA( OSR_GDV( papszPrj, "PARAM_2", 0.0 ),
768 : OSR_GDV( papszPrj, "PARAM_1", 0.0 ),
769 : OSR_GDV( papszPrj, "PARAM_3", 0.0 ),
770 0 : OSR_GDV( papszPrj, "PARAM_4", 0.0 ) );
771 : }
772 :
773 1 : else if( EQUAL(osProj,"EQUIDISTANT_CONIC") )
774 : {
775 0 : int nStdPCount = (int) OSR_GDV( papszPrj, "PARAM_1", 0.0 );
776 :
777 0 : if( nStdPCount == 1 )
778 : {
779 : SetEC( OSR_GDV( papszPrj, "PARAM_2", 0.0 ),
780 : OSR_GDV( papszPrj, "PARAM_2", 0.0 ),
781 : OSR_GDV( papszPrj, "PARAM_4", 0.0 ),
782 : OSR_GDV( papszPrj, "PARAM_3", 0.0 ),
783 : OSR_GDV( papszPrj, "PARAM_5", 0.0 ),
784 0 : OSR_GDV( papszPrj, "PARAM_6", 0.0 ) );
785 : }
786 : else
787 : {
788 : SetEC( OSR_GDV( papszPrj, "PARAM_2", 0.0 ),
789 : OSR_GDV( papszPrj, "PARAM_3", 0.0 ),
790 : OSR_GDV( papszPrj, "PARAM_5", 0.0 ),
791 : OSR_GDV( papszPrj, "PARAM_4", 0.0 ),
792 : OSR_GDV( papszPrj, "PARAM_5", 0.0 ),
793 0 : OSR_GDV( papszPrj, "PARAM_7", 0.0 ) );
794 : }
795 : }
796 :
797 1 : else if( EQUAL(osProj,"TRANSVERSE") )
798 : {
799 : SetTM( OSR_GDV( papszPrj, "PARAM_3", 0.0 ),
800 : OSR_GDV( papszPrj, "PARAM_2", 0.0 ),
801 : OSR_GDV( papszPrj, "PARAM_1", 0.0 ),
802 : OSR_GDV( papszPrj, "PARAM_4", 0.0 ),
803 1 : OSR_GDV( papszPrj, "PARAM_5", 0.0 ) );
804 : }
805 :
806 0 : else if( EQUAL(osProj,"POLAR") )
807 : {
808 : SetPS( OSR_GDV( papszPrj, "PARAM_2", 0.0 ),
809 : OSR_GDV( papszPrj, "PARAM_1", 0.0 ),
810 : 1.0,
811 : OSR_GDV( papszPrj, "PARAM_3", 0.0 ),
812 0 : OSR_GDV( papszPrj, "PARAM_4", 0.0 ) );
813 : }
814 :
815 0 : else if( EQUAL(osProj,"MERCATOR") )
816 : {
817 : SetMercator( OSR_GDV( papszPrj, "PARAM_1", 0.0 ),
818 : OSR_GDV( papszPrj, "PARAM_0", 0.0 ),
819 : 1.0,
820 : OSR_GDV( papszPrj, "PARAM_2", 0.0 ),
821 0 : OSR_GDV( papszPrj, "PARAM_3", 0.0 ) );
822 : }
823 :
824 0 : else if( EQUAL(osProj,"POLYCONIC") )
825 : {
826 : SetPolyconic( OSR_GDV( papszPrj, "PARAM_2", 0.0 ),
827 : OSR_GDV( papszPrj, "PARAM_1", 0.0 ),
828 : OSR_GDV( papszPrj, "PARAM_3", 0.0 ),
829 0 : OSR_GDV( papszPrj, "PARAM_4", 0.0 ) );
830 : }
831 :
832 : else
833 : {
834 0 : CPLDebug( "OGR_ESRI", "Unsupported projection: %s", osProj.c_str() );
835 0 : SetLocalCS( osProj );
836 : }
837 :
838 : /* -------------------------------------------------------------------- */
839 : /* Try to translate the datum/spheroid. */
840 : /* -------------------------------------------------------------------- */
841 20 : if( !IsLocal() && GetAttrNode( "GEOGCS" ) == NULL )
842 : {
843 16 : CPLString osDatum;
844 :
845 16 : osDatum = OSR_GDS( papszPrj, "Datum", "");
846 :
847 16 : if( EQUAL(osDatum,"NAD27") || EQUAL(osDatum,"NAD83")
848 : || EQUAL(osDatum,"WGS84") || EQUAL(osDatum,"WGS72") )
849 : {
850 11 : SetWellKnownGeogCS( osDatum );
851 : }
852 5 : else if( EQUAL( osDatum, "EUR" )
853 : || EQUAL( osDatum, "ED50" ) )
854 : {
855 0 : SetWellKnownGeogCS( "EPSG:4230" );
856 : }
857 5 : else if( EQUAL( osDatum, "GDA94" ) )
858 : {
859 5 : SetWellKnownGeogCS( "EPSG:4283" );
860 : }
861 : else
862 : {
863 0 : CPLString osSpheroid;
864 :
865 0 : osSpheroid = OSR_GDS( papszPrj, "Spheroid", "");
866 :
867 0 : if( EQUAL(osSpheroid,"INT1909")
868 : || EQUAL(osSpheroid,"INTERNATIONAL1909") )
869 : {
870 0 : OGRSpatialReference oGCS;
871 0 : oGCS.importFromEPSG( 4022 );
872 0 : CopyGeogCSFrom( &oGCS );
873 : }
874 0 : else if( EQUAL(osSpheroid,"AIRY") )
875 : {
876 0 : OGRSpatialReference oGCS;
877 0 : oGCS.importFromEPSG( 4001 );
878 0 : CopyGeogCSFrom( &oGCS );
879 : }
880 0 : else if( EQUAL(osSpheroid,"CLARKE1866") )
881 : {
882 0 : OGRSpatialReference oGCS;
883 0 : oGCS.importFromEPSG( 4008 );
884 0 : CopyGeogCSFrom( &oGCS );
885 : }
886 0 : else if( EQUAL(osSpheroid,"GRS80") )
887 : {
888 0 : OGRSpatialReference oGCS;
889 0 : oGCS.importFromEPSG( 4019 );
890 0 : CopyGeogCSFrom( &oGCS );
891 : }
892 0 : else if( EQUAL(osSpheroid,"KRASOVSKY")
893 : || EQUAL(osSpheroid,"KRASSOVSKY")
894 : || EQUAL(osSpheroid,"KRASSOWSKY") )
895 : {
896 0 : OGRSpatialReference oGCS;
897 0 : oGCS.importFromEPSG( 4024 );
898 0 : CopyGeogCSFrom( &oGCS );
899 : }
900 0 : else if( EQUAL(osSpheroid,"Bessel") )
901 : {
902 0 : OGRSpatialReference oGCS;
903 0 : oGCS.importFromEPSG( 4004 );
904 0 : CopyGeogCSFrom( &oGCS );
905 : }
906 : else
907 : {
908 : // If we don't know, default to WGS84 so there is something there.
909 0 : SetWellKnownGeogCS( "WGS84" );
910 0 : }
911 16 : }
912 : }
913 :
914 : /* -------------------------------------------------------------------- */
915 : /* Linear units translation */
916 : /* -------------------------------------------------------------------- */
917 20 : if( IsLocal() || IsProjected() )
918 : {
919 19 : CPLString osValue;
920 19 : double dfOldUnits = GetLinearUnits();
921 :
922 19 : osValue = OSR_GDS( papszPrj, "Units", "" );
923 19 : if( EQUAL(osValue, "" ) )
924 0 : SetLinearUnitsAndUpdateParameters( SRS_UL_METER, 1.0 );
925 19 : else if( EQUAL(osValue,"FEET") )
926 2 : SetLinearUnitsAndUpdateParameters( SRS_UL_US_FOOT, atof(SRS_UL_US_FOOT_CONV) );
927 17 : else if( atof(osValue) != 0.0 )
928 : SetLinearUnitsAndUpdateParameters( "user-defined",
929 1 : 1.0 / atof(osValue) );
930 : else
931 16 : SetLinearUnitsAndUpdateParameters( osValue, 1.0 );
932 :
933 : // If we have reset the linear units we should clear any authority
934 : // nodes on the PROJCS. This especially applies to state plane
935 : // per bug 1697
936 19 : double dfNewUnits = GetLinearUnits();
937 19 : if( dfOldUnits != 0.0
938 : && (dfNewUnits / dfOldUnits < 0.9999999
939 : || dfNewUnits / dfOldUnits > 1.0000001) )
940 : {
941 3 : if( GetRoot()->FindChild( "AUTHORITY" ) != -1 )
942 3 : GetRoot()->DestroyChild(GetRoot()->FindChild( "AUTHORITY" ));
943 19 : }
944 : }
945 :
946 20 : return OGRERR_NONE;
947 : }
948 :
949 : /************************************************************************/
950 : /* morphToESRI() */
951 : /************************************************************************/
952 : /**
953 : * \brief Convert in place to ESRI WKT format.
954 : *
955 : * The value nodes of this coordinate system are modified in various manners
956 : * more closely map onto the ESRI concept of WKT format. This includes
957 : * renaming a variety of projections and arguments, and stripping out
958 : * nodes note recognised by ESRI (like AUTHORITY and AXIS).
959 : *
960 : * This does the same as the C function OSRMorphToESRI().
961 : *
962 : * @return OGRERR_NONE unless something goes badly wrong.
963 : */
964 :
965 14549 : OGRErr OGRSpatialReference::morphToESRI()
966 :
967 : {
968 : OGRErr eErr;
969 :
970 14549 : CPLLocaleC localeC;
971 : /* -------------------------------------------------------------------- */
972 : /* Fixup ordering, missing linear units, etc. */
973 : /* -------------------------------------------------------------------- */
974 14549 : eErr = Fixup();
975 14549 : if( eErr != OGRERR_NONE )
976 0 : return eErr;
977 :
978 : /* -------------------------------------------------------------------- */
979 : /* Strip all CT parameters (AXIS, AUTHORITY, TOWGS84, etc). */
980 : /* -------------------------------------------------------------------- */
981 14549 : eErr = StripCTParms();
982 14549 : if( eErr != OGRERR_NONE )
983 0 : return eErr;
984 :
985 14549 : if( GetRoot() == NULL )
986 0 : return OGRERR_NONE;
987 :
988 : /* -------------------------------------------------------------------- */
989 : /* There is a special case for Hotine Oblique Mercator to split */
990 : /* out the case with an angle to rectified grid. Bug 423 */
991 : /* -------------------------------------------------------------------- */
992 14549 : const char *pszProjection = GetAttrValue("PROJECTION");
993 :
994 14549 : if( pszProjection != NULL
995 : && EQUAL(pszProjection,SRS_PT_HOTINE_OBLIQUE_MERCATOR)
996 : && fabs(GetProjParm(SRS_PP_AZIMUTH, 0.0 )-90) < 0.0001
997 : && fabs(GetProjParm(SRS_PP_RECTIFIED_GRID_ANGLE, 0.0 )-90) < 0.0001 )
998 : {
999 : SetNode( "PROJCS|PROJECTION",
1000 17 : "Hotine_Oblique_Mercator_Azimuth_Center" );
1001 :
1002 : /* ideally we should strip out of the rectified_grid_angle */
1003 : // strip off rectified_grid_angle -- I hope it is 90!
1004 17 : OGR_SRSNode *poPROJCS = GetAttrNode( "PROJCS" );
1005 17 : int iRGAChild = FindProjParm( "rectified_grid_angle", poPROJCS );
1006 17 : if( iRGAChild != -1 )
1007 17 : poPROJCS->DestroyChild( iRGAChild);
1008 :
1009 17 : pszProjection = GetAttrValue("PROJECTION");
1010 : }
1011 :
1012 : /* -------------------------------------------------------------------- */
1013 : /* Polar_Stereographic maps to ESRI codes */
1014 : /* Stereographic_South_Pole or Stereographic_North_Pole based */
1015 : /* on latitude. */
1016 : /* -------------------------------------------------------------------- */
1017 14549 : if( pszProjection != NULL
1018 : && ( EQUAL(pszProjection,SRS_PT_POLAR_STEREOGRAPHIC) ))
1019 : {
1020 80 : if( GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) < 0.0 )
1021 : {
1022 : SetNode( "PROJCS|PROJECTION",
1023 60 : "Stereographic_South_Pole" );
1024 60 : pszProjection = GetAttrValue("PROJECTION");
1025 : }
1026 : else
1027 : {
1028 : SetNode( "PROJCS|PROJECTION",
1029 20 : "Stereographic_North_Pole" );
1030 20 : pszProjection = GetAttrValue("PROJECTION");
1031 : }
1032 : }
1033 :
1034 : /* -------------------------------------------------------------------- */
1035 : /* OBLIQUE_STEREOGRAPHIC maps to ESRI Double_Stereographic */
1036 : /* -------------------------------------------------------------------- */
1037 14549 : if( pszProjection != NULL
1038 : && ( EQUAL(pszProjection,SRS_PT_OBLIQUE_STEREOGRAPHIC) ))
1039 : {
1040 58 : SetNode( "PROJCS|PROJECTION", "Double_Stereographic" );
1041 : }
1042 :
1043 : /* -------------------------------------------------------------------- */
1044 : /* Translate PROJECTION keywords that are misnamed. */
1045 : /* -------------------------------------------------------------------- */
1046 : GetRoot()->applyRemapper( "PROJECTION",
1047 : (char **)apszProjMapping+1,
1048 14549 : (char **)apszProjMapping, 2 );
1049 14549 : pszProjection = GetAttrValue("PROJECTION");
1050 :
1051 : /* -------------------------------------------------------------------- */
1052 : /* Translate DATUM keywords that are misnamed. */
1053 : /* -------------------------------------------------------------------- */
1054 14549 : InitDatumMappingTable();
1055 :
1056 : GetRoot()->applyRemapper( "DATUM",
1057 14549 : papszDatumMapping+2, papszDatumMapping+1, 3 );
1058 :
1059 14549 : const char *pszProjCSName = NULL;
1060 14549 : const char *pszGcsName = NULL;
1061 14549 : OGR_SRSNode *poProjCS = NULL;
1062 14549 : OGR_SRSNode *poProjCSNodeChild = NULL;
1063 :
1064 : /* -------------------------------------------------------------------- */
1065 : /* Very specific handling for some well known geographic */
1066 : /* coordinate systems. */
1067 : /* -------------------------------------------------------------------- */
1068 14549 : OGR_SRSNode *poGeogCS = GetAttrNode( "GEOGCS" );
1069 14549 : if( poGeogCS != NULL )
1070 : {
1071 14549 : const char *pszGeogCSName = poGeogCS->GetChild(0)->GetValue();
1072 14549 : const char *pszAuthName = GetAuthorityName("GEOGCS");
1073 14549 : const char *pszUTMPrefix = NULL;
1074 14549 : int nGCSCode = -1;
1075 :
1076 14549 : if( pszAuthName != NULL && EQUAL(pszAuthName,"EPSG") )
1077 0 : nGCSCode = atoi(GetAuthorityCode("GEOGCS"));
1078 :
1079 15233 : if( nGCSCode == 4326
1080 : || EQUAL(pszGeogCSName,"WGS84")
1081 : || EQUAL(pszGeogCSName,"WGS 84") )
1082 : {
1083 684 : poGeogCS->GetChild(0)->SetValue( "GCS_WGS_1984" );
1084 684 : pszUTMPrefix = "WGS_1984";
1085 : }
1086 14298 : else if( nGCSCode == 4267
1087 : || EQUAL(pszGeogCSName,"NAD27")
1088 : || EQUAL(pszGeogCSName,"NAD 27") )
1089 : {
1090 433 : poGeogCS->GetChild(0)->SetValue( "GCS_North_American_1927" );
1091 433 : pszUTMPrefix = "NAD_1927";
1092 : }
1093 13432 : else if( nGCSCode == 4269
1094 : || EQUAL(pszGeogCSName,"NAD83")
1095 : || EQUAL(pszGeogCSName,"NAD 83") )
1096 : {
1097 686 : poGeogCS->GetChild(0)->SetValue( "GCS_North_American_1983" );
1098 686 : pszUTMPrefix = "NAD_1983";
1099 : }
1100 :
1101 : /* -------------------------------------------------------------------- */
1102 : /* Force Unnamed to Unknown for most common locations. */
1103 : /* -------------------------------------------------------------------- */
1104 : static const char *apszUnknownMapping[] = {
1105 : "Unknown", "Unnamed",
1106 : NULL, NULL
1107 : };
1108 :
1109 : GetRoot()->applyRemapper( "PROJCS",
1110 : (char **)apszUnknownMapping+1,
1111 14549 : (char **)apszUnknownMapping+0, 2 );
1112 : GetRoot()->applyRemapper( "GEOGCS",
1113 : (char **)apszUnknownMapping+1,
1114 14549 : (char **)apszUnknownMapping+0, 2 );
1115 : GetRoot()->applyRemapper( "DATUM",
1116 : (char **)apszUnknownMapping+1,
1117 14549 : (char **)apszUnknownMapping+0, 2 );
1118 : GetRoot()->applyRemapper( "SPHEROID",
1119 : (char **)apszUnknownMapping+1,
1120 14549 : (char **)apszUnknownMapping+0, 2 );
1121 : GetRoot()->applyRemapper( "PRIMEM",
1122 : (char **)apszUnknownMapping+1,
1123 14549 : (char **)apszUnknownMapping+0, 2 );
1124 :
1125 : /* -------------------------------------------------------------------- */
1126 : /* If the PROJCS name is unset, use the PROJECTION name in */
1127 : /* place of unknown, or unnamed. At the request of Peng Gao. */
1128 : /* -------------------------------------------------------------------- */
1129 14549 : if( (poProjCS = GetAttrNode( "PROJCS" )) != NULL )
1130 11897 : poProjCSNodeChild = poProjCS->GetChild(0);
1131 :
1132 14549 : if( poProjCSNodeChild )
1133 : {
1134 11897 : pszProjCSName = poProjCSNodeChild->GetValue();
1135 11897 : char *pszNewValue = CPLStrdup(pszProjCSName);
1136 11897 : MorphNameToESRI( &pszNewValue );
1137 11897 : poProjCSNodeChild->SetValue( pszNewValue );
1138 11897 : CPLFree( pszNewValue );
1139 11897 : pszProjCSName = poProjCSNodeChild->GetValue();
1140 : }
1141 :
1142 14549 : if( pszProjCSName != NULL
1143 : && ( EQUAL(pszProjCSName,"unnamed")
1144 : || EQUAL(pszProjCSName,"unknown")
1145 : || EQUAL(pszProjCSName,"") ) )
1146 : {
1147 11 : if( GetAttrValue( "PROJECTION", 0 ) != NULL )
1148 : {
1149 11 : pszProjCSName = GetAttrValue( "PROJECTION", 0 );
1150 11 : poProjCSNodeChild->SetValue( pszProjCSName );
1151 : }
1152 : }
1153 :
1154 : /* -------------------------------------------------------------------- */
1155 : /* Prepare very specific PROJCS names for UTM coordinate */
1156 : /* systems. */
1157 : /* -------------------------------------------------------------------- */
1158 14549 : int bNorth = 0;
1159 14549 : int nZone = 0;
1160 :
1161 : /* get zone from name first */
1162 14549 : if( pszProjCSName && EQUALN(pszProjCSName, "UTM Zone ", 9) )
1163 : {
1164 0 : nZone = atoi(pszProjCSName+9);
1165 0 : if( strstr(pszProjCSName, "North") )
1166 0 : bNorth = 1;
1167 : }
1168 :
1169 : /* if can not get from the name, from the parameters */
1170 14549 : if( nZone <= 0 )
1171 14549 : nZone = GetUTMZone( &bNorth );
1172 :
1173 14549 : if( nZone > 0 && pszUTMPrefix )
1174 : {
1175 : char szUTMName[128];
1176 378 : if( bNorth )
1177 257 : sprintf( szUTMName, "%s_UTM_Zone_%dN", pszUTMPrefix, nZone );
1178 : else
1179 121 : sprintf( szUTMName, "%s_UTM_Zone_%dS", pszUTMPrefix, nZone );
1180 :
1181 378 : if( poProjCSNodeChild )
1182 378 : poProjCSNodeChild->SetValue( szUTMName );
1183 : }
1184 : }
1185 :
1186 : /* -------------------------------------------------------------------- */
1187 : /* Translate UNIT keywords that are misnamed, or even the wrong */
1188 : /* case. */
1189 : /* -------------------------------------------------------------------- */
1190 : GetRoot()->applyRemapper( "UNIT",
1191 : (char **)apszUnitMapping+1,
1192 14549 : (char **)apszUnitMapping, 2 );
1193 :
1194 : /* -------------------------------------------------------------------- */
1195 : /* reset constants for decimal degrees to the exact string ESRI */
1196 : /* expects when encountered to ensure a matchup. */
1197 : /* -------------------------------------------------------------------- */
1198 14549 : OGR_SRSNode *poUnit = GetAttrNode( "GEOGCS|UNIT" );
1199 :
1200 14549 : if( poUnit != NULL && poUnit->GetChildCount() >= 2
1201 : && ABS(GetAngularUnits()-0.0174532925199433) < 0.00000000001 )
1202 : {
1203 14438 : poUnit->GetChild(0)->SetValue("Degree");
1204 14438 : poUnit->GetChild(1)->SetValue("0.017453292519943295");
1205 : }
1206 :
1207 : /* -------------------------------------------------------------------- */
1208 : /* Make sure we reproduce US Feet exactly too. */
1209 : /* -------------------------------------------------------------------- */
1210 14549 : poUnit = GetAttrNode( "PROJCS|UNIT" );
1211 :
1212 14549 : if( poUnit != NULL && poUnit->GetChildCount() >= 2
1213 : && ABS(GetLinearUnits()- 0.30480060960121924) < 0.000000000000001)
1214 : {
1215 1839 : poUnit->GetChild(0)->SetValue("Foot_US");
1216 1839 : poUnit->GetChild(1)->SetValue("0.30480060960121924");
1217 : }
1218 :
1219 : /* -------------------------------------------------------------------- */
1220 : /* Remap parameters used for Albers and Mercator. */
1221 : /* -------------------------------------------------------------------- */
1222 14549 : pszProjection = GetAttrValue("PROJECTION");
1223 14549 : poProjCS = GetAttrNode( "PROJCS" );
1224 :
1225 14549 : if( pszProjection != NULL && EQUAL(pszProjection,"Albers") )
1226 : GetRoot()->applyRemapper(
1227 : "PARAMETER", (char **)apszAlbersMapping + 1,
1228 89 : (char **)apszAlbersMapping + 0, 2 );
1229 :
1230 14549 : if( pszProjection != NULL
1231 : && (EQUAL(pszProjection,SRS_PT_EQUIDISTANT_CONIC) ||
1232 : EQUAL(pszProjection,SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) ||
1233 : EQUAL(pszProjection,SRS_PT_AZIMUTHAL_EQUIDISTANT) ||
1234 : EQUAL(pszProjection,SRS_PT_SINUSOIDAL) ||
1235 : EQUAL(pszProjection,SRS_PT_ROBINSON) ) )
1236 : GetRoot()->applyRemapper(
1237 : "PARAMETER", (char **)apszECMapping + 1,
1238 67 : (char **)apszECMapping + 0, 2 );
1239 :
1240 14549 : if( pszProjection != NULL && EQUAL(pszProjection,"Mercator") )
1241 : GetRoot()->applyRemapper(
1242 : "PARAMETER",
1243 : (char **)apszMercatorMapping + 1,
1244 44 : (char **)apszMercatorMapping + 0, 2 );
1245 :
1246 14549 : if( pszProjection != NULL
1247 : && EQUALN(pszProjection,"Stereographic_",14)
1248 : && EQUALN(pszProjection+strlen(pszProjection)-5,"_Pole",5) )
1249 : GetRoot()->applyRemapper(
1250 : "PARAMETER",
1251 : (char **)apszPolarStereographicMapping + 1,
1252 80 : (char **)apszPolarStereographicMapping + 0, 2 );
1253 :
1254 14549 : if( pszProjection != NULL && EQUAL(pszProjection,"Plate_Carree") )
1255 0 : if(FindProjParm( SRS_PP_STANDARD_PARALLEL_1, poProjCS ) < 0)
1256 : GetRoot()->applyRemapper(
1257 : "PARAMETER",
1258 : (char **)apszPolarStereographicMapping + 1,
1259 0 : (char **)apszPolarStereographicMapping + 0, 2 );
1260 :
1261 : /* -------------------------------------------------------------------- */
1262 : /* ESRI's Equidistant_Cylindrical does not support the */
1263 : /* latitude_of_origin keyword. */
1264 : /* -------------------------------------------------------------------- */
1265 14549 : if( pszProjection != NULL
1266 : && EQUAL(pszProjection,"Equidistant_Cylindrical") )
1267 : {
1268 29 : if( GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0) != 0.0 )
1269 : {
1270 0 : CPLDebug( "OGR_ESRI", "Equirectangular with non-zero latitude of origin - not supported." );
1271 : }
1272 : else
1273 : {
1274 29 : OGR_SRSNode *poPROJCS = GetAttrNode("PROJCS");
1275 29 : if( poPROJCS )
1276 : poPROJCS->DestroyChild(
1277 29 : FindProjParm( SRS_PP_LATITUDE_OF_ORIGIN ) );
1278 : }
1279 : }
1280 :
1281 : /* -------------------------------------------------------------------- */
1282 : /* Convert SPHEROID name to use underscores instead of spaces. */
1283 : /* -------------------------------------------------------------------- */
1284 : OGR_SRSNode *poSpheroid;
1285 14549 : OGR_SRSNode *poSpheroidChild = NULL;
1286 14549 : poSpheroid = GetAttrNode( "SPHEROID" );
1287 14549 : if( poSpheroid != NULL )
1288 14549 : poSpheroidChild = poSpheroid->GetChild(0);
1289 :
1290 14549 : if( poSpheroidChild != NULL )
1291 : {
1292 : // char *pszNewValue = CPLStrdup(RemapSpheroidName(poSpheroidChild->GetValue()));
1293 14549 : char *pszNewValue = CPLStrdup(poSpheroidChild->GetValue());
1294 :
1295 14549 : MorphNameToESRI( &pszNewValue );
1296 :
1297 14549 : poSpheroidChild->SetValue( pszNewValue );
1298 14549 : CPLFree( pszNewValue );
1299 :
1300 : GetRoot()->applyRemapper( "SPHEROID",
1301 : (char **) apszSpheroidMapping+0,
1302 14549 : (char **) apszSpheroidMapping+1, 2 );
1303 : }
1304 :
1305 14549 : if( poSpheroid != NULL )
1306 14549 : poSpheroidChild = poSpheroid->GetChild(2);
1307 :
1308 14549 : if( poSpheroidChild != NULL )
1309 : {
1310 14549 : const char * dfValue = poSpheroidChild->GetValue();
1311 597068 : for( int i = 0; apszInvFlatteningMapping[i] != NULL; i += 2 )
1312 : {
1313 583357 : if( EQUALN(apszInvFlatteningMapping[i], dfValue, strlen(apszInvFlatteningMapping[i]) ))
1314 : {
1315 838 : poSpheroidChild->SetValue( apszInvFlatteningMapping[i+1] );
1316 838 : break;
1317 : }
1318 : }
1319 : }
1320 :
1321 : /* -------------------------------------------------------------------- */
1322 : /* Try to insert a D_ in front of the datum name. */
1323 : /* -------------------------------------------------------------------- */
1324 : OGR_SRSNode *poDatum;
1325 :
1326 14549 : poDatum = GetAttrNode( "DATUM" );
1327 14549 : if( poDatum != NULL )
1328 14549 : poDatum = poDatum->GetChild(0);
1329 :
1330 14549 : if( poDatum != NULL )
1331 : {
1332 14549 : const char* pszDatumName = poDatum->GetValue();
1333 14549 : if( !EQUALN(pszDatumName, "D_",2) )
1334 : {
1335 : char *pszNewValue;
1336 :
1337 2932 : pszNewValue = (char *) CPLMalloc(strlen(poDatum->GetValue())+3);
1338 2932 : strcpy( pszNewValue, "D_" );
1339 2932 : strcat( pszNewValue, poDatum->GetValue() );
1340 2932 : poDatum->SetValue( pszNewValue );
1341 2932 : CPLFree( pszNewValue );
1342 : }
1343 : }
1344 :
1345 : /* -------------------------------------------------------------------- */
1346 : /* final check names */
1347 : /* -------------------------------------------------------------------- */
1348 14549 : if( poProjCSNodeChild )
1349 11897 : pszProjCSName = poProjCSNodeChild->GetValue();
1350 :
1351 14549 : if( pszProjCSName )
1352 : {
1353 11897 : pszGcsName = GetAttrValue( "GEOGCS" );
1354 11897 : if(pszGcsName && !EQUALN( pszGcsName, "GCS_", 4 ) )
1355 : {
1356 5912 : char* newGcsName = (char *) CPLMalloc(strlen(pszGcsName) + 5);
1357 5912 : strcpy( newGcsName, "GCS_" );
1358 5912 : strcat(newGcsName, pszGcsName);
1359 5912 : SetNewName( this, "GEOGCS", newGcsName );
1360 5912 : CPLFree( newGcsName );
1361 5912 : pszGcsName = GetAttrValue("GEOGCS" );
1362 : }
1363 11897 : RemapGeogCSName(this, pszGcsName);
1364 :
1365 : // Specific processing and remapping
1366 11897 : pszProjection = GetAttrValue("PROJECTION");
1367 11897 : if(pszProjection)
1368 : {
1369 11897 : if(EQUAL(pszProjection,"Lambert_Conformal_Conic"))
1370 : {
1371 2710 : if(FindProjParm( SRS_PP_STANDARD_PARALLEL_2, poProjCS ) < 0 )
1372 : {
1373 288 : int iChild = FindProjParm( SRS_PP_LATITUDE_OF_ORIGIN, poProjCS );
1374 288 : int iChild1 = FindProjParm( SRS_PP_STANDARD_PARALLEL_1, poProjCS );
1375 288 : if( iChild >= 0 && iChild1 < 0 )
1376 : {
1377 151 : const OGR_SRSNode *poParameter = poProjCS->GetChild(iChild);
1378 151 : if( poParameter )
1379 : {
1380 151 : OGR_SRSNode *poNewParm = new OGR_SRSNode( "PARAMETER" );
1381 302 : poNewParm->AddChild( new OGR_SRSNode( "standard_parallel_1" ) );
1382 151 : poNewParm->AddChild( new OGR_SRSNode( poParameter->GetChild(1)->GetValue() ) );
1383 151 : poProjCS->AddChild( poNewParm );
1384 : }
1385 : }
1386 : }
1387 : }
1388 :
1389 11897 : if(EQUAL(pszProjection,"Plate_Carree"))
1390 : {
1391 0 : int iChild = FindProjParm( SRS_PP_STANDARD_PARALLEL_1, poProjCS );
1392 0 : if(iChild < 0)
1393 0 : iChild = FindProjParm( SRS_PP_PSEUDO_STD_PARALLEL_1, poProjCS );
1394 :
1395 0 : if(iChild >= 0)
1396 : {
1397 0 : const OGR_SRSNode *poParameter = poProjCS->GetChild(iChild);
1398 0 : if(!EQUAL(poParameter->GetChild(1)->GetValue(), "0.0") && !EQUAL(poParameter->GetChild(1)->GetValue(), "0"))
1399 : {
1400 0 : SetNode( "PROJCS|PROJECTION", "Equidistant_Cylindrical" );
1401 0 : pszProjection = GetAttrValue("PROJECTION");
1402 : }
1403 : }
1404 : }
1405 11897 : DeleteParamBasedOnPrjName( this, pszProjection, (char **)apszDeleteParametersBasedOnProjection);
1406 11897 : AddParamBasedOnPrjName( this, pszProjection, (char **)apszAddParametersBasedOnProjection);
1407 11897 : RemapPValuesBasedOnProjCSAndPName( this, pszProjection, (char **)apszParamValueMapping);
1408 11897 : RemapPNamesBasedOnProjCSAndPName( this, pszProjection, (char **)apszParamNameMapping);
1409 : }
1410 : }
1411 :
1412 14549 : return OGRERR_NONE;
1413 : }
1414 :
1415 : /************************************************************************/
1416 : /* OSRMorphToESRI() */
1417 : /************************************************************************/
1418 :
1419 : /**
1420 : * \brief Convert in place to ESRI WKT format.
1421 : *
1422 : * This function is the same as the C++ method OGRSpatialReference::morphToESRI()
1423 : */
1424 14258 : OGRErr OSRMorphToESRI( OGRSpatialReferenceH hSRS )
1425 :
1426 : {
1427 14258 : VALIDATE_POINTER1( hSRS, "OSRMorphToESRI", CE_Failure );
1428 :
1429 14258 : return ((OGRSpatialReference *) hSRS)->morphToESRI();
1430 : }
1431 :
1432 : /************************************************************************/
1433 : /* morphFromESRI() */
1434 : /* */
1435 : /* modify this definition from the ESRI definition of WKT to */
1436 : /* the "Standard" definition. */
1437 : /************************************************************************/
1438 :
1439 : /**
1440 : * \brief Convert in place from ESRI WKT format.
1441 : *
1442 : * The value notes of this coordinate system are modified in various manners
1443 : * to adhere more closely to the WKT standard. This mostly involves
1444 : * translating a variety of ESRI names for projections, arguments and
1445 : * datums to "standard" names, as defined by Adam Gawne-Cain's reference
1446 : * translation of EPSG to WKT for the CT specification.
1447 : *
1448 : * This does the same as the C function OSRMorphFromESRI().
1449 : *
1450 : * @return OGRERR_NONE unless something goes badly wrong.
1451 : */
1452 :
1453 14741 : OGRErr OGRSpatialReference::morphFromESRI()
1454 :
1455 : {
1456 14741 : OGRErr eErr = OGRERR_NONE;
1457 : OGR_SRSNode *poDatum;
1458 14741 : char *pszDatumOrig = NULL;
1459 :
1460 14741 : if( GetRoot() == NULL )
1461 0 : return OGRERR_NONE;
1462 :
1463 14741 : InitDatumMappingTable();
1464 :
1465 : /* -------------------------------------------------------------------- */
1466 : /* Save original datum name for later */
1467 : /* -------------------------------------------------------------------- */
1468 14741 : poDatum = GetAttrNode( "DATUM" );
1469 14741 : if( poDatum != NULL )
1470 : {
1471 14741 : poDatum = poDatum->GetChild(0);
1472 14741 : pszDatumOrig = CPLStrdup( poDatum->GetValue() );
1473 : }
1474 :
1475 : /* -------------------------------------------------------------------- */
1476 : /* Translate DATUM keywords that are oddly named. */
1477 : /* -------------------------------------------------------------------- */
1478 : GetRoot()->applyRemapper( "DATUM",
1479 : (char **)papszDatumMapping+1,
1480 14741 : (char **)papszDatumMapping+2, 3 );
1481 :
1482 : /* -------------------------------------------------------------------- */
1483 : /* Try to remove any D_ in front of the datum name. */
1484 : /* -------------------------------------------------------------------- */
1485 14741 : poDatum = GetAttrNode( "DATUM" );
1486 14741 : if( poDatum != NULL )
1487 14741 : poDatum = poDatum->GetChild(0);
1488 :
1489 14741 : if( poDatum != NULL )
1490 : {
1491 14741 : if( EQUALN(poDatum->GetValue(),"D_",2) )
1492 : {
1493 2929 : char *pszNewValue = CPLStrdup( poDatum->GetValue() + 2 );
1494 2929 : poDatum->SetValue( pszNewValue );
1495 2929 : CPLFree( pszNewValue );
1496 : }
1497 : }
1498 :
1499 : /* -------------------------------------------------------------------- */
1500 : /* Translate some SPHEROID keywords that are oddly named. */
1501 : /* -------------------------------------------------------------------- */
1502 : GetRoot()->applyRemapper( "SPHEROID",
1503 : (char **)apszSpheroidMapping+1,
1504 14741 : (char **)apszSpheroidMapping+0, 2 );
1505 :
1506 : /* -------------------------------------------------------------------- */
1507 : /* Split Lambert_Conformal_Conic into 1SP or 2SP form. */
1508 : /* */
1509 : /* See bugzilla.remotesensing.org/show_bug.cgi?id=187 */
1510 : /* */
1511 : /* We decide based on whether it has 2SPs. We used to assume */
1512 : /* 1SP if it had a scale factor but that turned out to be a */
1513 : /* poor test. */
1514 : /* -------------------------------------------------------------------- */
1515 14741 : const char *pszProjection = GetAttrValue("PROJECTION");
1516 :
1517 14741 : if( pszProjection != NULL
1518 : && EQUAL(pszProjection,"Lambert_Conformal_Conic") )
1519 : {
1520 2740 : if( GetProjParm( SRS_PP_STANDARD_PARALLEL_1, 1000.0 ) != 1000.0
1521 : && GetProjParm( SRS_PP_STANDARD_PARALLEL_2, 1000.0 ) != 1000.0 )
1522 : SetNode( "PROJCS|PROJECTION",
1523 2452 : SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP );
1524 : else
1525 : SetNode( "PROJCS|PROJECTION",
1526 288 : SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP );
1527 :
1528 2740 : pszProjection = GetAttrValue("PROJECTION");
1529 : }
1530 :
1531 : /* -------------------------------------------------------------------- */
1532 : /* If we are remapping Hotine_Oblique_Mercator_Azimuth_Center */
1533 : /* add a rectified_grid_angle parameter - to match the azimuth */
1534 : /* I guess. */
1535 : /* -------------------------------------------------------------------- */
1536 14741 : if( pszProjection != NULL
1537 : && EQUAL(pszProjection,"Hotine_Oblique_Mercator_Azimuth_Center") )
1538 : {
1539 : SetProjParm( SRS_PP_RECTIFIED_GRID_ANGLE ,
1540 18 : GetProjParm( SRS_PP_AZIMUTH, 0.0 ) );
1541 18 : FixupOrdering();
1542 : }
1543 :
1544 : /* -------------------------------------------------------------------- */
1545 : /* Remap Albers, Mercator and Polar Stereographic parameters. */
1546 : /* -------------------------------------------------------------------- */
1547 14741 : if( pszProjection != NULL && EQUAL(pszProjection,"Albers") )
1548 : GetRoot()->applyRemapper(
1549 : "PARAMETER", (char **)apszAlbersMapping + 0,
1550 92 : (char **)apszAlbersMapping + 1, 2 );
1551 :
1552 14741 : if( pszProjection != NULL
1553 : && (EQUAL(pszProjection,SRS_PT_EQUIDISTANT_CONIC) ||
1554 : EQUAL(pszProjection,SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) ||
1555 : EQUAL(pszProjection,SRS_PT_AZIMUTHAL_EQUIDISTANT) ||
1556 : EQUAL(pszProjection,SRS_PT_SINUSOIDAL) ||
1557 : EQUAL(pszProjection,SRS_PT_ROBINSON) ) )
1558 : GetRoot()->applyRemapper(
1559 : "PARAMETER", (char **)apszECMapping + 0,
1560 68 : (char **)apszECMapping + 1, 2 );
1561 :
1562 14741 : if( pszProjection != NULL && EQUAL(pszProjection,"Mercator") )
1563 : GetRoot()->applyRemapper(
1564 : "PARAMETER",
1565 : (char **)apszMercatorMapping + 0,
1566 44 : (char **)apszMercatorMapping + 1, 2 );
1567 :
1568 14741 : if( pszProjection != NULL && EQUAL(pszProjection,"Orthographic") )
1569 : GetRoot()->applyRemapper(
1570 : "PARAMETER", (char **)apszOrthographicMapping + 0,
1571 5 : (char **)apszOrthographicMapping + 1, 2 );
1572 :
1573 14741 : if( pszProjection != NULL
1574 : && EQUALN(pszProjection,"Stereographic_",14)
1575 : && EQUALN(pszProjection+strlen(pszProjection)-5,"_Pole",5) )
1576 : GetRoot()->applyRemapper(
1577 : "PARAMETER",
1578 : (char **)apszPolarStereographicMapping + 0,
1579 80 : (char **)apszPolarStereographicMapping + 1, 2 );
1580 :
1581 : /* -------------------------------------------------------------------- */
1582 : /* Remap south and north polar stereographic to one value. */
1583 : /* -------------------------------------------------------------------- */
1584 14741 : if( pszProjection != NULL
1585 : && EQUALN(pszProjection,"Stereographic_",14)
1586 : && EQUALN(pszProjection+strlen(pszProjection)-5,"_Pole",5) )
1587 : {
1588 80 : SetNode( "PROJCS|PROJECTION", SRS_PT_POLAR_STEREOGRAPHIC );
1589 80 : pszProjection = GetAttrValue("PROJECTION");
1590 : }
1591 :
1592 : /* -------------------------------------------------------------------- */
1593 : /* Remap Double_Stereographic to Oblique_Stereographic. */
1594 : /* -------------------------------------------------------------------- */
1595 14741 : if( pszProjection != NULL
1596 : && EQUAL(pszProjection,"Double_Stereographic") )
1597 : {
1598 58 : SetNode( "PROJCS|PROJECTION", SRS_PT_OBLIQUE_STEREOGRAPHIC );
1599 58 : pszProjection = GetAttrValue("PROJECTION");
1600 : }
1601 :
1602 : /* -------------------------------------------------------------------- */
1603 : /* Remap Equidistant_Cylindrical parameter. It is same as */
1604 : /* Stereographic */
1605 : /* -------------------------------------------------------------------- */
1606 : #ifdef notdef
1607 : if( pszProjection != NULL && EQUAL(pszProjection,"Equidistant_Cylindrical") )
1608 : GetRoot()->applyRemapper(
1609 : "PARAMETER",
1610 : (char **)apszPolarStereographicMapping + 0,
1611 : (char **)apszPolarStereographicMapping + 1, 2 );
1612 : #endif
1613 :
1614 : /* -------------------------------------------------------------------- */
1615 : /* Translate PROJECTION keywords that are misnamed. */
1616 : /* -------------------------------------------------------------------- */
1617 : GetRoot()->applyRemapper( "PROJECTION",
1618 : (char **)apszProjMapping,
1619 14741 : (char **)apszProjMapping+1, 2 );
1620 :
1621 : /* -------------------------------------------------------------------- */
1622 : /* Translate DATUM keywords that are misnamed. */
1623 : /* -------------------------------------------------------------------- */
1624 14741 : InitDatumMappingTable();
1625 :
1626 : GetRoot()->applyRemapper( "DATUM",
1627 : (char **)papszDatumMapping+1,
1628 14741 : (char **)papszDatumMapping+2, 3 );
1629 :
1630 : /* -------------------------------------------------------------------- */
1631 : /* Fix TOWGS84, DATUM or GEOGCS */
1632 : /* -------------------------------------------------------------------- */
1633 : /* TODO test more ESRI WKT; also add PROJCS */
1634 :
1635 : /* Check GDAL_FIX_ESRI_WKT config option (default=NO); if YES, set to DATUM */
1636 14741 : const char *pszFixWktConfig=CPLGetConfigOption( "GDAL_FIX_ESRI_WKT", "NO" );
1637 14741 : if ( EQUAL(pszFixWktConfig,"YES") )
1638 0 : pszFixWktConfig = "DATUM";
1639 :
1640 14741 : if( !EQUAL(pszFixWktConfig, "NO") && poDatum != NULL )
1641 : {
1642 : CPLDebug( "OGR_ESRI",
1643 : "morphFromESRI() looking for missing TOWGS84, datum=%s, config=%s",
1644 5061 : pszDatumOrig, pszFixWktConfig );
1645 :
1646 : /* Special case for WGS84 and other common GCS? */
1647 :
1648 2070092 : for( int i = 0; DMGetESRIName(i) != NULL; i++ )
1649 : {
1650 : /* we found the ESRI datum name in the map */
1651 2069123 : if( EQUAL(DMGetESRIName(i),pszDatumOrig) )
1652 : {
1653 : int nGeogCS;
1654 : int bDeprecated;
1655 4219 : const char *pszFilename = NULL;
1656 4219 : char **papszRecord = NULL;
1657 4219 : OGR_SRSNode *poNode = NULL;
1658 4219 : const char *pszThisValue = NULL;
1659 4219 : char *pszOtherValue = NULL;
1660 :
1661 : /* look for GEOGCS corresponding to this datum */
1662 4219 : pszFilename = CSVFilename("gcs.csv");
1663 : papszRecord = CSVScanFileByName( pszFilename, "DATUM_CODE",
1664 4219 : DMGetEPSGCode(i), CC_Integer );
1665 4219 : if ( papszRecord != NULL )
1666 : {
1667 : /* make sure we got a valid EPSG code and it is not DEPRECATED */
1668 : nGeogCS = atoi( CSLGetField( papszRecord,
1669 4219 : CSVGetFileFieldId(pszFilename,"COORD_REF_SYS_CODE")) );
1670 : bDeprecated = atoi( CSLGetField( papszRecord,
1671 4219 : CSVGetFileFieldId(pszFilename,"DEPRECATED")) );
1672 :
1673 : // if ( nGeogCS >= 1 && bDeprecated == 0 )
1674 4219 : if ( nGeogCS >= 1 )
1675 : {
1676 4219 : OGRSpatialReference oSRSTemp;
1677 4219 : if ( oSRSTemp.importFromEPSG( nGeogCS ) == OGRERR_NONE )
1678 : {
1679 : /* make clone of GEOGCS and strip CT parms for testing */
1680 4219 : OGRSpatialReference *poSRSTemp2 = NULL;
1681 4219 : int bIsSame = FALSE;
1682 4219 : poSRSTemp2 = oSRSTemp.CloneGeogCS();
1683 4219 : poSRSTemp2->StripCTParms();
1684 4219 : bIsSame = this->IsSameGeogCS( poSRSTemp2 );
1685 4219 : delete poSRSTemp2;
1686 :
1687 : /* clone GEOGCS from original if they match and if allowed */
1688 4219 : if ( EQUAL(pszFixWktConfig,"GEOGCS")
1689 : && bIsSame )
1690 : {
1691 774 : this->CopyGeogCSFrom( &oSRSTemp );
1692 : CPLDebug( "OGR_ESRI",
1693 : "morphFromESRI() cloned GEOGCS from EPSG:%d",
1694 774 : nGeogCS );
1695 : /* exit loop */
1696 : break;
1697 : }
1698 : /* else try to copy only DATUM or TOWGS84
1699 : we got here either because of config option or
1700 : GEOGCS are not strictly equal */
1701 3445 : else if ( EQUAL(pszFixWktConfig,"GEOGCS") ||
1702 : EQUAL(pszFixWktConfig,"DATUM") ||
1703 : EQUAL(pszFixWktConfig,"TOWGS84") )
1704 : {
1705 : /* test for matching SPHEROID, because there can be 2 datums with same ESRI name
1706 : but different spheroids (e.g. EPSG:4618 and EPSG:4291) - see bug #4345 */
1707 3445 : pszThisValue = pszOtherValue = NULL;
1708 3445 : pszThisValue = this->GetAttrValue( "DATUM|SPHEROID", 0 );
1709 3445 : if ( oSRSTemp.GetAttrValue( "DATUM|SPHEROID", 0 ) )
1710 : {
1711 3445 : pszOtherValue = CPLStrdup(oSRSTemp.GetAttrValue( "DATUM|SPHEROID", 0 ) );
1712 3445 : MorphNameToESRI( &pszOtherValue ); /* morph spheroid name to ESRI */
1713 : }
1714 3445 : if ( EQUAL( pszThisValue, pszOtherValue ) )
1715 3412 : bIsSame = TRUE;
1716 : else
1717 33 : bIsSame = FALSE;
1718 3445 : if (pszOtherValue) CPLFree(pszOtherValue);
1719 :
1720 3445 : if ( bIsSame )
1721 : {
1722 : /* test for matching PRIMEM, because there can be 2 datums with same ESRI name
1723 : but different prime meridian (e.g. EPSG:4218 and EPSG:4802) - see bug #4378 */
1724 3412 : pszThisValue = pszOtherValue = NULL;
1725 3412 : pszThisValue = this->GetAttrValue( "PRIMEM", 0 );
1726 3412 : if ( oSRSTemp.GetAttrValue( "PRIMEM", 0 ) )
1727 : {
1728 3412 : pszOtherValue = CPLStrdup(oSRSTemp.GetAttrValue( "PRIMEM", 0 ) );
1729 : }
1730 3412 : if ( EQUAL( pszThisValue, pszOtherValue ) )
1731 3318 : bIsSame = TRUE;
1732 : else
1733 94 : bIsSame = FALSE;
1734 3412 : if (pszOtherValue) CPLFree(pszOtherValue);
1735 : }
1736 :
1737 : /* found a matching spheroid */
1738 3445 : if ( bIsSame )
1739 : {
1740 : /* clone DATUM */
1741 6636 : if ( EQUAL(pszFixWktConfig,"GEOGCS") ||
1742 : EQUAL(pszFixWktConfig,"DATUM") )
1743 : {
1744 3318 : OGR_SRSNode *poGeogCS = this->GetAttrNode( "GEOGCS" );
1745 3318 : const OGR_SRSNode *poDatumOther = oSRSTemp.GetAttrNode( "DATUM" );
1746 3318 : if ( poGeogCS && poDatumOther )
1747 : {
1748 : /* make sure we preserve the position of the DATUM node */
1749 3318 : int nPos = poGeogCS->FindChild( "DATUM" );
1750 3318 : if ( nPos >= 0 )
1751 : {
1752 3318 : poGeogCS->DestroyChild( nPos );
1753 3318 : poGeogCS->InsertChild( poDatumOther->Clone(), nPos );
1754 : CPLDebug( "OGR_ESRI",
1755 : "morphFromESRI() cloned DATUM from EPSG:%d",
1756 3318 : nGeogCS );
1757 : }
1758 : }
1759 : }
1760 : /* just copy TOWGS84 */
1761 0 : else if ( EQUAL(pszFixWktConfig,"TOWGS84") )
1762 : {
1763 0 : poNode=oSRSTemp.GetAttrNode( "DATUM|TOWGS84" );
1764 0 : if ( poNode )
1765 : {
1766 0 : poNode=poNode->Clone();
1767 0 : GetAttrNode( "DATUM" )->AddChild( poNode );
1768 : CPLDebug( "OGR_ESRI",
1769 : "morphFromESRI() found missing TOWGS84 from EPSG:%d",
1770 0 : nGeogCS );
1771 : }
1772 : }
1773 : /* exit loop */
1774 : break;
1775 : }
1776 : }
1777 0 : }
1778 : }
1779 : }
1780 : }
1781 : }
1782 : }
1783 :
1784 14741 : CPLFree( pszDatumOrig );
1785 :
1786 14741 : return eErr;
1787 : }
1788 :
1789 : /************************************************************************/
1790 : /* OSRMorphFromESRI() */
1791 : /************************************************************************/
1792 :
1793 : /**
1794 : * \brief Convert in place from ESRI WKT format.
1795 : *
1796 : * This function is the same as the C++ method OGRSpatialReference::morphFromESRI()
1797 : */
1798 14261 : OGRErr OSRMorphFromESRI( OGRSpatialReferenceH hSRS )
1799 :
1800 : {
1801 14261 : VALIDATE_POINTER1( hSRS, "OSRMorphFromESRI", CE_Failure );
1802 :
1803 14261 : return ((OGRSpatialReference *) hSRS)->morphFromESRI();
1804 : }
1805 :
1806 : /************************************************************************/
1807 : /* SetNewName() */
1808 : /* */
1809 : /* Set an esri name */
1810 : /************************************************************************/
1811 5912 : void SetNewName( OGRSpatialReference* pOgr, const char* keyName, const char* newName )
1812 : {
1813 5912 : OGR_SRSNode *poNode = pOgr->GetAttrNode( keyName );
1814 5912 : OGR_SRSNode *poNodeChild = NULL;
1815 5912 : if(poNode)
1816 5912 : poNodeChild = poNode->GetChild(0);
1817 5912 : if( poNodeChild)
1818 5912 : poNodeChild->SetValue( newName);
1819 5912 : }
1820 :
1821 : /************************************************************************/
1822 : /* RemapImgWGSProjcsName() */
1823 : /* */
1824 : /* Convert Img projcs names to ESRI style */
1825 : /************************************************************************/
1826 0 : int RemapImgWGSProjcsName( OGRSpatialReference* pOgr, const char* pszProjCSName, const char* pszProgCSName )
1827 : {
1828 0 : if(EQUAL(pszProgCSName, "WGS_1972") || EQUAL(pszProgCSName, "WGS_1984") )
1829 : {
1830 0 : char* newName = (char *) CPLMalloc(strlen(pszProjCSName) + 10);
1831 0 : sprintf( newName, "%s_", pszProgCSName );
1832 0 : strcat(newName, pszProjCSName);
1833 0 : SetNewName( pOgr, "PROJCS", newName );
1834 0 : CPLFree( newName );
1835 0 : return 1;
1836 : }
1837 0 : return -1;
1838 : }
1839 :
1840 : /************************************************************************/
1841 : /* RemapImgUTMNames() */
1842 : /* */
1843 : /* Convert Img UTM names to ESRI style */
1844 : /************************************************************************/
1845 :
1846 0 : int RemapImgUTMNames( OGRSpatialReference* pOgr, const char* pszProjCSName, const char* pszProgCSName,
1847 : char **mappingTable )
1848 : {
1849 : long i;
1850 0 : long iIndex = -1;
1851 0 : for( i = 0; mappingTable[i] != NULL; i += 5 )
1852 : {
1853 0 : if( EQUAL(pszProjCSName, mappingTable[i]) )
1854 : {
1855 0 : long j = i;
1856 0 : while(mappingTable[j] != NULL && EQUAL(mappingTable[i], mappingTable[j]))
1857 : {
1858 0 : if( EQUAL(pszProgCSName, mappingTable[j+1]) )
1859 : {
1860 0 : iIndex = j;
1861 0 : break;
1862 : }
1863 0 : j += 5;
1864 : }
1865 0 : if (iIndex >= 0)
1866 0 : break;
1867 : }
1868 : }
1869 0 : if(iIndex >= 0)
1870 : {
1871 0 : OGR_SRSNode *poNode = pOgr->GetAttrNode( "PROJCS" );
1872 0 : OGR_SRSNode *poNodeChild = NULL;
1873 0 : if(poNode)
1874 0 : poNodeChild = poNode->GetChild(0);
1875 0 : if( poNodeChild && strlen(poNodeChild->GetValue()) > 0 )
1876 0 : poNodeChild->SetValue( mappingTable[iIndex+2]);
1877 :
1878 0 : poNode = pOgr->GetAttrNode( "GEOGCS" );
1879 0 : poNodeChild = NULL;
1880 0 : if(poNode)
1881 0 : poNodeChild = poNode->GetChild(0);
1882 0 : if( poNodeChild && strlen(poNodeChild->GetValue()) > 0 )
1883 0 : poNodeChild->SetValue( mappingTable[iIndex+3]);
1884 :
1885 0 : poNode = pOgr->GetAttrNode( "DATUM" );
1886 0 : poNodeChild = NULL;
1887 0 : if(poNode)
1888 0 : poNodeChild = poNode->GetChild(0);
1889 0 : if( poNodeChild && strlen(poNodeChild->GetValue()) > 0 )
1890 0 : poNodeChild->SetValue( mappingTable[iIndex+4]);
1891 : }
1892 0 : return iIndex;
1893 : }
1894 :
1895 : /************************************************************************/
1896 : /* RemapNameBasedOnKeyName() */
1897 : /* */
1898 : /* Convert a name to ESRI style name */
1899 : /************************************************************************/
1900 :
1901 11785 : int RemapNameBasedOnKeyName( OGRSpatialReference* pOgr, const char* pszName, const char* pszkeyName,
1902 : char **mappingTable )
1903 : {
1904 : long i;
1905 11785 : long iIndex = -1;
1906 1181791 : for( i = 0; mappingTable[i] != NULL; i += 2 )
1907 : {
1908 1170302 : if( EQUAL(pszName, mappingTable[i]) )
1909 : {
1910 296 : iIndex = i;
1911 296 : break;
1912 : }
1913 : }
1914 11785 : if(iIndex >= 0)
1915 : {
1916 296 : OGR_SRSNode *poNode = pOgr->GetAttrNode( pszkeyName );
1917 296 : OGR_SRSNode *poNodeChild = NULL;
1918 296 : if(poNode)
1919 296 : poNodeChild = poNode->GetChild(0);
1920 296 : if( poNodeChild && strlen(poNodeChild->GetValue()) > 0 )
1921 296 : poNodeChild->SetValue( mappingTable[iIndex+1]);
1922 : }
1923 11785 : return iIndex;
1924 : }
1925 :
1926 : /************************************************************************/
1927 : /* RemapNamesBasedOnTwo() */
1928 : /* */
1929 : /* Convert a name to ESRI style name */
1930 : /************************************************************************/
1931 :
1932 35225 : int RemapNamesBasedOnTwo( OGRSpatialReference* pOgr, const char* name1, const char* name2,
1933 : char **mappingTable, long nTableStepSize,
1934 : char** pszkeyNames, long nKeys )
1935 : {
1936 : long i, n, n1;
1937 35225 : long iIndex = -1;
1938 338748 : for( i = 0; mappingTable[i] != NULL; i += nTableStepSize )
1939 : {
1940 303644 : n = strlen(name1);
1941 303644 : n1 = strlen(mappingTable[i]);
1942 303644 : if( EQUALN(name1, mappingTable[i], n1<=n? n1 : n) )
1943 : {
1944 331 : long j = i;
1945 959 : while(mappingTable[j] != NULL && EQUAL(mappingTable[i], mappingTable[j]))
1946 : {
1947 418 : if( EQUALN(name2, mappingTable[j+1], strlen(mappingTable[j+1])) )
1948 : {
1949 121 : iIndex = j;
1950 121 : break;
1951 : }
1952 297 : j += 3;
1953 : }
1954 331 : if (iIndex >= 0)
1955 121 : break;
1956 : }
1957 : }
1958 35225 : if(iIndex >= 0)
1959 : {
1960 242 : for( i = 0; i < nKeys; i ++ )
1961 : {
1962 121 : OGR_SRSNode *poNode = pOgr->GetAttrNode( pszkeyNames[i] );
1963 121 : OGR_SRSNode *poNodeChild = NULL;
1964 121 : if(poNode)
1965 121 : poNodeChild = poNode->GetChild(0);
1966 121 : if( poNodeChild && strlen(poNodeChild->GetValue()) > 0 )
1967 121 : poNodeChild->SetValue( mappingTable[iIndex+i+2]);
1968 : }
1969 :
1970 : }
1971 35225 : return iIndex;
1972 : }
1973 :
1974 : /************************************************************************/
1975 : /* RemapPValuesBasedOnProjCSAndPName() */
1976 : /* */
1977 : /* Convert a parameters to ESRI style name */
1978 : /************************************************************************/
1979 :
1980 11897 : int RemapPValuesBasedOnProjCSAndPName( OGRSpatialReference* pOgr, const char* pszProgCSName,
1981 : char **mappingTable )
1982 : {
1983 11897 : long ret = 0;
1984 11897 : OGR_SRSNode *poPROJCS = pOgr->GetAttrNode( "PROJCS" );
1985 81704 : for( int i = 0; mappingTable[i] != NULL; i += 4 )
1986 : {
1987 219364 : while( mappingTable[i] != NULL && EQUALN(pszProgCSName, mappingTable[i], strlen(mappingTable[i])) )
1988 : {
1989 : OGR_SRSNode *poParm;
1990 57040 : const char* pszParamName = mappingTable[i+1];
1991 57040 : const char* pszParamValue = mappingTable[i+2];
1992 575892 : for( int iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ )
1993 : {
1994 518852 : poParm = poPROJCS->GetChild( iChild );
1995 :
1996 518852 : if( EQUAL(poParm->GetValue(),"PARAMETER")
1997 : && poParm->GetChildCount() == 2
1998 : && EQUAL(poParm->GetChild(0)->GetValue(),pszParamName)
1999 : && EQUALN(poParm->GetChild(1)->GetValue(),pszParamValue, strlen(pszParamValue) ) )
2000 : {
2001 0 : poParm->GetChild(1)->SetValue( mappingTable[i+3] );
2002 0 : break;
2003 : }
2004 : }
2005 57040 : ret ++;
2006 57040 : i += 4;
2007 : }
2008 81162 : if (ret > 0)
2009 11355 : break;
2010 : }
2011 11897 : return ret;
2012 : }
2013 :
2014 : /************************************************************************/
2015 : /* RemapPNamesBasedOnProjCSAndPName() */
2016 : /* */
2017 : /* Convert a parameters to ESRI style name */
2018 : /************************************************************************/
2019 :
2020 11897 : int RemapPNamesBasedOnProjCSAndPName( OGRSpatialReference* pOgr, const char* pszProgCSName,
2021 : char **mappingTable )
2022 : {
2023 11897 : long ret = 0;
2024 11897 : OGR_SRSNode *poPROJCS = pOgr->GetAttrNode( "PROJCS" );
2025 106701 : for( int i = 0; mappingTable[i] != NULL; i += 3 )
2026 : {
2027 189817 : while( mappingTable[i] != NULL && EQUALN(pszProgCSName, mappingTable[i], strlen(mappingTable[i])) )
2028 : {
2029 : OGR_SRSNode *poParm;
2030 101 : const char* pszParamName = mappingTable[i+1];
2031 866 : for( int iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ )
2032 : {
2033 777 : poParm = poPROJCS->GetChild( iChild );
2034 :
2035 777 : if( EQUAL(poParm->GetValue(),"PARAMETER")
2036 : && poParm->GetChildCount() == 2
2037 : && EQUAL(poParm->GetChild(0)->GetValue(),pszParamName) )
2038 : {
2039 12 : poParm->GetChild(0)->SetValue( mappingTable[i+2] );
2040 12 : break;
2041 : }
2042 : }
2043 101 : ret ++;
2044 101 : i += 3;
2045 : }
2046 94858 : if (ret > 0)
2047 54 : break;
2048 : }
2049 11897 : return ret;
2050 : }
2051 :
2052 : /************************************************************************/
2053 : /* DeleteParamBasedOnPrjName */
2054 : /* */
2055 : /* Delete non-ESRI parameters */
2056 : /************************************************************************/
2057 11897 : int DeleteParamBasedOnPrjName( OGRSpatialReference* pOgr, const char* pszProjectionName,
2058 : char **mappingTable )
2059 : {
2060 11897 : long iIndex = -1, ret = -1;
2061 142764 : for( int i = 0; mappingTable[i] != NULL; i += 2 )
2062 : {
2063 130867 : if( EQUALN(pszProjectionName, mappingTable[i], strlen(mappingTable[i])) )
2064 : {
2065 259 : OGR_SRSNode *poPROJCS = pOgr->GetAttrNode( "PROJCS" );
2066 : OGR_SRSNode *poParm;
2067 259 : const char* pszParamName = mappingTable[i+1];
2068 259 : iIndex = -1;
2069 1970 : for( int iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ )
2070 : {
2071 1848 : poParm = poPROJCS->GetChild( iChild );
2072 :
2073 1848 : if( EQUAL(poParm->GetValue(),"PARAMETER")
2074 : && poParm->GetChildCount() == 2
2075 : && EQUAL(poParm->GetChild(0)->GetValue(),pszParamName) )
2076 : {
2077 137 : iIndex = iChild;
2078 137 : break;
2079 : }
2080 : }
2081 259 : if(iIndex >= 0)
2082 : {
2083 137 : poPROJCS->DestroyChild( iIndex );
2084 137 : ret ++;
2085 : }
2086 : }
2087 : }
2088 11897 : return ret;
2089 : }
2090 : /************************************************************************/
2091 : /* AddParamBasedOnPrjName() */
2092 : /* */
2093 : /* Add ESRI style parameters */
2094 : /************************************************************************/
2095 11897 : int AddParamBasedOnPrjName( OGRSpatialReference* pOgr, const char* pszProjectionName,
2096 : char **mappingTable )
2097 : {
2098 11897 : long ret = -1;
2099 11897 : OGR_SRSNode *poPROJCS = pOgr->GetAttrNode( "PROJCS" );
2100 35691 : for( int i = 0; mappingTable[i] != NULL; i += 3 )
2101 : {
2102 23794 : if( EQUALN(pszProjectionName, mappingTable[i], strlen(mappingTable[i])) )
2103 : {
2104 : OGR_SRSNode *poParm;
2105 113 : int exist = 0;
2106 1011 : for( int iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ )
2107 : {
2108 898 : poParm = poPROJCS->GetChild( iChild );
2109 :
2110 1344 : if( EQUAL(poParm->GetValue(),"PARAMETER")
2111 : && poParm->GetChildCount() == 2
2112 446 : && EQUAL(poParm->GetChild(0)->GetValue(),mappingTable[i+1]) )
2113 43 : exist = 1;
2114 : }
2115 113 : if(!exist)
2116 : {
2117 70 : poParm = new OGR_SRSNode( "PARAMETER" );
2118 140 : poParm->AddChild( new OGR_SRSNode( mappingTable[i+1] ) );
2119 140 : poParm->AddChild( new OGR_SRSNode( mappingTable[i+2] ) );
2120 70 : poPROJCS->AddChild( poParm );
2121 70 : ret ++;
2122 : }
2123 : }
2124 : }
2125 11897 : return ret;
2126 : }
2127 :
2128 : /************************************************************************/
2129 : /* RemapGeogCSName() */
2130 : /* */
2131 : /* Convert names to ESRI style */
2132 : /************************************************************************/
2133 11897 : int RemapGeogCSName( OGRSpatialReference* pOgr, const char *pszGeogCSName )
2134 : {
2135 : static const char *keyNamesG[] = {
2136 : "GEOGCS"};
2137 11897 : int ret = -1;
2138 :
2139 11897 : const char* pszUnitName = pOgr->GetAttrValue( "GEOGCS|UNIT");
2140 11897 : if(pszUnitName)
2141 11897 : ret = RemapNamesBasedOnTwo( pOgr, pszGeogCSName+4, pszUnitName, (char**)apszGcsNameMappingBasedOnUnit, 3, (char**)keyNamesG, 1);
2142 11897 : if(ret < 0)
2143 : {
2144 11839 : const char* pszPrimeName = pOgr->GetAttrValue("PRIMEM");
2145 11839 : if(pszPrimeName)
2146 11839 : ret = RemapNamesBasedOnTwo( pOgr, pszGeogCSName+4, pszPrimeName, (char**)apszGcsNameMappingBasedPrime, 3, (char**)keyNamesG, 1);
2147 11839 : if(ret < 0)
2148 11785 : ret = RemapNameBasedOnKeyName( pOgr, pszGeogCSName+4, "GEOGCS", (char**)apszGcsNameMapping);
2149 : }
2150 11897 : if(ret < 0)
2151 : {
2152 11489 : const char* pszProjCS = pOgr->GetAttrValue( "PROJCS" );
2153 11489 : ret = RemapNamesBasedOnTwo( pOgr, pszProjCS, pszGeogCSName, (char**)apszGcsNameMappingBasedOnProjCS, 3, (char**)keyNamesG, 1);
2154 : }
2155 11897 : return ret;
2156 : }
2157 :
2158 : /************************************************************************/
2159 : /* ImportFromESRIStatePlaneWKT() */
2160 : /* */
2161 : /* Search a ESRI State Plane WKT and import it. */
2162 : /************************************************************************/
2163 :
2164 488 : OGRErr OGRSpatialReference::ImportFromESRIStatePlaneWKT( int code, const char* datumName, const char* unitsName, int pcsCode, const char* csName )
2165 : {
2166 : int i;
2167 488 : long searchCode = -1;
2168 :
2169 : /* if the CS name is known */
2170 488 : if (code == 0 && !datumName && !unitsName && pcsCode == 32767 && csName)
2171 : {
2172 : char codeS[10];
2173 1 : if (FindCodeFromDict( "esri_StatePlane_extra.wkt", csName, codeS ) != OGRERR_NONE)
2174 0 : return OGRERR_FAILURE;
2175 1 : return importFromDict( "esri_StatePlane_extra.wkt", codeS);
2176 : }
2177 :
2178 : /* Find state plane prj str by pcs code only */
2179 970 : if( code == 0 && !datumName && pcsCode != 32767 )
2180 : {
2181 :
2182 483 : int unitCode = 1;
2183 483 : if( EQUAL(unitsName, "international_feet") )
2184 0 : unitCode = 3;
2185 483 : else if( strstr(unitsName, "feet") || strstr(unitsName, "foot") )
2186 2 : unitCode = 2;
2187 125935 : for(i=0; statePlanePcsCodeToZoneCode[i] != 0; i+=2)
2188 : {
2189 125453 : if( pcsCode == statePlanePcsCodeToZoneCode[i] )
2190 : {
2191 1 : searchCode = statePlanePcsCodeToZoneCode[i+1];
2192 1 : int unitIndex = searchCode % 10;
2193 1 : if( (unitCode == 1 && !(unitIndex == 0 || unitIndex == 1))
2194 : || (unitCode == 2 && !(unitIndex == 2 || unitIndex == 3 || unitIndex == 4 ))
2195 : || (unitCode == 3 && !(unitIndex == 5 || unitIndex == 6 )) )
2196 : {
2197 1 : searchCode -= unitIndex;
2198 1 : switch (unitIndex)
2199 : {
2200 : case 0:
2201 : case 3:
2202 : case 5:
2203 1 : if(unitCode == 2)
2204 1 : searchCode += 3;
2205 0 : else if(unitCode == 3)
2206 0 : searchCode += 5;
2207 1 : break;
2208 : case 1:
2209 : case 2:
2210 : case 6:
2211 0 : if(unitCode == 1)
2212 0 : searchCode += 1;
2213 0 : if(unitCode == 2)
2214 0 : searchCode += 2;
2215 0 : else if(unitCode == 3)
2216 0 : searchCode += 6;
2217 0 : break;
2218 : case 4:
2219 0 : if(unitCode == 2)
2220 0 : searchCode += 4;
2221 : break;
2222 : }
2223 : }
2224 1 : break;
2225 : }
2226 : }
2227 : }
2228 : else /* Find state plane prj str by all inputs. */
2229 : {
2230 : /* Need to have a specail EPSG-ESRI zone code mapping first. */
2231 480 : for(i=0; statePlaneZoneMapping[i] != 0; i+=3)
2232 : {
2233 476 : if( code == statePlaneZoneMapping[i]
2234 0 : && (statePlaneZoneMapping[i+1] == -1 || pcsCode == statePlaneZoneMapping[i+1]))
2235 : {
2236 0 : code = statePlaneZoneMapping[i+2];
2237 0 : break;
2238 : }
2239 : }
2240 4 : searchCode = (long)code * 10;
2241 4 : if(EQUAL(datumName, "HARN"))
2242 : {
2243 1 : if( EQUAL(unitsName, "international_feet") )
2244 1 : searchCode += 5;
2245 0 : else if( strstr(unitsName, "feet") || strstr(unitsName, "foot") )
2246 0 : searchCode += 3;
2247 : }
2248 6 : else if(strstr(datumName, "NAD") && strstr(datumName, "83"))
2249 : {
2250 3 : if( EQUAL(unitsName, "meters") )
2251 0 : searchCode += 1;
2252 3 : else if( EQUAL(unitsName, "international_feet") )
2253 0 : searchCode += 6;
2254 3 : else if( strstr(unitsName, "feet") || strstr(unitsName, "foot") )
2255 3 : searchCode += 2;
2256 : }
2257 0 : else if(strstr(datumName, "NAD") && strstr(datumName, "27") && !EQUAL(unitsName, "meters"))
2258 : {
2259 0 : searchCode += 4;
2260 : }
2261 : else
2262 0 : searchCode = -1;
2263 : }
2264 487 : if(searchCode > 0)
2265 : {
2266 : char codeS[10];
2267 5 : sprintf(codeS, "%d", (int)searchCode);
2268 5 : return importFromDict( "esri_StatePlane_extra.wkt", codeS);
2269 : }
2270 482 : return OGRERR_FAILURE;
2271 : }
2272 :
2273 : /************************************************************************/
2274 : /* ImportFromESRIWisconsinWKT() */
2275 : /* */
2276 : /* Search a ESRI State Plane WKT and import it. */
2277 : /************************************************************************/
2278 :
2279 0 : OGRErr OGRSpatialReference::ImportFromESRIWisconsinWKT( const char* prjName, double centralMeridian, double latOfOrigin, const char* unitsName, const char* csName )
2280 : {
2281 : /* if the CS name is known */
2282 0 : if (!prjName && !unitsName && csName)
2283 : {
2284 : char codeS[10];
2285 0 : if (FindCodeFromDict( "esri_Wisconsin_extra.wkt", csName, codeS ) != OGRERR_NONE)
2286 0 : return OGRERR_FAILURE;
2287 0 : return importFromDict( "esri_Wisconsin_extra.wkt", codeS);
2288 : }
2289 : double* tableWISCRS;
2290 0 : if(EQUALN(prjName, "Lambert_Conformal_Conic", 22))
2291 0 : tableWISCRS = apszWISCRS_LCC_meter;
2292 0 : else if(EQUAL(prjName, SRS_PT_TRANSVERSE_MERCATOR))
2293 0 : tableWISCRS = apszWISCRS_TM_meter;
2294 : else
2295 0 : return OGRERR_FAILURE;
2296 0 : int k = -1;
2297 0 : for(int i=0; tableWISCRS[i] != 0; i+=3)
2298 : {
2299 0 : if( fabs(centralMeridian - tableWISCRS[i]) <= 0.0000000001 && fabs(latOfOrigin - tableWISCRS[i+1]) <= 0.0000000001)
2300 : {
2301 0 : k = (long)tableWISCRS[i+2];
2302 0 : break;
2303 : }
2304 : }
2305 0 : if(k > 0)
2306 : {
2307 0 : if(!EQUAL(unitsName, "meters"))
2308 0 : k += 100;
2309 : char codeS[10];
2310 0 : sprintf(codeS, "%d", k);
2311 0 : return importFromDict( "esri_Wisconsin_extra.wkt", codeS);
2312 : }
2313 0 : return OGRERR_FAILURE;
2314 : }
2315 :
2316 : /************************************************************************/
2317 : /* FindCodeFromDict() */
2318 : /* */
2319 : /* Find the code from a dict file. */
2320 : /************************************************************************/
2321 1 : static int FindCodeFromDict( const char* pszDictFile, const char* CSName, char* code )
2322 : {
2323 : const char *pszFilename;
2324 : FILE *fp;
2325 1 : OGRErr eErr = OGRERR_UNSUPPORTED_SRS;
2326 :
2327 : /* -------------------------------------------------------------------- */
2328 : /* Find and open file. */
2329 : /* -------------------------------------------------------------------- */
2330 1 : pszFilename = CPLFindFile( "gdal", pszDictFile );
2331 1 : if( pszFilename == NULL )
2332 0 : return OGRERR_UNSUPPORTED_SRS;
2333 :
2334 1 : fp = VSIFOpen( pszFilename, "rb" );
2335 1 : if( fp == NULL )
2336 0 : return OGRERR_UNSUPPORTED_SRS;
2337 :
2338 : /* -------------------------------------------------------------------- */
2339 : /* Process lines. */
2340 : /* -------------------------------------------------------------------- */
2341 : const char *pszLine;
2342 :
2343 399 : while( (pszLine = CPLReadLine(fp)) != NULL )
2344 :
2345 : {
2346 398 : if( pszLine[0] == '#' )
2347 : /* do nothing */;
2348 :
2349 398 : else if( strstr(pszLine,CSName) )
2350 : {
2351 1 : const char* pComma = strchr(pszLine, ',');
2352 1 : if( pComma )
2353 : {
2354 1 : strncpy( code, pszLine, pComma - pszLine);
2355 1 : code[pComma - pszLine] = '\0';
2356 1 : eErr = OGRERR_NONE;
2357 : }
2358 1 : break;
2359 : }
2360 : }
2361 :
2362 : /* -------------------------------------------------------------------- */
2363 : /* Cleanup */
2364 : /* -------------------------------------------------------------------- */
2365 1 : VSIFClose( fp );
2366 :
2367 1 : return eErr;
2368 : }
|