LCOV - code coverage report
Current view: directory - ogr - ogr_srs_esri.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 817 586 71.7 %
Date: 2013-03-30 Functions: 28 22 78.6 %

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

Generated by: LCOV version 1.7