LCOV - code coverage report
Current view: directory - ogr - ogr_srs_esri.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 627 461 73.5 %
Date: 2010-01-09 Functions: 23 20 87.0 %

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

Generated by: LCOV version 1.7