1 : /******************************************************************************
2 : * $Id: ogr_srs_esri.cpp 18024 2009-11-14 18:22:05Z rouault $
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 18024 2009-11-14 18:22:05Z rouault $");
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 const char *apszProjMapping[] = {
59 : "Albers", SRS_PT_ALBERS_CONIC_EQUAL_AREA,
60 : "Cassini", SRS_PT_CASSINI_SOLDNER,
61 : "Equidistant_Cylindrical", SRS_PT_EQUIRECTANGULAR,
62 : "Plate_Carree", SRS_PT_EQUIRECTANGULAR,
63 : "Hotine_Oblique_Mercator_Azimuth_Natural_Origin",
64 : SRS_PT_HOTINE_OBLIQUE_MERCATOR,
65 : "Hotine_Oblique_Mercator_Azimuth_Center",
66 : SRS_PT_HOTINE_OBLIQUE_MERCATOR,
67 : "Lambert_Conformal_Conic", SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP,
68 : "Lambert_Conformal_Conic", SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP,
69 : "Van_der_Grinten_I", SRS_PT_VANDERGRINTEN,
70 : SRS_PT_TRANSVERSE_MERCATOR, SRS_PT_TRANSVERSE_MERCATOR,
71 : "Gauss_Kruger", SRS_PT_TRANSVERSE_MERCATOR,
72 : "Mercator", SRS_PT_MERCATOR_1SP,
73 : NULL, NULL };
74 :
75 : static const char *apszAlbersMapping[] = {
76 : SRS_PP_CENTRAL_MERIDIAN, SRS_PP_LONGITUDE_OF_CENTER,
77 : SRS_PP_LATITUDE_OF_ORIGIN, SRS_PP_LATITUDE_OF_CENTER,
78 : "Central_Parallel", SRS_PP_LATITUDE_OF_CENTER,
79 : NULL, NULL };
80 :
81 : static const char *apszECMapping[] = {
82 : SRS_PP_CENTRAL_MERIDIAN, SRS_PP_LONGITUDE_OF_CENTER,
83 : SRS_PP_LATITUDE_OF_ORIGIN, SRS_PP_LATITUDE_OF_CENTER,
84 : NULL, NULL };
85 :
86 : static const char *apszMercatorMapping[] = {
87 : SRS_PP_STANDARD_PARALLEL_1, SRS_PP_LATITUDE_OF_ORIGIN,
88 : NULL, NULL };
89 :
90 : static const char *apszPolarStereographicMapping[] = {
91 : SRS_PP_STANDARD_PARALLEL_1, SRS_PP_LATITUDE_OF_ORIGIN,
92 : NULL, NULL };
93 :
94 : static char **papszDatumMapping = NULL;
95 :
96 : static const char *apszDefaultDatumMapping[] = {
97 : "6267", "North_American_1927", SRS_DN_NAD27,
98 : "6269", "North_American_1983", SRS_DN_NAD83,
99 : NULL, NULL, NULL };
100 :
101 : static const char *apszUnitMapping[] = {
102 : "Meter", "meter",
103 : "Meter", "metre",
104 : "Foot", "foot",
105 : "Foot", "feet",
106 : "Foot", "international_feet",
107 : "Foot_US", SRS_UL_US_FOOT,
108 : "Foot_Clarke", "clarke_feet",
109 : "Degree", "degree",
110 : "Degree", "degrees",
111 : "Degree", SRS_UA_DEGREE,
112 : "Radian", SRS_UA_RADIAN,
113 : NULL, NULL };
114 :
115 : /* -------------------------------------------------------------------- */
116 : /* Table relating USGS and ESRI state plane zones. */
117 : /* -------------------------------------------------------------------- */
118 : static const int anUsgsEsriZones[] =
119 : {
120 : 101, 3101,
121 : 102, 3126,
122 : 201, 3151,
123 : 202, 3176,
124 : 203, 3201,
125 : 301, 3226,
126 : 302, 3251,
127 : 401, 3276,
128 : 402, 3301,
129 : 403, 3326,
130 : 404, 3351,
131 : 405, 3376,
132 : 406, 3401,
133 : 407, 3426,
134 : 501, 3451,
135 : 502, 3476,
136 : 503, 3501,
137 : 600, 3526,
138 : 700, 3551,
139 : 901, 3601,
140 : 902, 3626,
141 : 903, 3576,
142 : 1001, 3651,
143 : 1002, 3676,
144 : 1101, 3701,
145 : 1102, 3726,
146 : 1103, 3751,
147 : 1201, 3776,
148 : 1202, 3801,
149 : 1301, 3826,
150 : 1302, 3851,
151 : 1401, 3876,
152 : 1402, 3901,
153 : 1501, 3926,
154 : 1502, 3951,
155 : 1601, 3976,
156 : 1602, 4001,
157 : 1701, 4026,
158 : 1702, 4051,
159 : 1703, 6426,
160 : 1801, 4076,
161 : 1802, 4101,
162 : 1900, 4126,
163 : 2001, 4151,
164 : 2002, 4176,
165 : 2101, 4201,
166 : 2102, 4226,
167 : 2103, 4251,
168 : 2111, 6351,
169 : 2112, 6376,
170 : 2113, 6401,
171 : 2201, 4276,
172 : 2202, 4301,
173 : 2203, 4326,
174 : 2301, 4351,
175 : 2302, 4376,
176 : 2401, 4401,
177 : 2402, 4426,
178 : 2403, 4451,
179 : 2500, 0,
180 : 2501, 4476,
181 : 2502, 4501,
182 : 2503, 4526,
183 : 2600, 0,
184 : 2601, 4551,
185 : 2602, 4576,
186 : 2701, 4601,
187 : 2702, 4626,
188 : 2703, 4651,
189 : 2800, 4676,
190 : 2900, 4701,
191 : 3001, 4726,
192 : 3002, 4751,
193 : 3003, 4776,
194 : 3101, 4801,
195 : 3102, 4826,
196 : 3103, 4851,
197 : 3104, 4876,
198 : 3200, 4901,
199 : 3301, 4926,
200 : 3302, 4951,
201 : 3401, 4976,
202 : 3402, 5001,
203 : 3501, 5026,
204 : 3502, 5051,
205 : 3601, 5076,
206 : 3602, 5101,
207 : 3701, 5126,
208 : 3702, 5151,
209 : 3800, 5176,
210 : 3900, 0,
211 : 3901, 5201,
212 : 3902, 5226,
213 : 4001, 5251,
214 : 4002, 5276,
215 : 4100, 5301,
216 : 4201, 5326,
217 : 4202, 5351,
218 : 4203, 5376,
219 : 4204, 5401,
220 : 4205, 5426,
221 : 4301, 5451,
222 : 4302, 5476,
223 : 4303, 5501,
224 : 4400, 5526,
225 : 4501, 5551,
226 : 4502, 5576,
227 : 4601, 5601,
228 : 4602, 5626,
229 : 4701, 5651,
230 : 4702, 5676,
231 : 4801, 5701,
232 : 4802, 5726,
233 : 4803, 5751,
234 : 4901, 5776,
235 : 4902, 5801,
236 : 4903, 5826,
237 : 4904, 5851,
238 : 5001, 6101,
239 : 5002, 6126,
240 : 5003, 6151,
241 : 5004, 6176,
242 : 5005, 6201,
243 : 5006, 6226,
244 : 5007, 6251,
245 : 5008, 6276,
246 : 5009, 6301,
247 : 5010, 6326,
248 : 5101, 5876,
249 : 5102, 5901,
250 : 5103, 5926,
251 : 5104, 5951,
252 : 5105, 5976,
253 : 5201, 6001,
254 : 5200, 6026,
255 : 5200, 6076,
256 : 5201, 6051,
257 : 5202, 6051,
258 : 5300, 0,
259 : 5400, 0
260 : };
261 :
262 : void OGREPSGDatumNameMassage( char ** ppszDatum );
263 :
264 : /************************************************************************/
265 : /* RemapSpheroidName() */
266 : /* */
267 : /* Convert Spheroid name to ESRI style name */
268 : /************************************************************************/
269 :
270 110 : static const char* RemapSpheroidName(const char* pszName)
271 : {
272 110 : if (strcmp(pszName, "WGS 84") == 0)
273 51 : return "WGS 1984";
274 :
275 59 : if (strcmp(pszName, "WGS 72") == 0)
276 0 : return "WGS 1972";
277 :
278 59 : return pszName;
279 : }
280 :
281 : /************************************************************************/
282 : /* ESRIToUSGSZone() */
283 : /* */
284 : /* Convert ESRI style state plane zones to USGS style state */
285 : /* plane zones. */
286 : /************************************************************************/
287 :
288 0 : static int ESRIToUSGSZone( int nESRIZone )
289 :
290 : {
291 0 : int nPairs = sizeof(anUsgsEsriZones) / (2*sizeof(int));
292 : int i;
293 :
294 0 : for( i = 0; i < nPairs; i++ )
295 : {
296 0 : if( anUsgsEsriZones[i*2+1] == nESRIZone )
297 0 : return anUsgsEsriZones[i*2];
298 : }
299 :
300 0 : return 0;
301 : }
302 :
303 : /************************************************************************/
304 : /* MorphNameToESRI() */
305 : /* */
306 : /* Make name ESRI compatible. Convert spaces and special */
307 : /* characters to underscores and then strip down. */
308 : /************************************************************************/
309 :
310 171 : static void MorphNameToESRI( char ** ppszName )
311 :
312 : {
313 : int i, j;
314 171 : char *pszName = *ppszName;
315 :
316 171 : if (pszName[0] == '\0')
317 0 : return;
318 :
319 : /* -------------------------------------------------------------------- */
320 : /* Translate non-alphanumeric values to underscores. */
321 : /* -------------------------------------------------------------------- */
322 2573 : for( i = 0; pszName[i] != '\0'; i++ )
323 : {
324 10488 : if( pszName[i] != '+'
325 3828 : && !(pszName[i] >= 'A' && pszName[i] <= 'Z')
326 2532 : && !(pszName[i] >= 'a' && pszName[i] <= 'z')
327 1726 : && !(pszName[i] >= '0' && pszName[i] <= '9') )
328 : {
329 388 : pszName[i] = '_';
330 : }
331 : }
332 :
333 : /* -------------------------------------------------------------------- */
334 : /* Remove repeated and trailing underscores. */
335 : /* -------------------------------------------------------------------- */
336 2402 : for( i = 1, j = 0; pszName[i] != '\0'; i++ )
337 : {
338 2231 : if( pszName[j] == '_' && pszName[i] == '_' )
339 92 : continue;
340 :
341 2139 : pszName[++j] = pszName[i];
342 : }
343 171 : if( pszName[j] == '_' )
344 0 : pszName[j] = '\0';
345 : else
346 171 : pszName[j+1] = '\0';
347 : }
348 :
349 : /************************************************************************/
350 : /* CleanESRIDatumMappingTable() */
351 : /************************************************************************/
352 :
353 : CPL_C_START
354 617 : void CleanupESRIDatumMappingTable()
355 :
356 : {
357 617 : if( papszDatumMapping == NULL )
358 574 : return;
359 :
360 43 : if( papszDatumMapping != (char **) apszDefaultDatumMapping )
361 : {
362 43 : CSLDestroy( papszDatumMapping );
363 43 : papszDatumMapping = NULL;
364 : }
365 : }
366 : CPL_C_END
367 :
368 : /************************************************************************/
369 : /* InitDatumMappingTable() */
370 : /************************************************************************/
371 :
372 562 : static void InitDatumMappingTable()
373 :
374 : {
375 562 : if( papszDatumMapping != NULL )
376 517 : return;
377 :
378 : /* -------------------------------------------------------------------- */
379 : /* Try to open the datum.csv file. */
380 : /* -------------------------------------------------------------------- */
381 45 : const char *pszFilename = CSVFilename("gdal_datum.csv");
382 45 : FILE * fp = VSIFOpen( pszFilename, "rb" );
383 :
384 : /* -------------------------------------------------------------------- */
385 : /* Use simple default set if we can't find the file. */
386 : /* -------------------------------------------------------------------- */
387 45 : if( fp == NULL )
388 : {
389 0 : papszDatumMapping = (char **)apszDefaultDatumMapping;
390 0 : return;
391 : }
392 :
393 : /* -------------------------------------------------------------------- */
394 : /* Figure out what fields we are interested in. */
395 : /* -------------------------------------------------------------------- */
396 45 : char **papszFieldNames = CSVReadParseLine( fp );
397 45 : int nDatumCodeField = CSLFindString( papszFieldNames, "DATUM_CODE" );
398 45 : int nEPSGNameField = CSLFindString( papszFieldNames, "DATUM_NAME" );
399 45 : int nESRINameField = CSLFindString( papszFieldNames, "ESRI_DATUM_NAME" );
400 :
401 45 : CSLDestroy( papszFieldNames );
402 :
403 45 : if( nDatumCodeField == -1 || nEPSGNameField == -1 || nESRINameField == -1 )
404 : {
405 : CPLError( CE_Failure, CPLE_AppDefined,
406 0 : "Failed to find required field in gdal_datum.csv in InitDatumMappingTable(), using default table setup." );
407 :
408 0 : papszDatumMapping = (char **)apszDefaultDatumMapping;
409 0 : return;
410 : }
411 :
412 : /* -------------------------------------------------------------------- */
413 : /* Read each line, adding a detail line for each. */
414 : /* -------------------------------------------------------------------- */
415 45 : int nMappingCount = 0;
416 45 : const int nMaxDatumMappings = 1000;
417 : char **papszFields;
418 45 : papszDatumMapping = (char **)CPLCalloc(sizeof(char*),nMaxDatumMappings*3);
419 :
420 25695 : for( papszFields = CSVReadParseLine( fp );
421 : papszFields != NULL;
422 : papszFields = CSVReadParseLine( fp ) )
423 : {
424 25650 : int nFieldCount = CSLCount(papszFields);
425 :
426 : CPLAssert( nMappingCount+1 < nMaxDatumMappings );
427 :
428 25650 : if( MAX(nEPSGNameField,MAX(nDatumCodeField,nESRINameField))
429 : < nFieldCount
430 : && nMaxDatumMappings > nMappingCount+1 )
431 : {
432 25650 : papszDatumMapping[nMappingCount*3+0] =
433 25650 : CPLStrdup( papszFields[nDatumCodeField] );
434 25650 : papszDatumMapping[nMappingCount*3+1] =
435 25650 : CPLStrdup( papszFields[nESRINameField] );
436 25650 : papszDatumMapping[nMappingCount*3+2] =
437 25650 : CPLStrdup( papszFields[nEPSGNameField] );
438 25650 : OGREPSGDatumNameMassage( &(papszDatumMapping[nMappingCount*3+2]) );
439 :
440 25650 : nMappingCount++;
441 : }
442 25650 : CSLDestroy( papszFields );
443 : }
444 :
445 45 : VSIFClose( fp );
446 :
447 45 : papszDatumMapping[nMappingCount*3+0] = NULL;
448 45 : papszDatumMapping[nMappingCount*3+1] = NULL;
449 45 : papszDatumMapping[nMappingCount*3+2] = NULL;
450 : }
451 :
452 :
453 : /************************************************************************/
454 : /* OSRImportFromESRI() */
455 : /************************************************************************/
456 :
457 : /**
458 : * \brief Import coordinate system from ESRI .prj format(s).
459 : *
460 : * This function is the same as the C++ method OGRSpatialReference::importFromESRI()
461 : */
462 5 : OGRErr OSRImportFromESRI( OGRSpatialReferenceH hSRS, char **papszPrj )
463 :
464 : {
465 5 : VALIDATE_POINTER1( hSRS, "OSRImportFromESRI", CE_Failure );
466 :
467 5 : return ((OGRSpatialReference *) hSRS)->importFromESRI( papszPrj );
468 : }
469 :
470 : /************************************************************************/
471 : /* OSR_GDV() */
472 : /* */
473 : /* Fetch a particular parameter out of the parameter list, or */
474 : /* the indicated default if it isn't available. This is a */
475 : /* helper function for importFromESRI(). */
476 : /************************************************************************/
477 :
478 55 : static double OSR_GDV( char **papszNV, const char * pszField,
479 : double dfDefaultValue )
480 :
481 : {
482 : int iLine;
483 :
484 55 : if( papszNV == NULL || papszNV[0] == NULL )
485 0 : return dfDefaultValue;
486 :
487 55 : if( EQUALN(pszField,"PARAM_",6) )
488 : {
489 : int nOffset;
490 :
491 493 : for( iLine = 0;
492 464 : papszNV[iLine] != NULL && !EQUALN(papszNV[iLine],"Paramet",7);
493 : iLine++ ) {}
494 :
495 256 : for( nOffset=atoi(pszField+6);
496 128 : papszNV[iLine] != NULL && nOffset > 0;
497 : iLine++ )
498 : {
499 99 : if( strlen(papszNV[iLine]) > 0 )
500 99 : nOffset--;
501 : }
502 :
503 58 : while( papszNV[iLine] != NULL && strlen(papszNV[iLine]) == 0 )
504 0 : iLine++;
505 :
506 29 : if( papszNV[iLine] != NULL )
507 : {
508 29 : char **papszTokens, *pszLine = papszNV[iLine];
509 : double dfValue;
510 :
511 : int i;
512 :
513 : // Trim comments.
514 2060 : for( i=0; pszLine[i] != '\0'; i++ )
515 : {
516 2031 : if( pszLine[i] == '/' && pszLine[i+1] == '*' )
517 29 : pszLine[i] = '\0';
518 : }
519 :
520 29 : papszTokens = CSLTokenizeString(papszNV[iLine]);
521 29 : if( CSLCount(papszTokens) == 3 )
522 : {
523 36 : dfValue = ABS(atof(papszTokens[0]))
524 18 : + atof(papszTokens[1]) / 60.0
525 54 : + atof(papszTokens[2]) / 3600.0;
526 :
527 18 : if( atof(papszTokens[0]) < 0.0 )
528 5 : dfValue *= -1;
529 : }
530 11 : else if( CSLCount(papszTokens) > 0 )
531 11 : dfValue = atof(papszTokens[0]);
532 : else
533 0 : dfValue = dfDefaultValue;
534 :
535 29 : CSLDestroy( papszTokens );
536 :
537 29 : return dfValue;
538 : }
539 : else
540 0 : return dfDefaultValue;
541 : }
542 : else
543 : {
544 244 : for( iLine = 0;
545 111 : papszNV[iLine] != NULL &&
546 107 : !EQUALN(papszNV[iLine],pszField,strlen(pszField));
547 : iLine++ ) {}
548 :
549 26 : if( papszNV[iLine] == NULL )
550 4 : return dfDefaultValue;
551 : else
552 22 : return atof( papszNV[iLine] + strlen(pszField) );
553 : }
554 : }
555 :
556 : /************************************************************************/
557 : /* OSR_GDS() */
558 : /************************************************************************/
559 :
560 45 : static CPLString OSR_GDS( char **papszNV, const char * pszField,
561 : const char *pszDefaultValue )
562 :
563 : {
564 : int iLine;
565 :
566 45 : if( papszNV == NULL || papszNV[0] == NULL )
567 0 : return pszDefaultValue;
568 :
569 287 : for( iLine = 0;
570 121 : papszNV[iLine] != NULL &&
571 121 : !EQUALN(papszNV[iLine],pszField,strlen(pszField));
572 : iLine++ ) {}
573 :
574 45 : if( papszNV[iLine] == NULL )
575 0 : return pszDefaultValue;
576 : else
577 : {
578 45 : CPLString osResult;
579 : char **papszTokens;
580 :
581 45 : papszTokens = CSLTokenizeString(papszNV[iLine]);
582 :
583 45 : if( CSLCount(papszTokens) > 1 )
584 45 : osResult = papszTokens[1];
585 : else
586 0 : osResult = pszDefaultValue;
587 :
588 45 : CSLDestroy( papszTokens );
589 45 : return osResult;
590 : }
591 : }
592 :
593 : /************************************************************************/
594 : /* importFromESRI() */
595 : /************************************************************************/
596 :
597 : /**
598 : * \brief Import coordinate system from ESRI .prj format(s).
599 : *
600 : * This function will read the text loaded from an ESRI .prj file, and
601 : * translate it into an OGRSpatialReference definition. This should support
602 : * many (but by no means all) old style (Arc/Info 7.x) .prj files, as well
603 : * as the newer pseudo-OGC WKT .prj files. Note that new style .prj files
604 : * are in OGC WKT format, but require some manipulation to correct datum
605 : * names, and units on some projection parameters. This is addressed within
606 : * importFromESRI() by an automatical call to morphFromESRI().
607 : *
608 : * Currently only GEOGRAPHIC, UTM, STATEPLANE, GREATBRITIAN_GRID, ALBERS,
609 : * EQUIDISTANT_CONIC, and TRANSVERSE (mercator) projections are supported
610 : * from old style files.
611 : *
612 : * At this time there is no equivelent exportToESRI() method. Writing old
613 : * style .prj files is not supported by OGRSpatialReference. However the
614 : * morphToESRI() and exportToWkt() methods can be used to generate output
615 : * suitable to write to new style (Arc 8) .prj files.
616 : *
617 : * This function is the equilvelent of the C function OSRImportFromESRI().
618 : *
619 : * @param papszPrj NULL terminated list of strings containing the definition.
620 : *
621 : * @return OGRERR_NONE on success or an error code in case of failure.
622 : */
623 :
624 154 : OGRErr OGRSpatialReference::importFromESRI( char **papszPrj )
625 :
626 : {
627 154 : if( papszPrj == NULL || papszPrj[0] == NULL )
628 0 : return OGRERR_CORRUPT_DATA;
629 :
630 : /* -------------------------------------------------------------------- */
631 : /* ArcGIS and related products now use a varient of Well Known */
632 : /* Text. Try to recognise this and ingest it. WKT is usually */
633 : /* all on one line, but we will accept multi-line formats and */
634 : /* concatenate. */
635 : /* -------------------------------------------------------------------- */
636 292 : if( EQUALN(papszPrj[0],"GEOGCS",6)
637 123 : || EQUALN(papszPrj[0],"PROJCS",6)
638 15 : || EQUALN(papszPrj[0],"LOCAL_CS",8) )
639 : {
640 : char *pszWKT, *pszWKT2;
641 : OGRErr eErr;
642 : int i;
643 :
644 139 : pszWKT = CPLStrdup(papszPrj[0]);
645 139 : for( i = 1; papszPrj[i] != NULL; i++ )
646 : {
647 : pszWKT = (char *)
648 0 : CPLRealloc(pszWKT,strlen(pszWKT)+strlen(papszPrj[i])+1);
649 0 : strcat( pszWKT, papszPrj[i] );
650 : }
651 139 : pszWKT2 = pszWKT;
652 139 : eErr = importFromWkt( &pszWKT2 );
653 139 : CPLFree( pszWKT );
654 :
655 139 : if( eErr == OGRERR_NONE )
656 139 : eErr = morphFromESRI();
657 139 : return eErr;
658 : }
659 :
660 : /* -------------------------------------------------------------------- */
661 : /* Operate on the basis of the projection name. */
662 : /* -------------------------------------------------------------------- */
663 15 : CPLString osProj = OSR_GDS( papszPrj, "Projection", "" );
664 :
665 15 : if( EQUAL(osProj,"") )
666 : {
667 0 : CPLDebug( "OGR_ESRI", "Can't find Projection\n" );
668 0 : return OGRERR_CORRUPT_DATA;
669 : }
670 :
671 15 : else if( EQUAL(osProj,"GEOGRAPHIC") )
672 : {
673 : }
674 :
675 15 : else if( EQUAL(osProj,"utm") )
676 : {
677 6 : if( (int) OSR_GDV( papszPrj, "zone", 0.0 ) != 0 )
678 : {
679 6 : double dfYShift = OSR_GDV( papszPrj, "Yshift", 0.0 );
680 :
681 : SetUTM( (int) OSR_GDV( papszPrj, "zone", 0.0 ),
682 6 : dfYShift == 0.0 );
683 : }
684 : else
685 : {
686 : double dfCentralMeridian, dfRefLat;
687 : int nZone;
688 :
689 0 : dfCentralMeridian = OSR_GDV( papszPrj, "PARAM_1", 0.0 );
690 0 : dfRefLat = OSR_GDV( papszPrj, "PARAM_2", 0.0 );
691 :
692 0 : nZone = (int) ((dfCentralMeridian+183) / 6.0 + 0.0000001);
693 0 : SetUTM( nZone, dfRefLat >= 0.0 );
694 : }
695 : }
696 :
697 9 : else if( EQUAL(osProj,"STATEPLANE") )
698 : {
699 4 : int nZone = (int) OSR_GDV( papszPrj, "zone", 0.0 );
700 4 : if( nZone != 0 )
701 0 : nZone = ESRIToUSGSZone( nZone );
702 : else
703 4 : nZone = (int) OSR_GDV( papszPrj, "fipszone", 0.0 );
704 :
705 4 : if( nZone != 0 )
706 : {
707 4 : if( EQUAL(OSR_GDS( papszPrj, "Datum", "NAD83"),"NAD27") )
708 0 : SetStatePlane( nZone, FALSE );
709 : else
710 4 : SetStatePlane( nZone, TRUE );
711 : }
712 : }
713 :
714 5 : else if( EQUAL(osProj,"GREATBRITIAN_GRID")
715 : || EQUAL(osProj,"GREATBRITAIN_GRID") )
716 : {
717 : const char *pszWkt =
718 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]]";
719 :
720 0 : importFromWkt( (char **) &pszWkt );
721 : }
722 :
723 5 : else if( EQUAL(osProj,"ALBERS") )
724 : {
725 : SetACEA( OSR_GDV( papszPrj, "PARAM_1", 0.0 ),
726 : OSR_GDV( papszPrj, "PARAM_2", 0.0 ),
727 : OSR_GDV( papszPrj, "PARAM_4", 0.0 ),
728 : OSR_GDV( papszPrj, "PARAM_3", 0.0 ),
729 : OSR_GDV( papszPrj, "PARAM_5", 0.0 ),
730 4 : OSR_GDV( papszPrj, "PARAM_6", 0.0 ) );
731 : }
732 :
733 1 : else if( EQUAL(osProj,"LAMBERT") )
734 : {
735 : SetLCC( OSR_GDV( papszPrj, "PARAM_1", 0.0 ),
736 : OSR_GDV( papszPrj, "PARAM_2", 0.0 ),
737 : OSR_GDV( papszPrj, "PARAM_4", 0.0 ),
738 : OSR_GDV( papszPrj, "PARAM_3", 0.0 ),
739 : OSR_GDV( papszPrj, "PARAM_5", 0.0 ),
740 0 : OSR_GDV( papszPrj, "PARAM_6", 0.0 ) );
741 : }
742 :
743 1 : else if( EQUAL(osProj,"EQUIDISTANT_CONIC") )
744 : {
745 0 : int nStdPCount = (int) OSR_GDV( papszPrj, "PARAM_1", 0.0 );
746 :
747 0 : if( nStdPCount == 1 )
748 : {
749 : SetEC( OSR_GDV( papszPrj, "PARAM_2", 0.0 ),
750 : OSR_GDV( papszPrj, "PARAM_2", 0.0 ),
751 : OSR_GDV( papszPrj, "PARAM_4", 0.0 ),
752 : OSR_GDV( papszPrj, "PARAM_3", 0.0 ),
753 : OSR_GDV( papszPrj, "PARAM_5", 0.0 ),
754 0 : OSR_GDV( papszPrj, "PARAM_6", 0.0 ) );
755 : }
756 : else
757 : {
758 : SetEC( OSR_GDV( papszPrj, "PARAM_2", 0.0 ),
759 : OSR_GDV( papszPrj, "PARAM_3", 0.0 ),
760 : OSR_GDV( papszPrj, "PARAM_5", 0.0 ),
761 : OSR_GDV( papszPrj, "PARAM_4", 0.0 ),
762 : OSR_GDV( papszPrj, "PARAM_5", 0.0 ),
763 0 : OSR_GDV( papszPrj, "PARAM_7", 0.0 ) );
764 : }
765 : }
766 :
767 1 : else if( EQUAL(osProj,"TRANSVERSE") )
768 : {
769 : SetTM( OSR_GDV( papszPrj, "PARAM_3", 0.0 ),
770 : OSR_GDV( papszPrj, "PARAM_2", 0.0 ),
771 : OSR_GDV( papszPrj, "PARAM_1", 0.0 ),
772 : OSR_GDV( papszPrj, "PARAM_4", 0.0 ),
773 1 : OSR_GDV( papszPrj, "PARAM_5", 0.0 ) );
774 : }
775 :
776 0 : else if( EQUAL(osProj,"POLAR") )
777 : {
778 : SetPS( OSR_GDV( papszPrj, "PARAM_2", 0.0 ),
779 : OSR_GDV( papszPrj, "PARAM_1", 0.0 ),
780 : 1.0,
781 : OSR_GDV( papszPrj, "PARAM_3", 0.0 ),
782 0 : OSR_GDV( papszPrj, "PARAM_4", 0.0 ) );
783 : }
784 :
785 : else
786 : {
787 0 : CPLDebug( "OGR_ESRI", "Unsupported projection: %s", osProj.c_str() );
788 0 : SetLocalCS( osProj );
789 : }
790 :
791 : /* -------------------------------------------------------------------- */
792 : /* Try to translate the datum/spheroid. */
793 : /* -------------------------------------------------------------------- */
794 15 : if( !IsLocal() && GetAttrNode( "GEOGCS" ) == NULL )
795 : {
796 11 : CPLString osDatum;
797 :
798 11 : osDatum = OSR_GDS( papszPrj, "Datum", "");
799 :
800 11 : if( EQUAL(osDatum,"NAD27") || EQUAL(osDatum,"NAD83")
801 : || EQUAL(osDatum,"WGS84") || EQUAL(osDatum,"WGS72") )
802 : {
803 6 : SetWellKnownGeogCS( osDatum );
804 : }
805 5 : else if( EQUAL( osDatum, "EUR" )
806 : || EQUAL( osDatum, "ED50" ) )
807 : {
808 0 : SetWellKnownGeogCS( "EPSG:4230" );
809 : }
810 5 : else if( EQUAL( osDatum, "GDA94" ) )
811 : {
812 5 : SetWellKnownGeogCS( "EPSG:4283" );
813 : }
814 : else
815 : {
816 0 : CPLString osSpheroid;
817 :
818 0 : osSpheroid = OSR_GDS( papszPrj, "Spheroid", "");
819 :
820 0 : if( EQUAL(osSpheroid,"INT1909")
821 : || EQUAL(osSpheroid,"INTERNATIONAL1909") )
822 : {
823 0 : OGRSpatialReference oGCS;
824 0 : oGCS.importFromEPSG( 4022 );
825 0 : CopyGeogCSFrom( &oGCS );
826 : }
827 0 : else if( EQUAL(osSpheroid,"AIRY") )
828 : {
829 0 : OGRSpatialReference oGCS;
830 0 : oGCS.importFromEPSG( 4001 );
831 0 : CopyGeogCSFrom( &oGCS );
832 : }
833 0 : else if( EQUAL(osSpheroid,"CLARKE1866") )
834 : {
835 0 : OGRSpatialReference oGCS;
836 0 : oGCS.importFromEPSG( 4008 );
837 0 : CopyGeogCSFrom( &oGCS );
838 : }
839 0 : else if( EQUAL(osSpheroid,"GRS80") )
840 : {
841 0 : OGRSpatialReference oGCS;
842 0 : oGCS.importFromEPSG( 4019 );
843 0 : CopyGeogCSFrom( &oGCS );
844 : }
845 0 : else if( EQUAL(osSpheroid,"KRASOVSKY")
846 : || EQUAL(osSpheroid,"KRASSOVSKY") )
847 : {
848 0 : OGRSpatialReference oGCS;
849 0 : oGCS.importFromEPSG( 4024 );
850 0 : CopyGeogCSFrom( &oGCS );
851 : }
852 0 : else if( EQUAL(osSpheroid,"Bessel") )
853 : {
854 0 : OGRSpatialReference oGCS;
855 0 : oGCS.importFromEPSG( 4004 );
856 0 : CopyGeogCSFrom( &oGCS );
857 : }
858 : else
859 : {
860 : // If we don't know, default to WGS84 so there is something there.
861 0 : SetWellKnownGeogCS( "WGS84" );
862 0 : }
863 11 : }
864 : }
865 :
866 : /* -------------------------------------------------------------------- */
867 : /* Linear units translation */
868 : /* -------------------------------------------------------------------- */
869 15 : if( IsLocal() || IsProjected() )
870 : {
871 15 : CPLString osValue;
872 15 : double dfOldUnits = GetLinearUnits();
873 :
874 15 : osValue = OSR_GDS( papszPrj, "Units", "" );
875 15 : if( EQUAL(osValue, "" ) )
876 0 : SetLinearUnitsAndUpdateParameters( SRS_UL_METER, 1.0 );
877 15 : else if( EQUAL(osValue,"FEET") )
878 2 : SetLinearUnitsAndUpdateParameters( SRS_UL_US_FOOT, atof(SRS_UL_US_FOOT_CONV) );
879 13 : else if( atof(osValue) != 0.0 )
880 : SetLinearUnitsAndUpdateParameters( "user-defined",
881 1 : 1.0 / atof(osValue) );
882 : else
883 12 : SetLinearUnitsAndUpdateParameters( osValue, 1.0 );
884 :
885 : // If we have reset the linear units we should clear any authority
886 : // nodes on the PROJCS. This especially applies to state plane
887 : // per bug 1697
888 15 : double dfNewUnits = GetLinearUnits();
889 15 : if( dfOldUnits != 0.0
890 : && (dfNewUnits / dfOldUnits < 0.9999999
891 : || dfNewUnits / dfOldUnits > 1.0000001) )
892 : {
893 3 : if( GetRoot()->FindChild( "AUTHORITY" ) != -1 )
894 3 : GetRoot()->DestroyChild(GetRoot()->FindChild( "AUTHORITY" ));
895 15 : }
896 : }
897 :
898 15 : return OGRERR_NONE;
899 : }
900 :
901 : /************************************************************************/
902 : /* morphToESRI() */
903 : /************************************************************************/
904 : /**
905 : * \brief Convert in place to ESRI WKT format.
906 : *
907 : * The value nodes of this coordinate system are modified in various manners
908 : * more closely map onto the ESRI concept of WKT format. This includes
909 : * renaming a variety of projections and arguments, and stripping out
910 : * nodes note recognised by ESRI (like AUTHORITY and AXIS).
911 : *
912 : * This does the same as the C function OSRMorphToESRI().
913 : *
914 : * @return OGRERR_NONE unless something goes badly wrong.
915 : */
916 :
917 110 : OGRErr OGRSpatialReference::morphToESRI()
918 :
919 : {
920 : OGRErr eErr;
921 :
922 110 : CPLLocaleC localeC;
923 : /* -------------------------------------------------------------------- */
924 : /* Fixup ordering, missing linear units, etc. */
925 : /* -------------------------------------------------------------------- */
926 110 : eErr = Fixup();
927 110 : if( eErr != OGRERR_NONE )
928 0 : return eErr;
929 :
930 : /* -------------------------------------------------------------------- */
931 : /* Strip all CT parameters (AXIS, AUTHORITY, TOWGS84, etc). */
932 : /* -------------------------------------------------------------------- */
933 110 : eErr = StripCTParms();
934 110 : if( eErr != OGRERR_NONE )
935 0 : return eErr;
936 :
937 110 : if( GetRoot() == NULL )
938 0 : return OGRERR_NONE;
939 :
940 : /* -------------------------------------------------------------------- */
941 : /* There is a special case for Hotine Oblique Mercator to split */
942 : /* out the case with an angle to rectified grid. Bug 423 */
943 : /* -------------------------------------------------------------------- */
944 110 : const char *pszProjection = GetAttrValue("PROJECTION");
945 :
946 110 : if( pszProjection != NULL
947 : && EQUAL(pszProjection,SRS_PT_HOTINE_OBLIQUE_MERCATOR)
948 : && fabs(GetProjParm(SRS_PP_AZIMUTH, 0.0 )-90) < 0.0001
949 : && fabs(GetProjParm(SRS_PP_RECTIFIED_GRID_ANGLE, 0.0 )-90) < 0.0001 )
950 : {
951 : SetNode( "PROJCS|PROJECTION",
952 1 : "Hotine_Oblique_Mercator_Azimuth_Center" );
953 :
954 : /* ideally we should strip out of the rectified_grid_angle */
955 : // strip off rectified_grid_angle -- I hope it is 90!
956 1 : OGR_SRSNode *poPROJCS = GetAttrNode( "PROJCS" );
957 1 : int iRGAChild = FindProjParm( "rectified_grid_angle", poPROJCS );
958 1 : if( iRGAChild != -1 )
959 1 : poPROJCS->DestroyChild( iRGAChild);
960 :
961 1 : pszProjection = GetAttrValue("PROJECTION");
962 : }
963 :
964 : /* -------------------------------------------------------------------- */
965 : /* Polar_Stereographic maps to ESRI codes */
966 : /* Stereographic_South_Pole or Stereographic_North_Pole based */
967 : /* on latitude. */
968 : /* -------------------------------------------------------------------- */
969 110 : if( pszProjection != NULL
970 : && ( EQUAL(pszProjection,SRS_PT_POLAR_STEREOGRAPHIC) ))
971 : {
972 1 : if( GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) < 0.0 )
973 : {
974 : SetNode( "PROJCS|PROJECTION",
975 1 : "Stereographic_South_Pole" );
976 1 : pszProjection = GetAttrValue("PROJECTION");
977 : }
978 : else
979 : {
980 : SetNode( "PROJCS|PROJECTION",
981 0 : "Stereographic_North_Pole" );
982 0 : pszProjection = GetAttrValue("PROJECTION");
983 : }
984 : }
985 :
986 : /* -------------------------------------------------------------------- */
987 : /* OBLIQUE_STEREOGRAPHIC maps to ESRI Stereographic */
988 : /* -------------------------------------------------------------------- */
989 110 : if( pszProjection != NULL
990 : && ( EQUAL(pszProjection,SRS_PT_OBLIQUE_STEREOGRAPHIC) ))
991 : {
992 0 : SetNode( "PROJCS|PROJECTION", "Stereographic" );
993 : }
994 :
995 : /* -------------------------------------------------------------------- */
996 : /* Translate PROJECTION keywords that are misnamed. */
997 : /* -------------------------------------------------------------------- */
998 : GetRoot()->applyRemapper( "PROJECTION",
999 : (char **)apszProjMapping+1,
1000 110 : (char **)apszProjMapping, 2 );
1001 110 : pszProjection = GetAttrValue("PROJECTION");
1002 :
1003 : /* -------------------------------------------------------------------- */
1004 : /* Translate DATUM keywords that are misnamed. */
1005 : /* -------------------------------------------------------------------- */
1006 110 : InitDatumMappingTable();
1007 :
1008 : GetRoot()->applyRemapper( "DATUM",
1009 110 : papszDatumMapping+2, papszDatumMapping+1, 3 );
1010 :
1011 110 : const char *pszProjCSName = NULL;
1012 110 : const char *pszGcsName = NULL;
1013 110 : OGR_SRSNode *poProjCS = NULL;
1014 110 : OGR_SRSNode *poProjCSNodeChild = NULL;
1015 :
1016 : /* -------------------------------------------------------------------- */
1017 : /* Very specific handling for some well known geographic */
1018 : /* coordinate systems. */
1019 : /* -------------------------------------------------------------------- */
1020 110 : OGR_SRSNode *poGeogCS = GetAttrNode( "GEOGCS" );
1021 110 : if( poGeogCS != NULL )
1022 : {
1023 110 : const char *pszGeogCSName = poGeogCS->GetChild(0)->GetValue();
1024 110 : const char *pszAuthName = GetAuthorityName("GEOGCS");
1025 110 : const char *pszUTMPrefix = NULL;
1026 110 : int nGCSCode = -1;
1027 :
1028 110 : if( pszAuthName != NULL && EQUAL(pszAuthName,"EPSG") )
1029 0 : nGCSCode = atoi(GetAuthorityCode("GEOGCS"));
1030 :
1031 162 : if( nGCSCode == 4326
1032 : || EQUAL(pszGeogCSName,"WGS84")
1033 : || EQUAL(pszGeogCSName,"WGS 84") )
1034 : {
1035 52 : poGeogCS->GetChild(0)->SetValue( "GCS_WGS_1984" );
1036 52 : pszUTMPrefix = "WGS_1984";
1037 : }
1038 87 : else if( nGCSCode == 4267
1039 : || EQUAL(pszGeogCSName,"NAD27")
1040 : || EQUAL(pszGeogCSName,"NAD 27") )
1041 : {
1042 29 : poGeogCS->GetChild(0)->SetValue( "GCS_North_American_1927" );
1043 29 : pszUTMPrefix = "NAD_1927";
1044 : }
1045 29 : else if( nGCSCode == 4269
1046 : || EQUAL(pszGeogCSName,"NAD83")
1047 : || EQUAL(pszGeogCSName,"NAD 83") )
1048 : {
1049 0 : poGeogCS->GetChild(0)->SetValue( "GCS_North_American_1983" );
1050 0 : pszUTMPrefix = "NAD_1983";
1051 : }
1052 :
1053 : /* -------------------------------------------------------------------- */
1054 : /* Force Unnamed to Unknown for most common locations. */
1055 : /* -------------------------------------------------------------------- */
1056 : static const char *apszUnknownMapping[] = {
1057 : "Unknown", "Unnamed",
1058 : NULL, NULL
1059 : };
1060 :
1061 : GetRoot()->applyRemapper( "PROJCS",
1062 : (char **)apszUnknownMapping+1,
1063 110 : (char **)apszUnknownMapping+0, 2 );
1064 : GetRoot()->applyRemapper( "GEOGCS",
1065 : (char **)apszUnknownMapping+1,
1066 110 : (char **)apszUnknownMapping+0, 2 );
1067 : GetRoot()->applyRemapper( "DATUM",
1068 : (char **)apszUnknownMapping+1,
1069 110 : (char **)apszUnknownMapping+0, 2 );
1070 : GetRoot()->applyRemapper( "SPHEROID",
1071 : (char **)apszUnknownMapping+1,
1072 110 : (char **)apszUnknownMapping+0, 2 );
1073 : GetRoot()->applyRemapper( "PRIMEM",
1074 : (char **)apszUnknownMapping+1,
1075 110 : (char **)apszUnknownMapping+0, 2 );
1076 :
1077 : /* -------------------------------------------------------------------- */
1078 : /* If the PROJCS name is unset, use the PROJECTION name in */
1079 : /* place of unknown, or unnamed. At the request of Peng Gao. */
1080 : /* -------------------------------------------------------------------- */
1081 110 : if( (poProjCS = GetAttrNode( "PROJCS" )) )
1082 61 : poProjCSNodeChild = poProjCS->GetChild(0);
1083 :
1084 110 : if( poProjCSNodeChild )
1085 : {
1086 61 : pszProjCSName = poProjCSNodeChild->GetValue();
1087 61 : char *pszNewValue = CPLStrdup(pszProjCSName);
1088 61 : MorphNameToESRI( &pszNewValue );
1089 61 : poProjCSNodeChild->SetValue( pszNewValue );
1090 61 : CPLFree( pszNewValue );
1091 61 : pszProjCSName = poProjCSNodeChild->GetValue();
1092 : }
1093 :
1094 110 : if( pszProjCSName != NULL
1095 : && ( EQUAL(pszProjCSName,"unnamed")
1096 : || EQUAL(pszProjCSName,"unknown")
1097 : || EQUAL(pszProjCSName,"") ) )
1098 : {
1099 3 : if( GetAttrValue( "PROJECTION", 0 ) != NULL )
1100 : {
1101 3 : pszProjCSName = GetAttrValue( "PROJECTION", 0 );
1102 3 : poProjCSNodeChild->SetValue( pszProjCSName );
1103 : }
1104 : }
1105 :
1106 : /* -------------------------------------------------------------------- */
1107 : /* Prepare very specific PROJCS names for UTM coordinate */
1108 : /* systems. */
1109 : /* -------------------------------------------------------------------- */
1110 110 : int bNorth = 0;
1111 110 : int nZone = 0;
1112 :
1113 : /* get zone from name first */
1114 110 : if( pszProjCSName && EQUALN(pszProjCSName, "UTM Zone ", 9) )
1115 : {
1116 0 : nZone = atoi(pszProjCSName+9);
1117 0 : if( strstr(pszProjCSName, "North") )
1118 0 : bNorth = 1;
1119 : }
1120 :
1121 : /* if can not get from the name, from the parameters */
1122 110 : if( nZone <= 0 )
1123 110 : nZone = GetUTMZone( &bNorth );
1124 :
1125 110 : if( nZone > 0 && pszUTMPrefix )
1126 : {
1127 : char szUTMName[128];
1128 31 : if( bNorth )
1129 30 : sprintf( szUTMName, "%s_UTM_Zone_%dN", pszUTMPrefix, nZone );
1130 : else
1131 1 : sprintf( szUTMName, "%s_UTM_Zone_%dS", pszUTMPrefix, nZone );
1132 :
1133 31 : if( poProjCSNodeChild )
1134 31 : poProjCSNodeChild->SetValue( szUTMName );
1135 : }
1136 : }
1137 :
1138 : /* -------------------------------------------------------------------- */
1139 : /* Translate UNIT keywords that are misnamed, or even the wrong */
1140 : /* case. */
1141 : /* -------------------------------------------------------------------- */
1142 : GetRoot()->applyRemapper( "UNIT",
1143 : (char **)apszUnitMapping+1,
1144 110 : (char **)apszUnitMapping, 2 );
1145 :
1146 : /* -------------------------------------------------------------------- */
1147 : /* reset constants for decimal degrees to the exact string ESRI */
1148 : /* expects when encountered to ensure a matchup. */
1149 : /* -------------------------------------------------------------------- */
1150 110 : OGR_SRSNode *poUnit = GetAttrNode( "GEOGCS|UNIT" );
1151 :
1152 110 : if( poUnit != NULL && poUnit->GetChildCount() >= 2
1153 : && ABS(GetAngularUnits()-0.0174532925199433) < 0.00000000001 )
1154 : {
1155 110 : poUnit->GetChild(0)->SetValue("Degree");
1156 110 : poUnit->GetChild(1)->SetValue("0.017453292519943295");
1157 : }
1158 :
1159 : /* -------------------------------------------------------------------- */
1160 : /* Make sure we reproduce US Feet exactly too. */
1161 : /* -------------------------------------------------------------------- */
1162 110 : poUnit = GetAttrNode( "PROJCS|UNIT" );
1163 :
1164 110 : if( poUnit != NULL && poUnit->GetChildCount() >= 2
1165 : && ABS(GetLinearUnits()- 0.30480060960121924) < 0.000000000000001)
1166 : {
1167 2 : poUnit->GetChild(0)->SetValue("Foot_US");
1168 2 : poUnit->GetChild(1)->SetValue("0.30480060960121924");
1169 : }
1170 :
1171 : /* -------------------------------------------------------------------- */
1172 : /* Remap parameters used for Albers and Mercator. */
1173 : /* -------------------------------------------------------------------- */
1174 110 : pszProjection = GetAttrValue("PROJECTION");
1175 110 : poProjCS = GetAttrNode( "PROJCS" );
1176 :
1177 110 : if( pszProjection != NULL && EQUAL(pszProjection,"Albers") )
1178 : GetRoot()->applyRemapper(
1179 : "PARAMETER", (char **)apszAlbersMapping + 1,
1180 0 : (char **)apszAlbersMapping + 0, 2 );
1181 :
1182 110 : if( pszProjection != NULL
1183 : && (EQUAL(pszProjection,SRS_PT_EQUIDISTANT_CONIC) ||
1184 : EQUAL(pszProjection,SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) ||
1185 : EQUAL(pszProjection,SRS_PT_AZIMUTHAL_EQUIDISTANT) ||
1186 : EQUAL(pszProjection,SRS_PT_SINUSOIDAL) ||
1187 : EQUAL(pszProjection,SRS_PT_ROBINSON) ) )
1188 : GetRoot()->applyRemapper(
1189 : "PARAMETER", (char **)apszECMapping + 1,
1190 2 : (char **)apszECMapping + 0, 2 );
1191 :
1192 110 : if( pszProjection != NULL && EQUAL(pszProjection,"Mercator") )
1193 : GetRoot()->applyRemapper(
1194 : "PARAMETER",
1195 : (char **)apszMercatorMapping + 1,
1196 0 : (char **)apszMercatorMapping + 0, 2 );
1197 :
1198 110 : if( pszProjection != NULL
1199 : && EQUALN(pszProjection,"Stereographic_",14)
1200 : && EQUALN(pszProjection+strlen(pszProjection)-5,"_Pole",5) )
1201 : GetRoot()->applyRemapper(
1202 : "PARAMETER",
1203 : (char **)apszPolarStereographicMapping + 1,
1204 1 : (char **)apszPolarStereographicMapping + 0, 2 );
1205 :
1206 110 : if( pszProjection != NULL && EQUAL(pszProjection,"Plate_Carree") )
1207 0 : if(FindProjParm( SRS_PP_STANDARD_PARALLEL_1, poProjCS ) < 0)
1208 : GetRoot()->applyRemapper(
1209 : "PARAMETER",
1210 : (char **)apszPolarStereographicMapping + 1,
1211 0 : (char **)apszPolarStereographicMapping + 0, 2 );
1212 :
1213 : /* -------------------------------------------------------------------- */
1214 : /* ESRI's Equidistant_Cylindrical does not support the */
1215 : /* latitude_of_origin keyword. */
1216 : /* -------------------------------------------------------------------- */
1217 110 : if( pszProjection != NULL
1218 : && EQUAL(pszProjection,"Equidistant_Cylindrical") )
1219 : {
1220 3 : if( GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0) != 0.0 )
1221 : {
1222 0 : CPLDebug( "OGR_ESRI", "Equirectangular with non-zero latitude of origin - not supported." );
1223 : }
1224 : else
1225 : {
1226 3 : OGR_SRSNode *poPROJCS = GetAttrNode("PROJCS");
1227 3 : if( poPROJCS )
1228 : poPROJCS->DestroyChild(
1229 3 : FindProjParm( SRS_PP_LATITUDE_OF_ORIGIN ) );
1230 : }
1231 : }
1232 :
1233 : /* -------------------------------------------------------------------- */
1234 : /* Convert SPHEROID name to use underscores instead of spaces. */
1235 : /* -------------------------------------------------------------------- */
1236 : OGR_SRSNode *poSpheroid;
1237 110 : OGR_SRSNode *poSpheroidChild = NULL;
1238 110 : poSpheroid = GetAttrNode( "SPHEROID" );
1239 110 : if( poSpheroid != NULL )
1240 110 : poSpheroidChild = poSpheroid->GetChild(0);
1241 :
1242 110 : if( poSpheroidChild != NULL )
1243 : {
1244 110 : char *pszNewValue = CPLStrdup(RemapSpheroidName(poSpheroidChild->GetValue()));
1245 :
1246 110 : MorphNameToESRI( &pszNewValue );
1247 :
1248 110 : poSpheroidChild->SetValue( pszNewValue );
1249 110 : CPLFree( pszNewValue );
1250 : }
1251 :
1252 110 : if( poSpheroid != NULL )
1253 110 : poSpheroidChild = poSpheroid->GetChild(2);
1254 :
1255 110 : if( poSpheroidChild != NULL )
1256 : {
1257 110 : const char * dfValue = poSpheroidChild->GetValue();
1258 1486 : for( int i = 0; apszInvFlatteningMapping[i] != NULL; i += 2 )
1259 : {
1260 1408 : if( EQUALN(apszInvFlatteningMapping[i], dfValue, strlen(apszInvFlatteningMapping[i]) ))
1261 : {
1262 32 : poSpheroidChild->SetValue( apszInvFlatteningMapping[i+1] );
1263 32 : break;
1264 : }
1265 : }
1266 : }
1267 :
1268 : /* -------------------------------------------------------------------- */
1269 : /* Try to insert a D_ in front of the datum name. */
1270 : /* -------------------------------------------------------------------- */
1271 : OGR_SRSNode *poDatum;
1272 :
1273 110 : poDatum = GetAttrNode( "DATUM" );
1274 110 : if( poDatum != NULL )
1275 110 : poDatum = poDatum->GetChild(0);
1276 :
1277 110 : if( poDatum != NULL )
1278 : {
1279 110 : const char* pszDatumName = poDatum->GetValue();
1280 110 : if( !EQUALN(pszDatumName, "D_",2) )
1281 : {
1282 : char *pszNewValue;
1283 :
1284 2 : pszNewValue = (char *) CPLMalloc(strlen(poDatum->GetValue())+3);
1285 2 : strcpy( pszNewValue, "D_" );
1286 2 : strcat( pszNewValue, poDatum->GetValue() );
1287 2 : poDatum->SetValue( pszNewValue );
1288 2 : CPLFree( pszNewValue );
1289 : }
1290 : }
1291 :
1292 : /* -------------------------------------------------------------------- */
1293 : /* final check names */
1294 : /* -------------------------------------------------------------------- */
1295 110 : if( poProjCSNodeChild )
1296 61 : pszProjCSName = poProjCSNodeChild->GetValue();
1297 :
1298 110 : if( pszProjCSName )
1299 : {
1300 61 : pszGcsName = GetAttrValue( "GEOGCS" );
1301 61 : if(pszGcsName && !EQUALN( pszGcsName, "GCS_", 4 ) )
1302 : {
1303 17 : char* newGcsName = (char *) CPLMalloc(strlen(pszGcsName) + 5);
1304 17 : strcpy( newGcsName, "GCS_" );
1305 17 : strcat(newGcsName, pszGcsName);
1306 17 : SetNewName( this, "GEOGCS", newGcsName );
1307 17 : CPLFree( newGcsName );
1308 17 : pszGcsName = GetAttrValue("GEOGCS" );
1309 : }
1310 61 : RemapGeogCSName(this, pszGcsName);
1311 :
1312 : // Specific processing and remapping
1313 61 : pszProjection = GetAttrValue("PROJECTION");
1314 61 : if(pszProjection)
1315 : {
1316 61 : if(EQUAL(pszProjection,"Lambert_Conformal_Conic"))
1317 : {
1318 2 : if(FindProjParm( SRS_PP_STANDARD_PARALLEL_2, poProjCS ) < 0 )
1319 : {
1320 0 : int iChild = FindProjParm( SRS_PP_LATITUDE_OF_ORIGIN, poProjCS );
1321 0 : int iChild1 = FindProjParm( SRS_PP_STANDARD_PARALLEL_1, poProjCS );
1322 0 : if( iChild >= 0 && iChild1 < 0 )
1323 : {
1324 0 : const OGR_SRSNode *poParameter = poProjCS->GetChild(iChild);
1325 0 : if( poParameter )
1326 : {
1327 0 : OGR_SRSNode *poNewParm = new OGR_SRSNode( "PARAMETER" );
1328 0 : poNewParm->AddChild( new OGR_SRSNode( "standard_parallel_1" ) );
1329 0 : poNewParm->AddChild( new OGR_SRSNode( poParameter->GetChild(1)->GetValue() ) );
1330 0 : poProjCS->AddChild( poNewParm );
1331 : }
1332 : }
1333 : }
1334 : }
1335 :
1336 61 : if(EQUAL(pszProjection,"Plate_Carree"))
1337 : {
1338 0 : int iChild = FindProjParm( SRS_PP_STANDARD_PARALLEL_1, poProjCS );
1339 0 : if(iChild < 0)
1340 0 : iChild = FindProjParm( SRS_PP_PSEUDO_STD_PARALLEL_1, poProjCS );
1341 :
1342 0 : if(iChild >= 0)
1343 : {
1344 0 : const OGR_SRSNode *poParameter = poProjCS->GetChild(iChild);
1345 0 : if(!EQUAL(poParameter->GetChild(1)->GetValue(), "0.0") && !EQUAL(poParameter->GetChild(1)->GetValue(), "0"))
1346 : {
1347 0 : SetNode( "PROJCS|PROJECTION", "Equidistant_Cylindrical" );
1348 0 : pszProjection = GetAttrValue("PROJECTION");
1349 : }
1350 : }
1351 : }
1352 61 : DeleteParamBasedOnPrjName( this, pszProjection, (char **)apszDeleteParametersBasedOnProjection);
1353 61 : AddParamBasedOnPrjName( this, pszProjection, (char **)apszAddParametersBasedOnProjection);
1354 61 : RemapPValuesBasedOnProjCSAndPName( this, pszProjection, (char **)apszParamValueMapping);
1355 61 : RemapPNamesBasedOnProjCSAndPName( this, pszProjection, (char **)apszParamNameMapping);
1356 : }
1357 : }
1358 :
1359 110 : return OGRERR_NONE;
1360 : }
1361 :
1362 : /************************************************************************/
1363 : /* OSRMorphToESRI() */
1364 : /************************************************************************/
1365 :
1366 : /**
1367 : * \brief Convert in place to ESRI WKT format.
1368 : *
1369 : * This function is the same as the C++ method OGRSpatialReference::morphToESRI()
1370 : */
1371 10 : OGRErr OSRMorphToESRI( OGRSpatialReferenceH hSRS )
1372 :
1373 : {
1374 10 : VALIDATE_POINTER1( hSRS, "OSRMorphToESRI", CE_Failure );
1375 :
1376 10 : return ((OGRSpatialReference *) hSRS)->morphToESRI();
1377 : }
1378 :
1379 : /************************************************************************/
1380 : /* morphFromESRI() */
1381 : /* */
1382 : /* modify this definition from the ESRI definition of WKT to */
1383 : /* the "Standard" definition. */
1384 : /************************************************************************/
1385 :
1386 : /**
1387 : * \brief Convert in place from ESRI WKT format.
1388 : *
1389 : * The value notes of this coordinate system are modified in various manners
1390 : * to adhere more closely to the WKT standard. This mostly involves
1391 : * translating a variety of ESRI names for projections, arguments and
1392 : * datums to "standard" names, as defined by Adam Gawne-Cain's reference
1393 : * translation of EPSG to WKT for the CT specification.
1394 : *
1395 : * This does the same as the C function OSRMorphFromESRI().
1396 : *
1397 : * @return OGRERR_NONE unless something goes badly wrong.
1398 : */
1399 :
1400 226 : OGRErr OGRSpatialReference::morphFromESRI()
1401 :
1402 : {
1403 226 : OGRErr eErr = OGRERR_NONE;
1404 :
1405 226 : if( GetRoot() == NULL )
1406 0 : return OGRERR_NONE;
1407 :
1408 : /* -------------------------------------------------------------------- */
1409 : /* Translate DATUM keywords that are oddly named. */
1410 : /* -------------------------------------------------------------------- */
1411 226 : InitDatumMappingTable();
1412 :
1413 : GetRoot()->applyRemapper( "DATUM",
1414 : (char **)papszDatumMapping+1,
1415 226 : (char **)papszDatumMapping+2, 3 );
1416 :
1417 : /* -------------------------------------------------------------------- */
1418 : /* Try to remove any D_ in front of the datum name. */
1419 : /* -------------------------------------------------------------------- */
1420 : OGR_SRSNode *poDatum;
1421 :
1422 226 : poDatum = GetAttrNode( "DATUM" );
1423 226 : if( poDatum != NULL )
1424 226 : poDatum = poDatum->GetChild(0);
1425 :
1426 226 : if( poDatum != NULL )
1427 : {
1428 226 : if( EQUALN(poDatum->GetValue(),"D_",2) )
1429 : {
1430 0 : char *pszNewValue = CPLStrdup( poDatum->GetValue() + 2 );
1431 0 : poDatum->SetValue( pszNewValue );
1432 0 : CPLFree( pszNewValue );
1433 : }
1434 : }
1435 :
1436 : /* -------------------------------------------------------------------- */
1437 : /* Split Lambert_Conformal_Conic into 1SP or 2SP form. */
1438 : /* */
1439 : /* See bugzilla.remotesensing.org/show_bug.cgi?id=187 */
1440 : /* */
1441 : /* We decide based on whether it has 2SPs. We used to assume */
1442 : /* 1SP if it had a scale factor but that turned out to be a */
1443 : /* poor test. */
1444 : /* -------------------------------------------------------------------- */
1445 226 : const char *pszProjection = GetAttrValue("PROJECTION");
1446 :
1447 226 : if( pszProjection != NULL
1448 : && EQUAL(pszProjection,"Lambert_Conformal_Conic") )
1449 : {
1450 10 : if( GetProjParm( SRS_PP_STANDARD_PARALLEL_1, 1000.0 ) != 1000.0
1451 : && GetProjParm( SRS_PP_STANDARD_PARALLEL_2, 1000.0 ) != 1000.0 )
1452 : SetNode( "PROJCS|PROJECTION",
1453 10 : SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP );
1454 : else
1455 : SetNode( "PROJCS|PROJECTION",
1456 0 : SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP );
1457 :
1458 10 : pszProjection = GetAttrValue("PROJECTION");
1459 : }
1460 :
1461 : /* -------------------------------------------------------------------- */
1462 : /* If we are remapping Hotine_Oblique_Mercator_Azimuth_Center */
1463 : /* add a rectified_grid_angle parameter - to match the azimuth */
1464 : /* I guess. */
1465 : /* -------------------------------------------------------------------- */
1466 226 : if( pszProjection != NULL
1467 : && EQUAL(pszProjection,"Hotine_Oblique_Mercator_Azimuth_Center") )
1468 : {
1469 : SetProjParm( SRS_PP_RECTIFIED_GRID_ANGLE ,
1470 1 : GetProjParm( SRS_PP_AZIMUTH, 0.0 ) );
1471 1 : FixupOrdering();
1472 : }
1473 :
1474 : /* -------------------------------------------------------------------- */
1475 : /* Remap Albers, Mercator and Polar Stereographic parameters. */
1476 : /* -------------------------------------------------------------------- */
1477 226 : if( pszProjection != NULL && EQUAL(pszProjection,"Albers") )
1478 : GetRoot()->applyRemapper(
1479 : "PARAMETER", (char **)apszAlbersMapping + 0,
1480 0 : (char **)apszAlbersMapping + 1, 2 );
1481 :
1482 226 : if( pszProjection != NULL
1483 : && (EQUAL(pszProjection,SRS_PT_EQUIDISTANT_CONIC) ||
1484 : EQUAL(pszProjection,SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) ||
1485 : EQUAL(pszProjection,SRS_PT_AZIMUTHAL_EQUIDISTANT) ||
1486 : EQUAL(pszProjection,SRS_PT_SINUSOIDAL) ||
1487 : EQUAL(pszProjection,SRS_PT_ROBINSON) ) )
1488 : GetRoot()->applyRemapper(
1489 : "PARAMETER", (char **)apszECMapping + 0,
1490 2 : (char **)apszECMapping + 1, 2 );
1491 :
1492 226 : if( pszProjection != NULL && EQUAL(pszProjection,"Mercator") )
1493 : GetRoot()->applyRemapper(
1494 : "PARAMETER",
1495 : (char **)apszMercatorMapping + 0,
1496 0 : (char **)apszMercatorMapping + 1, 2 );
1497 :
1498 226 : if( pszProjection != NULL
1499 : && EQUALN(pszProjection,"Stereographic_",14)
1500 : && EQUALN(pszProjection+strlen(pszProjection)-5,"_Pole",5) )
1501 : GetRoot()->applyRemapper(
1502 : "PARAMETER",
1503 : (char **)apszPolarStereographicMapping + 0,
1504 1 : (char **)apszPolarStereographicMapping + 1, 2 );
1505 :
1506 : /* -------------------------------------------------------------------- */
1507 : /* Remap south and north polar stereographic to one value. */
1508 : /* -------------------------------------------------------------------- */
1509 226 : if( pszProjection != NULL
1510 : && EQUALN(pszProjection,"Stereographic_",14)
1511 : && EQUALN(pszProjection+strlen(pszProjection)-5,"_Pole",5) )
1512 : {
1513 1 : SetNode( "PROJCS|PROJECTION", SRS_PT_POLAR_STEREOGRAPHIC );
1514 1 : pszProjection = GetAttrValue("PROJECTION");
1515 : }
1516 :
1517 : /* -------------------------------------------------------------------- */
1518 : /* Remap Equidistant_Cylindrical parameter. It is same as */
1519 : /* Stereographic */
1520 : /* -------------------------------------------------------------------- */
1521 : #ifdef notdef
1522 : if( pszProjection != NULL && EQUAL(pszProjection,"Equidistant_Cylindrical") )
1523 : GetRoot()->applyRemapper(
1524 : "PARAMETER",
1525 : (char **)apszPolarStereographicMapping + 0,
1526 : (char **)apszPolarStereographicMapping + 1, 2 );
1527 : #endif
1528 :
1529 : /* -------------------------------------------------------------------- */
1530 : /* Translate PROJECTION keywords that are misnamed. */
1531 : /* -------------------------------------------------------------------- */
1532 : GetRoot()->applyRemapper( "PROJECTION",
1533 : (char **)apszProjMapping,
1534 226 : (char **)apszProjMapping+1, 2 );
1535 :
1536 : /* -------------------------------------------------------------------- */
1537 : /* Translate DATUM keywords that are misnamed. */
1538 : /* -------------------------------------------------------------------- */
1539 226 : InitDatumMappingTable();
1540 :
1541 : GetRoot()->applyRemapper( "DATUM",
1542 : (char **)papszDatumMapping+1,
1543 226 : (char **)papszDatumMapping+2, 3 );
1544 :
1545 226 : return eErr;
1546 : }
1547 :
1548 : /************************************************************************/
1549 : /* OSRMorphFromESRI() */
1550 : /************************************************************************/
1551 :
1552 : /**
1553 : * \brief Convert in place from ESRI WKT format.
1554 : *
1555 : * This function is the same as the C++ method OGRSpatialReference::morphFromESRI()
1556 : */
1557 9 : OGRErr OSRMorphFromESRI( OGRSpatialReferenceH hSRS )
1558 :
1559 : {
1560 9 : VALIDATE_POINTER1( hSRS, "OSRMorphFromESRI", CE_Failure );
1561 :
1562 9 : return ((OGRSpatialReference *) hSRS)->morphFromESRI();
1563 : }
1564 :
1565 : /************************************************************************/
1566 : /* SetNewName() */
1567 : /* */
1568 : /* Set an esri name */
1569 : /************************************************************************/
1570 17 : void SetNewName( OGRSpatialReference* pOgr, const char* keyName, const char* newName )
1571 : {
1572 17 : OGR_SRSNode *poNode = pOgr->GetAttrNode( keyName );
1573 17 : OGR_SRSNode *poNodeChild = NULL;
1574 17 : if(poNode)
1575 17 : poNodeChild = poNode->GetChild(0);
1576 17 : if( poNodeChild)
1577 17 : poNodeChild->SetValue( newName);
1578 17 : }
1579 :
1580 : /************************************************************************/
1581 : /* RemapImgWGSProjcsName() */
1582 : /* */
1583 : /* Convert Img projcs names to ESRI style */
1584 : /************************************************************************/
1585 0 : int RemapImgWGSProjcsName( OGRSpatialReference* pOgr, const char* pszProjCSName, const char* pszProgCSName )
1586 : {
1587 0 : if(EQUAL(pszProgCSName, "WGS_1972") || EQUAL(pszProgCSName, "WGS_1984") )
1588 : {
1589 0 : char* newName = (char *) CPLMalloc(strlen(pszProjCSName) + 10);
1590 0 : sprintf( newName, "%s_", pszProgCSName );
1591 0 : strcat(newName, pszProjCSName);
1592 0 : SetNewName( pOgr, "PROJCS", newName );
1593 0 : CPLFree( newName );
1594 0 : return 1;
1595 : }
1596 0 : return -1;
1597 : }
1598 :
1599 : /************************************************************************/
1600 : /* RemapImgUTMNames() */
1601 : /* */
1602 : /* Convert Img UTM names to ESRI style */
1603 : /************************************************************************/
1604 :
1605 0 : int RemapImgUTMNames( OGRSpatialReference* pOgr, const char* pszProjCSName, const char* pszProgCSName,
1606 : char **mappingTable )
1607 : {
1608 : long i;
1609 0 : long iIndex = -1;
1610 0 : for( i = 0; mappingTable[i] != NULL; i += 5 )
1611 : {
1612 0 : if( EQUAL(pszProjCSName, mappingTable[i]) )
1613 : {
1614 0 : long j = i;
1615 0 : while(mappingTable[j] != NULL && EQUAL(mappingTable[i], mappingTable[j]))
1616 : {
1617 0 : if( EQUAL(pszProgCSName, mappingTable[j+1]) )
1618 : {
1619 0 : iIndex = j;
1620 0 : break;
1621 : }
1622 0 : j += 5;
1623 : }
1624 0 : if (iIndex >= 0)
1625 0 : break;
1626 : }
1627 : }
1628 0 : if(iIndex >= 0)
1629 : {
1630 0 : OGR_SRSNode *poNode = pOgr->GetAttrNode( "PROJCS" );
1631 0 : OGR_SRSNode *poNodeChild = NULL;
1632 0 : if(poNode)
1633 0 : poNodeChild = poNode->GetChild(0);
1634 0 : if( poNodeChild && strlen(poNodeChild->GetValue()) > 0 )
1635 0 : poNodeChild->SetValue( mappingTable[iIndex+2]);
1636 :
1637 0 : poNode = pOgr->GetAttrNode( "GEOGCS" );
1638 0 : poNodeChild = NULL;
1639 0 : if(poNode)
1640 0 : poNodeChild = poNode->GetChild(0);
1641 0 : if( poNodeChild && strlen(poNodeChild->GetValue()) > 0 )
1642 0 : poNodeChild->SetValue( mappingTable[iIndex+3]);
1643 :
1644 0 : poNode = pOgr->GetAttrNode( "DATUM" );
1645 0 : poNodeChild = NULL;
1646 0 : if(poNode)
1647 0 : poNodeChild = poNode->GetChild(0);
1648 0 : if( poNodeChild && strlen(poNodeChild->GetValue()) > 0 )
1649 0 : poNodeChild->SetValue( mappingTable[iIndex+4]);
1650 : }
1651 0 : return iIndex;
1652 : }
1653 :
1654 : /************************************************************************/
1655 : /* RemapNameBasedOnKeyName() */
1656 : /* */
1657 : /* Convert a name to ESRI style name */
1658 : /************************************************************************/
1659 :
1660 60 : int RemapNameBasedOnKeyName( OGRSpatialReference* pOgr, const char* pszName, const char* pszkeyName,
1661 : char **mappingTable )
1662 : {
1663 : long i, n;
1664 60 : long iIndex = -1;
1665 2160 : for( i = 0; mappingTable[i] != NULL; i += 2 )
1666 : {
1667 2100 : n = strlen(pszName);
1668 2100 : if( EQUALN(pszName, mappingTable[i],n) )
1669 : {
1670 0 : iIndex = i;
1671 0 : break;
1672 : }
1673 : }
1674 60 : if(iIndex >= 0)
1675 : {
1676 0 : OGR_SRSNode *poNode = pOgr->GetAttrNode( pszkeyName );
1677 0 : OGR_SRSNode *poNodeChild = NULL;
1678 0 : if(poNode)
1679 0 : poNodeChild = poNode->GetChild(0);
1680 0 : if( poNodeChild && strlen(poNodeChild->GetValue()) > 0 )
1681 0 : poNodeChild->SetValue( mappingTable[iIndex+1]);
1682 : }
1683 60 : return iIndex;
1684 : }
1685 :
1686 : /************************************************************************/
1687 : /* RemapNamesBasedOnTwo() */
1688 : /* */
1689 : /* Convert a name to ESRI style name */
1690 : /************************************************************************/
1691 :
1692 182 : int RemapNamesBasedOnTwo( OGRSpatialReference* pOgr, const char* name1, const char* name2,
1693 : char **mappingTable, long nTableStepSize,
1694 : char** pszkeyNames, long nKeys )
1695 : {
1696 : long i, n, n1;
1697 182 : long iIndex = -1;
1698 912 : for( i = 0; mappingTable[i] != NULL; i += nTableStepSize )
1699 : {
1700 731 : n = strlen(name1);
1701 731 : n1 = strlen(mappingTable[i]);
1702 731 : if( EQUALN(name1, mappingTable[i], n1<=n? n1 : n) )
1703 : {
1704 1 : long j = i;
1705 2 : while(mappingTable[j] != NULL && EQUAL(mappingTable[i], mappingTable[j]))
1706 : {
1707 1 : if( EQUALN(name2, mappingTable[j+1], strlen(mappingTable[j+1])) )
1708 : {
1709 1 : iIndex = j;
1710 1 : break;
1711 : }
1712 0 : j += 3;
1713 : }
1714 1 : if (iIndex >= 0)
1715 1 : break;
1716 : }
1717 : }
1718 182 : if(iIndex >= 0)
1719 : {
1720 2 : for( i = 0; i < nKeys; i ++ )
1721 : {
1722 1 : OGR_SRSNode *poNode = pOgr->GetAttrNode( pszkeyNames[i] );
1723 1 : OGR_SRSNode *poNodeChild = NULL;
1724 1 : if(poNode)
1725 1 : poNodeChild = poNode->GetChild(0);
1726 1 : if( poNodeChild && strlen(poNodeChild->GetValue()) > 0 )
1727 1 : poNodeChild->SetValue( mappingTable[iIndex+i+2]);
1728 : }
1729 :
1730 : }
1731 182 : return iIndex;
1732 : }
1733 :
1734 : /************************************************************************/
1735 : /* RemapPValuesBasedOnProjCSAndPName() */
1736 : /* */
1737 : /* Convert a parameters to ESRI style name */
1738 : /************************************************************************/
1739 :
1740 61 : int RemapPValuesBasedOnProjCSAndPName( OGRSpatialReference* pOgr, const char* pszProgCSName,
1741 : char **mappingTable )
1742 : {
1743 61 : long ret = 0;
1744 61 : OGR_SRSNode *poPROJCS = pOgr->GetAttrNode( "PROJCS" );
1745 353 : for( int i = 0; mappingTable[i] != NULL; i += 4 )
1746 : {
1747 878 : while( mappingTable[i] != NULL && EQUALN(pszProgCSName, mappingTable[i], strlen(mappingTable[i])) )
1748 : {
1749 : OGR_SRSNode *poParm;
1750 196 : const char* pszParamName = mappingTable[i+1];
1751 196 : const char* pszParamValue = mappingTable[i+2];
1752 1960 : for( int iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ )
1753 : {
1754 1764 : poParm = poPROJCS->GetChild( iChild );
1755 :
1756 1764 : if( EQUAL(poParm->GetValue(),"PARAMETER")
1757 : && poParm->GetChildCount() == 2
1758 : && EQUAL(poParm->GetChild(0)->GetValue(),pszParamName)
1759 : && EQUALN(poParm->GetChild(1)->GetValue(),pszParamValue, strlen(pszParamValue) ) )
1760 : {
1761 0 : poParm->GetChild(1)->SetValue( mappingTable[i+3] );
1762 0 : break;
1763 : }
1764 : }
1765 196 : ret ++;
1766 196 : i += 4;
1767 : }
1768 341 : if (ret > 0)
1769 49 : break;
1770 : }
1771 61 : return ret;
1772 : }
1773 :
1774 : /************************************************************************/
1775 : /* RemapPNamesBasedOnProjCSAndPName() */
1776 : /* */
1777 : /* Convert a parameters to ESRI style name */
1778 : /************************************************************************/
1779 :
1780 61 : int RemapPNamesBasedOnProjCSAndPName( OGRSpatialReference* pOgr, const char* pszProgCSName,
1781 : char **mappingTable )
1782 : {
1783 61 : long ret = 0;
1784 61 : OGR_SRSNode *poPROJCS = pOgr->GetAttrNode( "PROJCS" );
1785 535 : for( int i = 0; mappingTable[i] != NULL; i += 3 )
1786 : {
1787 955 : while( mappingTable[i] != NULL && EQUALN(pszProgCSName, mappingTable[i], strlen(mappingTable[i])) )
1788 : {
1789 : OGR_SRSNode *poParm;
1790 3 : const char* pszParamName = mappingTable[i+1];
1791 22 : for( int iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ )
1792 : {
1793 20 : poParm = poPROJCS->GetChild( iChild );
1794 :
1795 20 : if( EQUAL(poParm->GetValue(),"PARAMETER")
1796 : && poParm->GetChildCount() == 2
1797 : && EQUAL(poParm->GetChild(0)->GetValue(),pszParamName) )
1798 : {
1799 1 : poParm->GetChild(0)->SetValue( mappingTable[i+2] );
1800 1 : break;
1801 : }
1802 : }
1803 3 : ret ++;
1804 3 : i += 3;
1805 : }
1806 476 : if (ret > 0)
1807 2 : break;
1808 : }
1809 61 : return ret;
1810 : }
1811 :
1812 : /************************************************************************/
1813 : /* DeleteParamBasedOnPrjName */
1814 : /* */
1815 : /* Delete non-ESRI parameters */
1816 : /************************************************************************/
1817 61 : int DeleteParamBasedOnPrjName( OGRSpatialReference* pOgr, const char* pszProjectionName,
1818 : char **mappingTable )
1819 : {
1820 61 : long iIndex = -1, ret = -1;
1821 671 : for( int i = 0; mappingTable[i] != NULL; i += 2 )
1822 : {
1823 610 : if( EQUALN(pszProjectionName, mappingTable[i], strlen(mappingTable[i])) )
1824 : {
1825 6 : OGR_SRSNode *poPROJCS = pOgr->GetAttrNode( "PROJCS" );
1826 : OGR_SRSNode *poParm;
1827 6 : const char* pszParamName = mappingTable[i+1];
1828 6 : iIndex = -1;
1829 47 : for( int iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ )
1830 : {
1831 43 : poParm = poPROJCS->GetChild( iChild );
1832 :
1833 43 : if( EQUAL(poParm->GetValue(),"PARAMETER")
1834 : && poParm->GetChildCount() == 2
1835 : && EQUAL(poParm->GetChild(0)->GetValue(),pszParamName) )
1836 : {
1837 2 : iIndex = iChild;
1838 2 : break;
1839 : }
1840 : }
1841 6 : if(iIndex >= 0)
1842 : {
1843 2 : poPROJCS->DestroyChild( iIndex );
1844 2 : ret ++;
1845 : }
1846 : }
1847 : }
1848 61 : return ret;
1849 : }
1850 : /************************************************************************/
1851 : /* AddParamBasedOnPrjName() */
1852 : /* */
1853 : /* Add ESRI style parameters */
1854 : /************************************************************************/
1855 61 : int AddParamBasedOnPrjName( OGRSpatialReference* pOgr, const char* pszProjectionName,
1856 : char **mappingTable )
1857 : {
1858 61 : long ret = -1;
1859 61 : OGR_SRSNode *poPROJCS = pOgr->GetAttrNode( "PROJCS" );
1860 244 : for( int i = 0; mappingTable[i] != NULL; i += 3 )
1861 : {
1862 183 : if( EQUALN(pszProjectionName, mappingTable[i], strlen(mappingTable[i])) )
1863 : {
1864 : OGR_SRSNode *poParm;
1865 2 : int exist = 0;
1866 23 : for( int iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ )
1867 : {
1868 21 : poParm = poPROJCS->GetChild( iChild );
1869 :
1870 34 : if( EQUAL(poParm->GetValue(),"PARAMETER")
1871 : && poParm->GetChildCount() == 2
1872 13 : && EQUAL(poParm->GetChild(0)->GetValue(),mappingTable[i+1]) )
1873 1 : exist = 1;
1874 : }
1875 2 : if(!exist)
1876 : {
1877 1 : poParm = new OGR_SRSNode( "PARAMETER" );
1878 2 : poParm->AddChild( new OGR_SRSNode( mappingTable[i+1] ) );
1879 2 : poParm->AddChild( new OGR_SRSNode( mappingTable[i+2] ) );
1880 1 : poPROJCS->AddChild( poParm );
1881 1 : ret ++;
1882 : }
1883 : }
1884 : }
1885 61 : return ret;
1886 : }
1887 :
1888 : /************************************************************************/
1889 : /* RemapGeogCSName() */
1890 : /* */
1891 : /* Convert names to ESRI style */
1892 : /************************************************************************/
1893 61 : int RemapGeogCSName( OGRSpatialReference* pOgr, const char *pszGeogCSName )
1894 : {
1895 : static const char *keyNamesG[] = {
1896 : "GEOGCS"};
1897 61 : int ret = -1;
1898 :
1899 61 : const char* pszUnitName = pOgr->GetAttrValue( "GEOGCS|UNIT");
1900 61 : if(pszUnitName)
1901 61 : ret = RemapNamesBasedOnTwo( pOgr, pszGeogCSName+4, pszUnitName, (char**)apszGcsNameMappingBasedOnUnit, 3, (char**)keyNamesG, 1);
1902 61 : if(ret < 0)
1903 : {
1904 61 : const char* pszPrimeName = pOgr->GetAttrValue("PRIMEM");
1905 61 : if(pszPrimeName)
1906 61 : ret = RemapNamesBasedOnTwo( pOgr, pszGeogCSName+4, pszPrimeName, (char**)apszGcsNameMappingBasedPrime, 3, (char**)keyNamesG, 1);
1907 61 : if(ret < 0)
1908 60 : ret = RemapNameBasedOnKeyName( pOgr, pszGeogCSName+4, "GEOGCS", (char**)apszGcsNameMapping);
1909 : }
1910 61 : if(ret < 0)
1911 : {
1912 60 : const char* pszProjCS = pOgr->GetAttrValue( "PROJCS" );
1913 60 : ret = RemapNamesBasedOnTwo( pOgr, pszProjCS, pszGeogCSName, (char**)apszGcsNameMappingBasedOnProjCS, 3, (char**)keyNamesG, 1);
1914 : }
1915 61 : return ret;
1916 : }
1917 :
|