LCOV - code coverage report
Current view: directory - ogr - ogr_srs_proj4.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 705 610 86.5 %
Date: 2011-12-18 Functions: 11 11 100.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogr_srs_proj4.cpp 23246 2011-10-17 18:47:08Z etourigny $
       3                 :  *
       4                 :  * Project:  OpenGIS Simple Features Reference Implementation
       5                 :  * Purpose:  OGRSpatialReference interface to PROJ.4.
       6                 :  * Author:   Frank Warmerdam <warmerdam@pobox.com>
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 1999,  Les Technologies SoftMap Inc. 
      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_conv.h"
      33                 : 
      34                 : extern int EPSGGetWGS84Transform( int nGeogCS, double *padfTransform );
      35                 : 
      36                 : CPL_CVSID("$Id: ogr_srs_proj4.cpp 23246 2011-10-17 18:47:08Z etourigny $");
      37                 : 
      38                 : /* -------------------------------------------------------------------- */
      39                 : /*      The following list comes from osrs/proj/src/pj_ellps.c          */
      40                 : /*      ... please update from time to time.                            */
      41                 : /* -------------------------------------------------------------------- */
      42                 : static const char *ogr_pj_ellps[] = {
      43                 : "MERIT",        "a=6378137.0", "rf=298.257", "MERIT 1983",
      44                 : "SGS85",        "a=6378136.0", "rf=298.257",  "Soviet Geodetic System 85",
      45                 : "GRS80",        "a=6378137.0", "rf=298.257222101", "GRS 1980(IUGG, 1980)",
      46                 : "IAU76",        "a=6378140.0", "rf=298.257", "IAU 1976",
      47                 : "airy",         "a=6377563.396", "b=6356256.910", "Airy 1830",
      48                 : "APL4.9",       "a=6378137.0.",  "rf=298.25", "Appl. Physics. 1965",
      49                 : "NWL9D",        "a=6378145.0.",  "rf=298.25", "Naval Weapons Lab., 1965",
      50                 : "mod_airy",     "a=6377340.189", "b=6356034.446", "Modified Airy",
      51                 : "andrae",       "a=6377104.43",  "rf=300.0",    "Andrae 1876 (Den., Iclnd.)",
      52                 : "aust_SA",      "a=6378160.0", "rf=298.25", "Australian Natl & S. Amer. 1969",
      53                 : "GRS67",        "a=6378160.0", "rf=298.2471674270", "GRS 67(IUGG 1967)",
      54                 : "bessel",       "a=6377397.155", "rf=299.1528128", "Bessel 1841",
      55                 : "bess_nam",     "a=6377483.865", "rf=299.1528128", "Bessel 1841 (Namibia)",
      56                 : "clrk66",       "a=6378206.4", "b=6356583.8", "Clarke 1866",
      57                 : "clrk80",       "a=6378249.145", "rf=293.4663", "Clarke 1880 mod.",
      58                 : "CPM",          "a=6375738.7", "rf=334.29", "Comm. des Poids et Mesures 1799",
      59                 : "delmbr",       "a=6376428.",  "rf=311.5", "Delambre 1810 (Belgium)",
      60                 : "engelis",      "a=6378136.05", "rf=298.2566", "Engelis 1985",
      61                 : "evrst30",  "a=6377276.345", "rf=300.8017",  "Everest 1830",
      62                 : "evrst48",  "a=6377304.063", "rf=300.8017",  "Everest 1948",
      63                 : "evrst56",  "a=6377301.243", "rf=300.8017",  "Everest 1956",
      64                 : "evrst69",  "a=6377295.664", "rf=300.8017",  "Everest 1969",
      65                 : "evrstSS",  "a=6377298.556", "rf=300.8017",  "Everest (Sabah & Sarawak)",
      66                 : "fschr60",  "a=6378166.",   "rf=298.3", "Fischer (Mercury Datum) 1960",
      67                 : "fschr60m", "a=6378155.",   "rf=298.3", "Modified Fischer 1960",
      68                 : "fschr68",  "a=6378150.",   "rf=298.3", "Fischer 1968",
      69                 : "helmert",  "a=6378200.",   "rf=298.3", "Helmert 1906",
      70                 : "hough",        "a=6378270.0", "rf=297.", "Hough",
      71                 : "intl",         "a=6378388.0", "rf=297.", "International 1909 (Hayford)",
      72                 : "krass",        "a=6378245.0", "rf=298.3", "Krassovsky, 1942",
      73                 : "kaula",        "a=6378163.",  "rf=298.24", "Kaula 1961",
      74                 : "lerch",        "a=6378139.",  "rf=298.257", "Lerch 1979",
      75                 : "mprts",        "a=6397300.",  "rf=191.", "Maupertius 1738",
      76                 : "new_intl",     "a=6378157.5", "b=6356772.2", "New International 1967",
      77                 : "plessis",      "a=6376523.",  "b=6355863.", "Plessis 1817 (France)",
      78                 : "SEasia",       "a=6378155.0", "b=6356773.3205", "Southeast Asia",
      79                 : "walbeck",      "a=6376896.0", "b=6355834.8467", "Walbeck",
      80                 : "WGS60",    "a=6378165.0",  "rf=298.3", "WGS 60",
      81                 : "WGS66",        "a=6378145.0", "rf=298.25", "WGS 66",
      82                 : "WGS72",        "a=6378135.0", "rf=298.26", "WGS 72",
      83                 : "WGS84",    "a=6378137.0",  "rf=298.257223563", "WGS 84",
      84                 : "sphere",   "a=6370997.0",  "b=6370997.0", "Normal Sphere (r=6370997)",
      85                 : 0, 0, 0, 0,
      86                 : };
      87                 : 
      88                 : typedef struct
      89                 : {
      90                 :     const char* pszPJ;
      91                 :     const char* pszOGR;
      92                 :     int         nEPSG;
      93                 :     int         nGCS;
      94                 : } OGRProj4Datum;
      95                 : 
      96                 : /* Derived from proj/src/pj_datum.c */
      97                 : /* WGS84, NAD27 and NAD83 are directly hard-coded in the code */
      98                 : static const OGRProj4Datum ogr_pj_datums[] = {
      99                 :     { "GGRS87", "Greek_Geodetic_Reference_System_1987", 4121, 6121},
     100                 :     { "potsdam", "Deutsches_Hauptdreiecksnetz", 4314, 6314},
     101                 :     { "carthage", "Carthage", 4223, 6223},
     102                 :     { "hermannskogel", "Militar_Geographische_Institut", 4312, 6312},
     103                 :     { "ire65", "TM65", 4299, 6299},
     104                 :     { "nzgd49", "New_Zealand_Geodetic_Datum_1949", 4272, 6272},
     105                 :     { "OSGB36", "OSGB_1936", 4277, 6277}
     106                 : };
     107                 : 
     108                 : typedef struct
     109                 : {
     110                 :     const char* pszProj4PMName;
     111                 :     const char* pszWKTPMName;
     112                 :     const char* pszFromGreenwich;
     113                 :     int         nPMCode;
     114                 : } OGRProj4PM;
     115                 : 
     116                 : /* Derived from pj_datums.c */
     117                 : static const OGRProj4PM ogr_pj_pms [] = {
     118                 :     { "greenwich", "Greenwich", "0dE",               8901 },
     119                 :     { "lisbon",    "Lisbon",    "9d07'54.862\"W",    8902 },
     120                 :     { "paris",     "Paris",     "2d20'14.025\"E",    8903 },
     121                 :     { "bogota",    "Bogota",    "74d04'51.3\"W",     8904 },
     122                 :     { "madrid",    "Madrid",    "3d41'16.58\"W",     8905 },
     123                 :     { "rome",      "Rome",      "12d27'8.4\"E",      8906 },
     124                 :     { "bern",      "Bern",      "7d26'22.5\"E",      8907 },
     125                 :     { "jakarta",   "Jakarta",   "106d48'27.79\"E",   8908 },
     126                 :     { "ferro",     "Ferro",     "17d40'W",           8909 },
     127                 :     { "brussels",  "Brussels",  "4d22'4.71\"E",      8910 },
     128                 :     { "stockholm", "Stockholm", "18d3'29.8\"E",      8911 },
     129                 :     { "athens",    "Athens",    "23d42'58.815\"E",   8912 },
     130                 :     { "oslo",      "Oslo",      "10d43'22.5\"E",     8913 }
     131                 : };
     132                 : 
     133             171 : static const char* OGRGetProj4Datum(const char* pszDatum,
     134                 :                                     int nEPSGDatum)
     135                 : {
     136                 :     unsigned int i;
     137            1355 :     for(i=0;i<sizeof(ogr_pj_datums)/sizeof(ogr_pj_datums[0]);i++)
     138                 :     {
     139            1191 :         if (nEPSGDatum == ogr_pj_datums[i].nGCS ||
     140                 :             EQUAL(pszDatum, ogr_pj_datums[i].pszOGR))
     141                 :         {
     142               7 :             return ogr_pj_datums[i].pszPJ;
     143                 :         }
     144                 :     }
     145             164 :     return NULL;
     146                 : }
     147                 : 
     148               7 : static const OGRProj4PM* OGRGetProj4PMFromProj4Name(const char* pszProj4PMName)
     149                 : {
     150                 :     unsigned int i;
     151              46 :     for(i=0;i<sizeof(ogr_pj_pms)/sizeof(ogr_pj_pms[0]);i++)
     152                 :     {
     153              45 :         if (EQUAL(pszProj4PMName, ogr_pj_pms[i].pszProj4PMName))
     154                 :         {
     155               6 :             return &ogr_pj_pms[i];
     156                 :         }
     157                 :     }
     158               1 :     return NULL;
     159                 : }
     160                 : 
     161               7 : static const OGRProj4PM* OGRGetProj4PMFromCode(int nPMCode)
     162                 : {
     163                 :     unsigned int i;
     164              40 :     for(i=0;i<sizeof(ogr_pj_pms)/sizeof(ogr_pj_pms[0]);i++)
     165                 :     {
     166              40 :         if (nPMCode == ogr_pj_pms[i].nPMCode)
     167                 :         {
     168               7 :             return &ogr_pj_pms[i];
     169                 :         }
     170                 :     }
     171               0 :     return NULL;
     172                 : }
     173                 : 
     174               1 : static const OGRProj4PM* OGRGetProj4PMFromVal(double dfVal)
     175                 : {
     176                 :     unsigned int i;
     177               3 :     for(i=0;i<sizeof(ogr_pj_pms)/sizeof(ogr_pj_pms[0]);i++)
     178                 :     {
     179               3 :         if (fabs(dfVal - CPLDMSToDec(ogr_pj_pms[i].pszFromGreenwich)) < 1e-10)
     180                 :         {
     181               1 :             return &ogr_pj_pms[i];
     182                 :         }
     183                 :     }
     184               0 :     return NULL;
     185                 : }
     186                 : 
     187                 : /************************************************************************/
     188                 : /*                          OSRProj4Tokenize()                          */
     189                 : /*                                                                      */
     190                 : /*      Custom tokenizing function for PROJ.4 strings.  The main        */
     191                 : /*      reason we can't just use CSLTokenizeString is to handle         */
     192                 : /*      strings with a + sign in the exponents of parameter values.     */
     193                 : /************************************************************************/
     194                 : 
     195             134 : char **OSRProj4Tokenize( const char *pszFull )
     196                 : 
     197                 : {
     198             134 :     char *pszStart = NULL;
     199                 :     char *pszFullWrk;
     200             134 :     char **papszTokens = NULL;
     201                 :     int  i;
     202                 : 
     203             134 :     if( pszFull == NULL )
     204               0 :         return NULL;
     205                 : 
     206             134 :     pszFullWrk = CPLStrdup( pszFull );
     207                 : 
     208           10197 :     for( i=0; pszFullWrk[i] != '\0'; i++ )
     209                 :     {
     210           10063 :         switch( pszFullWrk[i] )
     211                 :         {
     212                 :           case '+':
     213             888 :             if( i == 0 || pszFullWrk[i-1] == '\0' )
     214                 :             {
     215             887 :                 if( pszStart != NULL )
     216                 :                 {
     217             755 :                     if( strstr(pszStart,"=") != NULL )
     218             732 :                         papszTokens = CSLAddString( papszTokens, pszStart );
     219                 :                     else
     220                 :                     {
     221              23 :                         CPLString osAsBoolean = pszStart;
     222              23 :                         osAsBoolean += "=yes";
     223              23 :                         papszTokens = CSLAddString( papszTokens, osAsBoolean );
     224                 :                     }
     225                 :                 }
     226             887 :                 pszStart = pszFullWrk + i + 1;
     227                 :             }
     228             888 :             break;
     229                 : 
     230                 :           case ' ':
     231                 :           case '\t':
     232                 :           case '\n':
     233             877 :             pszFullWrk[i] = '\0';
     234                 :             break;
     235                 : 
     236                 :           default:
     237                 :             break;
     238                 :         }
     239                 :     }
     240                 : 
     241             134 :     if( pszStart != NULL && strlen(pszStart) > 0 )
     242             132 :         papszTokens = CSLAddString( papszTokens, pszStart );
     243                 : 
     244             134 :     CPLFree( pszFullWrk );
     245                 : 
     246             134 :     return papszTokens;
     247                 : }
     248                 : 
     249                 : 
     250                 : /************************************************************************/
     251                 : /*                         OSRImportFromProj4()                         */
     252                 : /************************************************************************/
     253                 : /** 
     254                 :  * \brief Import PROJ.4 coordinate string.
     255                 :  *
     256                 :  * This function is the same as OGRSpatialReference::importFromProj4().
     257                 :  */
     258              69 : OGRErr OSRImportFromProj4( OGRSpatialReferenceH hSRS, const char *pszProj4 )
     259                 : 
     260                 : {
     261              69 :     VALIDATE_POINTER1( hSRS, "OSRImportFromProj4", CE_Failure );
     262                 : 
     263              69 :     return ((OGRSpatialReference *) hSRS)->importFromProj4( pszProj4 );
     264                 : }
     265                 : 
     266                 : /************************************************************************/
     267                 : /*                              OSR_GDV()                               */
     268                 : /*                                                                      */
     269                 : /*      Fetch a particular parameter out of the parameter list, or      */
     270                 : /*      the indicated default if it isn't available.  This is a         */
     271                 : /*      helper function for importFromProj4().                          */
     272                 : /************************************************************************/
     273                 : 
     274             560 : static double OSR_GDV( char **papszNV, const char * pszField, 
     275                 :                        double dfDefaultValue )
     276                 : 
     277                 : {
     278                 :     const char * pszValue;
     279                 : 
     280             560 :     pszValue = CSLFetchNameValue( papszNV, pszField );
     281                 : 
     282                 :     // special hack to use k_0 if available.
     283             560 :     if( pszValue == NULL && EQUAL(pszField,"k") )
     284               9 :         pszValue = CSLFetchNameValue( papszNV, "k_0" );
     285                 : 
     286             560 :     if( pszValue == NULL )
     287              66 :         return dfDefaultValue;
     288                 :     else
     289             494 :         return CPLDMSToDec(pszValue);
     290                 : }
     291                 : 
     292                 : /************************************************************************/
     293                 : /*                          importFromProj4()                           */
     294                 : /************************************************************************/
     295                 : 
     296                 : /**
     297                 :  * \brief Import PROJ.4 coordinate string.
     298                 :  *
     299                 :  * The OGRSpatialReference is initialized from the passed PROJ.4 style
     300                 :  * coordinate system string.  In addition to many +proj formulations which
     301                 :  * have OGC equivelents, it is also possible to import "+init=epsg:n" style
     302                 :  * definitions.  These are passed to importFromEPSG().  Other init strings
     303                 :  * (such as the state plane zones) are not currently supported.   
     304                 :  *
     305                 :  * Example:
     306                 :  *   pszProj4 = "+proj=utm +zone=11 +datum=WGS84" 
     307                 :  *
     308                 :  * Some parameters, such as grids, recognised by PROJ.4 may not be well
     309                 :  * understood and translated into the OGRSpatialReference model. It is possible
     310                 :  * to add the +wktext parameter which is a special keyword that OGR recognises
     311                 :  * as meaning "embed the entire PROJ.4 string in the WKT and use it literally
     312                 :  * when converting back to PROJ.4 format".
     313                 :  * 
     314                 :  * For example:
     315                 :  * "+proj=nzmg +lat_0=-41 +lon_0=173 +x_0=2510000 +y_0=6023150 +ellps=intl
     316                 :  *  +units=m +nadgrids=nzgd2kgrid0005.gsb +wktext"
     317                 :  *
     318                 :  * will be translated as :
     319                 :  * \code
     320                 :  * PROJCS["unnamed",
     321                 :  *    GEOGCS["International 1909 (Hayford)",
     322                 :  *        DATUM["unknown",
     323                 :  *            SPHEROID["intl",6378388,297]],
     324                 :  *        PRIMEM["Greenwich",0],
     325                 :  *        UNIT["degree",0.0174532925199433]],
     326                 :  *    PROJECTION["New_Zealand_Map_Grid"],
     327                 :  *    PARAMETER["latitude_of_origin",-41],
     328                 :  *    PARAMETER["central_meridian",173],
     329                 :  *    PARAMETER["false_easting",2510000],
     330                 :  *    PARAMETER["false_northing",6023150],
     331                 :  *    UNIT["Meter",1],
     332                 :  *    EXTENSION["PROJ4","+proj=nzmg +lat_0=-41 +lon_0=173 +x_0=2510000 
     333                 :  *               +y_0=6023150 +ellps=intl  +units=m +nadgrids=nzgd2kgrid0005.gsb +wktext"]]
     334                 :  * \endcode
     335                 :  *
     336                 :  * This method is the equivalent of the C function OSRImportFromProj4().
     337                 :  *
     338                 :  * @param pszProj4 the PROJ.4 style string. 
     339                 :  *
     340                 :  * @return OGRERR_NONE on success or OGRERR_CORRUPT_DATA on failure.
     341                 :  */
     342                 : 
     343             134 : OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
     344                 : 
     345                 : {
     346             134 :     char **papszNV = NULL;
     347                 :     char **papszTokens;
     348                 :     int  i;
     349                 :     char *pszCleanCopy;
     350                 : 
     351                 : /* -------------------------------------------------------------------- */
     352                 : /*      Clear any existing definition.                                  */
     353                 : /* -------------------------------------------------------------------- */
     354             134 :     Clear();
     355                 : 
     356                 : /* -------------------------------------------------------------------- */
     357                 : /*      Strip any newlines or other "funny" stuff that might occur      */
     358                 : /*      if this string just came from reading a file.                   */
     359                 : /* -------------------------------------------------------------------- */
     360             134 :     pszCleanCopy = CPLStrdup( pszProj4 );
     361            8633 :     for( i = 0; pszCleanCopy[i] != '\0'; i++ )
     362                 :     {
     363           25497 :         if( pszCleanCopy[i] == 10 
     364            8499 :             || pszCleanCopy[i] == 13 
     365            8499 :             || pszCleanCopy[i] == 9 )
     366               0 :             pszCleanCopy[i] = ' ';
     367                 :     }
     368                 : 
     369                 : /* -------------------------------------------------------------------- */
     370                 : /*      Try to normalize the definition.  This should expand +init=     */
     371                 : /*      clauses and so forth.                                           */
     372                 : /* -------------------------------------------------------------------- */
     373                 :     char *pszNormalized;
     374                 : 
     375             134 :     pszNormalized = OCTProj4Normalize( pszCleanCopy );
     376             134 :     CPLFree( pszCleanCopy );
     377                 :     
     378                 : /* -------------------------------------------------------------------- */
     379                 : /*      If we have an EPSG based init string, and no existing +proj     */
     380                 : /*      portion then try to normalize into into a PROJ.4 string.        */
     381                 : /* -------------------------------------------------------------------- */
     382             134 :     if( strstr(pszNormalized,"init=epsg:") != NULL 
     383                 :         && strstr(pszNormalized,"proj=") == NULL )
     384                 :     {
     385                 :         OGRErr eErr;
     386               0 :         const char *pszNumber = strstr(pszNormalized,"init=epsg:") + 10;
     387                 : 
     388               0 :         eErr = importFromEPSG( atoi(pszNumber) );
     389               0 :         if( eErr == OGRERR_NONE )
     390                 :         {
     391               0 :             CPLFree( pszNormalized );
     392               0 :             return eErr;
     393                 :         }
     394                 :     }
     395                 : 
     396                 : /* -------------------------------------------------------------------- */
     397                 : /*      Parse the PROJ.4 string into a cpl_string.h style name/value    */
     398                 : /*      list.                                                           */
     399                 : /* -------------------------------------------------------------------- */
     400             134 :     papszTokens = OSRProj4Tokenize( pszNormalized );
     401             134 :     CPLFree( pszNormalized );
     402                 :     
     403            1021 :     for( i = 0; papszTokens != NULL && papszTokens[i] != NULL; i++ )
     404                 :     {
     405             887 :         char *pszEqual = strstr(papszTokens[i],"=");
     406                 : 
     407             887 :         if( pszEqual == NULL )
     408              38 :             papszNV = CSLAddNameValue(papszNV, papszTokens[i], "" );
     409                 :         else
     410                 :         {
     411             849 :             pszEqual[0] = '\0';
     412             849 :             papszNV = CSLAddNameValue( papszNV, papszTokens[i], pszEqual+1 );
     413                 :         }
     414                 :     }
     415                 : 
     416             134 :     CSLDestroy( papszTokens );
     417                 : 
     418                 : /* -------------------------------------------------------------------- */
     419                 : /*      Extract the prime meridian, if there is one set.                */
     420                 : /* -------------------------------------------------------------------- */
     421             134 :     const char *pszPM = CSLFetchNameValue( papszNV, "pm" );
     422             134 :     double dfFromGreenwich = 0.0;
     423             134 :     int    nPMCode = -1;
     424                 : 
     425             134 :     if( pszPM != NULL )
     426                 :     {
     427               7 :         const OGRProj4PM* psProj4PM = OGRGetProj4PMFromProj4Name(pszPM);
     428               7 :         if (psProj4PM)
     429                 :         {
     430               6 :             dfFromGreenwich = CPLDMSToDec(psProj4PM->pszFromGreenwich);
     431               6 :             pszPM = psProj4PM->pszWKTPMName;
     432               6 :             nPMCode = psProj4PM->nPMCode;
     433                 :         }
     434                 :         else
     435                 :         {
     436               1 :             dfFromGreenwich = CPLDMSToDec( pszPM );
     437               1 :             pszPM = "unnamed";
     438                 :         }
     439                 :     }
     440                 :     else
     441             127 :         pszPM = "Greenwich";
     442                 : 
     443                 : /* -------------------------------------------------------------------- */
     444                 : /*      Operate on the basis of the projection name.                    */
     445                 : /* -------------------------------------------------------------------- */
     446             134 :     const char *pszProj = CSLFetchNameValue(papszNV,"proj");
     447                 : 
     448             134 :     if( pszProj == NULL )
     449                 :     {
     450               3 :         CPLDebug( "OGR_PROJ4", "Can't find +proj= in:\n%s", pszProj4 );
     451               3 :         CSLDestroy( papszNV );
     452               3 :         return OGRERR_CORRUPT_DATA;
     453                 :     }
     454                 : 
     455             131 :     else if( EQUAL(pszProj,"longlat") || EQUAL(pszProj,"latlong") )
     456                 :     {
     457                 :     }
     458                 :     
     459             118 :     else if( EQUAL(pszProj,"geocent") )
     460                 :     {
     461               2 :         SetGeocCS( "Geocentric" );
     462                 :     }
     463                 :     
     464             116 :     else if( EQUAL(pszProj,"bonne") )
     465                 :     {
     466                 :         SetBonne( OSR_GDV( papszNV, "lat_1", 0.0 ), 
     467                 :                   OSR_GDV( papszNV, "lon_0", 0.0 ), 
     468                 :                   OSR_GDV( papszNV, "x_0", 0.0 ), 
     469               1 :                   OSR_GDV( papszNV, "y_0", 0.0 ) );
     470                 :     }
     471                 : 
     472             115 :     else if( EQUAL(pszProj,"cass") )
     473                 :     {
     474                 :         SetCS( OSR_GDV( papszNV, "lat_0", 0.0 ), 
     475                 :                OSR_GDV( papszNV, "lon_0", 0.0 ), 
     476                 :                OSR_GDV( papszNV, "x_0", 0.0 ), 
     477               2 :                OSR_GDV( papszNV, "y_0", 0.0 ) );
     478                 :     }
     479                 : 
     480             113 :     else if( EQUAL(pszProj,"nzmg") )
     481                 :     {
     482                 :         SetNZMG( OSR_GDV( papszNV, "lat_0", -41.0 ), 
     483                 :                  OSR_GDV( papszNV, "lon_0", 173.0 ), 
     484                 :                  OSR_GDV( papszNV, "x_0", 2510000.0 ), 
     485               2 :                  OSR_GDV( papszNV, "y_0", 6023150.0 ) );
     486                 :     }
     487                 : 
     488             111 :     else if( EQUAL(pszProj,"cea") )
     489                 :     {
     490                 :         SetCEA( OSR_GDV( papszNV, "lat_ts", 0.0 ), 
     491                 :                 OSR_GDV( papszNV, "lon_0", 0.0 ), 
     492                 :                 OSR_GDV( papszNV, "x_0", 0.0 ), 
     493               3 :                 OSR_GDV( papszNV, "y_0", 0.0 ) );
     494                 :     }
     495                 : 
     496             108 :     else if( EQUAL(pszProj,"tmerc") )
     497                 :     {
     498               6 :         const char *pszAxis = CSLFetchNameValue( papszNV, "axis" );
     499                 : 
     500              11 :         if( pszAxis == NULL || !EQUAL(pszAxis,"wsu") )
     501                 :             SetTM( OSR_GDV( papszNV, "lat_0", 0.0 ), 
     502                 :                    OSR_GDV( papszNV, "lon_0", 0.0 ), 
     503                 :                    OSR_GDV( papszNV, "k", 1.0 ), 
     504                 :                    OSR_GDV( papszNV, "x_0", 0.0 ), 
     505               5 :                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     506                 :         else
     507                 :             SetTMSO( OSR_GDV( papszNV, "lat_0", 0.0 ), 
     508                 :                      OSR_GDV( papszNV, "lon_0", 0.0 ), 
     509                 :                      OSR_GDV( papszNV, "k", 1.0 ), 
     510                 :                      OSR_GDV( papszNV, "x_0", 0.0 ), 
     511               1 :                      OSR_GDV( papszNV, "y_0", 0.0 ) );
     512                 :     }
     513                 : 
     514             102 :     else if( EQUAL(pszProj,"utm") )
     515                 :     {
     516                 :         SetUTM( (int) OSR_GDV( papszNV, "zone", 0.0 ),
     517              12 :                 (int) OSR_GDV( papszNV, "south", 1.0 ) );
     518                 :     }
     519                 : 
     520              90 :     else if( EQUAL(pszProj,"merc") /* 2SP form */
     521                 :              && OSR_GDV(papszNV, "lat_ts", 1000.0) < 999.0 )
     522                 :     {
     523                 :         SetMercator2SP( OSR_GDV( papszNV, "lat_ts", 0.0 ), 
     524                 :                         0.0,
     525                 :                         OSR_GDV( papszNV, "lon_0", 0.0 ), 
     526                 :                         OSR_GDV( papszNV, "x_0", 0.0 ), 
     527               3 :                         OSR_GDV( papszNV, "y_0", 0.0 ) );
     528                 :     }
     529                 : 
     530              87 :     else if( EQUAL(pszProj,"merc") ) /* 1SP form */
     531                 :     {
     532                 :         SetMercator( 0.0,
     533                 :                      OSR_GDV( papszNV, "lon_0", 0.0 ), 
     534                 :                      OSR_GDV( papszNV, "k", 1.0 ), 
     535                 :                      OSR_GDV( papszNV, "x_0", 0.0 ), 
     536               3 :                      OSR_GDV( papszNV, "y_0", 0.0 ) );
     537                 :     }
     538                 : 
     539              84 :     else if( EQUAL(pszProj,"stere") 
     540                 :              && ABS(OSR_GDV( papszNV, "lat_0", 0.0 ) - 90) < 0.001 )
     541                 :     {
     542                 :         SetPS( OSR_GDV( papszNV, "lat_ts", 90.0 ), 
     543                 :                OSR_GDV( papszNV, "lon_0", 0.0 ), 
     544                 :                OSR_GDV( papszNV, "k", 1.0 ), 
     545                 :                OSR_GDV( papszNV, "x_0", 0.0 ), 
     546               4 :                OSR_GDV( papszNV, "y_0", 0.0 ) );
     547                 :     }
     548                 : 
     549              80 :     else if( EQUAL(pszProj,"stere") 
     550                 :              && ABS(OSR_GDV( papszNV, "lat_0", 0.0 ) + 90) < 0.001 )
     551                 :     {
     552                 :         SetPS( OSR_GDV( papszNV, "lat_ts", -90.0 ), 
     553                 :                OSR_GDV( papszNV, "lon_0", 0.0 ), 
     554                 :                OSR_GDV( papszNV, "k", 1.0 ), 
     555                 :                OSR_GDV( papszNV, "x_0", 0.0 ), 
     556               3 :                OSR_GDV( papszNV, "y_0", 0.0 ) );
     557                 :     }
     558                 : 
     559              77 :     else if( EQUAL(pszProj,"sterea") )
     560                 :     {
     561                 :         SetOS( OSR_GDV( papszNV, "lat_0", 0.0 ), 
     562                 :                OSR_GDV( papszNV, "lon_0", 0.0 ), 
     563                 :                OSR_GDV( papszNV, "k", 1.0 ), 
     564                 :                OSR_GDV( papszNV, "x_0", 0.0 ), 
     565               4 :                OSR_GDV( papszNV, "y_0", 0.0 ) );
     566                 :     }
     567                 : 
     568              73 :     else if( EQUAL(pszProj,"stere") )
     569                 :     {
     570                 :         SetStereographic( OSR_GDV( papszNV, "lat_0", 0.0 ), 
     571                 :                           OSR_GDV( papszNV, "lon_0", 0.0 ), 
     572                 :                           OSR_GDV( papszNV, "k", 1.0 ),  
     573                 :                           OSR_GDV( papszNV, "x_0", 0.0 ), 
     574               3 :                           OSR_GDV( papszNV, "y_0", 0.0 ) );
     575                 :     }
     576                 : 
     577              70 :     else if( EQUAL(pszProj,"eqc") )
     578                 :     {
     579               4 :         if( OSR_GDV( papszNV, "lat_ts", 0.0 ) != 0.0 )
     580                 :           SetEquirectangular2( OSR_GDV( papszNV, "lat_0", 0.0 ),
     581                 :                                OSR_GDV( papszNV, "lon_0", 0.0 ),
     582                 :                                OSR_GDV( papszNV, "lat_ts", 0.0 ),
     583                 :                                OSR_GDV( papszNV, "x_0", 0.0 ),
     584               2 :                                OSR_GDV( papszNV, "y_0", 0.0 ) );
     585                 :         else
     586                 :           SetEquirectangular( OSR_GDV( papszNV, "lat_0", 0.0 ),
     587                 :                               OSR_GDV( papszNV, "lon_0", 0.0 ),
     588                 :                               OSR_GDV( papszNV, "x_0", 0.0 ),
     589               2 :                               OSR_GDV( papszNV, "y_0", 0.0 ) );
     590                 :     }
     591                 : 
     592              66 :     else if( EQUAL(pszProj,"gstmerc") )
     593                 :     {
     594                 :         SetGaussSchreiberTMercator( OSR_GDV( papszNV, "lat_0", -21.116666667 ),
     595                 :                                     OSR_GDV( papszNV, "lon_0", 55.53333333309),
     596                 :                                     OSR_GDV( papszNV, "k_0", 1.0 ),
     597                 :                                     OSR_GDV( papszNV, "x_0", 160000.000 ),
     598               1 :                                     OSR_GDV( papszNV, "y_0", 50000.000 ) );
     599                 :     }
     600                 : 
     601              65 :     else if( EQUAL(pszProj,"gnom") )
     602                 :     {
     603                 :         SetGnomonic( OSR_GDV( papszNV, "lat_0", 0.0 ), 
     604                 :                      OSR_GDV( papszNV, "lon_0", 0.0 ), 
     605                 :                      OSR_GDV( papszNV, "x_0", 0.0 ), 
     606               1 :                      OSR_GDV( papszNV, "y_0", 0.0 ) );
     607                 :     }
     608                 : 
     609              64 :     else if( EQUAL(pszProj,"ortho") )
     610                 :     {
     611                 :         SetOrthographic( OSR_GDV( papszNV, "lat_0", 0.0 ), 
     612                 :                          OSR_GDV( papszNV, "lon_0", 0.0 ), 
     613                 :                          OSR_GDV( papszNV, "x_0", 0.0 ), 
     614               4 :                          OSR_GDV( papszNV, "y_0", 0.0 ) );
     615                 :     }
     616                 : 
     617              60 :     else if( EQUAL(pszProj,"laea") )
     618                 :     {
     619                 :         SetLAEA( OSR_GDV( papszNV, "lat_0", 0.0 ), 
     620                 :                  OSR_GDV( papszNV, "lon_0", 0.0 ), 
     621                 :                  OSR_GDV( papszNV, "x_0", 0.0 ), 
     622               3 :                  OSR_GDV( papszNV, "y_0", 0.0 ) );
     623                 :     }
     624                 : 
     625              57 :     else if( EQUAL(pszProj,"aeqd") )
     626                 :     {
     627                 :         SetAE( OSR_GDV( papszNV, "lat_0", 0.0 ), 
     628                 :                OSR_GDV( papszNV, "lon_0", 0.0 ), 
     629                 :                OSR_GDV( papszNV, "x_0", 0.0 ), 
     630               5 :                OSR_GDV( papszNV, "y_0", 0.0 ) );
     631                 :     }
     632                 : 
     633              52 :     else if( EQUAL(pszProj,"eqdc") )
     634                 :     {
     635                 :         SetEC( OSR_GDV( papszNV, "lat_1", 0.0 ), 
     636                 :                OSR_GDV( papszNV, "lat_2", 0.0 ), 
     637                 :                OSR_GDV( papszNV, "lat_0", 0.0 ), 
     638                 :                OSR_GDV( papszNV, "lon_0", 0.0 ), 
     639                 :                OSR_GDV( papszNV, "x_0", 0.0 ), 
     640               1 :                OSR_GDV( papszNV, "y_0", 0.0 ) );
     641                 :     }
     642                 : 
     643              51 :     else if( EQUAL(pszProj,"mill") )
     644                 :     {
     645                 :         SetMC( OSR_GDV( papszNV, "lat_0", 0.0 ), 
     646                 :                OSR_GDV( papszNV, "lon_0", 0.0 ), 
     647                 :                OSR_GDV( papszNV, "x_0", 0.0 ), 
     648               2 :                OSR_GDV( papszNV, "y_0", 0.0 ) );
     649                 :     }
     650                 : 
     651              49 :     else if( EQUAL(pszProj,"moll") )
     652                 :     {
     653                 :         SetMollweide( OSR_GDV( papszNV, "lon_0", 0.0 ), 
     654                 :                       OSR_GDV( papszNV, "x_0", 0.0 ), 
     655               1 :                       OSR_GDV( papszNV, "y_0", 0.0 ) );
     656                 :     }
     657                 : 
     658              55 :     else if( EQUAL(pszProj,"eck1") || EQUAL(pszProj,"eck2") || EQUAL(pszProj,"eck3") ||
     659                 :              EQUAL(pszProj,"eck4") || EQUAL(pszProj,"eck5") || EQUAL(pszProj,"eck6"))
     660                 :     {
     661               7 :         SetEckert(   pszProj[3] - '0',
     662                 :                      OSR_GDV( papszNV, "lon_0", 0.0 ), 
     663                 :                      OSR_GDV( papszNV, "x_0", 0.0 ), 
     664              14 :                      OSR_GDV( papszNV, "y_0", 0.0 ) );
     665                 :     }
     666                 : 
     667              41 :     else if( EQUAL(pszProj,"poly") )
     668                 :     {
     669                 :         SetPolyconic( OSR_GDV( papszNV, "lat_0", 0.0 ), 
     670                 :                       OSR_GDV( papszNV, "lon_0", 0.0 ), 
     671                 :                       OSR_GDV( papszNV, "x_0", 0.0 ), 
     672               2 :                       OSR_GDV( papszNV, "y_0", 0.0 ) );
     673                 :     }
     674                 : 
     675              39 :     else if( EQUAL(pszProj,"aea") )
     676                 :     {
     677                 :         SetACEA( OSR_GDV( papszNV, "lat_1", 0.0 ), 
     678                 :                  OSR_GDV( papszNV, "lat_2", 0.0 ), 
     679                 :                  OSR_GDV( papszNV, "lat_0", 0.0 ), 
     680                 :                  OSR_GDV( papszNV, "lon_0", 0.0 ), 
     681                 :                  OSR_GDV( papszNV, "x_0", 0.0 ), 
     682               2 :                  OSR_GDV( papszNV, "y_0", 0.0 ) );
     683                 :     }
     684                 : 
     685              37 :     else if( EQUAL(pszProj,"robin") )
     686                 :     {
     687                 :         SetRobinson( OSR_GDV( papszNV, "lon_0", 0.0 ), 
     688                 :                      OSR_GDV( papszNV, "x_0", 0.0 ), 
     689               1 :                      OSR_GDV( papszNV, "y_0", 0.0 ) );
     690                 :     }
     691                 : 
     692              36 :     else if( EQUAL(pszProj,"vandg") )
     693                 :     {
     694                 :         SetVDG( OSR_GDV( papszNV, "lon_0", 0.0 ), 
     695                 :                 OSR_GDV( papszNV, "x_0", 0.0 ), 
     696               4 :                 OSR_GDV( papszNV, "y_0", 0.0 ) );
     697                 :     }
     698                 : 
     699              32 :     else if( EQUAL(pszProj,"sinu") )
     700                 :     {
     701                 :         SetSinusoidal( OSR_GDV( papszNV, "lon_0", 0.0 ), 
     702                 :                        OSR_GDV( papszNV, "x_0", 0.0 ), 
     703               2 :                        OSR_GDV( papszNV, "y_0", 0.0 ) );
     704                 :     }
     705                 : 
     706              30 :     else if( EQUAL(pszProj,"gall") )
     707                 :     {
     708                 :         SetGS( OSR_GDV( papszNV, "lon_0", 0.0 ), 
     709                 :                OSR_GDV( papszNV, "x_0", 0.0 ), 
     710               2 :                OSR_GDV( papszNV, "y_0", 0.0 ) );
     711                 :     }
     712                 : 
     713              28 :     else if( EQUAL(pszProj,"goode") )
     714                 :     {
     715                 :         SetGH( OSR_GDV( papszNV, "lon_0", 0.0 ), 
     716                 :                OSR_GDV( papszNV, "x_0", 0.0 ), 
     717               1 :                OSR_GDV( papszNV, "y_0", 0.0 ) );
     718                 :     }
     719                 : 
     720              27 :     else if( EQUAL(pszProj,"igh") )
     721                 :     {
     722               1 :         SetIGH();
     723                 :     }
     724                 : 
     725              26 :     else if( EQUAL(pszProj,"geos") )
     726                 :     {
     727                 :         SetGEOS( OSR_GDV( papszNV, "lon_0", 0.0 ), 
     728                 :                  OSR_GDV( papszNV, "h", 35785831.0 ), 
     729                 :                  OSR_GDV( papszNV, "x_0", 0.0 ), 
     730               1 :                  OSR_GDV( papszNV, "y_0", 0.0 ) );
     731                 :     }
     732                 : 
     733              25 :     else if( EQUAL(pszProj,"lcc") ) 
     734                 :     {
     735               7 :         if( OSR_GDV(papszNV, "lat_0", 0.0 ) 
     736                 :             == OSR_GDV(papszNV, "lat_1", 0.0 ) )
     737                 :         {
     738                 :             /* 1SP form */
     739                 :             SetLCC1SP( OSR_GDV( papszNV, "lat_0", 0.0 ), 
     740                 :                        OSR_GDV( papszNV, "lon_0", 0.0 ), 
     741                 :                        OSR_GDV( papszNV, "k_0", 1.0 ), 
     742                 :                        OSR_GDV( papszNV, "x_0", 0.0 ), 
     743               5 :                        OSR_GDV( papszNV, "y_0", 0.0 ) );
     744                 :         }
     745                 :         else
     746                 :         {
     747                 :             /* 2SP form */
     748                 :             SetLCC( OSR_GDV( papszNV, "lat_1", 0.0 ), 
     749                 :                     OSR_GDV( papszNV, "lat_2", 0.0 ), 
     750                 :                     OSR_GDV( papszNV, "lat_0", 0.0 ), 
     751                 :                     OSR_GDV( papszNV, "lon_0", 0.0 ), 
     752                 :                     OSR_GDV( papszNV, "x_0", 0.0 ), 
     753               2 :                     OSR_GDV( papszNV, "y_0", 0.0 ) );
     754                 :         }
     755                 :     }
     756                 : 
     757              18 :     else if( EQUAL(pszProj,"omerc") )
     758                 :     {
     759                 :         SetHOM( OSR_GDV( papszNV, "lat_0", 0.0 ), 
     760                 :                 OSR_GDV( papszNV, "lonc", 0.0 ), 
     761                 :                 OSR_GDV( papszNV, "alpha", 0.0 ), 
     762                 :                 OSR_GDV( papszNV, "gamma", 0.0 ), 
     763                 :                 OSR_GDV( papszNV, "k", 1.0 ), 
     764                 :                 OSR_GDV( papszNV, "x_0", 0.0 ), 
     765               2 :                 OSR_GDV( papszNV, "y_0", 0.0 ) );
     766                 :     }
     767                 : 
     768              16 :     else if( EQUAL(pszProj,"somerc") )
     769                 :     {
     770                 :         SetHOM( OSR_GDV( papszNV, "lat_0", 0.0 ), 
     771                 :                 OSR_GDV( papszNV, "lon_0", 0.0 ), 
     772                 :                 90.0,  90.0, 
     773                 :                 OSR_GDV( papszNV, "k", 1.0 ), 
     774                 :                 OSR_GDV( papszNV, "x_0", 0.0 ), 
     775               3 :                 OSR_GDV( papszNV, "y_0", 0.0 ) );
     776                 :     }
     777                 : 
     778              13 :     else if( EQUAL(pszProj,"krovak") )
     779                 :     {
     780                 :         SetKrovak( OSR_GDV( papszNV, "lat_0", 0.0 ), 
     781                 :                    OSR_GDV( papszNV, "lon_0", 0.0 ), 
     782                 :                    OSR_GDV( papszNV, "alpha", 0.0 ), 
     783                 :                    0.0, // pseudo_standard_parallel_1
     784                 :                    OSR_GDV( papszNV, "k", 1.0 ), 
     785                 :                    OSR_GDV( papszNV, "x_0", 0.0 ), 
     786               2 :                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     787                 :     }
     788                 : 
     789              11 :     else if( EQUAL(pszProj, "iwm_p") )
     790                 :     {
     791                 :         SetIWMPolyconic( OSR_GDV( papszNV, "lat_1", 0.0 ), 
     792                 :                          OSR_GDV( papszNV, "lat_2", 0.0 ),
     793                 :                          OSR_GDV( papszNV, "lon_0", 0.0 ), 
     794                 :                          OSR_GDV( papszNV, "x_0", 0.0 ), 
     795               1 :                          OSR_GDV( papszNV, "y_0", 0.0 ) );
     796                 :     }
     797                 : 
     798              10 :     else if( EQUAL(pszProj, "wag1") )
     799                 :     {
     800                 :         SetWagner( 1, 0.0,
     801                 :                    OSR_GDV( papszNV, "x_0", 0.0 ), 
     802               1 :                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     803                 :     }
     804                 : 
     805               9 :     else if( EQUAL(pszProj, "wag2") )
     806                 :     {
     807                 :         SetWagner( 2, 0.0,
     808                 :                    OSR_GDV( papszNV, "x_0", 0.0 ), 
     809               1 :                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     810                 :     }
     811                 : 
     812               8 :     else if( EQUAL(pszProj, "wag3") )
     813                 :     {
     814                 :         SetWagner( 3,
     815                 :                    OSR_GDV( papszNV, "lat_ts", 0.0 ),
     816                 :                    OSR_GDV( papszNV, "x_0", 0.0 ), 
     817               1 :                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     818                 :     }
     819                 : 
     820               7 :     else if( EQUAL(pszProj, "wag4") )
     821                 :     {
     822                 :         SetWagner( 4, 0.0,
     823                 :                    OSR_GDV( papszNV, "x_0", 0.0 ), 
     824               1 :                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     825                 :     }
     826                 : 
     827               6 :     else if( EQUAL(pszProj, "wag5") )
     828                 :     {
     829                 :         SetWagner( 5, 0.0,
     830                 :                    OSR_GDV( papszNV, "x_0", 0.0 ), 
     831               1 :                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     832                 :     }
     833                 : 
     834               5 :     else if( EQUAL(pszProj, "wag6") )
     835                 :     {
     836                 :         SetWagner( 6, 0.0,
     837                 :                    OSR_GDV( papszNV, "x_0", 0.0 ), 
     838               1 :                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     839                 :     }
     840                 : 
     841               4 :     else if( EQUAL(pszProj, "wag7") )
     842                 :     {
     843                 :         SetWagner( 7, 0.0,
     844                 :                    OSR_GDV( papszNV, "x_0", 0.0 ), 
     845               1 :                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     846                 :     }
     847                 : 
     848               3 :     else if( EQUAL(pszProj,"tpeqd") )
     849                 :     {
     850                 :         SetTPED( OSR_GDV( papszNV, "lat_1", 0.0 ), 
     851                 :                  OSR_GDV( papszNV, "lon_1", 0.0 ), 
     852                 :                  OSR_GDV( papszNV, "lat_2", 0.0 ), 
     853                 :                  OSR_GDV( papszNV, "lon_2", 0.0 ), 
     854                 :                  OSR_GDV( papszNV, "x_0", 0.0 ), 
     855               2 :                  OSR_GDV( papszNV, "y_0", 0.0 ) );
     856                 :     }
     857                 : 
     858                 :     else
     859                 :     {
     860               1 :         CPLDebug( "OGR_PROJ4", "Unsupported projection: %s", pszProj );
     861               1 :         CSLDestroy( papszNV );
     862               1 :         return OGRERR_CORRUPT_DATA;
     863                 :     }
     864                 : 
     865                 : /* -------------------------------------------------------------------- */
     866                 : /*      Try to translate the datum.                                     */
     867                 : /* -------------------------------------------------------------------- */
     868                 :     const char *pszValue;
     869             130 :     int  bFullyDefined = FALSE;
     870                 : 
     871             130 :     pszValue = CSLFetchNameValue(papszNV, "datum");
     872             130 :     if( pszValue == NULL )
     873                 :     {
     874                 :         /* do nothing */
     875                 :     }
     876              55 :     else if( (EQUAL(pszValue,"NAD27") || EQUAL(pszValue,"NAD83")
     877                 :               || EQUAL(pszValue,"WGS84") || EQUAL(pszValue,"WGS72"))
     878                 :              && dfFromGreenwich == 0.0 )
     879                 :     {
     880              27 :         SetWellKnownGeogCS( pszValue );
     881              27 :         bFullyDefined = TRUE;
     882                 :     }
     883                 :     else
     884                 :     {
     885                 :         unsigned int i;
     886               8 :         for(i=0;i<sizeof(ogr_pj_datums)/sizeof(ogr_pj_datums[0]);i++)
     887                 :         {
     888               7 :             if ( EQUAL(pszValue, ogr_pj_datums[i].pszPJ) )
     889                 :             {
     890               0 :                 OGRSpatialReference oGCS;
     891               0 :                 oGCS.importFromEPSG( ogr_pj_datums[i].nEPSG );
     892               0 :                 CopyGeogCSFrom( &oGCS );
     893               0 :                 bFullyDefined = TRUE;
     894               0 :                 break;
     895                 :             }
     896                 :         }
     897                 : 
     898                 :         /* If we don't recognise the datum, we ignore it */
     899                 :     }
     900                 : 
     901                 : /* -------------------------------------------------------------------- */
     902                 : /*      Set the ellipsoid information.                                   */
     903                 : /* -------------------------------------------------------------------- */
     904                 :     double dfSemiMajor, dfInvFlattening, dfSemiMinor;
     905                 : 
     906             130 :     pszValue = CSLFetchNameValue(papszNV, "ellps");
     907             130 :     if( pszValue != NULL && !bFullyDefined )
     908                 :     {
     909            6372 :         for( i = 0; ogr_pj_ellps[i] != NULL; i += 4 )
     910                 :         {
     911            3186 :             if( !EQUAL(ogr_pj_ellps[i],pszValue) )
     912            3099 :                 continue;
     913                 : 
     914              87 :             CPLAssert( EQUALN(ogr_pj_ellps[i+1],"a=",2) );
     915                 :             
     916              87 :             dfSemiMajor = CPLAtof(ogr_pj_ellps[i+1]+2);
     917              87 :             if( EQUALN(ogr_pj_ellps[i+2],"rf=",3) )
     918              83 :                 dfInvFlattening = CPLAtof(ogr_pj_ellps[i+2]+3);
     919                 :             else
     920                 :             {
     921               4 :                 CPLAssert( EQUALN(ogr_pj_ellps[i+2],"b=",2) );
     922               4 :                 dfSemiMinor = CPLAtof(ogr_pj_ellps[i+2]+2);
     923                 :                 
     924               4 :                 if( ABS(dfSemiMajor/dfSemiMinor) - 1.0 < 0.0000000000001 )
     925               3 :                     dfInvFlattening = 0.0;
     926                 :                 else
     927               1 :                     dfInvFlattening = -1.0 / (dfSemiMinor/dfSemiMajor - 1.0);
     928                 :             }
     929                 :             
     930                 :             SetGeogCS( ogr_pj_ellps[i+3], "unknown", ogr_pj_ellps[i], 
     931                 :                        dfSemiMajor, dfInvFlattening,
     932              87 :                        pszPM, dfFromGreenwich );
     933                 : 
     934              87 :             bFullyDefined = TRUE;
     935              87 :             break;
     936                 :         }
     937                 :     }
     938                 : 
     939             130 :     if( !bFullyDefined )
     940                 :     {
     941              16 :         dfSemiMajor = OSR_GDV( papszNV, "a", 0.0 );
     942              16 :         if( dfSemiMajor == 0.0 )
     943                 :         {
     944               2 :             dfSemiMajor = OSR_GDV( papszNV, "R", 0.0 );
     945               2 :             if( dfSemiMajor != 0.0 )
     946                 :             {
     947               0 :                 dfSemiMinor = -1.0;
     948               0 :                 dfInvFlattening = 0.0;
     949                 :             }
     950                 :             else
     951                 :             {
     952                 :                 CPLDebug( "OGR_PROJ4", "Can't find ellipse definition, default to WGS84:\n%s", 
     953               2 :                           pszProj4 );
     954                 :                 
     955               2 :                 dfSemiMajor = SRS_WGS84_SEMIMAJOR;
     956               2 :                 dfSemiMinor = -1.0;
     957               2 :                 dfInvFlattening = SRS_WGS84_INVFLATTENING;
     958                 :             }
     959                 :         }
     960                 :         else
     961                 :         {
     962              14 :             dfSemiMinor = OSR_GDV( papszNV, "b", -1.0 );
     963              14 :             dfInvFlattening = OSR_GDV( papszNV, "rf", -1.0 );
     964              14 :             if ( dfSemiMinor == -1.0 && dfInvFlattening == -1.0 )
     965                 :             {
     966               1 :                 double dfFlattening = OSR_GDV( papszNV, "f", -1.0 );
     967               1 :                 if ( dfFlattening == 0.0 )
     968               0 :                     dfSemiMinor = dfSemiMajor;
     969               1 :                 else if ( dfFlattening != -1.0 )
     970               0 :                     dfInvFlattening = 1.0 / dfFlattening;
     971                 :             }
     972                 :         }
     973                 :         
     974              16 :         if( dfSemiMinor == -1.0 && dfInvFlattening == -1.0 )
     975                 :         {
     976                 :             CPLDebug( "OGR_PROJ4", "Can't find ellipse definition in:\n%s", 
     977               1 :                       pszProj4 );
     978               1 :             CSLDestroy( papszNV );
     979               1 :             return OGRERR_UNSUPPORTED_SRS;
     980                 :         }
     981                 : 
     982              15 :         if( dfInvFlattening == -1.0 )
     983                 :         {
     984              10 :             if( ABS(dfSemiMajor/dfSemiMinor) - 1.0 < 0.0000000000001 )
     985               6 :                 dfInvFlattening = 0.0;
     986                 :             else
     987               4 :                 dfInvFlattening = -1.0 / (dfSemiMinor/dfSemiMajor - 1.0);
     988                 :         }
     989                 :         
     990                 :         SetGeogCS( "unnamed ellipse", "unknown", "unnamed",
     991                 :                    dfSemiMajor, dfInvFlattening,
     992              15 :                    pszPM, dfFromGreenwich );
     993                 :         
     994              15 :         bFullyDefined = TRUE;
     995                 :     }
     996                 : 
     997                 : /* -------------------------------------------------------------------- */
     998                 : /*      Handle TOWGS84 conversion.                                      */
     999                 : /* -------------------------------------------------------------------- */
    1000             129 :     pszValue = CSLFetchNameValue(papszNV, "towgs84");
    1001             129 :     if(pszValue!=NULL)
    1002                 :     {
    1003                 :         char **papszToWGS84 = CSLTokenizeStringComplex( pszValue, ",", 
    1004              41 :                                                         FALSE, TRUE );
    1005                 : 
    1006              41 :         if( CSLCount(papszToWGS84) >= 7 )
    1007              17 :             SetTOWGS84( CPLAtof(papszToWGS84[0]), 
    1008              17 :                         CPLAtof(papszToWGS84[1]), 
    1009              17 :                         CPLAtof(papszToWGS84[2]), 
    1010              17 :                         CPLAtof(papszToWGS84[3]), 
    1011              17 :                         CPLAtof(papszToWGS84[4]), 
    1012              17 :                         CPLAtof(papszToWGS84[5]), 
    1013             119 :                         CPLAtof(papszToWGS84[6]) );
    1014              24 :         else if( CSLCount(papszToWGS84) >= 3 )
    1015              23 :             SetTOWGS84( CPLAtof(papszToWGS84[0]), 
    1016              23 :                         CPLAtof(papszToWGS84[1]), 
    1017              69 :                         CPLAtof(papszToWGS84[2]) );
    1018                 :         else
    1019                 :             CPLError( CE_Warning, CPLE_AppDefined, 
    1020                 :                       "Seemingly corrupt +towgs84 option (%s), ignoring.", 
    1021               1 :                       pszValue );
    1022                 :                         
    1023              41 :         CSLDestroy(papszToWGS84);
    1024                 :     }
    1025                 : 
    1026                 : /* -------------------------------------------------------------------- */
    1027                 : /*      Handle nadgrids via an extension node.                          */
    1028                 : /* -------------------------------------------------------------------- */
    1029             129 :     pszValue = CSLFetchNameValue(papszNV, "nadgrids");
    1030             129 :     if( pszValue != NULL )
    1031                 :     {
    1032               3 :         SetExtension( "DATUM", "PROJ4_GRIDS", pszValue );
    1033                 :     }
    1034                 : 
    1035                 : /* -------------------------------------------------------------------- */
    1036                 : /*      Linear units translation                                        */
    1037                 : /* -------------------------------------------------------------------- */
    1038             129 :     if( IsProjected() || IsLocal() || IsGeocentric() )
    1039                 :     {
    1040             117 :         pszValue = CSLFetchNameValue(papszNV, "to_meter");
    1041                 : 
    1042             117 :         if( pszValue != NULL && CPLAtofM(pszValue) > 0.0 )
    1043                 :         {
    1044               1 :             double dfValue = CPLAtofM(pszValue);
    1045                 : 
    1046               1 :             if( fabs(dfValue - CPLAtof(SRS_UL_US_FOOT_CONV)) < 0.00000001 )
    1047               0 :                 SetLinearUnits( SRS_UL_US_FOOT, CPLAtof(SRS_UL_US_FOOT_CONV) );
    1048               1 :             else if( fabs(dfValue - CPLAtof(SRS_UL_FOOT_CONV)) < 0.00000001 )
    1049               0 :                 SetLinearUnits( SRS_UL_FOOT, CPLAtof(SRS_UL_FOOT_CONV) );
    1050               1 :             else if( dfValue == 1.0 )
    1051               0 :                 SetLinearUnits( SRS_UL_METER, 1.0 );
    1052                 :             else
    1053               1 :                 SetLinearUnits( "unknown", CPLAtofM(pszValue) );
    1054                 :         }
    1055             116 :         else if( (pszValue = CSLFetchNameValue(papszNV, "units")) != NULL )
    1056                 :         {
    1057              95 :             if( EQUAL(pszValue,"meter" ) || EQUAL(pszValue,"m") )
    1058              45 :                 SetLinearUnits( SRS_UL_METER, 1.0 );
    1059               5 :             else if( EQUAL(pszValue,"us-ft" ) )
    1060               2 :                 SetLinearUnits( SRS_UL_US_FOOT, CPLAtof(SRS_UL_US_FOOT_CONV) );
    1061               3 :             else if( EQUAL(pszValue,"ft" ) )
    1062               1 :                 SetLinearUnits( SRS_UL_FOOT, CPLAtof(SRS_UL_FOOT_CONV) );
    1063               2 :             else if( EQUAL(pszValue,"yd" ) )
    1064               1 :                 SetLinearUnits( pszValue, 0.9144 );
    1065               1 :             else if( EQUAL(pszValue,"us-yd" ) )
    1066               1 :                 SetLinearUnits( pszValue, 0.914401828803658 );
    1067                 :             else // This case is untranslatable.  Should add all proj.4 unts
    1068               0 :                 SetLinearUnits( pszValue, 1.0 );
    1069                 :         }
    1070                 :     }
    1071                 : 
    1072                 : /* -------------------------------------------------------------------- */
    1073                 : /*      Adjust linear parameters into PROJCS units if the linear        */
    1074                 : /*      units are not meters.                                           */
    1075                 : /* -------------------------------------------------------------------- */
    1076             129 :     if( GetLinearUnits() != 1.0 && IsProjected() )
    1077                 :     {
    1078               6 :         OGR_SRSNode *poPROJCS = GetAttrNode( "PROJCS" );
    1079                 :         int  i;
    1080                 : 
    1081              60 :         for( i = 0; i < poPROJCS->GetChildCount(); i++ )
    1082                 :         {
    1083              54 :             OGR_SRSNode *poParm = poPROJCS->GetChild(i);
    1084              54 :             if( !EQUAL(poParm->GetValue(),"PARAMETER") 
    1085                 :                 || poParm->GetChildCount() != 2 )
    1086              24 :                 continue;
    1087                 : 
    1088              30 :             const char *pszParmName = poParm->GetChild(0)->GetValue();
    1089                 : 
    1090              30 :             if( IsLinearParameter(pszParmName) )
    1091              12 :                 SetNormProjParm(pszParmName,GetProjParm(pszParmName));
    1092                 :         }        
    1093                 :     }
    1094                 : 
    1095                 : /* -------------------------------------------------------------------- */
    1096                 : /*      Handle geoidgrids via an extension node and COMPD_CS.           */
    1097                 : /* -------------------------------------------------------------------- */
    1098             129 :     pszValue = CSLFetchNameValue(papszNV, "geoidgrids");
    1099             129 :     if( pszValue != NULL )
    1100                 :     {
    1101               1 :         OGR_SRSNode *poHorizSRS = GetRoot()->Clone();
    1102                 :         
    1103               1 :         Clear();
    1104                 :         
    1105               1 :         CPLString osName = poHorizSRS->GetChild(0)->GetValue();
    1106               1 :         osName += " + ";
    1107               1 :         osName += "Unnamed Vertical Datum";
    1108                 :         
    1109               1 :         SetNode( "COMPD_CS", osName );
    1110               1 :         GetRoot()->AddChild( poHorizSRS );
    1111                 : 
    1112                 :         OGR_SRSNode *poVertSRS;
    1113                 :         
    1114               1 :         poVertSRS = new OGR_SRSNode( "VERT_CS" );
    1115               2 :         GetRoot()->AddChild( poVertSRS );
    1116               1 :         poVertSRS->AddChild( new OGR_SRSNode( "Unnamed" ) );
    1117                 : 
    1118               1 :         CPLString osTarget = GetRoot()->GetValue();
    1119               1 :         osTarget += "|VERT_CS|VERT_DATUM";
    1120                 : 
    1121               1 :         SetNode( osTarget, "Unnamed" );
    1122                 :         
    1123               1 :         poVertSRS->GetChild(1)->AddChild( new OGR_SRSNode( "2005" ) );
    1124               1 :         SetExtension( osTarget, "PROJ4_GRIDS", pszValue );
    1125                 : 
    1126               1 :         OGR_SRSNode *poAxis = new OGR_SRSNode( "AXIS" );
    1127                 : 
    1128               2 :         poAxis->AddChild( new OGR_SRSNode( "Up" ) );
    1129               1 :         poAxis->AddChild( new OGR_SRSNode( "UP" ) );
    1130                 :         
    1131               1 :         poVertSRS->AddChild( poAxis );
    1132                 :     }
    1133                 : 
    1134                 : /* -------------------------------------------------------------------- */
    1135                 : /*      Handle vertical units.                                          */
    1136                 : /* -------------------------------------------------------------------- */
    1137             129 :     if( GetRoot()->GetNode( "VERT_CS" ) != NULL )
    1138                 :     {
    1139               1 :         const char *pszUnitName = NULL;
    1140               1 :         const char *pszUnitConv = NULL;
    1141                 : 
    1142               1 :         pszValue = CSLFetchNameValue(papszNV, "vto_meter");
    1143                 : 
    1144               1 :         if( pszValue != NULL && CPLAtofM(pszValue) > 0.0 )
    1145                 :         {
    1146               0 :             double dfValue = CPLAtofM(pszValue);
    1147                 : 
    1148               0 :             if( fabs(dfValue - CPLAtof(SRS_UL_US_FOOT_CONV)) < 0.00000001 )
    1149                 :             {
    1150               0 :                 pszUnitName = SRS_UL_US_FOOT;
    1151               0 :                 pszUnitConv = SRS_UL_US_FOOT_CONV;
    1152                 :             }
    1153               0 :             else if( fabs(dfValue - CPLAtof(SRS_UL_FOOT_CONV)) < 0.00000001 )
    1154                 :             {
    1155               0 :                 pszUnitName = SRS_UL_FOOT;
    1156               0 :                 pszUnitConv = SRS_UL_FOOT_CONV;
    1157                 :             }
    1158               0 :             else if( dfValue == 1.0 )
    1159                 :             {
    1160               0 :                 pszUnitName = SRS_UL_METER;
    1161               0 :                 pszUnitConv = "1.0";
    1162                 :             }
    1163                 :             else
    1164                 :             {
    1165               0 :                 pszUnitName = "unknown";
    1166               0 :                 pszUnitConv = pszValue;
    1167                 :             }
    1168                 :         }
    1169               1 :         else if( (pszValue = CSLFetchNameValue(papszNV, "vunits")) != NULL )
    1170                 :         {
    1171               1 :             if( EQUAL(pszValue,"meter" ) || EQUAL(pszValue,"m") )
    1172                 :             {
    1173               0 :                 pszUnitName = SRS_UL_METER;
    1174               0 :                 pszUnitConv = "1.0";
    1175                 :             }
    1176               1 :             else if( EQUAL(pszValue,"us-ft" ) )
    1177                 :             {
    1178               1 :                 pszUnitName = SRS_UL_US_FOOT;
    1179               1 :                 pszUnitConv = SRS_UL_US_FOOT_CONV;
    1180                 :             }
    1181               0 :             else if( EQUAL(pszValue,"ft" ) )
    1182                 :             {
    1183               0 :                 pszUnitName = SRS_UL_FOOT;
    1184               0 :                 pszUnitConv = SRS_UL_FOOT_CONV;
    1185                 :             }
    1186               0 :             else if( EQUAL(pszValue,"yd" ) )
    1187                 :             {
    1188               0 :                 pszUnitName = "Yard";
    1189               0 :                 pszUnitConv = "0.9144";
    1190                 :             }
    1191               0 :             else if( EQUAL(pszValue,"us-yd" ) )
    1192                 :             {
    1193               0 :                 pszUnitName = "US Yard";
    1194               0 :                 pszUnitConv = "0.914401828803658";
    1195                 :             }
    1196                 :         }
    1197                 : 
    1198               1 :         if( pszUnitName != NULL )
    1199                 :         {
    1200               1 :             OGR_SRSNode *poVERT_CS = GetRoot()->GetNode( "VERT_CS" );
    1201                 :             OGR_SRSNode *poUnits; 
    1202                 : 
    1203               1 :             poUnits = new OGR_SRSNode( "UNIT" );
    1204               2 :             poUnits->AddChild( new OGR_SRSNode( pszUnitName ) );
    1205               2 :             poUnits->AddChild( new OGR_SRSNode( pszUnitConv ) );
    1206                 :             
    1207               1 :             poVERT_CS->AddChild( poUnits );
    1208                 :         }
    1209                 :     }
    1210                 : 
    1211                 : /* -------------------------------------------------------------------- */
    1212                 : /*      do we want to insert a PROJ.4 EXTENSION item?                   */
    1213                 : /* -------------------------------------------------------------------- */
    1214             129 :     if( strstr(pszProj4,"wktext") != NULL )
    1215               0 :         SetExtension( GetRoot()->GetValue(), "PROJ4", pszProj4 );
    1216                 :         
    1217             129 :     CSLDestroy( papszNV );
    1218                 :     
    1219             129 :     return OGRERR_NONE;
    1220                 : }
    1221                 : 
    1222                 : /************************************************************************/
    1223                 : /*                           LinearToProj4()                            */
    1224                 : /************************************************************************/
    1225                 : 
    1226             453 : static const char *LinearToProj4( double dfLinearConv, 
    1227                 :                                   const char *pszLinearUnits )
    1228                 : 
    1229                 : {
    1230             453 :     if( dfLinearConv == 1.0 )
    1231             444 :         return "m";
    1232                 : 
    1233               9 :     else if( dfLinearConv == 1000.0 )
    1234               0 :         return "km";
    1235                 :     
    1236               9 :     else if( dfLinearConv == 0.0254 )
    1237               0 :         return "in";
    1238                 :     
    1239               9 :     else if( EQUAL(pszLinearUnits,SRS_UL_FOOT) 
    1240                 :              || fabs(dfLinearConv - atof(SRS_UL_FOOT_CONV)) < 0.000000001 )
    1241               1 :         return "ft";
    1242                 :     
    1243               8 :     else if( EQUAL(pszLinearUnits,"IYARD") || dfLinearConv == 0.9144 )
    1244               1 :         return "yd";
    1245                 : 
    1246               7 :     else if( dfLinearConv == 0.914401828803658 )
    1247               1 :         return "us-yd";
    1248                 :     
    1249               6 :     else if( dfLinearConv == 0.001 )
    1250               0 :         return "mm";
    1251                 :     
    1252               6 :     else if( dfLinearConv == 0.01 )
    1253               0 :         return "cm";
    1254                 : 
    1255               6 :     else if( EQUAL(pszLinearUnits,SRS_UL_US_FOOT) 
    1256                 :              || fabs(dfLinearConv - atof(SRS_UL_US_FOOT_CONV)) < 0.00000001 )
    1257               5 :         return "us-ft";
    1258                 : 
    1259               1 :     else if( EQUAL(pszLinearUnits,SRS_UL_NAUTICAL_MILE) )
    1260               0 :         return "kmi";
    1261                 : 
    1262               1 :     else if( EQUAL(pszLinearUnits,"Mile") 
    1263                 :              || EQUAL(pszLinearUnits,"IMILE") )
    1264               0 :         return "mi";
    1265                 :     else
    1266               1 :         return NULL;
    1267                 : }
    1268                 : 
    1269                 : 
    1270                 : /************************************************************************/
    1271                 : /*                          OSRExportToProj4()                          */
    1272                 : /************************************************************************/
    1273                 : /** 
    1274                 :  * \brief Export coordinate system in PROJ.4 format.
    1275                 :  *
    1276                 :  * This function is the same as OGRSpatialReference::exportToProj4().
    1277                 :  */
    1278             122 : OGRErr CPL_STDCALL OSRExportToProj4( OGRSpatialReferenceH hSRS, 
    1279                 :                                      char ** ppszReturn )
    1280                 : 
    1281                 : {
    1282             122 :     VALIDATE_POINTER1( hSRS, "OSRExportToProj4", CE_Failure );
    1283                 : 
    1284             122 :     *ppszReturn = NULL;
    1285                 : 
    1286             122 :     return ((OGRSpatialReference *) hSRS)->exportToProj4( ppszReturn );
    1287                 : }
    1288                 : 
    1289                 : /************************************************************************/
    1290                 : /*                           exportToProj4()                            */
    1291                 : /************************************************************************/
    1292                 : 
    1293                 : #define SAFE_PROJ4_STRCAT(szNewStr)  do { \
    1294                 :     if(CPLStrlcat(szProj4, szNewStr, sizeof(szProj4)) >= sizeof(szProj4)) { \
    1295                 :         CPLError(CE_Failure, CPLE_AppDefined, "String overflow when formatting proj.4 string"); \
    1296                 :         *ppszProj4 = CPLStrdup(""); \
    1297                 :         return OGRERR_FAILURE; \
    1298                 :     } } while(0);
    1299                 : 
    1300                 : /**
    1301                 :  * \brief Export coordinate system in PROJ.4 format.
    1302                 :  *
    1303                 :  * Converts the loaded coordinate reference system into PROJ.4 format
    1304                 :  * to the extent possible.  The string returned in ppszProj4 should be
    1305                 :  * deallocated by the caller with CPLFree() when no longer needed.
    1306                 :  *
    1307                 :  * LOCAL_CS coordinate systems are not translatable.  An empty string
    1308                 :  * will be returned along with OGRERR_NONE.  
    1309                 :  *
    1310                 :  * This method is the equivelent of the C function OSRExportToProj4().
    1311                 :  *
    1312                 :  * @param ppszProj4 pointer to which dynamically allocated PROJ.4 definition 
    1313                 :  * will be assigned. 
    1314                 :  *
    1315                 :  * @return OGRERR_NONE on success or an error code on failure. 
    1316                 :  */
    1317                 : 
    1318             725 : OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
    1319                 : 
    1320                 : {
    1321                 :     char        szProj4[512];
    1322             725 :     const char *pszProjection = GetAttrValue("PROJECTION");
    1323             725 :     CPLLocaleC  oLocaleEnforcer;
    1324                 : 
    1325             725 :     szProj4[0] = '\0';
    1326                 : 
    1327             725 :     if( GetRoot() == NULL )
    1328                 :     {
    1329               1 :         *ppszProj4 = CPLStrdup("");
    1330                 :         CPLError( CE_Failure, CPLE_NotSupported,
    1331               1 :                   "No translation an empty SRS to PROJ.4 format is known.");
    1332               1 :         return OGRERR_UNSUPPORTED_SRS;
    1333                 :     }
    1334                 : 
    1335                 : /* -------------------------------------------------------------------- */
    1336                 : /*      Do we have a PROJ.4 override definition?                        */
    1337                 : /* -------------------------------------------------------------------- */
    1338                 :     const char *pszPredefProj4 = GetExtension( GetRoot()->GetValue(), 
    1339             724 :                                                "PROJ4", NULL );
    1340             724 :     if( pszPredefProj4 != NULL )
    1341                 :     {
    1342              16 :         *ppszProj4 = CPLStrdup( pszPredefProj4 );
    1343              16 :         return OGRERR_NONE;
    1344                 :     }
    1345                 : 
    1346                 : /* -------------------------------------------------------------------- */
    1347                 : /*      Get the prime meridian info.                                    */
    1348                 : /* -------------------------------------------------------------------- */
    1349             708 :     const OGR_SRSNode *poPRIMEM = GetAttrNode( "PRIMEM" );
    1350             708 :     double dfFromGreenwich = 0.0;
    1351                 : 
    1352             708 :     if( poPRIMEM != NULL && poPRIMEM->GetChildCount() >= 2 
    1353                 :         && CPLAtof(poPRIMEM->GetChild(1)->GetValue()) != 0.0 )
    1354                 :     {
    1355               8 :         dfFromGreenwich = CPLAtof(poPRIMEM->GetChild(1)->GetValue());
    1356                 :     }
    1357                 : 
    1358                 : /* ==================================================================== */
    1359                 : /*      Handle the projection definition.                               */
    1360                 : /* ==================================================================== */
    1361                 : 
    1362             708 :     if( pszProjection == NULL && IsGeographic() )
    1363                 :     {
    1364             257 :         sprintf( szProj4+strlen(szProj4), "+proj=longlat " );
    1365                 :     }
    1366             451 :     else if( IsGeocentric() )
    1367                 :     {
    1368               3 :         sprintf( szProj4+strlen(szProj4), "+proj=geocent " );
    1369                 :     }
    1370                 : 
    1371             448 :     else if( pszProjection == NULL && !IsGeographic() )
    1372                 :     {
    1373                 :         // LOCAL_CS, or incompletely initialized coordinate systems.
    1374               0 :         *ppszProj4 = CPLStrdup("");
    1375               0 :         return OGRERR_NONE;
    1376                 :     }
    1377             448 :     else if( EQUAL(pszProjection,SRS_PT_CYLINDRICAL_EQUAL_AREA) )
    1378                 :     {
    1379                 :         sprintf( szProj4+strlen(szProj4),
    1380                 :                  "+proj=cea +lon_0=%.16g +lat_ts=%.16g +x_0=%.16g +y_0=%.16g ",
    1381                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1382                 :                  GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0),
    1383                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1384               6 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1385                 :     }
    1386                 : 
    1387             442 :     else if( EQUAL(pszProjection,SRS_PT_BONNE) )
    1388                 :     {
    1389                 :         sprintf( szProj4+strlen(szProj4),
    1390                 :                  "+proj=bonne +lon_0=%.16g +lat_1=%.16g +x_0=%.16g +y_0=%.16g ",
    1391                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1392                 :                  GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0),
    1393                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1394               3 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1395                 :     }
    1396                 : 
    1397             439 :     else if( EQUAL(pszProjection,SRS_PT_CASSINI_SOLDNER) )
    1398                 :     {
    1399                 :         sprintf( szProj4+strlen(szProj4),
    1400                 :                  "+proj=cass +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1401                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1402                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1403                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1404               2 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1405                 :     }
    1406                 : 
    1407             437 :     else if( EQUAL(pszProjection,SRS_PT_NEW_ZEALAND_MAP_GRID) )
    1408                 :     {
    1409                 :         sprintf( szProj4+strlen(szProj4),
    1410                 :                  "+proj=nzmg +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1411                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1412                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1413                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1414               2 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1415                 :     }
    1416                 : 
    1417             690 :     else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR) ||
    1418                 :              EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_MI_21) ||
    1419                 :              EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_MI_22) ||
    1420                 :              EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_MI_23) ||
    1421                 :              EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_MI_24) ||
    1422                 :              EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_MI_25) )
    1423                 :     {
    1424                 :         int bNorth;
    1425             255 :         int nZone = GetUTMZone( &bNorth );
    1426                 : 
    1427             255 :         if( nZone != 0 )
    1428                 :         {
    1429             243 :             if( bNorth )
    1430                 :                 sprintf( szProj4+strlen(szProj4), "+proj=utm +zone=%d ", 
    1431             236 :                          nZone );
    1432                 :             else
    1433                 :                 sprintf( szProj4+strlen(szProj4),"+proj=utm +zone=%d +south ", 
    1434               7 :                          nZone );
    1435                 :         }            
    1436                 :         else
    1437                 :             sprintf( szProj4+strlen(szProj4),
    1438                 :                      "+proj=tmerc +lat_0=%.16g +lon_0=%.16g +k=%.16g +x_0=%.16g +y_0=%.16g ",
    1439                 :                      GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1440                 :                      GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1441                 :                      GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
    1442                 :                      GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1443              12 :                      GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1444                 :     }
    1445                 : 
    1446             180 :     else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED) )
    1447                 :     {
    1448                 :         sprintf( szProj4+strlen(szProj4),
    1449                 :                  "+proj=tmerc +lat_0=%.16g +lon_0=%.16g +k=%.16g +x_0=%.16g +y_0=%.16g +axis=wsu ",
    1450                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1451                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1452                 :                  GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
    1453                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1454               1 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1455                 :     }
    1456                 : 
    1457             179 :     else if( EQUAL(pszProjection,SRS_PT_MERCATOR_1SP) )
    1458                 :     {
    1459               8 :         if( GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0) == 0.0 )
    1460                 :             sprintf( szProj4+strlen(szProj4),
    1461                 :                      "+proj=merc +lon_0=%.16g +k=%.16g +x_0=%.16g +y_0=%.16g ",
    1462                 :                      GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1463                 :                      GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
    1464                 :                      GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1465               6 :                      GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1466               2 :         else if( GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0) == 1.0 )
    1467                 :             sprintf( szProj4+strlen(szProj4),
    1468                 :                      "+proj=merc +lon_0=%.16g +lat_ts=%.16g +x_0=%.16g +y_0=%.16g ",
    1469                 :                      GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1470                 :                      GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1471                 :                      GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1472               2 :                      GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1473                 :         else
    1474                 :         {
    1475                 :             CPLError( CE_Failure, CPLE_NotSupported,
    1476               0 :                       "Mercator_1SP with scale != 1.0 and latitude of origin != 0, not supported by PROJ.4." );
    1477               0 :             *ppszProj4 = CPLStrdup("");
    1478               0 :             return OGRERR_UNSUPPORTED_SRS;
    1479                 :         }
    1480                 :     }
    1481                 : 
    1482             171 :     else if( EQUAL(pszProjection,SRS_PT_MERCATOR_2SP) )
    1483                 :     {
    1484                 :         sprintf( szProj4+strlen(szProj4),
    1485                 :                  "+proj=merc +lon_0=%.16g +lat_ts=%.16g +x_0=%.16g +y_0=%.16g ",
    1486                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1487                 :                  GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0),
    1488                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1489              10 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1490                 :     }
    1491                 : 
    1492             161 :     else if( EQUAL(pszProjection,SRS_PT_OBLIQUE_STEREOGRAPHIC) )
    1493                 :     {
    1494                 :         sprintf( szProj4+strlen(szProj4),
    1495                 :                  "+proj=sterea +lat_0=%.16g +lon_0=%.16g +k=%.16g +x_0=%.16g +y_0=%.16g ",
    1496                 : //         "+proj=stere +lat_0=%.16g +lon_0=%.16g +k=%.16g +x_0=%.16g +y_0=%.16g ",
    1497                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1498                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1499                 :                  GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
    1500                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1501              10 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1502                 :     }
    1503                 : 
    1504             151 :     else if( EQUAL(pszProjection,SRS_PT_STEREOGRAPHIC) )
    1505                 :     {
    1506                 :         sprintf( szProj4+strlen(szProj4),
    1507                 :                  "+proj=stere +lat_0=%.16g +lon_0=%.16g +k=%.16g +x_0=%.16g +y_0=%.16g ",
    1508                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1509                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1510                 :                  GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
    1511                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1512               8 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1513                 :     }
    1514                 : 
    1515             143 :     else if( EQUAL(pszProjection,SRS_PT_POLAR_STEREOGRAPHIC) )
    1516                 :     {
    1517              12 :         if( GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0) >= 0.0 )
    1518                 :             sprintf( szProj4+strlen(szProj4),
    1519                 :                      "+proj=stere +lat_0=90 +lat_ts=%.16g +lon_0=%.16g "
    1520                 :                      "+k=%.16g +x_0=%.16g +y_0=%.16g ",
    1521                 :                      GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,90.0),
    1522                 :                      GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1523                 :                      GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
    1524                 :                      GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1525               6 :                      GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1526                 :         else
    1527                 :             sprintf( szProj4+strlen(szProj4),
    1528                 :                      "+proj=stere +lat_0=-90 +lat_ts=%.16g +lon_0=%.16g "
    1529                 :                      "+k=%.16g +x_0=%.16g +y_0=%.16g ",
    1530                 :                      GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,-90.0),
    1531                 :                      GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1532                 :                      GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
    1533                 :                      GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1534               6 :                      GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1535                 :     }
    1536                 : 
    1537             131 :     else if( EQUAL(pszProjection,SRS_PT_EQUIRECTANGULAR) )
    1538                 :     {
    1539                 :         sprintf( szProj4+strlen(szProj4),
    1540                 :                  "+proj=eqc +lat_ts=%.16g +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1541                 :                  GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0),
    1542                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1543                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1544                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1545               4 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1546                 :     }
    1547                 : 
    1548             127 :     else if( EQUAL(pszProjection,SRS_PT_GAUSSSCHREIBERTMERCATOR) )
    1549                 :     {
    1550                 :         sprintf( szProj4+strlen(szProj4),
    1551                 :                  "+proj=gstmerc +lat_0=%.16g +lon_0=%.16g"
    1552                 :                  " +k_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1553                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,-21.116666667),
    1554                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,55.53333333309),
    1555                 :                  GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
    1556                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,160000.000),
    1557               1 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,50000.000) );
    1558                 :     }
    1559                 : 
    1560             126 :     else if( EQUAL(pszProjection,SRS_PT_GNOMONIC) )
    1561                 :     {
    1562                 :         sprintf( szProj4+strlen(szProj4),
    1563                 :                  "+proj=gnom +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1564                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1565                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1566                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1567               1 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1568                 :     }
    1569                 : 
    1570             125 :     else if( EQUAL(pszProjection,SRS_PT_ORTHOGRAPHIC) )
    1571                 :     {
    1572                 :         sprintf( szProj4+strlen(szProj4),
    1573                 :                  "+proj=ortho +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1574                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1575                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1576                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1577               9 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1578                 :     }
    1579                 : 
    1580             116 :     else if( EQUAL(pszProjection,SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) )
    1581                 :     {
    1582                 :         sprintf( szProj4+strlen(szProj4),
    1583                 :                  "+proj=laea +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1584                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1585                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1586                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1587               6 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1588                 :     }
    1589                 : 
    1590             110 :     else if( EQUAL(pszProjection,SRS_PT_AZIMUTHAL_EQUIDISTANT) )
    1591                 :     {
    1592                 :         sprintf( szProj4+strlen(szProj4),
    1593                 :                  "+proj=aeqd +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1594                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1595                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1596                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1597              13 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1598                 :     }
    1599                 : 
    1600              97 :     else if( EQUAL(pszProjection,SRS_PT_EQUIDISTANT_CONIC) )
    1601                 :     {
    1602                 :         sprintf( szProj4+strlen(szProj4),
    1603                 :                  "+proj=eqdc +lat_0=%.16g +lon_0=%.16g +lat_1=%.16g +lat_2=%.16g"
    1604                 :                  " +x_0=%.16g +y_0=%.16g ",
    1605                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_CENTER,0.0),
    1606                 :                  GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0),
    1607                 :                  GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0),
    1608                 :                  GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2,0.0),
    1609                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1610               1 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1611                 :     }
    1612                 : 
    1613              96 :     else if( EQUAL(pszProjection,SRS_PT_MILLER_CYLINDRICAL) )
    1614                 :     {
    1615                 :         sprintf( szProj4+strlen(szProj4),
    1616                 :                  "+proj=mill +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g +R_A ",
    1617                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1618                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1619                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1620               1 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1621                 :     }
    1622                 : 
    1623              95 :     else if( EQUAL(pszProjection,SRS_PT_MOLLWEIDE) )
    1624                 :     {
    1625                 :         sprintf( szProj4+strlen(szProj4),
    1626                 :                  "+proj=moll +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1627                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1628                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1629               1 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1630                 :     }
    1631                 : 
    1632              94 :     else if( EQUAL(pszProjection,SRS_PT_ECKERT_I) )
    1633                 :     {
    1634                 :         sprintf( szProj4+strlen(szProj4),
    1635                 :                  "+proj=eck1 +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1636                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1637                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1638               1 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1639                 :     }
    1640                 : 
    1641              93 :     else if( EQUAL(pszProjection,SRS_PT_ECKERT_II) )
    1642                 :     {
    1643                 :         sprintf( szProj4+strlen(szProj4),
    1644                 :                  "+proj=eck2 +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1645                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1646                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1647               1 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1648                 :     }
    1649                 : 
    1650              92 :     else if( EQUAL(pszProjection,SRS_PT_ECKERT_III) )
    1651                 :     {
    1652                 :         sprintf( szProj4+strlen(szProj4),
    1653                 :                  "+proj=eck3 +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1654                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1655                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1656               1 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1657                 :     }
    1658                 :     
    1659              91 :     else if( EQUAL(pszProjection,SRS_PT_ECKERT_IV) )
    1660                 :     {
    1661                 :         sprintf( szProj4+strlen(szProj4),
    1662                 :                  "+proj=eck4 +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1663                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1664                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1665               7 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1666                 :     }
    1667                 :     
    1668              84 :     else if( EQUAL(pszProjection,SRS_PT_ECKERT_V) )
    1669                 :     {
    1670                 :         sprintf( szProj4+strlen(szProj4),
    1671                 :                  "+proj=eck5 +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1672                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1673                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1674               1 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1675                 :     }
    1676                 :     
    1677              83 :     else if( EQUAL(pszProjection,SRS_PT_ECKERT_VI) )
    1678                 :     {
    1679                 :         sprintf( szProj4+strlen(szProj4),
    1680                 :                  "+proj=eck6 +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1681                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1682                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1683               1 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1684                 :     }
    1685                 : 
    1686              82 :     else if( EQUAL(pszProjection,SRS_PT_POLYCONIC) )
    1687                 :     {
    1688                 :         sprintf( szProj4+strlen(szProj4),
    1689                 :                  "+proj=poly +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1690                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1691                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1692                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1693               2 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1694                 :     }
    1695                 : 
    1696              80 :     else if( EQUAL(pszProjection,SRS_PT_ALBERS_CONIC_EQUAL_AREA) )
    1697                 :     {
    1698                 :         sprintf( szProj4+strlen(szProj4),
    1699                 :                  "+proj=aea +lat_1=%.16g +lat_2=%.16g +lat_0=%.16g +lon_0=%.16g"
    1700                 :                  " +x_0=%.16g +y_0=%.16g ",
    1701                 :                  GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0),
    1702                 :                  GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2,0.0),
    1703                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1704                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1705                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1706               6 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1707                 :     }
    1708                 : 
    1709              74 :     else if( EQUAL(pszProjection,SRS_PT_ROBINSON) )
    1710                 :     {
    1711                 :         sprintf( szProj4+strlen(szProj4),
    1712                 :                  "+proj=robin +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1713                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1714                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1715               1 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1716                 :     }
    1717                 : 
    1718              73 :     else if( EQUAL(pszProjection,SRS_PT_VANDERGRINTEN) )
    1719                 :     {
    1720                 :         sprintf( szProj4+strlen(szProj4),
    1721                 :                  "+proj=vandg +lon_0=%.16g +x_0=%.16g +y_0=%.16g +R_A ",
    1722                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1723                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1724               9 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1725                 :     }
    1726                 : 
    1727              64 :     else if( EQUAL(pszProjection,SRS_PT_SINUSOIDAL) )
    1728                 :     {
    1729                 :         sprintf( szProj4+strlen(szProj4),
    1730                 :                  "+proj=sinu +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1731                 :                  GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0),
    1732                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1733               7 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1734                 :     }
    1735                 : 
    1736              57 :     else if( EQUAL(pszProjection,SRS_PT_GALL_STEREOGRAPHIC) )
    1737                 :     {
    1738                 :         sprintf( szProj4+strlen(szProj4),
    1739                 :                  "+proj=gall +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1740                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1741                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1742               2 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1743                 :     }
    1744                 : 
    1745              55 :     else if( EQUAL(pszProjection,SRS_PT_GOODE_HOMOLOSINE) )
    1746                 :     {
    1747                 :         sprintf( szProj4+strlen(szProj4),
    1748                 :                  "+proj=goode +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1749                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1750                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1751               1 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1752                 :     }
    1753                 : 
    1754              54 :     else if( EQUAL(pszProjection,SRS_PT_IGH) )
    1755                 :     {
    1756               1 :         sprintf( szProj4+strlen(szProj4), "+proj=igh " );
    1757                 :     }
    1758                 : 
    1759              53 :     else if( EQUAL(pszProjection,SRS_PT_GEOSTATIONARY_SATELLITE) )
    1760                 :     {
    1761                 :         sprintf( szProj4+strlen(szProj4),
    1762                 :                  "+proj=geos +lon_0=%.16g +h=%.16g +x_0=%.16g +y_0=%.16g ",
    1763                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1764                 :                  GetNormProjParm(SRS_PP_SATELLITE_HEIGHT,35785831.0),
    1765                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1766               1 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1767                 :     }
    1768                 : 
    1769              80 :     else if( EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP)
    1770                 :              || EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM) )
    1771                 :     {
    1772                 :         sprintf( szProj4+strlen(szProj4),
    1773                 :                  "+proj=lcc +lat_1=%.16g +lat_2=%.16g +lat_0=%.16g +lon_0=%.16g"
    1774                 :                  " +x_0=%.16g +y_0=%.16g ",
    1775                 :                  GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0),
    1776                 :                  GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2,0.0),
    1777                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1778                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1779                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1780              28 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1781                 :     }
    1782                 :     
    1783              24 :     else if( EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP) )
    1784                 :     {
    1785                 :         sprintf( szProj4+strlen(szProj4),
    1786                 :                  "+proj=lcc +lat_1=%.16g +lat_0=%.16g +lon_0=%.16g"
    1787                 :                  " +k_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1788                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1789                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1790                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1791                 :                  GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
    1792                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1793               5 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1794                 :     }
    1795                 : 
    1796              19 :     else if( EQUAL(pszProjection,SRS_PT_HOTINE_OBLIQUE_MERCATOR) )
    1797                 :     {
    1798                 :         /* special case for swiss oblique mercator : see bug 423 */
    1799               5 :         if( fabs(GetNormProjParm(SRS_PP_AZIMUTH,0.0) - 90.0) < 0.0001 
    1800                 :             && fabs(GetNormProjParm(SRS_PP_RECTIFIED_GRID_ANGLE,0.0)-90.0) < 0.0001 )
    1801                 :         {
    1802                 :             sprintf( szProj4+strlen(szProj4),
    1803                 :                      "+proj=somerc +lat_0=%.16g +lon_0=%.16g"
    1804                 :                      " +k_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1805                 :                      GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1806                 :                      GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1807                 :                      GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
    1808                 :                      GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1809               3 :                      GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1810                 :         }
    1811                 :         else
    1812                 :         {
    1813                 :             sprintf( szProj4+strlen(szProj4),
    1814                 :                      "+proj=omerc +lat_0=%.16g +lonc=%.16g +alpha=%.16g"
    1815                 :                      " +k=%.16g +x_0=%.16g +y_0=%.16g ",
    1816                 :                      GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1817                 :                      GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1818                 :                      GetNormProjParm(SRS_PP_AZIMUTH,0.0),
    1819                 :                      GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
    1820                 :                      GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1821               2 :                      GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1822                 : 
    1823                 :             // RSO variant - http://trac.osgeo.org/proj/ticket/62
    1824                 :             // Note that gamma is only supported by PROJ 4.8.0 and later.
    1825               2 :             if( GetNormProjParm(SRS_PP_RECTIFIED_GRID_ANGLE,1000.0) != 1000.0 )
    1826                 :             {
    1827                 :                 sprintf( szProj4+strlen(szProj4), "+gamma=%.16g ",
    1828               2 :                          GetNormProjParm(SRS_PP_RECTIFIED_GRID_ANGLE,1000.0));
    1829                 :             }
    1830                 :         }
    1831                 :     }
    1832                 : 
    1833              14 :     else if( EQUAL(pszProjection,
    1834                 :                    SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN) )
    1835                 :     {
    1836                 :         sprintf( szProj4+strlen(szProj4),
    1837                 :                  "+proj=omerc +lat_0=%.16g"
    1838                 :                  " +lon_1=%.16g +lat_1=%.16g +lon_2=%.16g +lat_2=%.16g"
    1839                 :                  " +k=%.16g +x_0=%.16g +y_0=%.16g ",
    1840                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1841                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_POINT_1,0.0),
    1842                 :                  GetNormProjParm(SRS_PP_LONGITUDE_OF_POINT_1,0.0),
    1843                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_POINT_2,0.0),
    1844                 :                  GetNormProjParm(SRS_PP_LONGITUDE_OF_POINT_2,0.0),
    1845                 :                  GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
    1846                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1847               0 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1848                 :     }
    1849                 : 
    1850              14 :     else if( EQUAL(pszProjection,SRS_PT_KROVAK) )
    1851                 :     {
    1852                 :         sprintf( szProj4+strlen(szProj4),
    1853                 :                  "+proj=krovak +lat_0=%.16g +lon_0=%.16g +alpha=%.16g"
    1854                 :                  " +k=%.16g +x_0=%.16g +y_0=%.16g ",
    1855                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_CENTER,0.0),
    1856                 :                  GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0),
    1857                 :                  GetNormProjParm(SRS_PP_AZIMUTH,0.0),
    1858                 :                  GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
    1859                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1860               2 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1861                 :     }
    1862                 : 
    1863              12 :     else if( EQUAL(pszProjection,SRS_PT_TWO_POINT_EQUIDISTANT) )
    1864                 :     {
    1865                 :         sprintf( szProj4+strlen(szProj4),
    1866                 :                  "+proj=tpeqd +lat_1=%.16g +lon_1=%.16g "
    1867                 :                  "+lat_2=%.16g +lon_2=%.16g "
    1868                 :                  "+x_0=%.16g +y_0=%.16g ",
    1869                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_1ST_POINT,0.0),
    1870                 :                  GetNormProjParm(SRS_PP_LONGITUDE_OF_1ST_POINT,0.0),
    1871                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_2ND_POINT,0.0),
    1872                 :                  GetNormProjParm(SRS_PP_LONGITUDE_OF_2ND_POINT,0.0),
    1873                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1874               3 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1875                 :     }
    1876                 : 
    1877               9 :     else if( EQUAL(pszProjection, SRS_PT_IMW_POLYCONIC) )
    1878                 :     {
    1879                 :         sprintf( szProj4+strlen(szProj4),
    1880                 :                  "+proj=iwm_p +lat_1=%.16g +lat_2=%.16g +lon_0=%.16g "
    1881                 :                  "+x_0=%.16g +y_0=%.16g ",
    1882                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_1ST_POINT, 0.0),
    1883                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_2ND_POINT, 0.0),
    1884                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
    1885                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
    1886               1 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
    1887                 :     }
    1888                 : 
    1889               8 :     else if( EQUAL(pszProjection, SRS_PT_WAGNER_I) )
    1890                 :     {
    1891                 :         sprintf( szProj4+strlen(szProj4),
    1892                 :                  "+proj=wag1 +x_0=%.16g +y_0=%.16g ",
    1893                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
    1894               1 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
    1895                 :     }
    1896                 : 
    1897               7 :     else if( EQUAL(pszProjection, SRS_PT_WAGNER_II) )
    1898                 :     {
    1899                 :         sprintf( szProj4+strlen(szProj4),
    1900                 :                  "+proj=wag2 +x_0=%.16g +y_0=%.16g ",
    1901                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
    1902               1 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
    1903                 :     }
    1904                 : 
    1905               6 :     else if( EQUAL(pszProjection, SRS_PT_WAGNER_III) )
    1906                 :     {
    1907                 :         sprintf( szProj4+strlen(szProj4),
    1908                 :                  "+proj=wag3 +lat_ts=%.16g +x_0=%.16g +y_0=%.16g ",
    1909                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
    1910                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
    1911               1 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
    1912                 :     }
    1913                 : 
    1914               5 :     else if( EQUAL(pszProjection, SRS_PT_WAGNER_IV) )
    1915                 :     {
    1916                 :         sprintf( szProj4+strlen(szProj4),
    1917                 :                  "+proj=wag4 +x_0=%.16g +y_0=%.16g ",
    1918                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
    1919               1 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
    1920                 :     }
    1921                 : 
    1922               4 :     else if( EQUAL(pszProjection, SRS_PT_WAGNER_V) )
    1923                 :     {
    1924                 :         sprintf( szProj4+strlen(szProj4),
    1925                 :                  "+proj=wag5 +x_0=%.16g +y_0=%.16g ",
    1926                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
    1927               1 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
    1928                 :     }
    1929                 : 
    1930               3 :     else if( EQUAL(pszProjection, SRS_PT_WAGNER_VI) )
    1931                 :     {
    1932                 :         sprintf( szProj4+strlen(szProj4),
    1933                 :                  "+proj=wag6 +x_0=%.16g +y_0=%.16g ",
    1934                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
    1935               1 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
    1936                 :     }
    1937                 : 
    1938               2 :     else if( EQUAL(pszProjection, SRS_PT_WAGNER_VII) )
    1939                 :     {
    1940                 :         sprintf( szProj4+strlen(szProj4),
    1941                 :                  "+proj=wag7 +x_0=%.16g +y_0=%.16g ",
    1942                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
    1943               1 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
    1944                 :     }
    1945                 : 
    1946                 :     /* Note: This never really gets used currently.  See bug 423 */
    1947               1 :     else if( EQUAL(pszProjection,SRS_PT_SWISS_OBLIQUE_CYLINDRICAL) )
    1948                 :     {
    1949                 :         sprintf( szProj4+strlen(szProj4),
    1950                 :                  "+proj=somerc +lat_0=%.16g +lon_0=%.16g"
    1951                 :                  " +x_0=%.16g +y_0=%.16g ",
    1952                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1953                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1954                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1955               0 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1956                 :     }
    1957                 : 
    1958                 :     else
    1959                 :     {
    1960                 :         CPLError( CE_Failure, CPLE_NotSupported,
    1961                 :                   "No translation for %s to PROJ.4 format is known.", 
    1962               1 :                   pszProjection );
    1963               1 :         *ppszProj4 = CPLStrdup("");
    1964               1 :         return OGRERR_UNSUPPORTED_SRS;
    1965                 :     }
    1966                 : 
    1967                 : /* -------------------------------------------------------------------- */
    1968                 : /*      Handle earth model.  For now we just always emit the user       */
    1969                 : /*      defined ellipsoid parameters.                                   */
    1970                 : /* -------------------------------------------------------------------- */
    1971             707 :     double      dfSemiMajor = GetSemiMajor();
    1972             707 :     double      dfInvFlattening = GetInvFlattening();
    1973             707 :     const char  *pszPROJ4Ellipse = NULL;
    1974             707 :     const char  *pszDatum = GetAttrValue("DATUM");
    1975                 : 
    1976             707 :     if( ABS(dfSemiMajor-6378249.145) < 0.01
    1977                 :         && ABS(dfInvFlattening-293.465) < 0.0001 )
    1978                 :     {
    1979               0 :         pszPROJ4Ellipse = "clrk80";     /* Clark 1880 */
    1980                 :     }
    1981             712 :     else if( ABS(dfSemiMajor-6378245.0) < 0.01
    1982                 :              && ABS(dfInvFlattening-298.3) < 0.0001 )
    1983                 :     {
    1984               5 :         pszPROJ4Ellipse = "krass";      /* Krassovsky */
    1985                 :     }
    1986             708 :     else if( ABS(dfSemiMajor-6378388.0) < 0.01
    1987                 :              && ABS(dfInvFlattening-297.0) < 0.0001 )
    1988                 :     {
    1989               6 :         pszPROJ4Ellipse = "intl";       /* International 1924 */
    1990                 :     }
    1991             696 :     else if( ABS(dfSemiMajor-6378160.0) < 0.01
    1992                 :              && ABS(dfInvFlattening-298.25) < 0.0001 )
    1993                 :     {
    1994               0 :         pszPROJ4Ellipse = "aust_SA";    /* Australian */
    1995                 :     }
    1996             704 :     else if( ABS(dfSemiMajor-6377397.155) < 0.01
    1997                 :              && ABS(dfInvFlattening-299.1528128) < 0.0001 )
    1998                 :     {
    1999               8 :         pszPROJ4Ellipse = "bessel";     /* Bessel 1841 */
    2000                 :     }
    2001             688 :     else if( ABS(dfSemiMajor-6377483.865) < 0.01
    2002                 :              && ABS(dfInvFlattening-299.1528128) < 0.0001 )
    2003                 :     {
    2004               0 :         pszPROJ4Ellipse = "bess_nam";   /* Bessel 1841 (Namibia / Schwarzeck)*/
    2005                 :     }
    2006             690 :     else if( ABS(dfSemiMajor-6378160.0) < 0.01
    2007                 :              && ABS(dfInvFlattening-298.247167427) < 0.0001 )
    2008                 :     {
    2009               2 :         pszPROJ4Ellipse = "GRS67";      /* GRS 1967 */
    2010                 :     }
    2011             784 :     else if( ABS(dfSemiMajor-6378137) < 0.01
    2012                 :              && ABS(dfInvFlattening-298.257222101) < 0.000001 )
    2013                 :     {
    2014              98 :         pszPROJ4Ellipse = "GRS80";      /* GRS 1980 */
    2015                 :     }
    2016             679 :     else if( ABS(dfSemiMajor-6378206.4) < 0.01
    2017                 :              && ABS(dfInvFlattening-294.9786982) < 0.0001 )
    2018                 :     {
    2019              91 :         pszPROJ4Ellipse = "clrk66";     /* Clarke 1866 */
    2020                 :     }
    2021             497 :     else if( ABS(dfSemiMajor-6377340.189) < 0.01
    2022                 :              && ABS(dfInvFlattening-299.3249646) < 0.0001 )
    2023                 :     {
    2024               0 :         pszPROJ4Ellipse = "mod_airy";   /* Modified Airy */
    2025                 :     }
    2026             502 :     else if( ABS(dfSemiMajor-6377563.396) < 0.01
    2027                 :              && ABS(dfInvFlattening-299.3249646) < 0.0001 )
    2028                 :     {
    2029               5 :         pszPROJ4Ellipse = "airy";       /* Airy */
    2030                 :     }
    2031             492 :     else if( ABS(dfSemiMajor-6378200) < 0.01
    2032                 :              && ABS(dfInvFlattening-298.3) < 0.0001 )
    2033                 :     {
    2034               0 :         pszPROJ4Ellipse = "helmert";    /* Helmert 1906 */
    2035                 :     }
    2036             492 :     else if( ABS(dfSemiMajor-6378155) < 0.01
    2037                 :              && ABS(dfInvFlattening-298.3) < 0.0001 )
    2038                 :     {
    2039               0 :         pszPROJ4Ellipse = "fschr60m";   /* Modified Fischer 1960 */
    2040                 :     }
    2041             492 :     else if( ABS(dfSemiMajor-6377298.556) < 0.01
    2042                 :              && ABS(dfInvFlattening-300.8017) < 0.0001 )
    2043                 :     {
    2044               0 :         pszPROJ4Ellipse = "evrstSS";    /* Everest (Sabah & Sarawak) */
    2045                 :     }
    2046             492 :     else if( ABS(dfSemiMajor-6378165.0) < 0.01
    2047                 :              && ABS(dfInvFlattening-298.3) < 0.0001 )
    2048                 :     {
    2049               0 :         pszPROJ4Ellipse = "WGS60";      
    2050                 :     }
    2051             492 :     else if( ABS(dfSemiMajor-6378145.0) < 0.01
    2052                 :              && ABS(dfInvFlattening-298.25) < 0.0001 )
    2053                 :     {
    2054               0 :         pszPROJ4Ellipse = "WGS66";      
    2055                 :     }
    2056             493 :     else if( ABS(dfSemiMajor-6378135.0) < 0.01
    2057                 :              && ABS(dfInvFlattening-298.26) < 0.0001 )
    2058                 :     {
    2059               1 :         pszPROJ4Ellipse = "WGS72";      
    2060                 :     }
    2061             962 :     else if( ABS(dfSemiMajor-6378137.0) < 0.01
    2062                 :              && ABS(dfInvFlattening-298.257223563) < 0.000001 )
    2063                 :     {
    2064             471 :         pszPROJ4Ellipse = "WGS84";
    2065                 :     }
    2066              20 :     else if( EQUAL(pszDatum,"North_American_Datum_1927") )
    2067                 :     {
    2068                 : //        pszPROJ4Ellipse = "clrk66:+datum=nad27"; /* NAD 27 */
    2069               0 :         pszPROJ4Ellipse = "clrk66";
    2070                 :     }
    2071              20 :     else if( EQUAL(pszDatum,"North_American_Datum_1983") )
    2072                 :     {
    2073                 : //        pszPROJ4Ellipse = "GRS80:+datum=nad83";       /* NAD 83 */
    2074               0 :         pszPROJ4Ellipse = "GRS80";
    2075                 :     }
    2076                 : 
    2077                 :     char szEllipseDef[128];
    2078                 : 
    2079             707 :     if( pszPROJ4Ellipse == NULL )
    2080                 :         sprintf( szEllipseDef, "+a=%.16g +b=%.16g ",
    2081              20 :                  GetSemiMajor(), GetSemiMinor() );
    2082                 :     else
    2083                 :         sprintf( szEllipseDef, "+ellps=%s ",
    2084             687 :                  pszPROJ4Ellipse );
    2085                 : 
    2086                 : /* -------------------------------------------------------------------- */
    2087                 : /*      Translate the datum.                                            */
    2088                 : /* -------------------------------------------------------------------- */
    2089             707 :     const char *pszPROJ4Datum = NULL;
    2090             707 :     const OGR_SRSNode *poTOWGS84 = GetAttrNode( "TOWGS84" );
    2091                 :     char  szTOWGS84[256];
    2092             707 :     int nEPSGDatum = -1;
    2093                 :     const char *pszAuthority;
    2094             707 :     int nEPSGGeogCS = -1;
    2095                 :     const char *pszGeogCSAuthority;
    2096             707 :     const char *pszProj4Grids = GetExtension( "DATUM", "PROJ4_GRIDS" );
    2097                 : 
    2098             707 :     pszAuthority = GetAuthorityName( "DATUM" );
    2099                 : 
    2100             707 :     if( pszAuthority != NULL && EQUAL(pszAuthority,"EPSG") )
    2101             557 :         nEPSGDatum = atoi(GetAuthorityCode( "DATUM" ));
    2102                 : 
    2103             707 :     pszGeogCSAuthority = GetAuthorityName( "GEOGCS" );
    2104                 : 
    2105             707 :     if( pszGeogCSAuthority != NULL && EQUAL(pszGeogCSAuthority,"EPSG") )
    2106             561 :         nEPSGGeogCS = atoi(GetAuthorityCode( "GEOGCS" ));
    2107                 : 
    2108             707 :     if( pszDatum == NULL )
    2109                 :         /* nothing */;
    2110                 : 
    2111             793 :     else if( EQUAL(pszDatum,SRS_DN_NAD27) || nEPSGDatum == 6267 )
    2112              86 :         pszPROJ4Datum = "NAD27";
    2113                 : 
    2114             700 :     else if( EQUAL(pszDatum,SRS_DN_NAD83) || nEPSGDatum == 6269 )
    2115              79 :         pszPROJ4Datum = "NAD83";
    2116                 : 
    2117             913 :     else if( EQUAL(pszDatum,SRS_DN_WGS84) || nEPSGDatum == 6326 )
    2118             371 :         pszPROJ4Datum = "WGS84";
    2119                 : 
    2120             171 :     else if( (pszPROJ4Datum = OGRGetProj4Datum(pszDatum, nEPSGDatum)) != NULL )
    2121                 :     {
    2122                 :         /* nothing */
    2123                 :     }
    2124                 : 
    2125             707 :     if( pszProj4Grids != NULL )
    2126                 :     {
    2127               0 :         SAFE_PROJ4_STRCAT( szEllipseDef );
    2128               0 :         szEllipseDef[0] = '\0';
    2129               0 :         SAFE_PROJ4_STRCAT( "+nadgrids=" );
    2130               0 :         SAFE_PROJ4_STRCAT( pszProj4Grids );
    2131               0 :         SAFE_PROJ4_STRCAT(  " " );
    2132               0 :         pszPROJ4Datum = NULL;
    2133                 :     }
    2134                 : 
    2135             707 :     if( pszPROJ4Datum == NULL 
    2136                 :         || CSLTestBoolean(CPLGetConfigOption("OVERRIDE_PROJ_DATUM_WITH_TOWGS84", "YES")) )
    2137                 :     {
    2138             707 :         if( poTOWGS84 != NULL )
    2139                 :         {
    2140                 :             int iChild;
    2141             227 :             if( poTOWGS84->GetChildCount() >= 3
    2142                 :                 && (poTOWGS84->GetChildCount() < 7 
    2143                 :                     || (EQUAL(poTOWGS84->GetChild(3)->GetValue(),"")
    2144                 :                         && EQUAL(poTOWGS84->GetChild(4)->GetValue(),"")
    2145                 :                         && EQUAL(poTOWGS84->GetChild(5)->GetValue(),"")
    2146                 :                         && EQUAL(poTOWGS84->GetChild(6)->GetValue(),""))) )
    2147                 :             {
    2148               0 :                 SAFE_PROJ4_STRCAT( szEllipseDef );
    2149               0 :                 szEllipseDef[0] = '\0';
    2150               0 :                 SAFE_PROJ4_STRCAT( "+towgs84=");
    2151               0 :                 for(iChild = 0; iChild < 3; iChild ++)
    2152                 :                 {
    2153               0 :                     if (iChild > 0 ) SAFE_PROJ4_STRCAT( "," );
    2154               0 :                     SAFE_PROJ4_STRCAT( poTOWGS84->GetChild(iChild)->GetValue() );
    2155                 :                 }
    2156               0 :                 SAFE_PROJ4_STRCAT( " " );
    2157               0 :                 pszPROJ4Datum = NULL;
    2158                 :             }
    2159             227 :             else if( poTOWGS84->GetChildCount() >= 7)
    2160                 :             {
    2161             227 :                 SAFE_PROJ4_STRCAT( szEllipseDef );
    2162             227 :                 szEllipseDef[0] = '\0';
    2163             227 :                 SAFE_PROJ4_STRCAT( "+towgs84=");
    2164            1816 :                 for(iChild = 0; iChild < 7; iChild ++)
    2165                 :                 {
    2166            1589 :                     if (iChild > 0 ) SAFE_PROJ4_STRCAT( "," );
    2167            1589 :                     SAFE_PROJ4_STRCAT( poTOWGS84->GetChild(iChild)->GetValue() );
    2168                 :                 }
    2169             227 :                 SAFE_PROJ4_STRCAT( " " );
    2170             227 :                 pszPROJ4Datum = NULL;
    2171                 :             }
    2172                 :         }
    2173                 :         
    2174                 :         // If we don't know the datum, trying looking up TOWGS84 parameters
    2175                 :         // based on the EPSG GCS code.
    2176             480 :         else if( nEPSGGeogCS != -1 && pszPROJ4Datum == NULL )
    2177                 :         {
    2178                 :             double padfTransform[7];
    2179               7 :             if( EPSGGetWGS84Transform( nEPSGGeogCS, padfTransform ) )
    2180                 :             {
    2181                 :                 sprintf( szTOWGS84, "+towgs84=%.16g,%.16g,%.16g,%.16g,%.16g,%.16g,%.16g",
    2182                 :                          padfTransform[0],
    2183                 :                          padfTransform[1],
    2184                 :                          padfTransform[2],
    2185                 :                          padfTransform[3],
    2186                 :                          padfTransform[4],
    2187                 :                          padfTransform[5],
    2188               0 :                          padfTransform[6] );
    2189               0 :                 SAFE_PROJ4_STRCAT( szEllipseDef );
    2190               0 :                 szEllipseDef[0] = '\0';
    2191                 : 
    2192               0 :                 SAFE_PROJ4_STRCAT( szTOWGS84 );
    2193               0 :                 SAFE_PROJ4_STRCAT( " " );
    2194               0 :                 pszPROJ4Datum = NULL;
    2195                 :             }
    2196                 :         }
    2197                 :     }
    2198                 :     
    2199             707 :     if( pszPROJ4Datum != NULL )
    2200                 :     {
    2201             354 :         SAFE_PROJ4_STRCAT( "+datum=" );
    2202             354 :         SAFE_PROJ4_STRCAT( pszPROJ4Datum );
    2203             354 :         SAFE_PROJ4_STRCAT( " " );
    2204                 :     }
    2205                 :     else // The ellipsedef may already have been appended and will now
    2206                 :         // be empty, otherwise append now.
    2207                 :     {
    2208             353 :         SAFE_PROJ4_STRCAT( szEllipseDef );
    2209             353 :         szEllipseDef[0] = '\0';
    2210                 :     }
    2211                 : 
    2212                 : /* -------------------------------------------------------------------- */
    2213                 : /*      Is there prime meridian info to apply?                          */
    2214                 : /* -------------------------------------------------------------------- */
    2215             707 :     if( poPRIMEM != NULL && poPRIMEM->GetChildCount() >= 2 
    2216                 :         && CPLAtof(poPRIMEM->GetChild(1)->GetValue()) != 0.0 )
    2217                 :     {
    2218               8 :         const char *pszAuthority = GetAuthorityName( "PRIMEM" );
    2219                 :         char szPMValue[128];
    2220               8 :         int  nCode = -1;
    2221                 : 
    2222               8 :         if( pszAuthority != NULL && EQUAL(pszAuthority,"EPSG") )
    2223               7 :             nCode = atoi(GetAuthorityCode( "PRIMEM" ));
    2224                 : 
    2225               8 :         const OGRProj4PM* psProj4PM = NULL;
    2226               8 :         if (nCode > 0)
    2227               7 :             psProj4PM = OGRGetProj4PMFromCode(nCode);
    2228               8 :         if (psProj4PM == NULL)
    2229               1 :             psProj4PM = OGRGetProj4PMFromVal(dfFromGreenwich);
    2230                 : 
    2231               8 :         if (psProj4PM != NULL)
    2232                 :         {
    2233               8 :             strcpy( szPMValue, psProj4PM->pszProj4PMName );
    2234                 :         }
    2235                 :         else
    2236                 :         {
    2237               0 :             sprintf( szPMValue, "%.16g", dfFromGreenwich );
    2238                 :         }
    2239                 : 
    2240               8 :         SAFE_PROJ4_STRCAT( "+pm=" );
    2241               8 :         SAFE_PROJ4_STRCAT( szPMValue );
    2242               8 :         SAFE_PROJ4_STRCAT( " " );
    2243                 :     }
    2244                 :     
    2245                 : /* -------------------------------------------------------------------- */
    2246                 : /*      Handle linear units.                                            */
    2247                 : /* -------------------------------------------------------------------- */
    2248             707 :     const char  *pszPROJ4Units=NULL;
    2249             707 :     char        *pszLinearUnits = NULL;
    2250                 :     double      dfLinearConv;
    2251                 : 
    2252             707 :     dfLinearConv = GetLinearUnits( &pszLinearUnits );
    2253                 :         
    2254             707 :     if( strstr(szProj4,"longlat") != NULL )
    2255             257 :         pszPROJ4Units = NULL;
    2256                 :     else 
    2257                 :     {
    2258             450 :         pszPROJ4Units = LinearToProj4( dfLinearConv, pszLinearUnits );
    2259                 : 
    2260             450 :         if( pszPROJ4Units == NULL )
    2261                 :         {
    2262                 :             char szLinearConv[128];
    2263               1 :             sprintf( szLinearConv, "%.16g", dfLinearConv );
    2264               1 :             SAFE_PROJ4_STRCAT( "+to_meter=" );
    2265               1 :             SAFE_PROJ4_STRCAT( szLinearConv );
    2266               1 :             SAFE_PROJ4_STRCAT( " " );
    2267                 :         }
    2268                 :     }
    2269                 : 
    2270             707 :     if( pszPROJ4Units != NULL )
    2271                 :     {
    2272             449 :         SAFE_PROJ4_STRCAT( "+units=");
    2273             449 :         SAFE_PROJ4_STRCAT( pszPROJ4Units );
    2274             449 :         SAFE_PROJ4_STRCAT( " " );
    2275                 :     }
    2276                 : 
    2277                 : /* -------------------------------------------------------------------- */
    2278                 : /*      If we have vertical datum grids, attach them to the proj.4 string.*/
    2279                 : /* -------------------------------------------------------------------- */
    2280             707 :     const char *pszProj4Geoids = GetExtension( "VERT_DATUM", "PROJ4_GRIDS" );
    2281                 :     
    2282             707 :     if( pszProj4Geoids != NULL )
    2283                 :     {
    2284               2 :         SAFE_PROJ4_STRCAT( "+geoidgrids=" );
    2285               2 :         SAFE_PROJ4_STRCAT( pszProj4Geoids );
    2286               2 :         SAFE_PROJ4_STRCAT(  " " );
    2287                 :     }    
    2288                 : 
    2289                 : /* -------------------------------------------------------------------- */
    2290                 : /*      Handle vertical units, but only if we have them.                */
    2291                 : /* -------------------------------------------------------------------- */
    2292             707 :     const OGR_SRSNode *poVERT_CS = GetRoot()->GetNode( "VERT_CS" );
    2293             707 :     const OGR_SRSNode *poVUNITS = NULL;
    2294                 : 
    2295             707 :     if( poVERT_CS != NULL )
    2296               3 :         poVUNITS = poVERT_CS->GetNode( "UNIT" );
    2297                 : 
    2298             707 :     if( poVUNITS != NULL && poVUNITS->GetChildCount() >= 2 )
    2299                 :     {
    2300               3 :         pszPROJ4Units = NULL;
    2301                 : 
    2302               3 :         dfLinearConv = CPLAtof( poVUNITS->GetChild(1)->GetValue() );
    2303                 :         
    2304                 :         pszPROJ4Units = LinearToProj4( dfLinearConv,
    2305               3 :                                        poVUNITS->GetChild(0)->GetValue() );
    2306                 :             
    2307               3 :         if( pszPROJ4Units == NULL )
    2308                 :         {
    2309                 :             char szLinearConv[128];
    2310               0 :             sprintf( szLinearConv, "%.16g", dfLinearConv );
    2311               0 :             SAFE_PROJ4_STRCAT( "+vto_meter=" );
    2312               0 :             SAFE_PROJ4_STRCAT( szLinearConv );
    2313               0 :             SAFE_PROJ4_STRCAT( " " );
    2314                 :         }
    2315                 :         else
    2316                 :         {
    2317               3 :             SAFE_PROJ4_STRCAT( "+vunits=");
    2318               3 :             SAFE_PROJ4_STRCAT( pszPROJ4Units );
    2319               3 :             SAFE_PROJ4_STRCAT( " " );
    2320                 :         }
    2321                 :     }
    2322                 : 
    2323                 : /* -------------------------------------------------------------------- */
    2324                 : /*      Add the no_defs flag to ensure that no values from              */
    2325                 : /*      proj_def.dat are implicitly used with our definitions.          */
    2326                 : /* -------------------------------------------------------------------- */
    2327             707 :     SAFE_PROJ4_STRCAT( "+no_defs " );
    2328                 :     
    2329             707 :     *ppszProj4 = CPLStrdup( szProj4 );
    2330                 : 
    2331             707 :     return OGRERR_NONE;
    2332                 : }
    2333                 : 

Generated by: LCOV version 1.7