LCOV - code coverage report
Current view: directory - ogr - ogr_srs_proj4.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 715 613 85.7 %
Date: 2012-04-28 Functions: 11 11 100.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogr_srs_proj4.cpp 24323 2012-04-27 05:45:18Z warmerdam $
       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 24323 2012-04-27 05:45:18Z warmerdam $");
      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             654 : static const char* OGRGetProj4Datum(const char* pszDatum,
     134                 :                                     int nEPSGDatum)
     135                 : {
     136                 :     unsigned int i;
     137            5206 :     for(i=0;i<sizeof(ogr_pj_datums)/sizeof(ogr_pj_datums[0]);i++)
     138                 :     {
     139            4566 :         if (nEPSGDatum == ogr_pj_datums[i].nGCS ||
     140                 :             EQUAL(pszDatum, ogr_pj_datums[i].pszOGR))
     141                 :         {
     142              14 :             return ogr_pj_datums[i].pszPJ;
     143                 :         }
     144                 :     }
     145             640 :     return NULL;
     146                 : }
     147                 : 
     148              14 : static const OGRProj4PM* OGRGetProj4PMFromProj4Name(const char* pszProj4PMName)
     149                 : {
     150                 :     unsigned int i;
     151              92 :     for(i=0;i<sizeof(ogr_pj_pms)/sizeof(ogr_pj_pms[0]);i++)
     152                 :     {
     153              90 :         if (EQUAL(pszProj4PMName, ogr_pj_pms[i].pszProj4PMName))
     154                 :         {
     155              12 :             return &ogr_pj_pms[i];
     156                 :         }
     157                 :     }
     158               2 :     return NULL;
     159                 : }
     160                 : 
     161              14 : static const OGRProj4PM* OGRGetProj4PMFromCode(int nPMCode)
     162                 : {
     163                 :     unsigned int i;
     164              80 :     for(i=0;i<sizeof(ogr_pj_pms)/sizeof(ogr_pj_pms[0]);i++)
     165                 :     {
     166              80 :         if (nPMCode == ogr_pj_pms[i].nPMCode)
     167                 :         {
     168              14 :             return &ogr_pj_pms[i];
     169                 :         }
     170                 :     }
     171               0 :     return NULL;
     172                 : }
     173                 : 
     174               2 : static const OGRProj4PM* OGRGetProj4PMFromVal(double dfVal)
     175                 : {
     176                 :     unsigned int i;
     177               6 :     for(i=0;i<sizeof(ogr_pj_pms)/sizeof(ogr_pj_pms[0]);i++)
     178                 :     {
     179               6 :         if (fabs(dfVal - CPLDMSToDec(ogr_pj_pms[i].pszFromGreenwich)) < 1e-10)
     180                 :         {
     181               2 :             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             270 : char **OSRProj4Tokenize( const char *pszFull )
     196                 : 
     197                 : {
     198             270 :     char *pszStart = NULL;
     199                 :     char *pszFullWrk;
     200             270 :     char **papszTokens = NULL;
     201                 :     int  i;
     202                 : 
     203             270 :     if( pszFull == NULL )
     204               0 :         return NULL;
     205                 : 
     206             270 :     pszFullWrk = CPLStrdup( pszFull );
     207                 : 
     208           20726 :     for( i=0; pszFullWrk[i] != '\0'; i++ )
     209                 :     {
     210           20456 :         switch( pszFullWrk[i] )
     211                 :         {
     212                 :           case '+':
     213            1798 :             if( i == 0 || pszFullWrk[i-1] == '\0' )
     214                 :             {
     215            1796 :                 if( pszStart != NULL )
     216                 :                 {
     217            1530 :                     if( strstr(pszStart,"=") != NULL )
     218            1484 :                         papszTokens = CSLAddString( papszTokens, pszStart );
     219                 :                     else
     220                 :                     {
     221              46 :                         CPLString osAsBoolean = pszStart;
     222              46 :                         osAsBoolean += "=yes";
     223              46 :                         papszTokens = CSLAddString( papszTokens, osAsBoolean );
     224                 :                     }
     225                 :                 }
     226            1796 :                 pszStart = pszFullWrk + i + 1;
     227                 :             }
     228            1798 :             break;
     229                 : 
     230                 :           case ' ':
     231                 :           case '\t':
     232                 :           case '\n':
     233            1776 :             pszFullWrk[i] = '\0';
     234                 :             break;
     235                 : 
     236                 :           default:
     237                 :             break;
     238                 :         }
     239                 :     }
     240                 : 
     241             270 :     if( pszStart != NULL && strlen(pszStart) > 0 )
     242             266 :         papszTokens = CSLAddString( papszTokens, pszStart );
     243                 : 
     244             270 :     CPLFree( pszFullWrk );
     245                 : 
     246             270 :     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             138 : OGRErr OSRImportFromProj4( OGRSpatialReferenceH hSRS, const char *pszProj4 )
     259                 : 
     260                 : {
     261             138 :     VALIDATE_POINTER1( hSRS, "OSRImportFromProj4", CE_Failure );
     262                 : 
     263             138 :     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            1136 : static double OSR_GDV( char **papszNV, const char * pszField, 
     275                 :                        double dfDefaultValue )
     276                 : 
     277                 : {
     278                 :     const char * pszValue;
     279                 : 
     280            1136 :     pszValue = CSLFetchNameValue( papszNV, pszField );
     281                 : 
     282                 :     // special hack to use k_0 if available.
     283            1136 :     if( pszValue == NULL && EQUAL(pszField,"k") )
     284              18 :         pszValue = CSLFetchNameValue( papszNV, "k_0" );
     285                 : 
     286            1136 :     if( pszValue == NULL )
     287             132 :         return dfDefaultValue;
     288                 :     else
     289            1004 :         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             270 : OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
     344                 : 
     345                 : {
     346             270 :     char **papszNV = NULL;
     347                 :     char **papszTokens;
     348                 :     int  i;
     349                 :     char *pszCleanCopy;
     350                 : 
     351                 : /* -------------------------------------------------------------------- */
     352                 : /*      Clear any existing definition.                                  */
     353                 : /* -------------------------------------------------------------------- */
     354             270 :     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             270 :     pszCleanCopy = CPLStrdup( pszProj4 );
     361           17598 :     for( i = 0; pszCleanCopy[i] != '\0'; i++ )
     362                 :     {
     363           51984 :         if( pszCleanCopy[i] == 10 
     364           17328 :             || pszCleanCopy[i] == 13 
     365           17328 :             || 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             270 :     pszNormalized = OCTProj4Normalize( pszCleanCopy );
     376             270 :     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             270 :     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             270 :     papszTokens = OSRProj4Tokenize( pszNormalized );
     401             270 :     CPLFree( pszNormalized );
     402                 :     
     403            2066 :     for( i = 0; papszTokens != NULL && papszTokens[i] != NULL; i++ )
     404                 :     {
     405            1796 :         char *pszEqual = strstr(papszTokens[i],"=");
     406                 : 
     407            1796 :         if( pszEqual == NULL )
     408              78 :             papszNV = CSLAddNameValue(papszNV, papszTokens[i], "" );
     409                 :         else
     410                 :         {
     411            1718 :             pszEqual[0] = '\0';
     412            1718 :             papszNV = CSLAddNameValue( papszNV, papszTokens[i], pszEqual+1 );
     413                 :         }
     414                 :     }
     415                 : 
     416             270 :     CSLDestroy( papszTokens );
     417                 : 
     418                 : /* -------------------------------------------------------------------- */
     419                 : /*      Extract the prime meridian, if there is one set.                */
     420                 : /* -------------------------------------------------------------------- */
     421             270 :     const char *pszPM = CSLFetchNameValue( papszNV, "pm" );
     422             270 :     double dfFromGreenwich = 0.0;
     423             270 :     int    nPMCode = -1;
     424                 : 
     425             270 :     if( pszPM != NULL )
     426                 :     {
     427              14 :         const OGRProj4PM* psProj4PM = OGRGetProj4PMFromProj4Name(pszPM);
     428              14 :         if (psProj4PM)
     429                 :         {
     430              12 :             dfFromGreenwich = CPLDMSToDec(psProj4PM->pszFromGreenwich);
     431              12 :             pszPM = psProj4PM->pszWKTPMName;
     432              12 :             nPMCode = psProj4PM->nPMCode;
     433                 :         }
     434                 :         else
     435                 :         {
     436               2 :             dfFromGreenwich = CPLDMSToDec( pszPM );
     437               2 :             pszPM = "unnamed";
     438                 :         }
     439                 :     }
     440                 :     else
     441             256 :         pszPM = "Greenwich";
     442                 : 
     443                 : /* -------------------------------------------------------------------- */
     444                 : /*      Operate on the basis of the projection name.                    */
     445                 : /* -------------------------------------------------------------------- */
     446             270 :     const char *pszProj = CSLFetchNameValue(papszNV,"proj");
     447                 : 
     448             270 :     if( pszProj == NULL )
     449                 :     {
     450               6 :         CPLDebug( "OGR_PROJ4", "Can't find +proj= in:\n%s", pszProj4 );
     451               6 :         CSLDestroy( papszNV );
     452               6 :         return OGRERR_CORRUPT_DATA;
     453                 :     }
     454                 : 
     455             264 :     else if( EQUAL(pszProj,"longlat") || EQUAL(pszProj,"latlong") )
     456                 :     {
     457                 :     }
     458                 :     
     459             238 :     else if( EQUAL(pszProj,"geocent") )
     460                 :     {
     461               4 :         SetGeocCS( "Geocentric" );
     462                 :     }
     463                 :     
     464             234 :     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               2 :                   OSR_GDV( papszNV, "y_0", 0.0 ) );
     470                 :     }
     471                 : 
     472             232 :     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               4 :                OSR_GDV( papszNV, "y_0", 0.0 ) );
     478                 :     }
     479                 : 
     480             228 :     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               4 :                  OSR_GDV( papszNV, "y_0", 6023150.0 ) );
     486                 :     }
     487                 : 
     488             224 :     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               6 :                 OSR_GDV( papszNV, "y_0", 0.0 ) );
     494                 :     }
     495                 : 
     496             218 :     else if( EQUAL(pszProj,"tmerc") )
     497                 :     {
     498              12 :         const char *pszAxis = CSLFetchNameValue( papszNV, "axis" );
     499                 : 
     500              22 :         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              10 :                    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               2 :                      OSR_GDV( papszNV, "y_0", 0.0 ) );
     512                 :     }
     513                 : 
     514             206 :     else if( EQUAL(pszProj,"utm") )
     515                 :     {
     516                 :         SetUTM( (int) OSR_GDV( papszNV, "zone", 0.0 ),
     517              24 :                 (int) OSR_GDV( papszNV, "south", 1.0 ) );
     518                 :     }
     519                 : 
     520             182 :     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               6 :                         OSR_GDV( papszNV, "y_0", 0.0 ) );
     528                 :     }
     529                 : 
     530             176 :     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               6 :                      OSR_GDV( papszNV, "y_0", 0.0 ) );
     537                 :     }
     538                 : 
     539             170 :     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               8 :                OSR_GDV( papszNV, "y_0", 0.0 ) );
     547                 :     }
     548                 : 
     549             162 :     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               6 :                OSR_GDV( papszNV, "y_0", 0.0 ) );
     557                 :     }
     558                 : 
     559             156 :     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               8 :                OSR_GDV( papszNV, "y_0", 0.0 ) );
     566                 :     }
     567                 : 
     568             148 :     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               6 :                           OSR_GDV( papszNV, "y_0", 0.0 ) );
     575                 :     }
     576                 : 
     577             142 :     else if( EQUAL(pszProj,"eqc") )
     578                 :     {
     579               8 :         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               4 :                                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               4 :                               OSR_GDV( papszNV, "y_0", 0.0 ) );
     590                 :     }
     591                 : 
     592             134 :     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               2 :                                     OSR_GDV( papszNV, "y_0", 50000.000 ) );
     599                 :     }
     600                 : 
     601             132 :     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               2 :                      OSR_GDV( papszNV, "y_0", 0.0 ) );
     607                 :     }
     608                 : 
     609             130 :     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               8 :                          OSR_GDV( papszNV, "y_0", 0.0 ) );
     615                 :     }
     616                 : 
     617             122 :     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               6 :                  OSR_GDV( papszNV, "y_0", 0.0 ) );
     623                 :     }
     624                 : 
     625             116 :     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              10 :                OSR_GDV( papszNV, "y_0", 0.0 ) );
     631                 :     }
     632                 : 
     633             106 :     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               2 :                OSR_GDV( papszNV, "y_0", 0.0 ) );
     641                 :     }
     642                 : 
     643             104 :     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               4 :                OSR_GDV( papszNV, "y_0", 0.0 ) );
     649                 :     }
     650                 : 
     651             100 :     else if( EQUAL(pszProj,"moll") )
     652                 :     {
     653                 :         SetMollweide( OSR_GDV( papszNV, "lon_0", 0.0 ), 
     654                 :                       OSR_GDV( papszNV, "x_0", 0.0 ), 
     655               2 :                       OSR_GDV( papszNV, "y_0", 0.0 ) );
     656                 :     }
     657                 : 
     658             112 :     else if( EQUAL(pszProj,"eck1") || EQUAL(pszProj,"eck2") || EQUAL(pszProj,"eck3") ||
     659                 :              EQUAL(pszProj,"eck4") || EQUAL(pszProj,"eck5") || EQUAL(pszProj,"eck6"))
     660                 :     {
     661              14 :         SetEckert(   pszProj[3] - '0',
     662                 :                      OSR_GDV( papszNV, "lon_0", 0.0 ), 
     663                 :                      OSR_GDV( papszNV, "x_0", 0.0 ), 
     664              28 :                      OSR_GDV( papszNV, "y_0", 0.0 ) );
     665                 :     }
     666                 : 
     667              84 :     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               4 :                       OSR_GDV( papszNV, "y_0", 0.0 ) );
     673                 :     }
     674                 : 
     675              80 :     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               4 :                  OSR_GDV( papszNV, "y_0", 0.0 ) );
     683                 :     }
     684                 : 
     685              76 :     else if( EQUAL(pszProj,"robin") )
     686                 :     {
     687                 :         SetRobinson( OSR_GDV( papszNV, "lon_0", 0.0 ), 
     688                 :                      OSR_GDV( papszNV, "x_0", 0.0 ), 
     689               2 :                      OSR_GDV( papszNV, "y_0", 0.0 ) );
     690                 :     }
     691                 : 
     692              74 :     else if( EQUAL(pszProj,"vandg") )
     693                 :     {
     694                 :         SetVDG( OSR_GDV( papszNV, "lon_0", 0.0 ), 
     695                 :                 OSR_GDV( papszNV, "x_0", 0.0 ), 
     696               8 :                 OSR_GDV( papszNV, "y_0", 0.0 ) );
     697                 :     }
     698                 : 
     699              66 :     else if( EQUAL(pszProj,"sinu") )
     700                 :     {
     701                 :         SetSinusoidal( OSR_GDV( papszNV, "lon_0", 0.0 ), 
     702                 :                        OSR_GDV( papszNV, "x_0", 0.0 ), 
     703               4 :                        OSR_GDV( papszNV, "y_0", 0.0 ) );
     704                 :     }
     705                 : 
     706              62 :     else if( EQUAL(pszProj,"gall") )
     707                 :     {
     708                 :         SetGS( OSR_GDV( papszNV, "lon_0", 0.0 ), 
     709                 :                OSR_GDV( papszNV, "x_0", 0.0 ), 
     710               4 :                OSR_GDV( papszNV, "y_0", 0.0 ) );
     711                 :     }
     712                 : 
     713              58 :     else if( EQUAL(pszProj,"goode") )
     714                 :     {
     715                 :         SetGH( OSR_GDV( papszNV, "lon_0", 0.0 ), 
     716                 :                OSR_GDV( papszNV, "x_0", 0.0 ), 
     717               2 :                OSR_GDV( papszNV, "y_0", 0.0 ) );
     718                 :     }
     719                 : 
     720              56 :     else if( EQUAL(pszProj,"igh") )
     721                 :     {
     722               2 :         SetIGH();
     723                 :     }
     724                 : 
     725              54 :     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               2 :                  OSR_GDV( papszNV, "y_0", 0.0 ) );
     731                 :     }
     732                 : 
     733              52 :     else if( EQUAL(pszProj,"lcc") ) 
     734                 :     {
     735              16 :         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              10 :                        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               6 :                     OSR_GDV( papszNV, "y_0", 0.0 ) );
     754                 :         }
     755                 :     }
     756                 : 
     757              36 :     else if( EQUAL(pszProj,"omerc") )
     758                 :     {
     759               4 :         if( CSLFetchNameValue(papszNV,"no_uoff") != NULL
     760                 :             || CSLFetchNameValue(papszNV,"no_off") != NULL )
     761                 :         {
     762                 :             SetHOM( OSR_GDV( papszNV, "lat_0", 0.0 ), 
     763                 :                     OSR_GDV( papszNV, "lonc", 0.0 ), 
     764                 :                     OSR_GDV( papszNV, "alpha", 0.0 ), 
     765                 :                     OSR_GDV( papszNV, "gamma", 0.0 ), 
     766                 :                     OSR_GDV( papszNV, "k", 1.0 ), 
     767                 :                     OSR_GDV( papszNV, "x_0", 0.0 ), 
     768               0 :                     OSR_GDV( papszNV, "y_0", 0.0 ) );
     769                 :         }
     770                 :         else
     771                 :         {
     772                 :             SetHOMAC( OSR_GDV( papszNV, "lat_0", 0.0 ), 
     773                 :                    OSR_GDV( papszNV, "lonc", 0.0 ), 
     774                 :                    OSR_GDV( papszNV, "alpha", 0.0 ), 
     775                 :                    OSR_GDV( papszNV, "gamma", 0.0 ), 
     776                 :                    OSR_GDV( papszNV, "k", 1.0 ), 
     777                 :                    OSR_GDV( papszNV, "x_0", 0.0 ), 
     778               4 :                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     779                 :         }
     780                 :     }
     781                 : 
     782              32 :     else if( EQUAL(pszProj,"somerc") )
     783                 :     {
     784                 :         SetHOMAC( OSR_GDV( papszNV, "lat_0", 0.0 ), 
     785                 :                   OSR_GDV( papszNV, "lon_0", 0.0 ), 
     786                 :                   90.0,  90.0, 
     787                 :                   OSR_GDV( papszNV, "k", 1.0 ), 
     788                 :                   OSR_GDV( papszNV, "x_0", 0.0 ), 
     789               6 :                   OSR_GDV( papszNV, "y_0", 0.0 ) );
     790                 :     }
     791                 : 
     792              26 :     else if( EQUAL(pszProj,"krovak") )
     793                 :     {
     794                 :         SetKrovak( OSR_GDV( papszNV, "lat_0", 0.0 ), 
     795                 :                    OSR_GDV( papszNV, "lon_0", 0.0 ), 
     796                 :                    OSR_GDV( papszNV, "alpha", 0.0 ), 
     797                 :                    0.0, // pseudo_standard_parallel_1
     798                 :                    OSR_GDV( papszNV, "k", 1.0 ), 
     799                 :                    OSR_GDV( papszNV, "x_0", 0.0 ), 
     800               4 :                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     801                 :     }
     802                 : 
     803              22 :     else if( EQUAL(pszProj, "iwm_p") )
     804                 :     {
     805                 :         SetIWMPolyconic( OSR_GDV( papszNV, "lat_1", 0.0 ), 
     806                 :                          OSR_GDV( papszNV, "lat_2", 0.0 ),
     807                 :                          OSR_GDV( papszNV, "lon_0", 0.0 ), 
     808                 :                          OSR_GDV( papszNV, "x_0", 0.0 ), 
     809               2 :                          OSR_GDV( papszNV, "y_0", 0.0 ) );
     810                 :     }
     811                 : 
     812              20 :     else if( EQUAL(pszProj, "wag1") )
     813                 :     {
     814                 :         SetWagner( 1, 0.0,
     815                 :                    OSR_GDV( papszNV, "x_0", 0.0 ), 
     816               2 :                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     817                 :     }
     818                 : 
     819              18 :     else if( EQUAL(pszProj, "wag2") )
     820                 :     {
     821                 :         SetWagner( 2, 0.0,
     822                 :                    OSR_GDV( papszNV, "x_0", 0.0 ), 
     823               2 :                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     824                 :     }
     825                 : 
     826              16 :     else if( EQUAL(pszProj, "wag3") )
     827                 :     {
     828                 :         SetWagner( 3,
     829                 :                    OSR_GDV( papszNV, "lat_ts", 0.0 ),
     830                 :                    OSR_GDV( papszNV, "x_0", 0.0 ), 
     831               2 :                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     832                 :     }
     833                 : 
     834              14 :     else if( EQUAL(pszProj, "wag4") )
     835                 :     {
     836                 :         SetWagner( 4, 0.0,
     837                 :                    OSR_GDV( papszNV, "x_0", 0.0 ), 
     838               2 :                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     839                 :     }
     840                 : 
     841              12 :     else if( EQUAL(pszProj, "wag5") )
     842                 :     {
     843                 :         SetWagner( 5, 0.0,
     844                 :                    OSR_GDV( papszNV, "x_0", 0.0 ), 
     845               2 :                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     846                 :     }
     847                 : 
     848              10 :     else if( EQUAL(pszProj, "wag6") )
     849                 :     {
     850                 :         SetWagner( 6, 0.0,
     851                 :                    OSR_GDV( papszNV, "x_0", 0.0 ), 
     852               2 :                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     853                 :     }
     854                 : 
     855               8 :     else if( EQUAL(pszProj, "wag7") )
     856                 :     {
     857                 :         SetWagner( 7, 0.0,
     858                 :                    OSR_GDV( papszNV, "x_0", 0.0 ), 
     859               2 :                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     860                 :     }
     861                 : 
     862               6 :     else if( EQUAL(pszProj,"tpeqd") )
     863                 :     {
     864                 :         SetTPED( OSR_GDV( papszNV, "lat_1", 0.0 ), 
     865                 :                  OSR_GDV( papszNV, "lon_1", 0.0 ), 
     866                 :                  OSR_GDV( papszNV, "lat_2", 0.0 ), 
     867                 :                  OSR_GDV( papszNV, "lon_2", 0.0 ), 
     868                 :                  OSR_GDV( papszNV, "x_0", 0.0 ), 
     869               4 :                  OSR_GDV( papszNV, "y_0", 0.0 ) );
     870                 :     }
     871                 : 
     872               2 :     else if( strstr(pszProj4,"wktext") != NULL )
     873                 :     {
     874                 :         // Fake out a projected coordinate system for otherwise 
     875                 :         // unrecognised projections for which we are already planning
     876                 :         // to embed the actual PROJ.4 string via extension node.
     877               0 :         SetProjection( "custom_proj4" );
     878                 :     }
     879                 : 
     880                 :     else
     881                 :     {
     882               2 :         CPLDebug( "OGR_PROJ4", "Unsupported projection: %s", pszProj );
     883               2 :         CSLDestroy( papszNV );
     884               2 :         return OGRERR_CORRUPT_DATA;
     885                 :     }
     886                 : 
     887                 : /* -------------------------------------------------------------------- */
     888                 : /*      Try to translate the datum.                                     */
     889                 : /* -------------------------------------------------------------------- */
     890                 :     const char *pszValue;
     891             262 :     int  bFullyDefined = FALSE;
     892                 : 
     893             262 :     pszValue = CSLFetchNameValue(papszNV, "datum");
     894             262 :     if( pszValue == NULL )
     895                 :     {
     896                 :         /* do nothing */
     897                 :     }
     898             110 :     else if( (EQUAL(pszValue,"NAD27") || EQUAL(pszValue,"NAD83")
     899                 :               || EQUAL(pszValue,"WGS84") || EQUAL(pszValue,"WGS72"))
     900                 :              && dfFromGreenwich == 0.0 )
     901                 :     {
     902              54 :         SetWellKnownGeogCS( pszValue );
     903              54 :         bFullyDefined = TRUE;
     904                 :     }
     905                 :     else
     906                 :     {
     907                 :         unsigned int i;
     908              16 :         for(i=0;i<sizeof(ogr_pj_datums)/sizeof(ogr_pj_datums[0]);i++)
     909                 :         {
     910              14 :             if ( EQUAL(pszValue, ogr_pj_datums[i].pszPJ) )
     911                 :             {
     912               0 :                 OGRSpatialReference oGCS;
     913               0 :                 oGCS.importFromEPSG( ogr_pj_datums[i].nEPSG );
     914               0 :                 CopyGeogCSFrom( &oGCS );
     915               0 :                 bFullyDefined = TRUE;
     916               0 :                 break;
     917                 :             }
     918                 :         }
     919                 : 
     920                 :         /* If we don't recognise the datum, we ignore it */
     921                 :     }
     922                 : 
     923                 : /* -------------------------------------------------------------------- */
     924                 : /*      Set the ellipsoid information.                                   */
     925                 : /* -------------------------------------------------------------------- */
     926                 :     double dfSemiMajor, dfInvFlattening, dfSemiMinor;
     927                 : 
     928             262 :     pszValue = CSLFetchNameValue(papszNV, "ellps");
     929             262 :     if( pszValue != NULL && !bFullyDefined )
     930                 :     {
     931           12756 :         for( i = 0; ogr_pj_ellps[i] != NULL; i += 4 )
     932                 :         {
     933            6378 :             if( !EQUAL(ogr_pj_ellps[i],pszValue) )
     934            6202 :                 continue;
     935                 : 
     936             176 :             CPLAssert( EQUALN(ogr_pj_ellps[i+1],"a=",2) );
     937                 :             
     938             176 :             dfSemiMajor = CPLAtof(ogr_pj_ellps[i+1]+2);
     939             176 :             if( EQUALN(ogr_pj_ellps[i+2],"rf=",3) )
     940             168 :                 dfInvFlattening = CPLAtof(ogr_pj_ellps[i+2]+3);
     941                 :             else
     942                 :             {
     943               8 :                 CPLAssert( EQUALN(ogr_pj_ellps[i+2],"b=",2) );
     944               8 :                 dfSemiMinor = CPLAtof(ogr_pj_ellps[i+2]+2);
     945                 :                 
     946               8 :                 if( ABS(dfSemiMajor/dfSemiMinor) - 1.0 < 0.0000000000001 )
     947               6 :                     dfInvFlattening = 0.0;
     948                 :                 else
     949               2 :                     dfInvFlattening = -1.0 / (dfSemiMinor/dfSemiMajor - 1.0);
     950                 :             }
     951                 :             
     952                 :             SetGeogCS( ogr_pj_ellps[i+3], "unknown", ogr_pj_ellps[i], 
     953                 :                        dfSemiMajor, dfInvFlattening,
     954             176 :                        pszPM, dfFromGreenwich );
     955                 : 
     956             176 :             bFullyDefined = TRUE;
     957             176 :             break;
     958                 :         }
     959                 :     }
     960                 : 
     961             262 :     if( !bFullyDefined )
     962                 :     {
     963              32 :         dfSemiMajor = OSR_GDV( papszNV, "a", 0.0 );
     964              32 :         if( dfSemiMajor == 0.0 )
     965                 :         {
     966               4 :             dfSemiMajor = OSR_GDV( papszNV, "R", 0.0 );
     967               4 :             if( dfSemiMajor != 0.0 )
     968                 :             {
     969               0 :                 dfSemiMinor = -1.0;
     970               0 :                 dfInvFlattening = 0.0;
     971                 :             }
     972                 :             else
     973                 :             {
     974                 :                 CPLDebug( "OGR_PROJ4", "Can't find ellipse definition, default to WGS84:\n%s", 
     975               4 :                           pszProj4 );
     976                 :                 
     977               4 :                 dfSemiMajor = SRS_WGS84_SEMIMAJOR;
     978               4 :                 dfSemiMinor = -1.0;
     979               4 :                 dfInvFlattening = SRS_WGS84_INVFLATTENING;
     980                 :             }
     981                 :         }
     982                 :         else
     983                 :         {
     984              28 :             dfSemiMinor = OSR_GDV( papszNV, "b", -1.0 );
     985              28 :             dfInvFlattening = OSR_GDV( papszNV, "rf", -1.0 );
     986              28 :             if ( dfSemiMinor == -1.0 && dfInvFlattening == -1.0 )
     987                 :             {
     988               2 :                 double dfFlattening = OSR_GDV( papszNV, "f", -1.0 );
     989               2 :                 if ( dfFlattening == 0.0 )
     990               0 :                     dfSemiMinor = dfSemiMajor;
     991               2 :                 else if ( dfFlattening != -1.0 )
     992               0 :                     dfInvFlattening = 1.0 / dfFlattening;
     993                 :             }
     994                 :         }
     995                 :         
     996              32 :         if( dfSemiMinor == -1.0 && dfInvFlattening == -1.0 )
     997                 :         {
     998                 :             CPLDebug( "OGR_PROJ4", "Can't find ellipse definition in:\n%s", 
     999               2 :                       pszProj4 );
    1000               2 :             CSLDestroy( papszNV );
    1001               2 :             return OGRERR_UNSUPPORTED_SRS;
    1002                 :         }
    1003                 : 
    1004              30 :         if( dfInvFlattening == -1.0 )
    1005                 :         {
    1006              20 :             if( ABS(dfSemiMajor/dfSemiMinor) - 1.0 < 0.0000000000001 )
    1007              12 :                 dfInvFlattening = 0.0;
    1008                 :             else
    1009               8 :                 dfInvFlattening = -1.0 / (dfSemiMinor/dfSemiMajor - 1.0);
    1010                 :         }
    1011                 :         
    1012                 :         SetGeogCS( "unnamed ellipse", "unknown", "unnamed",
    1013                 :                    dfSemiMajor, dfInvFlattening,
    1014              30 :                    pszPM, dfFromGreenwich );
    1015                 :         
    1016              30 :         bFullyDefined = TRUE;
    1017                 :     }
    1018                 : 
    1019                 : /* -------------------------------------------------------------------- */
    1020                 : /*      Handle TOWGS84 conversion.                                      */
    1021                 : /* -------------------------------------------------------------------- */
    1022             260 :     pszValue = CSLFetchNameValue(papszNV, "towgs84");
    1023             260 :     if(pszValue!=NULL)
    1024                 :     {
    1025                 :         char **papszToWGS84 = CSLTokenizeStringComplex( pszValue, ",", 
    1026              84 :                                                         FALSE, TRUE );
    1027                 : 
    1028              84 :         if( CSLCount(papszToWGS84) >= 7 )
    1029              36 :             SetTOWGS84( CPLAtof(papszToWGS84[0]), 
    1030              36 :                         CPLAtof(papszToWGS84[1]), 
    1031              36 :                         CPLAtof(papszToWGS84[2]), 
    1032              36 :                         CPLAtof(papszToWGS84[3]), 
    1033              36 :                         CPLAtof(papszToWGS84[4]), 
    1034              36 :                         CPLAtof(papszToWGS84[5]), 
    1035             252 :                         CPLAtof(papszToWGS84[6]) );
    1036              48 :         else if( CSLCount(papszToWGS84) >= 3 )
    1037              46 :             SetTOWGS84( CPLAtof(papszToWGS84[0]), 
    1038              46 :                         CPLAtof(papszToWGS84[1]), 
    1039             138 :                         CPLAtof(papszToWGS84[2]) );
    1040                 :         else
    1041                 :             CPLError( CE_Warning, CPLE_AppDefined, 
    1042                 :                       "Seemingly corrupt +towgs84 option (%s), ignoring.", 
    1043               2 :                       pszValue );
    1044                 :                         
    1045              84 :         CSLDestroy(papszToWGS84);
    1046                 :     }
    1047                 : 
    1048                 : /* -------------------------------------------------------------------- */
    1049                 : /*      Handle nadgrids via an extension node.                          */
    1050                 : /* -------------------------------------------------------------------- */
    1051             260 :     pszValue = CSLFetchNameValue(papszNV, "nadgrids");
    1052             260 :     if( pszValue != NULL )
    1053                 :     {
    1054               6 :         SetExtension( "DATUM", "PROJ4_GRIDS", pszValue );
    1055                 :     }
    1056                 : 
    1057                 : /* -------------------------------------------------------------------- */
    1058                 : /*      Linear units translation                                        */
    1059                 : /* -------------------------------------------------------------------- */
    1060             260 :     if( IsProjected() || IsLocal() || IsGeocentric() )
    1061                 :     {
    1062             236 :         pszValue = CSLFetchNameValue(papszNV, "to_meter");
    1063                 : 
    1064             236 :         if( pszValue != NULL && CPLAtofM(pszValue) > 0.0 )
    1065                 :         {
    1066               2 :             double dfValue = CPLAtofM(pszValue);
    1067                 : 
    1068               2 :             if( fabs(dfValue - CPLAtof(SRS_UL_US_FOOT_CONV)) < 0.00000001 )
    1069               0 :                 SetLinearUnits( SRS_UL_US_FOOT, CPLAtof(SRS_UL_US_FOOT_CONV) );
    1070               2 :             else if( fabs(dfValue - CPLAtof(SRS_UL_FOOT_CONV)) < 0.00000001 )
    1071               0 :                 SetLinearUnits( SRS_UL_FOOT, CPLAtof(SRS_UL_FOOT_CONV) );
    1072               2 :             else if( dfValue == 1.0 )
    1073               0 :                 SetLinearUnits( SRS_UL_METER, 1.0 );
    1074                 :             else
    1075               2 :                 SetLinearUnits( "unknown", CPLAtofM(pszValue) );
    1076                 :         }
    1077             234 :         else if( (pszValue = CSLFetchNameValue(papszNV, "units")) != NULL )
    1078                 :         {
    1079             194 :             if( EQUAL(pszValue,"meter" ) || EQUAL(pszValue,"m") )
    1080              92 :                 SetLinearUnits( SRS_UL_METER, 1.0 );
    1081              10 :             else if( EQUAL(pszValue,"us-ft" ) )
    1082               4 :                 SetLinearUnits( SRS_UL_US_FOOT, CPLAtof(SRS_UL_US_FOOT_CONV) );
    1083               6 :             else if( EQUAL(pszValue,"ft" ) )
    1084               2 :                 SetLinearUnits( SRS_UL_FOOT, CPLAtof(SRS_UL_FOOT_CONV) );
    1085               4 :             else if( EQUAL(pszValue,"yd" ) )
    1086               2 :                 SetLinearUnits( pszValue, 0.9144 );
    1087               2 :             else if( EQUAL(pszValue,"us-yd" ) )
    1088               2 :                 SetLinearUnits( pszValue, 0.914401828803658 );
    1089                 :             else // This case is untranslatable.  Should add all proj.4 unts
    1090               0 :                 SetLinearUnits( pszValue, 1.0 );
    1091                 :         }
    1092                 :     }
    1093                 : 
    1094                 : /* -------------------------------------------------------------------- */
    1095                 : /*      Adjust linear parameters into PROJCS units if the linear        */
    1096                 : /*      units are not meters.                                           */
    1097                 : /* -------------------------------------------------------------------- */
    1098             260 :     if( GetLinearUnits() != 1.0 && IsProjected() )
    1099                 :     {
    1100              12 :         OGR_SRSNode *poPROJCS = GetAttrNode( "PROJCS" );
    1101                 :         int  i;
    1102                 : 
    1103             120 :         for( i = 0; i < poPROJCS->GetChildCount(); i++ )
    1104                 :         {
    1105             108 :             OGR_SRSNode *poParm = poPROJCS->GetChild(i);
    1106             108 :             if( !EQUAL(poParm->GetValue(),"PARAMETER") 
    1107                 :                 || poParm->GetChildCount() != 2 )
    1108              48 :                 continue;
    1109                 : 
    1110              60 :             const char *pszParmName = poParm->GetChild(0)->GetValue();
    1111                 : 
    1112              60 :             if( IsLinearParameter(pszParmName) )
    1113              24 :                 SetNormProjParm(pszParmName,GetProjParm(pszParmName));
    1114                 :         }        
    1115                 :     }
    1116                 : 
    1117                 : /* -------------------------------------------------------------------- */
    1118                 : /*      Handle geoidgrids via an extension node and COMPD_CS.           */
    1119                 : /* -------------------------------------------------------------------- */
    1120             260 :     pszValue = CSLFetchNameValue(papszNV, "geoidgrids");
    1121             260 :     if( pszValue != NULL )
    1122                 :     {
    1123               2 :         OGR_SRSNode *poHorizSRS = GetRoot()->Clone();
    1124                 :         
    1125               2 :         Clear();
    1126                 :         
    1127               2 :         CPLString osName = poHorizSRS->GetChild(0)->GetValue();
    1128               2 :         osName += " + ";
    1129               2 :         osName += "Unnamed Vertical Datum";
    1130                 :         
    1131               2 :         SetNode( "COMPD_CS", osName );
    1132               2 :         GetRoot()->AddChild( poHorizSRS );
    1133                 : 
    1134                 :         OGR_SRSNode *poVertSRS;
    1135                 :         
    1136               2 :         poVertSRS = new OGR_SRSNode( "VERT_CS" );
    1137               4 :         GetRoot()->AddChild( poVertSRS );
    1138               2 :         poVertSRS->AddChild( new OGR_SRSNode( "Unnamed" ) );
    1139                 : 
    1140               2 :         CPLString osTarget = GetRoot()->GetValue();
    1141               2 :         osTarget += "|VERT_CS|VERT_DATUM";
    1142                 : 
    1143               2 :         SetNode( osTarget, "Unnamed" );
    1144                 :         
    1145               2 :         poVertSRS->GetChild(1)->AddChild( new OGR_SRSNode( "2005" ) );
    1146               2 :         SetExtension( osTarget, "PROJ4_GRIDS", pszValue );
    1147                 : 
    1148               2 :         OGR_SRSNode *poAxis = new OGR_SRSNode( "AXIS" );
    1149                 : 
    1150               4 :         poAxis->AddChild( new OGR_SRSNode( "Up" ) );
    1151               2 :         poAxis->AddChild( new OGR_SRSNode( "UP" ) );
    1152                 :         
    1153               2 :         poVertSRS->AddChild( poAxis );
    1154                 :     }
    1155                 : 
    1156                 : /* -------------------------------------------------------------------- */
    1157                 : /*      Handle vertical units.                                          */
    1158                 : /* -------------------------------------------------------------------- */
    1159             260 :     if( GetRoot()->GetNode( "VERT_CS" ) != NULL )
    1160                 :     {
    1161               2 :         const char *pszUnitName = NULL;
    1162               2 :         const char *pszUnitConv = NULL;
    1163                 : 
    1164               2 :         pszValue = CSLFetchNameValue(papszNV, "vto_meter");
    1165                 : 
    1166               2 :         if( pszValue != NULL && CPLAtofM(pszValue) > 0.0 )
    1167                 :         {
    1168               0 :             double dfValue = CPLAtofM(pszValue);
    1169                 : 
    1170               0 :             if( fabs(dfValue - CPLAtof(SRS_UL_US_FOOT_CONV)) < 0.00000001 )
    1171                 :             {
    1172               0 :                 pszUnitName = SRS_UL_US_FOOT;
    1173               0 :                 pszUnitConv = SRS_UL_US_FOOT_CONV;
    1174                 :             }
    1175               0 :             else if( fabs(dfValue - CPLAtof(SRS_UL_FOOT_CONV)) < 0.00000001 )
    1176                 :             {
    1177               0 :                 pszUnitName = SRS_UL_FOOT;
    1178               0 :                 pszUnitConv = SRS_UL_FOOT_CONV;
    1179                 :             }
    1180               0 :             else if( dfValue == 1.0 )
    1181                 :             {
    1182               0 :                 pszUnitName = SRS_UL_METER;
    1183               0 :                 pszUnitConv = "1.0";
    1184                 :             }
    1185                 :             else
    1186                 :             {
    1187               0 :                 pszUnitName = "unknown";
    1188               0 :                 pszUnitConv = pszValue;
    1189                 :             }
    1190                 :         }
    1191               2 :         else if( (pszValue = CSLFetchNameValue(papszNV, "vunits")) != NULL )
    1192                 :         {
    1193               2 :             if( EQUAL(pszValue,"meter" ) || EQUAL(pszValue,"m") )
    1194                 :             {
    1195               0 :                 pszUnitName = SRS_UL_METER;
    1196               0 :                 pszUnitConv = "1.0";
    1197                 :             }
    1198               2 :             else if( EQUAL(pszValue,"us-ft" ) )
    1199                 :             {
    1200               2 :                 pszUnitName = SRS_UL_US_FOOT;
    1201               2 :                 pszUnitConv = SRS_UL_US_FOOT_CONV;
    1202                 :             }
    1203               0 :             else if( EQUAL(pszValue,"ft" ) )
    1204                 :             {
    1205               0 :                 pszUnitName = SRS_UL_FOOT;
    1206               0 :                 pszUnitConv = SRS_UL_FOOT_CONV;
    1207                 :             }
    1208               0 :             else if( EQUAL(pszValue,"yd" ) )
    1209                 :             {
    1210               0 :                 pszUnitName = "Yard";
    1211               0 :                 pszUnitConv = "0.9144";
    1212                 :             }
    1213               0 :             else if( EQUAL(pszValue,"us-yd" ) )
    1214                 :             {
    1215               0 :                 pszUnitName = "US Yard";
    1216               0 :                 pszUnitConv = "0.914401828803658";
    1217                 :             }
    1218                 :         }
    1219                 : 
    1220               2 :         if( pszUnitName != NULL )
    1221                 :         {
    1222               2 :             OGR_SRSNode *poVERT_CS = GetRoot()->GetNode( "VERT_CS" );
    1223                 :             OGR_SRSNode *poUnits; 
    1224                 : 
    1225               2 :             poUnits = new OGR_SRSNode( "UNIT" );
    1226               4 :             poUnits->AddChild( new OGR_SRSNode( pszUnitName ) );
    1227               4 :             poUnits->AddChild( new OGR_SRSNode( pszUnitConv ) );
    1228                 :             
    1229               2 :             poVERT_CS->AddChild( poUnits );
    1230                 :         }
    1231                 :     }
    1232                 : 
    1233                 : /* -------------------------------------------------------------------- */
    1234                 : /*      do we want to insert a PROJ.4 EXTENSION item?                   */
    1235                 : /* -------------------------------------------------------------------- */
    1236             260 :     if( strstr(pszProj4,"wktext") != NULL )
    1237               0 :         SetExtension( GetRoot()->GetValue(), "PROJ4", pszProj4 );
    1238                 :         
    1239             260 :     CSLDestroy( papszNV );
    1240                 :     
    1241             260 :     return OGRERR_NONE;
    1242                 : }
    1243                 : 
    1244                 : /************************************************************************/
    1245                 : /*                           LinearToProj4()                            */
    1246                 : /************************************************************************/
    1247                 : 
    1248            1166 : static const char *LinearToProj4( double dfLinearConv, 
    1249                 :                                   const char *pszLinearUnits )
    1250                 : 
    1251                 : {
    1252            1166 :     if( dfLinearConv == 1.0 )
    1253            1148 :         return "m";
    1254                 : 
    1255              18 :     else if( dfLinearConv == 1000.0 )
    1256               0 :         return "km";
    1257                 :     
    1258              18 :     else if( dfLinearConv == 0.0254 )
    1259               0 :         return "in";
    1260                 :     
    1261              18 :     else if( EQUAL(pszLinearUnits,SRS_UL_FOOT) 
    1262                 :              || fabs(dfLinearConv - atof(SRS_UL_FOOT_CONV)) < 0.000000001 )
    1263               2 :         return "ft";
    1264                 :     
    1265              16 :     else if( EQUAL(pszLinearUnits,"IYARD") || dfLinearConv == 0.9144 )
    1266               2 :         return "yd";
    1267                 : 
    1268              14 :     else if( dfLinearConv == 0.914401828803658 )
    1269               2 :         return "us-yd";
    1270                 :     
    1271              12 :     else if( dfLinearConv == 0.001 )
    1272               0 :         return "mm";
    1273                 :     
    1274              12 :     else if( dfLinearConv == 0.01 )
    1275               0 :         return "cm";
    1276                 : 
    1277              12 :     else if( EQUAL(pszLinearUnits,SRS_UL_US_FOOT) 
    1278                 :              || fabs(dfLinearConv - atof(SRS_UL_US_FOOT_CONV)) < 0.00000001 )
    1279              10 :         return "us-ft";
    1280                 : 
    1281               2 :     else if( EQUAL(pszLinearUnits,SRS_UL_NAUTICAL_MILE) )
    1282               0 :         return "kmi";
    1283                 : 
    1284               2 :     else if( EQUAL(pszLinearUnits,"Mile") 
    1285                 :              || EQUAL(pszLinearUnits,"IMILE") )
    1286               0 :         return "mi";
    1287                 :     else
    1288               2 :         return NULL;
    1289                 : }
    1290                 : 
    1291                 : 
    1292                 : /************************************************************************/
    1293                 : /*                          OSRExportToProj4()                          */
    1294                 : /************************************************************************/
    1295                 : /** 
    1296                 :  * \brief Export coordinate system in PROJ.4 format.
    1297                 :  *
    1298                 :  * This function is the same as OGRSpatialReference::exportToProj4().
    1299                 :  */
    1300             246 : OGRErr CPL_STDCALL OSRExportToProj4( OGRSpatialReferenceH hSRS, 
    1301                 :                                      char ** ppszReturn )
    1302                 : 
    1303                 : {
    1304             246 :     VALIDATE_POINTER1( hSRS, "OSRExportToProj4", CE_Failure );
    1305                 : 
    1306             246 :     *ppszReturn = NULL;
    1307                 : 
    1308             246 :     return ((OGRSpatialReference *) hSRS)->exportToProj4( ppszReturn );
    1309                 : }
    1310                 : 
    1311                 : /************************************************************************/
    1312                 : /*                           exportToProj4()                            */
    1313                 : /************************************************************************/
    1314                 : 
    1315                 : #define SAFE_PROJ4_STRCAT(szNewStr)  do { \
    1316                 :     if(CPLStrlcat(szProj4, szNewStr, sizeof(szProj4)) >= sizeof(szProj4)) { \
    1317                 :         CPLError(CE_Failure, CPLE_AppDefined, "String overflow when formatting proj.4 string"); \
    1318                 :         *ppszProj4 = CPLStrdup(""); \
    1319                 :         return OGRERR_FAILURE; \
    1320                 :     } } while(0);
    1321                 : 
    1322                 : /**
    1323                 :  * \brief Export coordinate system in PROJ.4 format.
    1324                 :  *
    1325                 :  * Converts the loaded coordinate reference system into PROJ.4 format
    1326                 :  * to the extent possible.  The string returned in ppszProj4 should be
    1327                 :  * deallocated by the caller with CPLFree() when no longer needed.
    1328                 :  *
    1329                 :  * LOCAL_CS coordinate systems are not translatable.  An empty string
    1330                 :  * will be returned along with OGRERR_NONE.  
    1331                 :  *
    1332                 :  * This method is the equivelent of the C function OSRExportToProj4().
    1333                 :  *
    1334                 :  * @param ppszProj4 pointer to which dynamically allocated PROJ.4 definition 
    1335                 :  * will be assigned. 
    1336                 :  *
    1337                 :  * @return OGRERR_NONE on success or an error code on failure. 
    1338                 :  */
    1339                 : 
    1340            2366 : OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
    1341                 : 
    1342                 : {
    1343                 :     char        szProj4[512];
    1344            2366 :     const char *pszProjection = GetAttrValue("PROJECTION");
    1345            2366 :     CPLLocaleC  oLocaleEnforcer;
    1346                 : 
    1347            2366 :     szProj4[0] = '\0';
    1348                 : 
    1349            2366 :     if( GetRoot() == NULL )
    1350                 :     {
    1351               2 :         *ppszProj4 = CPLStrdup("");
    1352                 :         CPLError( CE_Failure, CPLE_NotSupported,
    1353               2 :                   "No translation an empty SRS to PROJ.4 format is known.");
    1354               2 :         return OGRERR_UNSUPPORTED_SRS;
    1355                 :     }
    1356                 : 
    1357                 : /* -------------------------------------------------------------------- */
    1358                 : /*      Do we have a PROJ.4 override definition?                        */
    1359                 : /* -------------------------------------------------------------------- */
    1360                 :     const char *pszPredefProj4 = GetExtension( GetRoot()->GetValue(), 
    1361            2364 :                                                "PROJ4", NULL );
    1362            2364 :     if( pszPredefProj4 != NULL )
    1363                 :     {
    1364              32 :         *ppszProj4 = CPLStrdup( pszPredefProj4 );
    1365              32 :         return OGRERR_NONE;
    1366                 :     }
    1367                 : 
    1368                 : /* -------------------------------------------------------------------- */
    1369                 : /*      Get the prime meridian info.                                    */
    1370                 : /* -------------------------------------------------------------------- */
    1371            2332 :     const OGR_SRSNode *poPRIMEM = GetAttrNode( "PRIMEM" );
    1372            2332 :     double dfFromGreenwich = 0.0;
    1373                 : 
    1374            2332 :     if( poPRIMEM != NULL && poPRIMEM->GetChildCount() >= 2 
    1375                 :         && CPLAtof(poPRIMEM->GetChild(1)->GetValue()) != 0.0 )
    1376                 :     {
    1377              16 :         dfFromGreenwich = CPLAtof(poPRIMEM->GetChild(1)->GetValue());
    1378                 :     }
    1379                 : 
    1380                 : /* ==================================================================== */
    1381                 : /*      Handle the projection definition.                               */
    1382                 : /* ==================================================================== */
    1383                 : 
    1384            2332 :     if( pszProjection == NULL && IsGeographic() )
    1385                 :     {
    1386            1170 :         sprintf( szProj4+strlen(szProj4), "+proj=longlat " );
    1387                 :     }
    1388            1162 :     else if( IsGeocentric() )
    1389                 :     {
    1390               6 :         sprintf( szProj4+strlen(szProj4), "+proj=geocent " );
    1391                 :     }
    1392                 : 
    1393            1156 :     else if( pszProjection == NULL && !IsGeographic() )
    1394                 :     {
    1395                 :         // LOCAL_CS, or incompletely initialized coordinate systems.
    1396               0 :         *ppszProj4 = CPLStrdup("");
    1397               0 :         return OGRERR_NONE;
    1398                 :     }
    1399            1156 :     else if( EQUAL(pszProjection,SRS_PT_CYLINDRICAL_EQUAL_AREA) )
    1400                 :     {
    1401                 :         sprintf( szProj4+strlen(szProj4),
    1402                 :                  "+proj=cea +lon_0=%.16g +lat_ts=%.16g +x_0=%.16g +y_0=%.16g ",
    1403                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1404                 :                  GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0),
    1405                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1406              12 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1407                 :     }
    1408                 : 
    1409            1144 :     else if( EQUAL(pszProjection,SRS_PT_BONNE) )
    1410                 :     {
    1411                 :         sprintf( szProj4+strlen(szProj4),
    1412                 :                  "+proj=bonne +lon_0=%.16g +lat_1=%.16g +x_0=%.16g +y_0=%.16g ",
    1413                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1414                 :                  GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0),
    1415                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1416               6 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1417                 :     }
    1418                 : 
    1419            1138 :     else if( EQUAL(pszProjection,SRS_PT_CASSINI_SOLDNER) )
    1420                 :     {
    1421                 :         sprintf( szProj4+strlen(szProj4),
    1422                 :                  "+proj=cass +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1423                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1424                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1425                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1426               4 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1427                 :     }
    1428                 : 
    1429            1134 :     else if( EQUAL(pszProjection,SRS_PT_NEW_ZEALAND_MAP_GRID) )
    1430                 :     {
    1431                 :         sprintf( szProj4+strlen(szProj4),
    1432                 :                  "+proj=nzmg +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1433                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1434                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1435                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1436               4 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1437                 :     }
    1438                 : 
    1439            1920 :     else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR) ||
    1440                 :              EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_MI_21) ||
    1441                 :              EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_MI_22) ||
    1442                 :              EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_MI_23) ||
    1443                 :              EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_MI_24) ||
    1444                 :              EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_MI_25) )
    1445                 :     {
    1446                 :         int bNorth;
    1447             790 :         int nZone = GetUTMZone( &bNorth );
    1448                 : 
    1449             790 :         if( nZone != 0 )
    1450                 :         {
    1451             766 :             if( bNorth )
    1452                 :                 sprintf( szProj4+strlen(szProj4), "+proj=utm +zone=%d ", 
    1453             752 :                          nZone );
    1454                 :             else
    1455                 :                 sprintf( szProj4+strlen(szProj4),"+proj=utm +zone=%d +south ", 
    1456              14 :                          nZone );
    1457                 :         }            
    1458                 :         else
    1459                 :             sprintf( szProj4+strlen(szProj4),
    1460                 :                      "+proj=tmerc +lat_0=%.16g +lon_0=%.16g +k=%.16g +x_0=%.16g +y_0=%.16g ",
    1461                 :                      GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    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              24 :                      GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1466                 :     }
    1467                 : 
    1468             340 :     else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED) )
    1469                 :     {
    1470                 :         sprintf( szProj4+strlen(szProj4),
    1471                 :                  "+proj=tmerc +lat_0=%.16g +lon_0=%.16g +k=%.16g +x_0=%.16g +y_0=%.16g +axis=wsu ",
    1472                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1473                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1474                 :                  GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
    1475                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1476               2 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1477                 :     }
    1478                 : 
    1479             338 :     else if( EQUAL(pszProjection,SRS_PT_MERCATOR_1SP) )
    1480                 :     {
    1481              18 :         if( GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0) == 0.0 )
    1482                 :             sprintf( szProj4+strlen(szProj4),
    1483                 :                      "+proj=merc +lon_0=%.16g +k=%.16g +x_0=%.16g +y_0=%.16g ",
    1484                 :                      GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1485                 :                      GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
    1486                 :                      GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1487              12 :                      GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1488               6 :         else if( GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0) == 1.0 )
    1489                 :             sprintf( szProj4+strlen(szProj4),
    1490                 :                      "+proj=merc +lon_0=%.16g +lat_ts=%.16g +x_0=%.16g +y_0=%.16g ",
    1491                 :                      GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1492                 :                      GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1493                 :                      GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1494               6 :                      GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1495                 :         else
    1496                 :         {
    1497                 :             CPLError( CE_Failure, CPLE_NotSupported,
    1498               0 :                       "Mercator_1SP with scale != 1.0 and latitude of origin != 0, not supported by PROJ.4." );
    1499               0 :             *ppszProj4 = CPLStrdup("");
    1500               0 :             return OGRERR_UNSUPPORTED_SRS;
    1501                 :         }
    1502                 :     }
    1503                 : 
    1504             320 :     else if( EQUAL(pszProjection,SRS_PT_MERCATOR_2SP) )
    1505                 :     {
    1506                 :         sprintf( szProj4+strlen(szProj4),
    1507                 :                  "+proj=merc +lon_0=%.16g +lat_ts=%.16g +x_0=%.16g +y_0=%.16g ",
    1508                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1509                 :                  GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0),
    1510                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1511              20 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1512                 :     }
    1513                 : 
    1514             300 :     else if( EQUAL(pszProjection,SRS_PT_OBLIQUE_STEREOGRAPHIC) )
    1515                 :     {
    1516                 :         sprintf( szProj4+strlen(szProj4),
    1517                 :                  "+proj=sterea +lat_0=%.16g +lon_0=%.16g +k=%.16g +x_0=%.16g +y_0=%.16g ",
    1518                 : //         "+proj=stere +lat_0=%.16g +lon_0=%.16g +k=%.16g +x_0=%.16g +y_0=%.16g ",
    1519                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1520                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1521                 :                  GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
    1522                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1523              20 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1524                 :     }
    1525                 : 
    1526             280 :     else if( EQUAL(pszProjection,SRS_PT_STEREOGRAPHIC) )
    1527                 :     {
    1528                 :         sprintf( szProj4+strlen(szProj4),
    1529                 :                  "+proj=stere +lat_0=%.16g +lon_0=%.16g +k=%.16g +x_0=%.16g +y_0=%.16g ",
    1530                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.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              16 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1535                 :     }
    1536                 : 
    1537             264 :     else if( EQUAL(pszProjection,SRS_PT_POLAR_STEREOGRAPHIC) )
    1538                 :     {
    1539              24 :         if( GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0) >= 0.0 )
    1540                 :             sprintf( szProj4+strlen(szProj4),
    1541                 :                      "+proj=stere +lat_0=90 +lat_ts=%.16g +lon_0=%.16g "
    1542                 :                      "+k=%.16g +x_0=%.16g +y_0=%.16g ",
    1543                 :                      GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,90.0),
    1544                 :                      GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1545                 :                      GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
    1546                 :                      GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1547              12 :                      GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1548                 :         else
    1549                 :             sprintf( szProj4+strlen(szProj4),
    1550                 :                      "+proj=stere +lat_0=-90 +lat_ts=%.16g +lon_0=%.16g "
    1551                 :                      "+k=%.16g +x_0=%.16g +y_0=%.16g ",
    1552                 :                      GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,-90.0),
    1553                 :                      GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1554                 :                      GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
    1555                 :                      GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1556              12 :                      GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1557                 :     }
    1558                 : 
    1559             240 :     else if( EQUAL(pszProjection,SRS_PT_EQUIRECTANGULAR) )
    1560                 :     {
    1561                 :         sprintf( szProj4+strlen(szProj4),
    1562                 :                  "+proj=eqc +lat_ts=%.16g +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1563                 :                  GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0),
    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               8 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1568                 :     }
    1569                 : 
    1570             232 :     else if( EQUAL(pszProjection,SRS_PT_GAUSSSCHREIBERTMERCATOR) )
    1571                 :     {
    1572                 :         sprintf( szProj4+strlen(szProj4),
    1573                 :                  "+proj=gstmerc +lat_0=%.16g +lon_0=%.16g"
    1574                 :                  " +k_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1575                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,-21.116666667),
    1576                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,55.53333333309),
    1577                 :                  GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
    1578                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,160000.000),
    1579               2 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,50000.000) );
    1580                 :     }
    1581                 : 
    1582             230 :     else if( EQUAL(pszProjection,SRS_PT_GNOMONIC) )
    1583                 :     {
    1584                 :         sprintf( szProj4+strlen(szProj4),
    1585                 :                  "+proj=gnom +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1586                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1587                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1588                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1589               2 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1590                 :     }
    1591                 : 
    1592             228 :     else if( EQUAL(pszProjection,SRS_PT_ORTHOGRAPHIC) )
    1593                 :     {
    1594                 :         sprintf( szProj4+strlen(szProj4),
    1595                 :                  "+proj=ortho +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1596                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1597                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1598                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1599              18 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1600                 :     }
    1601                 : 
    1602             210 :     else if( EQUAL(pszProjection,SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) )
    1603                 :     {
    1604                 :         sprintf( szProj4+strlen(szProj4),
    1605                 :                  "+proj=laea +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1606                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1607                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1608                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1609              12 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1610                 :     }
    1611                 : 
    1612             198 :     else if( EQUAL(pszProjection,SRS_PT_AZIMUTHAL_EQUIDISTANT) )
    1613                 :     {
    1614                 :         sprintf( szProj4+strlen(szProj4),
    1615                 :                  "+proj=aeqd +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1616                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1617                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1618                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1619              26 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1620                 :     }
    1621                 : 
    1622             172 :     else if( EQUAL(pszProjection,SRS_PT_EQUIDISTANT_CONIC) )
    1623                 :     {
    1624                 :         sprintf( szProj4+strlen(szProj4),
    1625                 :                  "+proj=eqdc +lat_0=%.16g +lon_0=%.16g +lat_1=%.16g +lat_2=%.16g"
    1626                 :                  " +x_0=%.16g +y_0=%.16g ",
    1627                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_CENTER,0.0),
    1628                 :                  GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0),
    1629                 :                  GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0),
    1630                 :                  GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2,0.0),
    1631                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1632               2 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1633                 :     }
    1634                 : 
    1635             170 :     else if( EQUAL(pszProjection,SRS_PT_MILLER_CYLINDRICAL) )
    1636                 :     {
    1637                 :         sprintf( szProj4+strlen(szProj4),
    1638                 :                  "+proj=mill +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g +R_A ",
    1639                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1640                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1641                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1642               2 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1643                 :     }
    1644                 : 
    1645             168 :     else if( EQUAL(pszProjection,SRS_PT_MOLLWEIDE) )
    1646                 :     {
    1647                 :         sprintf( szProj4+strlen(szProj4),
    1648                 :                  "+proj=moll +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1649                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1650                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1651               2 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1652                 :     }
    1653                 : 
    1654             166 :     else if( EQUAL(pszProjection,SRS_PT_ECKERT_I) )
    1655                 :     {
    1656                 :         sprintf( szProj4+strlen(szProj4),
    1657                 :                  "+proj=eck1 +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1658                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1659                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1660               2 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1661                 :     }
    1662                 : 
    1663             164 :     else if( EQUAL(pszProjection,SRS_PT_ECKERT_II) )
    1664                 :     {
    1665                 :         sprintf( szProj4+strlen(szProj4),
    1666                 :                  "+proj=eck2 +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1667                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1668                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1669               2 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1670                 :     }
    1671                 : 
    1672             162 :     else if( EQUAL(pszProjection,SRS_PT_ECKERT_III) )
    1673                 :     {
    1674                 :         sprintf( szProj4+strlen(szProj4),
    1675                 :                  "+proj=eck3 +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1676                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1677                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1678               2 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1679                 :     }
    1680                 :     
    1681             160 :     else if( EQUAL(pszProjection,SRS_PT_ECKERT_IV) )
    1682                 :     {
    1683                 :         sprintf( szProj4+strlen(szProj4),
    1684                 :                  "+proj=eck4 +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1685                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1686                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1687              14 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1688                 :     }
    1689                 :     
    1690             146 :     else if( EQUAL(pszProjection,SRS_PT_ECKERT_V) )
    1691                 :     {
    1692                 :         sprintf( szProj4+strlen(szProj4),
    1693                 :                  "+proj=eck5 +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1694                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1695                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1696               2 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1697                 :     }
    1698                 :     
    1699             144 :     else if( EQUAL(pszProjection,SRS_PT_ECKERT_VI) )
    1700                 :     {
    1701                 :         sprintf( szProj4+strlen(szProj4),
    1702                 :                  "+proj=eck6 +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1703                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1704                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1705               2 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1706                 :     }
    1707                 : 
    1708             142 :     else if( EQUAL(pszProjection,SRS_PT_POLYCONIC) )
    1709                 :     {
    1710                 :         sprintf( szProj4+strlen(szProj4),
    1711                 :                  "+proj=poly +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1712                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1713                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1714                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1715               4 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1716                 :     }
    1717                 : 
    1718             138 :     else if( EQUAL(pszProjection,SRS_PT_ALBERS_CONIC_EQUAL_AREA) )
    1719                 :     {
    1720                 :         sprintf( szProj4+strlen(szProj4),
    1721                 :                  "+proj=aea +lat_1=%.16g +lat_2=%.16g +lat_0=%.16g +lon_0=%.16g"
    1722                 :                  " +x_0=%.16g +y_0=%.16g ",
    1723                 :                  GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0),
    1724                 :                  GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2,0.0),
    1725                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1726                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1727                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1728              12 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1729                 :     }
    1730                 : 
    1731             126 :     else if( EQUAL(pszProjection,SRS_PT_ROBINSON) )
    1732                 :     {
    1733                 :         sprintf( szProj4+strlen(szProj4),
    1734                 :                  "+proj=robin +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1735                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1736                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1737               2 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1738                 :     }
    1739                 : 
    1740             124 :     else if( EQUAL(pszProjection,SRS_PT_VANDERGRINTEN) )
    1741                 :     {
    1742                 :         sprintf( szProj4+strlen(szProj4),
    1743                 :                  "+proj=vandg +lon_0=%.16g +x_0=%.16g +y_0=%.16g +R_A ",
    1744                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1745                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1746              18 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1747                 :     }
    1748                 : 
    1749             106 :     else if( EQUAL(pszProjection,SRS_PT_SINUSOIDAL) )
    1750                 :     {
    1751                 :         sprintf( szProj4+strlen(szProj4),
    1752                 :                  "+proj=sinu +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1753                 :                  GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0),
    1754                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1755              14 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1756                 :     }
    1757                 : 
    1758              92 :     else if( EQUAL(pszProjection,SRS_PT_GALL_STEREOGRAPHIC) )
    1759                 :     {
    1760                 :         sprintf( szProj4+strlen(szProj4),
    1761                 :                  "+proj=gall +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1762                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1763                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1764               4 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1765                 :     }
    1766                 : 
    1767              88 :     else if( EQUAL(pszProjection,SRS_PT_GOODE_HOMOLOSINE) )
    1768                 :     {
    1769                 :         sprintf( szProj4+strlen(szProj4),
    1770                 :                  "+proj=goode +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1771                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1772                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1773               2 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1774                 :     }
    1775                 : 
    1776              86 :     else if( EQUAL(pszProjection,SRS_PT_IGH) )
    1777                 :     {
    1778               2 :         sprintf( szProj4+strlen(szProj4), "+proj=igh " );
    1779                 :     }
    1780                 : 
    1781              84 :     else if( EQUAL(pszProjection,SRS_PT_GEOSTATIONARY_SATELLITE) )
    1782                 :     {
    1783                 :         sprintf( szProj4+strlen(szProj4),
    1784                 :                  "+proj=geos +lon_0=%.16g +h=%.16g +x_0=%.16g +y_0=%.16g ",
    1785                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1786                 :                  GetNormProjParm(SRS_PP_SATELLITE_HEIGHT,35785831.0),
    1787                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1788               2 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1789                 :     }
    1790                 : 
    1791             116 :     else if( EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP)
    1792                 :              || EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM) )
    1793                 :     {
    1794                 :         sprintf( szProj4+strlen(szProj4),
    1795                 :                  "+proj=lcc +lat_1=%.16g +lat_2=%.16g +lat_0=%.16g +lon_0=%.16g"
    1796                 :                  " +x_0=%.16g +y_0=%.16g ",
    1797                 :                  GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0),
    1798                 :                  GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2,0.0),
    1799                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1800                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1801                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1802              34 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1803                 :     }
    1804                 :     
    1805              48 :     else if( EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP) )
    1806                 :     {
    1807                 :         sprintf( szProj4+strlen(szProj4),
    1808                 :                  "+proj=lcc +lat_1=%.16g +lat_0=%.16g +lon_0=%.16g"
    1809                 :                  " +k_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1810                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1811                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1812                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1813                 :                  GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
    1814                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1815              10 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1816                 :     }
    1817                 : 
    1818              38 :     else if( EQUAL(pszProjection,SRS_PT_HOTINE_OBLIQUE_MERCATOR) )
    1819                 :     {
    1820                 :         /* special case for swiss oblique mercator : see bug 423 */
    1821               0 :         if( fabs(GetNormProjParm(SRS_PP_AZIMUTH,0.0) - 90.0) < 0.0001 
    1822                 :             && fabs(GetNormProjParm(SRS_PP_RECTIFIED_GRID_ANGLE,0.0)-90.0) < 0.0001 )
    1823                 :         {
    1824                 :             sprintf( szProj4+strlen(szProj4),
    1825                 :                      "+proj=somerc +lat_0=%.16g +lon_0=%.16g"
    1826                 :                      " +k_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1827                 :                      GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1828                 :                      GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1829                 :                      GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
    1830                 :                      GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1831               0 :                      GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1832                 :         }
    1833                 :         else
    1834                 :         {
    1835                 :             sprintf( szProj4+strlen(szProj4),
    1836                 :                      "+proj=omerc +lat_0=%.16g +lonc=%.16g +alpha=%.16g"
    1837                 :                      " +k=%.16g +x_0=%.16g +y_0=%.16g +no_uoff ",
    1838                 :                      GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1839                 :                      GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1840                 :                      GetNormProjParm(SRS_PP_AZIMUTH,0.0),
    1841                 :                      GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
    1842                 :                      GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1843               0 :                      GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1844                 : 
    1845                 :             // RSO variant - http://trac.osgeo.org/proj/ticket/62
    1846                 :             // Note that gamma is only supported by PROJ 4.8.0 and later.
    1847               0 :             if( GetNormProjParm(SRS_PP_RECTIFIED_GRID_ANGLE,1000.0) != 1000.0 )
    1848                 :             {
    1849                 :                 sprintf( szProj4+strlen(szProj4), "+gamma=%.16g ",
    1850               0 :                          GetNormProjParm(SRS_PP_RECTIFIED_GRID_ANGLE,1000.0));
    1851                 :             }
    1852                 :         }
    1853                 :     }
    1854                 : 
    1855              38 :     else if( EQUAL(pszProjection,SRS_PT_HOTINE_OBLIQUE_MERCATOR_AZIMUTH_CENTER))
    1856                 :     {
    1857                 :         /* special case for swiss oblique mercator : see bug 423 */
    1858              10 :         if( fabs(GetNormProjParm(SRS_PP_AZIMUTH,0.0) - 90.0) < 0.0001 
    1859                 :             && fabs(GetNormProjParm(SRS_PP_RECTIFIED_GRID_ANGLE,0.0)-90.0) < 0.0001 )
    1860                 :         {
    1861                 :             sprintf( szProj4+strlen(szProj4),
    1862                 :                      "+proj=somerc +lat_0=%.16g +lon_0=%.16g"
    1863                 :                      " +k_0=%.16g +x_0=%.16g +y_0=%.16g ",
    1864                 :                      GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1865                 :                      GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1866                 :                      GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
    1867                 :                      GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1868               6 :                      GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1869                 :         }
    1870                 :         else
    1871                 :         {
    1872                 :             sprintf( szProj4+strlen(szProj4),
    1873                 :                      "+proj=omerc +lat_0=%.16g +lonc=%.16g +alpha=%.16g"
    1874                 :                      " +k=%.16g +x_0=%.16g +y_0=%.16g ",
    1875                 :                      GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1876                 :                      GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    1877                 :                      GetNormProjParm(SRS_PP_AZIMUTH,0.0),
    1878                 :                      GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
    1879                 :                      GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1880               4 :                      GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1881                 : 
    1882                 :             // RSO variant - http://trac.osgeo.org/proj/ticket/62
    1883                 :             // Note that gamma is only supported by PROJ 4.8.0 and later.
    1884               4 :             if( GetNormProjParm(SRS_PP_RECTIFIED_GRID_ANGLE,1000.0) != 1000.0 )
    1885                 :             {
    1886                 :                 sprintf( szProj4+strlen(szProj4), "+gamma=%.16g ",
    1887               4 :                          GetNormProjParm(SRS_PP_RECTIFIED_GRID_ANGLE,1000.0));
    1888                 :             }
    1889                 :         }
    1890                 :     }
    1891                 : 
    1892              28 :     else if( EQUAL(pszProjection,
    1893                 :                    SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN) )
    1894                 :     {
    1895                 :         sprintf( szProj4+strlen(szProj4),
    1896                 :                  "+proj=omerc +lat_0=%.16g"
    1897                 :                  " +lon_1=%.16g +lat_1=%.16g +lon_2=%.16g +lat_2=%.16g"
    1898                 :                  " +k=%.16g +x_0=%.16g +y_0=%.16g ",
    1899                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    1900                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_POINT_1,0.0),
    1901                 :                  GetNormProjParm(SRS_PP_LONGITUDE_OF_POINT_1,0.0),
    1902                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_POINT_2,0.0),
    1903                 :                  GetNormProjParm(SRS_PP_LONGITUDE_OF_POINT_2,0.0),
    1904                 :                  GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
    1905                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1906               0 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1907                 :     }
    1908                 : 
    1909              28 :     else if( EQUAL(pszProjection,SRS_PT_KROVAK) )
    1910                 :     {
    1911                 :         sprintf( szProj4+strlen(szProj4),
    1912                 :                  "+proj=krovak +lat_0=%.16g +lon_0=%.16g +alpha=%.16g"
    1913                 :                  " +k=%.16g +x_0=%.16g +y_0=%.16g ",
    1914                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_CENTER,0.0),
    1915                 :                  GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0),
    1916                 :                  GetNormProjParm(SRS_PP_AZIMUTH,0.0),
    1917                 :                  GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
    1918                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1919               4 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1920                 :     }
    1921                 : 
    1922              24 :     else if( EQUAL(pszProjection,SRS_PT_TWO_POINT_EQUIDISTANT) )
    1923                 :     {
    1924                 :         sprintf( szProj4+strlen(szProj4),
    1925                 :                  "+proj=tpeqd +lat_1=%.16g +lon_1=%.16g "
    1926                 :                  "+lat_2=%.16g +lon_2=%.16g "
    1927                 :                  "+x_0=%.16g +y_0=%.16g ",
    1928                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_1ST_POINT,0.0),
    1929                 :                  GetNormProjParm(SRS_PP_LONGITUDE_OF_1ST_POINT,0.0),
    1930                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_2ND_POINT,0.0),
    1931                 :                  GetNormProjParm(SRS_PP_LONGITUDE_OF_2ND_POINT,0.0),
    1932                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    1933               6 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    1934                 :     }
    1935                 : 
    1936              18 :     else if( EQUAL(pszProjection, SRS_PT_IMW_POLYCONIC) )
    1937                 :     {
    1938                 :         sprintf( szProj4+strlen(szProj4),
    1939                 :                  "+proj=iwm_p +lat_1=%.16g +lat_2=%.16g +lon_0=%.16g "
    1940                 :                  "+x_0=%.16g +y_0=%.16g ",
    1941                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_1ST_POINT, 0.0),
    1942                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_2ND_POINT, 0.0),
    1943                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
    1944                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
    1945               2 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
    1946                 :     }
    1947                 : 
    1948              16 :     else if( EQUAL(pszProjection, SRS_PT_WAGNER_I) )
    1949                 :     {
    1950                 :         sprintf( szProj4+strlen(szProj4),
    1951                 :                  "+proj=wag1 +x_0=%.16g +y_0=%.16g ",
    1952                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
    1953               2 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
    1954                 :     }
    1955                 : 
    1956              14 :     else if( EQUAL(pszProjection, SRS_PT_WAGNER_II) )
    1957                 :     {
    1958                 :         sprintf( szProj4+strlen(szProj4),
    1959                 :                  "+proj=wag2 +x_0=%.16g +y_0=%.16g ",
    1960                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
    1961               2 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
    1962                 :     }
    1963                 : 
    1964              12 :     else if( EQUAL(pszProjection, SRS_PT_WAGNER_III) )
    1965                 :     {
    1966                 :         sprintf( szProj4+strlen(szProj4),
    1967                 :                  "+proj=wag3 +lat_ts=%.16g +x_0=%.16g +y_0=%.16g ",
    1968                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
    1969                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
    1970               2 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
    1971                 :     }
    1972                 : 
    1973              10 :     else if( EQUAL(pszProjection, SRS_PT_WAGNER_IV) )
    1974                 :     {
    1975                 :         sprintf( szProj4+strlen(szProj4),
    1976                 :                  "+proj=wag4 +x_0=%.16g +y_0=%.16g ",
    1977                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
    1978               2 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
    1979                 :     }
    1980                 : 
    1981               8 :     else if( EQUAL(pszProjection, SRS_PT_WAGNER_V) )
    1982                 :     {
    1983                 :         sprintf( szProj4+strlen(szProj4),
    1984                 :                  "+proj=wag5 +x_0=%.16g +y_0=%.16g ",
    1985                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
    1986               2 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
    1987                 :     }
    1988                 : 
    1989               6 :     else if( EQUAL(pszProjection, SRS_PT_WAGNER_VI) )
    1990                 :     {
    1991                 :         sprintf( szProj4+strlen(szProj4),
    1992                 :                  "+proj=wag6 +x_0=%.16g +y_0=%.16g ",
    1993                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
    1994               2 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
    1995                 :     }
    1996                 : 
    1997               4 :     else if( EQUAL(pszProjection, SRS_PT_WAGNER_VII) )
    1998                 :     {
    1999                 :         sprintf( szProj4+strlen(szProj4),
    2000                 :                  "+proj=wag7 +x_0=%.16g +y_0=%.16g ",
    2001                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
    2002               2 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
    2003                 :     }
    2004                 : 
    2005                 :     /* Note: This never really gets used currently.  See bug 423 */
    2006               2 :     else if( EQUAL(pszProjection,SRS_PT_SWISS_OBLIQUE_CYLINDRICAL) )
    2007                 :     {
    2008                 :         sprintf( szProj4+strlen(szProj4),
    2009                 :                  "+proj=somerc +lat_0=%.16g +lon_0=%.16g"
    2010                 :                  " +x_0=%.16g +y_0=%.16g ",
    2011                 :                  GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
    2012                 :                  GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
    2013                 :                  GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
    2014               0 :                  GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
    2015                 :     }
    2016                 : 
    2017                 :     else
    2018                 :     {
    2019                 :         CPLError( CE_Failure, CPLE_NotSupported,
    2020                 :                   "No translation for %s to PROJ.4 format is known.", 
    2021               2 :                   pszProjection );
    2022               2 :         *ppszProj4 = CPLStrdup("");
    2023               2 :         return OGRERR_UNSUPPORTED_SRS;
    2024                 :     }
    2025                 : 
    2026                 : /* -------------------------------------------------------------------- */
    2027                 : /*      Handle earth model.  For now we just always emit the user       */
    2028                 : /*      defined ellipsoid parameters.                                   */
    2029                 : /* -------------------------------------------------------------------- */
    2030            2330 :     double      dfSemiMajor = GetSemiMajor();
    2031            2330 :     double      dfInvFlattening = GetInvFlattening();
    2032            2330 :     const char  *pszPROJ4Ellipse = NULL;
    2033            2330 :     const char  *pszDatum = GetAttrValue("DATUM");
    2034                 : 
    2035            2330 :     if( ABS(dfSemiMajor-6378249.145) < 0.01
    2036                 :         && ABS(dfInvFlattening-293.465) < 0.0001 )
    2037                 :     {
    2038               0 :         pszPROJ4Ellipse = "clrk80";     /* Clark 1880 */
    2039                 :     }
    2040            2340 :     else if( ABS(dfSemiMajor-6378245.0) < 0.01
    2041                 :              && ABS(dfInvFlattening-298.3) < 0.0001 )
    2042                 :     {
    2043              10 :         pszPROJ4Ellipse = "krass";      /* Krassovsky */
    2044                 :     }
    2045            2332 :     else if( ABS(dfSemiMajor-6378388.0) < 0.01
    2046                 :              && ABS(dfInvFlattening-297.0) < 0.0001 )
    2047                 :     {
    2048              12 :         pszPROJ4Ellipse = "intl";       /* International 1924 */
    2049                 :     }
    2050            2308 :     else if( ABS(dfSemiMajor-6378160.0) < 0.01
    2051                 :              && ABS(dfInvFlattening-298.25) < 0.0001 )
    2052                 :     {
    2053               0 :         pszPROJ4Ellipse = "aust_SA";    /* Australian */
    2054                 :     }
    2055            2324 :     else if( ABS(dfSemiMajor-6377397.155) < 0.01
    2056                 :              && ABS(dfInvFlattening-299.1528128) < 0.0001 )
    2057                 :     {
    2058              16 :         pszPROJ4Ellipse = "bessel";     /* Bessel 1841 */
    2059                 :     }
    2060            2292 :     else if( ABS(dfSemiMajor-6377483.865) < 0.01
    2061                 :              && ABS(dfInvFlattening-299.1528128) < 0.0001 )
    2062                 :     {
    2063               0 :         pszPROJ4Ellipse = "bess_nam";   /* Bessel 1841 (Namibia / Schwarzeck)*/
    2064                 :     }
    2065            2296 :     else if( ABS(dfSemiMajor-6378160.0) < 0.01
    2066                 :              && ABS(dfInvFlattening-298.247167427) < 0.0001 )
    2067                 :     {
    2068               4 :         pszPROJ4Ellipse = "GRS67";      /* GRS 1967 */
    2069                 :     }
    2070            2810 :     else if( ABS(dfSemiMajor-6378137) < 0.01
    2071                 :              && ABS(dfInvFlattening-298.257222101) < 0.000001 )
    2072                 :     {
    2073             522 :         pszPROJ4Ellipse = "GRS80";      /* GRS 1980 */
    2074                 :     }
    2075            2410 :     else if( ABS(dfSemiMajor-6378206.4) < 0.01
    2076                 :              && ABS(dfInvFlattening-294.9786982) < 0.0001 )
    2077                 :     {
    2078             644 :         pszPROJ4Ellipse = "clrk66";     /* Clarke 1866 */
    2079                 :     }
    2080            1122 :     else if( ABS(dfSemiMajor-6377340.189) < 0.01
    2081                 :              && ABS(dfInvFlattening-299.3249646) < 0.0001 )
    2082                 :     {
    2083               0 :         pszPROJ4Ellipse = "mod_airy";   /* Modified Airy */
    2084                 :     }
    2085            1132 :     else if( ABS(dfSemiMajor-6377563.396) < 0.01
    2086                 :              && ABS(dfInvFlattening-299.3249646) < 0.0001 )
    2087                 :     {
    2088              10 :         pszPROJ4Ellipse = "airy";       /* Airy */
    2089                 :     }
    2090            1112 :     else if( ABS(dfSemiMajor-6378200) < 0.01
    2091                 :              && ABS(dfInvFlattening-298.3) < 0.0001 )
    2092                 :     {
    2093               0 :         pszPROJ4Ellipse = "helmert";    /* Helmert 1906 */
    2094                 :     }
    2095            1112 :     else if( ABS(dfSemiMajor-6378155) < 0.01
    2096                 :              && ABS(dfInvFlattening-298.3) < 0.0001 )
    2097                 :     {
    2098               0 :         pszPROJ4Ellipse = "fschr60m";   /* Modified Fischer 1960 */
    2099                 :     }
    2100            1112 :     else if( ABS(dfSemiMajor-6377298.556) < 0.01
    2101                 :              && ABS(dfInvFlattening-300.8017) < 0.0001 )
    2102                 :     {
    2103               0 :         pszPROJ4Ellipse = "evrstSS";    /* Everest (Sabah & Sarawak) */
    2104                 :     }
    2105            1112 :     else if( ABS(dfSemiMajor-6378165.0) < 0.01
    2106                 :              && ABS(dfInvFlattening-298.3) < 0.0001 )
    2107                 :     {
    2108               0 :         pszPROJ4Ellipse = "WGS60";      
    2109                 :     }
    2110            1112 :     else if( ABS(dfSemiMajor-6378145.0) < 0.01
    2111                 :              && ABS(dfInvFlattening-298.25) < 0.0001 )
    2112                 :     {
    2113               0 :         pszPROJ4Ellipse = "WGS66";      
    2114                 :     }
    2115            1114 :     else if( ABS(dfSemiMajor-6378135.0) < 0.01
    2116                 :              && ABS(dfInvFlattening-298.26) < 0.0001 )
    2117                 :     {
    2118               2 :         pszPROJ4Ellipse = "WGS72";      
    2119                 :     }
    2120            2176 :     else if( ABS(dfSemiMajor-6378137.0) < 0.01
    2121                 :              && ABS(dfInvFlattening-298.257223563) < 0.000001 )
    2122                 :     {
    2123            1066 :         pszPROJ4Ellipse = "WGS84";
    2124                 :     }
    2125              44 :     else if( pszDatum != NULL && EQUAL(pszDatum,"North_American_Datum_1927") )
    2126                 :     {
    2127                 : //        pszPROJ4Ellipse = "clrk66:+datum=nad27"; /* NAD 27 */
    2128               0 :         pszPROJ4Ellipse = "clrk66";
    2129                 :     }
    2130              44 :     else if( pszDatum != NULL && EQUAL(pszDatum,"North_American_Datum_1983") )
    2131                 :     {
    2132                 : //        pszPROJ4Ellipse = "GRS80:+datum=nad83";       /* NAD 83 */
    2133               0 :         pszPROJ4Ellipse = "GRS80";
    2134                 :     }
    2135                 : 
    2136                 :     char szEllipseDef[128];
    2137                 : 
    2138            2330 :     if( pszPROJ4Ellipse == NULL )
    2139                 :         sprintf( szEllipseDef, "+a=%.16g +b=%.16g ",
    2140              44 :                  GetSemiMajor(), GetSemiMinor() );
    2141                 :     else
    2142                 :         sprintf( szEllipseDef, "+ellps=%s ",
    2143            2286 :                  pszPROJ4Ellipse );
    2144                 : 
    2145                 : /* -------------------------------------------------------------------- */
    2146                 : /*      Translate the datum.                                            */
    2147                 : /* -------------------------------------------------------------------- */
    2148            2330 :     const char *pszPROJ4Datum = NULL;
    2149            2330 :     const OGR_SRSNode *poTOWGS84 = GetAttrNode( "TOWGS84" );
    2150                 :     char  szTOWGS84[256];
    2151            2330 :     int nEPSGDatum = -1;
    2152                 :     const char *pszAuthority;
    2153            2330 :     int nEPSGGeogCS = -1;
    2154                 :     const char *pszGeogCSAuthority;
    2155            2330 :     const char *pszProj4Grids = GetExtension( "DATUM", "PROJ4_GRIDS" );
    2156                 : 
    2157            2330 :     pszAuthority = GetAuthorityName( "DATUM" );
    2158                 : 
    2159            2330 :     if( pszAuthority != NULL && EQUAL(pszAuthority,"EPSG") )
    2160            1990 :         nEPSGDatum = atoi(GetAuthorityCode( "DATUM" ));
    2161                 : 
    2162            2330 :     pszGeogCSAuthority = GetAuthorityName( "GEOGCS" );
    2163                 : 
    2164            2330 :     if( pszGeogCSAuthority != NULL && EQUAL(pszGeogCSAuthority,"EPSG") )
    2165            1998 :         nEPSGGeogCS = atoi(GetAuthorityCode( "GEOGCS" ));
    2166                 : 
    2167            2330 :     if( pszDatum == NULL )
    2168                 :         /* nothing */;
    2169                 : 
    2170            2964 :     else if( EQUAL(pszDatum,SRS_DN_NAD27) || nEPSGDatum == 6267 )
    2171             634 :         pszPROJ4Datum = "NAD27";
    2172                 : 
    2173            1872 :     else if( EQUAL(pszDatum,SRS_DN_NAD83) || nEPSGDatum == 6269 )
    2174             176 :         pszPROJ4Datum = "NAD83";
    2175                 : 
    2176            2386 :     else if( EQUAL(pszDatum,SRS_DN_WGS84) || nEPSGDatum == 6326 )
    2177             866 :         pszPROJ4Datum = "WGS84";
    2178                 : 
    2179             654 :     else if( (pszPROJ4Datum = OGRGetProj4Datum(pszDatum, nEPSGDatum)) != NULL )
    2180                 :     {
    2181                 :         /* nothing */
    2182                 :     }
    2183                 : 
    2184            2330 :     if( pszProj4Grids != NULL )
    2185                 :     {
    2186               0 :         SAFE_PROJ4_STRCAT( szEllipseDef );
    2187               0 :         szEllipseDef[0] = '\0';
    2188               0 :         SAFE_PROJ4_STRCAT( "+nadgrids=" );
    2189               0 :         SAFE_PROJ4_STRCAT( pszProj4Grids );
    2190               0 :         SAFE_PROJ4_STRCAT(  " " );
    2191               0 :         pszPROJ4Datum = NULL;
    2192                 :     }
    2193                 : 
    2194            2330 :     if( pszPROJ4Datum == NULL 
    2195                 :         || CSLTestBoolean(CPLGetConfigOption("OVERRIDE_PROJ_DATUM_WITH_TOWGS84", "YES")) )
    2196                 :     {
    2197            2330 :         if( poTOWGS84 != NULL )
    2198                 :         {
    2199                 :             int iChild;
    2200             782 :             if( poTOWGS84->GetChildCount() >= 3
    2201                 :                 && (poTOWGS84->GetChildCount() < 7 
    2202                 :                     || (EQUAL(poTOWGS84->GetChild(3)->GetValue(),"")
    2203                 :                         && EQUAL(poTOWGS84->GetChild(4)->GetValue(),"")
    2204                 :                         && EQUAL(poTOWGS84->GetChild(5)->GetValue(),"")
    2205                 :                         && EQUAL(poTOWGS84->GetChild(6)->GetValue(),""))) )
    2206                 :             {
    2207               0 :                 SAFE_PROJ4_STRCAT( szEllipseDef );
    2208               0 :                 szEllipseDef[0] = '\0';
    2209               0 :                 SAFE_PROJ4_STRCAT( "+towgs84=");
    2210               0 :                 for(iChild = 0; iChild < 3; iChild ++)
    2211                 :                 {
    2212               0 :                     if (iChild > 0 ) SAFE_PROJ4_STRCAT( "," );
    2213               0 :                     SAFE_PROJ4_STRCAT( poTOWGS84->GetChild(iChild)->GetValue() );
    2214                 :                 }
    2215               0 :                 SAFE_PROJ4_STRCAT( " " );
    2216               0 :                 pszPROJ4Datum = NULL;
    2217                 :             }
    2218             782 :             else if( poTOWGS84->GetChildCount() >= 7)
    2219                 :             {
    2220             782 :                 SAFE_PROJ4_STRCAT( szEllipseDef );
    2221             782 :                 szEllipseDef[0] = '\0';
    2222             782 :                 SAFE_PROJ4_STRCAT( "+towgs84=");
    2223            6256 :                 for(iChild = 0; iChild < 7; iChild ++)
    2224                 :                 {
    2225            5474 :                     if (iChild > 0 ) SAFE_PROJ4_STRCAT( "," );
    2226            5474 :                     SAFE_PROJ4_STRCAT( poTOWGS84->GetChild(iChild)->GetValue() );
    2227                 :                 }
    2228             782 :                 SAFE_PROJ4_STRCAT( " " );
    2229             782 :                 pszPROJ4Datum = NULL;
    2230                 :             }
    2231                 :         }
    2232                 :         
    2233                 :         // If we don't know the datum, trying looking up TOWGS84 parameters
    2234                 :         // based on the EPSG GCS code.
    2235            1548 :         else if( nEPSGGeogCS != -1 && pszPROJ4Datum == NULL )
    2236                 :         {
    2237                 :             double padfTransform[7];
    2238              14 :             if( EPSGGetWGS84Transform( nEPSGGeogCS, padfTransform ) )
    2239                 :             {
    2240                 :                 sprintf( szTOWGS84, "+towgs84=%.16g,%.16g,%.16g,%.16g,%.16g,%.16g,%.16g",
    2241                 :                          padfTransform[0],
    2242                 :                          padfTransform[1],
    2243                 :                          padfTransform[2],
    2244                 :                          padfTransform[3],
    2245                 :                          padfTransform[4],
    2246                 :                          padfTransform[5],
    2247               0 :                          padfTransform[6] );
    2248               0 :                 SAFE_PROJ4_STRCAT( szEllipseDef );
    2249               0 :                 szEllipseDef[0] = '\0';
    2250                 : 
    2251               0 :                 SAFE_PROJ4_STRCAT( szTOWGS84 );
    2252               0 :                 SAFE_PROJ4_STRCAT( " " );
    2253               0 :                 pszPROJ4Datum = NULL;
    2254                 :             }
    2255                 :         }
    2256                 :     }
    2257                 :     
    2258            2330 :     if( pszPROJ4Datum != NULL )
    2259                 :     {
    2260            1292 :         SAFE_PROJ4_STRCAT( "+datum=" );
    2261            1292 :         SAFE_PROJ4_STRCAT( pszPROJ4Datum );
    2262            1292 :         SAFE_PROJ4_STRCAT( " " );
    2263                 :     }
    2264                 :     else // The ellipsedef may already have been appended and will now
    2265                 :         // be empty, otherwise append now.
    2266                 :     {
    2267            1038 :         SAFE_PROJ4_STRCAT( szEllipseDef );
    2268            1038 :         szEllipseDef[0] = '\0';
    2269                 :     }
    2270                 : 
    2271                 : /* -------------------------------------------------------------------- */
    2272                 : /*      Is there prime meridian info to apply?                          */
    2273                 : /* -------------------------------------------------------------------- */
    2274            2330 :     if( poPRIMEM != NULL && poPRIMEM->GetChildCount() >= 2 
    2275                 :         && CPLAtof(poPRIMEM->GetChild(1)->GetValue()) != 0.0 )
    2276                 :     {
    2277              16 :         const char *pszAuthority = GetAuthorityName( "PRIMEM" );
    2278                 :         char szPMValue[128];
    2279              16 :         int  nCode = -1;
    2280                 : 
    2281              16 :         if( pszAuthority != NULL && EQUAL(pszAuthority,"EPSG") )
    2282              14 :             nCode = atoi(GetAuthorityCode( "PRIMEM" ));
    2283                 : 
    2284              16 :         const OGRProj4PM* psProj4PM = NULL;
    2285              16 :         if (nCode > 0)
    2286              14 :             psProj4PM = OGRGetProj4PMFromCode(nCode);
    2287              16 :         if (psProj4PM == NULL)
    2288               2 :             psProj4PM = OGRGetProj4PMFromVal(dfFromGreenwich);
    2289                 : 
    2290              16 :         if (psProj4PM != NULL)
    2291                 :         {
    2292              16 :             strcpy( szPMValue, psProj4PM->pszProj4PMName );
    2293                 :         }
    2294                 :         else
    2295                 :         {
    2296               0 :             sprintf( szPMValue, "%.16g", dfFromGreenwich );
    2297                 :         }
    2298                 : 
    2299              16 :         SAFE_PROJ4_STRCAT( "+pm=" );
    2300              16 :         SAFE_PROJ4_STRCAT( szPMValue );
    2301              16 :         SAFE_PROJ4_STRCAT( " " );
    2302                 :     }
    2303                 :     
    2304                 : /* -------------------------------------------------------------------- */
    2305                 : /*      Handle linear units.                                            */
    2306                 : /* -------------------------------------------------------------------- */
    2307            2330 :     const char  *pszPROJ4Units=NULL;
    2308            2330 :     char        *pszLinearUnits = NULL;
    2309                 :     double      dfLinearConv;
    2310                 : 
    2311            2330 :     dfLinearConv = GetLinearUnits( &pszLinearUnits );
    2312                 :         
    2313            2330 :     if( strstr(szProj4,"longlat") != NULL )
    2314            1170 :         pszPROJ4Units = NULL;
    2315                 :     else 
    2316                 :     {
    2317            1160 :         pszPROJ4Units = LinearToProj4( dfLinearConv, pszLinearUnits );
    2318                 : 
    2319            1160 :         if( pszPROJ4Units == NULL )
    2320                 :         {
    2321                 :             char szLinearConv[128];
    2322               2 :             sprintf( szLinearConv, "%.16g", dfLinearConv );
    2323               2 :             SAFE_PROJ4_STRCAT( "+to_meter=" );
    2324               2 :             SAFE_PROJ4_STRCAT( szLinearConv );
    2325               2 :             SAFE_PROJ4_STRCAT( " " );
    2326                 :         }
    2327                 :     }
    2328                 : 
    2329            2330 :     if( pszPROJ4Units != NULL )
    2330                 :     {
    2331            1158 :         SAFE_PROJ4_STRCAT( "+units=");
    2332            1158 :         SAFE_PROJ4_STRCAT( pszPROJ4Units );
    2333            1158 :         SAFE_PROJ4_STRCAT( " " );
    2334                 :     }
    2335                 : 
    2336                 : /* -------------------------------------------------------------------- */
    2337                 : /*      If we have vertical datum grids, attach them to the proj.4 string.*/
    2338                 : /* -------------------------------------------------------------------- */
    2339            2330 :     const char *pszProj4Geoids = GetExtension( "VERT_DATUM", "PROJ4_GRIDS" );
    2340                 :     
    2341            2330 :     if( pszProj4Geoids != NULL )
    2342                 :     {
    2343               4 :         SAFE_PROJ4_STRCAT( "+geoidgrids=" );
    2344               4 :         SAFE_PROJ4_STRCAT( pszProj4Geoids );
    2345               4 :         SAFE_PROJ4_STRCAT(  " " );
    2346                 :     }    
    2347                 : 
    2348                 : /* -------------------------------------------------------------------- */
    2349                 : /*      Handle vertical units, but only if we have them.                */
    2350                 : /* -------------------------------------------------------------------- */
    2351            2330 :     const OGR_SRSNode *poVERT_CS = GetRoot()->GetNode( "VERT_CS" );
    2352            2330 :     const OGR_SRSNode *poVUNITS = NULL;
    2353                 : 
    2354            2330 :     if( poVERT_CS != NULL )
    2355               6 :         poVUNITS = poVERT_CS->GetNode( "UNIT" );
    2356                 : 
    2357            2330 :     if( poVUNITS != NULL && poVUNITS->GetChildCount() >= 2 )
    2358                 :     {
    2359               6 :         pszPROJ4Units = NULL;
    2360                 : 
    2361               6 :         dfLinearConv = CPLAtof( poVUNITS->GetChild(1)->GetValue() );
    2362                 :         
    2363                 :         pszPROJ4Units = LinearToProj4( dfLinearConv,
    2364               6 :                                        poVUNITS->GetChild(0)->GetValue() );
    2365                 :             
    2366               6 :         if( pszPROJ4Units == NULL )
    2367                 :         {
    2368                 :             char szLinearConv[128];
    2369               0 :             sprintf( szLinearConv, "%.16g", dfLinearConv );
    2370               0 :             SAFE_PROJ4_STRCAT( "+vto_meter=" );
    2371               0 :             SAFE_PROJ4_STRCAT( szLinearConv );
    2372               0 :             SAFE_PROJ4_STRCAT( " " );
    2373                 :         }
    2374                 :         else
    2375                 :         {
    2376               6 :             SAFE_PROJ4_STRCAT( "+vunits=");
    2377               6 :             SAFE_PROJ4_STRCAT( pszPROJ4Units );
    2378               6 :             SAFE_PROJ4_STRCAT( " " );
    2379                 :         }
    2380                 :     }
    2381                 : 
    2382                 : /* -------------------------------------------------------------------- */
    2383                 : /*      Add the no_defs flag to ensure that no values from              */
    2384                 : /*      proj_def.dat are implicitly used with our definitions.          */
    2385                 : /* -------------------------------------------------------------------- */
    2386            2330 :     SAFE_PROJ4_STRCAT( "+no_defs " );
    2387                 :     
    2388            2330 :     *ppszProj4 = CPLStrdup( szProj4 );
    2389                 : 
    2390            2330 :     return OGRERR_NONE;
    2391                 : }
    2392                 : 

Generated by: LCOV version 1.7