1 : /******************************************************************************
2 : * $Id: ogr_srs_esri.cpp 19742 2010-05-19 14:58:58Z warmerdam $
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 19742 2010-05-19 14:58:58Z warmerdam $");
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 178 : static const char* RemapSpheroidName(const char* pszName)
271 : {
272 178 : if (strcmp(pszName, "WGS 84") == 0)
273 94 : return "WGS 1984";
274 :
275 84 : if (strcmp(pszName, "WGS 72") == 0)
276 0 : return "WGS 1972";
277 :
278 84 : 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 261 : static void MorphNameToESRI( char ** ppszName )
311 :
312 : {
313 : int i, j;
314 261 : char *pszName = *ppszName;
315 :
316 261 : if (pszName[0] == '\0')
317 0 : return;
318 :
319 : /* -------------------------------------------------------------------- */
320 : /* Translate non-alphanumeric values to underscores. */
321 : /* -------------------------------------------------------------------- */
322 3955 : for( i = 0; pszName[i] != '\0'; i++ )
323 : {
324 3694 : if( pszName[i] != '+'
325 : && !(pszName[i] >= 'A' && pszName[i] <= 'Z')
326 : && !(pszName[i] >= 'a' && pszName[i] <= 'z')
327 : && !(pszName[i] >= '0' && pszName[i] <= '9') )
328 : {
329 588 : pszName[i] = '_';
330 : }
331 : }
332 :
333 : /* -------------------------------------------------------------------- */
334 : /* Remove repeated and trailing underscores. */
335 : /* -------------------------------------------------------------------- */
336 3694 : for( i = 1, j = 0; pszName[i] != '\0'; i++ )
337 : {
338 3433 : if( pszName[j] == '_' && pszName[i] == '_' )
339 136 : continue;
340 :
341 3297 : pszName[++j] = pszName[i];
342 : }
343 261 : if( pszName[j] == '_' )
344 0 : pszName[j] = '\0';
345 : else
346 261 : pszName[j+1] = '\0';
347 : }
348 :
349 : /************************************************************************/
350 : /* CleanESRIDatumMappingTable() */
351 : /************************************************************************/
352 :
353 : CPL_C_START
354 719 : void CleanupESRIDatumMappingTable()
355 :
356 : {
357 719 : if( papszDatumMapping == NULL )
358 664 : return;
359 :
360 55 : if( papszDatumMapping != (char **) apszDefaultDatumMapping )
361 : {
362 55 : CSLDestroy( papszDatumMapping );
363 55 : papszDatumMapping = NULL;
364 : }
365 : }
366 : CPL_C_END
367 :
368 : /************************************************************************/
369 : /* InitDatumMappingTable() */
370 : /************************************************************************/
371 :
372 926 : static void InitDatumMappingTable()
373 :
374 : {
375 926 : if( papszDatumMapping != NULL )
376 870 : return;
377 :
378 : /* -------------------------------------------------------------------- */
379 : /* Try to open the datum.csv file. */
380 : /* -------------------------------------------------------------------- */
381 56 : const char *pszFilename = CSVFilename("gdal_datum.csv");
382 56 : FILE * fp = VSIFOpen( pszFilename, "rb" );
383 :
384 : /* -------------------------------------------------------------------- */
385 : /* Use simple default set if we can't find the file. */
386 : /* -------------------------------------------------------------------- */
387 56 : 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 56 : char **papszFieldNames = CSVReadParseLine( fp );
397 56 : int nDatumCodeField = CSLFindString( papszFieldNames, "DATUM_CODE" );
398 56 : int nEPSGNameField = CSLFindString( papszFieldNames, "DATUM_NAME" );
399 56 : int nESRINameField = CSLFindString( papszFieldNames, "ESRI_DATUM_NAME" );
400 :
401 56 : CSLDestroy( papszFieldNames );
402 :
403 56 : 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 56 : int nMappingCount = 0;
416 56 : const int nMaxDatumMappings = 1000;
417 : char **papszFields;
418 56 : papszDatumMapping = (char **)CPLCalloc(sizeof(char*),nMaxDatumMappings*3);
419 :
420 32592 : for( papszFields = CSVReadParseLine( fp );
421 : papszFields != NULL;
422 : papszFields = CSVReadParseLine( fp ) )
423 : {
424 32536 : int nFieldCount = CSLCount(papszFields);
425 :
426 32536 : CPLAssert( nMappingCount+1 < nMaxDatumMappings );
427 :
428 32536 : if( MAX(nEPSGNameField,MAX(nDatumCodeField,nESRINameField))
429 : < nFieldCount
430 : && nMaxDatumMappings > nMappingCount+1 )
431 : {
432 : papszDatumMapping[nMappingCount*3+0] =
433 32536 : CPLStrdup( papszFields[nDatumCodeField] );
434 : papszDatumMapping[nMappingCount*3+1] =
435 32536 : CPLStrdup( papszFields[nESRINameField] );
436 : papszDatumMapping[nMappingCount*3+2] =
437 32536 : CPLStrdup( papszFields[nEPSGNameField] );
438 32536 : OGREPSGDatumNameMassage( &(papszDatumMapping[nMappingCount*3+2]) );
439 :
440 32536 : nMappingCount++;
441 : }
442 32536 : CSLDestroy( papszFields );
443 : }
444 :
445 56 : VSIFClose( fp );
446 :
447 56 : papszDatumMapping[nMappingCount*3+0] = NULL;
448 56 : papszDatumMapping[nMappingCount*3+1] = NULL;
449 56 : 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 : static double OSR_GDV( char **papszNV, const char * pszField,
479 55 : 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 29 : for( iLine = 0;
492 : papszNV[iLine] != NULL && !EQUALN(papszNV[iLine],"Paramet",7);
493 : iLine++ ) {}
494 :
495 128 : for( nOffset=atoi(pszField+6);
496 : 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 : dfValue = ABS(atof(papszTokens[0]))
524 : + atof(papszTokens[1]) / 60.0
525 18 : + 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 26 : for( iLine = 0;
545 : papszNV[iLine] != NULL &&
546 : !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 : static CPLString OSR_GDS( char **papszNV, const char * pszField,
561 45 : const char *pszDefaultValue )
562 :
563 : {
564 : int iLine;
565 :
566 45 : if( papszNV == NULL || papszNV[0] == NULL )
567 0 : return pszDefaultValue;
568 :
569 45 : for( iLine = 0;
570 : papszNV[iLine] != NULL &&
571 : !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 249 : OGRErr OGRSpatialReference::importFromESRI( char **papszPrj )
625 :
626 : {
627 249 : 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 249 : if( EQUALN(papszPrj[0],"GEOGCS",6)
637 : || EQUALN(papszPrj[0],"PROJCS",6)
638 : || EQUALN(papszPrj[0],"LOCAL_CS",8) )
639 : {
640 : char *pszWKT, *pszWKT2;
641 : OGRErr eErr;
642 : int i;
643 :
644 234 : pszWKT = CPLStrdup(papszPrj[0]);
645 234 : 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 234 : pszWKT2 = pszWKT;
652 234 : eErr = importFromWkt( &pszWKT2 );
653 234 : CPLFree( pszWKT );
654 :
655 234 : if( eErr == OGRERR_NONE )
656 234 : eErr = morphFromESRI();
657 234 : 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 0 : else if( EQUAL(osProj,"MERCATOR") )
786 : {
787 : SetMercator( OSR_GDV( papszPrj, "PARAM_1", 0.0 ),
788 : OSR_GDV( papszPrj, "PARAM_0", 0.0 ),
789 : 1.0,
790 : OSR_GDV( papszPrj, "PARAM_2", 0.0 ),
791 0 : OSR_GDV( papszPrj, "PARAM_3", 0.0 ) );
792 : }
793 :
794 : else
795 : {
796 0 : CPLDebug( "OGR_ESRI", "Unsupported projection: %s", osProj.c_str() );
797 0 : SetLocalCS( osProj );
798 : }
799 :
800 : /* -------------------------------------------------------------------- */
801 : /* Try to translate the datum/spheroid. */
802 : /* -------------------------------------------------------------------- */
803 15 : if( !IsLocal() && GetAttrNode( "GEOGCS" ) == NULL )
804 : {
805 11 : CPLString osDatum;
806 :
807 11 : osDatum = OSR_GDS( papszPrj, "Datum", "");
808 :
809 11 : if( EQUAL(osDatum,"NAD27") || EQUAL(osDatum,"NAD83")
810 : || EQUAL(osDatum,"WGS84") || EQUAL(osDatum,"WGS72") )
811 : {
812 6 : SetWellKnownGeogCS( osDatum );
813 : }
814 5 : else if( EQUAL( osDatum, "EUR" )
815 : || EQUAL( osDatum, "ED50" ) )
816 : {
817 0 : SetWellKnownGeogCS( "EPSG:4230" );
818 : }
819 5 : else if( EQUAL( osDatum, "GDA94" ) )
820 : {
821 5 : SetWellKnownGeogCS( "EPSG:4283" );
822 : }
823 : else
824 : {
825 0 : CPLString osSpheroid;
826 :
827 0 : osSpheroid = OSR_GDS( papszPrj, "Spheroid", "");
828 :
829 0 : if( EQUAL(osSpheroid,"INT1909")
830 : || EQUAL(osSpheroid,"INTERNATIONAL1909") )
831 : {
832 0 : OGRSpatialReference oGCS;
833 0 : oGCS.importFromEPSG( 4022 );
834 0 : CopyGeogCSFrom( &oGCS );
835 : }
836 0 : else if( EQUAL(osSpheroid,"AIRY") )
837 : {
838 0 : OGRSpatialReference oGCS;
839 0 : oGCS.importFromEPSG( 4001 );
840 0 : CopyGeogCSFrom( &oGCS );
841 : }
842 0 : else if( EQUAL(osSpheroid,"CLARKE1866") )
843 : {
844 0 : OGRSpatialReference oGCS;
845 0 : oGCS.importFromEPSG( 4008 );
846 0 : CopyGeogCSFrom( &oGCS );
847 : }
848 0 : else if( EQUAL(osSpheroid,"GRS80") )
849 : {
850 0 : OGRSpatialReference oGCS;
851 0 : oGCS.importFromEPSG( 4019 );
852 0 : CopyGeogCSFrom( &oGCS );
853 : }
854 0 : else if( EQUAL(osSpheroid,"KRASOVSKY")
855 : || EQUAL(osSpheroid,"KRASSOVSKY") )
856 : {
857 0 : OGRSpatialReference oGCS;
858 0 : oGCS.importFromEPSG( 4024 );
859 0 : CopyGeogCSFrom( &oGCS );
860 : }
861 0 : else if( EQUAL(osSpheroid,"Bessel") )
862 : {
863 0 : OGRSpatialReference oGCS;
864 0 : oGCS.importFromEPSG( 4004 );
865 0 : CopyGeogCSFrom( &oGCS );
866 : }
867 : else
868 : {
869 : // If we don't know, default to WGS84 so there is something there.
870 0 : SetWellKnownGeogCS( "WGS84" );
871 0 : }
872 11 : }
873 : }
874 :
875 : /* -------------------------------------------------------------------- */
876 : /* Linear units translation */
877 : /* -------------------------------------------------------------------- */
878 15 : if( IsLocal() || IsProjected() )
879 : {
880 15 : CPLString osValue;
881 15 : double dfOldUnits = GetLinearUnits();
882 :
883 15 : osValue = OSR_GDS( papszPrj, "Units", "" );
884 15 : if( EQUAL(osValue, "" ) )
885 0 : SetLinearUnitsAndUpdateParameters( SRS_UL_METER, 1.0 );
886 15 : else if( EQUAL(osValue,"FEET") )
887 2 : SetLinearUnitsAndUpdateParameters( SRS_UL_US_FOOT, atof(SRS_UL_US_FOOT_CONV) );
888 13 : else if( atof(osValue) != 0.0 )
889 : SetLinearUnitsAndUpdateParameters( "user-defined",
890 1 : 1.0 / atof(osValue) );
891 : else
892 12 : SetLinearUnitsAndUpdateParameters( osValue, 1.0 );
893 :
894 : // If we have reset the linear units we should clear any authority
895 : // nodes on the PROJCS. This especially applies to state plane
896 : // per bug 1697
897 15 : double dfNewUnits = GetLinearUnits();
898 15 : if( dfOldUnits != 0.0
899 : && (dfNewUnits / dfOldUnits < 0.9999999
900 : || dfNewUnits / dfOldUnits > 1.0000001) )
901 : {
902 3 : if( GetRoot()->FindChild( "AUTHORITY" ) != -1 )
903 3 : GetRoot()->DestroyChild(GetRoot()->FindChild( "AUTHORITY" ));
904 15 : }
905 : }
906 :
907 15 : return OGRERR_NONE;
908 : }
909 :
910 : /************************************************************************/
911 : /* morphToESRI() */
912 : /************************************************************************/
913 : /**
914 : * \brief Convert in place to ESRI WKT format.
915 : *
916 : * The value nodes of this coordinate system are modified in various manners
917 : * more closely map onto the ESRI concept of WKT format. This includes
918 : * renaming a variety of projections and arguments, and stripping out
919 : * nodes note recognised by ESRI (like AUTHORITY and AXIS).
920 : *
921 : * This does the same as the C function OSRMorphToESRI().
922 : *
923 : * @return OGRERR_NONE unless something goes badly wrong.
924 : */
925 :
926 178 : OGRErr OGRSpatialReference::morphToESRI()
927 :
928 : {
929 : OGRErr eErr;
930 :
931 178 : CPLLocaleC localeC;
932 : /* -------------------------------------------------------------------- */
933 : /* Fixup ordering, missing linear units, etc. */
934 : /* -------------------------------------------------------------------- */
935 178 : eErr = Fixup();
936 178 : if( eErr != OGRERR_NONE )
937 0 : return eErr;
938 :
939 : /* -------------------------------------------------------------------- */
940 : /* Strip all CT parameters (AXIS, AUTHORITY, TOWGS84, etc). */
941 : /* -------------------------------------------------------------------- */
942 178 : eErr = StripCTParms();
943 178 : if( eErr != OGRERR_NONE )
944 0 : return eErr;
945 :
946 178 : if( GetRoot() == NULL )
947 0 : return OGRERR_NONE;
948 :
949 : /* -------------------------------------------------------------------- */
950 : /* There is a special case for Hotine Oblique Mercator to split */
951 : /* out the case with an angle to rectified grid. Bug 423 */
952 : /* -------------------------------------------------------------------- */
953 178 : const char *pszProjection = GetAttrValue("PROJECTION");
954 :
955 178 : if( pszProjection != NULL
956 : && EQUAL(pszProjection,SRS_PT_HOTINE_OBLIQUE_MERCATOR)
957 : && fabs(GetProjParm(SRS_PP_AZIMUTH, 0.0 )-90) < 0.0001
958 : && fabs(GetProjParm(SRS_PP_RECTIFIED_GRID_ANGLE, 0.0 )-90) < 0.0001 )
959 : {
960 : SetNode( "PROJCS|PROJECTION",
961 1 : "Hotine_Oblique_Mercator_Azimuth_Center" );
962 :
963 : /* ideally we should strip out of the rectified_grid_angle */
964 : // strip off rectified_grid_angle -- I hope it is 90!
965 1 : OGR_SRSNode *poPROJCS = GetAttrNode( "PROJCS" );
966 1 : int iRGAChild = FindProjParm( "rectified_grid_angle", poPROJCS );
967 1 : if( iRGAChild != -1 )
968 1 : poPROJCS->DestroyChild( iRGAChild);
969 :
970 1 : pszProjection = GetAttrValue("PROJECTION");
971 : }
972 :
973 : /* -------------------------------------------------------------------- */
974 : /* Polar_Stereographic maps to ESRI codes */
975 : /* Stereographic_South_Pole or Stereographic_North_Pole based */
976 : /* on latitude. */
977 : /* -------------------------------------------------------------------- */
978 178 : if( pszProjection != NULL
979 : && ( EQUAL(pszProjection,SRS_PT_POLAR_STEREOGRAPHIC) ))
980 : {
981 1 : if( GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) < 0.0 )
982 : {
983 : SetNode( "PROJCS|PROJECTION",
984 1 : "Stereographic_South_Pole" );
985 1 : pszProjection = GetAttrValue("PROJECTION");
986 : }
987 : else
988 : {
989 : SetNode( "PROJCS|PROJECTION",
990 0 : "Stereographic_North_Pole" );
991 0 : pszProjection = GetAttrValue("PROJECTION");
992 : }
993 : }
994 :
995 : /* -------------------------------------------------------------------- */
996 : /* OBLIQUE_STEREOGRAPHIC maps to ESRI Stereographic */
997 : /* -------------------------------------------------------------------- */
998 178 : if( pszProjection != NULL
999 : && ( EQUAL(pszProjection,SRS_PT_OBLIQUE_STEREOGRAPHIC) ))
1000 : {
1001 0 : SetNode( "PROJCS|PROJECTION", "Stereographic" );
1002 : }
1003 :
1004 : /* -------------------------------------------------------------------- */
1005 : /* Translate PROJECTION keywords that are misnamed. */
1006 : /* -------------------------------------------------------------------- */
1007 : GetRoot()->applyRemapper( "PROJECTION",
1008 : (char **)apszProjMapping+1,
1009 178 : (char **)apszProjMapping, 2 );
1010 178 : pszProjection = GetAttrValue("PROJECTION");
1011 :
1012 : /* -------------------------------------------------------------------- */
1013 : /* Translate DATUM keywords that are misnamed. */
1014 : /* -------------------------------------------------------------------- */
1015 178 : InitDatumMappingTable();
1016 :
1017 : GetRoot()->applyRemapper( "DATUM",
1018 178 : papszDatumMapping+2, papszDatumMapping+1, 3 );
1019 :
1020 178 : const char *pszProjCSName = NULL;
1021 178 : const char *pszGcsName = NULL;
1022 178 : OGR_SRSNode *poProjCS = NULL;
1023 178 : OGR_SRSNode *poProjCSNodeChild = NULL;
1024 :
1025 : /* -------------------------------------------------------------------- */
1026 : /* Very specific handling for some well known geographic */
1027 : /* coordinate systems. */
1028 : /* -------------------------------------------------------------------- */
1029 178 : OGR_SRSNode *poGeogCS = GetAttrNode( "GEOGCS" );
1030 178 : if( poGeogCS != NULL )
1031 : {
1032 178 : const char *pszGeogCSName = poGeogCS->GetChild(0)->GetValue();
1033 178 : const char *pszAuthName = GetAuthorityName("GEOGCS");
1034 178 : const char *pszUTMPrefix = NULL;
1035 178 : int nGCSCode = -1;
1036 :
1037 178 : if( pszAuthName != NULL && EQUAL(pszAuthName,"EPSG") )
1038 0 : nGCSCode = atoi(GetAuthorityCode("GEOGCS"));
1039 :
1040 273 : if( nGCSCode == 4326
1041 : || EQUAL(pszGeogCSName,"WGS84")
1042 : || EQUAL(pszGeogCSName,"WGS 84") )
1043 : {
1044 95 : poGeogCS->GetChild(0)->SetValue( "GCS_WGS_1984" );
1045 95 : pszUTMPrefix = "WGS_1984";
1046 : }
1047 112 : else if( nGCSCode == 4267
1048 : || EQUAL(pszGeogCSName,"NAD27")
1049 : || EQUAL(pszGeogCSName,"NAD 27") )
1050 : {
1051 29 : poGeogCS->GetChild(0)->SetValue( "GCS_North_American_1927" );
1052 29 : pszUTMPrefix = "NAD_1927";
1053 : }
1054 54 : else if( nGCSCode == 4269
1055 : || EQUAL(pszGeogCSName,"NAD83")
1056 : || EQUAL(pszGeogCSName,"NAD 83") )
1057 : {
1058 0 : poGeogCS->GetChild(0)->SetValue( "GCS_North_American_1983" );
1059 0 : pszUTMPrefix = "NAD_1983";
1060 : }
1061 :
1062 : /* -------------------------------------------------------------------- */
1063 : /* Force Unnamed to Unknown for most common locations. */
1064 : /* -------------------------------------------------------------------- */
1065 : static const char *apszUnknownMapping[] = {
1066 : "Unknown", "Unnamed",
1067 : NULL, NULL
1068 : };
1069 :
1070 : GetRoot()->applyRemapper( "PROJCS",
1071 : (char **)apszUnknownMapping+1,
1072 178 : (char **)apszUnknownMapping+0, 2 );
1073 : GetRoot()->applyRemapper( "GEOGCS",
1074 : (char **)apszUnknownMapping+1,
1075 178 : (char **)apszUnknownMapping+0, 2 );
1076 : GetRoot()->applyRemapper( "DATUM",
1077 : (char **)apszUnknownMapping+1,
1078 178 : (char **)apszUnknownMapping+0, 2 );
1079 : GetRoot()->applyRemapper( "SPHEROID",
1080 : (char **)apszUnknownMapping+1,
1081 178 : (char **)apszUnknownMapping+0, 2 );
1082 : GetRoot()->applyRemapper( "PRIMEM",
1083 : (char **)apszUnknownMapping+1,
1084 178 : (char **)apszUnknownMapping+0, 2 );
1085 :
1086 : /* -------------------------------------------------------------------- */
1087 : /* If the PROJCS name is unset, use the PROJECTION name in */
1088 : /* place of unknown, or unnamed. At the request of Peng Gao. */
1089 : /* -------------------------------------------------------------------- */
1090 178 : if( (poProjCS = GetAttrNode( "PROJCS" )) )
1091 83 : poProjCSNodeChild = poProjCS->GetChild(0);
1092 :
1093 178 : if( poProjCSNodeChild )
1094 : {
1095 83 : pszProjCSName = poProjCSNodeChild->GetValue();
1096 83 : char *pszNewValue = CPLStrdup(pszProjCSName);
1097 83 : MorphNameToESRI( &pszNewValue );
1098 83 : poProjCSNodeChild->SetValue( pszNewValue );
1099 83 : CPLFree( pszNewValue );
1100 83 : pszProjCSName = poProjCSNodeChild->GetValue();
1101 : }
1102 :
1103 178 : if( pszProjCSName != NULL
1104 : && ( EQUAL(pszProjCSName,"unnamed")
1105 : || EQUAL(pszProjCSName,"unknown")
1106 : || EQUAL(pszProjCSName,"") ) )
1107 : {
1108 3 : if( GetAttrValue( "PROJECTION", 0 ) != NULL )
1109 : {
1110 3 : pszProjCSName = GetAttrValue( "PROJECTION", 0 );
1111 3 : poProjCSNodeChild->SetValue( pszProjCSName );
1112 : }
1113 : }
1114 :
1115 : /* -------------------------------------------------------------------- */
1116 : /* Prepare very specific PROJCS names for UTM coordinate */
1117 : /* systems. */
1118 : /* -------------------------------------------------------------------- */
1119 178 : int bNorth = 0;
1120 178 : int nZone = 0;
1121 :
1122 : /* get zone from name first */
1123 178 : if( pszProjCSName && EQUALN(pszProjCSName, "UTM Zone ", 9) )
1124 : {
1125 0 : nZone = atoi(pszProjCSName+9);
1126 0 : if( strstr(pszProjCSName, "North") )
1127 0 : bNorth = 1;
1128 : }
1129 :
1130 : /* if can not get from the name, from the parameters */
1131 178 : if( nZone <= 0 )
1132 178 : nZone = GetUTMZone( &bNorth );
1133 :
1134 178 : if( nZone > 0 && pszUTMPrefix )
1135 : {
1136 : char szUTMName[128];
1137 31 : if( bNorth )
1138 30 : sprintf( szUTMName, "%s_UTM_Zone_%dN", pszUTMPrefix, nZone );
1139 : else
1140 1 : sprintf( szUTMName, "%s_UTM_Zone_%dS", pszUTMPrefix, nZone );
1141 :
1142 31 : if( poProjCSNodeChild )
1143 31 : poProjCSNodeChild->SetValue( szUTMName );
1144 : }
1145 : }
1146 :
1147 : /* -------------------------------------------------------------------- */
1148 : /* Translate UNIT keywords that are misnamed, or even the wrong */
1149 : /* case. */
1150 : /* -------------------------------------------------------------------- */
1151 : GetRoot()->applyRemapper( "UNIT",
1152 : (char **)apszUnitMapping+1,
1153 178 : (char **)apszUnitMapping, 2 );
1154 :
1155 : /* -------------------------------------------------------------------- */
1156 : /* reset constants for decimal degrees to the exact string ESRI */
1157 : /* expects when encountered to ensure a matchup. */
1158 : /* -------------------------------------------------------------------- */
1159 178 : OGR_SRSNode *poUnit = GetAttrNode( "GEOGCS|UNIT" );
1160 :
1161 178 : if( poUnit != NULL && poUnit->GetChildCount() >= 2
1162 : && ABS(GetAngularUnits()-0.0174532925199433) < 0.00000000001 )
1163 : {
1164 178 : poUnit->GetChild(0)->SetValue("Degree");
1165 178 : poUnit->GetChild(1)->SetValue("0.017453292519943295");
1166 : }
1167 :
1168 : /* -------------------------------------------------------------------- */
1169 : /* Make sure we reproduce US Feet exactly too. */
1170 : /* -------------------------------------------------------------------- */
1171 178 : poUnit = GetAttrNode( "PROJCS|UNIT" );
1172 :
1173 178 : if( poUnit != NULL && poUnit->GetChildCount() >= 2
1174 : && ABS(GetLinearUnits()- 0.30480060960121924) < 0.000000000000001)
1175 : {
1176 2 : poUnit->GetChild(0)->SetValue("Foot_US");
1177 2 : poUnit->GetChild(1)->SetValue("0.30480060960121924");
1178 : }
1179 :
1180 : /* -------------------------------------------------------------------- */
1181 : /* Remap parameters used for Albers and Mercator. */
1182 : /* -------------------------------------------------------------------- */
1183 178 : pszProjection = GetAttrValue("PROJECTION");
1184 178 : poProjCS = GetAttrNode( "PROJCS" );
1185 :
1186 178 : if( pszProjection != NULL && EQUAL(pszProjection,"Albers") )
1187 : GetRoot()->applyRemapper(
1188 : "PARAMETER", (char **)apszAlbersMapping + 1,
1189 0 : (char **)apszAlbersMapping + 0, 2 );
1190 :
1191 178 : if( pszProjection != NULL
1192 : && (EQUAL(pszProjection,SRS_PT_EQUIDISTANT_CONIC) ||
1193 : EQUAL(pszProjection,SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) ||
1194 : EQUAL(pszProjection,SRS_PT_AZIMUTHAL_EQUIDISTANT) ||
1195 : EQUAL(pszProjection,SRS_PT_SINUSOIDAL) ||
1196 : EQUAL(pszProjection,SRS_PT_ROBINSON) ) )
1197 : GetRoot()->applyRemapper(
1198 : "PARAMETER", (char **)apszECMapping + 1,
1199 2 : (char **)apszECMapping + 0, 2 );
1200 :
1201 178 : if( pszProjection != NULL && EQUAL(pszProjection,"Mercator") )
1202 : GetRoot()->applyRemapper(
1203 : "PARAMETER",
1204 : (char **)apszMercatorMapping + 1,
1205 0 : (char **)apszMercatorMapping + 0, 2 );
1206 :
1207 178 : if( pszProjection != NULL
1208 : && EQUALN(pszProjection,"Stereographic_",14)
1209 : && EQUALN(pszProjection+strlen(pszProjection)-5,"_Pole",5) )
1210 : GetRoot()->applyRemapper(
1211 : "PARAMETER",
1212 : (char **)apszPolarStereographicMapping + 1,
1213 1 : (char **)apszPolarStereographicMapping + 0, 2 );
1214 :
1215 178 : if( pszProjection != NULL && EQUAL(pszProjection,"Plate_Carree") )
1216 0 : if(FindProjParm( SRS_PP_STANDARD_PARALLEL_1, poProjCS ) < 0)
1217 : GetRoot()->applyRemapper(
1218 : "PARAMETER",
1219 : (char **)apszPolarStereographicMapping + 1,
1220 0 : (char **)apszPolarStereographicMapping + 0, 2 );
1221 :
1222 : /* -------------------------------------------------------------------- */
1223 : /* ESRI's Equidistant_Cylindrical does not support the */
1224 : /* latitude_of_origin keyword. */
1225 : /* -------------------------------------------------------------------- */
1226 178 : if( pszProjection != NULL
1227 : && EQUAL(pszProjection,"Equidistant_Cylindrical") )
1228 : {
1229 3 : if( GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0) != 0.0 )
1230 : {
1231 0 : CPLDebug( "OGR_ESRI", "Equirectangular with non-zero latitude of origin - not supported." );
1232 : }
1233 : else
1234 : {
1235 3 : OGR_SRSNode *poPROJCS = GetAttrNode("PROJCS");
1236 3 : if( poPROJCS )
1237 : poPROJCS->DestroyChild(
1238 3 : FindProjParm( SRS_PP_LATITUDE_OF_ORIGIN ) );
1239 : }
1240 : }
1241 :
1242 : /* -------------------------------------------------------------------- */
1243 : /* Convert SPHEROID name to use underscores instead of spaces. */
1244 : /* -------------------------------------------------------------------- */
1245 : OGR_SRSNode *poSpheroid;
1246 178 : OGR_SRSNode *poSpheroidChild = NULL;
1247 178 : poSpheroid = GetAttrNode( "SPHEROID" );
1248 178 : if( poSpheroid != NULL )
1249 178 : poSpheroidChild = poSpheroid->GetChild(0);
1250 :
1251 178 : if( poSpheroidChild != NULL )
1252 : {
1253 178 : char *pszNewValue = CPLStrdup(RemapSpheroidName(poSpheroidChild->GetValue()));
1254 :
1255 178 : MorphNameToESRI( &pszNewValue );
1256 :
1257 178 : poSpheroidChild->SetValue( pszNewValue );
1258 178 : CPLFree( pszNewValue );
1259 : }
1260 :
1261 178 : if( poSpheroid != NULL )
1262 178 : poSpheroidChild = poSpheroid->GetChild(2);
1263 :
1264 178 : if( poSpheroidChild != NULL )
1265 : {
1266 178 : const char * dfValue = poSpheroidChild->GetValue();
1267 2642 : for( int i = 0; apszInvFlatteningMapping[i] != NULL; i += 2 )
1268 : {
1269 2496 : if( EQUALN(apszInvFlatteningMapping[i], dfValue, strlen(apszInvFlatteningMapping[i]) ))
1270 : {
1271 32 : poSpheroidChild->SetValue( apszInvFlatteningMapping[i+1] );
1272 32 : break;
1273 : }
1274 : }
1275 : }
1276 :
1277 : /* -------------------------------------------------------------------- */
1278 : /* Try to insert a D_ in front of the datum name. */
1279 : /* -------------------------------------------------------------------- */
1280 : OGR_SRSNode *poDatum;
1281 :
1282 178 : poDatum = GetAttrNode( "DATUM" );
1283 178 : if( poDatum != NULL )
1284 178 : poDatum = poDatum->GetChild(0);
1285 :
1286 178 : if( poDatum != NULL )
1287 : {
1288 178 : const char* pszDatumName = poDatum->GetValue();
1289 178 : if( !EQUALN(pszDatumName, "D_",2) )
1290 : {
1291 : char *pszNewValue;
1292 :
1293 2 : pszNewValue = (char *) CPLMalloc(strlen(poDatum->GetValue())+3);
1294 2 : strcpy( pszNewValue, "D_" );
1295 2 : strcat( pszNewValue, poDatum->GetValue() );
1296 2 : poDatum->SetValue( pszNewValue );
1297 2 : CPLFree( pszNewValue );
1298 : }
1299 : }
1300 :
1301 : /* -------------------------------------------------------------------- */
1302 : /* final check names */
1303 : /* -------------------------------------------------------------------- */
1304 178 : if( poProjCSNodeChild )
1305 83 : pszProjCSName = poProjCSNodeChild->GetValue();
1306 :
1307 178 : if( pszProjCSName )
1308 : {
1309 83 : pszGcsName = GetAttrValue( "GEOGCS" );
1310 83 : if(pszGcsName && !EQUALN( pszGcsName, "GCS_", 4 ) )
1311 : {
1312 39 : char* newGcsName = (char *) CPLMalloc(strlen(pszGcsName) + 5);
1313 39 : strcpy( newGcsName, "GCS_" );
1314 39 : strcat(newGcsName, pszGcsName);
1315 39 : SetNewName( this, "GEOGCS", newGcsName );
1316 39 : CPLFree( newGcsName );
1317 39 : pszGcsName = GetAttrValue("GEOGCS" );
1318 : }
1319 83 : RemapGeogCSName(this, pszGcsName);
1320 :
1321 : // Specific processing and remapping
1322 83 : pszProjection = GetAttrValue("PROJECTION");
1323 83 : if(pszProjection)
1324 : {
1325 83 : if(EQUAL(pszProjection,"Lambert_Conformal_Conic"))
1326 : {
1327 2 : if(FindProjParm( SRS_PP_STANDARD_PARALLEL_2, poProjCS ) < 0 )
1328 : {
1329 0 : int iChild = FindProjParm( SRS_PP_LATITUDE_OF_ORIGIN, poProjCS );
1330 0 : int iChild1 = FindProjParm( SRS_PP_STANDARD_PARALLEL_1, poProjCS );
1331 0 : if( iChild >= 0 && iChild1 < 0 )
1332 : {
1333 0 : const OGR_SRSNode *poParameter = poProjCS->GetChild(iChild);
1334 0 : if( poParameter )
1335 : {
1336 0 : OGR_SRSNode *poNewParm = new OGR_SRSNode( "PARAMETER" );
1337 0 : poNewParm->AddChild( new OGR_SRSNode( "standard_parallel_1" ) );
1338 0 : poNewParm->AddChild( new OGR_SRSNode( poParameter->GetChild(1)->GetValue() ) );
1339 0 : poProjCS->AddChild( poNewParm );
1340 : }
1341 : }
1342 : }
1343 : }
1344 :
1345 83 : if(EQUAL(pszProjection,"Plate_Carree"))
1346 : {
1347 0 : int iChild = FindProjParm( SRS_PP_STANDARD_PARALLEL_1, poProjCS );
1348 0 : if(iChild < 0)
1349 0 : iChild = FindProjParm( SRS_PP_PSEUDO_STD_PARALLEL_1, poProjCS );
1350 :
1351 0 : if(iChild >= 0)
1352 : {
1353 0 : const OGR_SRSNode *poParameter = poProjCS->GetChild(iChild);
1354 0 : if(!EQUAL(poParameter->GetChild(1)->GetValue(), "0.0") && !EQUAL(poParameter->GetChild(1)->GetValue(), "0"))
1355 : {
1356 0 : SetNode( "PROJCS|PROJECTION", "Equidistant_Cylindrical" );
1357 0 : pszProjection = GetAttrValue("PROJECTION");
1358 : }
1359 : }
1360 : }
1361 83 : DeleteParamBasedOnPrjName( this, pszProjection, (char **)apszDeleteParametersBasedOnProjection);
1362 83 : AddParamBasedOnPrjName( this, pszProjection, (char **)apszAddParametersBasedOnProjection);
1363 83 : RemapPValuesBasedOnProjCSAndPName( this, pszProjection, (char **)apszParamValueMapping);
1364 83 : RemapPNamesBasedOnProjCSAndPName( this, pszProjection, (char **)apszParamNameMapping);
1365 : }
1366 : }
1367 :
1368 178 : return OGRERR_NONE;
1369 : }
1370 :
1371 : /************************************************************************/
1372 : /* OSRMorphToESRI() */
1373 : /************************************************************************/
1374 :
1375 : /**
1376 : * \brief Convert in place to ESRI WKT format.
1377 : *
1378 : * This function is the same as the C++ method OGRSpatialReference::morphToESRI()
1379 : */
1380 10 : OGRErr OSRMorphToESRI( OGRSpatialReferenceH hSRS )
1381 :
1382 : {
1383 10 : VALIDATE_POINTER1( hSRS, "OSRMorphToESRI", CE_Failure );
1384 :
1385 10 : return ((OGRSpatialReference *) hSRS)->morphToESRI();
1386 : }
1387 :
1388 : /************************************************************************/
1389 : /* morphFromESRI() */
1390 : /* */
1391 : /* modify this definition from the ESRI definition of WKT to */
1392 : /* the "Standard" definition. */
1393 : /************************************************************************/
1394 :
1395 : /**
1396 : * \brief Convert in place from ESRI WKT format.
1397 : *
1398 : * The value notes of this coordinate system are modified in various manners
1399 : * to adhere more closely to the WKT standard. This mostly involves
1400 : * translating a variety of ESRI names for projections, arguments and
1401 : * datums to "standard" names, as defined by Adam Gawne-Cain's reference
1402 : * translation of EPSG to WKT for the CT specification.
1403 : *
1404 : * This does the same as the C function OSRMorphFromESRI().
1405 : *
1406 : * @return OGRERR_NONE unless something goes badly wrong.
1407 : */
1408 :
1409 374 : OGRErr OGRSpatialReference::morphFromESRI()
1410 :
1411 : {
1412 374 : OGRErr eErr = OGRERR_NONE;
1413 :
1414 374 : if( GetRoot() == NULL )
1415 0 : return OGRERR_NONE;
1416 :
1417 : /* -------------------------------------------------------------------- */
1418 : /* Translate DATUM keywords that are oddly named. */
1419 : /* -------------------------------------------------------------------- */
1420 374 : InitDatumMappingTable();
1421 :
1422 : GetRoot()->applyRemapper( "DATUM",
1423 : (char **)papszDatumMapping+1,
1424 374 : (char **)papszDatumMapping+2, 3 );
1425 :
1426 : /* -------------------------------------------------------------------- */
1427 : /* Try to remove any D_ in front of the datum name. */
1428 : /* -------------------------------------------------------------------- */
1429 : OGR_SRSNode *poDatum;
1430 :
1431 374 : poDatum = GetAttrNode( "DATUM" );
1432 374 : if( poDatum != NULL )
1433 374 : poDatum = poDatum->GetChild(0);
1434 :
1435 374 : if( poDatum != NULL )
1436 : {
1437 374 : if( EQUALN(poDatum->GetValue(),"D_",2) )
1438 : {
1439 0 : char *pszNewValue = CPLStrdup( poDatum->GetValue() + 2 );
1440 0 : poDatum->SetValue( pszNewValue );
1441 0 : CPLFree( pszNewValue );
1442 : }
1443 : }
1444 :
1445 : /* -------------------------------------------------------------------- */
1446 : /* Split Lambert_Conformal_Conic into 1SP or 2SP form. */
1447 : /* */
1448 : /* See bugzilla.remotesensing.org/show_bug.cgi?id=187 */
1449 : /* */
1450 : /* We decide based on whether it has 2SPs. We used to assume */
1451 : /* 1SP if it had a scale factor but that turned out to be a */
1452 : /* poor test. */
1453 : /* -------------------------------------------------------------------- */
1454 374 : const char *pszProjection = GetAttrValue("PROJECTION");
1455 :
1456 374 : if( pszProjection != NULL
1457 : && EQUAL(pszProjection,"Lambert_Conformal_Conic") )
1458 : {
1459 10 : if( GetProjParm( SRS_PP_STANDARD_PARALLEL_1, 1000.0 ) != 1000.0
1460 : && GetProjParm( SRS_PP_STANDARD_PARALLEL_2, 1000.0 ) != 1000.0 )
1461 : SetNode( "PROJCS|PROJECTION",
1462 10 : SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP );
1463 : else
1464 : SetNode( "PROJCS|PROJECTION",
1465 0 : SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP );
1466 :
1467 10 : pszProjection = GetAttrValue("PROJECTION");
1468 : }
1469 :
1470 : /* -------------------------------------------------------------------- */
1471 : /* If we are remapping Hotine_Oblique_Mercator_Azimuth_Center */
1472 : /* add a rectified_grid_angle parameter - to match the azimuth */
1473 : /* I guess. */
1474 : /* -------------------------------------------------------------------- */
1475 374 : if( pszProjection != NULL
1476 : && EQUAL(pszProjection,"Hotine_Oblique_Mercator_Azimuth_Center") )
1477 : {
1478 : SetProjParm( SRS_PP_RECTIFIED_GRID_ANGLE ,
1479 1 : GetProjParm( SRS_PP_AZIMUTH, 0.0 ) );
1480 1 : FixupOrdering();
1481 : }
1482 :
1483 : /* -------------------------------------------------------------------- */
1484 : /* Remap Albers, Mercator and Polar Stereographic parameters. */
1485 : /* -------------------------------------------------------------------- */
1486 374 : if( pszProjection != NULL && EQUAL(pszProjection,"Albers") )
1487 : GetRoot()->applyRemapper(
1488 : "PARAMETER", (char **)apszAlbersMapping + 0,
1489 0 : (char **)apszAlbersMapping + 1, 2 );
1490 :
1491 374 : if( pszProjection != NULL
1492 : && (EQUAL(pszProjection,SRS_PT_EQUIDISTANT_CONIC) ||
1493 : EQUAL(pszProjection,SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) ||
1494 : EQUAL(pszProjection,SRS_PT_AZIMUTHAL_EQUIDISTANT) ||
1495 : EQUAL(pszProjection,SRS_PT_SINUSOIDAL) ||
1496 : EQUAL(pszProjection,SRS_PT_ROBINSON) ) )
1497 : GetRoot()->applyRemapper(
1498 : "PARAMETER", (char **)apszECMapping + 0,
1499 2 : (char **)apszECMapping + 1, 2 );
1500 :
1501 374 : if( pszProjection != NULL && EQUAL(pszProjection,"Mercator") )
1502 : GetRoot()->applyRemapper(
1503 : "PARAMETER",
1504 : (char **)apszMercatorMapping + 0,
1505 0 : (char **)apszMercatorMapping + 1, 2 );
1506 :
1507 374 : if( pszProjection != NULL
1508 : && EQUALN(pszProjection,"Stereographic_",14)
1509 : && EQUALN(pszProjection+strlen(pszProjection)-5,"_Pole",5) )
1510 : GetRoot()->applyRemapper(
1511 : "PARAMETER",
1512 : (char **)apszPolarStereographicMapping + 0,
1513 1 : (char **)apszPolarStereographicMapping + 1, 2 );
1514 :
1515 : /* -------------------------------------------------------------------- */
1516 : /* Remap south and north polar stereographic to one value. */
1517 : /* -------------------------------------------------------------------- */
1518 374 : if( pszProjection != NULL
1519 : && EQUALN(pszProjection,"Stereographic_",14)
1520 : && EQUALN(pszProjection+strlen(pszProjection)-5,"_Pole",5) )
1521 : {
1522 1 : SetNode( "PROJCS|PROJECTION", SRS_PT_POLAR_STEREOGRAPHIC );
1523 1 : pszProjection = GetAttrValue("PROJECTION");
1524 : }
1525 :
1526 : /* -------------------------------------------------------------------- */
1527 : /* Remap Equidistant_Cylindrical parameter. It is same as */
1528 : /* Stereographic */
1529 : /* -------------------------------------------------------------------- */
1530 : #ifdef notdef
1531 : if( pszProjection != NULL && EQUAL(pszProjection,"Equidistant_Cylindrical") )
1532 : GetRoot()->applyRemapper(
1533 : "PARAMETER",
1534 : (char **)apszPolarStereographicMapping + 0,
1535 : (char **)apszPolarStereographicMapping + 1, 2 );
1536 : #endif
1537 :
1538 : /* -------------------------------------------------------------------- */
1539 : /* Translate PROJECTION keywords that are misnamed. */
1540 : /* -------------------------------------------------------------------- */
1541 : GetRoot()->applyRemapper( "PROJECTION",
1542 : (char **)apszProjMapping,
1543 374 : (char **)apszProjMapping+1, 2 );
1544 :
1545 : /* -------------------------------------------------------------------- */
1546 : /* Translate DATUM keywords that are misnamed. */
1547 : /* -------------------------------------------------------------------- */
1548 374 : InitDatumMappingTable();
1549 :
1550 : GetRoot()->applyRemapper( "DATUM",
1551 : (char **)papszDatumMapping+1,
1552 374 : (char **)papszDatumMapping+2, 3 );
1553 :
1554 374 : return eErr;
1555 : }
1556 :
1557 : /************************************************************************/
1558 : /* OSRMorphFromESRI() */
1559 : /************************************************************************/
1560 :
1561 : /**
1562 : * \brief Convert in place from ESRI WKT format.
1563 : *
1564 : * This function is the same as the C++ method OGRSpatialReference::morphFromESRI()
1565 : */
1566 9 : OGRErr OSRMorphFromESRI( OGRSpatialReferenceH hSRS )
1567 :
1568 : {
1569 9 : VALIDATE_POINTER1( hSRS, "OSRMorphFromESRI", CE_Failure );
1570 :
1571 9 : return ((OGRSpatialReference *) hSRS)->morphFromESRI();
1572 : }
1573 :
1574 : /************************************************************************/
1575 : /* SetNewName() */
1576 : /* */
1577 : /* Set an esri name */
1578 : /************************************************************************/
1579 39 : void SetNewName( OGRSpatialReference* pOgr, const char* keyName, const char* newName )
1580 : {
1581 39 : OGR_SRSNode *poNode = pOgr->GetAttrNode( keyName );
1582 39 : OGR_SRSNode *poNodeChild = NULL;
1583 39 : if(poNode)
1584 39 : poNodeChild = poNode->GetChild(0);
1585 39 : if( poNodeChild)
1586 39 : poNodeChild->SetValue( newName);
1587 39 : }
1588 :
1589 : /************************************************************************/
1590 : /* RemapImgWGSProjcsName() */
1591 : /* */
1592 : /* Convert Img projcs names to ESRI style */
1593 : /************************************************************************/
1594 0 : int RemapImgWGSProjcsName( OGRSpatialReference* pOgr, const char* pszProjCSName, const char* pszProgCSName )
1595 : {
1596 0 : if(EQUAL(pszProgCSName, "WGS_1972") || EQUAL(pszProgCSName, "WGS_1984") )
1597 : {
1598 0 : char* newName = (char *) CPLMalloc(strlen(pszProjCSName) + 10);
1599 0 : sprintf( newName, "%s_", pszProgCSName );
1600 0 : strcat(newName, pszProjCSName);
1601 0 : SetNewName( pOgr, "PROJCS", newName );
1602 0 : CPLFree( newName );
1603 0 : return 1;
1604 : }
1605 0 : return -1;
1606 : }
1607 :
1608 : /************************************************************************/
1609 : /* RemapImgUTMNames() */
1610 : /* */
1611 : /* Convert Img UTM names to ESRI style */
1612 : /************************************************************************/
1613 :
1614 : int RemapImgUTMNames( OGRSpatialReference* pOgr, const char* pszProjCSName, const char* pszProgCSName,
1615 0 : char **mappingTable )
1616 : {
1617 : long i;
1618 0 : long iIndex = -1;
1619 0 : for( i = 0; mappingTable[i] != NULL; i += 5 )
1620 : {
1621 0 : if( EQUAL(pszProjCSName, mappingTable[i]) )
1622 : {
1623 0 : long j = i;
1624 0 : while(mappingTable[j] != NULL && EQUAL(mappingTable[i], mappingTable[j]))
1625 : {
1626 0 : if( EQUAL(pszProgCSName, mappingTable[j+1]) )
1627 : {
1628 0 : iIndex = j;
1629 0 : break;
1630 : }
1631 0 : j += 5;
1632 : }
1633 0 : if (iIndex >= 0)
1634 0 : break;
1635 : }
1636 : }
1637 0 : if(iIndex >= 0)
1638 : {
1639 0 : OGR_SRSNode *poNode = pOgr->GetAttrNode( "PROJCS" );
1640 0 : OGR_SRSNode *poNodeChild = NULL;
1641 0 : if(poNode)
1642 0 : poNodeChild = poNode->GetChild(0);
1643 0 : if( poNodeChild && strlen(poNodeChild->GetValue()) > 0 )
1644 0 : poNodeChild->SetValue( mappingTable[iIndex+2]);
1645 :
1646 0 : poNode = pOgr->GetAttrNode( "GEOGCS" );
1647 0 : poNodeChild = NULL;
1648 0 : if(poNode)
1649 0 : poNodeChild = poNode->GetChild(0);
1650 0 : if( poNodeChild && strlen(poNodeChild->GetValue()) > 0 )
1651 0 : poNodeChild->SetValue( mappingTable[iIndex+3]);
1652 :
1653 0 : poNode = pOgr->GetAttrNode( "DATUM" );
1654 0 : poNodeChild = NULL;
1655 0 : if(poNode)
1656 0 : poNodeChild = poNode->GetChild(0);
1657 0 : if( poNodeChild && strlen(poNodeChild->GetValue()) > 0 )
1658 0 : poNodeChild->SetValue( mappingTable[iIndex+4]);
1659 : }
1660 0 : return iIndex;
1661 : }
1662 :
1663 : /************************************************************************/
1664 : /* RemapNameBasedOnKeyName() */
1665 : /* */
1666 : /* Convert a name to ESRI style name */
1667 : /************************************************************************/
1668 :
1669 : int RemapNameBasedOnKeyName( OGRSpatialReference* pOgr, const char* pszName, const char* pszkeyName,
1670 82 : char **mappingTable )
1671 : {
1672 : long i, n;
1673 82 : long iIndex = -1;
1674 2952 : for( i = 0; mappingTable[i] != NULL; i += 2 )
1675 : {
1676 2870 : n = strlen(pszName);
1677 2870 : if( EQUALN(pszName, mappingTable[i],n) )
1678 : {
1679 0 : iIndex = i;
1680 0 : break;
1681 : }
1682 : }
1683 82 : if(iIndex >= 0)
1684 : {
1685 0 : OGR_SRSNode *poNode = pOgr->GetAttrNode( pszkeyName );
1686 0 : OGR_SRSNode *poNodeChild = NULL;
1687 0 : if(poNode)
1688 0 : poNodeChild = poNode->GetChild(0);
1689 0 : if( poNodeChild && strlen(poNodeChild->GetValue()) > 0 )
1690 0 : poNodeChild->SetValue( mappingTable[iIndex+1]);
1691 : }
1692 82 : return iIndex;
1693 : }
1694 :
1695 : /************************************************************************/
1696 : /* RemapNamesBasedOnTwo() */
1697 : /* */
1698 : /* Convert a name to ESRI style name */
1699 : /************************************************************************/
1700 :
1701 : int RemapNamesBasedOnTwo( OGRSpatialReference* pOgr, const char* name1, const char* name2,
1702 : char **mappingTable, long nTableStepSize,
1703 248 : char** pszkeyNames, long nKeys )
1704 : {
1705 : long i, n, n1;
1706 248 : long iIndex = -1;
1707 1242 : for( i = 0; mappingTable[i] != NULL; i += nTableStepSize )
1708 : {
1709 995 : n = strlen(name1);
1710 995 : n1 = strlen(mappingTable[i]);
1711 995 : if( EQUALN(name1, mappingTable[i], n1<=n? n1 : n) )
1712 : {
1713 1 : long j = i;
1714 2 : while(mappingTable[j] != NULL && EQUAL(mappingTable[i], mappingTable[j]))
1715 : {
1716 1 : if( EQUALN(name2, mappingTable[j+1], strlen(mappingTable[j+1])) )
1717 : {
1718 1 : iIndex = j;
1719 1 : break;
1720 : }
1721 0 : j += 3;
1722 : }
1723 1 : if (iIndex >= 0)
1724 1 : break;
1725 : }
1726 : }
1727 248 : if(iIndex >= 0)
1728 : {
1729 2 : for( i = 0; i < nKeys; i ++ )
1730 : {
1731 1 : OGR_SRSNode *poNode = pOgr->GetAttrNode( pszkeyNames[i] );
1732 1 : OGR_SRSNode *poNodeChild = NULL;
1733 1 : if(poNode)
1734 1 : poNodeChild = poNode->GetChild(0);
1735 1 : if( poNodeChild && strlen(poNodeChild->GetValue()) > 0 )
1736 1 : poNodeChild->SetValue( mappingTable[iIndex+i+2]);
1737 : }
1738 :
1739 : }
1740 248 : return iIndex;
1741 : }
1742 :
1743 : /************************************************************************/
1744 : /* RemapPValuesBasedOnProjCSAndPName() */
1745 : /* */
1746 : /* Convert a parameters to ESRI style name */
1747 : /************************************************************************/
1748 :
1749 : int RemapPValuesBasedOnProjCSAndPName( OGRSpatialReference* pOgr, const char* pszProgCSName,
1750 83 : char **mappingTable )
1751 : {
1752 83 : long ret = 0;
1753 83 : OGR_SRSNode *poPROJCS = pOgr->GetAttrNode( "PROJCS" );
1754 463 : for( int i = 0; mappingTable[i] != NULL; i += 4 )
1755 : {
1756 1186 : while( mappingTable[i] != NULL && EQUALN(pszProgCSName, mappingTable[i], strlen(mappingTable[i])) )
1757 : {
1758 : OGR_SRSNode *poParm;
1759 284 : const char* pszParamName = mappingTable[i+1];
1760 284 : const char* pszParamValue = mappingTable[i+2];
1761 2840 : for( int iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ )
1762 : {
1763 2556 : poParm = poPROJCS->GetChild( iChild );
1764 :
1765 2556 : if( EQUAL(poParm->GetValue(),"PARAMETER")
1766 : && poParm->GetChildCount() == 2
1767 : && EQUAL(poParm->GetChild(0)->GetValue(),pszParamName)
1768 : && EQUALN(poParm->GetChild(1)->GetValue(),pszParamValue, strlen(pszParamValue) ) )
1769 : {
1770 0 : poParm->GetChild(1)->SetValue( mappingTable[i+3] );
1771 0 : break;
1772 : }
1773 : }
1774 284 : ret ++;
1775 284 : i += 4;
1776 : }
1777 451 : if (ret > 0)
1778 71 : break;
1779 : }
1780 83 : return ret;
1781 : }
1782 :
1783 : /************************************************************************/
1784 : /* RemapPNamesBasedOnProjCSAndPName() */
1785 : /* */
1786 : /* Convert a parameters to ESRI style name */
1787 : /************************************************************************/
1788 :
1789 : int RemapPNamesBasedOnProjCSAndPName( OGRSpatialReference* pOgr, const char* pszProgCSName,
1790 83 : char **mappingTable )
1791 : {
1792 83 : long ret = 0;
1793 83 : OGR_SRSNode *poPROJCS = pOgr->GetAttrNode( "PROJCS" );
1794 733 : for( int i = 0; mappingTable[i] != NULL; i += 3 )
1795 : {
1796 1307 : while( mappingTable[i] != NULL && EQUALN(pszProgCSName, mappingTable[i], strlen(mappingTable[i])) )
1797 : {
1798 : OGR_SRSNode *poParm;
1799 3 : const char* pszParamName = mappingTable[i+1];
1800 22 : for( int iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ )
1801 : {
1802 20 : poParm = poPROJCS->GetChild( iChild );
1803 :
1804 20 : if( EQUAL(poParm->GetValue(),"PARAMETER")
1805 : && poParm->GetChildCount() == 2
1806 : && EQUAL(poParm->GetChild(0)->GetValue(),pszParamName) )
1807 : {
1808 1 : poParm->GetChild(0)->SetValue( mappingTable[i+2] );
1809 1 : break;
1810 : }
1811 : }
1812 3 : ret ++;
1813 3 : i += 3;
1814 : }
1815 652 : if (ret > 0)
1816 2 : break;
1817 : }
1818 83 : return ret;
1819 : }
1820 :
1821 : /************************************************************************/
1822 : /* DeleteParamBasedOnPrjName */
1823 : /* */
1824 : /* Delete non-ESRI parameters */
1825 : /************************************************************************/
1826 : int DeleteParamBasedOnPrjName( OGRSpatialReference* pOgr, const char* pszProjectionName,
1827 83 : char **mappingTable )
1828 : {
1829 83 : long iIndex = -1, ret = -1;
1830 913 : for( int i = 0; mappingTable[i] != NULL; i += 2 )
1831 : {
1832 830 : if( EQUALN(pszProjectionName, mappingTable[i], strlen(mappingTable[i])) )
1833 : {
1834 6 : OGR_SRSNode *poPROJCS = pOgr->GetAttrNode( "PROJCS" );
1835 : OGR_SRSNode *poParm;
1836 6 : const char* pszParamName = mappingTable[i+1];
1837 6 : iIndex = -1;
1838 47 : for( int iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ )
1839 : {
1840 43 : poParm = poPROJCS->GetChild( iChild );
1841 :
1842 43 : if( EQUAL(poParm->GetValue(),"PARAMETER")
1843 : && poParm->GetChildCount() == 2
1844 : && EQUAL(poParm->GetChild(0)->GetValue(),pszParamName) )
1845 : {
1846 2 : iIndex = iChild;
1847 2 : break;
1848 : }
1849 : }
1850 6 : if(iIndex >= 0)
1851 : {
1852 2 : poPROJCS->DestroyChild( iIndex );
1853 2 : ret ++;
1854 : }
1855 : }
1856 : }
1857 83 : return ret;
1858 : }
1859 : /************************************************************************/
1860 : /* AddParamBasedOnPrjName() */
1861 : /* */
1862 : /* Add ESRI style parameters */
1863 : /************************************************************************/
1864 : int AddParamBasedOnPrjName( OGRSpatialReference* pOgr, const char* pszProjectionName,
1865 83 : char **mappingTable )
1866 : {
1867 83 : long ret = -1;
1868 83 : OGR_SRSNode *poPROJCS = pOgr->GetAttrNode( "PROJCS" );
1869 332 : for( int i = 0; mappingTable[i] != NULL; i += 3 )
1870 : {
1871 249 : if( EQUALN(pszProjectionName, mappingTable[i], strlen(mappingTable[i])) )
1872 : {
1873 : OGR_SRSNode *poParm;
1874 2 : int exist = 0;
1875 23 : for( int iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ )
1876 : {
1877 21 : poParm = poPROJCS->GetChild( iChild );
1878 :
1879 21 : if( EQUAL(poParm->GetValue(),"PARAMETER")
1880 : && poParm->GetChildCount() == 2
1881 : && EQUAL(poParm->GetChild(0)->GetValue(),mappingTable[i+1]) )
1882 1 : exist = 1;
1883 : }
1884 2 : if(!exist)
1885 : {
1886 1 : poParm = new OGR_SRSNode( "PARAMETER" );
1887 2 : poParm->AddChild( new OGR_SRSNode( mappingTable[i+1] ) );
1888 2 : poParm->AddChild( new OGR_SRSNode( mappingTable[i+2] ) );
1889 1 : poPROJCS->AddChild( poParm );
1890 1 : ret ++;
1891 : }
1892 : }
1893 : }
1894 83 : return ret;
1895 : }
1896 :
1897 : /************************************************************************/
1898 : /* RemapGeogCSName() */
1899 : /* */
1900 : /* Convert names to ESRI style */
1901 : /************************************************************************/
1902 83 : int RemapGeogCSName( OGRSpatialReference* pOgr, const char *pszGeogCSName )
1903 : {
1904 : static const char *keyNamesG[] = {
1905 : "GEOGCS"};
1906 83 : int ret = -1;
1907 :
1908 83 : const char* pszUnitName = pOgr->GetAttrValue( "GEOGCS|UNIT");
1909 83 : if(pszUnitName)
1910 83 : ret = RemapNamesBasedOnTwo( pOgr, pszGeogCSName+4, pszUnitName, (char**)apszGcsNameMappingBasedOnUnit, 3, (char**)keyNamesG, 1);
1911 83 : if(ret < 0)
1912 : {
1913 83 : const char* pszPrimeName = pOgr->GetAttrValue("PRIMEM");
1914 83 : if(pszPrimeName)
1915 83 : ret = RemapNamesBasedOnTwo( pOgr, pszGeogCSName+4, pszPrimeName, (char**)apszGcsNameMappingBasedPrime, 3, (char**)keyNamesG, 1);
1916 83 : if(ret < 0)
1917 82 : ret = RemapNameBasedOnKeyName( pOgr, pszGeogCSName+4, "GEOGCS", (char**)apszGcsNameMapping);
1918 : }
1919 83 : if(ret < 0)
1920 : {
1921 82 : const char* pszProjCS = pOgr->GetAttrValue( "PROJCS" );
1922 82 : ret = RemapNamesBasedOnTwo( pOgr, pszProjCS, pszGeogCSName, (char**)apszGcsNameMappingBasedOnProjCS, 3, (char**)keyNamesG, 1);
1923 : }
1924 83 : return ret;
1925 : }
1926 :
|