LTP GCOV extension - code coverage report
Current view: directory - ogr - ogr_srs_esri.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 613
Code covered: 72.6 % Executed lines: 445

       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                 : 

Generated by: LTP GCOV extension version 1.5