LCOV - code coverage report
Current view: directory - ogr - ogr_srs_esri.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 818 584 71.4 %
Date: 2012-12-26 Functions: 28 22 78.6 %

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

Generated by: LCOV version 1.7