LCOV - code coverage report
Current view: directory - ogr - ogr_srs_proj4.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 723 627 86.7 %
Date: 2012-12-26 Functions: 11 11 100.0 %

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

Generated by: LCOV version 1.7