LCOV - code coverage report
Current view: directory - ogr - ogr_srs_esri.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 811 620 76.4 %
Date: 2011-12-18 Functions: 28 23 82.1 %

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

Generated by: LCOV version 1.7